library-picturebook-activity/docs/migration/rbac-audit.sql
2026-04-02 14:22:56 +08:00

138 lines
4.3 KiB
SQL
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- =========================================================
-- 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_idpermission 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 非空,则角色至少要拥有该 permissionrole_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;