package handler import ( "errors" "net/http" apperrors "carrot_bbs/internal/errors" "carrot_bbs/internal/model" "carrot_bbs/internal/service" "github.com/gin-gonic/gin" ) // RoleHandler 角色管理处理器 type RoleHandler struct { roleService service.RoleService } // NewRoleHandler 创建角色处理器 func NewRoleHandler(roleService service.RoleService) *RoleHandler { return &RoleHandler{ roleService: roleService, } } // GetAllRoles 获取所有角色 // GET /api/v1/admin/roles func (h *RoleHandler) GetAllRoles(c *gin.Context) { roles, err := h.roleService.GetAllRoles(c.Request.Context()) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "code": "INTERNAL_ERROR", "message": "获取角色列表失败", }) return } c.JSON(http.StatusOK, gin.H{ "data": h.toRoleListResponse(roles), }) } // GetUserRoles 获取用户的角色 // GET /api/v1/admin/users/:id/roles func (h *RoleHandler) GetUserRoles(c *gin.Context) { userID := c.Param("id") if userID == "" { c.JSON(http.StatusBadRequest, gin.H{ "code": "BAD_REQUEST", "message": "缺少用户ID", }) return } roles, err := h.roleService.GetUserRoles(c.Request.Context(), userID) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "code": "INTERNAL_ERROR", "message": "获取用户角色失败", }) return } c.JSON(http.StatusOK, gin.H{ "data": h.toRoleListResponse(roles), }) } // AssignRoleRequest 分配角色请求 type AssignRoleRequest struct { Role string `json:"role" binding:"required"` } // AssignRole 为用户分配角色 // POST /api/v1/admin/users/:id/roles func (h *RoleHandler) AssignRole(c *gin.Context) { targetUserID := c.Param("id") if targetUserID == "" { c.JSON(http.StatusBadRequest, gin.H{ "code": "BAD_REQUEST", "message": "缺少用户ID", }) return } var req AssignRoleRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{ "code": "BAD_REQUEST", "message": "请求参数错误", }) return } // 获取操作者ID operatorID, _ := c.Get("user_id") err := h.roleService.AssignRole(c.Request.Context(), operatorID.(string), targetUserID, req.Role) if err != nil { h.handleError(c, err) return } c.JSON(http.StatusOK, gin.H{ "message": "角色分配成功", }) } // RemoveRole 移除用户角色 // DELETE /api/v1/admin/users/:id/roles/:role func (h *RoleHandler) RemoveRole(c *gin.Context) { targetUserID := c.Param("id") role := c.Param("role") if targetUserID == "" || role == "" { c.JSON(http.StatusBadRequest, gin.H{ "code": "BAD_REQUEST", "message": "缺少用户ID或角色名", }) return } // 获取操作者ID operatorID, _ := c.Get("user_id") err := h.roleService.RemoveRole(c.Request.Context(), operatorID.(string), targetUserID, role) if err != nil { h.handleError(c, err) return } c.JSON(http.StatusOK, gin.H{ "message": "角色移除成功", }) } // GetMyRoles 获取当前用户的角色 // GET /api/v1/users/me/roles func (h *RoleHandler) GetMyRoles(c *gin.Context) { userID, _ := c.Get("user_id") roles, err := h.roleService.GetUserRoles(c.Request.Context(), userID.(string)) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "code": "INTERNAL_ERROR", "message": "获取用户角色失败", }) return } c.JSON(http.StatusOK, gin.H{ "data": h.toRoleListResponse(roles), }) } // toRoleListResponse 转换为响应格式 func (h *RoleHandler) toRoleListResponse(roles []model.Role) []gin.H { result := make([]gin.H, len(roles)) for i, role := range roles { result[i] = gin.H{ "name": role.Name, "display_name": role.DisplayName, "description": role.Description, "priority": role.Priority, } } return result } // handleError 处理错误 func (h *RoleHandler) handleError(c *gin.Context, err error) { switch { case errors.Is(err, apperrors.ErrCannotModifyOwnRole): c.JSON(http.StatusForbidden, gin.H{ "code": "CANNOT_MODIFY_OWN_ROLE", "message": "不能修改自己的角色", }) case errors.Is(err, apperrors.ErrCannotModifySuperAdmin): c.JSON(http.StatusForbidden, gin.H{ "code": "CANNOT_MODIFY_SUPER_ADMIN", "message": "不能修改超级管理员角色", }) case errors.Is(err, apperrors.ErrRoleAlreadyAssigned): c.JSON(http.StatusConflict, gin.H{ "code": "ROLE_ALREADY_ASSIGNED", "message": "用户已拥有该角色", }) case errors.Is(err, apperrors.ErrRoleNotAssigned): c.JSON(http.StatusConflict, gin.H{ "code": "ROLE_NOT_ASSIGNED", "message": "用户未拥有该角色", }) case errors.Is(err, apperrors.ErrRoleNotFound): c.JSON(http.StatusNotFound, gin.H{ "code": "ROLE_NOT_FOUND", "message": "角色不存在", }) default: c.JSON(http.StatusInternalServerError, gin.H{ "code": "INTERNAL_ERROR", "message": "操作失败", }) } }