-- =========================================================
-- 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 'ai-3d:create' UNION ALL
  SELECT 'class:create' UNION ALL
  SELECT 'class:delete' UNION ALL
  SELECT 'class:update' 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 'department:create' UNION ALL
  SELECT 'department:delete' UNION ALL
  SELECT 'department:update' UNION ALL
  SELECT 'dict:create' UNION ALL
  SELECT 'dict:delete' UNION ALL
  SELECT 'dict:update' UNION ALL
  SELECT 'grade:create' UNION ALL
  SELECT 'grade:delete' UNION ALL
  SELECT 'grade:update' UNION ALL
  SELECT 'homework:create' UNION ALL
  SELECT 'homework:delete' UNION ALL
  SELECT 'homework:read' UNION ALL
  SELECT 'homework: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 'school:create' UNION ALL
  SELECT 'school:update' UNION ALL
  SELECT 'student:create' UNION ALL
  SELECT 'student:delete' UNION ALL
  SELECT 'student:update' UNION ALL
  SELECT 'teacher:create' UNION ALL
  SELECT 'teacher:delete' UNION ALL
  SELECT 'teacher: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;

