解决合并后出现的问题,为swagger提供禁用选项,暂时移除wiki

This commit is contained in:
2025-12-26 01:15:17 +08:00
parent 44f007936e
commit 85a9463913
90 changed files with 602 additions and 20104 deletions

View File

@@ -34,11 +34,11 @@ type SetUserRoleRequest struct {
// @Accept json
// @Produce json
// @Param request body SetUserRoleRequest true "设置角色请求"
// @Success 200 {object} model.Response
// @Failure 400 {object} model.Response
// @Failure 403 {object} model.Response
// @Success 200 {object} model.Response{data=map[string]interface{}} "更新成功"
// @Failure 400 {object} model.ErrorResponse "参数错误"
// @Failure 403 {object} model.ErrorResponse "无权操作"
// @Security BearerAuth
// @Router /admin/users/role [put]
// @Router /api/v1/admin/users/role [put]
func (h *AdminHandler) SetUserRole(c *gin.Context) {
var req SetUserRoleRequest
if err := c.ShouldBindJSON(&req); err != nil {
@@ -99,10 +99,10 @@ func (h *AdminHandler) SetUserRole(c *gin.Context) {
// @Produce json
// @Param page query int false "页码" default(1)
// @Param page_size query int false "每页数量" default(20)
// @Success 200 {object} model.Response
// @Failure 403 {object} model.Response
// @Success 200 {object} model.Response{data=map[string]interface{}} "获取成功"
// @Failure 403 {object} model.ErrorResponse "无权操作"
// @Security BearerAuth
// @Router /admin/users [get]
// @Router /api/v1/admin/users [get]
func (h *AdminHandler) GetUserList(c *gin.Context) {
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))
@@ -152,10 +152,10 @@ func (h *AdminHandler) GetUserList(c *gin.Context) {
// @Tags Admin
// @Produce json
// @Param id path int true "用户ID"
// @Success 200 {object} model.Response
// @Failure 404 {object} model.Response
// @Success 200 {object} model.Response{data=map[string]interface{}} "获取成功"
// @Failure 404 {object} model.ErrorResponse "用户不存在"
// @Security BearerAuth
// @Router /admin/users/{id} [get]
// @Router /api/v1/admin/users/{id} [get]
func (h *AdminHandler) GetUserDetail(c *gin.Context) {
userID, err := strconv.ParseInt(c.Param("id"), 10, 64)
if err != nil {
@@ -201,10 +201,10 @@ type SetUserStatusRequest struct {
// @Accept json
// @Produce json
// @Param request body SetUserStatusRequest true "设置状态请求"
// @Success 200 {object} model.Response
// @Failure 400 {object} model.Response
// @Success 200 {object} model.Response{data=map[string]interface{}} "更新成功"
// @Failure 400 {object} model.ErrorResponse "参数错误"
// @Security BearerAuth
// @Router /admin/users/status [put]
// @Router /api/v1/admin/users/status [put]
func (h *AdminHandler) SetUserStatus(c *gin.Context) {
var req SetUserStatusRequest
if err := c.ShouldBindJSON(&req); err != nil {
@@ -266,10 +266,10 @@ func (h *AdminHandler) SetUserStatus(c *gin.Context) {
// @Tags Admin
// @Produce json
// @Param id path int true "材质ID"
// @Success 200 {object} model.Response
// @Failure 404 {object} model.Response
// @Success 200 {object} model.Response{data=map[string]interface{}} "删除成功"
// @Failure 404 {object} model.ErrorResponse "材质不存在"
// @Security BearerAuth
// @Router /admin/textures/{id} [delete]
// @Router /api/v1/admin/textures/{id} [delete]
func (h *AdminHandler) DeleteTexture(c *gin.Context) {
textureID, err := strconv.ParseInt(c.Param("id"), 10, 64)
if err != nil {
@@ -316,9 +316,9 @@ func (h *AdminHandler) DeleteTexture(c *gin.Context) {
// @Produce json
// @Param page query int false "页码" default(1)
// @Param page_size query int false "每页数量" default(20)
// @Success 200 {object} model.Response
// @Success 200 {object} model.Response{data=map[string]interface{}} "获取成功"
// @Security BearerAuth
// @Router /admin/textures [get]
// @Router /api/v1/admin/textures [get]
func (h *AdminHandler) GetTextureList(c *gin.Context) {
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))
@@ -364,3 +364,19 @@ func (h *AdminHandler) GetTextureList(c *gin.Context) {
"page_size": pageSize,
}))
}
// GetPermissions 获取权限列表
// @Summary 获取权限列表
// @Description 管理员获取所有Casbin权限规则
// @Tags Admin
// @Produce json
// @Success 200 {object} model.Response{data=map[string]interface{}} "获取成功"
// @Security BearerAuth
// @Router /api/v1/admin/permissions [get]
func (h *AdminHandler) GetPermissions(c *gin.Context) {
// 获取所有权限规则
policies, _ := h.container.Casbin.GetEnforcer().GetPolicy()
c.JSON(http.StatusOK, model.NewSuccessResponse(gin.H{
"policies": policies,
}))
}

View File

@@ -31,7 +31,7 @@ func NewAuthHandler(c *container.Container) *AuthHandler {
// @Accept json
// @Produce json
// @Param request body types.RegisterRequest true "注册信息"
// @Success 200 {object} model.Response "注册成功"
// @Success 200 {object} model.Response{data=types.LoginResponse} "注册成功"
// @Failure 400 {object} model.ErrorResponse "请求参数错误"
// @Router /api/v1/auth/register [post]
func (h *AuthHandler) Register(c *gin.Context) {
@@ -107,7 +107,7 @@ func (h *AuthHandler) Login(c *gin.Context) {
// @Accept json
// @Produce json
// @Param request body types.SendVerificationCodeRequest true "发送验证码请求"
// @Success 200 {object} model.Response "发送成功"
// @Success 200 {object} model.Response{data=map[string]string} "发送成功"
// @Failure 400 {object} model.ErrorResponse "请求参数错误"
// @Router /api/v1/auth/send-code [post]
func (h *AuthHandler) SendVerificationCode(c *gin.Context) {
@@ -137,7 +137,7 @@ func (h *AuthHandler) SendVerificationCode(c *gin.Context) {
// @Accept json
// @Produce json
// @Param request body types.ResetPasswordRequest true "重置密码请求"
// @Success 200 {object} model.Response "重置成功"
// @Success 200 {object} model.Response{data=map[string]string} "重置成功"
// @Failure 400 {object} model.ErrorResponse "请求参数错误"
// @Router /api/v1/auth/reset-password [post]
func (h *AuthHandler) ResetPassword(c *gin.Context) {

View File

@@ -34,7 +34,7 @@ type CaptchaVerifyRequest struct {
// @Tags captcha
// @Accept json
// @Produce json
// @Success 200 {object} map[string]interface{} "生成成功"
// @Success 200 {object} map[string]interface{} "生成成功 {code: 200, data: {masterImage, tileImage, captchaId, y}}"
// @Failure 500 {object} map[string]interface{} "生成失败"
// @Router /api/v1/captcha/generate [get]
func (h *CaptchaHandler) Generate(c *gin.Context) {
@@ -66,7 +66,7 @@ func (h *CaptchaHandler) Generate(c *gin.Context) {
// @Accept json
// @Produce json
// @Param request body CaptchaVerifyRequest true "验证请求"
// @Success 200 {object} map[string]interface{} "验证结果"
// @Success 200 {object} map[string]interface{} "验证结果 {code: 200/400, msg: string}"
// @Failure 400 {object} map[string]interface{} "参数错误"
// @Router /api/v1/captcha/verify [post]
func (h *CaptchaHandler) Verify(c *gin.Context) {

View File

@@ -35,7 +35,16 @@ type CustomSkinAPIResponse struct {
}
// GetPlayerInfo 获取玩家信息
// GET {ROOT}/{USERNAME}.json
// @Summary 获取玩家信息
// @Description CustomSkinAPI: 获取玩家皮肤配置信息
// @Tags CustomSkinAPI
// @Accept json
// @Produce json
// @Param username path string true "玩家用户名"
// @Success 200 {object} CustomSkinAPIResponse
// @Failure 400 {object} map[string]string "用户名不能为空"
// @Failure 404 {object} map[string]string "玩家未找到"
// @Router /api/v1/csl/{username} [get]
func (h *CustomSkinHandler) GetPlayerInfo(c *gin.Context) {
username := c.Param("username")
if username == "" {
@@ -136,7 +145,14 @@ func (h *CustomSkinHandler) GetPlayerInfo(c *gin.Context) {
}
// GetTexture 获取资源文件
// GET {ROOT}/textures/{hash}
// @Summary 获取资源文件
// @Description CustomSkinAPI: 获取材质图片文件
// @Tags CustomSkinAPI
// @Param hash path string true "材质Hash"
// @Success 200 {file} binary
// @Failure 400 {object} map[string]string "资源标识符不能为空"
// @Failure 404 {object} map[string]string "资源未找到或不可用"
// @Router /api/v1/csl/textures/{hash} [get]
func (h *CustomSkinHandler) GetTexture(c *gin.Context) {
hash := c.Param("hash")
if hash == "" {

View File

@@ -72,7 +72,8 @@ func (h *ProfileHandler) Create(c *gin.Context) {
// @Accept json
// @Produce json
// @Security BearerAuth
// @Success 200 {object} model.Response "获取成功"
// @Success 200 {object} model.Response{data=[]types.ProfileInfo} "获取成功"
// @Failure 500 {object} model.ErrorResponse "服务器错误"
// @Router /api/v1/profile [get]
func (h *ProfileHandler) List(c *gin.Context) {
userID, ok := GetUserIDFromContext(c)
@@ -100,7 +101,7 @@ func (h *ProfileHandler) List(c *gin.Context) {
// @Accept json
// @Produce json
// @Param uuid path string true "档案UUID"
// @Success 200 {object} model.Response "获取成功"
// @Success 200 {object} model.Response{data=types.ProfileInfo} "获取成功"
// @Failure 404 {object} model.ErrorResponse "档案不存在"
// @Router /api/v1/profile/{uuid} [get]
func (h *ProfileHandler) Get(c *gin.Context) {
@@ -132,7 +133,7 @@ func (h *ProfileHandler) Get(c *gin.Context) {
// @Security BearerAuth
// @Param uuid path string true "档案UUID"
// @Param request body types.UpdateProfileRequest true "更新信息"
// @Success 200 {object} model.Response "更新成功"
// @Success 200 {object} model.Response{data=types.ProfileInfo} "更新成功"
// @Failure 403 {object} model.ErrorResponse "无权操作"
// @Router /api/v1/profile/{uuid} [put]
func (h *ProfileHandler) Update(c *gin.Context) {
@@ -180,7 +181,7 @@ func (h *ProfileHandler) Update(c *gin.Context) {
// @Produce json
// @Security BearerAuth
// @Param uuid path string true "档案UUID"
// @Success 200 {object} model.Response "删除成功"
// @Success 200 {object} model.Response{data=map[string]string} "删除成功"
// @Failure 403 {object} model.ErrorResponse "无权操作"
// @Router /api/v1/profile/{uuid} [delete]
func (h *ProfileHandler) Delete(c *gin.Context) {

View File

@@ -3,7 +3,6 @@ package handler
import (
"carrotskin/internal/container"
"carrotskin/internal/middleware"
"carrotskin/internal/model"
"carrotskin/pkg/auth"
"carrotskin/pkg/config"
@@ -44,7 +43,10 @@ func RegisterRoutesWithDI(router *gin.Engine, c *container.Container) {
router.GET("/health", HealthCheck)
// Swagger文档路由
router.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
cfg, _ := config.GetConfig()
if cfg != nil && cfg.Server.SwaggerEnabled {
router.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
}
// 创建Handler实例
h := NewHandlers(c)
@@ -70,9 +72,6 @@ func RegisterRoutesWithDI(router *gin.Engine, c *container.Container) {
// Yggdrasil API路由组
registerYggdrasilRoutesWithDI(v1, h.Yggdrasil)
// 系统路由
registerSystemRoutes(v1, c)
// CustomSkinAPI 路由
registerCustomSkinRoutes(v1, h.CustomSkin)
@@ -193,24 +192,6 @@ func registerYggdrasilRoutesWithDI(v1 *gin.RouterGroup, h *YggdrasilHandler) {
}
}
// 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")
@@ -229,13 +210,7 @@ func registerAdminRoutes(v1 *gin.RouterGroup, c *container.Container, h *AdminHa
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,
}))
})
admin.GET("/permissions", h.GetPermissions)
}
}

View File

@@ -25,6 +25,16 @@ func NewTextureHandler(c *container.Container) *TextureHandler {
}
// Get 获取材质详情
// @Summary 获取材质详情
// @Description 获取指定ID的材质详细信息
// @Tags texture
// @Accept json
// @Produce json
// @Param id path int true "材质ID"
// @Success 200 {object} model.Response{data=types.TextureInfo} "获取成功"
// @Failure 400 {object} model.ErrorResponse "参数错误"
// @Failure 404 {object} model.ErrorResponse "材质不存在"
// @Router /api/v1/texture/{id} [get]
func (h *TextureHandler) Get(c *gin.Context) {
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
if err != nil {
@@ -42,6 +52,19 @@ func (h *TextureHandler) Get(c *gin.Context) {
}
// Search 搜索材质
// @Summary 搜索材质
// @Description 搜索材质列表,支持关键词、类型、公开性筛选和分页
// @Tags texture
// @Accept json
// @Produce json
// @Param keyword query string false "关键词"
// @Param type query string false "材质类型 (SKIN/CAPE)"
// @Param public_only query boolean false "仅显示公开材质"
// @Param page query int false "页码" default(1)
// @Param page_size query int false "每页数量" default(20)
// @Success 200 {object} model.Response{data=map[string]interface{}} "获取成功"
// @Failure 500 {object} model.ErrorResponse "服务器错误"
// @Router /api/v1/texture [get]
func (h *TextureHandler) Search(c *gin.Context) {
keyword := c.Query("keyword")
textureTypeStr := c.Query("type")
@@ -85,6 +108,18 @@ func (h *TextureHandler) Search(c *gin.Context) {
}
// Update 更新材质
// @Summary 更新材质
// @Description 更新材质信息(名称、描述、公开性)
// @Tags texture
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param id path int true "材质ID"
// @Param request body types.UpdateTextureRequest true "更新信息"
// @Success 200 {object} model.Response{data=types.TextureInfo} "更新成功"
// @Failure 400 {object} model.ErrorResponse "参数错误"
// @Failure 403 {object} model.ErrorResponse "无权操作"
// @Router /api/v1/texture/{id} [put]
func (h *TextureHandler) Update(c *gin.Context) {
userID, ok := GetUserIDFromContext(c)
if !ok {
@@ -118,6 +153,17 @@ func (h *TextureHandler) Update(c *gin.Context) {
}
// Delete 删除材质
// @Summary 删除材质
// @Description 删除指定ID的材质
// @Tags texture
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param id path int true "材质ID"
// @Success 200 {object} model.Response "删除成功"
// @Failure 400 {object} model.ErrorResponse "参数错误"
// @Failure 403 {object} model.ErrorResponse "无权操作"
// @Router /api/v1/texture/{id} [delete]
func (h *TextureHandler) Delete(c *gin.Context) {
userID, ok := GetUserIDFromContext(c)
if !ok {
@@ -144,6 +190,16 @@ func (h *TextureHandler) Delete(c *gin.Context) {
}
// ToggleFavorite 切换收藏状态
// @Summary 切换收藏状态
// @Description 收藏或取消收藏指定材质
// @Tags texture
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param id path int true "材质ID"
// @Success 200 {object} model.Response{data=map[string]bool} "操作成功"
// @Failure 400 {object} model.ErrorResponse "参数错误"
// @Router /api/v1/texture/{id} [post]
func (h *TextureHandler) ToggleFavorite(c *gin.Context) {
userID, ok := GetUserIDFromContext(c)
if !ok {
@@ -171,6 +227,17 @@ func (h *TextureHandler) ToggleFavorite(c *gin.Context) {
}
// GetUserTextures 获取用户上传的材质列表
// @Summary 获取我的材质
// @Description 获取当前登录用户上传的材质列表
// @Tags texture
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param page query int false "页码" default(1)
// @Param page_size query int false "每页数量" default(20)
// @Success 200 {object} model.Response{data=map[string]interface{}} "获取成功"
// @Failure 500 {object} model.ErrorResponse "服务器错误"
// @Router /api/v1/texture/my [get]
func (h *TextureHandler) GetUserTextures(c *gin.Context) {
userID, ok := GetUserIDFromContext(c)
if !ok {
@@ -196,6 +263,17 @@ func (h *TextureHandler) GetUserTextures(c *gin.Context) {
}
// GetUserFavorites 获取用户收藏的材质列表
// @Summary 获取我的收藏
// @Description 获取当前登录用户收藏的材质列表
// @Tags texture
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param page query int false "页码" default(1)
// @Param page_size query int false "每页数量" default(20)
// @Success 200 {object} model.Response{data=map[string]interface{}} "获取成功"
// @Failure 500 {object} model.ErrorResponse "服务器错误"
// @Router /api/v1/texture/favorites [get]
func (h *TextureHandler) GetUserFavorites(c *gin.Context) {
userID, ok := GetUserIDFromContext(c)
if !ok {
@@ -221,6 +299,21 @@ func (h *TextureHandler) GetUserFavorites(c *gin.Context) {
}
// Upload 直接上传材质文件
// @Summary 上传材质
// @Description 上传图片文件创建新材质
// @Tags texture
// @Accept multipart/form-data
// @Produce json
// @Security BearerAuth
// @Param file formData file true "材质文件 (PNG)"
// @Param name formData string true "材质名称"
// @Param description formData string false "材质描述"
// @Param type formData string false "材质类型 (SKIN/CAPE)" default(SKIN)
// @Param is_public formData boolean false "是否公开" default(false)
// @Param is_slim formData boolean false "是否为纤细模型 (仅SKIN有效)" default(false)
// @Success 200 {object} model.Response{data=types.TextureInfo} "上传成功"
// @Failure 400 {object} model.ErrorResponse "参数错误"
// @Router /api/v1/texture/upload [post]
func (h *TextureHandler) Upload(c *gin.Context) {
userID, ok := GetUserIDFromContext(c)
if !ok {

View File

@@ -24,6 +24,15 @@ func NewUserHandler(c *container.Container) *UserHandler {
}
// GetProfile 获取用户信息
// @Summary 获取用户信息
// @Description 获取当前登录用户的详细信息
// @Tags user
// @Accept json
// @Produce json
// @Security BearerAuth
// @Success 200 {object} model.Response{data=types.UserInfo} "获取成功"
// @Failure 404 {object} model.ErrorResponse "用户不存在"
// @Router /api/v1/user/profile [get]
func (h *UserHandler) GetProfile(c *gin.Context) {
userID, ok := GetUserIDFromContext(c)
if !ok {
@@ -44,6 +53,17 @@ func (h *UserHandler) GetProfile(c *gin.Context) {
}
// UpdateProfile 更新用户信息
// @Summary 更新用户信息
// @Description 更新用户资料密码、头像URL如需上传头像请使用上传接口
// @Tags user
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param request body types.UpdateUserRequest true "更新信息"
// @Success 200 {object} model.Response{data=types.UserInfo} "更新成功"
// @Failure 400 {object} model.ErrorResponse "参数错误"
// @Failure 404 {object} model.ErrorResponse "用户不存在"
// @Router /api/v1/user/profile [put]
func (h *UserHandler) UpdateProfile(c *gin.Context) {
userID, ok := GetUserIDFromContext(c)
if !ok {
@@ -103,6 +123,17 @@ func (h *UserHandler) UpdateProfile(c *gin.Context) {
}
// UploadAvatar 直接上传头像文件
// @Summary 上传头像
// @Description 上传图片文件作为用户头像
// @Tags user
// @Accept multipart/form-data
// @Produce json
// @Security BearerAuth
// @Param file formData file true "头像文件"
// @Success 200 {object} model.Response{data=map[string]interface{}} "上传成功"
// @Failure 400 {object} model.ErrorResponse "参数错误"
// @Failure 404 {object} model.ErrorResponse "用户不存在"
// @Router /api/v1/user/avatar/upload [post]
func (h *UserHandler) UploadAvatar(c *gin.Context) {
userID, ok := GetUserIDFromContext(c)
if !ok {
@@ -162,6 +193,17 @@ func (h *UserHandler) UploadAvatar(c *gin.Context) {
}
// UpdateAvatar 更新头像URL保留用于外部URL
// @Summary 更新头像URL
// @Description 更新用户头像为外部URL
// @Tags user
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param avatar_url query string true "头像URL"
// @Success 200 {object} model.Response{data=types.UserInfo} "更新成功"
// @Failure 400 {object} model.ErrorResponse "参数错误"
// @Failure 404 {object} model.ErrorResponse "用户不存在"
// @Router /api/v1/user/avatar [put]
func (h *UserHandler) UpdateAvatar(c *gin.Context) {
userID, ok := GetUserIDFromContext(c)
if !ok {
@@ -199,6 +241,17 @@ func (h *UserHandler) UpdateAvatar(c *gin.Context) {
}
// ChangeEmail 更换邮箱
// @Summary 更换邮箱
// @Description 更换用户绑定的邮箱,需要验证码
// @Tags user
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param request body types.ChangeEmailRequest true "更换邮箱请求"
// @Success 200 {object} model.Response{data=types.UserInfo} "更换成功"
// @Failure 400 {object} model.ErrorResponse "参数错误"
// @Failure 404 {object} model.ErrorResponse "用户不存在"
// @Router /api/v1/user/change-email [post]
func (h *UserHandler) ChangeEmail(c *gin.Context) {
userID, ok := GetUserIDFromContext(c)
if !ok {
@@ -237,6 +290,15 @@ func (h *UserHandler) ChangeEmail(c *gin.Context) {
}
// ResetYggdrasilPassword 重置Yggdrasil密码
// @Summary 重置Yggdrasil密码
// @Description 重置用户的Yggdrasil API认证密码
// @Tags user
// @Accept json
// @Produce json
// @Security BearerAuth
// @Success 200 {object} model.Response{data=map[string]string} "重置成功"
// @Failure 500 {object} model.ErrorResponse "服务器错误"
// @Router /api/v1/user/yggdrasil-password/reset [post]
func (h *UserHandler) ResetYggdrasilPassword(c *gin.Context) {
userID, ok := GetUserIDFromContext(c)
if !ok {

View File

@@ -167,6 +167,15 @@ func NewYggdrasilHandler(c *container.Container) *YggdrasilHandler {
}
// Authenticate 用户认证
// @Summary Yggdrasil认证
// @Description Yggdrasil协议: 用户登录认证
// @Tags Yggdrasil
// @Accept json
// @Produce json
// @Param request body AuthenticateRequest true "认证请求"
// @Success 200 {object} AuthenticateResponse
// @Failure 403 {object} map[string]string "认证失败"
// @Router /api/v1/yggdrasil/authserver/authenticate [post]
func (h *YggdrasilHandler) Authenticate(c *gin.Context) {
rawData, err := io.ReadAll(c.Request.Body)
if err != nil {
@@ -248,6 +257,15 @@ func (h *YggdrasilHandler) Authenticate(c *gin.Context) {
}
// ValidToken 验证令牌
// @Summary Yggdrasil验证令牌
// @Description Yggdrasil协议: 验证AccessToken是否有效
// @Tags Yggdrasil
// @Accept json
// @Produce json
// @Param request body ValidTokenRequest true "验证请求"
// @Success 204 "令牌有效"
// @Failure 403 {object} map[string]bool "令牌无效"
// @Router /api/v1/yggdrasil/authserver/validate [post]
func (h *YggdrasilHandler) ValidToken(c *gin.Context) {
var request ValidTokenRequest
if err := c.ShouldBindJSON(&request); err != nil {
@@ -266,6 +284,15 @@ func (h *YggdrasilHandler) ValidToken(c *gin.Context) {
}
// RefreshToken 刷新令牌
// @Summary Yggdrasil刷新令牌
// @Description Yggdrasil协议: 刷新AccessToken
// @Tags Yggdrasil
// @Accept json
// @Produce json
// @Param request body RefreshRequest true "刷新请求"
// @Success 200 {object} RefreshResponse
// @Failure 400 {object} map[string]string "刷新失败"
// @Router /api/v1/yggdrasil/authserver/refresh [post]
func (h *YggdrasilHandler) RefreshToken(c *gin.Context) {
var request RefreshRequest
if err := c.ShouldBindJSON(&request); err != nil {
@@ -350,6 +377,14 @@ func (h *YggdrasilHandler) RefreshToken(c *gin.Context) {
}
// InvalidToken 使令牌失效
// @Summary Yggdrasil注销令牌
// @Description Yggdrasil协议: 使AccessToken失效
// @Tags Yggdrasil
// @Accept json
// @Produce json
// @Param request body ValidTokenRequest true "失效请求"
// @Success 204 "操作成功"
// @Router /api/v1/yggdrasil/authserver/invalidate [post]
func (h *YggdrasilHandler) InvalidToken(c *gin.Context) {
var request ValidTokenRequest
if err := c.ShouldBindJSON(&request); err != nil {
@@ -364,6 +399,15 @@ func (h *YggdrasilHandler) InvalidToken(c *gin.Context) {
}
// SignOut 用户登出
// @Summary Yggdrasil登出
// @Description Yggdrasil协议: 用户登出,使所有令牌失效
// @Tags Yggdrasil
// @Accept json
// @Produce json
// @Param request body SignOutRequest true "登出请求"
// @Success 204 "操作成功"
// @Failure 400 {object} map[string]string "参数错误"
// @Router /api/v1/yggdrasil/authserver/signout [post]
func (h *YggdrasilHandler) SignOut(c *gin.Context) {
var request SignOutRequest
if err := c.ShouldBindJSON(&request); err != nil {
@@ -397,6 +441,15 @@ func (h *YggdrasilHandler) SignOut(c *gin.Context) {
}
// GetProfileByUUID 根据UUID获取档案
// @Summary Yggdrasil获取档案
// @Description Yggdrasil协议: 根据UUID获取用户档案信息
// @Tags Yggdrasil
// @Accept json
// @Produce json
// @Param uuid path string true "用户UUID"
// @Success 200 {object} map[string]interface{} "档案信息"
// @Failure 500 {object} APIResponse "服务器错误"
// @Router /api/v1/yggdrasil/sessionserver/session/minecraft/profile/{uuid} [get]
func (h *YggdrasilHandler) GetProfileByUUID(c *gin.Context) {
uuid := utils.FormatUUID(c.Param("uuid"))
h.logger.Info("获取配置文件请求", zap.String("uuid", uuid))
@@ -413,6 +466,16 @@ func (h *YggdrasilHandler) GetProfileByUUID(c *gin.Context) {
}
// JoinServer 加入服务器
// @Summary Yggdrasil加入服务器
// @Description Yggdrasil协议: 客户端加入服务器
// @Tags Yggdrasil
// @Accept json
// @Produce json
// @Param request body JoinServerRequest true "加入请求"
// @Success 204 "加入成功"
// @Failure 400 {object} APIResponse "参数错误"
// @Failure 500 {object} APIResponse "服务器错误"
// @Router /api/v1/yggdrasil/sessionserver/session/minecraft/join [post]
func (h *YggdrasilHandler) JoinServer(c *gin.Context) {
var request JoinServerRequest
clientIP := c.ClientIP()
@@ -449,6 +512,17 @@ func (h *YggdrasilHandler) JoinServer(c *gin.Context) {
}
// HasJoinedServer 验证玩家是否已加入服务器
// @Summary Yggdrasil验证加入
// @Description Yggdrasil协议: 服务端验证客户端是否已加入
// @Tags Yggdrasil
// @Accept json
// @Produce json
// @Param username query string true "用户名"
// @Param serverId query string true "服务器ID"
// @Param ip query string false "客户端IP"
// @Success 200 {object} map[string]interface{} "验证成功,返回档案"
// @Failure 204 "验证失败"
// @Router /api/v1/yggdrasil/sessionserver/session/minecraft/hasJoined [get]
func (h *YggdrasilHandler) HasJoinedServer(c *gin.Context) {
clientIP, _ := c.GetQuery("ip")
@@ -499,6 +573,15 @@ func (h *YggdrasilHandler) HasJoinedServer(c *gin.Context) {
}
// GetProfilesByName 批量获取配置文件
// @Summary Yggdrasil批量获取档案
// @Description Yggdrasil协议: 根据名称批量获取用户档案
// @Tags Yggdrasil
// @Accept json
// @Produce json
// @Param request body []string true "用户名列表"
// @Success 200 {array} model.Profile "档案列表"
// @Failure 400 {object} APIResponse "参数错误"
// @Router /api/v1/yggdrasil/api/profiles/minecraft [post]
func (h *YggdrasilHandler) GetProfilesByName(c *gin.Context) {
var names []string
@@ -520,6 +603,14 @@ func (h *YggdrasilHandler) GetProfilesByName(c *gin.Context) {
}
// GetMetaData 获取Yggdrasil元数据
// @Summary Yggdrasil元数据
// @Description Yggdrasil协议: 获取服务器元数据
// @Tags Yggdrasil
// @Accept json
// @Produce json
// @Success 200 {object} map[string]interface{} "元数据"
// @Failure 500 {object} APIResponse "服务器错误"
// @Router /api/v1/yggdrasil [get]
func (h *YggdrasilHandler) GetMetaData(c *gin.Context) {
meta := gin.H{
"implementationName": "CellAuth",
@@ -550,6 +641,16 @@ func (h *YggdrasilHandler) GetMetaData(c *gin.Context) {
}
// GetPlayerCertificates 获取玩家证书
// @Summary Yggdrasil获取证书
// @Description Yggdrasil协议: 获取玩家证书
// @Tags Yggdrasil
// @Accept json
// @Produce json
// @Param Authorization header string true "Bearer {token}"
// @Success 200 {object} map[string]interface{} "证书信息"
// @Failure 401 {object} map[string]string "未授权"
// @Failure 500 {object} APIResponse "服务器错误"
// @Router /api/v1/yggdrasil/minecraftservices/player/certificates [post]
func (h *YggdrasilHandler) GetPlayerCertificates(c *gin.Context) {
authHeader := c.GetHeader("Authorization")
if authHeader == "" {