Files
Agent-System/internal/server/admin_roles_handlers.go
weichenandCursor f6813cc272 feat(api): add additive HTTP/SSE error envelopes
Public errors now emit code, safe message, and request_id while keeping the legacy error field. Raw SQL, paths, tokens, and XSS payloads are stripped; the frontend branches on code instead of substring matching.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-15 14:40:56 +00:00

100 lines
2.8 KiB
Go

package server
import (
"encoding/json"
"errors"
"net/http"
"strings"
"chat-agent-system/internal/authz"
)
func (s *Server) handleAdminRoles(w http.ResponseWriter, r *http.Request) {
if _, ok := s.requireSystemAdmin(w, r); !ok {
return
}
switch r.Method {
case http.MethodGet:
roles, err := s.authzSvc.ListRoles(r.Context())
if err != nil {
writeSafeError(w, r, http.StatusInternalServerError, err.Error())
return
}
writeJSONResponse(w, http.StatusOK, map[string]any{"roles": roles})
case http.MethodPost:
var req authz.CreateRoleInput
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
writeSafeError(w, r, http.StatusBadRequest, "无效的 JSON 请求体")
return
}
created, err := s.authzSvc.CreateRole(r.Context(), req)
if err != nil {
status := http.StatusBadRequest
if errors.Is(err, authz.ErrRolesNotAvailable) {
status = http.StatusServiceUnavailable
}
writeSafeError(w, r, status, err.Error())
return
}
writeJSONResponse(w, http.StatusCreated, created)
default:
writeSafeError(w, r, http.StatusMethodNotAllowed, "不支持的请求方法")
}
}
func (s *Server) handleAdminRoleByID(w http.ResponseWriter, r *http.Request) {
if _, ok := s.requireSystemAdmin(w, r); !ok {
return
}
roleID := strings.TrimSpace(r.PathValue("id"))
if roleID == "" {
writeSafeError(w, r, http.StatusBadRequest, "无效的角色 ID")
return
}
switch r.Method {
case http.MethodPatch, http.MethodPut:
var req authz.UpdateRoleInput
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
writeSafeError(w, r, http.StatusBadRequest, "无效的 JSON 请求体")
return
}
updated, err := s.authzSvc.UpdateRole(r.Context(), roleID, req)
if err != nil {
status := http.StatusBadRequest
switch {
case errors.Is(err, authz.ErrRoleNotFound):
status = http.StatusNotFound
case errors.Is(err, authz.ErrRoleIsSystem):
status = http.StatusForbidden
case errors.Is(err, authz.ErrRolesNotAvailable):
status = http.StatusServiceUnavailable
}
writeSafeError(w, r, status, err.Error())
return
}
writeJSONResponse(w, http.StatusOK, updated)
case http.MethodDelete:
if err := s.authzSvc.DeleteRole(r.Context(), roleID); err != nil {
status := http.StatusBadRequest
switch {
case errors.Is(err, authz.ErrRoleNotFound):
status = http.StatusNotFound
case errors.Is(err, authz.ErrRoleIsSystem):
status = http.StatusForbidden
case errors.Is(err, authz.ErrRoleInUse):
status = http.StatusConflict
case errors.Is(err, authz.ErrRolesNotAvailable):
status = http.StatusServiceUnavailable
}
writeSafeError(w, r, status, err.Error())
return
}
writeJSONResponse(w, http.StatusOK, map[string]bool{"success": true})
default:
writeSafeError(w, r, http.StatusMethodNotAllowed, "不支持的请求方法")
}
}