[feature/backend] update put /users/me endpoint, allow setting username and display name
This commit is contained in:
parent
1526c27b49
commit
79912925db
4 changed files with 46 additions and 3 deletions
|
@ -216,14 +216,23 @@ user_me:
|
||||||
schema:
|
schema:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
username:
|
||||||
|
type: string
|
||||||
|
minLength: 3
|
||||||
|
maxLength: 32
|
||||||
|
display_name:
|
||||||
|
type: string
|
||||||
|
maxLength: 64
|
||||||
email:
|
email:
|
||||||
type: string
|
type: string
|
||||||
format: email
|
format: email
|
||||||
current_password:
|
current_password:
|
||||||
type: string
|
type: string
|
||||||
|
description: 当修改密码时必填
|
||||||
new_password:
|
new_password:
|
||||||
type: string
|
type: string
|
||||||
minLength: 8
|
minLength: 8
|
||||||
|
description: 新密码,如果要修改密码则必填
|
||||||
responses:
|
responses:
|
||||||
'200':
|
'200':
|
||||||
description: 用户信息更新成功
|
description: 用户信息更新成功
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type UpdateCurrentUserRequest struct {
|
type UpdateCurrentUserRequest struct {
|
||||||
|
Username string `json:"username,omitempty" binding:"omitempty,min=3,max=32"`
|
||||||
Email string `json:"email,omitempty" binding:"omitempty,email"`
|
Email string `json:"email,omitempty" binding:"omitempty,email"`
|
||||||
CurrentPassword string `json:"current_password,omitempty"`
|
CurrentPassword string `json:"current_password,omitempty"`
|
||||||
NewPassword string `json:"new_password,omitempty" binding:"omitempty,min=8"`
|
NewPassword string `json:"new_password,omitempty" binding:"omitempty,min=8"`
|
||||||
|
@ -211,12 +212,20 @@ func (h *Handler) GetCurrentUser(c *gin.Context) {
|
||||||
// UpdateCurrentUser updates the current user's information
|
// UpdateCurrentUser updates the current user's information
|
||||||
func (h *Handler) UpdateCurrentUser(c *gin.Context) {
|
func (h *Handler) UpdateCurrentUser(c *gin.Context) {
|
||||||
// 从上下文中获取用户ID(由认证中间件设置)
|
// 从上下文中获取用户ID(由认证中间件设置)
|
||||||
userID, exists := c.Get("user_id")
|
userIDStr, exists := c.Get("user_id")
|
||||||
if !exists {
|
if !exists {
|
||||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"})
|
c.JSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 将用户ID转换为整数
|
||||||
|
userID, err := strconv.Atoi(userIDStr.(string))
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Err(err).Msg("Failed to convert user ID to integer")
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Invalid user ID format"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
var req UpdateCurrentUserRequest
|
var req UpdateCurrentUserRequest
|
||||||
if err := c.ShouldBindJSON(&req); err != nil {
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||||
|
@ -231,20 +240,25 @@ func (h *Handler) UpdateCurrentUser(c *gin.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 验证当前密码
|
// 验证当前密码
|
||||||
if err := h.service.VerifyPassword(c.Request.Context(), userID.(int), req.CurrentPassword); err != nil {
|
if err := h.service.VerifyPassword(c.Request.Context(), userID, req.CurrentPassword); err != nil {
|
||||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid current password"})
|
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid current password"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新用户信息
|
// 更新用户信息
|
||||||
user, err := h.service.UpdateUser(c.Request.Context(), userID.(int), &types.UpdateUserInput{
|
user, err := h.service.UpdateUser(c.Request.Context(), userID, &types.UpdateUserInput{
|
||||||
|
Username: req.Username,
|
||||||
Email: req.Email,
|
Email: req.Email,
|
||||||
Password: req.NewPassword,
|
Password: req.NewPassword,
|
||||||
DisplayName: req.DisplayName,
|
DisplayName: req.DisplayName,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err).Msg("Failed to update user")
|
log.Error().Err(err).Msg("Failed to update user")
|
||||||
|
if err.Error() == "username already taken" {
|
||||||
|
c.JSON(http.StatusConflict, gin.H{"error": "Username already taken"})
|
||||||
|
return
|
||||||
|
}
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update user information"})
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update user information"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,25 @@ func (s *serviceImpl) UpdateUser(ctx context.Context, userID int, input *types.U
|
||||||
// Start building the update
|
// Start building the update
|
||||||
update := s.client.User.UpdateOneID(userID)
|
update := s.client.User.UpdateOneID(userID)
|
||||||
|
|
||||||
|
// Update username if provided
|
||||||
|
if input.Username != "" {
|
||||||
|
// Check if username is already taken
|
||||||
|
exists, err := s.client.User.Query().
|
||||||
|
Where(user.And(
|
||||||
|
user.UsernameEQ(input.Username),
|
||||||
|
user.IDNEQ(userID),
|
||||||
|
)).
|
||||||
|
Exist(ctx)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Err(err).Msg("Failed to check username availability")
|
||||||
|
return nil, fmt.Errorf("failed to check username availability: %w", err)
|
||||||
|
}
|
||||||
|
if exists {
|
||||||
|
return nil, fmt.Errorf("username already taken")
|
||||||
|
}
|
||||||
|
update.SetUsername(input.Username)
|
||||||
|
}
|
||||||
|
|
||||||
// Update email if provided
|
// Update email if provided
|
||||||
if input.Email != "" {
|
if input.Email != "" {
|
||||||
update.SetEmail(input.Email)
|
update.SetEmail(input.Email)
|
||||||
|
|
|
@ -2,6 +2,7 @@ package types
|
||||||
|
|
||||||
// UpdateUserInput defines the input for updating a user
|
// UpdateUserInput defines the input for updating a user
|
||||||
type UpdateUserInput struct {
|
type UpdateUserInput struct {
|
||||||
|
Username string
|
||||||
Email string
|
Email string
|
||||||
Password string
|
Password string
|
||||||
Role string
|
Role string
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue