Files
NianAIGC/backend/internal/httpapi/job_projection.go
T
2026-10-02 19:56:32 +08:00

61 lines
1.8 KiB
Go

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"
}