Commit 85f2928aa51e1670f1f2f69fa310f18d0872949f
1 parent
89a6c642
fix(crm): 修复管理员转移数据时旧负责人权限处理
Showing
2 changed files
with
309 additions
and
16 deletions
yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java
| @@ -206,41 +206,47 @@ public class CrmPermissionServiceImpl implements CrmPermissionService { | @@ -206,41 +206,47 @@ public class CrmPermissionServiceImpl implements CrmPermissionService { | ||
| 206 | @Override | 206 | @Override |
| 207 | @Transactional(rollbackFor = Exception.class) | 207 | @Transactional(rollbackFor = Exception.class) |
| 208 | public void transferPermission(CrmPermissionTransferReqBO transferReqBO) { | 208 | public void transferPermission(CrmPermissionTransferReqBO transferReqBO) { |
| 209 | - // 1. 校验数据权限:是否是负责人,只有负责人才可以转移 | ||
| 210 | - CrmPermissionDO oldPermission = permissionMapper.selectByBizTypeAndBizIdByUserId( | ||
| 211 | - transferReqBO.getBizType(), transferReqBO.getBizId(), transferReqBO.getUserId()); | ||
| 212 | String bizTypeName = CrmBizTypeEnum.getNameByType(transferReqBO.getBizType()); | 209 | String bizTypeName = CrmBizTypeEnum.getNameByType(transferReqBO.getBizType()); |
| 213 | - if ((oldPermission == null || !isOwner(oldPermission.getLevel())) | ||
| 214 | - && !CrmPermissionUtils.isCrmAdmin()) { // 并且不是超管 | 210 | + List<CrmPermissionDO> permissions = permissionMapper.selectByBizTypeAndBizId( |
| 211 | + transferReqBO.getBizType(), transferReqBO.getBizId()); // 获得所有数据权限 | ||
| 212 | + // 1.1 校验数据权限:只有负责人,或者 CRM 管理员,才可以转移 | ||
| 213 | + CrmPermissionDO userPermission = CollUtil.findOne(permissions, | ||
| 214 | + item -> ObjUtil.equal(item.getUserId(), transferReqBO.getUserId())); | ||
| 215 | + boolean owner = userPermission != null && isOwner(userPermission.getLevel()); | ||
| 216 | + if (!owner && !CrmPermissionUtils.isCrmAdmin()) { | ||
| 215 | throw exception(CRM_PERMISSION_DENIED, bizTypeName); | 217 | throw exception(CRM_PERMISSION_DENIED, bizTypeName); |
| 216 | } | 218 | } |
| 217 | - // 1.1 校验转移对象是否已经是该负责人 | ||
| 218 | - if (oldPermission != null && ObjUtil.equal(transferReqBO.getNewOwnerUserId(), oldPermission.getUserId())) { | 219 | + // 1.2 获得老负责人的权限:操作人是负责人时,就是操作人的权限;否则(CRM 管理员),是数据实际的负责人,而不是管理员自己的团队权限 |
| 220 | + CrmPermissionDO oldOwnerPermission = owner ? userPermission | ||
| 221 | + : CollUtil.findOne(permissions, item -> isOwner(item.getLevel())); | ||
| 222 | + if (oldOwnerPermission == null) { // 数据缺少负责人时,在修改任何权限前失败,避免部分写入 | ||
| 223 | + throw exception(CRM_PERMISSION_NOT_EXISTS); | ||
| 224 | + } | ||
| 225 | + // 1.3 校验转移对象是否已经是该负责人 | ||
| 226 | + if (ObjUtil.equal(transferReqBO.getNewOwnerUserId(), oldOwnerPermission.getUserId())) { | ||
| 219 | throw exception(CRM_PERMISSION_MODEL_TRANSFER_FAIL_OWNER_USER_EXISTS, bizTypeName); | 227 | throw exception(CRM_PERMISSION_MODEL_TRANSFER_FAIL_OWNER_USER_EXISTS, bizTypeName); |
| 220 | } | 228 | } |
| 221 | - // 1.2 校验新负责人是否存在 | 229 | + // 1.4 校验新负责人是否存在 |
| 222 | adminUserApi.validateUserList(Collections.singletonList(transferReqBO.getNewOwnerUserId())); | 230 | adminUserApi.validateUserList(Collections.singletonList(transferReqBO.getNewOwnerUserId())); |
| 223 | 231 | ||
| 224 | - // 2. 修改新负责人的权限 | ||
| 225 | - List<CrmPermissionDO> permissions = permissionMapper.selectByBizTypeAndBizId( | ||
| 226 | - transferReqBO.getBizType(), transferReqBO.getBizId()); // 获得所有数据权限 | ||
| 227 | - CrmPermissionDO permission = CollUtil.findOne(permissions, | 232 | + // 2. 修改新负责人的权限:已在团队中时,提升为负责人,不重复新增 |
| 233 | + CrmPermissionDO newOwnerPermission = CollUtil.findOne(permissions, | ||
| 228 | item -> ObjUtil.equal(item.getUserId(), transferReqBO.getNewOwnerUserId())); | 234 | item -> ObjUtil.equal(item.getUserId(), transferReqBO.getNewOwnerUserId())); |
| 229 | - if (permission == null) { | 235 | + if (newOwnerPermission == null) { |
| 230 | permissionMapper.insert(new CrmPermissionDO().setBizType(transferReqBO.getBizType()) | 236 | permissionMapper.insert(new CrmPermissionDO().setBizType(transferReqBO.getBizType()) |
| 231 | .setBizId(transferReqBO.getBizId()).setUserId(transferReqBO.getNewOwnerUserId()) | 237 | .setBizId(transferReqBO.getBizId()).setUserId(transferReqBO.getNewOwnerUserId()) |
| 232 | .setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); | 238 | .setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); |
| 233 | } else { | 239 | } else { |
| 234 | - permissionMapper.updateById(new CrmPermissionDO().setId(permission.getId()) | 240 | + permissionMapper.updateById(new CrmPermissionDO().setId(newOwnerPermission.getId()) |
| 235 | .setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); | 241 | .setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); |
| 236 | } | 242 | } |
| 237 | 243 | ||
| 238 | // 3. 修改老负责人的权限 | 244 | // 3. 修改老负责人的权限 |
| 239 | if (transferReqBO.getOldOwnerPermissionLevel() != null) { | 245 | if (transferReqBO.getOldOwnerPermissionLevel() != null) { |
| 240 | - permissionMapper.updateById(new CrmPermissionDO().setId(oldPermission.getId()) | 246 | + permissionMapper.updateById(new CrmPermissionDO().setId(oldOwnerPermission.getId()) |
| 241 | .setLevel(transferReqBO.getOldOwnerPermissionLevel())); | 247 | .setLevel(transferReqBO.getOldOwnerPermissionLevel())); |
| 242 | } else { | 248 | } else { |
| 243 | - permissionMapper.deleteById(oldPermission.getId()); | 249 | + permissionMapper.deleteById(oldOwnerPermission.getId()); |
| 244 | } | 250 | } |
| 245 | } | 251 | } |
| 246 | 252 |
yudao-module-crm/src/test/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImplTest.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.crm.service.permission; | ||
| 2 | + | ||
| 3 | +import cn.hutool.extra.spring.SpringUtil; | ||
| 4 | +import cn.iocoder.yudao.framework.common.biz.system.permission.PermissionCommonApi; | ||
| 5 | +import cn.iocoder.yudao.framework.security.core.LoginUser; | ||
| 6 | +import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; | ||
| 7 | +import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; | ||
| 8 | +import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO; | ||
| 9 | +import cn.iocoder.yudao.module.crm.dal.mysql.permission.CrmPermissionMapper; | ||
| 10 | +import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; | ||
| 11 | +import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; | ||
| 12 | +import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO; | ||
| 13 | +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | ||
| 14 | +import cn.iocoder.yudao.module.system.enums.permission.RoleCodeEnum; | ||
| 15 | +import org.junit.jupiter.api.AfterEach; | ||
| 16 | +import org.junit.jupiter.api.BeforeEach; | ||
| 17 | +import org.junit.jupiter.api.Test; | ||
| 18 | +import org.mockito.InjectMocks; | ||
| 19 | +import org.mockito.Mock; | ||
| 20 | +import org.mockito.MockedStatic; | ||
| 21 | +import org.springframework.mock.web.MockHttpServletRequest; | ||
| 22 | +import org.springframework.security.core.context.SecurityContextHolder; | ||
| 23 | + | ||
| 24 | +import java.util.Arrays; | ||
| 25 | +import java.util.Collections; | ||
| 26 | +import java.util.List; | ||
| 27 | +import java.util.Objects; | ||
| 28 | + | ||
| 29 | +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | ||
| 30 | +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; | ||
| 31 | +import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; | ||
| 32 | +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.USER_NOT_EXISTS; | ||
| 33 | +import static org.mockito.ArgumentMatchers.argThat; | ||
| 34 | +import static org.mockito.Mockito.*; | ||
| 35 | + | ||
| 36 | +/** | ||
| 37 | + * {@link CrmPermissionServiceImpl} 的单元测试类 | ||
| 38 | + * | ||
| 39 | + * 重点覆盖 {@link CrmPermissionServiceImpl#transferPermission(CrmPermissionTransferReqBO)}:区分操作人的权限、数据实际的负责人 | ||
| 40 | + * | ||
| 41 | + * @author 芋道源码 | ||
| 42 | + */ | ||
| 43 | +public class CrmPermissionServiceImplTest extends BaseMockitoUnitTest { | ||
| 44 | + | ||
| 45 | + private static final Integer BIZ_TYPE = CrmBizTypeEnum.CRM_CUSTOMER.getType(); | ||
| 46 | + private static final String BIZ_TYPE_NAME = CrmBizTypeEnum.CRM_CUSTOMER.getName(); | ||
| 47 | + private static final Long BIZ_ID = 10L; | ||
| 48 | + | ||
| 49 | + private static final Long LOGIN_USER_ID = 100L; | ||
| 50 | + private static final Long OWNER_USER_ID = 200L; | ||
| 51 | + private static final Long NEW_OWNER_USER_ID = 300L; | ||
| 52 | + | ||
| 53 | + private static final Long OWNER_PERMISSION_ID = 1L; | ||
| 54 | + private static final Long LOGIN_USER_PERMISSION_ID = 2L; | ||
| 55 | + private static final Long NEW_OWNER_PERMISSION_ID = 3L; | ||
| 56 | + | ||
| 57 | + @InjectMocks | ||
| 58 | + private CrmPermissionServiceImpl permissionService; | ||
| 59 | + | ||
| 60 | + @Mock | ||
| 61 | + private CrmPermissionMapper permissionMapper; | ||
| 62 | + @Mock | ||
| 63 | + private AdminUserApi adminUserApi; | ||
| 64 | + @Mock | ||
| 65 | + private PermissionCommonApi permissionCommonApi; | ||
| 66 | + | ||
| 67 | + private MockedStatic<SpringUtil> springUtilMockedStatic; | ||
| 68 | + | ||
| 69 | + @BeforeEach | ||
| 70 | + public void setUp() { | ||
| 71 | + // mock CrmPermissionUtils#isCrmAdmin() 使用的 PermissionCommonApi,在 mockCrmAdmin 方法中按需 mock 返回值 | ||
| 72 | + springUtilMockedStatic = mockStatic(SpringUtil.class); | ||
| 73 | + // mock 登录用户 | ||
| 74 | + SecurityFrameworkUtils.setLoginUser(new LoginUser().setId(LOGIN_USER_ID), new MockHttpServletRequest()); | ||
| 75 | + } | ||
| 76 | + | ||
| 77 | + @AfterEach | ||
| 78 | + public void tearDown() { | ||
| 79 | + springUtilMockedStatic.close(); | ||
| 80 | + SecurityContextHolder.clearContext(); | ||
| 81 | + } | ||
| 82 | + | ||
| 83 | + // ========== 负责人转移 ========== | ||
| 84 | + | ||
| 85 | + @Test | ||
| 86 | + public void testTransferPermission_ownerRemoveOldOwner() { | ||
| 87 | + // mock 数据:当前用户是负责人,新负责人不在团队中 | ||
| 88 | + mockPermissions(buildPermission(LOGIN_USER_PERMISSION_ID, LOGIN_USER_ID, CrmPermissionLevelEnum.OWNER)); | ||
| 89 | + | ||
| 90 | + // 调用:老负责人移除 | ||
| 91 | + permissionService.transferPermission(buildTransferReqBO(NEW_OWNER_USER_ID, null)); | ||
| 92 | + // 断言:新增新负责人;删除老负责人(当前用户) | ||
| 93 | + verify(adminUserApi).validateUserList(Collections.singletonList(NEW_OWNER_USER_ID)); | ||
| 94 | + verify(permissionMapper).selectByBizTypeAndBizId(BIZ_TYPE, BIZ_ID); | ||
| 95 | + verifyNewOwnerInserted(); | ||
| 96 | + verify(permissionMapper).deleteById(LOGIN_USER_PERMISSION_ID); | ||
| 97 | + verifyNoMoreInteractions(permissionMapper); | ||
| 98 | + } | ||
| 99 | + | ||
| 100 | + @Test | ||
| 101 | + public void testTransferPermission_ownerKeepOldOwnerAndPromoteTeamMember() { | ||
| 102 | + // mock 数据:当前用户是负责人,新负责人已有 READ 团队权限 | ||
| 103 | + mockPermissions(buildPermission(LOGIN_USER_PERMISSION_ID, LOGIN_USER_ID, CrmPermissionLevelEnum.OWNER), | ||
| 104 | + buildPermission(NEW_OWNER_PERMISSION_ID, NEW_OWNER_USER_ID, CrmPermissionLevelEnum.READ)); | ||
| 105 | + | ||
| 106 | + // 调用:老负责人保留为 WRITE | ||
| 107 | + permissionService.transferPermission(buildTransferReqBO(NEW_OWNER_USER_ID, CrmPermissionLevelEnum.WRITE.getLevel())); | ||
| 108 | + // 断言:新负责人的团队权限提升为负责人,不重复新增;老负责人(当前用户)改为 WRITE | ||
| 109 | + verify(permissionMapper).selectByBizTypeAndBizId(BIZ_TYPE, BIZ_ID); | ||
| 110 | + verifyLevelUpdated(NEW_OWNER_PERMISSION_ID, CrmPermissionLevelEnum.OWNER); | ||
| 111 | + verifyLevelUpdated(LOGIN_USER_PERMISSION_ID, CrmPermissionLevelEnum.WRITE); | ||
| 112 | + verifyNoMoreInteractions(permissionMapper); | ||
| 113 | + } | ||
| 114 | + | ||
| 115 | + @Test | ||
| 116 | + public void testTransferPermission_ownerToSelf() { | ||
| 117 | + // mock 数据:当前用户是负责人 | ||
| 118 | + mockPermissions(buildPermission(LOGIN_USER_PERMISSION_ID, LOGIN_USER_ID, CrmPermissionLevelEnum.OWNER)); | ||
| 119 | + | ||
| 120 | + // 调用,并断言异常:转移给自己 | ||
| 121 | + assertServiceException(() -> permissionService.transferPermission(buildTransferReqBO(LOGIN_USER_ID, null)), | ||
| 122 | + CRM_PERMISSION_MODEL_TRANSFER_FAIL_OWNER_USER_EXISTS, BIZ_TYPE_NAME); | ||
| 123 | + assertNoPermissionWrite(); | ||
| 124 | + verifyNoInteractions(adminUserApi); | ||
| 125 | + } | ||
| 126 | + | ||
| 127 | + // ========== 非负责人、非 CRM 管理员 ========== | ||
| 128 | + | ||
| 129 | + @Test | ||
| 130 | + public void testTransferPermission_teamMemberDenied() { | ||
| 131 | + // mock 数据:当前用户只有 WRITE 团队权限,不是 CRM 管理员 | ||
| 132 | + mockPermissions(buildPermission(OWNER_PERMISSION_ID, OWNER_USER_ID, CrmPermissionLevelEnum.OWNER), | ||
| 133 | + buildPermission(LOGIN_USER_PERMISSION_ID, LOGIN_USER_ID, CrmPermissionLevelEnum.WRITE)); | ||
| 134 | + mockCrmAdmin(false); | ||
| 135 | + | ||
| 136 | + // 调用,并断言异常 | ||
| 137 | + assertServiceException(() -> permissionService.transferPermission(buildTransferReqBO(NEW_OWNER_USER_ID, null)), | ||
| 138 | + CRM_PERMISSION_DENIED, BIZ_TYPE_NAME); | ||
| 139 | + assertNoPermissionWrite(); | ||
| 140 | + verifyNoInteractions(adminUserApi); | ||
| 141 | + } | ||
| 142 | + | ||
| 143 | + @Test | ||
| 144 | + public void testTransferPermission_noPermissionDenied() { | ||
| 145 | + // mock 数据:当前用户没有任何权限,不是 CRM 管理员 | ||
| 146 | + mockPermissions(buildPermission(OWNER_PERMISSION_ID, OWNER_USER_ID, CrmPermissionLevelEnum.OWNER)); | ||
| 147 | + mockCrmAdmin(false); | ||
| 148 | + | ||
| 149 | + // 调用,并断言异常 | ||
| 150 | + assertServiceException(() -> permissionService.transferPermission(buildTransferReqBO(NEW_OWNER_USER_ID, null)), | ||
| 151 | + CRM_PERMISSION_DENIED, BIZ_TYPE_NAME); | ||
| 152 | + assertNoPermissionWrite(); | ||
| 153 | + verifyNoInteractions(adminUserApi); | ||
| 154 | + } | ||
| 155 | + | ||
| 156 | + // ========== CRM 管理员转移 ========== | ||
| 157 | + | ||
| 158 | + @Test | ||
| 159 | + public void testTransferPermission_crmAdminWithoutPermission() { | ||
| 160 | + // mock 数据:CRM 管理员没有权限,数据的负责人是其他人(修复前:先新增新负责人,再因 NPE 失败) | ||
| 161 | + mockPermissions(buildPermission(OWNER_PERMISSION_ID, OWNER_USER_ID, CrmPermissionLevelEnum.OWNER)); | ||
| 162 | + mockCrmAdmin(true); | ||
| 163 | + | ||
| 164 | + // 调用:老负责人移除 | ||
| 165 | + permissionService.transferPermission(buildTransferReqBO(NEW_OWNER_USER_ID, null)); | ||
| 166 | + // 断言:新增新负责人;删除实际的老负责人 | ||
| 167 | + verify(adminUserApi).validateUserList(Collections.singletonList(NEW_OWNER_USER_ID)); | ||
| 168 | + verify(permissionMapper).selectByBizTypeAndBizId(BIZ_TYPE, BIZ_ID); | ||
| 169 | + verifyNewOwnerInserted(); | ||
| 170 | + verify(permissionMapper).deleteById(OWNER_PERMISSION_ID); | ||
| 171 | + verifyNoMoreInteractions(permissionMapper); | ||
| 172 | + } | ||
| 173 | + | ||
| 174 | + @Test | ||
| 175 | + public void testTransferPermission_crmAdminWithTeamPermission() { | ||
| 176 | + // mock 数据:CRM 管理员有 WRITE 团队权限,数据的负责人是其他人 | ||
| 177 | + mockPermissions(buildPermission(OWNER_PERMISSION_ID, OWNER_USER_ID, CrmPermissionLevelEnum.OWNER), | ||
| 178 | + buildPermission(LOGIN_USER_PERMISSION_ID, LOGIN_USER_ID, CrmPermissionLevelEnum.WRITE)); | ||
| 179 | + mockCrmAdmin(true); | ||
| 180 | + | ||
| 181 | + // 调用:老负责人保留为 READ | ||
| 182 | + permissionService.transferPermission(buildTransferReqBO(NEW_OWNER_USER_ID, CrmPermissionLevelEnum.READ.getLevel())); | ||
| 183 | + // 断言:新增新负责人;实际的老负责人改为 READ;管理员自己的团队权限不变 | ||
| 184 | + verify(permissionMapper).selectByBizTypeAndBizId(BIZ_TYPE, BIZ_ID); | ||
| 185 | + verifyNewOwnerInserted(); | ||
| 186 | + verifyLevelUpdated(OWNER_PERMISSION_ID, CrmPermissionLevelEnum.READ); | ||
| 187 | + verifyNoMoreInteractions(permissionMapper); | ||
| 188 | + } | ||
| 189 | + | ||
| 190 | + @Test | ||
| 191 | + public void testTransferPermission_crmAdminToSelf() { | ||
| 192 | + // mock 数据:CRM 管理员有 READ 团队权限,数据的负责人是其他人 | ||
| 193 | + mockPermissions(buildPermission(OWNER_PERMISSION_ID, OWNER_USER_ID, CrmPermissionLevelEnum.OWNER), | ||
| 194 | + buildPermission(LOGIN_USER_PERMISSION_ID, LOGIN_USER_ID, CrmPermissionLevelEnum.READ)); | ||
| 195 | + mockCrmAdmin(true); | ||
| 196 | + | ||
| 197 | + // 调用:转移给自己,老负责人移除 | ||
| 198 | + permissionService.transferPermission(buildTransferReqBO(LOGIN_USER_ID, null)); | ||
| 199 | + // 断言:管理员的团队权限提升为负责人,不重复新增;删除实际的老负责人 | ||
| 200 | + verify(adminUserApi).validateUserList(Collections.singletonList(LOGIN_USER_ID)); | ||
| 201 | + verify(permissionMapper).selectByBizTypeAndBizId(BIZ_TYPE, BIZ_ID); | ||
| 202 | + verifyLevelUpdated(LOGIN_USER_PERMISSION_ID, CrmPermissionLevelEnum.OWNER); | ||
| 203 | + verify(permissionMapper).deleteById(OWNER_PERMISSION_ID); | ||
| 204 | + verifyNoMoreInteractions(permissionMapper); | ||
| 205 | + } | ||
| 206 | + | ||
| 207 | + @Test | ||
| 208 | + public void testTransferPermission_crmAdminNewOwnerIsOwner() { | ||
| 209 | + // mock 数据:CRM 管理员没有权限,新负责人已经是负责人 | ||
| 210 | + mockPermissions(buildPermission(OWNER_PERMISSION_ID, OWNER_USER_ID, CrmPermissionLevelEnum.OWNER)); | ||
| 211 | + mockCrmAdmin(true); | ||
| 212 | + | ||
| 213 | + // 调用,并断言异常 | ||
| 214 | + assertServiceException(() -> permissionService.transferPermission(buildTransferReqBO(OWNER_USER_ID, null)), | ||
| 215 | + CRM_PERMISSION_MODEL_TRANSFER_FAIL_OWNER_USER_EXISTS, BIZ_TYPE_NAME); | ||
| 216 | + assertNoPermissionWrite(); | ||
| 217 | + verifyNoInteractions(adminUserApi); | ||
| 218 | + } | ||
| 219 | + | ||
| 220 | + @Test | ||
| 221 | + public void testTransferPermission_crmAdminOwnerNotExists() { | ||
| 222 | + // mock 数据:CRM 管理员有 WRITE 团队权限,但数据缺少负责人 | ||
| 223 | + mockPermissions(buildPermission(LOGIN_USER_PERMISSION_ID, LOGIN_USER_ID, CrmPermissionLevelEnum.WRITE), | ||
| 224 | + buildPermission(NEW_OWNER_PERMISSION_ID, NEW_OWNER_USER_ID, CrmPermissionLevelEnum.READ)); | ||
| 225 | + mockCrmAdmin(true); | ||
| 226 | + | ||
| 227 | + // 调用,并断言异常:在修改任何权限前失败 | ||
| 228 | + assertServiceException(() -> permissionService.transferPermission(buildTransferReqBO(NEW_OWNER_USER_ID, null)), | ||
| 229 | + CRM_PERMISSION_NOT_EXISTS); | ||
| 230 | + assertNoPermissionWrite(); | ||
| 231 | + verifyNoInteractions(adminUserApi); | ||
| 232 | + } | ||
| 233 | + | ||
| 234 | + @Test | ||
| 235 | + public void testTransferPermission_newOwnerNotExists() { | ||
| 236 | + // mock 数据:CRM 管理员没有权限,数据的负责人是其他人 | ||
| 237 | + mockPermissions(buildPermission(OWNER_PERMISSION_ID, OWNER_USER_ID, CrmPermissionLevelEnum.OWNER)); | ||
| 238 | + mockCrmAdmin(true); | ||
| 239 | + // mock 方法:新负责人不存在 | ||
| 240 | + doThrow(exception(USER_NOT_EXISTS)).when(adminUserApi) | ||
| 241 | + .validateUserList(Collections.singletonList(NEW_OWNER_USER_ID)); | ||
| 242 | + | ||
| 243 | + // 调用,并断言异常:在修改任何权限前失败 | ||
| 244 | + assertServiceException(() -> permissionService.transferPermission(buildTransferReqBO(NEW_OWNER_USER_ID, null)), | ||
| 245 | + USER_NOT_EXISTS); | ||
| 246 | + assertNoPermissionWrite(); | ||
| 247 | + } | ||
| 248 | + | ||
| 249 | + private void mockCrmAdmin(boolean crmAdmin) { | ||
| 250 | + springUtilMockedStatic.when(() -> SpringUtil.getBean(PermissionCommonApi.class)).thenReturn(permissionCommonApi); | ||
| 251 | + when(permissionCommonApi.hasAnyRoles(LOGIN_USER_ID, RoleCodeEnum.CRM_ADMIN.getCode())).thenReturn(crmAdmin); | ||
| 252 | + } | ||
| 253 | + | ||
| 254 | + private void mockPermissions(CrmPermissionDO... permissions) { | ||
| 255 | + List<CrmPermissionDO> list = Arrays.asList(permissions); | ||
| 256 | + when(permissionMapper.selectByBizTypeAndBizId(BIZ_TYPE, BIZ_ID)).thenReturn(list); | ||
| 257 | + } | ||
| 258 | + | ||
| 259 | + private void verifyNewOwnerInserted() { | ||
| 260 | + verify(permissionMapper).insert(argThat((CrmPermissionDO permission) -> | ||
| 261 | + permission.getId() == null | ||
| 262 | + && Objects.equals(permission.getBizType(), BIZ_TYPE) | ||
| 263 | + && Objects.equals(permission.getBizId(), BIZ_ID) | ||
| 264 | + && Objects.equals(permission.getUserId(), NEW_OWNER_USER_ID) | ||
| 265 | + && CrmPermissionLevelEnum.isOwner(permission.getLevel()))); | ||
| 266 | + } | ||
| 267 | + | ||
| 268 | + private void verifyLevelUpdated(Long id, CrmPermissionLevelEnum level) { | ||
| 269 | + verify(permissionMapper).updateById(argThat((CrmPermissionDO permission) -> | ||
| 270 | + Objects.equals(permission.getId(), id) && Objects.equals(permission.getLevel(), level.getLevel()))); | ||
| 271 | + } | ||
| 272 | + | ||
| 273 | + private void assertNoPermissionWrite() { | ||
| 274 | + verify(permissionMapper).selectByBizTypeAndBizId(BIZ_TYPE, BIZ_ID); | ||
| 275 | + verifyNoMoreInteractions(permissionMapper); | ||
| 276 | + } | ||
| 277 | + | ||
| 278 | + private static CrmPermissionTransferReqBO buildTransferReqBO(Long newOwnerUserId, Integer oldOwnerPermissionLevel) { | ||
| 279 | + return new CrmPermissionTransferReqBO(LOGIN_USER_ID, BIZ_TYPE, BIZ_ID, newOwnerUserId, oldOwnerPermissionLevel); | ||
| 280 | + } | ||
| 281 | + | ||
| 282 | + private static CrmPermissionDO buildPermission(Long id, Long userId, CrmPermissionLevelEnum level) { | ||
| 283 | + return new CrmPermissionDO().setId(id).setBizType(BIZ_TYPE).setBizId(BIZ_ID) | ||
| 284 | + .setUserId(userId).setLevel(level.getLevel()); | ||
| 285 | + } | ||
| 286 | + | ||
| 287 | +} |