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
|
|
|
{
|
|
|
|
|
"scan": {
|
|
|
|
|
"controllerStyle": "spring",
|
|
|
|
|
"sourceRoots": ["crm-auth/src/main/java", "crm-file/src/main/java", "crm-lead/src/main/java", "crm-opportunity/src/main/java", "crm-rule/src/main/java", "crm-preference/src/main/java", "crm-dict/src/main/java", "crm-customer/src/main/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
|
|
|
},
|
|
|
|
|
"urlPattern": "/api/{module}/{resource}",
|
|
|
|
|
"grouping": "tag",
|
|
|
|
|
"menuBindings": {
|
|
|
|
|
"A2 线索管理/线索公海": { "viewType": "PUBLIC_POOL", "scopeKey": "lead.public_pool" },
|
|
|
|
|
"A2 线索管理/我的线索": { "viewType": "MY_LEAD", "scopeKey": "lead.my_lead" },
|
|
|
|
|
"A2 线索管理/我的关注": { "viewType": "MY_FOLLOW", "scopeKey": "lead.my_follow" },
|
|
|
|
|
"A2 线索管理/线索管理": { "viewType": "MANAGE", "scopeKey": "lead.manage" },
|
|
|
|
|
"A4 客户管理/客户公海": { "viewType": "pool", "scopeKey": "customer.pool" },
|
|
|
|
|
"A4 客户管理/客户总览": { "viewType": "overview", "scopeKey": "customer.overview" },
|
|
|
|
|
"A4 客户管理/我的客户": { "viewType": "mine", "scopeKey": "customer.mine" },
|
|
|
|
|
"A4 客户管理/客户交割": { "viewType": null, "scopeKey": null },
|
|
|
|
|
"A4 客户管理/联系人": { "viewType": null, "scopeKey": "contact.list" },
|
|
|
|
|
"A7 后台管理/客户管理设置": { "viewType": null, "scopeKey": null }
|
|
|
|
|
},
|
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
|
|
|
"envelope": {
|
|
|
|
|
"fields": ["code", "success", "message", "data"],
|
|
|
|
|
"successWhen": "success == true",
|
|
|
|
|
"pageWrapper": ["content", "total", "size", "current", "pages", "empty"]
|
|
|
|
|
},
|
|
|
|
|
"auth": {
|
|
|
|
|
"type": "bearer",
|
|
|
|
|
"header": "Authorization",
|
|
|
|
|
"prefix": "Bearer ",
|
|
|
|
|
"publicUrls": ["/api/auth/login/**"]
|
|
|
|
|
},
|
|
|
|
|
"params": {
|
|
|
|
|
"write": "form-urlencoded",
|
|
|
|
|
"read": "query",
|
|
|
|
|
"complexFields": "json-string-in-form"
|
|
|
|
|
},
|
|
|
|
|
"login": {
|
|
|
|
|
"method": "POST",
|
|
|
|
|
"url": "/api/auth/login/dingtalk",
|
|
|
|
|
"tokenPath": "data.token"
|
|
|
|
|
},
|
|
|
|
|
"naming": { "language": "zh" },
|
|
|
|
|
"contractDoc": "README.md",
|
|
|
|
|
"environments": { "local": "http://localhost:8080" }
|
|
|
|
|
}
|