- Remove BOM from all Go source files - Standardize import ordering and whitespace across handlers and services - Replace PostgreSQL full-text search with ILIKE pattern matching in post and user repositories - Enhance JPush client with TLS transport, rate limit monitoring, and simplified API - Refactor PushService to include userID in device management methods - Add MaxDevicesPerUser limit and extract helper functions for push payload construction
330 lines
7.7 KiB
Go
330 lines
7.7 KiB
Go
package handler
|
|
|
|
import (
|
|
"errors"
|
|
"net/http"
|
|
|
|
apperrors "with_you/internal/errors"
|
|
"with_you/internal/model"
|
|
"with_you/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": "操作失败",
|
|
})
|
|
}
|
|
}
|
|
|
|
// GetRoleDetail 获取角色详情
|
|
// GET /api/v1/admin/roles/:name
|
|
func (h *RoleHandler) GetRoleDetail(c *gin.Context) {
|
|
name := c.Param("name")
|
|
if name == "" {
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
|
"code": "BAD_REQUEST",
|
|
"message": "缺少角色名称",
|
|
})
|
|
return
|
|
}
|
|
|
|
detail, err := h.roleService.GetRoleDetail(c.Request.Context(), name)
|
|
if err != nil {
|
|
h.handleError(c, err)
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"data": detail,
|
|
})
|
|
}
|
|
|
|
// GetRolePermissions 获取角色权限
|
|
// GET /api/v1/admin/roles/:name/permissions
|
|
func (h *RoleHandler) GetRolePermissions(c *gin.Context) {
|
|
name := c.Param("name")
|
|
if name == "" {
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
|
"code": "BAD_REQUEST",
|
|
"message": "缺少角色名称",
|
|
})
|
|
return
|
|
}
|
|
|
|
permissions, err := h.roleService.GetRolePermissions(c.Request.Context(), name)
|
|
if err != nil {
|
|
h.handleError(c, err)
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"data": permissions,
|
|
})
|
|
}
|
|
|
|
// GetAllPermissions 获取所有权限定义
|
|
// GET /api/v1/admin/permissions
|
|
func (h *RoleHandler) GetAllPermissions(c *gin.Context) {
|
|
permissions, err := h.roleService.GetAllPermissions(c.Request.Context())
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{
|
|
"code": "INTERNAL_ERROR",
|
|
"message": "获取权限列表失败",
|
|
})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"data": permissions,
|
|
})
|
|
}
|
|
|
|
// UpdateRolePermissionsRequest 更新角色权限请求
|
|
type UpdateRolePermissionsRequest struct {
|
|
Permissions []PermissionInput `json:"permissions" binding:"required"`
|
|
}
|
|
|
|
// PermissionInput 权限输入
|
|
type PermissionInput struct {
|
|
Resource string `json:"resource" binding:"required"`
|
|
Action string `json:"action" binding:"required"`
|
|
}
|
|
|
|
// UpdateRolePermissions 更新角色权限
|
|
// PUT /api/v1/admin/roles/:name/permissions
|
|
func (h *RoleHandler) UpdateRolePermissions(c *gin.Context) {
|
|
name := c.Param("name")
|
|
if name == "" {
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
|
"code": "BAD_REQUEST",
|
|
"message": "缺少角色名称",
|
|
})
|
|
return
|
|
}
|
|
|
|
var req UpdateRolePermissionsRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
|
"code": "BAD_REQUEST",
|
|
"message": "请求参数错误",
|
|
})
|
|
return
|
|
}
|
|
|
|
// 转换权限格式
|
|
var permissions []service.Permission
|
|
for _, p := range req.Permissions {
|
|
permissions = append(permissions, service.Permission{
|
|
Resource: p.Resource,
|
|
Action: p.Action,
|
|
})
|
|
}
|
|
|
|
err := h.roleService.UpdateRolePermissions(c.Request.Context(), name, permissions)
|
|
if err != nil {
|
|
h.handleError(c, err)
|
|
return
|
|
}
|
|
|
|
// 返回更新后的角色信息
|
|
detail, err := h.roleService.GetRoleDetail(c.Request.Context(), name)
|
|
if err != nil {
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"message": "权限更新成功",
|
|
})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"message": "权限更新成功",
|
|
"data": detail,
|
|
})
|
|
}
|