package api import ( "context" "net/http" "strings" "git.jnss.me/joakim/opal/internal/engine" ) type contextKey string const userIDKey contextKey = "userID" // AuthMiddleware validates API keys and adds userID to context func AuthMiddleware() func(http.Handler) http.Handler { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // Get Authorization header authHeader := r.Header.Get("Authorization") if authHeader == "" { Error(w, http.StatusUnauthorized, "missing authorization header") return } // Parse "Bearer " parts := strings.SplitN(authHeader, " ", 2) if len(parts) != 2 || parts[0] != "Bearer" { Error(w, http.StatusUnauthorized, "invalid authorization header format") return } apiKey := parts[1] // Validate API key valid, userID, err := engine.ValidateAPIKey(apiKey) if err != nil { Error(w, http.StatusInternalServerError, "failed to validate API key") return } if !valid { Error(w, http.StatusUnauthorized, "invalid API key") return } // Add userID to context ctx := context.WithValue(r.Context(), userIDKey, userID) next.ServeHTTP(w, r.WithContext(ctx)) }) } } // GetUserID extracts userID from request context func GetUserID(r *http.Request) int { userID, ok := r.Context().Value(userIDKey).(int) if !ok { return 0 } return userID } // CORSMiddleware adds CORS headers for future web frontend func CORSMiddleware() func(http.Handler) http.Handler { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Access-Control-Allow-Origin", "*") w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS") w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization") if r.Method == "OPTIONS" { w.WriteHeader(http.StatusOK) return } next.ServeHTTP(w, r) }) } }