package middleware import ( "context" "net/http" "github.com/google/uuid" "github.com/dbiz/cdp/data-layer/api/internal/apperr" ) const ctxKeyWorkspace ctxKey = "workspace_id" // Workspace pulls the active workspace UUID from the X-Workspace-Id header // and stores it in context. Returns 400 for missing / malformed values. // // TODO(auth): wire this to the console session / JWT once the auth scheme // for the data-layer is finalized. For now the header drives everything. func Workspace(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { raw := r.Header.Get("X-Workspace-Id") if raw == "" { writeAppErr(w, apperr.BadRequest("missing X-Workspace-Id header", "workspace_id", nil)) return } id, err := uuid.Parse(raw) if err != nil { writeAppErr(w, apperr.BadRequest("invalid X-Workspace-Id", "workspace_id", err)) return } ctx := context.WithValue(r.Context(), ctxKeyWorkspace, id.String()) next.ServeHTTP(w, r.WithContext(ctx)) }) } // WorkspaceFromCtx returns the workspace id set by Workspace middleware. func WorkspaceFromCtx(ctx context.Context) string { v, _ := ctx.Value(ctxKeyWorkspace).(string) return v } func writeAppErr(w http.ResponseWriter, err *apperr.AppError) { w.Header().Set("Content-Type", "application/json") w.WriteHeader(err.Code) body := `{"error":"` + err.Message + `"` if err.Field != "" { body += `,"field":"` + err.Field + `"` } body += `}` _, _ = w.Write([]byte(body)) }