Files
Agent-System/internal/server/software_project_handlers.go
T
weichen f3f23a3018 feat(errcode): 用稳定错误码记录 HTTP 与异步失败
失败响应此前不写日志,request_id 无法对照原因。注册表不覆盖处理器已经给出的 HTTP 状态。
2026-09-28 02:27:16 +00:00

73 lines
2.3 KiB
Go

package server
import (
"encoding/json"
"net/http"
"path/filepath"
"strings"
"time"
"chat-agent-system/internal/swboot"
)
// handleProjectTypesCatalog GET /api/v1/project-types/catalog
func (s *Server) handleProjectTypesCatalog(w http.ResponseWriter, r *http.Request) {
if _, ok := s.requirePrincipal(w, r); !ok {
return
}
writeJSONResponse(w, http.StatusOK, map[string]any{
"project_types": swboot.ProjectTypesCatalog(),
})
}
// handleComplianceProfilesCatalog GET /api/v1/compliance-profiles/catalog
func (s *Server) handleComplianceProfilesCatalog(w http.ResponseWriter, r *http.Request) {
if _, ok := s.requirePrincipal(w, r); !ok {
return
}
writeJSONResponse(w, http.StatusOK, map[string]any{
"compliance_profiles": swboot.ComplianceProfilesCatalog(),
})
}
// handleProjectCreationPreview POST /api/v1/projects/creation-preview
func (s *Server) handleProjectCreationPreview(w http.ResponseWriter, r *http.Request) {
user, err := s.authenticateUser(r)
if err != nil || user == nil {
writeSafeError(w, r, http.StatusUnauthorized, `{"error":"ERR_UNAUTHENTICATED","message":"请先登录"}`)
return
}
if ok, permErr := s.userHasSystemPermission(r.Context(), user, "project:create"); permErr != nil {
writeDomainError(w, r, http.StatusInternalServerError, permErr)
return
} else if !ok {
writeJSONResponse(w, http.StatusForbidden, map[string]string{
"error_code": "ERR_FORBIDDEN",
"message": "无权创建项目",
})
return
}
var req swboot.CreationPreviewInput
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
writeSafeError(w, r, http.StatusBadRequest, `{"error":"ERR_INVALID_PARAM","message":"无效的 JSON 请求体"}`)
return
}
// SWBOOT-10: controlled_patch is only preview-valid with an admin-allowlisted
// repo binding; fail-closed when the allowlist is not configured.
if strings.TrimSpace(req.ExecutionMode) == swboot.ExecutionControlledPatch && strings.TrimSpace(req.RepoPath) != "" {
if exec, err := s.swbootExec(); err == nil {
if abs, absErr := filepath.Abs(strings.TrimSpace(req.RepoPath)); absErr == nil {
req.RepoPath = abs
req.RepoAllowlisted = exec.Allowlist.IsAllowlisted(abs)
}
}
}
res := swboot.BuildCreationPreview(req, time.Now().UTC())
status := http.StatusOK
if !res.Valid {
status = http.StatusBadRequest
}
writeJSONResponse(w, status, res)
}