| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003 |
- // Package routes provides HTTP route registration and handlers.
- package routes
- import (
- "github.com/Wei-Shaw/sub2api/internal/handler"
- "github.com/Wei-Shaw/sub2api/internal/pkg/response"
- "github.com/Wei-Shaw/sub2api/internal/server/middleware"
- "github.com/Wei-Shaw/sub2api/internal/service"
- "github.com/gin-gonic/gin"
- )
- // RegisterAdminRoutes 注册管理员路由
- func RegisterAdminRoutes(
- v1 *gin.RouterGroup,
- h *handler.Handlers,
- adminAuth middleware.AdminAuthMiddleware,
- auditLog middleware.AuditLogMiddleware,
- stepUpAuth middleware.StepUpAuthMiddleware,
- settingService *service.SettingService,
- panelRateLimiter *middleware.PanelRateLimiter,
- userService *service.UserService,
- ) {
- // 插件 UI 使用短时能力 URL,仅提供经过安装校验的静态资源。
- v1.GET("/plugin-ui/:token/*path", h.Admin.Plugin.ServeUIAsset)
- admin := v1.Group("/admin")
- admin.Use(gin.HandlerFunc(adminAuth))
- // 面板全局按用户限流(默认管理员豁免,可在系统设置中关闭豁免)
- admin.Use(panelRateLimiter.Global())
- // 审计中间件挂在认证之后:所有管理面变更类操作 + 敏感读取入审计日志
- admin.Use(gin.HandlerFunc(auditLog))
- admin.Use(middleware.UserHierarchyGuard(userService))
- admin.Use(middleware.AdminComplianceGuard(settingService))
- {
- // 部署与运营合规确认
- registerAdminComplianceRoutes(admin, h)
- // 仪表盘
- registerDashboardRoutes(admin, h)
- // 用户管理
- registerUserManagementRoutes(admin, h)
- registerRelayManagementRoutes(admin, h)
- // 分组管理
- registerGroupRoutes(admin, h)
- // 账号管理
- registerAccountRoutes(admin, h, stepUpAuth)
- // 公告管理
- registerAnnouncementRoutes(admin, h)
- // OpenAI OAuth
- registerOpenAIOAuthRoutes(admin, h)
- // Gemini OAuth
- registerGeminiOAuthRoutes(admin, h)
- // Antigravity OAuth
- registerAntigravityOAuthRoutes(admin, h)
- // Grok OAuth
- registerGrokOAuthRoutes(admin, h)
- // 国产供应商(kimi/zhipu/deepseek)额度与余额
- registerCNProviderRoutes(admin, h)
- // 代理管理
- registerProxyRoutes(admin, h, stepUpAuth)
- // 卡密管理
- registerRedeemCodeRoutes(admin, h)
- // 优惠码管理
- registerPromoCodeRoutes(admin, h)
- // 系统设置
- registerSettingsRoutes(admin, h)
- // 数据管理
- registerDataManagementRoutes(admin, h, stepUpAuth)
- // 数据库备份恢复
- registerBackupRoutes(admin, h, stepUpAuth)
- // 运维监控(Ops)
- registerOpsRoutes(admin, h)
- // 系统管理
- registerSystemRoutes(admin, h, stepUpAuth)
- // 订阅管理
- registerSubscriptionRoutes(admin, h)
- // 使用记录管理
- registerUsageRoutes(admin, h)
- // 用户属性管理
- registerUserAttributeRoutes(admin, h)
- // 错误透传规则管理
- registerErrorPassthroughRoutes(admin, h)
- // TLS 指纹模板管理
- registerTLSFingerprintProfileRoutes(admin, h)
- // 本地进程插件管理
- registerPluginRoutes(admin, h, stepUpAuth)
- // API Key 管理
- registerAdminAPIKeyRoutes(admin, h)
- // 定时测试计划
- registerScheduledTestRoutes(admin, h)
- // 渠道管理
- registerChannelRoutes(admin, h)
- // 渠道监控
- registerChannelMonitorRoutes(admin, h, settingService)
- registerChannelMonitorV2Routes(admin, h, settingService)
- // 风控中心
- registerContentModerationRoutes(admin, h)
- registerSecurityPolicyRoutes(admin, h)
- // 分组安全策略(自定义词包 + 会话解封)
- // 全站模型定价覆盖
- registerGlobalPricingRoutes(admin, h)
- // 账号健康分
- registerAccountHealthRoutes(admin, h)
- // 毛利看板与熔断
- registerMarginRoutes(admin, h)
- // 分级路由
- registerTieredRoutingRoutes(admin, h)
- // 烧钱防护
- registerSpendGuardRoutes(admin, h)
- // 工单系统
- registerTicketAdminRoutes(admin, h)
- // 账单导出
- registerBillingExportAdminRoutes(admin, h)
- // 独立提示词输入审计
- registerPromptAuditRoutes(admin, h)
- // 邀请返利(专属用户管理)
- registerAffiliateRoutes(admin, h)
- // 操作审计日志
- registerAuditLogRoutes(admin, h, stepUpAuth)
- }
- }
- func registerPromptAuditRoutes(admin *gin.RouterGroup, h *handler.Handlers) {
- promptAudit := admin.Group("/prompt-audit")
- {
- promptAudit.GET("/config", h.Admin.PromptAudit.GetConfig)
- promptAudit.PUT("/config", h.Admin.PromptAudit.UpdateConfig)
- promptAudit.POST("/endpoints/probe", h.Admin.PromptAudit.ProbeEndpoint)
- promptAudit.GET("/runtime", h.Admin.PromptAudit.GetRuntime)
- promptAudit.GET("/events", h.Admin.PromptAudit.ListEvents)
- promptAudit.GET("/events/:id", h.Admin.PromptAudit.GetEvent)
- promptAudit.DELETE("/events/:id", h.Admin.PromptAudit.DeleteEvent)
- promptAudit.POST("/events/batch-delete", h.Admin.PromptAudit.BatchDelete)
- promptAudit.POST("/events/delete-preview", h.Admin.PromptAudit.DeletePreview)
- promptAudit.POST("/events/delete-by-filter", h.Admin.PromptAudit.DeleteByFilter)
- }
- }
- func registerAuditLogRoutes(admin *gin.RouterGroup, h *handler.Handlers, _ middleware.StepUpAuthMiddleware) {
- auditLogs := admin.Group("/audit-logs")
- {
- auditLogs.GET("", h.Admin.AuditLog.List)
- auditLogs.GET("/:id", h.Admin.AuditLog.Get)
- // 清空需现场 TOTP 校验(在 handler 内强制),不复用 step-up sudo 窗口
- auditLogs.POST("/clear", h.Admin.AuditLog.Clear)
- }
- }
- func registerAdminComplianceRoutes(admin *gin.RouterGroup, h *handler.Handlers) {
- compliance := admin.Group("/compliance")
- {
- compliance.GET("", h.Admin.Compliance.GetStatus)
- compliance.POST("/accept", h.Admin.Compliance.Accept)
- }
- }
- func registerContentModerationRoutes(admin *gin.RouterGroup, h *handler.Handlers) {
- risk := admin.Group("/risk-control")
- {
- risk.GET("/config", h.Admin.ContentModeration.GetConfig)
- risk.PUT("/config", h.Admin.ContentModeration.UpdateConfig)
- risk.POST("/api-keys/test", h.Admin.ContentModeration.TestAPIKeys)
- risk.GET("/status", h.Admin.ContentModeration.GetStatus)
- risk.GET("/logs", h.Admin.ContentModeration.ListLogs)
- risk.POST("/users/:user_id/unban", h.Admin.ContentModeration.UnbanUser)
- risk.DELETE("/hashes", h.Admin.ContentModeration.DeleteFlaggedHash)
- risk.DELETE("/hashes/all", h.Admin.ContentModeration.ClearFlaggedHashes)
- }
- }
- func registerSecurityPolicyRoutes(admin *gin.RouterGroup, h *handler.Handlers) {
- secpol := admin.Group("/security-policy")
- {
- secpol.GET("/keywords/builtin", h.Admin.SecurityPolicy.ListBuiltin)
- secpol.GET("/keywords", h.Admin.SecurityPolicy.ListKeywords)
- secpol.POST("/keywords", h.Admin.SecurityPolicy.CreateKeyword)
- secpol.PUT("/keywords/:id", h.Admin.SecurityPolicy.UpdateKeyword)
- secpol.DELETE("/keywords/:id", h.Admin.SecurityPolicy.DeleteKeyword)
- secpol.POST("/sessions/unblock", h.Admin.SecurityPolicy.UnblockSession)
- }
- }
- func registerAdminAPIKeyRoutes(admin *gin.RouterGroup, h *handler.Handlers) {
- apiKeys := admin.Group("/api-keys")
- {
- apiKeys.PUT("/:id", h.Admin.APIKey.UpdateGroup)
- }
- }
- func registerOpsRoutes(admin *gin.RouterGroup, h *handler.Handlers) {
- ops := admin.Group("/ops")
- {
- // Realtime ops signals
- ops.GET("/concurrency", h.Admin.Ops.GetConcurrencyStats)
- ops.GET("/user-concurrency", h.Admin.Ops.GetUserConcurrencyStats)
- ops.GET("/account-availability", h.Admin.Ops.GetAccountAvailability)
- ops.GET("/realtime-traffic", h.Admin.Ops.GetRealtimeTrafficSummary)
- // Alerts (rules + events)
- ops.GET("/alert-rules", h.Admin.Ops.ListAlertRules)
- ops.POST("/alert-rules", h.Admin.Ops.CreateAlertRule)
- ops.PUT("/alert-rules/:id", h.Admin.Ops.UpdateAlertRule)
- ops.DELETE("/alert-rules/:id", h.Admin.Ops.DeleteAlertRule)
- ops.GET("/alert-events", h.Admin.Ops.ListAlertEvents)
- ops.GET("/alert-events/:id", h.Admin.Ops.GetAlertEvent)
- ops.PUT("/alert-events/:id/status", h.Admin.Ops.UpdateAlertEventStatus)
- ops.POST("/alert-silences", h.Admin.Ops.CreateAlertSilence)
- // Email notification config (DB-backed)
- ops.GET("/email-notification/config", h.Admin.Ops.GetEmailNotificationConfig)
- ops.PUT("/email-notification/config", h.Admin.Ops.UpdateEmailNotificationConfig)
- // Runtime settings (DB-backed)
- runtime := ops.Group("/runtime")
- {
- runtime.GET("/alert", h.Admin.Ops.GetAlertRuntimeSettings)
- runtime.PUT("/alert", h.Admin.Ops.UpdateAlertRuntimeSettings)
- runtime.GET("/logging", h.Admin.Ops.GetRuntimeLogConfig)
- runtime.PUT("/logging", h.Admin.Ops.UpdateRuntimeLogConfig)
- runtime.POST("/logging/reset", h.Admin.Ops.ResetRuntimeLogConfig)
- }
- // Advanced settings (DB-backed)
- ops.GET("/advanced-settings", h.Admin.Ops.GetAdvancedSettings)
- ops.PUT("/advanced-settings", h.Admin.Ops.UpdateAdvancedSettings)
- // Settings group (DB-backed)
- settings := ops.Group("/settings")
- {
- settings.GET("/metric-thresholds", h.Admin.Ops.GetMetricThresholds)
- settings.PUT("/metric-thresholds", h.Admin.Ops.UpdateMetricThresholds)
- }
- // WebSocket realtime (QPS/TPS)
- ws := ops.Group("/ws")
- {
- ws.GET("/qps", h.Admin.Ops.QPSWSHandler)
- }
- // Error logs (legacy)
- ops.GET("/errors", h.Admin.Ops.GetErrorLogs)
- ops.GET("/errors/:id", h.Admin.Ops.GetErrorLogByID)
- ops.PUT("/errors/:id/resolve", h.Admin.Ops.UpdateErrorResolution)
- // Request errors (client-visible failures)
- ops.GET("/request-errors", h.Admin.Ops.ListRequestErrors)
- ops.GET("/request-errors/:id", h.Admin.Ops.GetRequestError)
- ops.GET("/request-errors/:id/upstream-errors", h.Admin.Ops.ListRequestErrorUpstreamErrors)
- ops.PUT("/request-errors/:id/resolve", h.Admin.Ops.ResolveRequestError)
- // Bounded ingress-admission rejection aggregates.
- ops.GET("/ingress-rejections", h.Admin.Ops.ListIngressRejects)
- ops.GET("/ingress-rejections/health", h.Admin.Ops.GetIngressRejectHealth)
- ops.GET("/auth-cache-invalidation/health", h.Admin.Ops.GetAuthCacheInvalidationHealth)
- // Upstream errors (independent upstream failures)
- ops.GET("/upstream-errors", h.Admin.Ops.ListUpstreamErrors)
- ops.GET("/upstream-errors/:id", h.Admin.Ops.GetUpstreamError)
- ops.PUT("/upstream-errors/:id/resolve", h.Admin.Ops.ResolveUpstreamError)
- // Request drilldown (success + error)
- ops.GET("/requests", h.Admin.Ops.ListRequestDetails)
- // Indexed system logs
- ops.GET("/system-logs", h.Admin.Ops.ListSystemLogs)
- ops.POST("/system-logs/cleanup", h.Admin.Ops.CleanupSystemLogs)
- ops.GET("/system-logs/health", h.Admin.Ops.GetSystemLogIngestionHealth)
- // Dashboard (vNext - raw path for MVP)
- ops.GET("/dashboard/snapshot-v2", h.Admin.Ops.GetDashboardSnapshotV2)
- ops.GET("/dashboard/overview", h.Admin.Ops.GetDashboardOverview)
- ops.GET("/dashboard/throughput-trend", h.Admin.Ops.GetDashboardThroughputTrend)
- ops.GET("/dashboard/latency-histogram", h.Admin.Ops.GetDashboardLatencyHistogram)
- ops.GET("/dashboard/error-trend", h.Admin.Ops.GetDashboardErrorTrend)
- ops.GET("/dashboard/error-distribution", h.Admin.Ops.GetDashboardErrorDistribution)
- ops.GET("/dashboard/openai-token-stats", h.Admin.Ops.GetDashboardOpenAITokenStats)
- }
- }
- func registerDashboardRoutes(admin *gin.RouterGroup, h *handler.Handlers) {
- dashboard := admin.Group("/dashboard")
- {
- dashboard.GET("/snapshot-v2", h.Admin.Dashboard.GetSnapshotV2)
- dashboard.GET("/stats", h.Admin.Dashboard.GetStats)
- dashboard.GET("/realtime", h.Admin.Dashboard.GetRealtimeMetrics)
- dashboard.GET("/trend", h.Admin.Dashboard.GetUsageTrend)
- dashboard.GET("/models", h.Admin.Dashboard.GetModelStats)
- dashboard.GET("/groups", h.Admin.Dashboard.GetGroupStats)
- dashboard.GET("/api-keys-trend", h.Admin.Dashboard.GetAPIKeyUsageTrend)
- dashboard.GET("/users-trend", h.Admin.Dashboard.GetUserUsageTrend)
- dashboard.GET("/users-ranking", h.Admin.Dashboard.GetUserSpendingRanking)
- dashboard.POST("/users-usage", h.Admin.Dashboard.GetBatchUsersUsage)
- dashboard.POST("/api-keys-usage", h.Admin.Dashboard.GetBatchAPIKeysUsage)
- dashboard.GET("/user-breakdown", h.Admin.Dashboard.GetUserBreakdown)
- dashboard.POST("/aggregation/backfill", h.Admin.Dashboard.BackfillAggregation)
- }
- }
- func registerUserManagementRoutes(admin *gin.RouterGroup, h *handler.Handlers) {
- users := admin.Group("/users")
- {
- users.GET("", h.Admin.User.List)
- users.GET("/:id", h.Admin.User.GetByID)
- users.POST("/:id/auth-identities", h.Admin.User.BindAuthIdentity)
- users.POST("", h.Admin.User.Create)
- users.PUT("/:id", h.Admin.User.Update)
- users.DELETE("/:id", h.Admin.User.Delete)
- users.POST("/:id/balance", h.Admin.User.UpdateBalance)
- users.GET("/:id/api-keys", h.Admin.User.GetUserAPIKeys)
- users.GET("/:id/usage", h.Admin.User.GetUserUsage)
- users.GET("/:id/balance-history", h.Admin.User.GetBalanceHistory)
- users.POST("/:id/replace-group", h.Admin.User.ReplaceGroup)
- users.GET("/:id/rpm-status", h.Admin.User.GetUserRPMStatus)
- users.POST("/batch-concurrency", h.Admin.User.BatchUpdateConcurrency)
- users.POST("/batch-limits", h.Admin.User.BatchUpdateLimits)
- users.GET("/:id/platform-quotas", h.Admin.User.GetUserPlatformQuotas)
- users.PUT("/:id/platform-quotas", h.Admin.User.UpdateUserPlatformQuotas)
- users.POST("/:id/platform-quotas/reset", h.Admin.User.ResetUserPlatformQuotaWindow)
- // User attribute values
- users.GET("/:id/attributes", h.Admin.UserAttribute.GetUserAttributes)
- users.PUT("/:id/attributes", h.Admin.UserAttribute.UpdateUserAttributes)
- }
- }
- func registerGroupRoutes(admin *gin.RouterGroup, h *handler.Handlers) {
- groups := admin.Group("/groups")
- {
- groups.GET("", h.Admin.Group.List)
- groups.GET("/all", h.Admin.Group.GetAll)
- groups.GET("/usage-summary", h.Admin.Group.GetUsageSummary)
- groups.GET("/capacity-summary", h.Admin.Group.GetCapacitySummary)
- groups.GET("/live-capability", h.Admin.Group.GetLiveCapability)
- groups.PUT("/sort-order", h.Admin.Group.UpdateSortOrder)
- groups.GET("/:id/composite-routes", h.Admin.Group.ListCompositeRoutes)
- groups.POST("/:id/composite-routes", h.Admin.Group.CreateCompositeRoute)
- groups.POST("/:id/composite-routes/preview", h.Admin.Group.PreviewCompositeRoute)
- groups.PUT("/:id/composite-routes/:route_id", h.Admin.Group.UpdateCompositeRoute)
- groups.DELETE("/:id/composite-routes/:route_id", h.Admin.Group.DeleteCompositeRoute)
- groups.GET("/:id", h.Admin.Group.GetByID)
- groups.POST("", h.Admin.Group.Create)
- groups.POST("/:id/duplicate", h.Admin.Group.Duplicate)
- groups.PUT("/:id", h.Admin.Group.Update)
- groups.DELETE("/:id", h.Admin.Group.Delete)
- groups.GET("/:id/stats", h.Admin.Group.GetStats)
- groups.GET("/:id/rate-multipliers", h.Admin.Group.GetGroupRateMultipliers)
- groups.PUT("/:id/rate-multipliers", h.Admin.Group.BatchSetGroupRateMultipliers)
- groups.DELETE("/:id/rate-multipliers", h.Admin.Group.ClearGroupRateMultipliers)
- groups.PUT("/:id/rpm-overrides", h.Admin.Group.BatchSetGroupRPMOverrides)
- groups.DELETE("/:id/rpm-overrides", h.Admin.Group.ClearGroupRPMOverrides)
- groups.GET("/:id/api-keys", h.Admin.Group.GetGroupAPIKeys)
- }
- }
- func registerAccountRoutes(admin *gin.RouterGroup, h *handler.Handlers, stepUpAuth middleware.StepUpAuthMiddleware) {
- accounts := admin.Group("/accounts")
- {
- accounts.GET("", h.Admin.Account.List)
- // Keep the registry route ahead of the dynamic /:id routes so clients can
- // always discover the available strategy profiles without ambiguity.
- accounts.GET("/anti-degrade/strategies", h.Admin.AntiDegrade.Strategies)
- accounts.GET("/upstream-billing-rates", h.Admin.Account.GetUpstreamBillingRates)
- accounts.GET("/upstream-billing-probe/settings", h.Admin.Account.GetUpstreamBillingProbeSettings)
- accounts.PUT("/upstream-billing-probe/settings", h.Admin.Account.UpdateUpstreamBillingProbeSettings)
- accounts.POST("/upstream-billing-probe/batch", h.Admin.Account.ProbeUpstreamBillingBatch)
- accounts.GET("/ollama-cloud-usage/settings", h.Admin.Account.GetOllamaCloudUsageSettings)
- accounts.PUT("/ollama-cloud-usage/settings", h.Admin.Account.UpdateOllamaCloudUsageSettings)
- accounts.GET("/:id", h.Admin.Account.GetByID)
- accounts.POST("", h.Admin.Account.Create)
- accounts.POST("/:id/duplicate", h.Admin.Account.Duplicate)
- accounts.POST("/check-mixed-channel", h.Admin.Account.CheckMixedChannel)
- accounts.POST("/import/codex-session", h.Admin.Account.ImportCodexSession)
- accounts.POST("/sync/crs", h.Admin.Account.SyncFromCRS)
- accounts.POST("/sync/crs/preview", h.Admin.Account.PreviewFromCRS)
- accounts.PUT("/:id", h.Admin.Account.Update)
- accounts.GET("/:id/grok-media-eligibility", h.Admin.Account.GetGrokMediaEligibility)
- accounts.PUT("/:id/grok-media-eligibility", h.Admin.Account.UpdateGrokMediaEligibility)
- accounts.PUT("/:id/upstream-billing-probe", h.Admin.Account.SetUpstreamBillingProbeEnabled)
- accounts.POST("/:id/upstream-billing-probe", h.Admin.Account.ProbeUpstreamBilling)
- accounts.GET("/:id/ollama-cloud-usage", h.Admin.Account.GetOllamaCloudUsage)
- accounts.PUT("/:id/ollama-cloud-usage/session", h.Admin.Account.SaveOllamaCloudUsageSession)
- accounts.DELETE("/:id/ollama-cloud-usage/session", h.Admin.Account.DeleteOllamaCloudUsageSession)
- accounts.PUT("/:id/ollama-cloud-usage/auto-refresh", h.Admin.Account.SetOllamaCloudUsageAutoRefresh)
- accounts.POST("/:id/ollama-cloud-usage/refresh", h.Admin.Account.RefreshOllamaCloudUsage)
- accounts.DELETE("/:id", h.Admin.Account.Delete)
- accounts.POST("/:id/test", h.Admin.Account.Test)
- accounts.POST("/:id/recover-state", h.Admin.Account.RecoverState)
- accounts.POST("/:id/refresh", h.Admin.Account.Refresh)
- accounts.POST("/:id/apply-oauth-credentials", h.Admin.Account.ApplyOAuthCredentials)
- accounts.POST("/:id/set-privacy", h.Admin.Account.SetPrivacy)
- accounts.POST("/:id/refresh-tier", h.Admin.Account.RefreshTier)
- accounts.GET("/:id/stats", h.Admin.Account.GetStats)
- accounts.POST("/:id/clear-error", h.Admin.Account.ClearError)
- accounts.POST("/:id/revert-proxy-fallback", h.Admin.Account.RevertProxyFallback)
- accounts.GET("/:id/anti-degrade", h.Admin.AntiDegrade.Preview)
- accounts.POST("/:id/anti-degrade/apply", h.Admin.AntiDegrade.Apply)
- accounts.POST("/:id/anti-degrade/revert", h.Admin.AntiDegrade.Revert)
- accounts.GET("/:id/usage", h.Admin.Account.GetUsage)
- accounts.GET("/:id/today-stats", h.Admin.Account.GetTodayStats)
- accounts.POST("/usage/batch", h.Admin.Account.GetBatchUsage)
- accounts.POST("/today-stats/batch", h.Admin.Account.GetBatchTodayStats)
- accounts.POST("/:id/clear-rate-limit", h.Admin.Account.ClearRateLimit)
- accounts.POST("/:id/reset-quota", h.Admin.Account.ResetQuota)
- accounts.GET("/:id/temp-unschedulable", h.Admin.Account.GetTempUnschedulable)
- accounts.DELETE("/:id/temp-unschedulable", h.Admin.Account.ClearTempUnschedulable)
- accounts.POST("/:id/schedulable", h.Admin.Account.SetSchedulable)
- accounts.POST("/models/sync-upstream-preview", h.Admin.Account.SyncUpstreamModelsPreview)
- accounts.GET("/:id/models", h.Admin.Account.GetAvailableModels)
- accounts.POST("/:id/models/sync-upstream", h.Admin.Account.SyncUpstreamModels)
- accounts.POST("/batch", h.Admin.Account.BatchCreate)
- // 账号导出泄露上游凭证原文——要求 step-up 2FA
- accounts.GET("/data", gin.HandlerFunc(stepUpAuth), h.Admin.Account.ExportData)
- accounts.POST("/data", h.Admin.Account.ImportData)
- accounts.POST("/batch-update-credentials", h.Admin.Account.BatchUpdateCredentials)
- accounts.POST("/batch-refresh-tier", h.Admin.Account.BatchRefreshTier)
- accounts.POST("/bulk-update", h.Admin.Account.BulkUpdate)
- accounts.POST("/batch-delete", h.Admin.Account.BatchDelete)
- accounts.POST("/batch-clear-error", h.Admin.Account.BatchClearError)
- accounts.POST("/batch-refresh", h.Admin.Account.BatchRefresh)
- // 历史明文凭据加密回填(幂等;未启用凭据加密时返回 0)
- // Antigravity 默认模型映射
- accounts.GET("/antigravity/default-model-mapping", h.Admin.Account.GetAntigravityDefaultModelMapping)
- // Spark 影子账号
- accounts.POST("/:id/shadow", h.Admin.OpenAIOAuth.CreateShadow)
- // Claude OAuth routes
- accounts.POST("/generate-auth-url", h.Admin.OAuth.GenerateAuthURL)
- accounts.POST("/generate-setup-token-url", h.Admin.OAuth.GenerateSetupTokenURL)
- accounts.POST("/exchange-code", h.Admin.OAuth.ExchangeCode)
- accounts.POST("/exchange-setup-token-code", h.Admin.OAuth.ExchangeSetupTokenCode)
- accounts.POST("/cookie-auth", h.Admin.OAuth.CookieAuth)
- accounts.POST("/setup-token-cookie-auth", h.Admin.OAuth.SetupTokenCookieAuth)
- }
- }
- func registerAnnouncementRoutes(admin *gin.RouterGroup, h *handler.Handlers) {
- announcements := admin.Group("/announcements")
- {
- announcements.GET("", h.Admin.Announcement.List)
- announcements.POST("", h.Admin.Announcement.Create)
- announcements.GET("/:id", h.Admin.Announcement.GetByID)
- announcements.PUT("/:id", h.Admin.Announcement.Update)
- announcements.DELETE("/:id", h.Admin.Announcement.Delete)
- announcements.GET("/:id/read-status", h.Admin.Announcement.ListReadStatus)
- }
- }
- func registerOpenAIOAuthRoutes(admin *gin.RouterGroup, h *handler.Handlers) {
- openai := admin.Group("/openai")
- {
- openai.POST("/generate-auth-url", h.Admin.OpenAIOAuth.GenerateAuthURL)
- openai.POST("/exchange-code", h.Admin.OpenAIOAuth.ExchangeCode)
- openai.POST("/refresh-token", h.Admin.OpenAIOAuth.RefreshToken)
- openai.POST("/accounts/:id/refresh", h.Admin.OpenAIOAuth.RefreshAccountToken)
- openai.POST("/create-from-oauth", h.Admin.OpenAIOAuth.CreateAccountFromOAuth)
- openai.POST("/create-from-codex-pat", h.Admin.OpenAIOAuth.CreateAccountFromCodexPAT)
- openai.GET("/accounts/:id/quota", h.Admin.OpenAIOAuth.QueryQuota)
- openai.POST("/accounts/:id/quota/refresh", h.Admin.OpenAIOAuth.RefreshQuota)
- openai.POST("/accounts/:id/reset-quota", h.Admin.OpenAIOAuth.ResetQuota)
- }
- }
- func registerGeminiOAuthRoutes(admin *gin.RouterGroup, h *handler.Handlers) {
- gemini := admin.Group("/gemini")
- {
- gemini.POST("/oauth/auth-url", h.Admin.GeminiOAuth.GenerateAuthURL)
- gemini.POST("/oauth/exchange-code", h.Admin.GeminiOAuth.ExchangeCode)
- gemini.GET("/oauth/capabilities", h.Admin.GeminiOAuth.GetCapabilities)
- }
- }
- func registerAntigravityOAuthRoutes(admin *gin.RouterGroup, h *handler.Handlers) {
- antigravity := admin.Group("/antigravity")
- {
- antigravity.POST("/oauth/auth-url", h.Admin.AntigravityOAuth.GenerateAuthURL)
- antigravity.POST("/oauth/exchange-code", h.Admin.AntigravityOAuth.ExchangeCode)
- antigravity.POST("/oauth/refresh-token", h.Admin.AntigravityOAuth.RefreshToken)
- }
- }
- func registerGrokOAuthRoutes(admin *gin.RouterGroup, h *handler.Handlers) {
- grok := admin.Group("/grok")
- {
- grok.GET("/oauth/capabilities", h.Admin.GrokOAuth.GetCapabilities)
- grok.POST("/oauth/auth-url", h.Admin.GrokOAuth.GenerateAuthURL)
- grok.POST("/oauth/exchange-code", h.Admin.GrokOAuth.ExchangeCode)
- grok.POST("/oauth/refresh-token", h.Admin.GrokOAuth.RefreshToken)
- grok.POST("/oauth/sso-token", h.Admin.GrokOAuth.ValidateSSOToken)
- grok.POST("/oauth/password", h.Admin.GrokOAuth.AuthorizePassword)
- grok.POST("/oauth/create-from-oauth", h.Admin.GrokOAuth.CreateAccountFromOAuth)
- grok.POST("/sso-to-oauth", h.Admin.GrokOAuth.CreateAccountsFromSSO)
- grok.POST("/oauth/reconcile", h.Admin.GrokOAuth.ReconcileOAuthAccounts)
- grok.POST("/accounts/:id/refresh", h.Admin.GrokOAuth.RefreshAccountToken)
- grok.GET("/accounts/:id/quota", h.Admin.GrokOAuth.QueryQuota)
- grok.POST("/accounts/:id/reset-quota", h.Admin.GrokOAuth.ResetQuota)
- grok.GET("/runtime-sanity", h.Admin.GrokOAuth.RuntimeSanity)
- }
- }
- // registerCNProviderRoutes 注册国产供应商(kimi/zhipu/deepseek)的额度与余额查询端点。
- func registerCNProviderRoutes(admin *gin.RouterGroup, h *handler.Handlers) {
- cn := admin.Group("/cn-providers")
- {
- // Coding Plan 滚动窗口用量(kimi/zhipu coding 账号)。
- cn.GET("/accounts/:id/quota", h.Admin.CNProvider.QueryQuota)
- // payg 账号余额(kimi/deepseek;zhipu 无余额端点)。
- cn.GET("/accounts/:id/balance", h.Admin.CNProvider.QueryBalance)
- }
- }
- func registerProxyRoutes(admin *gin.RouterGroup, h *handler.Handlers, stepUpAuth middleware.StepUpAuthMiddleware) {
- proxies := admin.Group("/proxies")
- {
- proxies.GET("", h.Admin.Proxy.List)
- proxies.GET("/all", h.Admin.Proxy.GetAll)
- // 代理导出泄露账号密码原文——要求 step-up 2FA
- proxies.GET("/data", gin.HandlerFunc(stepUpAuth), h.Admin.Proxy.ExportData)
- proxies.POST("/data", h.Admin.Proxy.ImportData)
- proxies.GET("/:id", h.Admin.Proxy.GetByID)
- proxies.POST("", h.Admin.Proxy.Create)
- proxies.PUT("/:id", h.Admin.Proxy.Update)
- proxies.DELETE("/:id", h.Admin.Proxy.Delete)
- proxies.POST("/:id/test", h.Admin.Proxy.Test)
- proxies.POST("/:id/quality-check", h.Admin.Proxy.CheckQuality)
- proxies.GET("/:id/stats", h.Admin.Proxy.GetStats)
- proxies.GET("/:id/accounts", h.Admin.Proxy.GetProxyAccounts)
- proxies.POST("/batch-delete", h.Admin.Proxy.BatchDelete)
- proxies.POST("/batch", h.Admin.Proxy.BatchCreate)
- }
- }
- func registerRedeemCodeRoutes(admin *gin.RouterGroup, h *handler.Handlers) {
- codes := admin.Group("/redeem-codes")
- {
- codes.GET("", h.Admin.Redeem.List)
- codes.GET("/stats", h.Admin.Redeem.GetStats)
- codes.GET("/export", h.Admin.Redeem.Export)
- codes.GET("/:id", h.Admin.Redeem.GetByID)
- codes.POST("/create-and-redeem", h.Admin.Redeem.CreateAndRedeem)
- codes.POST("/generate", h.Admin.Redeem.Generate)
- codes.DELETE("/:id", h.Admin.Redeem.Delete)
- codes.POST("/batch-delete", h.Admin.Redeem.BatchDelete)
- codes.POST("/batch-update", h.Admin.Redeem.BatchUpdate)
- codes.POST("/:id/expire", h.Admin.Redeem.Expire)
- }
- }
- func registerPromoCodeRoutes(admin *gin.RouterGroup, h *handler.Handlers) {
- promoCodes := admin.Group("/promo-codes")
- {
- promoCodes.GET("", h.Admin.Promo.List)
- promoCodes.GET("/:id", h.Admin.Promo.GetByID)
- promoCodes.POST("", h.Admin.Promo.Create)
- promoCodes.PUT("/:id", h.Admin.Promo.Update)
- promoCodes.DELETE("/:id", h.Admin.Promo.Delete)
- promoCodes.GET("/:id/usages", h.Admin.Promo.GetUsages)
- }
- }
- func registerSettingsRoutes(admin *gin.RouterGroup, h *handler.Handlers) {
- adminSettings := admin.Group("/settings")
- {
- adminSettings.GET("", h.Admin.Setting.GetSettings)
- adminSettings.PUT("", h.Admin.Setting.UpdateSettings)
- adminSettings.POST("/test-smtp", h.Admin.Setting.TestSMTPConnection)
- adminSettings.POST("/send-test-email", h.Admin.Setting.SendTestEmail)
- adminSettings.GET("/email-templates", h.Admin.Setting.ListEmailTemplates)
- adminSettings.POST("/email-template-preview", h.Admin.Setting.PreviewEmailTemplate)
- adminSettings.GET("/email-templates/:event/:locale", h.Admin.Setting.GetEmailTemplate)
- adminSettings.PUT("/email-templates/:event/:locale", h.Admin.Setting.UpdateEmailTemplate)
- adminSettings.POST("/email-templates/:event/:locale/restore-official", h.Admin.Setting.RestoreOfficialEmailTemplate)
- // Admin API Key 管理
- adminSettings.GET("/admin-api-key", h.Admin.Setting.GetAdminAPIKey)
- adminSettings.POST("/admin-api-key/regenerate", h.Admin.Setting.RegenerateAdminAPIKey)
- adminSettings.DELETE("/admin-api-key", h.Admin.Setting.DeleteAdminAPIKey)
- // 529过载冷却配置
- adminSettings.GET("/overload-cooldown", h.Admin.Setting.GetOverloadCooldownSettings)
- adminSettings.PUT("/overload-cooldown", h.Admin.Setting.UpdateOverloadCooldownSettings)
- // 429默认回避配置
- adminSettings.GET("/rate-limit-429-cooldown", h.Admin.Setting.GetRateLimit429CooldownSettings)
- adminSettings.PUT("/rate-limit-429-cooldown", h.Admin.Setting.UpdateRateLimit429CooldownSettings)
- // OpenAI OAuth image-tool unavailable cooldown configuration
- adminSettings.GET("/openai-images-oauth-unavailable-cooldown", h.Admin.Setting.GetOpenAIImagesOAuthUnavailableCooldownSettings)
- adminSettings.PUT("/openai-images-oauth-unavailable-cooldown", h.Admin.Setting.UpdateOpenAIImagesOAuthUnavailableCooldownSettings)
- // 面板 API 限流配置
- adminSettings.GET("/panel-rate-limit", h.Admin.Setting.GetPanelRateLimitSettings)
- adminSettings.PUT("/panel-rate-limit", h.Admin.Setting.UpdatePanelRateLimitSettings)
- // 流超时处理配置
- adminSettings.GET("/stream-timeout", h.Admin.Setting.GetStreamTimeoutSettings)
- adminSettings.PUT("/stream-timeout", h.Admin.Setting.UpdateStreamTimeoutSettings)
- // 请求整流器配置
- adminSettings.GET("/rectifier", h.Admin.Setting.GetRectifierSettings)
- adminSettings.PUT("/rectifier", h.Admin.Setting.UpdateRectifierSettings)
- // Beta 策略配置
- adminSettings.GET("/beta-policy", h.Admin.Setting.GetBetaPolicySettings)
- adminSettings.PUT("/beta-policy", h.Admin.Setting.UpdateBetaPolicySettings)
- // Web Search 模拟配置
- adminSettings.GET("/web-search-emulation", h.Admin.Setting.GetWebSearchEmulationConfig)
- adminSettings.PUT("/web-search-emulation", h.Admin.Setting.UpdateWebSearchEmulationConfig)
- adminSettings.POST("/web-search-emulation/test", h.Admin.Setting.TestWebSearchEmulation)
- adminSettings.POST("/web-search-emulation/reset-usage", h.Admin.Setting.ResetWebSearchUsage)
- }
- }
- func registerDataManagementRoutes(admin *gin.RouterGroup, h *handler.Handlers, stepUpAuth middleware.StepUpAuthMiddleware) {
- dataManagement := admin.Group("/data-management")
- {
- dataManagement.GET("/agent/health", h.Admin.DataManagement.GetAgentHealth)
- dataManagement.GET("/config", h.Admin.DataManagement.GetConfig)
- dataManagement.PUT("/config", h.Admin.DataManagement.UpdateConfig)
- dataManagement.GET("/sources/:source_type/profiles", h.Admin.DataManagement.ListSourceProfiles)
- dataManagement.POST("/sources/:source_type/profiles", h.Admin.DataManagement.CreateSourceProfile)
- dataManagement.PUT("/sources/:source_type/profiles/:profile_id", h.Admin.DataManagement.UpdateSourceProfile)
- dataManagement.DELETE("/sources/:source_type/profiles/:profile_id", h.Admin.DataManagement.DeleteSourceProfile)
- dataManagement.POST("/sources/:source_type/profiles/:profile_id/activate", h.Admin.DataManagement.SetActiveSourceProfile)
- dataManagement.POST("/s3/test", h.Admin.DataManagement.TestS3)
- dataManagement.GET("/s3/profiles", h.Admin.DataManagement.ListS3Profiles)
- // 修改 S3 目标可将数据备份外泄——要求 step-up 2FA
- dataManagement.POST("/s3/profiles", gin.HandlerFunc(stepUpAuth), h.Admin.DataManagement.CreateS3Profile)
- dataManagement.PUT("/s3/profiles/:profile_id", gin.HandlerFunc(stepUpAuth), h.Admin.DataManagement.UpdateS3Profile)
- dataManagement.DELETE("/s3/profiles/:profile_id", h.Admin.DataManagement.DeleteS3Profile)
- dataManagement.POST("/s3/profiles/:profile_id/activate", gin.HandlerFunc(stepUpAuth), h.Admin.DataManagement.SetActiveS3Profile)
- dataManagement.POST("/backups", gin.HandlerFunc(stepUpAuth), h.Admin.DataManagement.CreateBackupJob)
- dataManagement.GET("/backups", h.Admin.DataManagement.ListBackupJobs)
- dataManagement.GET("/backups/:job_id", h.Admin.DataManagement.GetBackupJob)
- }
- }
- func registerBackupRoutes(admin *gin.RouterGroup, h *handler.Handlers, stepUpAuth middleware.StepUpAuthMiddleware) {
- backup := admin.Group("/backups")
- {
- // S3 存储配置
- backup.GET("/s3-config", h.Admin.Backup.GetS3Config)
- // 修改 S3 目标可将数据库备份外泄——要求 step-up 2FA
- backup.PUT("/s3-config", gin.HandlerFunc(stepUpAuth), h.Admin.Backup.UpdateS3Config)
- backup.POST("/s3-config/test", h.Admin.Backup.TestS3Connection)
- // 异步生图对象存储配置(与备份共用 S3 客户端,可直接复用备份凭证)
- backup.GET("/image-storage", h.Admin.Backup.GetImageStorageConfig)
- // 同 S3 配置:改写对象存储目标可将生成内容导向外部账号——要求 step-up 2FA
- backup.PUT("/image-storage", gin.HandlerFunc(stepUpAuth), h.Admin.Backup.UpdateImageStorageConfig)
- backup.POST("/image-storage/test", h.Admin.Backup.TestImageStorageConnection)
- // 定时备份配置
- backup.GET("/schedule", h.Admin.Backup.GetSchedule)
- backup.PUT("/schedule", h.Admin.Backup.UpdateSchedule)
- // 备份操作
- backup.POST("", gin.HandlerFunc(stepUpAuth), h.Admin.Backup.CreateBackup)
- backup.GET("", h.Admin.Backup.ListBackups)
- backup.GET("/:id", h.Admin.Backup.GetBackup)
- backup.DELETE("/:id", h.Admin.Backup.DeleteBackup)
- // 备份下载链接可直接取走整库数据——要求 step-up 2FA
- backup.GET("/:id/download-url", gin.HandlerFunc(stepUpAuth), h.Admin.Backup.GetDownloadURL)
- // 恢复操作:整库覆盖可回滚安全设置(含 step-up 开关本身)——要求 step-up 2FA
- backup.POST("/:id/restore", gin.HandlerFunc(stepUpAuth), h.Admin.Backup.RestoreBackup)
- }
- }
- func registerSystemRoutes(admin *gin.RouterGroup, h *handler.Handlers, stepUpAuth middleware.StepUpAuthMiddleware) {
- system := admin.Group("/system")
- {
- system.GET("/version", h.Admin.System.GetVersion)
- system.GET("/check-updates", h.Admin.System.CheckUpdates)
- system.GET("/rollback-versions", h.Admin.System.GetRollbackVersions)
- system.POST("/update", gin.HandlerFunc(stepUpAuth), h.Admin.System.PerformUpdate)
- system.POST("/rollback", gin.HandlerFunc(stepUpAuth), h.Admin.System.Rollback)
- system.POST("/restart", gin.HandlerFunc(stepUpAuth), h.Admin.System.RestartService)
- }
- }
- func registerSubscriptionRoutes(admin *gin.RouterGroup, h *handler.Handlers) {
- subscriptions := admin.Group("/subscriptions")
- {
- subscriptions.GET("", h.Admin.Subscription.List)
- subscriptions.GET("/:id", h.Admin.Subscription.GetByID)
- subscriptions.GET("/:id/progress", h.Admin.Subscription.GetProgress)
- subscriptions.POST("/assign", h.Admin.Subscription.Assign)
- subscriptions.POST("/bulk-assign", h.Admin.Subscription.BulkAssign)
- subscriptions.POST("/:id/extend", h.Admin.Subscription.Extend)
- subscriptions.POST("/:id/reset-quota", h.Admin.Subscription.ResetQuota)
- subscriptions.POST("/:id/revoke", h.Admin.Subscription.Revoke)
- subscriptions.POST("/:id/restore", h.Admin.Subscription.Restore)
- subscriptions.DELETE("/:id", h.Admin.Subscription.Revoke)
- }
- // 分组下的订阅列表
- admin.GET("/groups/:id/subscriptions", h.Admin.Subscription.ListByGroup)
- // 用户下的订阅列表
- admin.GET("/users/:id/subscriptions", h.Admin.Subscription.ListByUser)
- }
- func registerUsageRoutes(admin *gin.RouterGroup, h *handler.Handlers) {
- usage := admin.Group("/usage")
- {
- usage.GET("", h.Admin.Usage.List)
- usage.GET("/stats", h.Admin.Usage.Stats)
- usage.GET("/search-users", h.Admin.Usage.SearchUsers)
- usage.GET("/search-api-keys", h.Admin.Usage.SearchAPIKeys)
- usage.GET("/cleanup-tasks", h.Admin.Usage.ListCleanupTasks)
- usage.POST("/cleanup-tasks", h.Admin.Usage.CreateCleanupTask)
- usage.POST("/cleanup-tasks/:id/cancel", h.Admin.Usage.CancelCleanupTask)
- }
- }
- func registerUserAttributeRoutes(admin *gin.RouterGroup, h *handler.Handlers) {
- attrs := admin.Group("/user-attributes")
- {
- attrs.GET("", h.Admin.UserAttribute.ListDefinitions)
- attrs.POST("", h.Admin.UserAttribute.CreateDefinition)
- attrs.POST("/batch", h.Admin.UserAttribute.GetBatchUserAttributes)
- attrs.PUT("/reorder", h.Admin.UserAttribute.ReorderDefinitions)
- attrs.PUT("/:id", h.Admin.UserAttribute.UpdateDefinition)
- attrs.DELETE("/:id", h.Admin.UserAttribute.DeleteDefinition)
- }
- }
- func registerScheduledTestRoutes(admin *gin.RouterGroup, h *handler.Handlers) {
- plans := admin.Group("/scheduled-test-plans")
- {
- plans.POST("", h.Admin.ScheduledTest.Create)
- plans.PUT("/:id", h.Admin.ScheduledTest.Update)
- plans.DELETE("/:id", h.Admin.ScheduledTest.Delete)
- plans.GET("/:id/results", h.Admin.ScheduledTest.ListResults)
- }
- // Nested under accounts
- admin.GET("/accounts/:id/scheduled-test-plans", h.Admin.ScheduledTest.ListByAccount)
- }
- func registerErrorPassthroughRoutes(admin *gin.RouterGroup, h *handler.Handlers) {
- rules := admin.Group("/error-passthrough-rules")
- {
- rules.GET("", h.Admin.ErrorPassthrough.List)
- rules.GET("/:id", h.Admin.ErrorPassthrough.GetByID)
- rules.POST("", h.Admin.ErrorPassthrough.Create)
- rules.PUT("/:id", h.Admin.ErrorPassthrough.Update)
- rules.DELETE("/:id", h.Admin.ErrorPassthrough.Delete)
- }
- }
- func registerTLSFingerprintProfileRoutes(admin *gin.RouterGroup, h *handler.Handlers) {
- profiles := admin.Group("/tls-fingerprint-profiles")
- {
- profiles.GET("", h.Admin.TLSFingerprintProfile.List)
- profiles.GET("/:id", h.Admin.TLSFingerprintProfile.GetByID)
- profiles.POST("", h.Admin.TLSFingerprintProfile.Create)
- profiles.PUT("/:id", h.Admin.TLSFingerprintProfile.Update)
- profiles.DELETE("/:id", h.Admin.TLSFingerprintProfile.Delete)
- }
- }
- func registerPluginRoutes(admin *gin.RouterGroup, h *handler.Handlers, stepUpAuth middleware.StepUpAuthMiddleware) {
- plugins := admin.Group("/plugins")
- {
- plugins.GET("", h.Admin.Plugin.List)
- plugins.GET("/:id", h.Admin.Plugin.Get)
- plugins.POST("/upload", gin.HandlerFunc(stepUpAuth), h.Admin.Plugin.Upload)
- plugins.POST("/:id/enable", gin.HandlerFunc(stepUpAuth), h.Admin.Plugin.Enable)
- plugins.POST("/:id/disable", gin.HandlerFunc(stepUpAuth), h.Admin.Plugin.Disable)
- plugins.DELETE("/:id", gin.HandlerFunc(stepUpAuth), h.Admin.Plugin.Delete)
- plugins.GET("/:id/config", h.Admin.Plugin.GetConfig)
- plugins.PUT("/:id/config", gin.HandlerFunc(stepUpAuth), h.Admin.Plugin.SaveConfig)
- plugins.POST("/:id/test", gin.HandlerFunc(stepUpAuth), h.Admin.Plugin.Test)
- plugins.POST("/:id/ui-session", h.Admin.Plugin.CreateUISession)
- }
- }
- func registerGlobalPricingRoutes(admin *gin.RouterGroup, h *handler.Handlers) {
- pricing := admin.Group("/global-pricing")
- {
- pricing.GET("", h.Admin.GlobalPricing.List)
- pricing.POST("", h.Admin.GlobalPricing.Create)
- pricing.PUT("/:id", h.Admin.GlobalPricing.Update)
- pricing.DELETE("/:id", h.Admin.GlobalPricing.Delete)
- pricing.POST("/:id/enable", h.Admin.GlobalPricing.SetEnabled)
- }
- }
- func registerAccountHealthRoutes(admin *gin.RouterGroup, h *handler.Handlers) {
- health := admin.Group("/account-health")
- {
- health.GET("", h.Admin.AccountHealth.Snapshot)
- health.GET("/settings", h.Admin.AccountHealth.GetSettings)
- health.PUT("/settings", h.Admin.AccountHealth.UpdateSettings)
- health.POST("/:id/isolate", h.Admin.AccountHealth.Isolate)
- health.POST("/:id/resume", h.Admin.AccountHealth.Resume)
- }
- }
- func registerMarginRoutes(admin *gin.RouterGroup, h *handler.Handlers) {
- margins := admin.Group("/margins")
- {
- margins.GET("", h.Admin.Margin.Summary)
- margins.GET("/fuse-settings", h.Admin.Margin.GetSettings)
- margins.PUT("/fuse-settings", h.Admin.Margin.UpdateSettings)
- margins.GET("/events", h.Admin.Margin.Events)
- margins.POST("/channels/:id/unfuse", h.Admin.Margin.Unfuse)
- }
- }
- func registerTieredRoutingRoutes(admin *gin.RouterGroup, h *handler.Handlers) {
- routing := admin.Group("/tiered-routing")
- {
- routing.GET("/settings", h.Admin.TieredRouting.GetSettings)
- routing.PUT("/settings", h.Admin.TieredRouting.UpdateSettings)
- }
- }
- func registerSpendGuardRoutes(admin *gin.RouterGroup, h *handler.Handlers) {
- guard := admin.Group("/spend-guard")
- {
- guard.GET("", h.Admin.SpendGuard.Offenders)
- guard.GET("/settings", h.Admin.SpendGuard.GetSettings)
- guard.PUT("/settings", h.Admin.SpendGuard.UpdateSettings)
- guard.GET("/events", h.Admin.SpendGuard.Events)
- guard.POST("/keys/:id/unfreeze", h.Admin.SpendGuard.Unfreeze)
- }
- }
- func registerTicketAdminRoutes(admin *gin.RouterGroup, h *handler.Handlers) {
- tickets := admin.Group("/tickets")
- {
- tickets.GET("", h.Admin.Ticket.ListAll)
- tickets.GET("/stats", h.Admin.Ticket.Stats)
- tickets.GET("/:id", h.Admin.Ticket.GetAny)
- tickets.POST("/:id/replies", h.Admin.Ticket.ReplyAny)
- tickets.POST("/:id/close", h.Admin.Ticket.CloseAny)
- }
- }
- func registerBillingExportAdminRoutes(admin *gin.RouterGroup, h *handler.Handlers) {
- billing := admin.Group("/billing/users/:userId")
- {
- billing.GET("/statement", h.Admin.BillingExport.AdminStatement)
- billing.GET("/export", h.Admin.BillingExport.AdminExport)
- }
- }
- func registerChannelRoutes(admin *gin.RouterGroup, h *handler.Handlers) {
- channels := admin.Group("/channels")
- {
- channels.GET("", h.Admin.Channel.List)
- channels.GET("/model-pricing", h.Admin.Channel.GetModelDefaultPricing)
- channels.GET("/pricing/sync-models", h.Admin.Channel.SyncPricingModels)
- channels.GET("/:id", h.Admin.Channel.GetByID)
- channels.POST("", h.Admin.Channel.Create)
- channels.PUT("/:id", h.Admin.Channel.Update)
- channels.DELETE("/:id", h.Admin.Channel.Delete)
- }
- }
- func registerChannelMonitorRoutes(admin *gin.RouterGroup, h *handler.Handlers, settingService *service.SettingService) {
- guard := channelMonitorAdminFeatureGuard(settingService)
- monitors := admin.Group("/channel-monitors")
- monitors.Use(guard)
- {
- monitors.GET("", h.Admin.ChannelMonitor.List)
- monitors.POST("", h.Admin.ChannelMonitor.Create)
- monitors.GET("/:id", h.Admin.ChannelMonitor.Get)
- monitors.POST("/:id/duplicate", h.Admin.ChannelMonitor.Duplicate)
- monitors.PUT("/:id", h.Admin.ChannelMonitor.Update)
- monitors.DELETE("/:id", h.Admin.ChannelMonitor.Delete)
- monitors.POST("/:id/run", h.Admin.ChannelMonitor.Run)
- monitors.GET("/:id/history", h.Admin.ChannelMonitor.History)
- }
- templates := admin.Group("/channel-monitor-templates")
- templates.Use(guard)
- {
- templates.GET("", h.Admin.ChannelMonitorTemplate.List)
- templates.POST("", h.Admin.ChannelMonitorTemplate.Create)
- templates.GET("/:id", h.Admin.ChannelMonitorTemplate.Get)
- templates.PUT("/:id", h.Admin.ChannelMonitorTemplate.Update)
- templates.DELETE("/:id", h.Admin.ChannelMonitorTemplate.Delete)
- templates.GET("/:id/monitors", h.Admin.ChannelMonitorTemplate.AssociatedMonitors)
- templates.POST("/:id/apply", h.Admin.ChannelMonitorTemplate.Apply)
- }
- }
- // registerAffiliateRoutes 注册邀请返利的管理端路由(专属用户配置)
- func registerAffiliateRoutes(admin *gin.RouterGroup, h *handler.Handlers) {
- affiliates := admin.Group("/affiliates")
- {
- affiliates.GET("/invites", h.Admin.Affiliate.ListInviteRecords)
- affiliates.GET("/rebates", h.Admin.Affiliate.ListRebateRecords)
- affiliates.GET("/transfers", h.Admin.Affiliate.ListTransferRecords)
- users := affiliates.Group("/users")
- {
- users.GET("", h.Admin.Affiliate.ListUsers)
- users.GET("/lookup", h.Admin.Affiliate.LookupUsers)
- users.POST("/batch-rate", h.Admin.Affiliate.BatchSetRate)
- users.GET("/:user_id/overview", h.Admin.Affiliate.GetUserOverview)
- users.PUT("/:user_id", h.Admin.Affiliate.UpdateUserSettings)
- users.DELETE("/:user_id", h.Admin.Affiliate.ClearUserSettings)
- }
- }
- }
- func registerChannelMonitorV2Routes(admin *gin.RouterGroup, h *handler.Handlers, settingService *service.SettingService) {
- // Config GET/PUT: feature enabled only (operators can prepare V2 before flipping mode).
- // Read/matrix endpoints: require mode=v2 so V1 deployments do not serve passive data.
- featureGuard := channelMonitorAdminFeatureGuard(settingService)
- modeV2Guard := channelMonitorModeV2Guard(settingService)
- monitor := admin.Group("/channel-monitor-v2")
- {
- config := monitor.Group("")
- config.Use(featureGuard)
- {
- config.GET("/config", h.ChannelMonitorV2.GetConfig)
- config.PUT("/config", h.ChannelMonitorV2.UpdateConfig)
- }
- reads := monitor.Group("")
- reads.Use(modeV2Guard)
- {
- reads.GET("/dimensions", h.ChannelMonitorV2.Dimensions)
- reads.GET("/snapshot", h.ChannelMonitorV2.AdminSnapshot)
- reads.GET("/models", h.ChannelMonitorV2.AdminModels)
- reads.GET("/matrix", h.ChannelMonitorV2.AdminMatrix)
- reads.GET("/errors", h.ChannelMonitorV2.Errors)
- reads.GET("/users", h.ChannelMonitorV2.AdminUsers)
- }
- }
- }
- func channelMonitorAdminFeatureGuard(settingService *service.SettingService) gin.HandlerFunc {
- return func(c *gin.Context) {
- if settingService != nil && settingService.GetChannelMonitorRuntime(c.Request.Context()).Enabled {
- c.Next()
- return
- }
- response.ErrorFrom(c, service.ErrChannelMonitorDisabled)
- c.Abort()
- }
- }
- // channelMonitorModeV2Guard requires feature enabled and channel_monitor_mode=v2.
- func channelMonitorModeV2Guard(settingService *service.SettingService) gin.HandlerFunc {
- return func(c *gin.Context) {
- if settingService == nil {
- response.ErrorFrom(c, service.ErrChannelMonitorDisabled)
- c.Abort()
- return
- }
- rt := settingService.GetChannelMonitorRuntime(c.Request.Context())
- if !rt.Enabled {
- response.ErrorFrom(c, service.ErrChannelMonitorDisabled)
- c.Abort()
- return
- }
- if !rt.PassiveAggregationAllowed() {
- response.ErrorFrom(c, service.ErrChannelMonitorModeMismatch)
- c.Abort()
- return
- }
- c.Next()
- }
- }
|