505 lines
23 KiB
Java
505 lines
23 KiB
Java
package com.yunhai.userbase.service.impl;
|
||
|
||
import com.yunhai.userbase.entity.AppCategory;
|
||
import com.yunhai.userbase.entity.AppModule;
|
||
import com.yunhai.userbase.entity.ApplicationInfo;
|
||
import com.yunhai.userbase.entity.SysGroup;
|
||
import com.yunhai.userbase.entity.SysGroupAppRel;
|
||
import com.yunhai.userbase.entity.SysGroupModulePerm;
|
||
import com.yunhai.userbase.entity.SysUser;
|
||
import com.yunhai.userbase.entity.SysUserGroupRel;
|
||
import com.yunhai.userbase.enums.GroupTypeEnum;
|
||
import com.yunhai.userbase.enums.UserTypeEnum;
|
||
import com.yunhai.userbase.model.groupauthz.UserPermissionCategoryVo;
|
||
import com.yunhai.userbase.model.groupauthz.UserPermissionModuleVo;
|
||
import com.yunhai.userbase.repository.AppCategoryRepository;
|
||
import com.yunhai.userbase.repository.AppModuleRepository;
|
||
import com.yunhai.userbase.repository.ApplicationInfoRepository;
|
||
import com.yunhai.userbase.repository.SysAppRoleModuleRelRepository;
|
||
import com.yunhai.userbase.repository.SysAppRoleRepository;
|
||
import com.yunhai.userbase.repository.SysGroupAppRelRepository;
|
||
import com.yunhai.userbase.repository.SysGroupModulePermRepository;
|
||
import com.yunhai.userbase.repository.SysGroupRepository;
|
||
import com.yunhai.userbase.repository.SysUserAppRoleRelRepository;
|
||
import com.yunhai.userbase.repository.SysUserGroupRelRepository;
|
||
import com.yunhai.userbase.repository.SysUserRepository;
|
||
import org.junit.jupiter.api.BeforeEach;
|
||
import org.junit.jupiter.api.Test;
|
||
import org.mockito.InjectMocks;
|
||
import org.mockito.Mock;
|
||
import org.mockito.MockitoAnnotations;
|
||
|
||
import java.util.Arrays;
|
||
import java.util.Collections;
|
||
import java.util.LinkedHashSet;
|
||
import java.util.List;
|
||
import java.util.Optional;
|
||
import java.util.Set;
|
||
|
||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||
import static org.mockito.ArgumentMatchers.any;
|
||
import static org.mockito.ArgumentMatchers.anyList;
|
||
import static org.mockito.Mockito.when;
|
||
|
||
/**
|
||
* GroupAuthzService 权限计算单元测试。
|
||
* 重点验证「就近原则 + 子组继承闸门」:沿组的祖先链向上,取<b>最近</b>的有显式模块配置的组作为该应用唯一权限来源,
|
||
* 只返回该来源组的模块集合(不向上合并更远的祖先);且<b>来源组若为祖先,必须勾选子组继承(inheritFlag=true)才下放</b>
|
||
* (修复「子组只勾1个却继承学校全部」「返回3个而非最近祖先的2个」「父级未勾子组继承仍被继承」三类 bug)。
|
||
*/
|
||
class GroupAuthzServiceTest {
|
||
|
||
@InjectMocks
|
||
private GroupAuthzService groupAuthzService;
|
||
|
||
@Mock
|
||
private SysGroupAppRelRepository sysGroupAppRelRepository;
|
||
@Mock
|
||
private SysGroupModulePermRepository sysGroupModulePermRepository;
|
||
@Mock
|
||
private SysGroupRepository sysGroupRepository;
|
||
@Mock
|
||
private ApplicationInfoRepository applicationInfoRepository;
|
||
@Mock
|
||
private AppCategoryRepository appCategoryRepository;
|
||
@Mock
|
||
private AppModuleRepository appModuleRepository;
|
||
@Mock
|
||
private SysUserGroupRelRepository sysUserGroupRelRepository;
|
||
@Mock
|
||
private SysUserRepository sysUserRepository;
|
||
@Mock
|
||
private SysAppRoleRepository sysAppRoleRepository;
|
||
@Mock
|
||
private SysAppRoleModuleRelRepository sysAppRoleModuleRelRepository;
|
||
@Mock
|
||
private SysUserAppRoleRelRepository sysUserAppRoleRelRepository;
|
||
|
||
@BeforeEach
|
||
void setUp() {
|
||
MockitoAnnotations.openMocks(this);
|
||
initGroups();
|
||
}
|
||
|
||
/**
|
||
* 构造一组固定层级:
|
||
* 5 教育云中心(根)
|
||
* └─ 27 信阳教育局
|
||
* └─ 16 云海中学(学校)
|
||
* ├─ 29 教师组
|
||
* │ └─ 31 英语组
|
||
* └─ 30 学生组
|
||
*/
|
||
private void initGroups() {
|
||
when(sysGroupRepository.findAll()).thenReturn(Arrays.asList(
|
||
group(5, "教育云中心", 0, GroupTypeEnum.NORMAL_GROUP),
|
||
group(27, "信阳教育局", 5, GroupTypeEnum.AREA_GROUP),
|
||
group(16, "云海中学", 27, GroupTypeEnum.SCHOOL_GROUP),
|
||
group(28, "信阳高级中学", 27, GroupTypeEnum.SCHOOL_GROUP),
|
||
group(29, "教师组", 16, GroupTypeEnum.TEACHER_GROUP),
|
||
group(30, "学生组", 16, GroupTypeEnum.STUDENT_GROUP),
|
||
group(31, "英语组", 29, GroupTypeEnum.NORMAL_GROUP)
|
||
));
|
||
}
|
||
|
||
@Test
|
||
void findUserPermissionTree_whenSelfGroupConfiguredApp_shouldNotInheritAncestorModules() {
|
||
// user 1 仅属于英语组 31
|
||
when(sysUserRepository.findById(1)).thenReturn(Optional.of(user(1, UserTypeEnum.NORMAL)));
|
||
when(sysUserGroupRelRepository.findByUserId(1)).thenReturn(
|
||
Collections.singletonList(rel(1, 31, 1)));
|
||
|
||
// 祖先链上的应用开通:只有学校 16 开通了 100003
|
||
when(sysGroupAppRelRepository.findByGroupIdIn(anyList())).thenAnswer(inv -> {
|
||
List<Integer> ids = inv.getArgument(0);
|
||
if (ids.contains(16)) {
|
||
return Collections.singletonList(appRel(16, 100003));
|
||
}
|
||
return Collections.emptyList();
|
||
});
|
||
|
||
ApplicationInfo app = new ApplicationInfo();
|
||
app.setId(100003);
|
||
app.setName("通知公告");
|
||
app.setAppKey(100002);
|
||
app.setCategoryId(2);
|
||
when(applicationInfoRepository.findAllById(any())).thenReturn(Collections.singletonList(app));
|
||
|
||
AppCategory category = new AppCategory();
|
||
category.setId(2);
|
||
category.setName("家校互动");
|
||
category.setSortNo(2);
|
||
when(appCategoryRepository.findAllByOrderBySortNoAsc()).thenReturn(Collections.singletonList(category));
|
||
|
||
AppModule m8 = module(8, 100003, "已收通知");
|
||
AppModule m9 = module(9, 100003, "已发通知");
|
||
AppModule m10 = module(10, 100003, "全部通知");
|
||
when(appModuleRepository.findByAppIdIn(anyList())).thenReturn(Arrays.asList(m8, m9, m10));
|
||
|
||
// 权限记录:英语组 31 只有模块 8;学校 16 有 8/9/10 且都允许继承
|
||
when(sysGroupModulePermRepository.findByModuleIdInAndGroupIdIn(anyList(), anyList()))
|
||
.thenReturn(Arrays.asList(
|
||
perm(31, 8, true),
|
||
perm(16, 8, true),
|
||
perm(16, 9, true),
|
||
perm(16, 10, true)));
|
||
|
||
List<UserPermissionCategoryVo> result = groupAuthzService.findUserPermissionTree(31, 1);
|
||
|
||
assertEquals(1, result.size(), "应只有一个分类");
|
||
assertEquals("家校互动", result.get(0).getName());
|
||
assertEquals(1, result.get(0).getApps().size(), "应只有一个应用");
|
||
assertEquals(1, result.get(0).getApps().get(0).getModules().size(), "只应返回模块 8");
|
||
assertEquals(8, result.get(0).getApps().get(0).getModules().get(0).getId());
|
||
}
|
||
|
||
@Test
|
||
void findUserPermissionTree_whenSelfGroupNotConfiguredApp_shouldInheritFromSchool() {
|
||
// user 2 仅属于学生组 30,学生组没有配置通知公告应用的任何模块
|
||
when(sysUserRepository.findById(2)).thenReturn(Optional.of(user(2, UserTypeEnum.NORMAL)));
|
||
when(sysUserGroupRelRepository.findByUserId(2)).thenReturn(
|
||
Collections.singletonList(rel(2, 30, 1)));
|
||
|
||
when(sysGroupAppRelRepository.findByGroupIdIn(anyList())).thenAnswer(inv -> {
|
||
List<Integer> ids = inv.getArgument(0);
|
||
if (ids.contains(16)) {
|
||
return Collections.singletonList(appRel(16, 100003));
|
||
}
|
||
return Collections.emptyList();
|
||
});
|
||
|
||
ApplicationInfo app = new ApplicationInfo();
|
||
app.setId(100003);
|
||
app.setName("通知公告");
|
||
app.setAppKey(100002);
|
||
app.setCategoryId(2);
|
||
when(applicationInfoRepository.findAllById(any())).thenReturn(Collections.singletonList(app));
|
||
|
||
AppCategory category = new AppCategory();
|
||
category.setId(2);
|
||
category.setName("家校互动");
|
||
category.setSortNo(2);
|
||
when(appCategoryRepository.findAllByOrderBySortNoAsc()).thenReturn(Collections.singletonList(category));
|
||
|
||
AppModule m8 = module(8, 100003, "已收通知");
|
||
AppModule m9 = module(9, 100003, "已发通知");
|
||
AppModule m10 = module(10, 100003, "全部通知");
|
||
when(appModuleRepository.findByAppIdIn(anyList())).thenReturn(Arrays.asList(m8, m9, m10));
|
||
|
||
// 学校 16 三个模块都开放继承;学生组 30 没有任何记录
|
||
when(sysGroupModulePermRepository.findByModuleIdInAndGroupIdIn(anyList(), anyList()))
|
||
.thenReturn(Arrays.asList(
|
||
perm(16, 8, true),
|
||
perm(16, 9, true),
|
||
perm(16, 10, true)));
|
||
|
||
List<UserPermissionCategoryVo> result = groupAuthzService.findUserPermissionTree(30, 2);
|
||
|
||
assertEquals(3, result.get(0).getApps().get(0).getModules().size(),
|
||
"未配置应用时,应继承学校的全部 3 个模块");
|
||
}
|
||
|
||
@Test
|
||
void hasModulePermission_whenSelfGroupConfiguredApp_onlySelfRecordsCount() {
|
||
AppModule m8 = module(8, 100003, "已收通知");
|
||
AppModule m9 = module(9, 100003, "已发通知");
|
||
AppModule m10 = module(10, 100003, "全部通知");
|
||
when(appModuleRepository.findById(9)).thenReturn(Optional.of(m9));
|
||
when(sysUserAppRoleRelRepository.findByUserId(1)).thenReturn(Collections.emptyList());
|
||
|
||
when(sysUserGroupRelRepository.findByUserId(1)).thenReturn(
|
||
Collections.singletonList(rel(1, 31, 1)));
|
||
|
||
when(sysGroupAppRelRepository.existsByGroupIdAndAppId(31, 100003)).thenReturn(true);
|
||
when(appModuleRepository.findByAppIdIn(Collections.singletonList(100003))).thenReturn(Arrays.asList(m8, m9, m10));
|
||
|
||
// 英语组 31 配置了应用 100003(模块 8);学校 16 有模块 9(但 31 已就近接管,不应继承)
|
||
when(sysGroupModulePermRepository.findByModuleIdInAndGroupIdIn(
|
||
Arrays.asList(8, 9, 10), Arrays.asList(31, 29, 16, 27, 5)))
|
||
.thenReturn(Arrays.asList(perm(31, 8, true), perm(16, 9, true)));
|
||
|
||
assertFalse(groupAuthzService.hasModulePermission(1, 9),
|
||
"英语组已配置通知公告应用(就近接管),不应再继承学校的已发通知模块");
|
||
}
|
||
|
||
@Test
|
||
void hasModulePermission_whenSelfGroupHasTheModule_shouldReturnTrue() {
|
||
AppModule m8 = module(8, 100003, "已收通知");
|
||
AppModule m9 = module(9, 100003, "已发通知");
|
||
AppModule m10 = module(10, 100003, "全部通知");
|
||
when(appModuleRepository.findById(8)).thenReturn(Optional.of(m8));
|
||
when(sysUserAppRoleRelRepository.findByUserId(1)).thenReturn(Collections.emptyList());
|
||
|
||
when(sysUserGroupRelRepository.findByUserId(1)).thenReturn(
|
||
Collections.singletonList(rel(1, 31, 1)));
|
||
|
||
when(sysGroupAppRelRepository.existsByGroupIdAndAppId(31, 100003)).thenReturn(true);
|
||
when(appModuleRepository.findByAppIdIn(Collections.singletonList(100003))).thenReturn(Arrays.asList(m8, m9, m10));
|
||
|
||
when(sysGroupModulePermRepository.findByModuleIdInAndGroupIdIn(
|
||
Arrays.asList(8, 9, 10), Arrays.asList(31, 29, 16, 27, 5)))
|
||
.thenReturn(Arrays.asList(perm(31, 8, true), perm(16, 8, true)));
|
||
|
||
assertTrue(groupAuthzService.hasModulePermission(1, 8),
|
||
"英语组自身已配置模块 8,应返回 true");
|
||
}
|
||
|
||
@Test
|
||
void findUserPermissionTree_whenSelfGroupEmpty_shouldUseNearestAncestorTeacherGroup() {
|
||
// user 1 仅属于英语组 31;英语组(31)无任何模块授权,教师组(29)有模块9/10,学校(16)有8/9/10
|
||
when(sysUserRepository.findById(1)).thenReturn(Optional.of(user(1, UserTypeEnum.NORMAL)));
|
||
when(sysUserGroupRelRepository.findByUserId(1)).thenReturn(
|
||
Collections.singletonList(rel(1, 31, 1)));
|
||
|
||
when(sysGroupAppRelRepository.findByGroupIdIn(anyList())).thenAnswer(inv -> {
|
||
List<Integer> ids = inv.getArgument(0);
|
||
if (ids.contains(16)) {
|
||
return Collections.singletonList(appRel(16, 100003));
|
||
}
|
||
return Collections.emptyList();
|
||
});
|
||
|
||
ApplicationInfo app = new ApplicationInfo();
|
||
app.setId(100003);
|
||
app.setName("通知公告");
|
||
app.setAppKey(100002);
|
||
app.setCategoryId(2);
|
||
when(applicationInfoRepository.findAllById(any())).thenReturn(Collections.singletonList(app));
|
||
|
||
AppCategory category = new AppCategory();
|
||
category.setId(2);
|
||
category.setName("家校互动");
|
||
category.setSortNo(2);
|
||
when(appCategoryRepository.findAllByOrderBySortNoAsc()).thenReturn(Collections.singletonList(category));
|
||
|
||
AppModule m8 = module(8, 100003, "已收通知");
|
||
AppModule m9 = module(9, 100003, "已发通知");
|
||
AppModule m10 = module(10, 100003, "全部通知");
|
||
when(appModuleRepository.findByAppIdIn(anyList())).thenReturn(Arrays.asList(m8, m9, m10));
|
||
|
||
// 英语组31空;教师组29有9/10;学校16有8/9/10
|
||
when(sysGroupModulePermRepository.findByModuleIdInAndGroupIdIn(anyList(), anyList()))
|
||
.thenReturn(Arrays.asList(
|
||
perm(29, 9, true),
|
||
perm(29, 10, true),
|
||
perm(16, 8, true),
|
||
perm(16, 9, true),
|
||
perm(16, 10, true)));
|
||
|
||
List<UserPermissionCategoryVo> result = groupAuthzService.findUserPermissionTree(31, 1);
|
||
|
||
assertEquals(1, result.size(), "应只有一个分类");
|
||
assertEquals(1, result.get(0).getApps().size(), "应只有一个应用");
|
||
assertEquals(2, result.get(0).getApps().get(0).getModules().size(),
|
||
"本组空→取最近教师组29的2个模块,不应合并学校组多出的模块8");
|
||
Set<Integer> moduleIds = new LinkedHashSet<>();
|
||
for (UserPermissionModuleVo mv : result.get(0).getApps().get(0).getModules()) {
|
||
moduleIds.add(mv.getId());
|
||
}
|
||
assertTrue(moduleIds.contains(9) && moduleIds.contains(10) && moduleIds.size() == 2,
|
||
"应仅含模块 9 和 10,不含学校组多出的模块 8");
|
||
}
|
||
|
||
@Test
|
||
void findUserPermissionTree_whenNearestAncestorAllNotInheritable_returnsEmpty() {
|
||
// 英语组31空;教师组29有9/10但 inheritFlag=false(未勾子组继承);学校16有8/9/10
|
||
when(sysUserRepository.findById(1)).thenReturn(Optional.of(user(1, UserTypeEnum.NORMAL)));
|
||
when(sysUserGroupRelRepository.findByUserId(1)).thenReturn(
|
||
Collections.singletonList(rel(1, 31, 1)));
|
||
|
||
when(sysGroupAppRelRepository.findByGroupIdIn(anyList())).thenAnswer(inv -> {
|
||
List<Integer> ids = inv.getArgument(0);
|
||
if (ids.contains(16)) {
|
||
return Collections.singletonList(appRel(16, 100003));
|
||
}
|
||
return Collections.emptyList();
|
||
});
|
||
|
||
ApplicationInfo app = new ApplicationInfo();
|
||
app.setId(100003);
|
||
app.setName("通知公告");
|
||
app.setAppKey(100002);
|
||
app.setCategoryId(2);
|
||
when(applicationInfoRepository.findAllById(any())).thenReturn(Collections.singletonList(app));
|
||
|
||
AppCategory category = new AppCategory();
|
||
category.setId(2);
|
||
category.setName("家校互动");
|
||
category.setSortNo(2);
|
||
when(appCategoryRepository.findAllByOrderBySortNoAsc()).thenReturn(Collections.singletonList(category));
|
||
|
||
AppModule m8 = module(8, 100003, "已收通知");
|
||
AppModule m9 = module(9, 100003, "已发通知");
|
||
AppModule m10 = module(10, 100003, "全部通知");
|
||
when(appModuleRepository.findByAppIdIn(anyList())).thenReturn(Arrays.asList(m8, m9, m10));
|
||
|
||
// 教师组29(最近来源)所有模块 inheritFlag=false;即便学校16开放,也不应被继承
|
||
when(sysGroupModulePermRepository.findByModuleIdInAndGroupIdIn(anyList(), anyList()))
|
||
.thenReturn(Arrays.asList(
|
||
perm(29, 9, false),
|
||
perm(29, 10, false),
|
||
perm(16, 8, true),
|
||
perm(16, 9, true),
|
||
perm(16, 10, true)));
|
||
|
||
List<UserPermissionCategoryVo> result = groupAuthzService.findUserPermissionTree(31, 1);
|
||
|
||
// 最近来源(教师组)对该应用所有模块都未勾子组继承 → 本组该应用为空,不应合并学校组
|
||
assertTrue(result.isEmpty(),
|
||
"最近祖先(教师组)未勾子组继承,应返回空,不应从学校组继承任何模块");
|
||
}
|
||
|
||
@Test
|
||
void findUserPermissionTree_whenNearestAncestorPartiallyInheritable_returnsOnlyInheritable() {
|
||
// 英语组31空;教师组29有9(inheritFlag=true)/10(inheritFlag=false);学校16有8/9/10
|
||
when(sysUserRepository.findById(1)).thenReturn(Optional.of(user(1, UserTypeEnum.NORMAL)));
|
||
when(sysUserGroupRelRepository.findByUserId(1)).thenReturn(
|
||
Collections.singletonList(rel(1, 31, 1)));
|
||
|
||
when(sysGroupAppRelRepository.findByGroupIdIn(anyList())).thenAnswer(inv -> {
|
||
List<Integer> ids = inv.getArgument(0);
|
||
if (ids.contains(16)) {
|
||
return Collections.singletonList(appRel(16, 100003));
|
||
}
|
||
return Collections.emptyList();
|
||
});
|
||
|
||
ApplicationInfo app = new ApplicationInfo();
|
||
app.setId(100003);
|
||
app.setName("通知公告");
|
||
app.setAppKey(100002);
|
||
app.setCategoryId(2);
|
||
when(applicationInfoRepository.findAllById(any())).thenReturn(Collections.singletonList(app));
|
||
|
||
AppCategory category = new AppCategory();
|
||
category.setId(2);
|
||
category.setName("家校互动");
|
||
category.setSortNo(2);
|
||
when(appCategoryRepository.findAllByOrderBySortNoAsc()).thenReturn(Collections.singletonList(category));
|
||
|
||
AppModule m8 = module(8, 100003, "已收通知");
|
||
AppModule m9 = module(9, 100003, "已发通知");
|
||
AppModule m10 = module(10, 100003, "全部通知");
|
||
when(appModuleRepository.findByAppIdIn(anyList())).thenReturn(Arrays.asList(m8, m9, m10));
|
||
|
||
when(sysGroupModulePermRepository.findByModuleIdInAndGroupIdIn(anyList(), anyList()))
|
||
.thenReturn(Arrays.asList(
|
||
perm(29, 9, true),
|
||
perm(29, 10, false),
|
||
perm(16, 8, true),
|
||
perm(16, 9, true),
|
||
perm(16, 10, true)));
|
||
|
||
List<UserPermissionCategoryVo> result = groupAuthzService.findUserPermissionTree(31, 1);
|
||
|
||
assertEquals(1, result.size(), "应只有一个分类");
|
||
assertEquals(1, result.get(0).getApps().size(), "应只有一个应用");
|
||
assertEquals(1, result.get(0).getApps().get(0).getModules().size(),
|
||
"最近来源(教师组)只有模块9勾了子组继承,应只返回模块9,模块10与学校组模块8均不继承");
|
||
assertEquals(9, result.get(0).getApps().get(0).getModules().get(0).getId());
|
||
}
|
||
|
||
@Test
|
||
void hasModulePermission_whenSelfGroupEmpty_nearestAncestorIsTeacherGroup() {
|
||
// 英语组31空,教师组29有9/10,学校16有8/9/10
|
||
AppModule m8 = module(8, 100003, "已收通知");
|
||
AppModule m9 = module(9, 100003, "已发通知");
|
||
AppModule m10 = module(10, 100003, "全部通知");
|
||
when(appModuleRepository.findById(8)).thenReturn(Optional.of(m8));
|
||
when(appModuleRepository.findById(9)).thenReturn(Optional.of(m9));
|
||
when(appModuleRepository.findById(10)).thenReturn(Optional.of(m10));
|
||
when(sysUserAppRoleRelRepository.findByUserId(1)).thenReturn(Collections.emptyList());
|
||
when(sysUserGroupRelRepository.findByUserId(1)).thenReturn(
|
||
Collections.singletonList(rel(1, 31, 1)));
|
||
when(sysGroupAppRelRepository.existsByGroupIdAndAppId(31, 100003)).thenReturn(true);
|
||
when(appModuleRepository.findByAppIdIn(Collections.singletonList(100003))).thenReturn(Arrays.asList(m8, m9, m10));
|
||
when(sysGroupModulePermRepository.findByModuleIdInAndGroupIdIn(
|
||
Arrays.asList(8, 9, 10), Arrays.asList(31, 29, 16, 27, 5)))
|
||
.thenReturn(Arrays.asList(
|
||
perm(29, 9, true), perm(29, 10, true),
|
||
perm(16, 8, true), perm(16, 9, true), perm(16, 10, true)));
|
||
|
||
assertFalse(groupAuthzService.hasModulePermission(1, 8),
|
||
"英语组为空→最近来源是教师组29,学校组多勾的模块8不应被继承");
|
||
assertTrue(groupAuthzService.hasModulePermission(1, 9),
|
||
"教师组29勾选的模块9应可访问");
|
||
assertTrue(groupAuthzService.hasModulePermission(1, 10),
|
||
"教师组29勾选的模块10应可访问");
|
||
}
|
||
|
||
@Test
|
||
void hasModulePermission_whenSuperAdmin_shouldReturnTrueRegardlessOfGroup() {
|
||
// 超级管理员:type=SUPER_ADMIN,且不归属任何组(超管通常不在任何组下)
|
||
when(sysUserRepository.findById(1)).thenReturn(Optional.of(user(1, UserTypeEnum.SUPER_ADMIN)));
|
||
when(sysUserGroupRelRepository.findByUserId(1)).thenReturn(Collections.emptyList());
|
||
|
||
assertTrue(groupAuthzService.hasModulePermission(1, 8),
|
||
"超级管理员应直接拥有全部模块权限,无需归属组/角色(修复「超管无组→返回false」的 bug)");
|
||
assertTrue(groupAuthzService.hasModulePermission(1, 100),
|
||
"超级管理员对任意模块都应返回 true");
|
||
}
|
||
|
||
// ===================== helper =====================
|
||
|
||
private SysGroup group(Integer id, String name, Integer parentId, GroupTypeEnum type) {
|
||
SysGroup g = new SysGroup();
|
||
g.setId(id);
|
||
g.setName(name);
|
||
g.setParentId(parentId);
|
||
g.setType(type);
|
||
return g;
|
||
}
|
||
|
||
private SysUser user(Integer id, UserTypeEnum type) {
|
||
SysUser u = new SysUser();
|
||
u.setId(id);
|
||
u.setType(type);
|
||
u.setAccount("u" + id);
|
||
u.setRealName("用户" + id);
|
||
return u;
|
||
}
|
||
|
||
private SysUserGroupRel rel(Integer userId, Integer groupId, Integer isMain) {
|
||
SysUserGroupRel r = new SysUserGroupRel();
|
||
r.setUserId(userId);
|
||
r.setGroupId(groupId);
|
||
r.setIsMain(isMain);
|
||
return r;
|
||
}
|
||
|
||
private SysGroupAppRel appRel(Integer groupId, Integer appId) {
|
||
SysGroupAppRel r = new SysGroupAppRel();
|
||
r.setGroupId(groupId);
|
||
r.setAppId(appId);
|
||
return r;
|
||
}
|
||
|
||
private SysGroupModulePerm perm(Integer groupId, Integer moduleId, boolean inherit) {
|
||
SysGroupModulePerm p = new SysGroupModulePerm();
|
||
p.setGroupId(groupId);
|
||
p.setModuleId(moduleId);
|
||
p.setInheritFlag(inherit);
|
||
return p;
|
||
}
|
||
|
||
private ApplicationInfo app(Integer id, String name, Integer categoryId) {
|
||
ApplicationInfo a = new ApplicationInfo();
|
||
a.setId(id);
|
||
a.setName(name);
|
||
a.setCategoryId(categoryId);
|
||
return a;
|
||
}
|
||
|
||
private AppModule module(Integer id, Integer appId, String name) {
|
||
AppModule m = new AppModule();
|
||
m.setId(id);
|
||
m.setAppId(appId);
|
||
m.setName(name);
|
||
m.setCustomId(String.valueOf(id));
|
||
m.setLevel(1);
|
||
return m;
|
||
}
|
||
}
|