Fixed auth and cleaned up docker

This commit is contained in:
Atridad Lahiji 2024-06-27 21:51:00 -06:00
parent 96671ff7a6
commit 9a579912cd
No known key found for this signature in database
12 changed files with 103 additions and 36 deletions

View file

@ -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
View 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)
}

View file

@ -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:

View file

@ -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 {

View file

@ -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
View file

@ -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")

View file

@ -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"}

View file

@ -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"}}

View file

@ -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}}

View file

@ -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>

View file

@ -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>

File diff suppressed because one or more lines are too long