feat(需求): ①创建/编辑用户菜单权限勾选父菜单自动全选子菜单(el-tree去check-strictly走父子联动,提交前压缩为最小直接授权集,父勾选时后代不重复落库) ②修复管理员勾选店铺数据菜单仍提示'无权查看店铺数据任务'——admin分区授权后若有效授权含店铺数据任务/重复检查菜单(含经'店铺管理'分组展开),自动补内部数据权限 admin_shop_data_crawl_task_data(镜像V84惯例只增不删,回收仍走超管数据范围授权UI)
This commit is contained in:
+159
@@ -623,6 +623,165 @@ class PermissionMenuServiceTest {
|
||||
assertThat(inserted.getValue().getColumnId()).isEqualTo(76L);
|
||||
}
|
||||
|
||||
@Test
|
||||
void adminScopedReplacementAutoGrantsShopDataPermissionForTaskMenu() {
|
||||
// 反馈:管理员勾了「店铺数据任务管理」菜单仍提示“无权查看店铺数据任务”。
|
||||
// 镜像 V84 惯例:admin 分区授权含店铺数据任务菜单时自动补内部数据权限。
|
||||
PermissionMenuMapper menuMapper = mock(PermissionMenuMapper.class);
|
||||
UserColumnPermissionMapper permissionMapper = mock(UserColumnPermissionMapper.class);
|
||||
AdminUserMapper userMapper = mock(AdminUserMapper.class);
|
||||
PermissionMenuService service = new PermissionMenuService(menuMapper, permissionMapper, userMapper);
|
||||
|
||||
PermissionMenuEntity taskMenu = menu(70L, null, "admin", 1);
|
||||
taskMenu.setColumnKey("admin_shop_data_crawl_tasks");
|
||||
PermissionMenuEntity duplicateCheckMenu = menu(71L, null, "admin", 2);
|
||||
duplicateCheckMenu.setColumnKey("admin_shop_data_duplicate_check");
|
||||
PermissionMenuEntity dataPermission = menu(76L, null, "internal", 0);
|
||||
dataPermission.setColumnKey("admin_shop_data_crawl_task_data");
|
||||
when(userMapper.selectById(9L)).thenReturn(user(9L, "super_admin", 1));
|
||||
when(menuMapper.selectList(any())).thenReturn(
|
||||
List.of(taskMenu, duplicateCheckMenu), List.of(taskMenu, duplicateCheckMenu));
|
||||
when(menuMapper.selectOne(any())).thenReturn(taskMenu, duplicateCheckMenu, dataPermission);
|
||||
when(permissionMapper.countByUserIdAndColumnId(any(), any())).thenReturn(0L);
|
||||
|
||||
UserColumnPermissionUpdateRequest request = new UserColumnPermissionUpdateRequest();
|
||||
request.setColumnIds(List.of(70L));
|
||||
service.updateUserColumnPermissions(null, 9L, request, PermissionMenuService.MENU_TYPE_ADMIN);
|
||||
|
||||
ArgumentCaptor<UserColumnPermissionEntity> captor = ArgumentCaptor.forClass(UserColumnPermissionEntity.class);
|
||||
verify(permissionMapper, times(2)).insert(captor.capture());
|
||||
assertThat(captor.getAllValues())
|
||||
.extracting(UserColumnPermissionEntity::getColumnId)
|
||||
.containsExactly(70L, 76L);
|
||||
}
|
||||
|
||||
@Test
|
||||
void adminScopedReplacementAutoGrantsShopDataPermissionViaGroup() {
|
||||
// 反馈场景:直接授权是「店铺管理」一级分组(勾选分组代表整组,前端联动分组全选)
|
||||
// 时,有效展开包含任务菜单,同样自动补内部数据权限。
|
||||
PermissionMenuMapper menuMapper = mock(PermissionMenuMapper.class);
|
||||
UserColumnPermissionMapper permissionMapper = mock(UserColumnPermissionMapper.class);
|
||||
AdminUserMapper userMapper = mock(AdminUserMapper.class);
|
||||
PermissionMenuService service = new PermissionMenuService(menuMapper, permissionMapper, userMapper);
|
||||
|
||||
PermissionMenuEntity group = menu(60L, null, "admin", 1);
|
||||
group.setColumnKey("admin_group_shop");
|
||||
PermissionMenuEntity taskMenu = menu(70L, 60L, "admin", 2);
|
||||
taskMenu.setColumnKey("admin_shop_data_crawl_tasks");
|
||||
PermissionMenuEntity dataPermission = menu(76L, null, "internal", 0);
|
||||
dataPermission.setColumnKey("admin_shop_data_crawl_task_data");
|
||||
when(userMapper.selectById(9L)).thenReturn(user(9L, "super_admin", 1));
|
||||
when(menuMapper.selectList(any())).thenReturn(List.of(group, taskMenu), List.of(group, taskMenu));
|
||||
when(menuMapper.selectOne(any())).thenReturn(taskMenu, null, dataPermission);
|
||||
when(permissionMapper.countByUserIdAndColumnId(any(), any())).thenReturn(0L);
|
||||
|
||||
UserColumnPermissionUpdateRequest request = new UserColumnPermissionUpdateRequest();
|
||||
request.setColumnIds(List.of(60L));
|
||||
service.updateUserColumnPermissions(null, 9L, request, PermissionMenuService.MENU_TYPE_ADMIN);
|
||||
|
||||
ArgumentCaptor<UserColumnPermissionEntity> captor = ArgumentCaptor.forClass(UserColumnPermissionEntity.class);
|
||||
verify(permissionMapper, times(2)).insert(captor.capture());
|
||||
assertThat(captor.getAllValues())
|
||||
.extracting(UserColumnPermissionEntity::getColumnId)
|
||||
.containsExactly(60L, 76L);
|
||||
}
|
||||
|
||||
@Test
|
||||
void adminScopedReplacementAutoGrantsShopDataPermissionForDuplicateCheckMenu() {
|
||||
// 只勾「店铺数据重复检查」菜单同样自动补数据权限(撞款监控接口要求同一内部数据权限)。
|
||||
PermissionMenuMapper menuMapper = mock(PermissionMenuMapper.class);
|
||||
UserColumnPermissionMapper permissionMapper = mock(UserColumnPermissionMapper.class);
|
||||
AdminUserMapper userMapper = mock(AdminUserMapper.class);
|
||||
PermissionMenuService service = new PermissionMenuService(menuMapper, permissionMapper, userMapper);
|
||||
|
||||
PermissionMenuEntity taskMenu = menu(70L, null, "admin", 1);
|
||||
taskMenu.setColumnKey("admin_shop_data_crawl_tasks");
|
||||
PermissionMenuEntity duplicateCheckMenu = menu(71L, null, "admin", 2);
|
||||
duplicateCheckMenu.setColumnKey("admin_shop_data_duplicate_check");
|
||||
PermissionMenuEntity dataPermission = menu(76L, null, "internal", 0);
|
||||
dataPermission.setColumnKey("admin_shop_data_crawl_task_data");
|
||||
when(userMapper.selectById(9L)).thenReturn(user(9L, "super_admin", 1));
|
||||
when(menuMapper.selectList(any())).thenReturn(
|
||||
List.of(taskMenu, duplicateCheckMenu), List.of(taskMenu, duplicateCheckMenu));
|
||||
when(menuMapper.selectOne(any())).thenReturn(taskMenu, duplicateCheckMenu, dataPermission);
|
||||
when(permissionMapper.countByUserIdAndColumnId(any(), any())).thenReturn(0L);
|
||||
|
||||
UserColumnPermissionUpdateRequest request = new UserColumnPermissionUpdateRequest();
|
||||
request.setColumnIds(List.of(71L));
|
||||
service.updateUserColumnPermissions(null, 9L, request, PermissionMenuService.MENU_TYPE_ADMIN);
|
||||
|
||||
ArgumentCaptor<UserColumnPermissionEntity> captor = ArgumentCaptor.forClass(UserColumnPermissionEntity.class);
|
||||
verify(permissionMapper, times(2)).insert(captor.capture());
|
||||
assertThat(captor.getAllValues())
|
||||
.extracting(UserColumnPermissionEntity::getColumnId)
|
||||
.containsExactly(71L, 76L);
|
||||
}
|
||||
|
||||
@Test
|
||||
void adminScopedReplacementDoesNotAutoGrantWithoutShopDataMenus() {
|
||||
// 无关菜单(如用户管理)不触发数据权限自动补,避免权限放大。
|
||||
PermissionMenuMapper menuMapper = mock(PermissionMenuMapper.class);
|
||||
UserColumnPermissionMapper permissionMapper = mock(UserColumnPermissionMapper.class);
|
||||
AdminUserMapper userMapper = mock(AdminUserMapper.class);
|
||||
PermissionMenuService service = new PermissionMenuService(menuMapper, permissionMapper, userMapper);
|
||||
|
||||
PermissionMenuEntity usersMenu = menu(10L, null, "admin", 1);
|
||||
when(userMapper.selectById(9L)).thenReturn(user(9L, "super_admin", 1));
|
||||
when(menuMapper.selectList(any())).thenReturn(List.of(usersMenu), List.of(usersMenu));
|
||||
when(menuMapper.selectOne(any())).thenReturn(null);
|
||||
|
||||
UserColumnPermissionUpdateRequest request = new UserColumnPermissionUpdateRequest();
|
||||
request.setColumnIds(List.of(10L));
|
||||
service.updateUserColumnPermissions(null, 9L, request, PermissionMenuService.MENU_TYPE_ADMIN);
|
||||
|
||||
ArgumentCaptor<UserColumnPermissionEntity> captor = ArgumentCaptor.forClass(UserColumnPermissionEntity.class);
|
||||
verify(permissionMapper).insert(captor.capture());
|
||||
assertThat(captor.getValue().getColumnId()).isEqualTo(10L);
|
||||
}
|
||||
|
||||
@Test
|
||||
void adminScopedReplacementKeepsExistingShopDataPermissionWithoutDuplicate() {
|
||||
// 用户已通过超管「数据范围授权」配过数据权限时不重复插入。
|
||||
PermissionMenuMapper menuMapper = mock(PermissionMenuMapper.class);
|
||||
UserColumnPermissionMapper permissionMapper = mock(UserColumnPermissionMapper.class);
|
||||
AdminUserMapper userMapper = mock(AdminUserMapper.class);
|
||||
PermissionMenuService service = new PermissionMenuService(menuMapper, permissionMapper, userMapper);
|
||||
|
||||
PermissionMenuEntity taskMenu = menu(70L, null, "admin", 1);
|
||||
taskMenu.setColumnKey("admin_shop_data_crawl_tasks");
|
||||
PermissionMenuEntity dataPermission = menu(76L, null, "internal", 0);
|
||||
dataPermission.setColumnKey("admin_shop_data_crawl_task_data");
|
||||
when(userMapper.selectById(9L)).thenReturn(user(9L, "super_admin", 1));
|
||||
when(menuMapper.selectList(any())).thenReturn(List.of(taskMenu), List.of(taskMenu));
|
||||
when(menuMapper.selectOne(any())).thenReturn(taskMenu, null, dataPermission);
|
||||
when(permissionMapper.countByUserIdAndColumnId(any(), any())).thenReturn(1L);
|
||||
|
||||
UserColumnPermissionUpdateRequest request = new UserColumnPermissionUpdateRequest();
|
||||
request.setColumnIds(List.of(70L));
|
||||
service.updateUserColumnPermissions(null, 9L, request, PermissionMenuService.MENU_TYPE_ADMIN);
|
||||
|
||||
verify(permissionMapper, times(1)).insert(any(UserColumnPermissionEntity.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void appScopedReplacementNeverAutoGrantsShopDataPermission() {
|
||||
// 客户端(app)分区授权不触发数据权限补发(数据权限属后台 admin 体系)。
|
||||
PermissionMenuMapper menuMapper = mock(PermissionMenuMapper.class);
|
||||
UserColumnPermissionMapper permissionMapper = mock(UserColumnPermissionMapper.class);
|
||||
AdminUserMapper userMapper = mock(AdminUserMapper.class);
|
||||
PermissionMenuService service = new PermissionMenuService(menuMapper, permissionMapper, userMapper);
|
||||
|
||||
when(userMapper.selectById(9L)).thenReturn(user(9L, "super_admin", 1));
|
||||
when(menuMapper.selectList(any())).thenReturn(List.of(menu(11L, null, "app", 1)));
|
||||
when(menuMapper.selectOne(any())).thenReturn(null);
|
||||
|
||||
UserColumnPermissionUpdateRequest request = new UserColumnPermissionUpdateRequest();
|
||||
request.setColumnIds(List.of(11L));
|
||||
service.updateUserColumnPermissions(null, 9L, request, PermissionMenuService.MENU_TYPE_APP);
|
||||
|
||||
verify(permissionMapper, times(1)).insert(any(UserColumnPermissionEntity.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void fullCatalogOrdersAppMenusBeforeAdminMenus() {
|
||||
PermissionMenuMapper menuMapper = mock(PermissionMenuMapper.class);
|
||||
|
||||
Reference in New Issue
Block a user