Files
Agent-System/internal/server/admin_roles_handlers.go
T
weichenandCursor 6219caf690 feat(authz): complete Phase 1 admin roles, sessions, and unified admin gate
Add roles CRUD backed by system_roles tables, session list/revoke APIs,
capabilities fallback for memory mode, and route all admin checks through
AuthorizationService instead of hardcoded role-admin checks.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-13 02:50:22 +00:00

100 lines
2.7 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 {
http.Error(w, err.Error(), http.StatusInternalServerError)
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 {
http.Error(w, "无效的 JSON 请求体", http.StatusBadRequest)
return
}
created, err := s.authzSvc.CreateRole(r.Context(), req)
if err != nil {
status := http.StatusBadRequest
if errors.Is(err, authz.ErrRolesNotAvailable) {
status = http.StatusServiceUnavailable
}
http.Error(w, err.Error(), status)
return
}
writeJSONResponse(w, http.StatusCreated, created)
default:
http.Error(w, "不支持的请求方法", 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 == "" {
http.Error(w, "无效的角色 ID", http.StatusBadRequest)
return
}
switch r.Method {
case http.MethodPatch, http.MethodPut:
var req authz.UpdateRoleInput
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, "无效的 JSON 请求体", http.StatusBadRequest)
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
}
http.Error(w, err.Error(), status)
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
}
http.Error(w, err.Error(), status)
return
}
writeJSONResponse(w, http.StatusOK, map[string]bool{"success": true})
default:
http.Error(w, "不支持的请求方法", http.StatusMethodNotAllowed)
}
}