Files
backend/internal/handler/routes_di.go
lan f7589ebbb8 feat: 引入依赖注入模式
- 创建Repository接口定义(UserRepository、ProfileRepository、TextureRepository等)
- 创建Repository接口实现
- 创建依赖注入容器(container.Container)
- 改造Handler层使用依赖注入(AuthHandler、UserHandler、TextureHandler)
- 创建新的路由注册方式(RegisterRoutesWithDI)
- 提供main.go示例文件展示如何使用依赖注入

同时包含之前的安全修复:
- CORS配置安全加固
- 头像URL验证安全修复
- JWT algorithm confusion漏洞修复
- Recovery中间件增强
- 敏感错误信息泄露修复
- 类型断言安全修复
2025-12-02 17:40:39 +08:00

192 lines
5.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package handler
import (
"carrotskin/internal/container"
"carrotskin/internal/middleware"
"carrotskin/internal/model"
"github.com/gin-gonic/gin"
)
// Handlers 集中管理所有Handler
type Handlers struct {
Auth *AuthHandler
User *UserHandler
Texture *TextureHandler
// Profile *ProfileHandler // 后续添加
// Captcha *CaptchaHandler // 后续添加
// Yggdrasil *YggdrasilHandler // 后续添加
}
// NewHandlers 创建所有Handler实例
func NewHandlers(c *container.Container) *Handlers {
return &Handlers{
Auth: NewAuthHandler(c),
User: NewUserHandler(c),
Texture: NewTextureHandler(c),
}
}
// RegisterRoutesWithDI 使用依赖注入注册所有路由
func RegisterRoutesWithDI(router *gin.Engine, c *container.Container) {
// 设置Swagger文档
SetupSwagger(router)
// 创建Handler实例
h := NewHandlers(c)
// API路由组
v1 := router.Group("/api/v1")
{
// 认证路由无需JWT
registerAuthRoutes(v1, h.Auth)
// 用户路由需要JWT认证
registerUserRoutes(v1, h.User)
// 材质路由
registerTextureRoutes(v1, h.Texture)
// 档案路由(暂时保持原有方式)
registerProfileRoutes(v1)
// 验证码路由(暂时保持原有方式)
registerCaptchaRoutes(v1)
// Yggdrasil API路由组暂时保持原有方式
registerYggdrasilRoutes(v1)
// 系统路由
registerSystemRoutes(v1)
}
}
// registerAuthRoutes 注册认证路由
func registerAuthRoutes(v1 *gin.RouterGroup, h *AuthHandler) {
authGroup := v1.Group("/auth")
{
authGroup.POST("/register", h.Register)
authGroup.POST("/login", h.Login)
authGroup.POST("/send-code", h.SendVerificationCode)
authGroup.POST("/reset-password", h.ResetPassword)
}
}
// registerUserRoutes 注册用户路由
func registerUserRoutes(v1 *gin.RouterGroup, h *UserHandler) {
userGroup := v1.Group("/user")
userGroup.Use(middleware.AuthMiddleware())
{
userGroup.GET("/profile", h.GetProfile)
userGroup.PUT("/profile", h.UpdateProfile)
// 头像相关
userGroup.POST("/avatar/upload-url", h.GenerateAvatarUploadURL)
userGroup.PUT("/avatar", h.UpdateAvatar)
// 更换邮箱
userGroup.POST("/change-email", h.ChangeEmail)
// Yggdrasil密码相关
userGroup.POST("/yggdrasil-password/reset", h.ResetYggdrasilPassword)
}
}
// registerTextureRoutes 注册材质路由
func registerTextureRoutes(v1 *gin.RouterGroup, h *TextureHandler) {
textureGroup := v1.Group("/texture")
{
// 公开路由(无需认证)
textureGroup.GET("", h.Search)
textureGroup.GET("/:id", h.Get)
// 需要认证的路由
textureAuth := textureGroup.Group("")
textureAuth.Use(middleware.AuthMiddleware())
{
textureAuth.POST("/upload-url", h.GenerateUploadURL)
textureAuth.POST("", h.Create)
textureAuth.PUT("/:id", h.Update)
textureAuth.DELETE("/:id", h.Delete)
textureAuth.POST("/:id/favorite", h.ToggleFavorite)
textureAuth.GET("/my", h.GetUserTextures)
textureAuth.GET("/favorites", h.GetUserFavorites)
}
}
}
// registerProfileRoutes 注册档案路由(保持原有方式,后续改造)
func registerProfileRoutes(v1 *gin.RouterGroup) {
profileGroup := v1.Group("/profile")
{
// 公开路由(无需认证)
profileGroup.GET("/:uuid", GetProfile)
// 需要认证的路由
profileAuth := profileGroup.Group("")
profileAuth.Use(middleware.AuthMiddleware())
{
profileAuth.POST("/", CreateProfile)
profileAuth.GET("/", GetProfiles)
profileAuth.PUT("/:uuid", UpdateProfile)
profileAuth.DELETE("/:uuid", DeleteProfile)
profileAuth.POST("/:uuid/activate", SetActiveProfile)
}
}
}
// registerCaptchaRoutes 注册验证码路由(保持原有方式)
func registerCaptchaRoutes(v1 *gin.RouterGroup) {
captchaGroup := v1.Group("/captcha")
{
captchaGroup.GET("/generate", Generate)
captchaGroup.POST("/verify", Verify)
}
}
// registerYggdrasilRoutes 注册Yggdrasil API路由保持原有方式
func registerYggdrasilRoutes(v1 *gin.RouterGroup) {
ygg := v1.Group("/yggdrasil")
{
ygg.GET("", GetMetaData)
ygg.POST("/minecraftservices/player/certificates", GetPlayerCertificates)
authserver := ygg.Group("/authserver")
{
authserver.POST("/authenticate", Authenticate)
authserver.POST("/validate", ValidToken)
authserver.POST("/refresh", RefreshToken)
authserver.POST("/invalidate", InvalidToken)
authserver.POST("/signout", SignOut)
}
sessionServer := ygg.Group("/sessionserver")
{
sessionServer.GET("/session/minecraft/profile/:uuid", GetProfileByUUID)
sessionServer.POST("/session/minecraft/join", JoinServer)
sessionServer.GET("/session/minecraft/hasJoined", HasJoinedServer)
}
api := ygg.Group("/api")
profiles := api.Group("/profiles")
{
profiles.POST("/minecraft", GetProfilesByName)
}
}
}
// registerSystemRoutes 注册系统路由
func registerSystemRoutes(v1 *gin.RouterGroup) {
system := v1.Group("/system")
{
system.GET("/config", func(c *gin.Context) {
// TODO: 实现从数据库读取系统配置
c.JSON(200, model.NewSuccessResponse(gin.H{
"site_name": "CarrotSkin",
"site_description": "A Minecraft Skin Station",
"registration_enabled": true,
"max_textures_per_user": 100,
"max_profiles_per_user": 5,
}))
})
}
}