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

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。

改成

  1. sys_role_data_scope(02 新表)中该用户所有角色的行
  2. 按 module_code 分组,每组取最宽 level(角色无行 = 贡献 SELF,02 决策 3)
  3. 组成 Map<String, DataScopeLevel>
  4. 部门集合 / 子树展开只算一次——任一模块的 widest 是 DEPT_AND_CHILDREN 就算 expandedDeptIds
  5. 建一份 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 的前半部分),后半段不动。