|
@@ -0,0 +1,147 @@
|
|
|
|
|
+-- module/system 方法级授权 —— 清点(**只读**,2026-09-28)
|
|
|
|
|
+--
|
|
|
|
|
+-- 【本脚本只读】没有 INSERT / UPDATE / DELETE / DDL,跑它不改任何数据。
|
|
|
|
|
+-- 执行由用户做,把三个结果集贴回即可。
|
|
|
|
|
+--
|
|
|
|
|
+-- ── 为什么要清点 ─────────────────────────────────────────────────────
|
|
|
|
|
+-- java 侧 module/system/** 共 12 个 controller、**102 个端点,@PreAuthorize 出现 0 次**;
|
|
|
|
|
+-- SecurityConfig 的授权规则只有 .anyRequest().authenticated()(仅认证,无 hasAuthority),
|
|
|
|
|
+-- 全 main 树也没有授权用的 HandlerInterceptor(唯一的 OperationLogInterceptor 只管日志)、
|
|
|
|
|
+-- 没有 @Aspect。Python 版不是这样:`366311e^` 时每条路由都挂
|
|
|
|
|
+-- AuthPermission([...]) ⇒ 这是**平移时掉的**,不是设计选择。
|
|
|
|
|
+--
|
|
|
|
|
+-- 后果是具体的:sys_role / sys_menu / sys_role_menus / sys_dept / sys_position /
|
|
|
|
|
+-- sys_dict_* / sys_param / sys_notice 全在 TenantInnerInterceptor 的 IGNORE_TABLES 里
|
|
|
|
|
+-- (不加租户谓词)⇒ 一个普通租户账号登录后可以直接
|
|
|
|
|
+-- PATCH /system/role/permission/setting 改写**任意**角色的授权
|
|
|
|
|
+-- DELETE /system/role/delete 删掉平台自己的角色
|
|
|
|
|
+-- (POST /system/user/create 那条走不通:UserService#createUser 显式拦了 is_superuser。)
|
|
|
|
|
+--
|
|
|
|
|
+-- ── 为什么不能直接补注解 ─────────────────────────────────────────────
|
|
|
|
|
+-- 权限串若在 sys_menu 里**不存在**(或所在行 status='1',被 @TableLogic 判成已删),
|
|
|
|
|
+-- 就没有任何角色能持有它 ⇒ 补上注解后,**除超管外全部被锁在角色/用户管理之外**
|
|
|
|
|
+-- (超管不受影响:PermissionCheck 对 ROLE_SUPERUSER 直通)。所以先量,再改代码。
|
|
|
|
|
+--
|
|
|
|
|
+-- ── 三个结果集 ───────────────────────────────────────────────────────
|
|
|
|
|
+-- ① sys_menu 里现存的 module_system:% 权限串 —— 连同 status('0' 才是活的)
|
|
|
|
|
+-- ② 这些串分别授给了哪些角色 —— 判断「改了会锁住谁」
|
|
|
|
|
+-- ③ 期望清单里**库里没有**(或只有 status='1' 的行)的串 —— 这些端点不能照搬注解
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+-- ① 现存的 module_system:% 权限串
|
|
|
|
|
+SELECT m.id,
|
|
|
|
|
+ m.parent_id,
|
|
|
|
|
+ m.type,
|
|
|
|
|
+ m.status,
|
|
|
|
|
+ m.permission,
|
|
|
|
|
+ m.name,
|
|
|
|
|
+ m.title
|
|
|
|
|
+ FROM sys_menu m
|
|
|
|
|
+ WHERE m.permission IS NOT NULL
|
|
|
|
|
+ AND m.permission <> ''
|
|
|
|
|
+ AND m.permission LIKE 'module_system:%'
|
|
|
|
|
+ ORDER BY m.permission, m.id;
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+-- ② 这些串分别授给了哪些角色(menu_cnt 是行数,perms 是串本身)
|
|
|
|
|
+SELECT rm.role_id,
|
|
|
|
|
+ r.name AS role_name,
|
|
|
|
|
+ r.status AS role_status,
|
|
|
|
|
+ count(*) AS menu_cnt,
|
|
|
|
|
+ string_agg(DISTINCT m.permission, ', ' ORDER BY m.permission) AS perms
|
|
|
|
|
+ FROM sys_role_menus rm
|
|
|
|
|
+ JOIN sys_role r ON r.id = rm.role_id
|
|
|
|
|
+ JOIN sys_menu m ON m.id = rm.menu_id
|
|
|
|
|
+ WHERE m.permission LIKE 'module_system:%'
|
|
|
|
|
+ GROUP BY rm.role_id, r.name, r.status
|
|
|
|
|
+ ORDER BY rm.role_id;
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+-- ③ 期望清单里库中没有活行的串(73 个,取自 Python 版每条路由的 AuthPermission)
|
|
|
|
|
+-- 这些串**没有**任何角色能持有 ⇒ 对应端点直接照搬注解就会锁人,要单独裁定。
|
|
|
|
|
+-- status 过滤与 MenuMapper.selectList(@TableLogic)对齐:'1' 的行不出现在菜单树里,
|
|
|
|
|
+-- 也就没法被勾选授权。
|
|
|
|
|
+WITH expected(permission) AS (
|
|
|
|
|
+ VALUES
|
|
|
|
|
+ ('module_system:dept:create'),
|
|
|
|
|
+ ('module_system:dept:delete'),
|
|
|
|
|
+ ('module_system:dept:detail'),
|
|
|
|
|
+ ('module_system:dept:patch'),
|
|
|
|
|
+ ('module_system:dept:query'),
|
|
|
|
|
+ ('module_system:dept:update'),
|
|
|
|
|
+ ('module_system:dict_data:create'),
|
|
|
|
|
+ ('module_system:dict_data:delete'),
|
|
|
|
|
+ ('module_system:dict_data:detail'),
|
|
|
|
|
+ ('module_system:dict_data:export'),
|
|
|
|
|
+ ('module_system:dict_data:patch'),
|
|
|
|
|
+ ('module_system:dict_data:query'),
|
|
|
|
|
+ ('module_system:dict_data:update'),
|
|
|
|
|
+ ('module_system:dict_type:create'),
|
|
|
|
|
+ ('module_system:dict_type:delete'),
|
|
|
|
|
+ ('module_system:dict_type:detail'),
|
|
|
|
|
+ ('module_system:dict_type:export'),
|
|
|
|
|
+ ('module_system:dict_type:patch'),
|
|
|
|
|
+ ('module_system:dict_type:query'),
|
|
|
|
|
+ ('module_system:dict_type:update'),
|
|
|
|
|
+ ('module_system:log:delete'),
|
|
|
|
|
+ ('module_system:log:detail'),
|
|
|
|
|
+ ('module_system:log:export'),
|
|
|
|
|
+ ('module_system:log:query'),
|
|
|
|
|
+ ('module_system:menu:create'),
|
|
|
|
|
+ ('module_system:menu:delete'),
|
|
|
|
|
+ ('module_system:menu:detail'),
|
|
|
|
|
+ ('module_system:menu:patch'),
|
|
|
|
|
+ ('module_system:menu:query'),
|
|
|
|
|
+ ('module_system:menu:update'),
|
|
|
|
|
+ ('module_system:notice:create'),
|
|
|
|
|
+ ('module_system:notice:delete'),
|
|
|
|
|
+ ('module_system:notice:detail'),
|
|
|
|
|
+ ('module_system:notice:export'),
|
|
|
|
|
+ ('module_system:notice:patch'),
|
|
|
|
|
+ ('module_system:notice:query'),
|
|
|
|
|
+ ('module_system:notice:update'),
|
|
|
|
|
+ ('module_system:param:create'),
|
|
|
|
|
+ ('module_system:param:delete'),
|
|
|
|
|
+ ('module_system:param:detail'),
|
|
|
|
|
+ ('module_system:param:export'),
|
|
|
|
|
+ ('module_system:param:query'),
|
|
|
|
|
+ ('module_system:param:update'),
|
|
|
|
|
+ ('module_system:param:upload'),
|
|
|
|
|
+ ('module_system:position:create'),
|
|
|
|
|
+ ('module_system:position:delete'),
|
|
|
|
|
+ ('module_system:position:detail'),
|
|
|
|
|
+ ('module_system:position:export'),
|
|
|
|
|
+ ('module_system:position:patch'),
|
|
|
|
|
+ ('module_system:position:query'),
|
|
|
|
|
+ ('module_system:position:update'),
|
|
|
|
|
+ ('module_system:role:create'),
|
|
|
|
|
+ ('module_system:role:delete'),
|
|
|
|
|
+ ('module_system:role:detail'),
|
|
|
|
|
+ ('module_system:role:export'),
|
|
|
|
|
+ ('module_system:role:patch'),
|
|
|
|
|
+ ('module_system:role:permission'),
|
|
|
|
|
+ ('module_system:role:query'),
|
|
|
|
|
+ ('module_system:role:update'),
|
|
|
|
|
+ ('module_system:tenant:create'),
|
|
|
|
|
+ ('module_system:tenant:delete'),
|
|
|
|
|
+ ('module_system:tenant:patch'),
|
|
|
|
|
+ ('module_system:tenant:query'),
|
|
|
|
|
+ ('module_system:tenant:update'),
|
|
|
|
|
+ ('module_system:user:create'),
|
|
|
|
|
+ ('module_system:user:delete'),
|
|
|
|
|
+ ('module_system:user:detail'),
|
|
|
|
|
+ ('module_system:user:download'),
|
|
|
|
|
+ ('module_system:user:export'),
|
|
|
|
|
+ ('module_system:user:import'),
|
|
|
|
|
+ ('module_system:user:patch'),
|
|
|
|
|
+ ('module_system:user:query'),
|
|
|
|
|
+ ('module_system:user:update')
|
|
|
|
|
+)
|
|
|
|
|
+SELECT e.permission AS missing_or_dead_permission
|
|
|
|
|
+ FROM expected e
|
|
|
|
|
+ WHERE NOT EXISTS (
|
|
|
|
|
+ SELECT 1 FROM sys_menu m
|
|
|
|
|
+ WHERE m.permission = e.permission
|
|
|
|
|
+ AND m.status = '0'
|
|
|
|
|
+ )
|
|
|
|
|
+ ORDER BY e.permission;
|