- Updated main.go to initialize email service and include it in the dependency injection container. - Refactored handlers to utilize context in service method calls, improving consistency and error handling. - Introduced new service options for upload, security, and captcha services, enhancing modularity and testability. - Removed unused repository implementations to streamline the codebase. This commit continues the effort to improve the architecture by ensuring all services are properly injected and utilized across the application.
234 lines
6.0 KiB
Go
234 lines
6.0 KiB
Go
package handler
|
|
|
|
import (
|
|
"carrotskin/internal/container"
|
|
"carrotskin/internal/service"
|
|
"carrotskin/internal/types"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
// UserHandler 用户处理器(依赖注入版本)
|
|
type UserHandler struct {
|
|
container *container.Container
|
|
logger *zap.Logger
|
|
}
|
|
|
|
// NewUserHandler 创建UserHandler实例
|
|
func NewUserHandler(c *container.Container) *UserHandler {
|
|
return &UserHandler{
|
|
container: c,
|
|
logger: c.Logger,
|
|
}
|
|
}
|
|
|
|
// GetProfile 获取用户信息
|
|
func (h *UserHandler) GetProfile(c *gin.Context) {
|
|
userID, ok := GetUserIDFromContext(c)
|
|
if !ok {
|
|
return
|
|
}
|
|
|
|
user, err := h.container.UserService.GetByID(c.Request.Context(), userID)
|
|
if err != nil || user == nil {
|
|
h.logger.Error("获取用户信息失败",
|
|
zap.Int64("user_id", userID),
|
|
zap.Error(err),
|
|
)
|
|
RespondNotFound(c, "用户不存在")
|
|
return
|
|
}
|
|
|
|
RespondSuccess(c, UserToUserInfo(user))
|
|
}
|
|
|
|
// UpdateProfile 更新用户信息
|
|
func (h *UserHandler) UpdateProfile(c *gin.Context) {
|
|
userID, ok := GetUserIDFromContext(c)
|
|
if !ok {
|
|
return
|
|
}
|
|
|
|
var req types.UpdateUserRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
RespondBadRequest(c, "请求参数错误", err)
|
|
return
|
|
}
|
|
|
|
user, err := h.container.UserService.GetByID(c.Request.Context(), userID)
|
|
if err != nil || user == nil {
|
|
RespondNotFound(c, "用户不存在")
|
|
return
|
|
}
|
|
|
|
// 处理密码修改
|
|
if req.NewPassword != "" {
|
|
if req.OldPassword == "" {
|
|
RespondBadRequest(c, "修改密码需要提供原密码", nil)
|
|
return
|
|
}
|
|
|
|
if err := h.container.UserService.ChangePassword(c.Request.Context(), userID, req.OldPassword, req.NewPassword); err != nil {
|
|
h.logger.Error("修改密码失败", zap.Int64("user_id", userID), zap.Error(err))
|
|
RespondBadRequest(c, err.Error(), nil)
|
|
return
|
|
}
|
|
|
|
h.logger.Info("用户修改密码成功", zap.Int64("user_id", userID))
|
|
}
|
|
|
|
// 更新头像
|
|
if req.Avatar != "" {
|
|
if err := h.container.UserService.ValidateAvatarURL(c.Request.Context(), req.Avatar); err != nil {
|
|
RespondBadRequest(c, err.Error(), nil)
|
|
return
|
|
}
|
|
user.Avatar = req.Avatar
|
|
if err := h.container.UserService.UpdateInfo(c.Request.Context(), user); err != nil {
|
|
h.logger.Error("更新用户信息失败", zap.Int64("user_id", user.ID), zap.Error(err))
|
|
RespondServerError(c, "更新失败", err)
|
|
return
|
|
}
|
|
}
|
|
|
|
// 重新获取更新后的用户信息
|
|
updatedUser, err := h.container.UserService.GetByID(c.Request.Context(), userID)
|
|
if err != nil || updatedUser == nil {
|
|
RespondNotFound(c, "用户不存在")
|
|
return
|
|
}
|
|
|
|
RespondSuccess(c, UserToUserInfo(updatedUser))
|
|
}
|
|
|
|
// GenerateAvatarUploadURL 生成头像上传URL
|
|
func (h *UserHandler) GenerateAvatarUploadURL(c *gin.Context) {
|
|
userID, ok := GetUserIDFromContext(c)
|
|
if !ok {
|
|
return
|
|
}
|
|
|
|
var req types.GenerateAvatarUploadURLRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
RespondBadRequest(c, "请求参数错误", err)
|
|
return
|
|
}
|
|
|
|
if h.container.Storage == nil {
|
|
RespondServerError(c, "存储服务不可用", nil)
|
|
return
|
|
}
|
|
|
|
result, err := h.container.UploadService.GenerateAvatarUploadURL(c.Request.Context(), userID, req.FileName)
|
|
if err != nil {
|
|
h.logger.Error("生成头像上传URL失败",
|
|
zap.Int64("user_id", userID),
|
|
zap.String("file_name", req.FileName),
|
|
zap.Error(err),
|
|
)
|
|
RespondBadRequest(c, err.Error(), nil)
|
|
return
|
|
}
|
|
|
|
RespondSuccess(c, &types.GenerateAvatarUploadURLResponse{
|
|
PostURL: result.PostURL,
|
|
FormData: result.FormData,
|
|
AvatarURL: result.FileURL,
|
|
ExpiresIn: 900,
|
|
})
|
|
}
|
|
|
|
// UpdateAvatar 更新头像URL
|
|
func (h *UserHandler) UpdateAvatar(c *gin.Context) {
|
|
userID, ok := GetUserIDFromContext(c)
|
|
if !ok {
|
|
return
|
|
}
|
|
|
|
avatarURL := c.Query("avatar_url")
|
|
if avatarURL == "" {
|
|
RespondBadRequest(c, "头像URL不能为空", nil)
|
|
return
|
|
}
|
|
|
|
if err := h.container.UserService.ValidateAvatarURL(c.Request.Context(), avatarURL); err != nil {
|
|
RespondBadRequest(c, err.Error(), nil)
|
|
return
|
|
}
|
|
|
|
if err := h.container.UserService.UpdateAvatar(c.Request.Context(), userID, avatarURL); err != nil {
|
|
h.logger.Error("更新头像失败",
|
|
zap.Int64("user_id", userID),
|
|
zap.String("avatar_url", avatarURL),
|
|
zap.Error(err),
|
|
)
|
|
RespondServerError(c, "更新头像失败", err)
|
|
return
|
|
}
|
|
|
|
user, err := h.container.UserService.GetByID(c.Request.Context(), userID)
|
|
if err != nil || user == nil {
|
|
RespondNotFound(c, "用户不存在")
|
|
return
|
|
}
|
|
|
|
RespondSuccess(c, UserToUserInfo(user))
|
|
}
|
|
|
|
// ChangeEmail 更换邮箱
|
|
func (h *UserHandler) ChangeEmail(c *gin.Context) {
|
|
userID, ok := GetUserIDFromContext(c)
|
|
if !ok {
|
|
return
|
|
}
|
|
|
|
var req types.ChangeEmailRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
RespondBadRequest(c, "请求参数错误", err)
|
|
return
|
|
}
|
|
|
|
if err := h.container.VerificationService.VerifyCode(c.Request.Context(), req.NewEmail, req.VerificationCode, service.VerificationTypeChangeEmail); err != nil {
|
|
h.logger.Warn("验证码验证失败", zap.String("new_email", req.NewEmail), zap.Error(err))
|
|
RespondBadRequest(c, err.Error(), nil)
|
|
return
|
|
}
|
|
|
|
if err := h.container.UserService.ChangeEmail(c.Request.Context(), userID, req.NewEmail); err != nil {
|
|
h.logger.Error("更换邮箱失败",
|
|
zap.Int64("user_id", userID),
|
|
zap.String("new_email", req.NewEmail),
|
|
zap.Error(err),
|
|
)
|
|
RespondBadRequest(c, err.Error(), nil)
|
|
return
|
|
}
|
|
|
|
user, err := h.container.UserService.GetByID(c.Request.Context(), userID)
|
|
if err != nil || user == nil {
|
|
RespondNotFound(c, "用户不存在")
|
|
return
|
|
}
|
|
|
|
RespondSuccess(c, UserToUserInfo(user))
|
|
}
|
|
|
|
// ResetYggdrasilPassword 重置Yggdrasil密码
|
|
func (h *UserHandler) ResetYggdrasilPassword(c *gin.Context) {
|
|
userID, ok := GetUserIDFromContext(c)
|
|
if !ok {
|
|
return
|
|
}
|
|
|
|
newPassword, err := h.container.YggdrasilService.ResetYggdrasilPassword(c.Request.Context(), userID)
|
|
if err != nil {
|
|
h.logger.Error("重置Yggdrasil密码失败", zap.Error(err), zap.Int64("userId", userID))
|
|
RespondServerError(c, "重置Yggdrasil密码失败", nil)
|
|
return
|
|
}
|
|
|
|
h.logger.Info("Yggdrasil密码重置成功", zap.Int64("userId", userID))
|
|
RespondSuccess(c, gin.H{"password": newPassword})
|
|
}
|