Files
Atlas/internal/api/admin_handlers.go
T
renjue 4bc1b8d2e3
CI / docker (push) Has been cancelled
实现 Atlas AI 平台一期能力并完成品牌化改造。
引入用户端对话/生图与管理端 Provider 配置,统一 invoke 编排、Gateway、请求日志与模型管理;前端按设计规范拆分布局,Go module 更名为 github.com/rose_cat707/Atlas;生图长任务 SSE 推送;管理端登录防爆破;协议与服务类型联动;Replicate 模型同步修复;用户端创作台 UI 重构;管理端创作历史替代请求日志。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-29 22:34:44 +08:00

200 lines
6.6 KiB
Go

package api
import (
"net/http"
"strconv"
"github.com/gin-gonic/gin"
"github.com/rose_cat707/Atlas/internal/store"
)
func (s *Server) registerAdminRoutes(r gin.IRoutes) {
r.GET("/admin/providers", s.adminListProviders)
r.POST("/admin/providers", s.adminCreateProvider)
r.GET("/admin/providers/:id", s.adminGetProvider)
r.PUT("/admin/providers/:id", s.adminUpdateProvider)
r.DELETE("/admin/providers/:id", s.adminDeleteProvider)
r.GET("/admin/providers/:id/models", s.adminListProviderModels)
r.POST("/admin/providers/:id/models", s.adminAddProviderModel)
r.DELETE("/admin/providers/:id/models/:modelId", s.adminDeleteProviderModel)
r.POST("/admin/providers/:id/models/sync", s.adminSyncProviderModels)
r.GET("/admin/generations", s.adminListGenerations)
r.GET("/admin/generations/:id", s.adminGetGeneration)
r.DELETE("/admin/generations/:id", s.adminDeleteGeneration)
r.GET("/admin/dashboard/stats", s.adminDashboardStats)
}
func (s *Server) adminListProviders(c *gin.Context) {
items, err := s.app.Store.ListProviders(c.Request.Context(), c.Query("service_type"), false)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
masked := make([]store.Provider, len(items))
for i, p := range items {
masked[i] = store.MaskProvider(p)
}
c.JSON(http.StatusOK, gin.H{"items": masked})
}
func (s *Server) adminCreateProvider(c *gin.Context) {
var in store.Provider
if err := c.ShouldBindJSON(&in); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
if err := store.ValidateProvider(&in); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
if in.ExtraJSON == "" {
in.ExtraJSON = "{}"
}
id, err := s.app.Store.CreateProvider(c.Request.Context(), &in)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
in.ID = id
_ = s.app.Store.InsertAuditLog(c.Request.Context(), "create", "provider", in.Name)
c.JSON(http.StatusOK, store.MaskProvider(in))
}
func (s *Server) adminGetProvider(c *gin.Context) {
id, _ := strconv.ParseInt(c.Param("id"), 10, 64)
p, err := s.app.Store.GetProvider(c.Request.Context(), id)
if err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "not found"})
return
}
c.JSON(http.StatusOK, store.MaskProvider(*p))
}
func (s *Server) adminUpdateProvider(c *gin.Context) {
id, _ := strconv.ParseInt(c.Param("id"), 10, 64)
var in store.Provider
if err := c.ShouldBindJSON(&in); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
existing, err := s.app.Store.GetProvider(c.Request.Context(), id)
if err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "not found"})
return
}
in.ID = id
if in.APIKey == "" || in.APIKey == "******" {
in.APIKey = existing.APIKey
}
if err := store.ValidateProvider(&in); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
if err := s.app.Store.UpdateProvider(c.Request.Context(), &in); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
_ = s.app.Store.InsertAuditLog(c.Request.Context(), "update", "provider", in.Name)
c.JSON(http.StatusOK, store.MaskProvider(in))
}
func (s *Server) adminDeleteProvider(c *gin.Context) {
id, _ := strconv.ParseInt(c.Param("id"), 10, 64)
if err := s.app.Store.DeleteProvider(c.Request.Context(), id); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
_ = s.app.Store.InsertAuditLog(c.Request.Context(), "delete", "provider", strconv.FormatInt(id, 10))
c.JSON(http.StatusOK, gin.H{"ok": true})
}
func (s *Server) adminListProviderModels(c *gin.Context) {
id, _ := strconv.ParseInt(c.Param("id"), 10, 64)
breakdown, err := s.app.Models.Breakdown(c.Request.Context(), id)
if err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, breakdown)
}
func (s *Server) adminAddProviderModel(c *gin.Context) {
id, _ := strconv.ParseInt(c.Param("id"), 10, 64)
var in struct {
ModelID string `json:"model_id"`
Name string `json:"name"`
}
if err := c.ShouldBindJSON(&in); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
if err := s.app.Models.AddManual(c.Request.Context(), id, in.ModelID, in.Name); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
breakdown, _ := s.app.Models.Breakdown(c.Request.Context(), id)
c.JSON(http.StatusOK, breakdown)
}
func (s *Server) adminDeleteProviderModel(c *gin.Context) {
id, _ := strconv.ParseInt(c.Param("id"), 10, 64)
modelID := c.Param("modelId")
if err := s.app.Models.RemoveManual(c.Request.Context(), id, modelID); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
breakdown, _ := s.app.Models.Breakdown(c.Request.Context(), id)
c.JSON(http.StatusOK, breakdown)
}
func (s *Server) adminSyncProviderModels(c *gin.Context) {
id, _ := strconv.ParseInt(c.Param("id"), 10, 64)
upstream, err := s.app.Models.RefreshUpstream(c.Request.Context(), id)
if err != nil {
c.JSON(http.StatusBadGateway, gin.H{"error": err.Error()})
return
}
breakdown, _ := s.app.Models.Breakdown(c.Request.Context(), id)
c.JSON(http.StatusOK, gin.H{"upstream": upstream, "breakdown": breakdown})
}
func (s *Server) adminListGenerations(c *gin.Context) {
limit, offset := parseLimitOffset(c, 50, 500)
items, total, err := s.app.Store.ListAllGenerations(c.Request.Context(), c.Query("service_type"), limit, offset)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"items": items, "total": total})
}
func (s *Server) adminGetGeneration(c *gin.Context) {
id, _ := strconv.ParseInt(c.Param("id"), 10, 64)
item, err := s.app.Store.AdminGetGeneration(c.Request.Context(), id)
if err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "not found"})
return
}
c.JSON(http.StatusOK, item)
}
func (s *Server) adminDeleteGeneration(c *gin.Context) {
id, _ := strconv.ParseInt(c.Param("id"), 10, 64)
if err := s.app.Store.AdminDeleteGeneration(c.Request.Context(), id); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
_ = s.app.Store.InsertAuditLog(c.Request.Context(), "delete", "generation", strconv.FormatInt(id, 10))
c.JSON(http.StatusOK, gin.H{"ok": true})
}
func (s *Server) adminDashboardStats(c *gin.Context) {
stats, err := s.app.Store.DashboardStats(c.Request.Context())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, stats)
}