user.go 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. package routes
  2. import (
  3. "github.com/Wei-Shaw/sub2api/internal/handler"
  4. "github.com/Wei-Shaw/sub2api/internal/server/middleware"
  5. "github.com/Wei-Shaw/sub2api/internal/service"
  6. "github.com/gin-gonic/gin"
  7. )
  8. // RegisterUserRoutes 注册用户相关路由(需要认证)
  9. func RegisterUserRoutes(
  10. v1 *gin.RouterGroup,
  11. h *handler.Handlers,
  12. jwtAuth middleware.JWTAuthMiddleware,
  13. auditLog middleware.AuditLogMiddleware,
  14. settingService *service.SettingService,
  15. panelRateLimiter *middleware.PanelRateLimiter,
  16. ) {
  17. authenticated := v1.Group("")
  18. authenticated.Use(gin.HandlerFunc(jwtAuth))
  19. authenticated.Use(middleware.BackendModeUserGuard(settingService))
  20. // 面板全局按用户限流:防止单个账号高频刷接口打爆数据库
  21. authenticated.Use(panelRateLimiter.Global())
  22. // 用户管理面变更类操作入审计(含 TOTP 启用/禁用、step-up 验证、密码修改等安全事件)
  23. authenticated.Use(gin.HandlerFunc(auditLog))
  24. registerAccountCapabilityRoutes(authenticated, h)
  25. {
  26. // 用户接口
  27. user := authenticated.Group("/user")
  28. {
  29. user.GET("/profile", h.User.GetProfile)
  30. user.PUT("/password", h.User.ChangePassword)
  31. user.PUT("", h.User.UpdateProfile)
  32. user.GET("/aff", h.User.GetAffiliate)
  33. user.POST("/aff/transfer", h.User.TransferAffiliateQuota)
  34. user.POST("/account-bindings/email/send-code", h.User.SendEmailBindingCode)
  35. user.POST("/account-bindings/email", h.User.BindEmailIdentity)
  36. user.DELETE("/account-bindings/:provider", h.User.UnbindIdentity)
  37. user.POST("/auth-identities/bind/start", h.User.StartIdentityBinding)
  38. user.GET("/api-keys/:id/usage/daily", panelRateLimiter.Heavy(), h.Usage.GetMyAPIKeyDailyUsage)
  39. user.GET("/platform-quotas", h.User.GetMyPlatformQuotas)
  40. // 通知邮箱管理
  41. notifyEmail := user.Group("/notify-email")
  42. {
  43. notifyEmail.POST("/send-code", h.User.SendNotifyEmailCode)
  44. notifyEmail.POST("/verify", h.User.VerifyNotifyEmail)
  45. notifyEmail.PUT("/toggle", h.User.ToggleNotifyEmail)
  46. notifyEmail.DELETE("", h.User.RemoveNotifyEmail)
  47. }
  48. // TOTP 双因素认证
  49. totp := user.Group("/totp")
  50. {
  51. totp.GET("/status", h.Totp.GetStatus)
  52. totp.GET("/verification-method", h.Totp.GetVerificationMethod)
  53. totp.POST("/send-code", h.Totp.SendVerifyCode)
  54. totp.POST("/setup", h.Totp.InitiateSetup)
  55. totp.POST("/enable", h.Totp.Enable)
  56. totp.POST("/disable", h.Totp.Disable)
  57. // 敏感操作二次验证:授予当前会话一段时间的 step-up 权限
  58. totp.POST("/step-up", h.Totp.StepUp)
  59. }
  60. passkeys := user.Group("/passkeys")
  61. {
  62. passkeys.GET("", h.Passkey.List)
  63. passkeys.POST("/register/begin", h.Passkey.BeginRegistration)
  64. passkeys.POST("/register/finish", h.Passkey.FinishRegistration)
  65. passkeys.PATCH("/:id", h.Passkey.Rename)
  66. passkeys.DELETE("/:id", h.Passkey.Delete)
  67. }
  68. }
  69. // API Key管理
  70. keys := authenticated.Group("/keys")
  71. {
  72. keys.GET("", h.APIKey.List)
  73. keys.GET("/:id", h.APIKey.GetByID)
  74. keys.POST("", h.APIKey.Create)
  75. keys.PUT("/:id", h.APIKey.Update)
  76. keys.DELETE("/:id", h.APIKey.Delete)
  77. }
  78. // 用户可用分组(非管理员接口)
  79. groups := authenticated.Group("/groups")
  80. {
  81. groups.GET("/available", h.APIKey.GetAvailableGroups)
  82. groups.GET("/rates", h.APIKey.GetUserGroupRates)
  83. }
  84. // 用户可用渠道(非管理员接口)
  85. channels := authenticated.Group("/channels")
  86. {
  87. channels.GET("/available", h.AvailableChannel.List)
  88. }
  89. // 使用记录(聚合统计属重查询,叠加更严格的按用户限流)
  90. usage := authenticated.Group("/usage")
  91. usage.Use(panelRateLimiter.Heavy())
  92. {
  93. usage.GET("", h.Usage.List)
  94. usage.GET("/errors", h.Usage.ListErrors)
  95. usage.GET("/errors/:id", h.Usage.GetErrorDetail)
  96. usage.GET("/:id", h.Usage.GetByID)
  97. usage.GET("/stats", h.Usage.Stats)
  98. // User dashboard endpoints
  99. usage.GET("/dashboard/stats", h.Usage.DashboardStats)
  100. usage.GET("/dashboard/trend", h.Usage.DashboardTrend)
  101. usage.GET("/dashboard/models", h.Usage.DashboardModels)
  102. usage.GET("/dashboard/snapshot-v2", h.Usage.DashboardSnapshotV2)
  103. usage.POST("/dashboard/api-keys-usage", h.Usage.DashboardAPIKeysUsage)
  104. }
  105. // 公告(用户可见)
  106. announcements := authenticated.Group("/announcements")
  107. {
  108. announcements.GET("", h.Announcement.List)
  109. announcements.POST("/:id/read", h.Announcement.MarkRead)
  110. }
  111. // 工单
  112. tickets := authenticated.Group("/tickets")
  113. {
  114. tickets.GET("", h.Admin.Ticket.ListMine)
  115. tickets.POST("", h.Admin.Ticket.Create)
  116. tickets.GET("/:id", h.Admin.Ticket.GetMine)
  117. tickets.POST("/:id/replies", h.Admin.Ticket.ReplyMine)
  118. tickets.POST("/:id/close", h.Admin.Ticket.CloseMine)
  119. }
  120. // 账单:月账单与用量导出
  121. billing := authenticated.Group("/billing")
  122. {
  123. billing.GET("/statement", h.Admin.BillingExport.Statement)
  124. billing.GET("/export", h.Admin.BillingExport.Export)
  125. }
  126. // 卡密兑换
  127. redeem := authenticated.Group("/redeem")
  128. {
  129. redeem.POST("", h.Redeem.Redeem)
  130. redeem.GET("/history", h.Redeem.GetHistory)
  131. }
  132. // 用户订阅
  133. subscriptions := authenticated.Group("/subscriptions")
  134. {
  135. subscriptions.GET("", h.Subscription.List)
  136. subscriptions.GET("/active", h.Subscription.GetActive)
  137. subscriptions.GET("/progress", h.Subscription.GetProgress)
  138. subscriptions.GET("/summary", h.Subscription.GetSummary)
  139. }
  140. // 渠道监控(用户只读)
  141. monitors := authenticated.Group("/channel-monitors")
  142. {
  143. monitors.GET("", h.ChannelMonitor.List)
  144. monitors.GET("/:id/status", h.ChannelMonitor.GetStatus)
  145. }
  146. // V2 passive views require feature on + mode=v2.
  147. monitorV2 := authenticated.Group("/channel-monitor-v2")
  148. monitorV2.Use(panelRateLimiter.Heavy())
  149. monitorV2.Use(channelMonitorModeV2Guard(settingService))
  150. {
  151. monitorV2.GET("/dimensions", h.ChannelMonitorV2.Dimensions)
  152. monitorV2.GET("/snapshot", h.ChannelMonitorV2.Snapshot)
  153. monitorV2.GET("/models", h.ChannelMonitorV2.Models)
  154. monitorV2.GET("/matrix", h.ChannelMonitorV2.Matrix)
  155. monitorV2.GET("/errors", h.ChannelMonitorV2.Errors)
  156. monitorV2.GET("/users", h.ChannelMonitorV2.Users)
  157. }
  158. }
  159. }