|
|
|
|
# 权限管理系统
|
|
|
|
|
|
|
|
|
|
<cite>
|
|
|
|
|
**本文引用的文件**
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
- [PermissionResolver.java](file://crm-auth/src/main/java/com/crm/auth/security/PermissionResolver.java)
|
|
|
|
|
- [PermissionGrant.java](file://crm-auth/src/main/java/com/crm/auth/security/PermissionGrant.java)
|
|
|
|
|
- [PermissionResolverImpl.java](file://crm-auth/src/main/java/com/crm/auth/security/PermissionResolverImpl.java)
|
|
|
|
|
- [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java)
|
|
|
|
|
- [SystemController.java](file://crm-auth/src/main/java/com/crm/auth/controller/SystemController.java)
|
|
|
|
|
- [SysMenu.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysMenu.java)
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
- [ResourceNode.java](file://crm-auth/src/main/java/com/crm/auth/domain/dto/ResourceNode.java)
|
|
|
|
|
- [MenuType.java](file://crm-auth/src/main/java/com/crm/auth/domain/enums/MenuType.java)
|
|
|
|
|
- [DataScopeEnum.java](file://crm-auth/src/main/java/com/crm/auth/domain/enums/DataScopeEnum.java)
|
|
|
|
|
- [TreeUtils.java](file://crm-base/src/main/java/com/crm/base/utils/TreeUtils.java)
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
- [DataInitializer.java](file://crm-auth/src/main/java/com/crm/auth/config/DataInitializer.java)
|
|
|
|
|
- [ApiPermissionInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/ApiPermissionInterceptor.java)
|
|
|
|
|
- [ApiPermissionCache.java](file://crm-auth/src/main/java/com/crm/auth/security/ApiPermissionCache.java)
|
|
|
|
|
- [ApiPermissionRule.java](file://crm-auth/src/main/java/com/crm/auth/security/ApiPermissionRule.java)
|
|
|
|
|
- [WebMvcConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/WebMvcConfig.java)
|
|
|
|
|
- [AuthServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/AuthServiceImpl.java)
|
|
|
|
|
- [ResourceServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/ResourceServiceImpl.java)
|
|
|
|
|
</cite>
|
|
|
|
|
|
|
|
|
|
## 更新摘要
|
|
|
|
|
**所做更改**
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
- **新增** 动态API权限拦截系统,基于Caffeine缓存和HandlerInterceptor实现URL级别的权限控制
|
|
|
|
|
- **增强** AuthServiceImpl认证流程重构,优化事务处理和第三方登录逻辑
|
|
|
|
|
- **完善** 资源树变更时的缓存失效机制,确保权限规则实时更新
|
|
|
|
|
- **扩展** 测试覆盖范围,包含API权限拦截、认证流程和数据权限的完整测试场景
|
|
|
|
|
|
|
|
|
|
## 目录
|
|
|
|
|
1. [简介](#简介)
|
|
|
|
|
2. [项目结构](#项目结构)
|
|
|
|
|
3. [核心组件](#核心组件)
|
|
|
|
|
4. [架构总览](#架构总览)
|
|
|
|
|
5. [详细组件分析](#详细组件分析)
|
|
|
|
|
6. [依赖关系分析](#依赖关系分析)
|
|
|
|
|
7. [性能考虑](#性能考虑)
|
|
|
|
|
8. [故障排查指南](#故障排查指南)
|
|
|
|
|
9. [结论](#结论)
|
|
|
|
|
10. [附录](#附录)
|
|
|
|
|
|
|
|
|
|
## 简介
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
本文件为基于RBAC(角色-资源)的权限管理系统文档,覆盖角色管理、菜单权限控制与数据权限范围控制。重点说明实体设计(如 SysRole、SysMenu)、权限校验逻辑(PermissionResolver三组件架构)、数据权限类型(DataScopeEnum),以及权限注解使用、动态权限加载与权限缓存机制的实现细节和配置方法。读者可据此快速理解系统权限模型并正确扩展与使用。
|
|
|
|
|
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
**更新** 本次更新重点关注新增的动态API权限拦截系统和改进的认证流程重构,包括ApiPermissionInterceptor、ApiPermissionCache等核心组件,以及AuthServiceImpl的事务处理优化。
|
|
|
|
|
|
|
|
|
|
## 项目结构
|
|
|
|
|
本项目采用多模块组织:
|
|
|
|
|
- crm-app:应用启动入口与全局配置
|
|
|
|
|
- crm-auth:认证与权限核心模块,包含RBAC实体、服务、安全拦截、第三方登录等
|
|
|
|
|
- crm-base:公共基础能力(异常、工具、通用配置、数据可见性上下文等)
|
|
|
|
|
- crm-file:文件服务(与本权限文档无直接关联)
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
graph TB
|
|
|
|
|
subgraph "应用层"
|
|
|
|
|
APP["crm-app<br/>启动与应用配置"]
|
|
|
|
|
end
|
|
|
|
|
subgraph "认证与权限"
|
|
|
|
|
AUTH["crm-auth<br/>RBAC实体/服务/安全/客户端"]
|
|
|
|
|
end
|
|
|
|
|
subgraph "基础能力"
|
|
|
|
|
BASE["crm-base<br/>异常/工具/通用配置/数据可见性"]
|
|
|
|
|
end
|
|
|
|
|
APP --> AUTH
|
|
|
|
|
AUTH --> BASE
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
章节来源
|
|
|
|
|
- [CrmAppApplication.java:1-200](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java#L1-L200)
|
|
|
|
|
- [AuthApplication.java:1-200](file://crm-auth/src/main/java/com/crm/auth/AuthApplication.java#L1-L200)
|
|
|
|
|
|
|
|
|
|
## 核心组件
|
|
|
|
|
- RBAC 实体
|
|
|
|
|
- SysRole:角色定义,承载角色标识、名称、状态等元信息
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
- SysMenu:增强的菜单与按钮资源定义,支持三层层级结构(目录-菜单-按钮)和细粒度权限控制
|
|
|
|
|
- SysUserRole、SysRoleMenu:用户-角色、角色-菜单的多对多关系表
|
|
|
|
|
- SysDept、SysUserDept:部门与用户部门关系,用于数据权限范围
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
- 数据传输对象
|
|
|
|
|
- ResourceNode:支持SysMenu与ResourceNode之间的双向转换,包含children字段支持层次结构
|
|
|
|
|
- 权限解析引擎(**重构**)
|
|
|
|
|
- **PermissionResolver接口**:定义权限解析的核心抽象,包含resolve()和visibleMenuTree()两个方法
|
|
|
|
|
- **PermissionGrant值对象**:不可变的权限解析结果,包含数据可见性、权限码并集和角色编码
|
|
|
|
|
- **PermissionResolverImpl实现**:具体的权限解析逻辑实现,采用共享查询链优化
|
|
|
|
|
- **动态API权限拦截系统(新增)**
|
|
|
|
|
- **ApiPermissionInterceptor**:HandlerInterceptor实现,基于AntPathMatcher进行URL模式匹配
|
|
|
|
|
- **ApiPermissionCache**:基于Caffeine的进程内缓存,懒加载已注册的API权限规则
|
|
|
|
|
- **ApiPermissionRule**:记录apiUrl pattern与perms权限码的映射关系
|
|
|
|
|
- 控制器层
|
|
|
|
|
- ResourceController:统一权限资源树管理端接口
|
|
|
|
|
- SystemController:系统管理相关接口,集成新的权限解析器
|
|
|
|
|
- 安全与拦截
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
- SecurityConfig、JwtAuthenticationFilter:认证流程与JWT过滤,集成新的权限解析器
|
|
|
|
|
- DataScopeInterceptor、DataScopeTables:数据权限拦截与SQL改写
|
|
|
|
|
- AuthLoginUser、TokenService:当前登录用户上下文与令牌操作
|
|
|
|
|
- 数据权限
|
|
|
|
|
- DataScopeEnum:数据权限范围枚举(如全部、本部门、本部门及子部门、仅本人等)
|
|
|
|
|
- DataScope(注解)、DataScopeHelper、DataVisibilityContext:注解驱动的数据可见性控制
|
|
|
|
|
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
**更新** 权限解析引擎已重构为三组件架构,PermissionResolver接口定义了清晰的权限解析契约,PermissionGrant提供了不可变的权限结果封装,PermissionResolverImpl实现了高效的权限解析逻辑。新增的动态API权限拦截系统通过ApiPermissionInterceptor和ApiPermissionCache实现了URL级别的权限控制。SystemController现在直接使用PermissionResolver进行菜单树获取,简化了调用方式。
|
|
|
|
|
|
|
|
|
|
章节来源
|
|
|
|
|
- [SysRole.java:1-200](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysRole.java#L1-L200)
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
- [SysMenu.java:12-76](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysMenu.java#L12-L76)
|
|
|
|
|
- [ResourceNode.java:16-84](file://crm-auth/src/main/java/com/crm/auth/domain/dto/ResourceNode.java#L16-L84)
|
|
|
|
|
- [PermissionResolver.java:16-35](file://crm-auth/src/main/java/com/crm/auth/security/PermissionResolver.java#L16-L35)
|
|
|
|
|
- [PermissionGrant.java:23-67](file://crm-auth/src/main/java/com/crm/auth/security/PermissionGrant.java#L23-L67)
|
|
|
|
|
- [PermissionResolverImpl.java:42-139](file://crm-auth/src/main/java/com/crm/auth/security/PermissionResolverImpl.java#L42-L139)
|
|
|
|
|
- [ApiPermissionInterceptor.java:32-82](file://crm-auth/src/main/java/com/crm/auth/security/ApiPermissionInterceptor.java#L32-L82)
|
|
|
|
|
- [ApiPermissionCache.java:25-65](file://crm-auth/src/main/java/com/crm/auth/security/ApiPermissionCache.java#L25-L65)
|
|
|
|
|
- [SystemController.java:36-44](file://crm-auth/src/main/java/com/crm/auth/controller/SystemController.java#L36-L44)
|
|
|
|
|
|
|
|
|
|
## 架构总览
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
下图展示认证与权限在请求链路中的关键交互:从JWT鉴权到权限校验、再到数据权限注入与SQL改写,以及新增的动态API权限拦截。
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
sequenceDiagram
|
|
|
|
|
participant Client as "客户端"
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
participant Filter as "JwtAuthenticationFilter"
|
|
|
|
|
participant Interceptor as "ApiPermissionInterceptor"
|
|
|
|
|
participant Resolver as "PermissionResolver"
|
|
|
|
|
participant Grant as "PermissionGrant"
|
|
|
|
|
participant Controller as "SystemController"
|
|
|
|
|
participant DB as "数据库"
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
Client->>Filter : "HTTP 请求 (带JWT)"
|
|
|
|
|
Filter->>Filter : "验证Token"
|
|
|
|
|
Filter->>Interceptor : "API权限拦截检查"
|
|
|
|
|
Interceptor->>Cache : "获取API权限规则"
|
|
|
|
|
Cache-->>Interceptor : "返回规则列表"
|
|
|
|
|
Interceptor->>Interceptor : "AntPathMatcher匹配"
|
|
|
|
|
Interceptor-->>Filter : "权限检查通过"
|
|
|
|
|
Filter->>Resolver : "调用权限解析器"
|
|
|
|
|
Resolver->>DB : "查询用户角色和权限"
|
|
|
|
|
DB-->>Resolver : "返回权限数据"
|
|
|
|
|
Resolver-->>Filter : "返回PermissionGrant"
|
|
|
|
|
Filter->>Filter : "设置Security上下文"
|
|
|
|
|
Controller->>Resolver : "获取菜单树"
|
|
|
|
|
Resolver->>DB : "查询可见菜单"
|
|
|
|
|
DB-->>Resolver : "返回菜单数据"
|
|
|
|
|
Resolver-->>Controller : "返回菜单树"
|
|
|
|
|
Controller-->>Client : "响应菜单数据"
|
|
|
|
|
```
|
|
|
|
|
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
**更新** 新的架构中,JwtAuthenticationFilter直接使用PermissionResolver进行权限解析,通过PermissionGrant封装完整的权限信息。新增的ApiPermissionInterceptor在JWT过滤器之后执行,提供URL级别的权限控制。SystemController也直接使用PermissionResolver获取菜单树,简化了调用链路。
|
|
|
|
|
|
|
|
|
|
图表来源
|
|
|
|
|
- [SecurityConfig.java:1-200](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java#L1-L200)
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
- [JwtAuthenticationFilter.java:32-56](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java#L32-L56)
|
|
|
|
|
- [ApiPermissionInterceptor.java:38-80](file://crm-auth/src/main/java/com/crm/auth/security/ApiPermissionInterceptor.java#L38-L80)
|
|
|
|
|
- [PermissionResolver.java:16-35](file://crm-auth/src/main/java/com/crm/auth/security/PermissionResolver.java#L16-L35)
|
|
|
|
|
- [SystemController.java:40-44](file://crm-auth/src/main/java/com/crm/auth/controller/SystemController.java#L40-L44)
|
|
|
|
|
|
|
|
|
|
## 详细组件分析
|
|
|
|
|
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
### 权限解析三组件架构
|
|
|
|
|
**重构** 权限解析引擎已重构为清晰的三组件架构:
|
|
|
|
|
|
|
|
|
|
#### PermissionResolver接口
|
|
|
|
|
定义了权限解析的核心抽象:
|
|
|
|
|
- `resolve(Long userId)`:解析用户的数据可见性与全部授权码
|
|
|
|
|
- `visibleMenuTree(Long userId)`:获取用户可见的菜单树
|
|
|
|
|
|
|
|
|
|
#### PermissionGrant值对象
|
|
|
|
|
不可变的权限解析结果封装:
|
|
|
|
|
- `DataVisibility visibility`:数据可见性信息
|
|
|
|
|
- `Set<String> permCodes`:权限码并集(button节点且status=enabled)
|
|
|
|
|
- `Set<String> roleCodes`:角色编码集合
|
|
|
|
|
- `asAuthorities()`:合成Spring Security authorities
|
|
|
|
|
|
|
|
|
|
#### PermissionResolverImpl实现
|
|
|
|
|
具体的权限解析逻辑实现:
|
|
|
|
|
- 共享查询链:用户→角色→授权→资源
|
|
|
|
|
- 多角色权限合并:取最宽档可见性
|
|
|
|
|
- 权限码并集:仅包含button节点且启用状态的perms
|
|
|
|
|
- 菜单树构建:过滤button节点并按sort排序
|
|
|
|
|
|
|
|
|
|
```mermaid
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
classDiagram
|
|
|
|
|
class PermissionResolver {
|
|
|
|
|
+resolve(userId) PermissionGrant
|
|
|
|
|
+visibleMenuTree(userId) SysMenu[]
|
|
|
|
|
}
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
class PermissionGrant {
|
|
|
|
|
+DataVisibility visibility
|
|
|
|
|
+Set~String~ permCodes
|
|
|
|
|
+Set~String~ roleCodes
|
|
|
|
|
+asAuthorities() SimpleGrantedAuthority[]
|
|
|
|
|
}
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
class PermissionResolverImpl {
|
|
|
|
|
-SysUserRoleMapper sysUserRoleMapper
|
|
|
|
|
-SysRoleMapper sysRoleMapper
|
|
|
|
|
-SysRoleMenuMapper sysRoleMenuMapper
|
|
|
|
|
-SysMenuMapper sysMenuMapper
|
|
|
|
|
-AuthUserMapper authUserMapper
|
|
|
|
|
-DeptTreeCache deptTreeCache
|
|
|
|
|
-SysUserDeptMapper sysUserDeptMapper
|
|
|
|
|
+resolve(userId) PermissionGrant
|
|
|
|
|
+visibleMenuTree(userId) SysMenu[]
|
|
|
|
|
}
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
PermissionResolver <|.. PermissionResolverImpl
|
|
|
|
|
PermissionResolverImpl --> PermissionGrant : 返回
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**更新** 新的三组件架构提供了清晰的职责分离,PermissionResolver接口定义了明确的契约,PermissionGrant作为不可变值对象确保数据安全,PermissionResolverImpl专注于权限解析逻辑的实现。
|
|
|
|
|
|
|
|
|
|
图表来源
|
|
|
|
|
- [PermissionResolver.java:16-35](file://crm-auth/src/main/java/com/crm/auth/security/PermissionResolver.java#L16-L35)
|
|
|
|
|
- [PermissionGrant.java:23-67](file://crm-auth/src/main/java/com/crm/auth/security/PermissionGrant.java#L23-L67)
|
|
|
|
|
- [PermissionResolverImpl.java:42-139](file://crm-auth/src/main/java/com/crm/auth/security/PermissionResolverImpl.java#L42-L139)
|
|
|
|
|
|
|
|
|
|
### 动态API权限拦截系统(新增)
|
|
|
|
|
**新增** 动态API权限拦截系统基于HandlerInterceptor实现URL级别的权限控制:
|
|
|
|
|
|
|
|
|
|
#### ApiPermissionInterceptor
|
|
|
|
|
HandlerInterceptor实现,负责URL模式匹配和权限校验:
|
|
|
|
|
- **fail-open策略**:未匹配任何注册规则时放行请求
|
|
|
|
|
- **AntPathMatcher匹配**:支持*单层通配和**多层通配
|
|
|
|
|
- **权限检查**:从SecurityContext读取用户authority集合进行匹配
|
|
|
|
|
- **403响应**:匹配到规则但用户无对应权限时返回403
|
|
|
|
|
|
|
|
|
|
#### ApiPermissionCache
|
|
|
|
|
基于Caffeine的进程内缓存,懒加载API权限规则:
|
|
|
|
|
- **单key缓存**:存储整份规则列表,避免频繁重建
|
|
|
|
|
- **懒加载机制**:首次访问时从数据库加载已启用的button节点
|
|
|
|
|
- **主动失效**:资源树变更后调用invalidate()清空缓存
|
|
|
|
|
- **规则过滤**:仅加载menuType=BUTTON且status='enabled'且有apiUrl的节点
|
|
|
|
|
|
|
|
|
|
#### ApiPermissionRule
|
|
|
|
|
简单的record类,记录API权限规则映射:
|
|
|
|
|
- **pattern**:Ant风格的URL模式
|
|
|
|
|
- **perms**:对应的权限码
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
flowchart TD
|
|
|
|
|
Start(["HTTP请求进入"]) --> GetRules["从缓存获取规则"]
|
|
|
|
|
GetRules --> MatchCheck{"是否有匹配规则?"}
|
|
|
|
|
MatchCheck --> |否| Pass["放行请求"]
|
|
|
|
|
MatchCheck --> |是| CheckPerm["检查用户权限"]
|
|
|
|
|
CheckPerm --> HasPerm{"用户有权限?"}
|
|
|
|
|
HasPerm --> |是| Pass
|
|
|
|
|
HasPerm --> |否| Deny["返回403"]
|
|
|
|
|
Pass --> End(["继续处理"])
|
|
|
|
|
Deny --> End
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**更新** 动态API权限拦截系统提供了灵活的URL级别权限控制,通过Caffeine缓存保证性能,fail-open策略确保向后兼容性。
|
|
|
|
|
|
|
|
|
|
图表来源
|
|
|
|
|
- [ApiPermissionInterceptor.java:38-80](file://crm-auth/src/main/java/com/crm/auth/security/ApiPermissionInterceptor.java#L38-L80)
|
|
|
|
|
- [ApiPermissionCache.java:37-63](file://crm-auth/src/main/java/com/crm/auth/security/ApiPermissionCache.java#L37-L63)
|
|
|
|
|
- [ApiPermissionRule.java:9](file://crm-auth/src/main/java/com/crm/auth/security/ApiPermissionRule.java#L9)
|
|
|
|
|
|
|
|
|
|
### WebMvcConfig拦截器注册
|
|
|
|
|
**新增** WebMvcConfig配置类负责注册API权限拦截器:
|
|
|
|
|
|
|
|
|
|
- **拦截器注册**:将ApiPermissionInterceptor添加到MVC拦截器链
|
|
|
|
|
- **路径匹配**:仅拦截/api/**路径的请求
|
|
|
|
|
- **执行顺序**:在Spring Security(JWT过滤器)之后、Controller之前执行
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
flowchart TD
|
|
|
|
|
Start(["请求进入"]) --> JwtFilter["JWT过滤器"]
|
|
|
|
|
JwtFilter --> ApiInterceptor["API权限拦截器"]
|
|
|
|
|
ApiInterceptor --> Controller["业务控制器"]
|
|
|
|
|
Controller --> Response["返回响应"]
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**更新** 拦截器的注册确保了权限检查的执行顺序,先进行JWT认证,再进行API权限检查,最后执行业务逻辑。
|
|
|
|
|
|
|
|
|
|
图表来源
|
|
|
|
|
- [WebMvcConfig.java:19-23](file://crm-auth/src/main/java/com/crm/auth/config/WebMvcConfig.java#L19-L23)
|
|
|
|
|
|
|
|
|
|
### JwtAuthenticationFilter集成新架构
|
|
|
|
|
**更新** JwtAuthenticationFilter已集成新的PermissionResolver:
|
|
|
|
|
|
|
|
|
|
- **fail-closed安全原则**:权限解析失败即拒绝请求
|
|
|
|
|
- **一次解析完成**:通过PermissionResolver.resolve()一次性获取所有权限信息
|
|
|
|
|
- **自动上下文装载**:将DataVisibility装载到DataVisibilityContext
|
|
|
|
|
- **Spring Security集成**:通过PermissionGrant.asAuthorities()生成authorities
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
flowchart TD
|
|
|
|
|
Start(["进入过滤器"]) --> TokenCheck{"Token有效?"}
|
|
|
|
|
TokenCheck --> |否| Next["继续过滤器链"]
|
|
|
|
|
TokenCheck --> |是| ResolvePerm["调用PermissionResolver.resolve()"]
|
|
|
|
|
ResolvePerm --> LoadContext["装载DataVisibility到上下文"]
|
|
|
|
|
LoadContext --> CreateAuth["创建UsernamePasswordAuthenticationToken"]
|
|
|
|
|
CreateAuth --> SetContext["设置到SecurityContextHolder"]
|
|
|
|
|
SetContext --> Next
|
|
|
|
|
Next --> End(["结束"])
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**更新** 新的实现遵循fail-closed原则,权限解析失败时直接让请求失败,不存在部分成功的状态。通过PermissionGrant统一处理权限码和角色编码,简化了Spring Security的集成。
|
|
|
|
|
|
|
|
|
|
图表来源
|
|
|
|
|
- [JwtAuthenticationFilter.java:32-56](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java#L32-L56)
|
|
|
|
|
|
|
|
|
|
### SystemController集成新架构
|
|
|
|
|
**更新** SystemController已集成新的PermissionResolver:
|
|
|
|
|
|
|
|
|
|
- **菜单树获取**:通过permissionResolver.visibleMenuTree(userId)直接获取菜单树
|
|
|
|
|
- **简化调用**:无需复杂的Service层调用,直接通过接口获取数据
|
|
|
|
|
- **类型安全**:返回类型为List<SysMenu>,保证类型安全
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
flowchart TD
|
|
|
|
|
Start(["菜单树请求"]) --> GetUserId["获取当前用户ID"]
|
|
|
|
|
GetUserId --> CallResolver["调用PermissionResolver.visibleMenuTree()"]
|
|
|
|
|
CallResolver --> QueryRoles["查询用户角色"]
|
|
|
|
|
QueryRoles --> QueryMenus["查询角色授权的菜单"]
|
|
|
|
|
QueryMenus --> FilterVisible["过滤可见菜单"]
|
|
|
|
|
FilterVisible --> BuildTree["构建菜单树"]
|
|
|
|
|
BuildTree --> Return["返回菜单树"]
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**更新** SystemController现在直接使用PermissionResolver接口,简化了菜单树的获取逻辑,提高了代码的可维护性和测试性。
|
|
|
|
|
|
|
|
|
|
图表来源
|
|
|
|
|
- [SystemController.java:40-44](file://crm-auth/src/main/java/com/crm/auth/controller/SystemController.java#L40-L44)
|
|
|
|
|
|
|
|
|
|
### 认证流程重构(AuthServiceImpl)
|
|
|
|
|
**更新** AuthServiceImpl进行了重大重构,优化了第三方登录流程和事务处理:
|
|
|
|
|
|
|
|
|
|
#### 主要改进
|
|
|
|
|
- **事务分离**:DB写入在事务中完成,Redis token写入在事务外执行,避免脏数据问题
|
|
|
|
|
- **组织准入预校验**:仅在首登注册前触发钉钉组织通讯录校验,减少HTTP调用开销
|
|
|
|
|
- **身份定位优化**:统一的locateUser方法供只读探测和登录定位共用,避免逻辑漂移
|
|
|
|
|
- **孤儿身份处理**:自动重定向指向已删除用户的身份绑定到新注册用户
|
|
|
|
|
|
|
|
|
|
#### 登录流程
|
|
|
|
|
1. **前置校验**:验证authCode非空
|
|
|
|
|
2. **三方用户信息获取**:通过clientFactory获取对应平台的用户信息
|
|
|
|
|
3. **组织准入预校验**:仅本地无匹配用户时触发
|
|
|
|
|
4. **事务内登录逻辑**:定位用户 + 校验状态 + 刷新登录时间
|
|
|
|
|
5. **签发token**:在事务外执行,失败不影响DB数据
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
flowchart TD
|
|
|
|
|
Start(["登录请求"]) --> Validate["验证authCode"]
|
|
|
|
|
Validate --> GetUserInfo["获取三方用户信息"]
|
|
|
|
|
GetUserInfo --> PreCheck{"本地有匹配用户?"}
|
|
|
|
|
PreCheck --> |是| SkipOrgCheck["跳过组织校验"]
|
|
|
|
|
PreCheck --> |否| OrgCheck["组织准入预校验"]
|
|
|
|
|
SkipOrgCheck --> DoLogin["事务内登录逻辑"]
|
|
|
|
|
OrgCheck --> DoLogin
|
|
|
|
|
DoLogin --> LocateUser["定位用户"]
|
|
|
|
|
LocateUser --> CheckEnabled{"用户是否启用?"}
|
|
|
|
|
CheckEnabled --> |否| ThrowError["抛出禁用错误"]
|
|
|
|
|
CheckEnabled --> |是| UpdateLoginTime["刷新登录时间"]
|
|
|
|
|
UpdateLoginTime --> CreateToken["签发token"]
|
|
|
|
|
CreateToken --> ReturnResult["返回登录结果"]
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**更新** 重构后的认证流程更加健壮,事务处理避免了脏数据,组织准入预校验提升了性能,身份定位逻辑更加清晰。
|
|
|
|
|
|
|
|
|
|
图表来源
|
|
|
|
|
- [AuthServiceImpl.java:64-93](file://crm-auth/src/main/java/com/crm/auth/service/impl/AuthServiceImpl.java#L64-L93)
|
|
|
|
|
- [AuthServiceImpl.java:98-111](file://crm-auth/src/main/java/com/crm/auth/service/impl/AuthServiceImpl.java#L98-L111)
|
|
|
|
|
- [AuthServiceImpl.java:117-139](file://crm-auth/src/main/java/com/crm/auth/service/impl/AuthServiceImpl.java#L117-L139)
|
|
|
|
|
|
|
|
|
|
### 三层资源层级结构设计
|
|
|
|
|
系统现在支持完整的三层资源层级结构,通过MenuType枚举定义了目录、菜单、按钮三种资源类型:
|
|
|
|
|
|
|
|
|
|
- **目录(CATALOG)**:作为收纳容器,不承载页面,只能挂menu子节点
|
|
|
|
|
- **菜单(MENU)**:可导航的页面,只能挂button子节点
|
|
|
|
|
- **按钮(BUTTON)**:叶子节点,不可再挂子节点,承载权限码和接口映射
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
classDiagram
|
|
|
|
|
class MenuType {
|
|
|
|
|
+CATALOG : MenuType
|
|
|
|
|
+MENU : MenuType
|
|
|
|
|
+BUTTON : MenuType
|
|
|
|
|
+fromCode(code) : MenuType
|
|
|
|
|
+isLegalChild(parent, child) : boolean
|
|
|
|
|
}
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
class SysMenu {
|
|
|
|
|
+Long parentId
|
|
|
|
|
+String menuName
|
|
|
|
|
+Integer menuType
|
|
|
|
|
+String path
|
|
|
|
|
+String component
|
|
|
|
|
+String icon
|
|
|
|
|
+Integer sort
|
|
|
|
|
+Boolean visible
|
|
|
|
|
+String description
|
|
|
|
|
+String perms
|
|
|
|
|
+String denyBehavior
|
|
|
|
|
+String status
|
|
|
|
|
+String apiUrl
|
|
|
|
|
+SysMenu[] children
|
|
|
|
|
}
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
class ResourceNode {
|
|
|
|
|
+Long id
|
|
|
|
|
+Long parentId
|
|
|
|
|
+String name
|
|
|
|
|
+MenuType type
|
|
|
|
|
+Integer sort
|
|
|
|
|
+String description
|
|
|
|
|
+String route
|
|
|
|
|
+String perms
|
|
|
|
|
+String denyBehavior
|
|
|
|
|
+String apiUrl
|
|
|
|
|
+String status
|
|
|
|
|
+String icon
|
|
|
|
|
+ResourceNode[] children
|
|
|
|
|
+fromEntity(entity) : ResourceNode
|
|
|
|
|
+toEntity() : SysMenu
|
|
|
|
|
}
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
MenuType <|-- SysMenu
|
|
|
|
|
SysMenu <..> ResourceNode : 双向转换
|
|
|
|
|
```
|
|
|
|
|
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
**更新** 三层资源层级结构在PermissionResolverImpl中得到了充分利用,visibleMenuTree方法会过滤掉button类型的菜单,只返回catalog和menu类型的菜单树。
|
|
|
|
|
|
|
|
|
|
图表来源
|
|
|
|
|
- [MenuType.java:12-52](file://crm-auth/src/main/java/com/crm/auth/domain/enums/MenuType.java#L12-L52)
|
|
|
|
|
- [SysMenu.java:12-76](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysMenu.java#L12-L76)
|
|
|
|
|
- [ResourceNode.java:16-84](file://crm-auth/src/main/java/com/crm/auth/domain/dto/ResourceNode.java#L16-L84)
|
|
|
|
|
|
|
|
|
|
### SysMenu实体增强设计
|
|
|
|
|
SysMenu实体经过大幅增强,现在支持按钮级别的细粒度权限控制:
|
|
|
|
|
|
|
|
|
|
- **基础字段**:parentId、menuName、menuType、path、component、icon、sort、visible
|
|
|
|
|
- **按钮级权限字段**:description(描述/备注)、perms(权限码)、denyBehavior(拒绝行为)、status(权限点状态)、apiUrl(接口URL)
|
|
|
|
|
- **树形结构支持**:children字段用于TreeUtils构建树时填充
|
|
|
|
|
|
|
|
|
|
**更新** SysMenu实体现在具备完整的按钮级权限控制能力,包括详细的权限描述、权限码、前端行为和API映射。
|
|
|
|
|
|
|
|
|
|
章节来源
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
- [SysMenu.java:12-76](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysMenu.java#L12-L76)
|
|
|
|
|
|
|
|
|
|
### ResourceNode DTO层次结构支持
|
|
|
|
|
ResourceNode DTO现在支持完整的层次结构,包含children字段:
|
|
|
|
|
|
|
|
|
|
- **层次结构字段**:`List<ResourceNode> children` - 子节点列表,仅在listAll()返回时填充
|
|
|
|
|
- **双向转换方法**:
|
|
|
|
|
- `fromEntity方法`:将SysMenu实体转换为ResourceNode DTO
|
|
|
|
|
- `toEntity方法`:将ResourceNode DTO转换回SysMenu实体
|
|
|
|
|
- **字段映射**:自动处理name↔menuName、route↔path、type↔menuType等字段映射
|
|
|
|
|
|
|
|
|
|
**更新** ResourceNode DTO现在支持层次结构,简化了前后端数据交互,提供了灵活的DTO转换机制和完整的树形数据支持。
|
|
|
|
|
|
|
|
|
|
章节来源
|
|
|
|
|
- [ResourceNode.java:16-84](file://crm-auth/src/main/java/com/crm/auth/domain/dto/ResourceNode.java#L16-L84)
|
|
|
|
|
|
|
|
|
|
### 统一资源树管理系统
|
|
|
|
|
完整的资源树管理系统,包含控制器、服务和接口,遵循全局接口契约:
|
|
|
|
|
|
|
|
|
|
#### ResourceController
|
|
|
|
|
提供标准化的RESTful API接口,采用显式动作后缀设计:
|
|
|
|
|
- `GET /api/resources/list`:**获取全量资源树(返回嵌套层次结构)**
|
|
|
|
|
- `POST /api/resources/saveOrUpdate`:新增或编辑节点
|
|
|
|
|
- `POST /api/resources/delete`:删除节点
|
|
|
|
|
- `POST /api/resources/icon/upload`:图标上传
|
|
|
|
|
|
|
|
|
|
#### ResourceServiceImpl
|
|
|
|
|
实现完整的业务逻辑:
|
|
|
|
|
- **层级约束验证**:确保父子关系的合法性,使用MenuType.isLegalChild()进行统一验证
|
|
|
|
|
- **字段必填校验**:根据不同类型验证必填字段
|
|
|
|
|
- **级联清理**:删除时自动清理角色授权引用
|
|
|
|
|
- **图标上传**:支持多种格式的图标文件上传
|
|
|
|
|
- **树形结构构建**:使用TreeUtils构建真正的层次结构
|
|
|
|
|
- **缓存失效**:保存和删除操作后调用apiPermissionCache.invalidate()
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
flowchart TD
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
Start(["保存资源节点"]) --> Validate["参数校验"]
|
|
|
|
|
Validate --> TypeCheck{"检查节点类型"}
|
|
|
|
|
TypeCheck --> |目录| CatalogRule["目录规则验证"]
|
|
|
|
|
TypeCheck --> |菜单| MenuRule["菜单规则验证"]
|
|
|
|
|
TypeCheck --> |按钮| ButtonRule["按钮规则验证"]
|
|
|
|
|
CatalogRule --> HierarchyCheck["层级约束检查"]
|
|
|
|
|
MenuRule --> HierarchyCheck
|
|
|
|
|
ButtonRule --> HierarchyCheck
|
|
|
|
|
HierarchyCheck --> ApplyMapping["DTO→Entity映射"]
|
|
|
|
|
ApplyMapping --> Save["保存至数据库"]
|
|
|
|
|
Save --> InvalidateCache["失效API权限缓存"]
|
|
|
|
|
InvalidateCache --> Return["返回ResourceNode"]
|
|
|
|
|
```
|
|
|
|
|
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
**更新** 资源树管理系统提供了完善的CRUD操作和严格的业务规则验证。validateHierarchy方法现在使用MenuType.isLegalChild()进行层级验证,避免了硬编码的魔术数字,提高了代码的可维护性和可读性。新增的缓存失效机制确保权限规则实时更新。
|
|
|
|
|
|
|
|
|
|
图表来源
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
- [ResourceController.java:1-56](file://crm-auth/src/main/java/com/crm/auth/controller/ResourceController.java#L1-56)
|
|
|
|
|
- [ResourceServiceImpl.java:55-97](file://crm-auth/src/main/java/com/crm/auth/service/impl/ResourceServiceImpl.java#L55-L97)
|
|
|
|
|
- [IResourceService.java:1-26](file://crm-auth/src/main/java/com/crm/auth/service/IResourceService.java#L1-L26)
|
|
|
|
|
|
|
|
|
|
### 数据权限范围控制(DataScopeEnum 与拦截器)
|
|
|
|
|
- 数据权限类型
|
|
|
|
|
- 全部数据、本部门数据、本部门及子部门数据、仅本人数据等
|
|
|
|
|
- 注解驱动
|
|
|
|
|
- 在方法上使用 @DataScope 指定数据范围与目标表
|
|
|
|
|
- 拦截与SQL改写
|
|
|
|
|
- DataScopeInterceptor 读取上下文中的数据权限范围
|
|
|
|
|
- DataScopeTables 维护表与列的映射关系
|
|
|
|
|
- 通过 MyBatis Plus 的 SQL 注入器自动追加 WHERE 条件
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
sequenceDiagram
|
|
|
|
|
participant Controller as "业务控制器"
|
|
|
|
|
participant Interceptor as "DataScopeInterceptor"
|
|
|
|
|
participant Helper as "DataScopeHelper"
|
|
|
|
|
participant Tables as "DataScopeTables"
|
|
|
|
|
participant MP as "MyBatisPlus注入器"
|
|
|
|
|
participant DB as "数据库"
|
|
|
|
|
Controller->>Interceptor : "进入受保护方法"
|
|
|
|
|
Interceptor->>Helper : "解析@DataScope参数"
|
|
|
|
|
Helper->>Tables : "查找表/列映射"
|
|
|
|
|
Tables-->>Helper : "返回映射信息"
|
|
|
|
|
Helper-->>MP : "生成数据权限WHERE片段"
|
|
|
|
|
MP-->>DB : "执行带限制的SQL"
|
|
|
|
|
DB-->>Controller : "返回受限结果"
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
图表来源
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
- [DataScope.java:1-200](file://crm-base/src/main/java/com/crm/base/annotation/DataScope.java#L1-L200)
|
|
|
|
|
- [DataScopeInterceptor.java:1-200](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java#L1-L200)
|
|
|
|
|
- [DataScopeTables.java:1-200](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeTables.java#L1-L200)
|
|
|
|
|
- [DataScopeHelper.java:1-200](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java#L1-L200)
|
|
|
|
|
- [CrmSqlInjector.java:1-200](file://crm-base/src/main/java/com/crm/base/config/CrmSqlInjector.java#L1-L200)
|
|
|
|
|
|
|
|
|
|
章节来源
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
- [DataScopeEnum.java:1-19](file://crm-auth/src/main/java/com/crm/auth/domain/enums/DataScopeEnum.java#L1-L19)
|
|
|
|
|
- [DataScope.java:1-200](file://crm-base/src/main/java/com/crm/base/annotation/DataScope.java#L1-L200)
|
|
|
|
|
- [DataScopeInterceptor.java:1-200](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java#L1-L200)
|
|
|
|
|
- [DataScopeTables.java:1-200](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeTables.java#L1-L200)
|
|
|
|
|
- [DataScopeHelper.java:1-200](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java#L1-L200)
|
|
|
|
|
- [CrmSqlInjector.java:1-200](file://crm-base/src/main/java/com/crm/base/config/CrmSqlInjector.java#L1-L200)
|
|
|
|
|
|
|
|
|
|
### 认证与安全配置(SecurityConfig、JwtAuthenticationFilter、TokenService)
|
|
|
|
|
- SecurityConfig:定义URL白名单、授权规则、跨域与异常处理器
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
- JwtAuthenticationFilter:解析JWT,填充认证上下文,集成新的PermissionResolver
|
|
|
|
|
- TokenService:生成、刷新、注销令牌,维护会话状态
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
classDiagram
|
|
|
|
|
class SecurityConfig {
|
|
|
|
|
+configure(http) void
|
|
|
|
|
+cors() CorsConfigurationSource
|
|
|
|
|
+exceptionHandler() SecurityExceptionHandlers
|
|
|
|
|
}
|
|
|
|
|
class JwtAuthenticationFilter {
|
|
|
|
|
+doFilter(request, response, chain) void
|
|
|
|
|
+parseToken(request) String
|
|
|
|
|
+setContext(token) void
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
+permissionResolver : PermissionResolver
|
|
|
|
|
}
|
|
|
|
|
class TokenService {
|
|
|
|
|
+createToken(user) String
|
|
|
|
|
+refreshToken(token) String
|
|
|
|
|
+logout(token) void
|
|
|
|
|
+validate(token) boolean
|
|
|
|
|
}
|
|
|
|
|
SecurityConfig --> JwtAuthenticationFilter : "注册过滤器"
|
|
|
|
|
JwtAuthenticationFilter --> TokenService : "验证/解析令牌"
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
JwtAuthenticationFilter --> PermissionResolver : "权限解析"
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
图表来源
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
- [SecurityConfig.java:1-200](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java#L1-L200)
|
|
|
|
|
- [JwtAuthenticationFilter.java:1-66](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java#L1-L66)
|
|
|
|
|
- [TokenService.java:1-200](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java#L1-L200)
|
|
|
|
|
|
|
|
|
|
章节来源
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
- [SecurityConfig.java:1-200](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java#L1-L200)
|
|
|
|
|
- [JwtAuthenticationFilter.java:1-66](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java#L1-L66)
|
|
|
|
|
- [TokenService.java:1-200](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java#L1-L200)
|
|
|
|
|
|
|
|
|
|
### 权限注解使用与最佳实践
|
|
|
|
|
- 接口级权限控制
|
|
|
|
|
- 在需要权限校验的方法上标注权限标识(如菜单code或按钮标识)
|
|
|
|
|
- 结合白名单跳过敏感接口校验
|
|
|
|
|
- 数据权限注解
|
|
|
|
|
- 在查询方法上标注 @DataScope,指定范围类型与目标表
|
|
|
|
|
- 确保 DataScopeTables 中已配置对应表的列映射
|
|
|
|
|
- 注意事项
|
|
|
|
|
- 避免在事务内频繁切换数据权限上下文
|
|
|
|
|
- 合理设置缓存失效时机,保证权限变更后即时生效
|
|
|
|
|
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
**更新** 基于新的PermissionResolver架构,权限控制更加模块化和安全化,fail-closed原则确保了权限解析失败的请求会被拒绝。新增的ApiPermissionInterceptor提供了URL级别的权限控制,与注解方式互补使用。
|
|
|
|
|
|
|
|
|
|
章节来源
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
- [DataScope.java:1-200](file://crm-base/src/main/java/com/crm/base/annotation/DataScope.java#L1-L200)
|
|
|
|
|
- [DataScopeTables.java:1-200](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeTables.java#L1-L200)
|
|
|
|
|
- [PermissionResolver.java:16-35](file://crm-auth/src/main/java/com/crm/auth/security/PermissionResolver.java#L16-L35)
|
|
|
|
|
|
|
|
|
|
### 动态权限加载与缓存机制
|
|
|
|
|
- 动态加载
|
|
|
|
|
- 登录后根据用户角色拉取菜单树与按钮权限
|
|
|
|
|
- 将权限集合与菜单树写入缓存
|
|
|
|
|
- 缓存键设计
|
|
|
|
|
- 用户维度:user:{userId}:perms
|
|
|
|
|
- 角色维度:role:{roleId}:menuTree
|
|
|
|
|
- 缓存更新
|
|
|
|
|
- 角色/菜单变更触发失效
|
|
|
|
|
- 提供手动刷新接口供管理员使用
|
|
|
|
|
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
**更新** 新的PermissionResolverImpl实现了共享查询链优化,减少了重复查询,提高了性能表现。新增的ApiPermissionCache基于Caffeine提供进程内缓存,支持懒加载和主动失效。
|
|
|
|
|
|
|
|
|
|
章节来源
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
- [PermissionResolverImpl.java:118-139](file://crm-auth/src/main/java/com/crm/auth/security/PermissionResolverImpl.java#L118-L139)
|
|
|
|
|
- [ApiPermissionCache.java:37-63](file://crm-auth/src/main/java/com/crm/auth/security/ApiPermissionCache.java#L37-L63)
|
|
|
|
|
- [SysMenuServiceImpl.java:1-200](file://crm-auth/src/main/java/com/crm/auth/service/impl/SysMenuServiceImpl.java#L1-L200)
|
|
|
|
|
- [SysRoleServiceImpl.java:1-200](file://crm-auth/src/main/java/com/crm/auth/service/impl/SysRoleServiceImpl.java#L1-L200)
|
|
|
|
|
|
|
|
|
|
### 配置方法与初始化
|
|
|
|
|
- 权限配置
|
|
|
|
|
- PermissionConfig:集中管理权限相关开关与默认值
|
|
|
|
|
- 安全配置
|
|
|
|
|
- SecurityConfig:URL白名单、跨域、异常处理器
|
|
|
|
|
- 数据初始化
|
|
|
|
|
- DataInitializer:初始化默认角色、菜单、管理员账号等
|
|
|
|
|
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
**更新** DataInitializer现在支持三层资源层级结构的初始化,包括目录、菜单和按钮的完整权限体系。新增的WebMvcConfig负责注册API权限拦截器。
|
|
|
|
|
|
|
|
|
|
章节来源
|
|
|
|
|
- [PermissionConfig.java:1-200](file://crm-auth/src/main/java/com/crm/auth/config/PermissionConfig.java#L1-L200)
|
|
|
|
|
- [SecurityConfig.java:1-200](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java#L1-L200)
|
|
|
|
|
- [DataInitializer.java:1-76](file://crm-auth/src/main/java/com/crm/auth/config/DataInitializer.java#L1-L76)
|
|
|
|
|
- [WebMvcConfig.java:19-23](file://crm-auth/src/main/java/com/crm/auth/config/WebMvcConfig.java#L19-L23)
|
|
|
|
|
|
|
|
|
|
### 资源树层级约束验证机制
|
|
|
|
|
资源树的层级约束验证机制通过MenuType枚举和validateHierarchy方法实现:
|
|
|
|
|
|
|
|
|
|
- **根节点验证**:根节点不允许添加button类型
|
|
|
|
|
- **父节点类型检查**:确保父节点存在且类型有效
|
|
|
|
|
- **层级关系验证**:使用MenuType.isLegalChild()方法进行统一的层级关系验证
|
|
|
|
|
- **空值安全处理**:防止未知菜单类型导致的NullPointerException
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
flowchart TD
|
|
|
|
|
Start(["验证层级关系"]) --> RootCheck{"是否根节点?"}
|
|
|
|
|
RootCheck --> |是| RootRule["根节点规则检查"]
|
|
|
|
|
RootCheck --> |否| ParentCheck["父节点存在性检查"]
|
|
|
|
|
RootCheck --> |否| ParentTypeCheck["父节点类型检查"]
|
|
|
|
|
ParentTypeCheck --> UnknownType{"父节点类型是否已知?"}
|
|
|
|
|
UnknownType --> |否| Error["抛出未知类型错误"]
|
|
|
|
|
UnknownType --> |是| LegalCheck["使用MenuType.isLegalChild验证"]
|
|
|
|
|
LegalCheck --> Valid{"层级关系合法?"}
|
|
|
|
|
Valid --> |是| Success["验证通过"]
|
|
|
|
|
Valid --> |否| ErrorMsg["抛出具体错误消息"]
|
|
|
|
|
RootRule --> Success
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**更新** validateHierarchy方法现在完全依赖MenuType.isLegalChild()进行层级验证,消除了硬编码的魔术数字,提高了代码的可维护性和一致性。
|
|
|
|
|
|
|
|
|
|
图表来源
|
|
|
|
|
- [ResourceServiceImpl.java:174-202](file://crm-auth/src/main/java/com/crm/auth/service/impl/ResourceServiceImpl.java#L174-L202)
|
|
|
|
|
- [MenuType.java:37-51](file://crm-auth/src/main/java/com/crm/auth/domain/enums/MenuType.java#L37-L51)
|
|
|
|
|
|
|
|
|
|
章节来源
|
|
|
|
|
- [ResourceServiceImpl.java:174-202](file://crm-auth/src/main/java/com/crm/auth/service/impl/ResourceServiceImpl.java#L174-L202)
|
|
|
|
|
- [MenuType.java:37-51](file://crm-auth/src/main/java/com/crm/auth/domain/enums/MenuType.java#L37-L51)
|
|
|
|
|
|
|
|
|
|
### 路由路径处理逻辑改进
|
|
|
|
|
改进了路由路径处理逻辑,避免空字符串覆盖数据库值:
|
|
|
|
|
|
|
|
|
|
- **非空值覆盖原则**:只有当node.getRoute()为非空时才覆盖entity.getPath()
|
|
|
|
|
- **空串保留机制**:空字符串或空白字符不会覆盖数据库中已有的path值
|
|
|
|
|
- **编辑模式支持**:在编辑模式下,如果未提供route但数据库已有path则保持原值
|
|
|
|
|
|
|
|
|
|
这种改进确保了数据的一致性和完整性,避免了意外覆盖数据库中的有效数据。
|
|
|
|
|
|
|
|
|
|
章节来源
|
|
|
|
|
- [ResourceServiceImpl.java:243-246](file://crm-auth/src/main/java/com/crm/auth/service/impl/ResourceServiceImpl.java#L243-L246)
|
|
|
|
|
|
|
|
|
|
### API设计标准化
|
|
|
|
|
资源管理系统的API设计遵循全局接口契约,采用显式动作后缀模式:
|
|
|
|
|
|
|
|
|
|
- **GET /api/resources/list**:**获取全量资源树,返回嵌套层次结构**
|
|
|
|
|
- **POST /api/resources/saveOrUpdate**:新增或编辑节点,支持表单字段接收
|
|
|
|
|
- **POST /api/resources/delete**:删除节点,通过@RequestParam接收ID参数
|
|
|
|
|
- **POST /api/resources/icon/upload**:图标上传,支持MultipartFile文件处理
|
|
|
|
|
|
|
|
|
|
这种设计确保了与应用程序其他部分的API设计一致性,避免了传统RESTful约定的歧义。
|
|
|
|
|
|
|
|
|
|
**更新** ResourceController严格遵循全局接口契约,所有写操作都使用POST + 动作后缀的模式,提升了API的一致性和可预测性。
|
|
|
|
|
|
|
|
|
|
章节来源
|
|
|
|
|
- [ResourceController.java:1-56](file://crm-auth/src/main/java/com/crm/auth/controller/ResourceController.java#L1-56)
|
|
|
|
|
|
|
|
|
|
### 树形结构构建机制
|
|
|
|
|
基于TreeUtils的高效树形结构构建机制:
|
|
|
|
|
|
|
|
|
|
- **O(n)复杂度算法**:相比旧版O(n²)算法,性能显著提升
|
|
|
|
|
- **泛型支持**:支持Long/String等多种主键类型
|
|
|
|
|
- **灵活配置**:通过函数式接口支持自定义的getter/setter方法
|
|
|
|
|
- **智能分组**:按parentId分组后一次性挂载子节点
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
flowchart TD
|
|
|
|
|
Start(["开始构建树"]) --> EmptyCheck{"列表是否为空?"}
|
|
|
|
|
EmptyCheck --> |是| ReturnEmpty["返回空列表"]
|
|
|
|
|
EmptyCheck --> |否| IdCollection["收集所有节点ID"]
|
|
|
|
|
IdCollection --> GroupByParent["按parentId分组"]
|
|
|
|
|
GroupByParent --> MountChildren["挂载子节点"]
|
|
|
|
|
MountChildren --> IdentifyRoots["识别顶级节点"]
|
|
|
|
|
IdentifyRoots --> ReturnTree["返回树形结构"]
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**更新** TreeUtils工具类提供了高效的树形结构构建能力,PermissionResolverImpl中使用它来构建菜单树,ResourceServiceImpl中使用它来构建资源树。
|
|
|
|
|
|
|
|
|
|
图表来源
|
|
|
|
|
- [TreeUtils.java:36-71](file://crm-base/src/main/java/com/crm/base/utils/TreeUtils.java#L36-L71)
|
|
|
|
|
- [PermissionResolverImpl.java:115](file://crm-auth/src/main/java/com/crm/auth/security/PermissionResolverImpl.java#L115)
|
|
|
|
|
|
|
|
|
|
章节来源
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
- [TreeUtils.java:1-91](file://crm-base/src/main/java/com/crm/base/utils/TreeUtils.java#L1-L91)
|
|
|
|
|
- [PermissionResolverImpl.java:115](file://crm-auth/src/main/java/com/crm/auth/security/PermissionResolverImpl.java#L115)
|
|
|
|
|
|
|
|
|
|
## 依赖关系分析
|
|
|
|
|
- 模块依赖
|
|
|
|
|
- crm-auth 依赖 crm-base(异常、工具、数据可见性上下文)
|
|
|
|
|
- crm-app 依赖 crm-auth(作为应用入口)
|
|
|
|
|
- 组件耦合
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
- **PermissionResolverImpl** 依赖多个Mapper和DeptTreeCache
|
|
|
|
|
- **JwtAuthenticationFilter** 依赖PermissionResolver和TokenService
|
|
|
|
|
- **SystemController** 依赖PermissionResolver和其他服务
|
|
|
|
|
- **ApiPermissionInterceptor** 依赖ApiPermissionCache
|
|
|
|
|
- **ResourceServiceImpl** 依赖ApiPermissionCache进行缓存失效
|
|
|
|
|
- DataScopeInterceptor 依赖 DataScopeHelper 与 CrmSqlInjector
|
|
|
|
|
- SecurityConfig 依赖 JwtAuthenticationFilter 与异常处理器
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
graph LR
|
|
|
|
|
APP["crm-app"] --> AUTH["crm-auth"]
|
|
|
|
|
AUTH --> BASE["crm-base"]
|
|
|
|
|
AUTH --> |"依赖"| Mapper["Mapper层"]
|
|
|
|
|
AUTH --> |"依赖"| Service["Service层"]
|
|
|
|
|
Service --> |"依赖"| Mapper
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
ResourceController --> ResourceService
|
|
|
|
|
ResourceService --> SysMenuService
|
|
|
|
|
ResourceService --> FileApi
|
|
|
|
|
ResourceService --> ApiPermissionCache
|
|
|
|
|
JwtAuthenticationFilter --> PermissionResolver
|
|
|
|
|
PermissionResolver --> PermissionResolverImpl
|
|
|
|
|
SystemController --> PermissionResolver
|
|
|
|
|
ApiPermissionInterceptor --> ApiPermissionCache
|
|
|
|
|
```
|
|
|
|
|
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
**更新** 新的架构中,PermissionResolverImpl解耦了具体的权限解析逻辑,JwtAuthenticationFilter和SystemController都通过PermissionResolver接口进行依赖,降低了耦合度。新增的ApiPermissionInterceptor依赖ApiPermissionCache,ResourceServiceImpl通过ApiPermissionCache实现缓存失效。
|
|
|
|
|
|
|
|
|
|
图表来源
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
- [CrmAppApplication.java:1-200](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java#L1-L200)
|
|
|
|
|
- [AuthApplication.java:1-200](file://crm-auth/src/main/java/com/crm/auth/AuthApplication.java#L1-L200)
|
|
|
|
|
|
|
|
|
|
章节来源
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
- [CrmAppApplication.java:1-200](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java#L1-L200)
|
|
|
|
|
- [AuthApplication.java:1-200](file://crm-auth/src/main/java/com/crm/auth/AuthApplication.java#L1-L200)
|
|
|
|
|
|
|
|
|
|
## 性能考虑
|
|
|
|
|
- 缓存优先
|
|
|
|
|
- 菜单树与权限集合应缓存至Redis,降低重复查询
|
|
|
|
|
- 合理设置过期时间与失效策略
|
|
|
|
|
- 批量与懒加载
|
|
|
|
|
- 菜单树构建尽量使用批量查询与懒加载
|
|
|
|
|
- 数据权限SQL优化
|
|
|
|
|
- 在 DataScopeTables 中精确映射表与列,避免全表扫描
|
|
|
|
|
- 为常用过滤列添加索引
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
- **新增** 资源树操作优化
|
|
|
|
|
- **TreeUtils提供O(n)复杂度的树构建算法,性能显著提升**
|
|
|
|
|
- **listAll()方法直接返回树形结构,减少前端处理开销**
|
|
|
|
|
- 图标上传异步处理提升用户体验
|
|
|
|
|
- 使用MenuType枚举提高类型检查效率
|
|
|
|
|
- **新增** API权限拦截优化
|
|
|
|
|
- **ApiPermissionCache基于Caffeine提供高性能进程内缓存**
|
|
|
|
|
- **懒加载机制避免不必要的数据库查询**
|
|
|
|
|
- **AntPathMatcher提供高效的URL模式匹配**
|
|
|
|
|
|
|
|
|
|
**更新** 新的PermissionResolverImpl实现了共享查询链优化,通过authorizedMenus()方法复用查询结果,减少了重复的数据库访问。同时,PermissionGrant作为不可变值对象,避免了不必要的对象创建和修改开销。新增的ApiPermissionCache基于Caffeine提供高性能缓存,懒加载机制确保只在首次访问时加载规则。
|
|
|
|
|
|
|
|
|
|
## 故障排查指南
|
|
|
|
|
- 常见错误
|
|
|
|
|
- 未认证或令牌过期:检查 JwtAuthenticationFilter 与 TokenService 配置
|
|
|
|
|
- 权限不足:确认角色-菜单授权是否正确,缓存是否及时失效
|
|
|
|
|
- 数据权限不生效:检查 @DataScope 注解与 DataScopeTables 映射
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
- **新增** 权限解析失败:检查PermissionResolverImpl的实现和依赖注入
|
|
|
|
|
- **新增** API权限拦截403:检查ApiPermissionCache规则和用户权限
|
|
|
|
|
- **新增** 认证流程异常:检查AuthServiceImpl的事务处理和第三方登录逻辑
|
|
|
|
|
- 定位步骤
|
|
|
|
|
- 查看全局异常处理器输出
|
|
|
|
|
- 开启调试日志,观察拦截器与SQL注入过程
|
|
|
|
|
- 核对缓存键与失效时机
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
- **新增** 检查PermissionResolverImpl中的权限解析逻辑
|
|
|
|
|
- **新增** 验证PermissionGrant的值对象构造和数据完整性
|
|
|
|
|
- **新增** 确认JwtAuthenticationFilter中的fail-closed逻辑
|
|
|
|
|
- **新增** 检查SystemController中PermissionResolver的使用
|
|
|
|
|
- **新增** 验证ApiPermissionInterceptor的URL匹配逻辑
|
|
|
|
|
- **新增** 检查ResourceServiceImpl中的缓存失效调用
|
|
|
|
|
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
**更新** 对于新的三组件架构,建议特别关注PermissionResolverImpl的依赖注入是否正确,PermissionGrant的构造参数是否完整,以及JwtAuthenticationFilter中的fail-closed逻辑是否正常工作。新增的API权限拦截系统需要检查ApiPermissionCache的规则加载和用户权限匹配。
|
|
|
|
|
|
|
|
|
|
章节来源
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
- [GlobalExceptionHandlerAdvice.java:1-200](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java#L1-L200)
|
|
|
|
|
- [JwtAuthenticationFilter.java:1-66](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java#L1-L66)
|
|
|
|
|
- [TokenService.java:1-200](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java#L1-L200)
|
|
|
|
|
- [DataScopeInterceptor.java:1-200](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java#L1-L200)
|
|
|
|
|
- [DataScopeTables.java:1-200](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeTables.java#L1-L200)
|
|
|
|
|
- [PermissionResolverImpl.java:1-140](file://crm-auth/src/main/java/com/crm/auth/security/PermissionResolverImpl.java#L1-L140)
|
|
|
|
|
- [ApiPermissionInterceptor.java:38-80](file://crm-auth/src/main/java/com/crm/auth/security/ApiPermissionInterceptor.java#L38-L80)
|
|
|
|
|
- [AuthServiceImpl.java:64-93](file://crm-auth/src/main/java/com/crm/auth/service/impl/AuthServiceImpl.java#L64-L93)
|
|
|
|
|
|
|
|
|
|
## 结论
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
本权限管理系统以RBAC为核心,结合注解驱动的数据权限控制与拦截器实现的SQL改写,形成完整的权限校验与数据隔离方案。**通过本次重构,系统实现了PermissionResolver三组件架构,包括PermissionResolver接口、PermissionGrant不可变值对象和PermissionResolverImpl实现类,显著提升了权限解析的模块化设计和安全性。**
|
|
|
|
|
|
|
|
|
|
**最重要的改进是新的三组件架构采用了fail-closed安全原则,确保权限解析失败的请求会被拒绝;PermissionGrant作为不可变值对象保证了数据的一致性和线程安全;PermissionResolverImpl实现了共享查询链优化,减少了重复查询开销。** 通过JwtAuthenticationFilter和SystemController对PermissionResolver的统一使用,简化了权限解析的调用方式,提高了代码的可维护性和测试性。
|
|
|
|
|
|
|
|
|
|
**新增的动态API权限拦截系统通过ApiPermissionInterceptor和ApiPermissionCache提供了URL级别的权限控制,基于Caffeine缓存保证性能,fail-open策略确保向后兼容性。** 资源树变更时自动触发缓存失效,确保权限规则实时更新。
|
|
|
|
|
|
|
|
|
|
**改进的认证流程重构优化了事务处理,避免了脏数据问题,组织准入预校验提升了性能,身份定位逻辑更加清晰。** 新的架构还充分利用了三层资源层级结构(目录-菜单-按钮),在visibleMenuTree方法中正确过滤button类型的菜单,只返回catalog和menu类型的菜单树。TreeUtils工具类的O(n)算法相比之前的O(n²)算法有显著的性能提升。通过对PermissionResolverImpl中authorizedMenus方法的优化,实现了用户→角色→授权→资源的共享查询链,进一步提升了性能表现。
|
|
|
|
|
|
|
|
|
|
通过合理的缓存策略与配置化开关,可在保障安全性的同时提升性能与可维护性。建议在生产环境严格管理权限变更与缓存失效,确保权限一致性与实时性。
|
|
|
|
|
|
|
|
|
|
## 附录
|
|
|
|
|
- 术语
|
|
|
|
|
- RBAC:基于角色的访问控制
|
|
|
|
|
- 数据权限:基于用户所属组织或范围的查询限制
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
- fail-closed:失败关闭原则,权限解析失败即拒绝请求
|
|
|
|
|
- fail-open:失败开放原则,未匹配规则时放行请求
|
|
|
|
|
- 不可变值对象:一旦创建就不能修改的对象
|
|
|
|
|
- AntPathMatcher:Spring提供的URL模式匹配器
|
|
|
|
|
- 参考
|
feat(auth): role management — ancestor completion, CRUD, permission assignment, cascade delete (ADR-0012)
Implements ADR-0005 (backend ancestor completion) and ADR-0012 (role management
architecture) across 5 tracer-bullet tickets:
- ISysMenuService.getAncestorIds: batch query full table, in-memory parentId
traversal, returns complete ancestor set (ADR-0005)
- SysRole.builtin field + DataInitializer idempotent refactor + 5 button
permission seeds (crm:role:list/detail/save/delete/assign) bound to ADMIN
- RoleController (/api/roles/*): page, saveOrUpdate, detail, assign-resources,
delete — pure hasAuthority, POST + action suffix, form params
- SysRoleServiceImpl.saveRole: roleCode uniqueness, builtin protection,
dataScope 1-4 range, create can't set builtin=true
- assignResources: calls getAncestorIds for ancestor completion, then
full replacement (delete + insert) of sys_role_menu
- getRoleDetail: returns RoleDetailVO with basic info + resourceIds
- deleteRoleCascade: cleans sys_role_menu + sys_user_role, builtin rejection,
three-table transaction
- SystemController: all role endpoints removed, unused deps cleaned
- Dead code removed: assignMenus, getMenuIdsByRoleId (superseded by
assignResources, getRoleDetail)
- H2 test schemas updated with builtin column
- 150 tests pass (16 new in SysRoleServiceImplTest, 7 in SysMenuServiceImplTest)
1 month ago
|
|
|
- 实体与枚举:SysRole、SysMenu、DataScopeEnum、MenuType
|
|
|
|
|
- 数据传输对象:ResourceNode
|
|
|
|
|
- **新增** 权限解析三组件:PermissionResolver、PermissionGrant、PermissionResolverImpl
|
|
|
|
|
- **新增** 动态API权限拦截:ApiPermissionInterceptor、ApiPermissionCache、ApiPermissionRule
|
|
|
|
|
- 服务与拦截:DataScopeInterceptor、JwtAuthenticationFilter
|
|
|
|
|
- **新增** 系统集成:SystemController对PermissionResolver的使用
|
|
|
|
|
- 工具类:TreeUtils
|
|
|
|
|
- 配置与初始化:PermissionConfig、SecurityConfig、DataInitializer、WebMvcConfig
|
|
|
|
|
|
|
|
|
|
**更新** 重点关注新的PermissionResolver三组件架构,它们提供了更强大的权限解析能力和更好的模块化设计。PermissionGrant不可变值对象确保了数据安全,PermissionResolverImpl的共享查询链优化提升了性能。SystemController对PermissionResolver的直接使用简化了调用方式,提高了代码的可维护性。新增的ApiPermissionInterceptor和ApiPermissionCache提供了灵活的URL级别权限控制,AuthServiceImpl的重构优化了认证流程。
|