package handlers import ( "net/http" "strings" "stock-user-system/internal/config" "stock-user-system/internal/middleware" "stock-user-system/internal/models" "github.com/gin-gonic/gin" "gorm.io/gorm" ) type AdminHandler struct { DB *gorm.DB CFG *config.Config } func allowedRolesForCreation(actor models.RoleName) []models.RoleName { switch actor { case models.RoleSystemAdmin: return []models.RoleName{models.RoleAdmin, models.RoleUser} case models.RoleAdmin: return []models.RoleName{models.RoleUser} default: return nil } } func containsRole(roles []models.RoleName, target models.RoleName) bool { for _, r := range roles { if r == target { return true } } return false } func (h *AdminHandler) ListUsers(c *gin.Context) { var users []models.User if err := h.DB.Preload("Role").Order("created_at DESC").Find(&users).Error; err != nil { c.JSON(http.StatusInternalServerError, gin.H{"success": false, "error": "internal server error"}) return } result := make([]models.PublicUserInfo, 0, len(users)) for _, u := range users { result = append(result, u.ToPublicInfo()) } c.JSON(http.StatusOK, result) } func (h *AdminHandler) CreateUser(c *gin.Context) { current, _ := middleware.GetCurrentUser(c) var req struct { Username string `json:"username" binding:"required"` Email *string `json:"email"` Password string `json:"password" binding:"required"` Role string `json:"role"` } if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"success": false, "error": "请求参数错误"}) return } targetRole := models.RoleUser if req.Role != "" { parsed, err := models.ParseRoleName(req.Role) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"success": false, "error": "无效的角色"}) return } targetRole = parsed } if !containsRole(allowedRolesForCreation(current.Role), targetRole) { c.JSON(http.StatusForbidden, gin.H{"success": false, "error": "权限不足"}) return } if err := validateUsername(req.Username); err != nil { c.JSON(http.StatusBadRequest, gin.H{"success": false, "error": err.Error()}) return } if len(req.Password) < 6 { c.JSON(http.StatusBadRequest, gin.H{"success": false, "error": "密码长度至少 6 位"}) return } var role models.Role if err := h.DB.Where("name = ?", targetRole.String()).First(&role).Error; err != nil { c.JSON(http.StatusBadRequest, gin.H{"success": false, "error": "角色不存在"}) return } hash, err := hashPassword(req.Password) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"success": false, "error": "internal server error"}) return } username := strings.ToLower(strings.TrimSpace(req.Username)) var email *string if req.Email != nil && *req.Email != "" { e := strings.ToLower(strings.TrimSpace(*req.Email)) email = &e } user := models.User{ Username: username, Email: email, PasswordHash: hash, RoleID: role.ID, Status: "active", } if err := h.DB.Create(&user).Error; err != nil { if strings.Contains(err.Error(), "duplicate key") { c.JSON(http.StatusConflict, gin.H{"success": false, "error": "用户名或邮箱已存在"}) return } c.JSON(http.StatusInternalServerError, gin.H{"success": false, "error": "internal server error"}) return } h.DB.Preload("Role").First(&user, "id = ?", user.ID) c.JSON(http.StatusOK, user.ToPublicInfo()) } func (h *AdminHandler) UpdateUser(c *gin.Context) { current, _ := middleware.GetCurrentUser(c) userID := c.Param("id") var req struct { Email *string `json:"email"` Role string `json:"role"` Status string `json:"status"` } if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"success": false, "error": "请求参数错误"}) return } var target models.User if err := h.DB.Preload("Role").Where("id = ?", userID).First(&target).Error; err != nil { c.JSON(http.StatusNotFound, gin.H{"success": false, "error": "not found"}) return } if !current.Role.CanManage(target.Role.NameEnum()) && current.ID != userID { c.JSON(http.StatusForbidden, gin.H{"success": false, "error": "权限不足"}) return } updates := map[string]interface{}{} if req.Email != nil && *req.Email != "" { updates["email"] = strings.ToLower(strings.TrimSpace(*req.Email)) } if req.Status != "" { if target.Role.NameEnum() == models.RoleSystemAdmin && req.Status != "active" { c.JSON(http.StatusForbidden, gin.H{"success": false, "error": "不能禁用系统管理员账号"}) return } updates["status"] = req.Status } if req.Role != "" { newRole, err := models.ParseRoleName(req.Role) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"success": false, "error": "无效的角色"}) return } if target.Role.NameEnum() == models.RoleSystemAdmin && newRole != models.RoleSystemAdmin { c.JSON(http.StatusForbidden, gin.H{"success": false, "error": "不能修改系统管理员账号的角色"}) return } if !containsRole(allowedRolesForCreation(current.Role), newRole) || !current.Role.CanManage(newRole) { c.JSON(http.StatusForbidden, gin.H{"success": false, "error": "权限不足"}) return } var role models.Role if err := h.DB.Where("name = ?", newRole.String()).First(&role).Error; err != nil { c.JSON(http.StatusBadRequest, gin.H{"success": false, "error": "角色不存在"}) return } updates["role_id"] = role.ID } if err := h.DB.Model(&target).Updates(updates).Error; err != nil { c.JSON(http.StatusInternalServerError, gin.H{"success": false, "error": "internal server error"}) return } h.DB.Preload("Role").First(&target, "id = ?", userID) c.JSON(http.StatusOK, target.ToPublicInfo()) } func (h *AdminHandler) DeleteUser(c *gin.Context) { current, _ := middleware.GetCurrentUser(c) userID := c.Param("id") if current.ID == userID { c.JSON(http.StatusBadRequest, gin.H{"success": false, "error": "不能删除自己"}) return } var target models.User if err := h.DB.Preload("Role").Where("id = ?", userID).First(&target).Error; err != nil { c.JSON(http.StatusNotFound, gin.H{"success": false, "error": "not found"}) return } if !current.Role.CanManage(target.Role.NameEnum()) { c.JSON(http.StatusForbidden, gin.H{"success": false, "error": "权限不足"}) return } if target.Role.NameEnum() == models.RoleSystemAdmin { c.JSON(http.StatusForbidden, gin.H{"success": false, "error": "不能删除系统管理员账号"}) return } if err := h.DB.Delete(&target).Error; err != nil { c.JSON(http.StatusInternalServerError, gin.H{"success": false, "error": "internal server error"}) return } c.JSON(http.StatusOK, gin.H{"message": "用户已删除"}) } func (h *AdminHandler) ListRoles(c *gin.Context) { var roles []models.Role if err := h.DB.Order("id").Find(&roles).Error; err != nil { c.JSON(http.StatusInternalServerError, gin.H{"success": false, "error": "internal server error"}) return } c.JSON(http.StatusOK, roles) }