- Refactored AuthHandler, UserHandler, TextureHandler, ProfileHandler, CaptchaHandler, and YggdrasilHandler to use dependency injection. - Removed direct instantiation of services and repositories within handlers, replacing them with constructor injection. - Updated the container to initialize service instances and provide them to handlers. - Enhanced code structure for better testability and adherence to Go best practices.
177 lines
5.4 KiB
Go
177 lines
5.4 KiB
Go
package handler
|
||
|
||
import (
|
||
"carrotskin/internal/container"
|
||
"carrotskin/internal/service"
|
||
"carrotskin/internal/types"
|
||
"carrotskin/pkg/email"
|
||
|
||
"github.com/gin-gonic/gin"
|
||
"go.uber.org/zap"
|
||
)
|
||
|
||
// AuthHandler 认证处理器(依赖注入版本)
|
||
type AuthHandler struct {
|
||
container *container.Container
|
||
logger *zap.Logger
|
||
}
|
||
|
||
// NewAuthHandler 创建AuthHandler实例
|
||
func NewAuthHandler(c *container.Container) *AuthHandler {
|
||
return &AuthHandler{
|
||
container: c,
|
||
logger: c.Logger,
|
||
}
|
||
}
|
||
|
||
// Register 用户注册
|
||
// @Summary 用户注册
|
||
// @Description 注册新用户账号
|
||
// @Tags auth
|
||
// @Accept json
|
||
// @Produce json
|
||
// @Param request body types.RegisterRequest true "注册信息"
|
||
// @Success 200 {object} model.Response "注册成功"
|
||
// @Failure 400 {object} model.ErrorResponse "请求参数错误"
|
||
// @Router /api/v1/auth/register [post]
|
||
func (h *AuthHandler) Register(c *gin.Context) {
|
||
var req types.RegisterRequest
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
RespondBadRequest(c, "请求参数错误", err)
|
||
return
|
||
}
|
||
|
||
// 验证邮箱验证码
|
||
if err := service.VerifyCode(c.Request.Context(), h.container.Redis, req.Email, req.VerificationCode, service.VerificationTypeRegister); err != nil {
|
||
h.logger.Warn("验证码验证失败", zap.String("email", req.Email), zap.Error(err))
|
||
RespondBadRequest(c, err.Error(), nil)
|
||
return
|
||
}
|
||
|
||
// 注册用户
|
||
user, token, err := h.container.UserService.Register(req.Username, req.Password, req.Email, req.Avatar)
|
||
if err != nil {
|
||
h.logger.Error("用户注册失败", zap.Error(err))
|
||
RespondBadRequest(c, err.Error(), nil)
|
||
return
|
||
}
|
||
|
||
RespondSuccess(c, &types.LoginResponse{
|
||
Token: token,
|
||
UserInfo: UserToUserInfo(user),
|
||
})
|
||
}
|
||
|
||
// Login 用户登录
|
||
// @Summary 用户登录
|
||
// @Description 用户登录获取JWT Token,支持用户名或邮箱登录
|
||
// @Tags auth
|
||
// @Accept json
|
||
// @Produce json
|
||
// @Param request body types.LoginRequest true "登录信息(username字段支持用户名或邮箱)"
|
||
// @Success 200 {object} model.Response{data=types.LoginResponse} "登录成功"
|
||
// @Failure 400 {object} model.ErrorResponse "请求参数错误"
|
||
// @Failure 401 {object} model.ErrorResponse "登录失败"
|
||
// @Router /api/v1/auth/login [post]
|
||
func (h *AuthHandler) Login(c *gin.Context) {
|
||
var req types.LoginRequest
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
RespondBadRequest(c, "请求参数错误", err)
|
||
return
|
||
}
|
||
|
||
ipAddress := c.ClientIP()
|
||
userAgent := c.GetHeader("User-Agent")
|
||
|
||
user, token, err := h.container.UserService.Login(req.Username, req.Password, ipAddress, userAgent)
|
||
if err != nil {
|
||
h.logger.Warn("用户登录失败",
|
||
zap.String("username_or_email", req.Username),
|
||
zap.String("ip", ipAddress),
|
||
zap.Error(err),
|
||
)
|
||
RespondUnauthorized(c, err.Error())
|
||
return
|
||
}
|
||
|
||
RespondSuccess(c, &types.LoginResponse{
|
||
Token: token,
|
||
UserInfo: UserToUserInfo(user),
|
||
})
|
||
}
|
||
|
||
// SendVerificationCode 发送验证码
|
||
// @Summary 发送验证码
|
||
// @Description 发送邮箱验证码(注册/重置密码/更换邮箱)
|
||
// @Tags auth
|
||
// @Accept json
|
||
// @Produce json
|
||
// @Param request body types.SendVerificationCodeRequest true "发送验证码请求"
|
||
// @Success 200 {object} model.Response "发送成功"
|
||
// @Failure 400 {object} model.ErrorResponse "请求参数错误"
|
||
// @Router /api/v1/auth/send-code [post]
|
||
func (h *AuthHandler) SendVerificationCode(c *gin.Context) {
|
||
var req types.SendVerificationCodeRequest
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
RespondBadRequest(c, "请求参数错误", err)
|
||
return
|
||
}
|
||
|
||
emailService, err := h.getEmailService()
|
||
if err != nil {
|
||
RespondServerError(c, "邮件服务不可用", err)
|
||
return
|
||
}
|
||
|
||
if err := service.SendVerificationCode(c.Request.Context(), h.container.Redis, emailService, req.Email, req.Type); err != nil {
|
||
h.logger.Error("发送验证码失败",
|
||
zap.String("email", req.Email),
|
||
zap.String("type", req.Type),
|
||
zap.Error(err),
|
||
)
|
||
RespondBadRequest(c, err.Error(), nil)
|
||
return
|
||
}
|
||
|
||
RespondSuccess(c, gin.H{"message": "验证码已发送,请查收邮件"})
|
||
}
|
||
|
||
// ResetPassword 重置密码
|
||
// @Summary 重置密码
|
||
// @Description 通过邮箱验证码重置密码
|
||
// @Tags auth
|
||
// @Accept json
|
||
// @Produce json
|
||
// @Param request body types.ResetPasswordRequest true "重置密码请求"
|
||
// @Success 200 {object} model.Response "重置成功"
|
||
// @Failure 400 {object} model.ErrorResponse "请求参数错误"
|
||
// @Router /api/v1/auth/reset-password [post]
|
||
func (h *AuthHandler) ResetPassword(c *gin.Context) {
|
||
var req types.ResetPasswordRequest
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
RespondBadRequest(c, "请求参数错误", err)
|
||
return
|
||
}
|
||
|
||
// 验证验证码
|
||
if err := service.VerifyCode(c.Request.Context(), h.container.Redis, req.Email, req.VerificationCode, service.VerificationTypeResetPassword); err != nil {
|
||
h.logger.Warn("验证码验证失败", zap.String("email", req.Email), zap.Error(err))
|
||
RespondBadRequest(c, err.Error(), nil)
|
||
return
|
||
}
|
||
|
||
// 重置密码
|
||
if err := h.container.UserService.ResetPassword(req.Email, req.NewPassword); err != nil {
|
||
h.logger.Error("重置密码失败", zap.String("email", req.Email), zap.Error(err))
|
||
RespondServerError(c, err.Error(), nil)
|
||
return
|
||
}
|
||
|
||
RespondSuccess(c, gin.H{"message": "密码重置成功"})
|
||
}
|
||
|
||
// getEmailService 获取邮件服务(暂时使用全局方式,后续可改为依赖注入)
|
||
func (h *AuthHandler) getEmailService() (*email.Service, error) {
|
||
return email.GetService()
|
||
}
|