Files
backend/internal/handler/profile_handler.go
lan 4b4980820f
Some checks failed
SonarQube Analysis / sonarqube (push) Has been cancelled
Test / test (push) Has been cancelled
Test / lint (push) Has been cancelled
Test / build (push) Has been cancelled
chore: 初始化仓库,排除二进制文件和覆盖率文件
2025-11-28 23:30:49 +08:00

399 lines
10 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/model"
"carrotskin/internal/service"
"carrotskin/internal/types"
"carrotskin/pkg/database"
"carrotskin/pkg/logger"
"net/http"
"github.com/gin-gonic/gin"
"go.uber.org/zap"
)
// CreateProfile 创建档案
// @Summary 创建Minecraft档案
// @Description 创建新的Minecraft角色档案UUID由后端自动生成
// @Tags profile
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param request body types.CreateProfileRequest true "档案信息(仅需提供角色名)"
// @Success 200 {object} model.Response{data=types.ProfileInfo} "创建成功返回完整档案信息含自动生成的UUID"
// @Failure 400 {object} model.ErrorResponse "请求参数错误或已达档案数量上限"
// @Failure 401 {object} model.ErrorResponse "未授权"
// @Failure 500 {object} model.ErrorResponse "服务器错误"
// @Router /api/v1/profile [post]
func CreateProfile(c *gin.Context) {
loggerInstance := logger.MustGetLogger()
// 获取用户ID
userID, exists := c.Get("user_id")
if !exists {
c.JSON(http.StatusUnauthorized, model.NewErrorResponse(
model.CodeUnauthorized,
"未授权",
nil,
))
return
}
// 解析请求
var req types.CreateProfileRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, model.NewErrorResponse(
model.CodeBadRequest,
"请求参数错误: "+err.Error(),
nil,
))
return
}
// TODO: 从配置或数据库读取限制
maxProfiles := 5
db := database.MustGetDB()
// 检查档案数量限制
if err := service.CheckProfileLimit(db, userID.(int64), maxProfiles); err != nil {
c.JSON(http.StatusBadRequest, model.NewErrorResponse(
model.CodeBadRequest,
err.Error(),
nil,
))
return
}
// 创建档案
profile, err := service.CreateProfile(db, userID.(int64), req.Name)
if err != nil {
loggerInstance.Error("创建档案失败",
zap.Int64("user_id", userID.(int64)),
zap.String("name", req.Name),
zap.Error(err),
)
c.JSON(http.StatusInternalServerError, model.NewErrorResponse(
model.CodeServerError,
err.Error(),
nil,
))
return
}
// 返回成功响应
c.JSON(http.StatusOK, model.NewSuccessResponse(&types.ProfileInfo{
UUID: profile.UUID,
UserID: profile.UserID,
Name: profile.Name,
SkinID: profile.SkinID,
CapeID: profile.CapeID,
IsActive: profile.IsActive,
LastUsedAt: profile.LastUsedAt,
CreatedAt: profile.CreatedAt,
UpdatedAt: profile.UpdatedAt,
}))
}
// GetProfiles 获取档案列表
// @Summary 获取档案列表
// @Description 获取当前用户的所有档案
// @Tags profile
// @Accept json
// @Produce json
// @Security BearerAuth
// @Success 200 {object} model.Response "获取成功"
// @Failure 401 {object} model.ErrorResponse "未授权"
// @Failure 500 {object} model.ErrorResponse "服务器错误"
// @Router /api/v1/profile [get]
func GetProfiles(c *gin.Context) {
loggerInstance := logger.MustGetLogger()
// 获取用户ID
userID, exists := c.Get("user_id")
if !exists {
c.JSON(http.StatusUnauthorized, model.NewErrorResponse(
model.CodeUnauthorized,
"未授权",
nil,
))
return
}
// 查询档案列表
profiles, err := service.GetUserProfiles(database.MustGetDB(), userID.(int64))
if err != nil {
loggerInstance.Error("获取档案列表失败",
zap.Int64("user_id", userID.(int64)),
zap.Error(err),
)
c.JSON(http.StatusInternalServerError, model.NewErrorResponse(
model.CodeServerError,
err.Error(),
nil,
))
return
}
// 转换为响应格式
result := make([]*types.ProfileInfo, 0, len(profiles))
for _, profile := range profiles {
result = append(result, &types.ProfileInfo{
UUID: profile.UUID,
UserID: profile.UserID,
Name: profile.Name,
SkinID: profile.SkinID,
CapeID: profile.CapeID,
IsActive: profile.IsActive,
LastUsedAt: profile.LastUsedAt,
CreatedAt: profile.CreatedAt,
UpdatedAt: profile.UpdatedAt,
})
}
c.JSON(http.StatusOK, model.NewSuccessResponse(result))
}
// GetProfile 获取档案详情
// @Summary 获取档案详情
// @Description 根据UUID获取档案详细信息
// @Tags profile
// @Accept json
// @Produce json
// @Param uuid path string true "档案UUID"
// @Success 200 {object} model.Response "获取成功"
// @Failure 404 {object} model.ErrorResponse "档案不存在"
// @Failure 500 {object} model.ErrorResponse "服务器错误"
// @Router /api/v1/profile/{uuid} [get]
func GetProfile(c *gin.Context) {
loggerInstance := logger.MustGetLogger()
uuid := c.Param("uuid")
// 查询档案
profile, err := service.GetProfileByUUID(database.MustGetDB(), uuid)
if err != nil {
loggerInstance.Error("获取档案失败",
zap.String("uuid", uuid),
zap.Error(err),
)
c.JSON(http.StatusNotFound, model.NewErrorResponse(
model.CodeNotFound,
err.Error(),
nil,
))
return
}
// 返回成功响应
c.JSON(http.StatusOK, model.NewSuccessResponse(&types.ProfileInfo{
UUID: profile.UUID,
UserID: profile.UserID,
Name: profile.Name,
SkinID: profile.SkinID,
CapeID: profile.CapeID,
IsActive: profile.IsActive,
LastUsedAt: profile.LastUsedAt,
CreatedAt: profile.CreatedAt,
UpdatedAt: profile.UpdatedAt,
}))
}
// UpdateProfile 更新档案
// @Summary 更新档案
// @Description 更新档案信息
// @Tags profile
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param uuid path string true "档案UUID"
// @Param request body types.UpdateProfileRequest true "更新信息"
// @Success 200 {object} model.Response "更新成功"
// @Failure 400 {object} model.ErrorResponse "请求参数错误"
// @Failure 401 {object} model.ErrorResponse "未授权"
// @Failure 403 {object} model.ErrorResponse "无权操作"
// @Failure 404 {object} model.ErrorResponse "档案不存在"
// @Failure 500 {object} model.ErrorResponse "服务器错误"
// @Router /api/v1/profile/{uuid} [put]
func UpdateProfile(c *gin.Context) {
loggerInstance := logger.MustGetLogger()
uuid := c.Param("uuid")
// 获取用户ID
userID, exists := c.Get("user_id")
if !exists {
c.JSON(http.StatusUnauthorized, model.NewErrorResponse(
model.CodeUnauthorized,
"未授权",
nil,
))
return
}
// 解析请求
var req types.UpdateProfileRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, model.NewErrorResponse(
model.CodeBadRequest,
"请求参数错误: "+err.Error(),
nil,
))
return
}
// 更新档案
var namePtr *string
if req.Name != "" {
namePtr = &req.Name
}
profile, err := service.UpdateProfile(database.MustGetDB(), uuid, userID.(int64), namePtr, req.SkinID, req.CapeID)
if err != nil {
loggerInstance.Error("更新档案失败",
zap.String("uuid", uuid),
zap.Int64("user_id", userID.(int64)),
zap.Error(err),
)
statusCode := http.StatusInternalServerError
if err.Error() == "档案不存在" {
statusCode = http.StatusNotFound
} else if err.Error() == "无权操作此档案" {
statusCode = http.StatusForbidden
}
c.JSON(statusCode, model.NewErrorResponse(
model.CodeServerError,
err.Error(),
nil,
))
return
}
// 返回成功响应
c.JSON(http.StatusOK, model.NewSuccessResponse(&types.ProfileInfo{
UUID: profile.UUID,
UserID: profile.UserID,
Name: profile.Name,
SkinID: profile.SkinID,
CapeID: profile.CapeID,
IsActive: profile.IsActive,
LastUsedAt: profile.LastUsedAt,
CreatedAt: profile.CreatedAt,
UpdatedAt: profile.UpdatedAt,
}))
}
// DeleteProfile 删除档案
// @Summary 删除档案
// @Description 删除指定的Minecraft档案
// @Tags profile
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param uuid path string true "档案UUID"
// @Success 200 {object} model.Response "删除成功"
// @Failure 401 {object} model.ErrorResponse "未授权"
// @Failure 403 {object} model.ErrorResponse "无权操作"
// @Failure 404 {object} model.ErrorResponse "档案不存在"
// @Failure 500 {object} model.ErrorResponse "服务器错误"
// @Router /api/v1/profile/{uuid} [delete]
func DeleteProfile(c *gin.Context) {
loggerInstance := logger.MustGetLogger()
uuid := c.Param("uuid")
// 获取用户ID
userID, exists := c.Get("user_id")
if !exists {
c.JSON(http.StatusUnauthorized, model.NewErrorResponse(
model.CodeUnauthorized,
"未授权",
nil,
))
return
}
// 删除档案
err := service.DeleteProfile(database.MustGetDB(), uuid, userID.(int64))
if err != nil {
loggerInstance.Error("删除档案失败",
zap.String("uuid", uuid),
zap.Int64("user_id", userID.(int64)),
zap.Error(err),
)
statusCode := http.StatusInternalServerError
if err.Error() == "档案不存在" {
statusCode = http.StatusNotFound
} else if err.Error() == "无权操作此档案" {
statusCode = http.StatusForbidden
}
c.JSON(statusCode, model.NewErrorResponse(
model.CodeServerError,
err.Error(),
nil,
))
return
}
// 返回成功响应
c.JSON(http.StatusOK, model.NewSuccessResponse(gin.H{
"message": "删除成功",
}))
}
// SetActiveProfile 设置活跃档案
// @Summary 设置活跃档案
// @Description 将指定档案设置为活跃状态
// @Tags profile
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param uuid path string true "档案UUID"
// @Success 200 {object} model.Response "设置成功"
// @Failure 401 {object} model.ErrorResponse "未授权"
// @Failure 403 {object} model.ErrorResponse "无权操作"
// @Failure 404 {object} model.ErrorResponse "档案不存在"
// @Failure 500 {object} model.ErrorResponse "服务器错误"
// @Router /api/v1/profile/{uuid}/activate [post]
func SetActiveProfile(c *gin.Context) {
loggerInstance := logger.MustGetLogger()
uuid := c.Param("uuid")
// 获取用户ID
userID, exists := c.Get("user_id")
if !exists {
c.JSON(http.StatusUnauthorized, model.NewErrorResponse(
model.CodeUnauthorized,
"未授权",
nil,
))
return
}
// 设置活跃状态
err := service.SetActiveProfile(database.MustGetDB(), uuid, userID.(int64))
if err != nil {
loggerInstance.Error("设置活跃档案失败",
zap.String("uuid", uuid),
zap.Int64("user_id", userID.(int64)),
zap.Error(err),
)
statusCode := http.StatusInternalServerError
if err.Error() == "档案不存在" {
statusCode = http.StatusNotFound
} else if err.Error() == "无权操作此档案" {
statusCode = http.StatusForbidden
}
c.JSON(statusCode, model.NewErrorResponse(
model.CodeServerError,
err.Error(),
nil,
))
return
}
// 返回成功响应
c.JSON(http.StatusOK, model.NewSuccessResponse(gin.H{
"message": "设置成功",
}))
}