package httpapi import ( "encoding/json" "git.nianxx.cn/wangxuming/NianAIGC/backend/internal/identity" "git.nianxx.cn/wangxuming/NianAIGC/backend/internal/jobs" ) // The diagnostics stored with a job are intended for platform administrators. // Project a copy at the HTTP boundary so neither the persisted job nor a // caller's shared RawMessage buffer is changed by a response to another role. func projectJobForViewer(job jobs.Job, diagnosticsAllowed bool) jobs.Job { if diagnosticsAllowed || len(job.ResponsePayload) == 0 { return job } var payload map[string]json.RawMessage if err := json.Unmarshal(job.ResponsePayload, &payload); err != nil || payload == nil { job.ResponsePayload = nil return job } for _, key := range []string{"providerError", "errorCode", "errorDetail", "requestId"} { delete(payload, key) } if job.Status == jobs.StatusFailed || job.Status == jobs.StatusCancelled || job.Status == jobs.StatusExpired { // Historical failures may contain an unsanitized provider body. The // user-facing explanation is job.Error.Message, never this raw body. delete(payload, "raw") delete(payload, "errorMessage") } if len(payload) == 0 { job.ResponsePayload = nil return job } projected, err := json.Marshal(payload) if err != nil { job.ResponsePayload = nil return job } job.ResponsePayload = projected return job } func projectJobsForViewer(items []jobs.Job, diagnosticsAllowed bool) []jobs.Job { if diagnosticsAllowed || len(items) == 0 { return items } projected := make([]jobs.Job, len(items)) for index := range items { projected[index] = projectJobForViewer(items[index], false) } return projected } func canViewJobDiagnostics(session identity.Session) bool { if session.AuthMode != identity.AuthModeAdmin { return false } return session.User.Role == "super_admin" || session.User.Role == "organization_admin" }