diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/RoleService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/RoleService.java index 2d68c71d94..d837d1e8b0 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/RoleService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/RoleService.java @@ -106,14 +106,6 @@ public interface RoleService { */ List getRoleList(); - /** - * 判断角色编号数组中,是否有管理员 - * - * @param ids 角色编号数组 - * @return 是否有管理员 - */ - boolean hasAnySuperAdmin(Collection ids); - /** * 获得角色分页 * @@ -130,6 +122,14 @@ public interface RoleService { */ List getRoleList(RoleExportReqVO reqVO); + /** + * 判断角色编号数组中,是否有管理员 + * + * @param ids 角色编号数组 + * @return 是否有管理员 + */ + boolean hasAnySuperAdmin(Collection ids); + /** * 校验角色们是否有效。如下情况,视为无效: * 1. 角色编号不存在 diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceImpl.java index 214a20ac31..30c624219b 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceImpl.java @@ -52,7 +52,7 @@ public class RoleServiceImpl implements RoleService { private RoleMapper roleMapper; @Override - @Transactional + @Transactional(rollbackFor = Exception.class) public Long createRole(RoleCreateReqVO reqVO, Integer type) { // 校验角色 validateRoleDuplicate(reqVO.getName(), reqVO.getCode(), null); @@ -116,64 +116,6 @@ public class RoleServiceImpl implements RoleService { permissionService.processRoleDeleted(id); } - @Override - public List getRoleListByStatus(@Nullable Collection statuses) { - return roleMapper.selectListByStatus(statuses); - } - - @Override - public List getRoleList() { - return roleMapper.selectList(); - } - - @Override - public RoleDO getRole(Long id) { - return roleMapper.selectById(id); - } - - @Override - @Cacheable(value = RedisKeyConstants.ROLE, key = "#id", unless = "#result == null") - public RoleDO getRoleFromCache(Long id) { - return roleMapper.selectById(id); - } - - @Override - public List getRoleList(Collection ids) { - return roleMapper.selectBatchIds(ids); - } - - @Override - public List getRoleListFromCache(Collection ids) { - if (CollectionUtil.isEmpty(ids)) { - return Collections.emptyList(); - } - // 这里采用 for 循环从缓存中获取,主要考虑 Spring CacheManager 无法批量操作的问题 - RoleServiceImpl self = getSelf(); - return convertList(ids, self::getRoleFromCache); - } - - - @Override - public boolean hasAnySuperAdmin(Collection ids) { - if (CollectionUtil.isEmpty(ids)) { - return false; - } - return ids.stream().anyMatch(id -> { - RoleDO role = getRoleFromCache(id); - return role != null && RoleCodeEnum.isSuperAdmin(role.getCode()); - }); - } - - @Override - public PageResult getRolePage(RolePageReqVO reqVO) { - return roleMapper.selectPage(reqVO); - } - - @Override - public List getRoleList(RoleExportReqVO reqVO) { - return roleMapper.selectList(reqVO); - } - /** * 校验角色的唯一字段是否重复 * @@ -223,6 +165,65 @@ public class RoleServiceImpl implements RoleService { } } + @Override + public RoleDO getRole(Long id) { + return roleMapper.selectById(id); + } + + @Override + @Cacheable(value = RedisKeyConstants.ROLE, key = "#id", unless = "#result == null") + public RoleDO getRoleFromCache(Long id) { + return roleMapper.selectById(id); + } + + + @Override + public List getRoleListByStatus(Collection statuses) { + return roleMapper.selectListByStatus(statuses); + } + + @Override + public List getRoleList() { + return roleMapper.selectList(); + } + + @Override + public List getRoleList(Collection ids) { + return roleMapper.selectBatchIds(ids); + } + + @Override + public List getRoleListFromCache(Collection ids) { + if (CollectionUtil.isEmpty(ids)) { + return Collections.emptyList(); + } + // 这里采用 for 循环从缓存中获取,主要考虑 Spring CacheManager 无法批量操作的问题 + RoleServiceImpl self = getSelf(); + return convertList(ids, self::getRoleFromCache); + } + + @Override + public PageResult getRolePage(RolePageReqVO reqVO) { + return roleMapper.selectPage(reqVO); + } + + @Override + public List getRoleList(RoleExportReqVO reqVO) { + return roleMapper.selectList(reqVO); + } + + @Override + public boolean hasAnySuperAdmin(Collection ids) { + if (CollectionUtil.isEmpty(ids)) { + return false; + } + RoleServiceImpl self = getSelf(); + return ids.stream().anyMatch(id -> { + RoleDO role = self.getRoleFromCache(id); + return role != null && RoleCodeEnum.isSuperAdmin(role.getCode()); + }); + } + @Override public void validateRoleList(Collection ids) { if (CollUtil.isEmpty(ids)) { diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceImplTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceImplTest.java index a114556c40..5c7e963982 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceImplTest.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.system.service.permission; +import cn.hutool.extra.spring.SpringUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; @@ -11,15 +12,14 @@ import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO; import cn.iocoder.yudao.module.system.dal.mysql.permission.RoleMapper; import cn.iocoder.yudao.module.system.enums.permission.DataScopeEnum; import cn.iocoder.yudao.module.system.enums.permission.RoleTypeEnum; -import cn.iocoder.yudao.module.system.mq.producer.permission.RoleProducer; import org.junit.jupiter.api.Test; +import org.mockito.MockedStatic; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Import; import javax.annotation.Resource; import java.util.Collection; import java.util.List; -import java.util.Map; import java.util.Set; import static cn.hutool.core.util.RandomUtil.randomEle; @@ -33,6 +33,8 @@ import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; import static java.util.Collections.singleton; import static java.util.Collections.singletonList; import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mockStatic; import static org.mockito.Mockito.verify; @Import(RoleServiceImpl.class) @@ -46,26 +48,9 @@ public class RoleServiceImplTest extends BaseDbUnitTest { @MockBean private PermissionService permissionService; - @MockBean - private RoleProducer roleProducer; @Test - public void testInitLocalCache() { - RoleDO roleDO1 = randomPojo(RoleDO.class); - roleMapper.insert(roleDO1); - RoleDO roleDO2 = randomPojo(RoleDO.class); - roleMapper.insert(roleDO2); - - // 调用 - roleService.initLocalCache(); - // 断言 roleCache 缓存 - Map roleCache = roleService.getRoleCache(); - assertPojoEquals(roleDO1, roleCache.get(roleDO1.getId())); - assertPojoEquals(roleDO2, roleCache.get(roleDO2.getId())); - } - - @Test - public void testCreateRole_success() { + public void testCreateRole() { // 准备参数 RoleCreateReqVO reqVO = randomPojo(RoleCreateReqVO.class); @@ -77,12 +62,10 @@ public class RoleServiceImplTest extends BaseDbUnitTest { assertEquals(RoleTypeEnum.CUSTOM.getType(), roleDO.getType()); assertEquals(CommonStatusEnum.ENABLE.getStatus(), roleDO.getStatus()); assertEquals(DataScopeEnum.ALL.getScope(), roleDO.getDataScope()); - // verify 发送刷新消息 - verify(roleProducer).sendRoleRefreshMessage(); } @Test - public void testUpdateRole_success() { + public void testUpdateRole() { // mock 数据 RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setType(RoleTypeEnum.CUSTOM.getType())); roleMapper.insert(roleDO); @@ -95,12 +78,10 @@ public class RoleServiceImplTest extends BaseDbUnitTest { // 断言 RoleDO newRoleDO = roleMapper.selectById(id); assertPojoEquals(reqVO, newRoleDO); - // verify 发送刷新消息 - verify(roleProducer).sendRoleRefreshMessage(); } @Test - public void testUpdateRoleStatus_success() { + public void testUpdateRoleStatus() { // mock 数据 RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus()) .setType(RoleTypeEnum.CUSTOM.getType())); @@ -114,12 +95,10 @@ public class RoleServiceImplTest extends BaseDbUnitTest { // 断言 RoleDO dbRoleDO = roleMapper.selectById(roleId); assertEquals(CommonStatusEnum.DISABLE.getStatus(), dbRoleDO.getStatus()); - // verify 发送刷新消息 - verify(roleProducer).sendRoleRefreshMessage(); } @Test - public void testUpdateRoleDataScope_success() { + public void testUpdateRoleDataScope() { // mock 数据 RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setType(RoleTypeEnum.CUSTOM.getType())); roleMapper.insert(roleDO); @@ -134,12 +113,10 @@ public class RoleServiceImplTest extends BaseDbUnitTest { RoleDO dbRoleDO = roleMapper.selectById(id); assertEquals(dataScope, dbRoleDO.getDataScope()); assertEquals(dataScopeRoleIds, dbRoleDO.getDataScopeDeptIds()); - // verify 发送刷新消息 - verify(roleProducer).sendRoleRefreshMessage(); } @Test - public void testDeleteRole_success() { + public void testDeleteRole() { // mock 数据 RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setType(RoleTypeEnum.CUSTOM.getType())); roleMapper.insert(roleDO); @@ -152,23 +129,65 @@ public class RoleServiceImplTest extends BaseDbUnitTest { assertNull(roleMapper.selectById(id)); // verify 删除相关数据 verify(permissionService).processRoleDeleted(id); - // verify 发送刷新消息 - verify(roleProducer).sendRoleRefreshMessage(); } @Test - public void testGetRoleFromCache() { - // mock 数据(缓存) + public void testValidateRoleDuplicate_success() { + // 调用,不会抛异常 + roleService.validateRoleDuplicate(randomString(), randomString(), null); + } + + @Test + public void testValidateRoleDuplicate_nameDuplicate() { + // mock 数据 + RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setName("role_name")); + roleMapper.insert(roleDO); + // 准备参数 + String name = "role_name"; + + // 调用,并断言异常 + assertServiceException(() -> roleService.validateRoleDuplicate(name, randomString(), null), + ROLE_NAME_DUPLICATE, name); + } + + @Test + public void testValidateRoleDuplicate_codeDuplicate() { + // mock 数据 + RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setCode("code")); + roleMapper.insert(roleDO); + // 准备参数 + String code = "code"; + + // 调用,并断言异常 + assertServiceException(() -> roleService.validateRoleDuplicate(randomString(), code, null), + ROLE_CODE_DUPLICATE, code); + } + + @Test + public void testValidateUpdateRole_success() { RoleDO roleDO = randomPojo(RoleDO.class); roleMapper.insert(roleDO); - roleService.initLocalCache(); - // 参数准备 + // 准备参数 Long id = roleDO.getId(); - // 调用 - RoleDO dbRoleDO = roleService.getRoleFromCache(id); - // 断言 - assertPojoEquals(roleDO, dbRoleDO); + // 调用,无异常 + roleService.validateRoleForUpdate(id); + } + + @Test + public void testValidateUpdateRole_roleIdNotExist() { + assertServiceException(() -> roleService.validateRoleForUpdate(randomLongId()), ROLE_NOT_EXISTS); + } + + @Test + public void testValidateUpdateRole_systemRoleCanNotBeUpdate() { + RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setType(RoleTypeEnum.SYSTEM.getType())); + roleMapper.insert(roleDO); + // 准备参数 + Long id = roleDO.getId(); + + assertServiceException(() -> roleService.validateRoleForUpdate(id), + ROLE_CAN_NOT_UPDATE_SYSTEM_TYPE_ROLE); } @Test @@ -186,22 +205,21 @@ public class RoleServiceImplTest extends BaseDbUnitTest { } @Test - public void testGetRoleListByStatus_statusNotEmpty() { - // mock 数据 - RoleDO dbRole = randomPojo(RoleDO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus())); - roleMapper.insert(dbRole); - // 测试 status 不匹配 - roleMapper.insert(cloneIgnoreId(dbRole, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()))); + public void testGetRoleFromCache() { + // mock 数据(缓存) + RoleDO roleDO = randomPojo(RoleDO.class); + roleMapper.insert(roleDO); + // 参数准备 + Long id = roleDO.getId(); // 调用 - List list = roleService.getRoleListByStatus(singleton(CommonStatusEnum.ENABLE.getStatus())); + RoleDO dbRoleDO = roleService.getRoleFromCache(id); // 断言 - assertEquals(1, list.size()); - assertPojoEquals(dbRole, list.get(0)); + assertPojoEquals(roleDO, dbRoleDO); } @Test - public void testGetRoleListByStatus_statusEmpty() { + public void testGetRoleListByStatus() { // mock 数据 RoleDO dbRole01 = randomPojo(RoleDO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus())); roleMapper.insert(dbRole01); @@ -209,29 +227,33 @@ public class RoleServiceImplTest extends BaseDbUnitTest { roleMapper.insert(dbRole02); // 调用 - List list = roleService.getRoleListByStatus(null); + List list = roleService.getRoleListByStatus( + singleton(CommonStatusEnum.ENABLE.getStatus())); // 断言 - assertEquals(2, list.size()); + assertEquals(1, list.size()); assertPojoEquals(dbRole01, list.get(0)); - assertPojoEquals(dbRole02, list.get(1)); } @Test public void testGetRoleListFromCache() { - // mock 数据 - RoleDO dbRole = randomPojo(RoleDO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus())); - roleMapper.insert(dbRole); - // 测试 id 不匹配 - roleMapper.insert(cloneIgnoreId(dbRole, o -> {})); - roleService.initLocalCache(); - // 准备参数 - Collection ids = singleton(dbRole.getId()); + try (MockedStatic springUtilMockedStatic = mockStatic(SpringUtil.class)) { + springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(RoleServiceImpl.class))) + .thenReturn(roleService); - // 调用 - List list = roleService.getRoleListFromCache(ids); - // 断言 - assertEquals(1, list.size()); - assertPojoEquals(dbRole, list.get(0)); + // mock 数据 + RoleDO dbRole = randomPojo(RoleDO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus())); + roleMapper.insert(dbRole); + // 测试 id 不匹配 + roleMapper.insert(cloneIgnoreId(dbRole, o -> {})); + // 准备参数 + Collection ids = singleton(dbRole.getId()); + + // 调用 + List list = roleService.getRoleListFromCache(ids); + // 断言 + assertEquals(1, list.size()); + assertPojoEquals(dbRole, list.get(0)); + } } @Test @@ -296,72 +318,37 @@ public class RoleServiceImplTest extends BaseDbUnitTest { } @Test - public void testHasAnySuperAdmin() { - // 是超级 - assertTrue(roleService.hasAnySuperAdmin(singletonList(randomPojo(RoleDO.class, - o -> o.setCode("super_admin"))))); - // 非超级 - assertFalse(roleService.hasAnySuperAdmin(singletonList(randomPojo(RoleDO.class, - o -> o.setCode("tenant_admin"))))); + public void testHasAnySuperAdmin_true() { + try (MockedStatic springUtilMockedStatic = mockStatic(SpringUtil.class)) { + springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(RoleServiceImpl.class))) + .thenReturn(roleService); + + // mock 数据 + RoleDO dbRole = randomPojo(RoleDO.class).setCode("super_admin"); + roleMapper.insert(dbRole); + // 准备参数 + Long id = dbRole.getId(); + + // 调用,并调用 + assertTrue(roleService.hasAnySuperAdmin(singletonList(id))); + } } @Test - public void testValidateRoleDuplicate_success() { - // 调用,不会抛异常 - roleService.validateRoleDuplicate(randomString(), randomString(), null); - } + public void testHasAnySuperAdmin_false() { + try (MockedStatic springUtilMockedStatic = mockStatic(SpringUtil.class)) { + springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(RoleServiceImpl.class))) + .thenReturn(roleService); - @Test - public void testValidateRoleDuplicate_nameDuplicate() { - // mock 数据 - RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setName("role_name")); - roleMapper.insert(roleDO); - // 准备参数 - String name = "role_name"; + // mock 数据 + RoleDO dbRole = randomPojo(RoleDO.class).setCode("tenant_admin"); + roleMapper.insert(dbRole); + // 准备参数 + Long id = dbRole.getId(); - // 调用,并断言异常 - assertServiceException(() -> roleService.validateRoleDuplicate(name, randomString(), null), - ROLE_NAME_DUPLICATE, name); - } - - @Test - public void testValidateRoleDuplicate_codeDuplicate() { - // mock 数据 - RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setCode("code")); - roleMapper.insert(roleDO); - // 准备参数 - String code = "code"; - - // 调用,并断言异常 - assertServiceException(() -> roleService.validateRoleDuplicate(randomString(), code, null), - ROLE_CODE_DUPLICATE, code); - } - - @Test - public void testValidateUpdateRole_success() { - RoleDO roleDO = randomPojo(RoleDO.class); - roleMapper.insert(roleDO); - // 准备参数 - Long id = roleDO.getId(); - - // 调用,无异常 - roleService.validateRoleForUpdate(id); - } - - @Test - public void testValidateUpdateRole_roleIdNotExist() { - assertServiceException(() -> roleService.validateRoleForUpdate(randomLongId()), ROLE_NOT_EXISTS); - } - - @Test - public void testValidateUpdateRole_systemRoleCanNotBeUpdate() { - RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setType(RoleTypeEnum.SYSTEM.getType())); - roleMapper.insert(roleDO); - // 准备参数 - Long id = roleDO.getId(); - - assertServiceException(() -> roleService.validateRoleForUpdate(id), - ROLE_CAN_NOT_UPDATE_SYSTEM_TYPE_ROLE); + // 调用,并调用 + assertFalse(roleService.hasAnySuperAdmin(singletonList(id))); + } } @Test