package operator import ( "crypto/subtle" "encoding/json" "net/http" "proxui/backend/internal/membership" "proxui/backend/internal/rbac" ) const HeaderName = "X-ProxUI-Operator-Token" type Middleware struct { token string } func NewMiddleware(token string) Middleware { return Middleware{token: token} } func (m Middleware) RequireOperator(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if m.token == "" { writeError(w, http.StatusServiceUnavailable, "operator_auth_not_configured") return } provided := r.Header.Get(HeaderName) if subtle.ConstantTimeCompare([]byte(provided), []byte(m.token)) != 1 { writeError(w, http.StatusForbidden, "operator_forbidden") return } operatorContext := membership.ContextWithMembership(r.Context(), membership.Membership{ Role: rbac.RoleOperator, }) next.ServeHTTP(w, r.WithContext(operatorContext)) }) } func writeError(w http.ResponseWriter, status int, message string) { w.Header().Set("Content-Type", "application/json") w.WriteHeader(status) _ = json.NewEncoder(w).Encode(map[string]string{"error": message}) }