权限回收级联清理:管理员被回收权限后自动清理其直建员工的越权授权

- 保存管理员权限时,若其权限被回收,级联删除其直接创建的员工中超出
  该管理员当前有效范围的授权(创建时快照遗留的越权项)
- 只清理越权项,保留员工合法持有的其他授权;超级管理员不受此限制
This commit is contained in:
2026-09-04 00:16:18 +08:00
parent d0db577a9c
commit 92a7a2c478
2 changed files with 76 additions and 0 deletions
@@ -413,6 +413,43 @@ class PermissionMenuServiceTest {
.containsExactly(1L);
}
@Test
void adminPermissionRevocationCascadesToCreatedSubordinates() {
// 回收管理员的菜单权限后,其直接创建员工超出范围的授权必须级联删除。
// 生产场景:管理员 1000 的"去重数据汇总"被回收后,员工 1002 仍持有它。
PermissionMenuMapper menuMapper = mock(PermissionMenuMapper.class);
UserColumnPermissionMapper permissionMapper = mock(UserColumnPermissionMapper.class);
AdminUserMapper userMapper = mock(AdminUserMapper.class);
PermissionMenuService service = new PermissionMenuService(menuMapper, permissionMapper, userMapper);
// 超管操作员编辑管理员 10:管理员仅保留 id=1 的授权(回收 2)
AdminUserEntity operator = user(1L, "super_admin", 1);
AdminUserEntity target = user(10L, "admin", 1);
target.setCreatedById(1L);
AdminUserEntity subordinate = user(20L, "normal", 0);
subordinate.setCreatedById(10L);
when(userMapper.selectById(10L)).thenReturn(target);
when(menuMapper.selectCount(any())).thenReturn(1L);
when(menuMapper.selectOne(any())).thenReturn(null);
when(menuMapper.selectList(any())).thenReturn(List.of(
menu(1L, null, "admin", 1),
menu(2L, null, "admin", 2)));
// 管理员当前授权:1(新)+ 2(被回收前存在)
when(permissionMapper.selectByUserId(10L))
.thenReturn(List.of(grant(10L, 1L), grant(10L, 2L)));
// 员工 20 的授权:1(合法)+ 2(越权,应被级联删除)
when(permissionMapper.selectByUserId(20L))
.thenReturn(List.of(grant(20L, 1L), grant(20L, 2L)));
when(userMapper.selectList(any())).thenReturn(List.of(subordinate));
UserColumnPermissionUpdateRequest request = new UserColumnPermissionUpdateRequest();
request.setColumnIds(List.of(1L));
service.updateUserColumnPermissions(operator, 10L, request);
// 员工越权授权 2 必须被清除,合法授权 1 保留
verify(permissionMapper).deleteByUserIdAndColumnIds(20L, List.of(2L));
}
@Test
void replacementStoresOnlyDirectRequestedParentId() {
PermissionMenuMapper menuMapper = mock(PermissionMenuMapper.class);