Browse Source

chore(系统): module/system 授权事后核对 SQL 交付件(只读,待用户执行)

用户贴回 §0 两个读数后,出现了无法从读数本身判定的分叉:回复里那句「第三个无数据」
有两种读法而结论相反 —— 整个授权文件已从头跑到尾(§3 返回 0 行 = 通过),
或只跑了 §0(那就不存在第三个结果集)。§3 返回 0 行既可能是「已执行且正确」,
也可能是「这条查询根本没跑到」,两者读数一样。

所以用只读读数定死:① 角色 1 现在持不持有 id 2 与两个新权限点 ② §1 那两个权限点
在不在 sys_menu ③ §2a 的快照表在不在。三条一起看,执行过没执行过不会混。

另加 ④ 祖先目录检查,这条与 §3 是两回事:§3 只核权限串,不核菜单渲不渲染。
依据 ⓪-B 实测,角色 1 持有 242/243 而**不持有它们的父节点 id 2**(系统管理目录),
按 UserService#buildMenuTree(662 行)「父节点不在授权集合里的行静默丢弃」的写法,
今天只要有人给非超管账号分配角色 1,那个人的侧边栏里整个系统管理都不会出现。
admin 是超管走 getAllMenusTree(58-59 行)所以从未暴露。④ 顺带核 id 2 的 status:
若为 '1'(软删除)则授了也不渲染,得单独处理。

只读性配了正对照:同一把尺(行首写操作关键字)在本文件 0 命中,
在 sys-authz-grant-module-system.sql 命中 3;放宽到全文任意位置分别是 0 与 5。

本文件只读,执行由用户做。
alphaH 2 weeks ago
parent
commit
3a9a655eac
1 changed files with 61 additions and 0 deletions
  1. 61 0
      java/src/main/resources/db/sys-authz-postcheck-readonly.sql

+ 61 - 0
java/src/main/resources/db/sys-authz-postcheck-readonly.sql

@@ -0,0 +1,61 @@
+-- module/system 授权 —— 事后核对(**只读**,2026-09-28)
+--
+-- 【本脚本只读】没有 INSERT / UPDATE / DELETE / DDL,跑它不改任何数据。
+--
+-- 为什么要这一份:sys-authz-grant-module-system.sql 里 §0 是只读、§1/§2 写数据,
+-- 跑完之后无法从「§3 返回 0 行」单独判定 §1/§2 到底执行过没有 ——
+-- 没执行时 §3 会返回 76 行(全都「没授给角色 1」),已执行且正确时返回 0 行,
+-- 但「返回 0 行」也可能来自「这条查询根本没跑到」。所以用下面三条只读读数来定。
+--
+-- 依据(用户已贴回的执行前读数):
+--   执行前角色 1 持有的 module_system 行只有 242、243 两条;id 2(系统管理目录)不在其中。
+--   角色 1 的唯一持有者是 admin(id=1),且它是超管(is_superuser=t)。
+
+
+-- ① 角色 1 现在持有多少行、包不包含关键节点
+--    预期(§2 已执行):held_total 约 84,持有 id 2,并持有两个新权限点
+--    预期(§2 未执行):held_total = 2(只有 242/243),不持有 id 2
+SELECT (SELECT count(*) FROM sys_role_menus WHERE role_id = 1) AS held_total,
+       EXISTS (SELECT 1 FROM sys_role_menus WHERE role_id = 1 AND menu_id = 2) AS holds_menu_2,
+       EXISTS (SELECT 1
+                 FROM sys_role_menus rm JOIN sys_menu m ON m.id = rm.menu_id
+                WHERE rm.role_id = 1
+                  AND m.permission = 'module_system:invitation:create') AS holds_invite_create,
+       EXISTS (SELECT 1
+                 FROM sys_role_menus rm JOIN sys_menu m ON m.id = rm.menu_id
+                WHERE rm.role_id = 1
+                  AND m.permission = 'module_system:invitation:delete') AS holds_invite_delete;
+
+
+-- ② §1 补的两个权限点在不在 sys_menu 里
+--    预期(§1 已执行):2 行;未执行:0 行
+SELECT id, parent_id, type, status, permission, name
+  FROM sys_menu
+ WHERE permission IN ('module_system:invitation:create', 'module_system:invitation:delete')
+ ORDER BY permission;
+
+
+-- ③ §2a 的快照表在不在(在 = §2 那段跑过)
+SELECT to_regclass('public._bak_role_menus_role1') AS snapshot_table;
+
+
+-- ④ 祖先目录检查 —— 这条决定菜单**渲不渲染**,与 §3 是两回事。
+--    UserService#buildMenuTree(UserService.java:662)对父节点不在授权集合里的行是
+--    静默丢弃(既不进 tree 也不挂到父上),所以只授子节点 = 菜单看不见。
+--    这里列出所有「module_system:% 行的父节点」,看它们各自的状态与角色 1 是否持有。
+--    预期:只有 id 2 一行,status='0',held_by_role1 = true。
+--    若 status='1' ⇒ 该目录被软删除(@TableLogic),授了也不渲染,需要单独处理。
+SELECT m.id,
+       m.parent_id,
+       m.type,
+       m.status,
+       m.name,
+       m.title,
+       EXISTS (SELECT 1 FROM sys_role_menus rm
+                WHERE rm.role_id = 1 AND rm.menu_id = m.id) AS held_by_role1
+  FROM sys_menu m
+ WHERE m.id IN (SELECT DISTINCT parent_id
+                  FROM sys_menu
+                 WHERE parent_id IS NOT NULL
+                   AND permission LIKE 'module_system:%')
+ ORDER BY m.id;