Fixed auth and cleaned up docker
This commit is contained in:
parent
96671ff7a6
commit
9a579912cd
12 changed files with 103 additions and 36 deletions
10
.env.example
10
.env.example
|
@ -2,9 +2,13 @@
|
||||||
# This file should not be committed to the repository
|
# This file should not be committed to the repository
|
||||||
# The actual .env file should contain the following variables
|
# The actual .env file should contain the following variables
|
||||||
|
|
||||||
# The database URL should be in the format postgres://username:password@host:port/database
|
# The database credentials
|
||||||
DATABASE_URL=
|
POSTGRES_HOST=localhost
|
||||||
|
POSTGRES_PORT=5432
|
||||||
|
POSTGRES_PASSWORD=postgres
|
||||||
|
POSTGRES_USER=postgres
|
||||||
|
POSTGRES_DB=db
|
||||||
# The secret key used to sign the JWT tokens
|
# The secret key used to sign the JWT tokens
|
||||||
AUTH_SECRET=
|
AUTH_SECRET=super-duper-secret
|
||||||
# If you want to run the app in development mode, set this to true
|
# If you want to run the app in development mode, set this to true
|
||||||
DEVMODE=true
|
DEVMODE=true
|
17
api/signout.go
Normal file
17
api/signout.go
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"pollo/lib"
|
||||||
|
|
||||||
|
"github.com/labstack/echo/v4"
|
||||||
|
)
|
||||||
|
|
||||||
|
func SignOutUserHandler(c echo.Context) error {
|
||||||
|
// Clear the session cookie
|
||||||
|
lib.ClearSessionCookie(c.Response().Writer, "session_id")
|
||||||
|
|
||||||
|
// Proceed with login success logic
|
||||||
|
c.Response().Header().Set("HX-Redirect", "/")
|
||||||
|
return c.NoContent(http.StatusOK)
|
||||||
|
}
|
|
@ -13,15 +13,28 @@ services:
|
||||||
networks:
|
networks:
|
||||||
- proxy_default
|
- proxy_default
|
||||||
environment:
|
environment:
|
||||||
- AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID
|
- POSTGRES_HOST=$POSTGRES_HOST
|
||||||
- AWS_ENDPOINT_URL_S3=$AWS_ENDPOINT_URL_S3
|
- POSTGRES_PORT=$POSTGRES_PORT
|
||||||
- AWS_REGION=$AWS_REGION
|
- POSTGRES_DB=$POSTGRES_DB
|
||||||
- AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY
|
- POSTGRES_USER=$POSTGRES_USER
|
||||||
- BUCKET_NAME=$BUCKET_NAME
|
- POSTGRES_PASSWORD=$POSTGRES_PASSWORD
|
||||||
- CLERK_SECRET_KEY=$CLERK_SECRET_KEY
|
- AUTH_SECRET=$AUTH_SECRET
|
||||||
- CLERK_WEBHOOK_SECRET=$CLERK_WEBHOOK_SECRET
|
- DEVMODE=$DEVMODE
|
||||||
- RESEND_API_KEY=$RESEND_API_KEY
|
|
||||||
- STRIPE_SECRET_KEY=$STRIPE_SECRET_KEY
|
db:
|
||||||
|
image: 'postgres:latest'
|
||||||
|
pull_policy: build
|
||||||
|
environment:
|
||||||
|
- POSTGRES_DB=$POSTGRES_DB
|
||||||
|
- POSTGRES_PASSWORD=$POSTGRES_PASSWORD
|
||||||
|
- POSTGRES_USER=$POSTGRES_USER
|
||||||
|
ports:
|
||||||
|
- 5432:5432
|
||||||
|
volumes:
|
||||||
|
- pgdata:/var/lib/postgresql/data
|
||||||
|
networks:
|
||||||
|
- proxy_default
|
||||||
|
restart: on-failure:3
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
proxy_default:
|
proxy_default:
|
||||||
|
|
|
@ -2,6 +2,7 @@ package lib
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/jackc/pgx/v4/pgxpool"
|
"github.com/jackc/pgx/v4/pgxpool"
|
||||||
)
|
)
|
||||||
|
@ -9,7 +10,10 @@ import (
|
||||||
var dbPool *pgxpool.Pool
|
var dbPool *pgxpool.Pool
|
||||||
|
|
||||||
// Initializes the global database connection pool.
|
// Initializes the global database connection pool.
|
||||||
func InitializeDBPool(connString string) error {
|
func InitializeDBPool(host, user, password, dbname string, port int) error {
|
||||||
|
// Construct the connection string using the provided parameters
|
||||||
|
connString := fmt.Sprintf("postgres://%s:%s@%s:%d/%s", user, password, host, port, dbname)
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
dbPool, err = pgxpool.Connect(context.Background(), connString)
|
dbPool, err = pgxpool.Connect(context.Background(), connString)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -48,6 +48,19 @@ func GetSessionCookie(r *http.Request, name string) (string, error) {
|
||||||
return cookie.Value, nil
|
return cookie.Value, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ClearSessionCookie clears the session cookie from the client's browser
|
||||||
|
func ClearSessionCookie(w http.ResponseWriter, name string) {
|
||||||
|
http.SetCookie(w, &http.Cookie{
|
||||||
|
Name: name,
|
||||||
|
Value: "",
|
||||||
|
Path: "/",
|
||||||
|
HttpOnly: true,
|
||||||
|
Secure: os.Getenv("DEVMODE") != "true",
|
||||||
|
SameSite: http.SameSiteStrictMode,
|
||||||
|
MaxAge: -1, // Set MaxAge to -1 to delete the cookie immediately.
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// Checks if the user is signed in by checking the session cookie
|
// Checks if the user is signed in by checking the session cookie
|
||||||
func IsSignedIn(c echo.Context) bool {
|
func IsSignedIn(c echo.Context) bool {
|
||||||
_, err := GetSessionCookie(c.Request(), "session_id")
|
_, err := GetSessionCookie(c.Request(), "session_id")
|
||||||
|
|
19
main.go
19
main.go
|
@ -7,6 +7,7 @@ import (
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"pollo/api"
|
"pollo/api"
|
||||||
"pollo/api/webhooks"
|
"pollo/api/webhooks"
|
||||||
|
@ -28,12 +29,21 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize the database connection pool
|
// Initialize the database connection pool
|
||||||
connString := os.Getenv("DATABASE_URL")
|
postgresHost := os.Getenv("POSTGRES_HOST")
|
||||||
if connString == "" {
|
postgresPort := os.Getenv("POSTGRES_PORT")
|
||||||
log.Fatal("DATABASE_URL environment variable is not set.")
|
postgresUser := os.Getenv("POSTGRES_USER")
|
||||||
|
postgresPassword := os.Getenv("POSTGRES_PASSWORD")
|
||||||
|
postgresDB := os.Getenv("POSTGRES_DB")
|
||||||
|
if postgresHost == "" || postgresPort == "" || postgresUser == "" || postgresPassword == "" || postgresDB == "" {
|
||||||
|
log.Fatal("Darta environment variable is not set.")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := lib.InitializeDBPool(connString); err != nil {
|
portNumber, err := strconv.Atoi(postgresPort)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Invalid database port: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := lib.InitializeDBPool(postgresHost, postgresUser, postgresPassword, postgresDB, portNumber); err != nil {
|
||||||
log.Fatalf("Failed to initialize DB pool: %v", err)
|
log.Fatalf("Failed to initialize DB pool: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,6 +90,7 @@ func main() {
|
||||||
// Public routes
|
// Public routes
|
||||||
apiGroup.POST("/register", api.RegisterUserHandler)
|
apiGroup.POST("/register", api.RegisterUserHandler)
|
||||||
apiGroup.POST("/signin", api.SignInUserHandler)
|
apiGroup.POST("/signin", api.SignInUserHandler)
|
||||||
|
apiGroup.POST("/signout", api.SignOutUserHandler)
|
||||||
|
|
||||||
// Webhook Routes:
|
// Webhook Routes:
|
||||||
webhookGroup := e.Group("/webhook")
|
webhookGroup := e.Group("/webhook")
|
||||||
|
|
|
@ -7,10 +7,13 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type DashboardProps struct {
|
type DashboardProps struct {
|
||||||
|
IsLoggedIn bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func Dashboard(c echo.Context) error {
|
func Dashboard(c echo.Context) error {
|
||||||
props := HomeProps{}
|
props := DashboardProps{
|
||||||
|
IsLoggedIn: lib.IsSignedIn(c),
|
||||||
|
}
|
||||||
|
|
||||||
// Specify the partials used by this page
|
// Specify the partials used by this page
|
||||||
partials := []string{"header"}
|
partials := []string{"header"}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
{{define "title"}}
|
{{define "title"}}
|
||||||
Pollo // Root
|
Pollo // Dashboard
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{define "headercontent"}}
|
{{define "headercontent"}}
|
||||||
Pollo // Root
|
Pollo // Dashboard
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{define "head"}}
|
{{define "head"}}
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
<a class="btn btn-primary btn-outline mx-2" href="/dashboard">
|
<a class="btn btn-primary btn-outline mx-2" href="/dashboard">
|
||||||
Dashboard
|
Dashboard
|
||||||
</a>
|
</a>
|
||||||
<a class="btn btn-primary" href="/signout">
|
<a class="btn btn-primary" hx-post="/api/signout" hx-redirect="/">
|
||||||
Sign Out
|
Sign Out
|
||||||
</a>
|
</a>
|
||||||
{{else}}
|
{{else}}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
{{define "title"}}
|
{{define "title"}}
|
||||||
Pollo // Root
|
Pollo // Register
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{define "headercontent"}}
|
{{define "headercontent"}}
|
||||||
Pollo // Root
|
Pollo // Register
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{define "head"}}
|
{{define "head"}}
|
||||||
|
@ -12,11 +12,12 @@ Pollo // Root
|
||||||
|
|
||||||
{{define "main"}}
|
{{define "main"}}
|
||||||
<div id="auth-form">
|
<div id="auth-form">
|
||||||
<h2>Register</h2>
|
<h2 class="text-4xl">Register</h2>
|
||||||
<form hx-post="/api/register" hx-swap="none">
|
<br>
|
||||||
<input type="email" name="email" placeholder="Email" required>
|
<form class="flex flex-col gap-2" hx-post="/api/register" hx-swap="none">
|
||||||
<input type="password" name="password" placeholder="Password" required>
|
<input class="input input-bordered input-primary w-full max-w-xs" type="email" name="email" placeholder="Email" required>
|
||||||
<button type="submit">Register</button>
|
<input class="input input-bordered input-primary w-full max-w-xs" type="password" name="password" placeholder="Password" required>
|
||||||
|
<button class="btn btn-primary" type="submit">Register</button>
|
||||||
</form>
|
</form>
|
||||||
<p>Already have an account? <a href="/signin">Sign In</a></p>
|
<p>Already have an account? <a href="/signin">Sign In</a></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
{{define "title"}}
|
{{define "title"}}
|
||||||
Pollo // Root
|
Pollo // Sign In
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{define "headercontent"}}
|
{{define "headercontent"}}
|
||||||
Pollo // Root
|
Pollo // Sign In
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{define "head"}}
|
{{define "head"}}
|
||||||
|
@ -12,11 +12,12 @@ Pollo // Root
|
||||||
|
|
||||||
{{define "main"}}
|
{{define "main"}}
|
||||||
<div id="auth-form" hx-ext="response-targets">
|
<div id="auth-form" hx-ext="response-targets">
|
||||||
<h2>Sign In</h2>
|
<h2 class="text-4xl">Sign In</h2>
|
||||||
<form hx-post="/api/signin" hx-target-4*="#error-message">
|
<br>
|
||||||
<input type="email" name="email" placeholder="Email" required>
|
<form class="flex flex-col gap-2" hx-post="/api/signin" hx-target-4*="#error-message">
|
||||||
<input type="password" name="password" placeholder="Password" required>
|
<input class="input input-bordered input-primary w-full max-w-xs" type="email" name="email" placeholder="Email" required>
|
||||||
<button type="submit">Sign In</button>
|
<input class="input input-bordered input-primary w-full max-w-xs" type="password" name="password" placeholder="Password" required>
|
||||||
|
<button class="btn btn-primary" type="submit">Sign In</button>
|
||||||
</form>
|
</form>
|
||||||
<div id="error-message"style="color: red;"></div>
|
<div id="error-message"style="color: red;"></div>
|
||||||
<p>Don't have an account? <a href="/register">Register</a></p>
|
<p>Don't have an account? <a href="/register">Register</a></p>
|
||||||
|
|
2
public/css/styles.css
vendored
2
public/css/styles.css
vendored
File diff suppressed because one or more lines are too long
Loading…
Add table
Reference in a new issue