2026-05-02 13:02:38 +08:00

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})
}