code review:crm 权限模块的实现

This commit is contained in:
zhijiantianya@gmail.com 2023-11-03 18:53:40 +08:00
parent 68c9d563bc
commit 4092f298ed
18 changed files with 67 additions and 18 deletions

View File

@ -21,6 +21,7 @@ public class CrmBusinessTransferReqVO {
@Schema(description = "新负责人的用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430")
private Long newOwnerUserId;
// TODO @puhui999joinTeam 可以合并成 permissionLevel oldOwnerPermissionLevel这样 null 说明移除因为都换负责人啦
/**
* 老负责人是否加入团队/
*/

View File

@ -21,13 +21,13 @@ public class CrmContactTransferReqVO {
@Schema(description = "新负责人的用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430")
private Long newOwnerUserId;
// TODO @puhui999joinTeam 可以合并成 permissionLevel oldOwnerPermissionLevel这样 null 说明移除因为都换负责人啦
/**
* 老负责人是否加入团队/
*/
@Schema(description = "老负责人是否加入团队", requiredMode = Schema.RequiredMode.REQUIRED, example = "false")
@NotNull(message = "老负责人是否加入团队不能为空")
private Boolean joinTeam;
/**
* 老负责人加入团队后的权限级别如果 {@link #joinTeam} false, permissionLevel null
* 关联 {@link CrmPermissionLevelEnum}

View File

@ -21,6 +21,7 @@ public class CrmContractTransferReqVO {
@Schema(description = "新负责人的用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430")
private Long newOwnerUserId;
// TODO @puhui999joinTeam 可以合并成 permissionLevel oldOwnerPermissionLevel这样 null 说明移除因为都换负责人啦
/**
* 老负责人是否加入团队/
*/

View File

@ -21,6 +21,7 @@ public class CrmCustomerTransferReqVO {
@Schema(description = "新负责人的用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430")
private Long newOwnerUserId;
// TODO @puhui999joinTeam 可以合并成 permissionLevel oldOwnerPermissionLevel这样 null 说明移除因为都换负责人啦
/**
* 老负责人是否加入团队/
*/

View File

@ -48,9 +48,11 @@ public class CrmPermissionController {
@Resource
private List<CrmPermissionValidateService> permissionValidateServices;
// TODO @puhui999这个能不能使用 CrmPermission 注解替代
private void validatePermission(Integer bizType, Long bizId) {
// 1. TODO 校验是否为超级管理员
// 2. 防御一手如果是超级管理员不校验权限还是得校验一下数据是否存在
// TODO @puhui999是不是不用校验每个业务方的数据是否存在其实不是很关键哈简单一点~ 说白了负责人只要在它的数据就是存在~
permissionValidateServices.forEach(item -> {
if (!item.validateBizIdExists(bizType, bizId)) {
throw exception(CRM_PERMISSION_MODEL_NOT_EXISTS, getNameByType(bizType));
@ -90,9 +92,11 @@ public class CrmPermissionController {
return success(true);
}
// TODO @puhui999deletemapping
@GetMapping("/delete")
@Operation(summary = "移除团队成员")
@Parameter(name = "id", description = "团队成员编号", required = true)
// TODO @puhui999是不是 id 参数就够了
@PreAuthorize("@ss.hasPermission('crm:permission:delete')")
public CommonResult<Boolean> deletePermission(@RequestParam("bizType") Integer bizType,
@RequestParam("bizId") Long bizId,
@ -105,6 +109,8 @@ public class CrmPermissionController {
return success(true);
}
// TODO @puhui999这个是哪个地方使用到哈
// TODO @puhui999是不是 deletemapping
@GetMapping("/quit")
@Operation(summary = "退出团队")
@Parameters({
@ -114,9 +120,10 @@ public class CrmPermissionController {
@PreAuthorize("@ss.hasPermission('crm:permission:delete')")
public CommonResult<Boolean> quitPermission(@RequestParam("bizType") Integer bizType,
@RequestParam("bizId") Long bizId) {
// 没有就不是团队成员
CrmPermissionDO permission = crmPermissionService.getPermissionByBizTypeAndBizIdAndUserId(
bizType, bizId, getLoginUserId());
if (permission == null) { // 没有就不是团队成员
if (permission == null) {
return success(false);
}
crmPermissionService.deletePermission(permission.getId());
@ -136,6 +143,7 @@ public class CrmPermissionController {
if (CollUtil.isEmpty(permission)) {
return success(Collections.emptyList());
}
// TODO @puhui999池子的逻辑
permission.removeIf(item -> ObjUtil.equal(item.getUserId(), CrmPermissionDO.POOL_USER_ID)); // 排除
// 拼接数据

View File

@ -30,6 +30,7 @@ public class CrmPermissionBaseVO {
@NotNull(message = "Crm 类型数据编号不能为空")
private Long bizId;
// TODO @puhui999level
@Schema(description = "权限级别", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
@InEnum(CrmPermissionLevelEnum.class)
@NotNull(message = "权限级别不能为空")

View File

@ -12,9 +12,11 @@ public class CrmPermissionRespVO extends CrmPermissionBaseVO {
@Schema(description = "数据权限编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563")
private Long id;
// TODO @puhui999搞到字典里
@Schema(description = "团队级别", requiredMode = Schema.RequiredMode.REQUIRED, example = "负责人")
private String permissionLevelName;
// TODO @puhui999deptIdpostIds 是不是要提供中文名哈
@Schema(description = "部门编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long deptId;

View File

@ -12,6 +12,9 @@ import lombok.ToString;
public class CrmPermissionUpdateReqVO extends CrmPermissionBaseVO {
@Schema(description = "数据权限编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563")
// TODO @puhui999非空判断
private Long id;
// TODO @puhui999是不是只更新 permission
}

View File

@ -23,6 +23,7 @@ import lombok.*;
@AllArgsConstructor
public class CrmPermissionDO extends BaseDO {
// TODO puhui999是不是公海的数据就不插入了
/**
* 当数据变为公海数据时也就是数据团队成员中没有负责人的时候将原本的负责人 userId 设置为 POOL_USER_ID 方便查询公海数据
* 也就是说每条数据到最后都有一个负责人如果有人领取则 userId 为领取人
@ -34,22 +35,35 @@ public class CrmPermissionDO extends BaseDO {
*/
@TableId
private Long id;
/**
* 数据类型关联 {@link CrmBizTypeEnum}
* 数据类型
*
* 枚举 {@link CrmBizTypeEnum}
*/
private Integer bizType;
/**
* 数据编号关联 {@link CrmBizTypeEnum} 对应模块 DO#getId()
* 数据编号
*
* 关联 {@link CrmBizTypeEnum} 对应模块 DO id 字段
*/
private Long bizId;
/**
* 团队成员关联 AdminUser#id
* 团队成员
*
* 关联 AdminUser id 字段
*
* 如果为公海数据的话会干掉此数据的负责人后设置为 {@link #POOL_USER_ID}领取人则上位负责人
* 客户放入公海后会干掉团队成员中的负责人而其他团队成员则不受影响
*/
private Long userId;
// TODO @puhui999是不是搞成 level 字段简洁一点主要表明已经 perssmion 实体里了
/**
* 权限级别关联 {@link CrmPermissionLevelEnum}
* 权限级别
*
* 关联 {@link CrmPermissionLevelEnum}
*/
private Integer permissionLevel;

View File

@ -18,6 +18,7 @@ import java.util.List;
@Mapper
public interface CrmPermissionMapper extends BaseMapperX<CrmPermissionDO> {
// TODO @puhui999是不是不用谢这个注释因为方法名可以自解释
/**
* 获取用户数据权限通过 数据类型 x 某个数据 x 用户编号
*
@ -33,6 +34,7 @@ public interface CrmPermissionMapper extends BaseMapperX<CrmPermissionDO> {
.eq(CrmPermissionDO::getUserId, userId));
}
// TODO @puhui999是不是不用谢这个注释因为方法名可以自解释
/**
* 获取数据权限列表通过 数据类型 x 某个数据
*

View File

@ -26,12 +26,14 @@ public @interface CrmPermission {
*/
CrmBizTypeEnum bizType();
// TODO @puhui999id通过 spring el 表达式获取
/**
* 数据编号获取来源类确保数据 id 编号在此类中不能在父类中
* 如果在 baseVO 中需要把 id 弄到 updateVO
*/
Class<?>[] getIdFor() default {};
// TODO @puhui999是不是搞成 level 字段简洁一点主要表明已经 perssmion 实体里了
/**
* 操作类型
*/

View File

@ -43,6 +43,7 @@ public class CrmPermissionAspect {
return WebFrameworkUtils.getLoginUserId();
}
// TODO @puhui999id通过 spring el 表达式获取
private Long getBizId(JoinPoint joinPoint, CrmPermission crmPermission) throws NoSuchFieldException, IllegalAccessException {
Object[] args = joinPoint.getArgs();
for (Object arg : args) {
@ -61,6 +62,7 @@ public class CrmPermissionAspect {
return null;
}
// TODO @puhui999一般核心的方法放到最前面private 放后面主要是主次要分出来哈
@Before("@annotation(crmPermission)")
public void doBefore(JoinPoint joinPoint, CrmPermission crmPermission) {
try {
@ -75,12 +77,17 @@ public class CrmPermissionAspect {
// 1. 获取数据权限
List<CrmPermissionDO> bizPermissions = crmPermissionService.getPermissionByBizTypeAndBizId(bizType, bizId);
// TODO puhui999这种情况下最好是 CrmPermissionLevelEnum.isOwner
// 2.1 情况一如果自己是负责人则默认有所有权限
// TODO @puhui999会不会存在空指针的问题
CrmPermissionDO userPermission = CollUtil.findOne(bizPermissions, item -> ObjUtil.equal(item.getUserId(), getUserId()));
if (isOwner(userPermission.getPermissionLevel())) { // 校验自己是否是负责人
if (isOwner(userPermission.getPermissionLevel())) {
return;
}
if (isRead(permissionLevel)) { // 读权限
// 2.2 情况二校验自己是否有读权限
if (isRead(permissionLevel)) {
// 如果没有数据权限或没有负责人则表示此记录为公海数据所有人都有只读权限可以领取成为负责人团队成员领取的
// TODO @puhui99989 92 这块的逻辑感觉可以不用 @CrmPermission公海那自己 check 即可
if (CollUtil.isEmpty(bizPermissions) || CollUtil.anyMatch(bizPermissions,
item -> ObjUtil.equal(item.getUserId(), CrmPermissionDO.POOL_USER_ID))) { // 详见 CrmPermissionDO.POOL_USER_ID 注释
return;
@ -93,15 +100,18 @@ public class CrmPermissionAspect {
return;
}
}
if (isWrite(permissionLevel)) { // 写权限
// 2.3 情况三校验自己是否有写权限
if (isWrite(permissionLevel)) {
if (isWrite(userPermission.getPermissionLevel())) { // 校验当前用户是否有写权限
return;
}
}
// 2. 没通过结束报错 {}操作失败原因没有权限
// 3. 没通过结束报错 {} 操作失败原因没有权限
// TODO @puhui999这里打个 info 日志方便后续排查问题审计
throw exception(CRM_PERMISSION_DENIED, crmPermission.bizType().getName());
} catch (Exception ex) {
// TODO @puhui999不用 catch 就是系统异常
log.error("[doBefore][crmPermission({}) 数据校验错误]", toJsonString(crmPermission), ex);
// TODO 报错抛个什么异常好呢
throw exception(CRM_PERMISSION_DENIED, crmPermission.bizType().getName());

View File

@ -33,6 +33,7 @@ public enum CrmBizTypeEnum implements IntArrayValuable {
private final String name;
public static String getNameByType(Integer type) {
// TODO @puhui999可以 findone更简洁另外不存在返回 null 即可啦
for (CrmBizTypeEnum crmBizTypeEnum : CrmBizTypeEnum.values()) {
if (ObjUtil.equal(crmBizTypeEnum.type, type)) {
return crmBizTypeEnum.name;

View File

@ -19,6 +19,7 @@ public enum CrmPermissionLevelEnum implements IntArrayValuable {
OWNER(1, "负责人"),
READ(2, ""),
WRITE(3, "");
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CrmPermissionLevelEnum::getLevel).toArray();
/**
@ -48,6 +49,7 @@ public enum CrmPermissionLevelEnum implements IntArrayValuable {
}
public static String getNameByLevel(Integer level) {
// TODO @puhui999可以 findone更简洁另外不存在返回 null 即可啦
for (CrmPermissionLevelEnum levelEnum : CrmPermissionLevelEnum.values()) {
if (ObjUtil.equal(levelEnum.level, level)) {
return levelEnum.name;

View File

@ -55,6 +55,7 @@ public class CrmPermissionServiceImpl implements CrmPermissionService {
@Override
@Transactional(rollbackFor = Exception.class)
public void updatePermission(CrmPermissionUpdateReqBO updateBO) {
// TODO @puhui999这里 1.1 1.2下面 2.这样更有序一点
// 1. 校验用户是否存在
adminUserApi.validateUserList(Collections.singletonList(updateBO.getUserId()));
// 2. 校验存在
@ -91,7 +92,6 @@ public class CrmPermissionServiceImpl implements CrmPermissionService {
}
}
@Override
public void transferPermission(CrmTransferPermissionReqBO transferReqBO) {
// 1. 校验数据权限-是否是负责人只有负责人才可以转移
@ -103,6 +103,7 @@ public class CrmPermissionServiceImpl implements CrmPermissionService {
throw exception(CRM_PERMISSION_DENIED, crmName);
}
// TODO @puhui999这个顺序编号看看调整下2. 后面是 2.1 结果没 2.2 有点怪
// 2. 校验转移对象是否已经是该负责人
if (ObjUtil.equal(transferReqBO.getNewOwnerUserId(), oldPermission.getUserId())) {
throw exception(CRM_PERMISSION_MODEL_TRANSFER_FAIL_OWNER_USER_EXISTS, crmName);

View File

@ -27,16 +27,15 @@ public class CrmPermissionCreateReqBO {
@NotNull(message = "Crm 类型不能为空")
@InEnum(CrmBizTypeEnum.class)
private Integer bizType;
/**
* 数据编号
*/
@NotNull(message = "Crm 数据编号不能为空")
private Long bizId;
// TODO @puhui999简化成 level
/**
* 权限级别
* 关联 {@link CrmPermissionLevelEnum}
*/
@NotNull(message = "权限级别不能为空")
@InEnum(CrmPermissionLevelEnum.class)

View File

@ -17,7 +17,7 @@ import javax.validation.constraints.NotNull;
public class CrmPermissionUpdateReqBO {
/**
* 数据权限编号 {@link CrmPermissionDO#getId()}
* 数据权限编号
*/
@NotNull(message = "Crm 数据权限编号不能为空")
private Long id;
@ -28,22 +28,22 @@ public class CrmPermissionUpdateReqBO {
@NotNull(message = "用户编号不能为空")
private Long userId;
// TODO @puhui999id 字段 bizType + bizId 是否二选一
/**
* Crm 类型
*/
@NotNull(message = "Crm 类型不能为空")
@InEnum(CrmBizTypeEnum.class)
private Integer bizType;
/**
* 数据编号
*/
@NotNull(message = "Crm 数据编号不能为空")
private Long bizId;
// TODO @puhui999简化成 level
/**
* 权限级别
* 关联 {@link CrmPermissionLevelEnum}
*/
@NotNull(message = "权限级别不能为空")
@InEnum(CrmPermissionLevelEnum.class)

View File

@ -7,6 +7,7 @@ import lombok.Data;
import javax.validation.constraints.NotNull;
// TODO @puhui999CrmPermissionTransferReqBO
/**
* 数据权限转移 Request BO
*
@ -27,7 +28,6 @@ public class CrmTransferPermissionReqBO {
@NotNull(message = "Crm 类型不能为空")
@InEnum(CrmBizTypeEnum.class)
private Integer bizType;
/**
* 数据编号
*/
@ -40,6 +40,7 @@ public class CrmTransferPermissionReqBO {
@NotNull(message = "新负责人的用户编号不能为空")
private Long newOwnerUserId;
// TODO @puhui999joinTeam 可以合并成 permissionLevel oldOwnerPermissionLevel这样 null 说明移除因为都换负责人啦
/**
* 老负责人是否加入团队/
*/