package handler import ( "net/http" "strconv" "github.com/gin-gonic/gin" "github.com/rs/zerolog/log" "tss-rocks-be/internal/types" "fmt" ) type UpdateCurrentUserRequest struct { Email string `json:"email,omitempty" binding:"omitempty,email"` CurrentPassword string `json:"current_password,omitempty"` NewPassword string `json:"new_password,omitempty" binding:"omitempty,min=8"` DisplayName string `json:"display_name,omitempty" binding:"omitempty,max=64"` } type CreateUserRequest struct { Email string `json:"email" binding:"required,email"` Password string `json:"password" binding:"required,min=8"` Role string `json:"role" binding:"required,oneof=admin editor"` DisplayName string `json:"display_name,omitempty" binding:"omitempty,max=64"` } type UpdateUserRequest struct { Email string `json:"email,omitempty" binding:"omitempty,email"` Password string `json:"password,omitempty" binding:"omitempty,min=8"` Role string `json:"role,omitempty" binding:"omitempty,oneof=admin editor"` Status string `json:"status,omitempty" binding:"omitempty,oneof=active inactive"` DisplayName string `json:"display_name,omitempty" binding:"omitempty,max=64"` } // ListUsers returns a list of users func (h *Handler) ListUsers(c *gin.Context) { // Parse query parameters params := &types.ListUsersParams{ Page: 1, PerPage: 10, } if page := c.Query("page"); page != "" { if p, err := strconv.Atoi(page); err == nil && p > 0 { params.Page = p } } if perPage := c.Query("per_page"); perPage != "" { if pp, err := strconv.Atoi(perPage); err == nil && pp > 0 { params.PerPage = pp } } params.Sort = c.Query("sort") params.Role = c.Query("role") params.Status = c.Query("status") params.Email = c.Query("email") // Get users users, err := h.service.ListUsers(c.Request.Context(), params) if err != nil { log.Error().Err(err).Msg("Failed to list users") c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to list users"}) return } c.JSON(http.StatusOK, gin.H{ "data": users, }) } // CreateUser creates a new user func (h *Handler) CreateUser(c *gin.Context) { var req CreateUserRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } user, err := h.service.CreateUser(c.Request.Context(), req.Email, req.Email, req.Password, req.Role) if err != nil { log.Error().Err(err).Msg("Failed to create user") c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create user"}) return } c.JSON(http.StatusCreated, gin.H{ "data": user, }) } // GetUser returns user details func (h *Handler) GetUser(c *gin.Context) { id, err := strconv.Atoi(c.Param("id")) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid user ID"}) return } user, err := h.service.GetUser(c.Request.Context(), id) if err != nil { log.Error().Err(err).Msg("Failed to get user") c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get user"}) return } c.JSON(http.StatusOK, gin.H{ "data": user, }) } // UpdateUser updates user information func (h *Handler) UpdateUser(c *gin.Context) { id, err := strconv.Atoi(c.Param("id")) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid user ID"}) return } var req UpdateUserRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } user, err := h.service.UpdateUser(c.Request.Context(), id, &types.UpdateUserInput{ Email: req.Email, Password: req.Password, Role: req.Role, Status: req.Status, DisplayName: req.DisplayName, }) if err != nil { log.Error().Err(err).Msg("Failed to update user") c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update user"}) return } c.JSON(http.StatusOK, gin.H{ "data": user, }) } // DeleteUser deletes a user func (h *Handler) DeleteUser(c *gin.Context) { id, err := strconv.Atoi(c.Param("id")) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid user ID"}) return } if err := h.service.DeleteUser(c.Request.Context(), id); err != nil { log.Error().Err(err).Msg("Failed to delete user") c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to delete user"}) return } c.Status(http.StatusNoContent) } // GetCurrentUser returns the current user's information func (h *Handler) GetCurrentUser(c *gin.Context) { userID, exists := c.Get("user_id") if !exists { c.JSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"}) return } // 将用户ID转换为int64 var id int64 switch v := userID.(type) { case int64: id = v case int: id = int64(v) case float64: id = int64(v) case string: // 尝试将字符串转换为int64 parsedID, err := strconv.ParseInt(v, 10, 64) if err != nil { log.Error(). Err(err). Str("user_id", v). Msg("Failed to parse user_id string") c.JSON(http.StatusInternalServerError, gin.H{"error": "Invalid user_id format"}) return } id = parsedID default: log.Error(). Str("type", fmt.Sprintf("%T", userID)). Interface("value", userID). Msg("Invalid user_id type") c.JSON(http.StatusInternalServerError, gin.H{"error": "Invalid user_id type"}) return } // 获取用户信息 user, err := h.service.GetUser(c.Request.Context(), int(id)) if err != nil { log.Error().Err(err).Msg("Failed to get user") c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get user information"}) return } c.JSON(http.StatusOK, user) } // UpdateCurrentUser updates the current user's information func (h *Handler) UpdateCurrentUser(c *gin.Context) { // 从上下文中获取用户ID(由认证中间件设置) userID, exists := c.Get("user_id") if !exists { c.JSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"}) return } var req UpdateCurrentUserRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } // 如果要更新密码,需要验证当前密码 if req.NewPassword != "" { if req.CurrentPassword == "" { c.JSON(http.StatusBadRequest, gin.H{"error": "Current password is required to update password"}) return } // 验证当前密码 if err := h.service.VerifyPassword(c.Request.Context(), userID.(int), req.CurrentPassword); err != nil { c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid current password"}) return } } // 更新用户信息 user, err := h.service.UpdateUser(c.Request.Context(), userID.(int), &types.UpdateUserInput{ Email: req.Email, Password: req.NewPassword, DisplayName: req.DisplayName, }) if err != nil { log.Error().Err(err).Msg("Failed to update user") c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update user information"}) return } c.JSON(http.StatusOK, gin.H{ "data": user, }) }