204 lines
6.1 KiB
Go
204 lines
6.1 KiB
Go
package rbac
|
|
|
|
import (
|
|
"fmt"
|
|
"github.com/gin-gonic/gin"
|
|
"hyapp-admin-server/internal/middleware"
|
|
"hyapp-admin-server/internal/modules/shared"
|
|
"hyapp-admin-server/internal/repository"
|
|
"hyapp-admin-server/internal/response"
|
|
)
|
|
|
|
type Handler struct {
|
|
service *RBACService
|
|
audit shared.OperationLogger
|
|
}
|
|
|
|
func New(store *repository.Store, audit shared.OperationLogger) *Handler {
|
|
return &Handler{service: NewService(store), audit: audit}
|
|
}
|
|
|
|
func (h *Handler) ListPermissions(c *gin.Context) {
|
|
permissions, err := h.service.ListPermissions()
|
|
if err != nil {
|
|
response.ServerError(c, "获取权限失败")
|
|
return
|
|
}
|
|
response.OK(c, permissions)
|
|
}
|
|
|
|
func (h *Handler) CreatePermission(c *gin.Context) {
|
|
var req permissionRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
response.BadRequest(c, "权限名称、编码和类型不能为空")
|
|
return
|
|
}
|
|
|
|
permission, err := h.service.CreatePermission(PermissionInput{Name: req.Name, Code: req.Code, Kind: req.Kind, Description: req.Description})
|
|
if err != nil {
|
|
response.BadRequest(c, err.Error())
|
|
return
|
|
}
|
|
shared.OperationLog(c, h.audit, "create-permission", "admin_permissions", "success", permission.Code)
|
|
response.Created(c, *permission)
|
|
}
|
|
|
|
func (h *Handler) UpdatePermission(c *gin.Context) {
|
|
id, ok := shared.ParseID(c, "id")
|
|
if !ok {
|
|
return
|
|
}
|
|
var req permissionRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
response.BadRequest(c, "权限名称、编码和类型不能为空")
|
|
return
|
|
}
|
|
|
|
permission, err := h.service.UpdatePermission(id, PermissionInput{Name: req.Name, Code: req.Code, Kind: req.Kind, Description: req.Description})
|
|
if err != nil {
|
|
response.BadRequest(c, err.Error())
|
|
return
|
|
}
|
|
shared.OperationLog(c, h.audit, "update-permission", "admin_permissions", "success", permission.Code)
|
|
response.OK(c, permission)
|
|
}
|
|
|
|
func (h *Handler) DeletePermission(c *gin.Context) {
|
|
id, ok := shared.ParseID(c, "id")
|
|
if !ok {
|
|
return
|
|
}
|
|
if err := h.service.DeletePermission(id); err != nil {
|
|
response.BadRequest(c, err.Error())
|
|
return
|
|
}
|
|
shared.OperationLog(c, h.audit, "delete-permission", "admin_permissions", "success", fmt.Sprintf("permission_id=%d", id))
|
|
response.OK(c, gin.H{"deleted": true})
|
|
}
|
|
|
|
func (h *Handler) SyncPermissions(c *gin.Context) {
|
|
// 同步只写入系统内置权限,不删除人工新增权限,避免新功能上线时破坏现场配置。
|
|
if err := h.service.SyncPermissions(); err != nil {
|
|
response.ServerError(c, "同步权限失败")
|
|
return
|
|
}
|
|
shared.OperationLog(c, h.audit, "sync-permissions", "admin_permissions", "success", "default permissions")
|
|
response.OK(c, gin.H{"synced": true})
|
|
}
|
|
|
|
func (h *Handler) ListRoles(c *gin.Context) {
|
|
roles, err := h.service.ListRoles()
|
|
if err != nil {
|
|
response.ServerError(c, "获取角色失败")
|
|
return
|
|
}
|
|
response.OK(c, roles)
|
|
}
|
|
|
|
func (h *Handler) CreateRole(c *gin.Context) {
|
|
var req roleRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
response.BadRequest(c, "角色名称和编码不能为空")
|
|
return
|
|
}
|
|
if len(req.PermissionIDs) > 0 && !middleware.HasAnyPermission(c, "role:permission", "role:manage") {
|
|
// 创建角色和授予权限是两个风险等级,直接调用 API 时也必须阻断越权授权。
|
|
response.Forbidden(c, "没有角色授权权限")
|
|
return
|
|
}
|
|
|
|
role, err := h.service.CreateRole(RoleInput{Name: req.Name, Code: req.Code, Description: req.Description, PermissionIDs: req.PermissionIDs})
|
|
if err != nil {
|
|
response.BadRequest(c, err.Error())
|
|
return
|
|
}
|
|
shared.OperationLog(c, h.audit, "create-role", "admin_roles", "success", role.Name)
|
|
response.Created(c, *role)
|
|
}
|
|
|
|
func (h *Handler) UpdateRole(c *gin.Context) {
|
|
id, ok := shared.ParseID(c, "id")
|
|
if !ok {
|
|
return
|
|
}
|
|
var req roleRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
response.BadRequest(c, "角色名称和编码不能为空")
|
|
return
|
|
}
|
|
// 角色基础信息和角色授权分开保存,避免只有编辑权限的操作者顺带修改权限集合。
|
|
role, err := h.service.UpdateRole(id, RoleInput{Name: req.Name, Code: req.Code, Description: req.Description})
|
|
if err != nil {
|
|
response.BadRequest(c, err.Error())
|
|
return
|
|
}
|
|
shared.OperationLog(c, h.audit, "update-role", "admin_roles", "success", role.Name)
|
|
response.OK(c, role)
|
|
}
|
|
|
|
func (h *Handler) DeleteRole(c *gin.Context) {
|
|
id, ok := shared.ParseID(c, "id")
|
|
if !ok {
|
|
return
|
|
}
|
|
if err := h.service.DeleteRole(id); err != nil {
|
|
response.BadRequest(c, err.Error())
|
|
return
|
|
}
|
|
shared.OperationLog(c, h.audit, "delete-role", "admin_roles", "success", fmt.Sprintf("role_id=%d", id))
|
|
response.OK(c, gin.H{"deleted": true})
|
|
}
|
|
|
|
func (h *Handler) ReplaceRolePermissions(c *gin.Context) {
|
|
id, ok := shared.ParseID(c, "id")
|
|
if !ok {
|
|
return
|
|
}
|
|
var req rolePermissionRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
response.BadRequest(c, "权限参数不正确")
|
|
return
|
|
}
|
|
if err := h.service.ReplaceRolePermissions(id, req.PermissionIDs); err != nil {
|
|
response.BadRequest(c, err.Error())
|
|
return
|
|
}
|
|
shared.OperationLog(c, h.audit, "replace-role-permissions", "admin_role_permissions", "success", fmt.Sprintf("role_id=%d", id))
|
|
response.OK(c, gin.H{"updated": true})
|
|
}
|
|
|
|
func (h *Handler) GetRoleDataScopes(c *gin.Context) {
|
|
id, ok := shared.ParseID(c, "id")
|
|
if !ok {
|
|
return
|
|
}
|
|
scopes, err := h.service.ListRoleDataScopes(id)
|
|
if err != nil {
|
|
response.ServerError(c, "获取数据权限失败")
|
|
return
|
|
}
|
|
response.OK(c, gin.H{"items": scopes})
|
|
}
|
|
|
|
func (h *Handler) ReplaceRoleDataScopes(c *gin.Context) {
|
|
id, ok := shared.ParseID(c, "id")
|
|
if !ok {
|
|
return
|
|
}
|
|
var req dataScopeRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
response.BadRequest(c, "数据权限参数不正确")
|
|
return
|
|
}
|
|
scopes := make([]DataScopeItem, 0, len(req.Scopes))
|
|
for _, item := range req.Scopes {
|
|
scopes = append(scopes, DataScopeItem{ScopeType: item.ScopeType, ScopeValue: item.ScopeValue})
|
|
}
|
|
if err := h.service.ReplaceRoleDataScopes(id, DataScopeInput{Scopes: scopes}); err != nil {
|
|
response.BadRequest(c, err.Error())
|
|
return
|
|
}
|
|
shared.OperationLog(c, h.audit, "replace-role-data-scopes", "admin_data_scopes", "success", fmt.Sprintf("role_id=%d scopes=%d", id, len(scopes)))
|
|
response.OK(c, gin.H{"updated": true})
|
|
}
|