- 支持创建/编辑/删除优惠码,设置赠送金额和使用限制 - 注册页面实时验证优惠码并显示赠送金额 - 支持 URL 参数自动填充 (?promo=CODE) - 添加优惠码验证接口速率限制 - 使用数据库行锁防止并发超限 - 新增后台优惠码管理页面,支持复制注册链接
284 lines
10 KiB
Go
284 lines
10 KiB
Go
// Package routes provides HTTP route registration and handlers.
|
|
package routes
|
|
|
|
import (
|
|
"github.com/Wei-Shaw/sub2api/internal/handler"
|
|
"github.com/Wei-Shaw/sub2api/internal/server/middleware"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
// RegisterAdminRoutes 注册管理员路由
|
|
func RegisterAdminRoutes(
|
|
v1 *gin.RouterGroup,
|
|
h *handler.Handlers,
|
|
adminAuth middleware.AdminAuthMiddleware,
|
|
) {
|
|
admin := v1.Group("/admin")
|
|
admin.Use(gin.HandlerFunc(adminAuth))
|
|
{
|
|
// 仪表盘
|
|
registerDashboardRoutes(admin, h)
|
|
|
|
// 用户管理
|
|
registerUserManagementRoutes(admin, h)
|
|
|
|
// 分组管理
|
|
registerGroupRoutes(admin, h)
|
|
|
|
// 账号管理
|
|
registerAccountRoutes(admin, h)
|
|
|
|
// OpenAI OAuth
|
|
registerOpenAIOAuthRoutes(admin, h)
|
|
|
|
// Gemini OAuth
|
|
registerGeminiOAuthRoutes(admin, h)
|
|
|
|
// Antigravity OAuth
|
|
registerAntigravityOAuthRoutes(admin, h)
|
|
|
|
// 代理管理
|
|
registerProxyRoutes(admin, h)
|
|
|
|
// 卡密管理
|
|
registerRedeemCodeRoutes(admin, h)
|
|
|
|
// 优惠码管理
|
|
registerPromoCodeRoutes(admin, h)
|
|
|
|
// 系统设置
|
|
registerSettingsRoutes(admin, h)
|
|
|
|
// 系统管理
|
|
registerSystemRoutes(admin, h)
|
|
|
|
// 订阅管理
|
|
registerSubscriptionRoutes(admin, h)
|
|
|
|
// 使用记录管理
|
|
registerUsageRoutes(admin, h)
|
|
|
|
// 用户属性管理
|
|
registerUserAttributeRoutes(admin, h)
|
|
}
|
|
}
|
|
|
|
func registerDashboardRoutes(admin *gin.RouterGroup, h *handler.Handlers) {
|
|
dashboard := admin.Group("/dashboard")
|
|
{
|
|
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("/api-keys-trend", h.Admin.Dashboard.GetAPIKeyUsageTrend)
|
|
dashboard.GET("/users-trend", h.Admin.Dashboard.GetUserUsageTrend)
|
|
dashboard.POST("/users-usage", h.Admin.Dashboard.GetBatchUsersUsage)
|
|
dashboard.POST("/api-keys-usage", h.Admin.Dashboard.GetBatchAPIKeysUsage)
|
|
}
|
|
}
|
|
|
|
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("", 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)
|
|
|
|
// 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("/:id", h.Admin.Group.GetByID)
|
|
groups.POST("", h.Admin.Group.Create)
|
|
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/api-keys", h.Admin.Group.GetGroupAPIKeys)
|
|
}
|
|
}
|
|
|
|
func registerAccountRoutes(admin *gin.RouterGroup, h *handler.Handlers) {
|
|
accounts := admin.Group("/accounts")
|
|
{
|
|
accounts.GET("", h.Admin.Account.List)
|
|
accounts.GET("/:id", h.Admin.Account.GetByID)
|
|
accounts.POST("", h.Admin.Account.Create)
|
|
accounts.POST("/sync/crs", h.Admin.Account.SyncFromCRS)
|
|
accounts.PUT("/:id", h.Admin.Account.Update)
|
|
accounts.DELETE("/:id", h.Admin.Account.Delete)
|
|
accounts.POST("/:id/test", h.Admin.Account.Test)
|
|
accounts.POST("/:id/refresh", h.Admin.Account.Refresh)
|
|
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.GET("/:id/usage", h.Admin.Account.GetUsage)
|
|
accounts.GET("/:id/today-stats", h.Admin.Account.GetTodayStats)
|
|
accounts.POST("/:id/clear-rate-limit", h.Admin.Account.ClearRateLimit)
|
|
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.GET("/:id/models", h.Admin.Account.GetAvailableModels)
|
|
accounts.POST("/batch", h.Admin.Account.BatchCreate)
|
|
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)
|
|
|
|
// 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 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)
|
|
}
|
|
}
|
|
|
|
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)
|
|
}
|
|
}
|
|
|
|
func registerProxyRoutes(admin *gin.RouterGroup, h *handler.Handlers) {
|
|
proxies := admin.Group("/proxies")
|
|
{
|
|
proxies.GET("", h.Admin.Proxy.List)
|
|
proxies.GET("/all", h.Admin.Proxy.GetAll)
|
|
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.GET("/:id/stats", h.Admin.Proxy.GetStats)
|
|
proxies.GET("/:id/accounts", h.Admin.Proxy.GetProxyAccounts)
|
|
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("/generate", h.Admin.Redeem.Generate)
|
|
codes.DELETE("/:id", h.Admin.Redeem.Delete)
|
|
codes.POST("/batch-delete", h.Admin.Redeem.BatchDelete)
|
|
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)
|
|
// 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)
|
|
}
|
|
}
|
|
|
|
func registerSystemRoutes(admin *gin.RouterGroup, h *handler.Handlers) {
|
|
system := admin.Group("/system")
|
|
{
|
|
system.GET("/version", h.Admin.System.GetVersion)
|
|
system.GET("/check-updates", h.Admin.System.CheckUpdates)
|
|
system.POST("/update", h.Admin.System.PerformUpdate)
|
|
system.POST("/rollback", h.Admin.System.Rollback)
|
|
system.POST("/restart", 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.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)
|
|
}
|
|
}
|
|
|
|
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)
|
|
}
|
|
}
|