package middleware import ( "context" "net/http" "strings" "cmr-backend/internal/apperr" "cmr-backend/internal/httpx" "cmr-backend/internal/platform/jwtx" ) type opsAuthContextKey string const opsAuthKey opsAuthContextKey = "ops-auth" type OpsAuthContext struct { OpsUserID string OpsUserPublicID string RoleCode string } func NewOpsAuthMiddleware(jwtManager *jwtx.Manager, appEnv string) func(http.Handler) http.Handler { devContext := func(r *http.Request) *http.Request { ctx := context.WithValue(r.Context(), opsAuthKey, &OpsAuthContext{ OpsUserID: "dev-ops-user", OpsUserPublicID: "ops_dev_console", RoleCode: "owner", }) return r.WithContext(ctx) } return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { authHeader := strings.TrimSpace(r.Header.Get("Authorization")) if authHeader == "" || !strings.HasPrefix(authHeader, "Bearer ") { if appEnv != "production" { next.ServeHTTP(w, devContext(r)) return } httpx.WriteError(w, apperr.New(http.StatusUnauthorized, "unauthorized", "missing bearer token")) return } token := strings.TrimSpace(strings.TrimPrefix(authHeader, "Bearer ")) claims, err := jwtManager.ParseAccessToken(token) if err != nil { if appEnv != "production" { next.ServeHTTP(w, devContext(r)) return } httpx.WriteError(w, apperr.New(http.StatusUnauthorized, "invalid_token", "invalid access token")) return } if claims.ActorType != "ops" { if appEnv != "production" { next.ServeHTTP(w, devContext(r)) return } httpx.WriteError(w, apperr.New(http.StatusUnauthorized, "invalid_token", "invalid ops access token")) return } ctx := context.WithValue(r.Context(), opsAuthKey, &OpsAuthContext{ OpsUserID: claims.UserID, OpsUserPublicID: claims.UserPublicID, RoleCode: claims.RoleCode, }) next.ServeHTTP(w, r.WithContext(ctx)) }) } } func GetOpsAuthContext(ctx context.Context) *OpsAuthContext { auth, _ := ctx.Value(opsAuthKey).(*OpsAuthContext) return auth }