diff --git a/src/main/java/com/yunhai/userbase/service/impl/GroupAuthzService.java b/src/main/java/com/yunhai/userbase/service/impl/GroupAuthzService.java index 9dddf0c..2922d5e 100644 --- a/src/main/java/com/yunhai/userbase/service/impl/GroupAuthzService.java +++ b/src/main/java/com/yunhai/userbase/service/impl/GroupAuthzService.java @@ -910,6 +910,26 @@ public class GroupAuthzService implements IGroupAuthzService { return null; } + /** + * 子组继承闸门:判定「来源组 authority 对 moduleId 的记录」是否对本组 selfGroupId 生效。 + * + *

规则(修复「父级未勾子组继承却仍被继承」的 bug): + * ① 来源组 == 本组:本组自身勾选的模块直接生效——{@code inheritFlag} 只约束是否下放到子组,不影响本组自己; + * ② 来源组为祖先(往上回溯得来):必须勾选了「子组继承」({@code inheritFlag=true}) 才会下放到本组, + * 否则该模块不继承。即「只过滤勾选了子组继承的模块;若来源组对该应用所有模块都没勾子组继承,则本组对该应用返回空」。 + */ + private boolean isPermEffectiveForSelf(Integer authority, Integer selfGroupId, + Map permMap) { + SysGroupModulePerm perm = (permMap == null) ? null : permMap.get(authority); + if (perm == null) { + return false; + } + if (authority.equals(selfGroupId)) { + return true; + } + return Boolean.TRUE.equals(perm.getInheritFlag()); + } + /** * 用户维度权限判定:用户对指定模块是否有权限(就近原则 + 学校截止 + 角色授权并集 + 超管兜底)。 * @@ -921,6 +941,10 @@ public class GroupAuthzService implements IGroupAuthzService { * ② 本组无配置(如英语组为空)→ 取最近的有配置祖先(如教师组)为来源,不再越级到更远的学校组; * ③ 来源组的模块集合即最终集合,更上层同应用模块(如学校组多勾的模块8)一律不合并。 * + *

子组继承闸门(修复「父级未勾子组继承仍被继承」的 bug):来源组若是本组,本组勾选的模块直接生效; + * 来源组若是祖先,必须该模块记录 {@code inheritFlag=true}(勾选子组继承)才下放到本组,否则不继承—— + * 即「只过滤勾选了子组继承的模块;若来源组对该应用所有模块都没勾子组继承,则本组对该应用返回空」。 + * *

学校截止:祖先链只查到第一个学校组(含)为止,不跨学校到教育局/根。 * *

其余:归属组需已开通该模块所属应用(双保险,防越权)。 @@ -947,8 +971,9 @@ public class GroupAuthzService implements IGroupAuthzService { if (authority == null) { continue; } - // 权限来源组对该模块有显式记录 → 许可;否则(来源组未勾此模块)不许可 - if (permMap != null && permMap.get(authority) != null) { + // 来源组对该模块有显式记录,且(来源是本组 或 来源是祖先且勾选了子组继承)→ 许可; + // 否则(来源组未勾此模块 / 祖先未开启子组继承)不许可。 + if (isPermEffectiveForSelf(authority, selfGroupId, permMap)) { return true; } } @@ -1233,7 +1258,7 @@ public class GroupAuthzService implements IGroupAuthzService { continue; } Map pm = modulePermMap.get(moduleId); - if (pm != null && pm.get(authority) != null) { + if (isPermEffectiveForSelf(authority, selfGroupId, pm)) { return true; } } diff --git a/src/test/java/com/yunhai/userbase/service/impl/GroupAuthzServiceTest.java b/src/test/java/com/yunhai/userbase/service/impl/GroupAuthzServiceTest.java new file mode 100644 index 0000000..b342f68 --- /dev/null +++ b/src/test/java/com/yunhai/userbase/service/impl/GroupAuthzServiceTest.java @@ -0,0 +1,492 @@ +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 权限计算单元测试。 + * 重点验证「就近原则 + 子组继承闸门」:沿组的祖先链向上,取最近的有显式模块配置的组作为该应用唯一权限来源, + * 只返回该来源组的模块集合(不向上合并更远的祖先);且来源组若为祖先,必须勾选子组继承(inheritFlag=true)才下放 + * (修复「子组只勾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 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 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 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 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 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 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 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 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 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 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 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应可访问"); + } + + // ===================== 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; + } +}