Split user and workspace contexts

This commit is contained in:
2024-11-03 22:02:39 +01:00
parent c8cc854fd6
commit 927d1feb05
3 changed files with 34 additions and 29 deletions

View File

@@ -27,7 +27,7 @@ func SetupRoutes(r chi.Router, db *db.DB, fs *filesystem.FileSystem, authMiddlew
r.Group(func(r chi.Router) { r.Group(func(r chi.Router) {
// Apply authentication middleware to all routes in this group // Apply authentication middleware to all routes in this group
r.Use(authMiddleware.Authenticate) r.Use(authMiddleware.Authenticate)
r.Use(middleware.WithHandlerContext(db)) r.Use(middleware.WithUserContext)
// Auth routes // Auth routes
r.Post("/auth/logout", handler.Logout(sessionService)) r.Post("/auth/logout", handler.Logout(sessionService))
@@ -49,7 +49,8 @@ func SetupRoutes(r chi.Router, db *db.DB, fs *filesystem.FileSystem, authMiddlew
r.Put("/last", handler.UpdateLastWorkspace()) r.Put("/last", handler.UpdateLastWorkspace())
// Single workspace routes // Single workspace routes
r.Route("/{workspaceId}", func(r chi.Router) { r.Route("/{workspaceName}", func(r chi.Router) {
r.Use(middleware.WithWorkspaceContext(db))
r.Use(authMiddleware.RequireWorkspaceAccess) r.Use(authMiddleware.RequireWorkspaceAccess)
r.Get("/", handler.GetWorkspace()) r.Get("/", handler.GetWorkspace())

View File

@@ -10,7 +10,7 @@ import (
type HandlerContext struct { type HandlerContext struct {
UserID int UserID int
UserRole string UserRole string
Workspace *models.Workspace // Will be nil for non-workspace endpoints Workspace *models.Workspace
} }
type contextKey string type contextKey string

View File

@@ -5,45 +5,49 @@ import (
"novamd/internal/auth" "novamd/internal/auth"
"novamd/internal/db" "novamd/internal/db"
"novamd/internal/httpcontext" "novamd/internal/httpcontext"
"novamd/internal/models"
"github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5"
) )
// WithHandlerContext middleware populates the HandlerContext for the request // User ID and User Role context
// This should be placed after authentication middleware func WithUserContext(next http.Handler) http.Handler {
func WithHandlerContext(db *db.DB) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Get user claims from auth middleware
claims, err := auth.GetUserFromContext(r.Context()) claims, err := auth.GetUserFromContext(r.Context())
if err != nil { if err != nil {
http.Error(w, "Unauthorized", http.StatusUnauthorized) http.Error(w, "Unauthorized", http.StatusUnauthorized)
return return
} }
// Try to get workspace from URL if it exists
workspaceName := chi.URLParam(r, "workspaceName")
var workspace *models.Workspace
if workspaceName != "" {
workspace, err = db.GetWorkspaceByName(claims.UserID, workspaceName)
if err != nil {
http.Error(w, "Internal server error", http.StatusInternalServerError)
return
}
}
// Create handler context with user and workspace info
hctx := &httpcontext.HandlerContext{ hctx := &httpcontext.HandlerContext{
UserID: claims.UserID, UserID: claims.UserID,
UserRole: claims.Role, UserRole: claims.Role,
Workspace: workspace,
} }
// Add context to request
r = httpcontext.WithHandlerContext(r, hctx) r = httpcontext.WithHandlerContext(r, hctx)
next.ServeHTTP(w, r) next.ServeHTTP(w, r)
}) })
} }
// Workspace context
func WithWorkspaceContext(db *db.DB) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx, ok := httpcontext.GetRequestContext(w, r)
if !ok {
return
}
workspaceName := chi.URLParam(r, "workspaceName")
workspace, err := db.GetWorkspaceByName(ctx.UserID, workspaceName)
if err != nil {
http.Error(w, "Workspace not found", http.StatusNotFound)
return
}
// Update existing context with workspace
ctx.Workspace = workspace
r = httpcontext.WithHandlerContext(r, ctx)
next.ServeHTTP(w, r)
})
}
} }