Files
eng-pad-server/internal/server/middleware.go
Kyle Isom 37c2d35ceb Implement Phase 6: REST API with chi router
- Login endpoint (password → bearer token + session cookie)
- Auth middleware (bearer header or session cookie)
- Notebook list endpoint (authenticated)
- Page SVG/JPG rendering endpoints (authenticated)
- Notebook PDF download endpoint (authenticated)
- Share link endpoints: view, page SVG, page JPG, PDF (no auth)
- Route registration with chi groups

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 19:55:47 -07:00

55 lines
1.2 KiB
Go

package server
import (
"context"
"database/sql"
"net/http"
"strings"
"git.wntrmute.dev/kyle/eng-pad-server/internal/auth"
)
type contextKey string
const userIDKey contextKey = "user_id"
func UserIDFromContext(ctx context.Context) (int64, bool) {
id, ok := ctx.Value(userIDKey).(int64)
return id, ok
}
func AuthMiddleware(database *sql.DB) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
token := ""
// Check Authorization header
authHeader := r.Header.Get("Authorization")
if strings.HasPrefix(authHeader, "Bearer ") {
token = strings.TrimPrefix(authHeader, "Bearer ")
}
// Check cookie
if token == "" {
if cookie, err := r.Cookie("session"); err == nil {
token = cookie.Value
}
}
if token == "" {
http.Error(w, `{"error":"unauthenticated"}`, http.StatusUnauthorized)
return
}
userID, err := auth.ValidateToken(database, token)
if err != nil {
http.Error(w, `{"error":"invalid token"}`, http.StatusUnauthorized)
return
}
ctx := context.WithValue(r.Context(), userIDKey, userID)
next.ServeHTTP(w, r.WithContext(ctx))
})
}
}