109 lines
3.0 KiB
Go
109 lines
3.0 KiB
Go
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", "个人资料更新失败")
|
|
}
|
|
}
|