package handler import ( "carrotskin/internal/container" "carrotskin/internal/middleware" "carrotskin/internal/model" "carrotskin/pkg/auth" "carrotskin/pkg/config" "github.com/gin-gonic/gin" swaggerFiles "github.com/swaggo/files" ginSwagger "github.com/swaggo/gin-swagger" ) // Handlers 集中管理所有Handler type Handlers struct { Auth *AuthHandler User *UserHandler Texture *TextureHandler Profile *ProfileHandler Captcha *CaptchaHandler Yggdrasil *YggdrasilHandler CustomSkin *CustomSkinHandler Admin *AdminHandler } // NewHandlers 创建所有Handler实例 func NewHandlers(c *container.Container) *Handlers { return &Handlers{ Auth: NewAuthHandler(c), User: NewUserHandler(c), Texture: NewTextureHandler(c), Profile: NewProfileHandler(c), Captcha: NewCaptchaHandler(c), Yggdrasil: NewYggdrasilHandler(c), CustomSkin: NewCustomSkinHandler(c), Admin: NewAdminHandler(c), } } // RegisterRoutesWithDI 使用依赖注入注册所有路由 func RegisterRoutesWithDI(router *gin.Engine, c *container.Container) { // 健康检查路由 router.GET("/health", HealthCheck) // Swagger文档路由 router.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler)) // 创建Handler实例 h := NewHandlers(c) // API路由组 v1 := router.Group("/api/v1") { // 认证路由(无需JWT) registerAuthRoutes(v1, h.Auth) // 用户路由(需要JWT认证) registerUserRoutes(v1, h.User, c.JWT) // 材质路由 registerTextureRoutes(v1, h.Texture, c.JWT) // 档案路由 registerProfileRoutesWithDI(v1, h.Profile, c.JWT) // 验证码路由 registerCaptchaRoutesWithDI(v1, h.Captcha) // Yggdrasil API路由组 registerYggdrasilRoutesWithDI(v1, h.Yggdrasil) // 系统路由 registerSystemRoutes(v1, c) // CustomSkinAPI 路由 registerCustomSkinRoutes(v1, h.CustomSkin) // 管理员路由(需要管理员权限) registerAdminRoutes(v1, c, h.Admin) } } // 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, jwtService *auth.JWTService) { userGroup := v1.Group("/user") userGroup.Use(middleware.AuthMiddleware(jwtService)) { userGroup.GET("/profile", h.GetProfile) userGroup.PUT("/profile", h.UpdateProfile) // 头像相关 userGroup.POST("/avatar/upload", h.UploadAvatar) // 直接上传头像文件 userGroup.PUT("/avatar", h.UpdateAvatar) // 更新头像URL(外部URL) // 更换邮箱 userGroup.POST("/change-email", h.ChangeEmail) // Yggdrasil密码相关 userGroup.POST("/yggdrasil-password/reset", h.ResetYggdrasilPassword) } } // registerTextureRoutes 注册材质路由 func registerTextureRoutes(v1 *gin.RouterGroup, h *TextureHandler, jwtService *auth.JWTService) { textureGroup := v1.Group("/texture") { // 公开路由(无需认证) textureGroup.GET("", h.Search) textureGroup.GET("/:id", h.Get) // 需要认证的路由 textureAuth := textureGroup.Group("") textureAuth.Use(middleware.AuthMiddleware(jwtService)) { textureAuth.POST("/upload", h.Upload) // 直接上传文件 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) } } } // registerProfileRoutesWithDI 注册档案路由(依赖注入版本) func registerProfileRoutesWithDI(v1 *gin.RouterGroup, h *ProfileHandler, jwtService *auth.JWTService) { profileGroup := v1.Group("/profile") { // 公开路由(无需认证) profileGroup.GET("/:uuid", h.Get) // 需要认证的路由 profileAuth := profileGroup.Group("") profileAuth.Use(middleware.AuthMiddleware(jwtService)) { // 同时支持 /api/v1/profile 和 /api/v1/profile/ 两种形式返回列表与创建 profileAuth.GET("", h.List) profileAuth.POST("", h.Create) profileAuth.POST("/", h.Create) profileAuth.GET("/", h.List) profileAuth.PUT("/:uuid", h.Update) profileAuth.DELETE("/:uuid", h.Delete) } } } // registerCaptchaRoutesWithDI 注册验证码路由(依赖注入版本) func registerCaptchaRoutesWithDI(v1 *gin.RouterGroup, h *CaptchaHandler) { captchaGroup := v1.Group("/captcha") { captchaGroup.GET("/generate", h.Generate) captchaGroup.POST("/verify", h.Verify) } } // registerYggdrasilRoutesWithDI 注册Yggdrasil API路由(依赖注入版本) func registerYggdrasilRoutesWithDI(v1 *gin.RouterGroup, h *YggdrasilHandler) { ygg := v1.Group("/yggdrasil") { ygg.GET("", h.GetMetaData) ygg.POST("/minecraftservices/player/certificates", h.GetPlayerCertificates) authserver := ygg.Group("/authserver") { authserver.POST("/authenticate", h.Authenticate) authserver.POST("/validate", h.ValidToken) authserver.POST("/refresh", h.RefreshToken) authserver.POST("/invalidate", h.InvalidToken) authserver.POST("/signout", h.SignOut) } sessionServer := ygg.Group("/sessionserver") { sessionServer.GET("/session/minecraft/profile/:uuid", h.GetProfileByUUID) sessionServer.POST("/session/minecraft/join", h.JoinServer) sessionServer.GET("/session/minecraft/hasJoined", h.HasJoinedServer) } api := ygg.Group("/api") profiles := api.Group("/profiles") { profiles.POST("/minecraft", h.GetProfilesByName) } } } // registerSystemRoutes 注册系统路由 func registerSystemRoutes(v1 *gin.RouterGroup, c *container.Container) { system := v1.Group("/system") { // 公开配置(无需认证) system.GET("/config", func(ctx *gin.Context) { cfg, _ := config.GetConfig() ctx.JSON(200, model.NewSuccessResponse(gin.H{ "site_name": cfg.Site.Name, "site_description": cfg.Site.Description, "registration_enabled": cfg.Site.RegistrationEnabled, "max_textures_per_user": cfg.Site.MaxTexturesPerUser, "max_profiles_per_user": cfg.Site.MaxProfilesPerUser, })) }) } } // registerAdminRoutes 注册管理员路由 func registerAdminRoutes(v1 *gin.RouterGroup, c *container.Container, h *AdminHandler) { admin := v1.Group("/admin") admin.Use(middleware.AuthMiddleware(c.JWT)) admin.Use(middleware.RequireAdmin()) { // 用户管理 admin.GET("/users", h.GetUserList) admin.GET("/users/:id", h.GetUserDetail) admin.PUT("/users/role", h.SetUserRole) admin.PUT("/users/status", h.SetUserStatus) // 材质管理(审核) admin.GET("/textures", h.GetTextureList) admin.DELETE("/textures/:id", h.DeleteTexture) // 权限管理 admin.GET("/permissions", func(ctx *gin.Context) { // 获取所有权限规则 policies, _ := c.Casbin.GetEnforcer().GetPolicy() ctx.JSON(200, model.NewSuccessResponse(gin.H{ "policies": policies, })) }) } } // registerCustomSkinRoutes 注册CustomSkinAPI路由 // CustomSkinAPI 协议要求根地址必须以 / 结尾 // 路由格式: // - {ROOT}/{USERNAME}.json - 获取玩家信息 // - {ROOT}/textures/{hash} - 获取资源文件 // // 根路径为 /api/v1/csl/ func registerCustomSkinRoutes(v1 *gin.RouterGroup, h *CustomSkinHandler) { // CustomSkinAPI 路由组 csl := v1.Group("/csl") { // 获取玩家信息: {ROOT}/{USERNAME}.json csl.GET("/:username", h.GetPlayerInfo) // 获取资源文件: {ROOT}/textures/{hash} csl.GET("/textures/:hash", h.GetTexture) } }