package auth import ( "errors" "net/http" "github.com/gin-gonic/gin" "gorm.io/gorm" "senlinai-agent/backend/internal/models" ) type Handler struct { service *Service } func NewHandler(service *Service) *Handler { return &Handler{service: service} } func (h *Handler) Register(router gin.IRouter) { router.POST("/auth/login", h.login) router.GET("/auth/me", h.me) router.PATCH("/auth/me", h.updateMe) } func (h *Handler) login(c *gin.Context) { var input struct { Email string `json:"email"` Password string `json:"password"` } if err := c.ShouldBindJSON(&input); err != nil { abortWithError(c, http.StatusBadRequest, "invalid_request", "请求参数无效") return } token, err := h.service.Login(input.Email, input.Password) if err != nil { abortWithError(c, http.StatusUnauthorized, "invalid_credentials", "邮箱或密码错误") return } userID, err := h.service.VerifySession(token) if err != nil { abortWithError(c, http.StatusInternalServerError, "internal_error", "登录状态创建失败") return } user, err := h.service.CurrentUser(userID) if err != nil { abortWithError(c, http.StatusInternalServerError, "internal_error", "用户资料加载失败") return } c.JSON(http.StatusOK, gin.H{"token": token, "user": currentUserDTO(*user)}) } type CurrentUserDTO struct { Email string `json:"email"` DisplayName string `json:"displayName"` } func (h *Handler) me(c *gin.Context) { userID, ok := CurrentUserID(c) if !ok { abortWithError(c, http.StatusUnauthorized, "unauthorized", "请先登录后再操作") return } user, err := h.service.CurrentUser(userID) if err != nil { writeProfileError(c, err) return } c.JSON(http.StatusOK, currentUserDTO(*user)) } func (h *Handler) updateMe(c *gin.Context) { userID, ok := CurrentUserID(c) if !ok { abortWithError(c, http.StatusUnauthorized, "unauthorized", "请先登录后再操作") return } var input struct { DisplayName string `json:"displayName"` CurrentPassword string `json:"currentPassword"` NewPassword string `json:"newPassword"` } if err := c.ShouldBindJSON(&input); err != nil { abortWithError(c, http.StatusBadRequest, "invalid_request", "个人资料参数无效") return } user, err := h.service.UpdateCurrentUser(userID, input.DisplayName, input.CurrentPassword, input.NewPassword) if err != nil { writeProfileError(c, err) return } c.JSON(http.StatusOK, currentUserDTO(*user)) } func currentUserDTO(user models.SaUser) CurrentUserDTO { return CurrentUserDTO{Email: user.Email, DisplayName: user.DisplayName} } func writeProfileError(c *gin.Context, err error) { switch { case errors.Is(err, gorm.ErrRecordNotFound): abortWithError(c, http.StatusNotFound, "not_found", "用户不存在") case errors.Is(err, ErrProfileNameRequired), errors.Is(err, ErrPasswordTooShort), errors.Is(err, ErrCurrentPassword): abortWithError(c, http.StatusBadRequest, "invalid_request", err.Error()) default: abortWithError(c, http.StatusInternalServerError, "internal_error", "个人资料更新失败") } }