You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3.8 KiB
3.8 KiB
05 · 拦截器按模块取档:DataScopeInterceptor / PermissionResolverImpl
Type: grilling Status: resolved Blocked by: 01, 04
Question
DataScopeInterceptor 拦到某张受控表时,如何知道它属于哪个模块、取该模块的 scope?
PermissionResolverImpl.resolve 如何算出「每模块各自取最宽」的一组档位?
要定的点:
- 拦截器:拦到表 → 查表所属模块(依赖 01 的表→模块映射)→ 从上下文取该模块 scope → 注入 WHERE。 表不属任何模块时的行为(依赖 01 对「未接入表」的裁决)。
PermissionResolverImpl.resolve:现在遍历角色取全局最宽;改成对每个模块分别在所有角色的 该模块档位里取最宽,结出一组 DataVisibility(依赖 02 存储、04 上下文形态)。- 部门集合/子树展开只算一次、各模块档位复用(承接 04 的结论)。
- 权限码并集、可见菜单树等
resolve的其他产物不受影响,只动数据可见性那段。
依赖 01(表→模块映射)与 04(上下文/值对象形态)。
Answer
全部从 01 和 04 推导,无新决策。
1. 拦截器 DataScopeInterceptor:顺序调换
现在:先拿一份 scope → 如果 ALL_VISIBLE 跳过 → 解析 SQL 找表 → 查注解 → 造 WHERE。
改成:解析 SQL 找表 → 查注解(含 01 加的 module 属性)→ 用 anno.module() 取该模块的 scope currentScope(anno.module()) → 如果 ALL_VISIBLE 跳过这张表 → 造 WHERE。
// 现在 line 52
VisibilityScope scope = DataVisibilityContext.currentScope();
if (scope.kind() == ALL_VISIBLE) return invocation.proceed();
// ... 后面找表、查注解
// 改成:先找表、查注解,再取 scope
DataScope anno = tables.find(tableName);
if (anno == null) return select.toString();
VisibilityScope scope = DataVisibilityContext.currentScope(anno.module());
if (scope.kind() == ALL_VISIBLE) return select.toString();
Expression condition = buildCondition(scope, anno);
- 全局 ALL_VISIBLE 早退优化取消——不同模块档位不同,不能在解析 SQL 前判断。
DataScopeTables不需改——它存的是@DataScope注解实例,注解加了module后自动带出。buildCondition不变——它只看VisibilityScope的 kind/ownerId/deptIds + 注解的 ownerColumn/deptColumn。
2. 解析器 PermissionResolverImpl.resolve:每模块各取最宽
现在:遍历角色 → 取全局最宽 level → 建一份 DataVisibility。
改成:
- 查
sys_role_data_scope(02 新表)中该用户所有角色的行 - 按 module_code 分组,每组取最宽 level(角色无行 = 贡献 SELF,02 决策 3)
- 组成
Map<String, DataScopeLevel> - 部门集合 / 子树展开只算一次——任一模块的 widest 是 DEPT_AND_CHILDREN 就算 expandedDeptIds
- 建一份
DataVisibility(userId, primaryDeptId, deptIds, moduleLevels, expandedDeptIds)
// 新增依赖:SysRoleDataScopeMapper(02 建的 mapper)
List<SysRoleDataScope> roleScopes = sysRoleDataScopeMapper.selectList(
new LambdaQueryWrapper<SysRoleDataScope>().in(SysRoleDataScope::getRoleId, roleIds));
Map<String, DataScopeLevel> moduleLevels = new HashMap<>();
for (SysRoleDataScope rs : roleScopes) {
DataScopeLevel level = DataScopeLevel.fromCode(rs.getDataScope());
moduleLevels.merge(rs.getModuleCode(), level,
(a, b) -> a.getCode() >= b.getCode() ? a : b);
}
// 无行的模块不进 map,DataVisibility.visibilityScope() 用 getOrDefault(moduleCode, SELF)
expandedDeptIds判定从widest == DEPT_AND_CHILDREN改为moduleLevels.values().stream().anyMatch(l -> l == DEPT_AND_CHILDREN)
3. 不受影响
权限码并集、可见菜单树、角色编码——只动数据可见性那段(resolve 的前半部分),后半段不动。