138 lines
4.3 KiB
SQL
138 lines
4.3 KiB
SQL
-- =========================================================
|
||
-- RBAC/菜单/权限 数据审计(只读)
|
||
-- 目标:快速定位“已授权但菜单为空 / 权限缺失 / 绑定缺失”等问题
|
||
-- 说明:不做任何写操作,可在生产环境安全执行
|
||
-- =========================================================
|
||
|
||
-- 0) 基础:租户列表
|
||
SELECT id, code, name, tenant_type, is_super, valid_state, deleted
|
||
FROM t_sys_tenant
|
||
WHERE deleted = 0
|
||
ORDER BY id;
|
||
|
||
-- 1) 角色存在但未做菜单授权(role_menu 为空)
|
||
-- 重点:tenant_admin / school_admin / teacher / student / judge 等关键角色
|
||
SELECT
|
||
r.tenant_id,
|
||
t.code AS tenant_code,
|
||
r.id AS role_id,
|
||
r.code AS role_code,
|
||
r.name AS role_name
|
||
FROM t_auth_role r
|
||
JOIN t_sys_tenant t ON t.id = r.tenant_id AND t.deleted = 0
|
||
LEFT JOIN t_auth_role_menu rm ON rm.role_id = r.id
|
||
WHERE r.deleted = 0
|
||
AND r.valid_state = 1
|
||
GROUP BY r.tenant_id, t.code, r.id, r.code, r.name
|
||
HAVING COUNT(rm.id) = 0
|
||
ORDER BY r.tenant_id, r.code;
|
||
|
||
-- 2) 菜单表中声明的 permission 在某些租户的 permission 表缺失
|
||
-- 由于 t_auth_menu 无 tenant_id,permission code 应在每个租户的 t_auth_permission 中都存在(除 super_admin 这种全局码也同理)
|
||
SELECT
|
||
t.id AS tenant_id,
|
||
t.code AS tenant_code,
|
||
m.permission AS menu_permission_code
|
||
FROM t_sys_tenant t
|
||
JOIN (
|
||
SELECT DISTINCT permission
|
||
FROM t_auth_menu
|
||
WHERE deleted = 0
|
||
AND valid_state = 1
|
||
AND permission IS NOT NULL
|
||
AND permission <> ''
|
||
) m ON 1 = 1
|
||
LEFT JOIN t_auth_permission p
|
||
ON p.tenant_id = t.id
|
||
AND p.code = m.permission
|
||
AND p.deleted = 0
|
||
AND p.valid_state = 1
|
||
WHERE t.deleted = 0
|
||
AND t.valid_state = 1
|
||
AND p.id IS NULL
|
||
ORDER BY t.id, m.permission;
|
||
|
||
-- 3) 关键前端权限码在各租户 permission 表缺失
|
||
-- 来自 docs/migration/permission-inventory.md(前端提取)
|
||
SELECT
|
||
t.id AS tenant_id,
|
||
t.code AS tenant_code,
|
||
req.code AS required_code
|
||
FROM t_sys_tenant t
|
||
JOIN (
|
||
SELECT 'activity:read' AS code UNION ALL
|
||
SELECT 'config:create' UNION ALL
|
||
SELECT 'config:delete' UNION ALL
|
||
SELECT 'config:update' UNION ALL
|
||
SELECT 'contest:create' UNION ALL
|
||
SELECT 'contest:delete' UNION ALL
|
||
SELECT 'contest:publish' UNION ALL
|
||
SELECT 'contest:read' UNION ALL
|
||
SELECT 'contest:update' UNION ALL
|
||
SELECT 'dict:create' UNION ALL
|
||
SELECT 'dict:delete' UNION ALL
|
||
SELECT 'dict:update' UNION ALL
|
||
SELECT 'judge:create' UNION ALL
|
||
SELECT 'judge:delete' UNION ALL
|
||
SELECT 'judge:read' UNION ALL
|
||
SELECT 'judge:update' UNION ALL
|
||
SELECT 'log:delete' UNION ALL
|
||
SELECT 'menu:create' UNION ALL
|
||
SELECT 'menu:delete' UNION ALL
|
||
SELECT 'menu:read' UNION ALL
|
||
SELECT 'menu:update' UNION ALL
|
||
SELECT 'notice:create' UNION ALL
|
||
SELECT 'notice:delete' UNION ALL
|
||
SELECT 'notice:update' UNION ALL
|
||
SELECT 'permission:read' UNION ALL
|
||
SELECT 'registration:read' UNION ALL
|
||
SELECT 'review:score' UNION ALL
|
||
SELECT 'role:create' UNION ALL
|
||
SELECT 'role:delete' UNION ALL
|
||
SELECT 'role:read' UNION ALL
|
||
SELECT 'role:update' UNION ALL
|
||
SELECT 'tenant:create' UNION ALL
|
||
SELECT 'tenant:delete' UNION ALL
|
||
SELECT 'tenant:update' UNION ALL
|
||
SELECT 'work:read'
|
||
) req ON 1 = 1
|
||
LEFT JOIN t_auth_permission p
|
||
ON p.tenant_id = t.id
|
||
AND p.code = req.code
|
||
AND p.deleted = 0
|
||
AND p.valid_state = 1
|
||
WHERE t.deleted = 0
|
||
AND t.valid_state = 1
|
||
AND p.id IS NULL
|
||
ORDER BY t.id, req.code;
|
||
|
||
-- 4) 角色拥有菜单,但缺少对应 permission(可能导致“菜单看得到但点进去 403 / 按钮缺失”)
|
||
-- 规则:若菜单 permission 非空,则角色至少要拥有该 permission(role_permission)
|
||
SELECT
|
||
r.tenant_id,
|
||
t.code AS tenant_code,
|
||
r.id AS role_id,
|
||
r.code AS role_code,
|
||
m.id AS menu_id,
|
||
m.name AS menu_name,
|
||
m.permission AS menu_permission_code
|
||
FROM t_auth_role r
|
||
JOIN t_sys_tenant t ON t.id = r.tenant_id AND t.deleted = 0
|
||
JOIN t_auth_role_menu rm ON rm.role_id = r.id
|
||
JOIN t_auth_menu m ON m.id = rm.menu_id AND m.deleted = 0 AND m.valid_state = 1
|
||
LEFT JOIN t_auth_permission p
|
||
ON p.tenant_id = r.tenant_id
|
||
AND p.code = m.permission
|
||
AND p.deleted = 0
|
||
AND p.valid_state = 1
|
||
LEFT JOIN t_auth_role_permission rp
|
||
ON rp.role_id = r.id
|
||
AND rp.permission_id = p.id
|
||
WHERE r.deleted = 0
|
||
AND r.valid_state = 1
|
||
AND m.permission IS NOT NULL
|
||
AND m.permission <> ''
|
||
AND (p.id IS NULL OR rp.id IS NULL)
|
||
ORDER BY r.tenant_id, r.code, m.id;
|
||
|