CRM-数据权限:完善 code review 提到的问题

This commit is contained in:
puhui999 2023-11-07 17:52:18 +08:00
parent ecf728966f
commit 668fae9398
36 changed files with 346 additions and 353 deletions

View File

@ -21,19 +21,11 @@ public class CrmBusinessTransferReqVO {
@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
* 老负责人加入团队后的权限级别如果 null 说明移除
* 关联 {@link CrmPermissionLevelEnum}
*/
@Schema(description = "老负责人加入团队后的权限级别", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
private Integer permissionLevel;
private Integer oldOwnerPermissionLevel;
}

View File

@ -21,18 +21,11 @@ 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
* 老负责人加入团队后的权限级别如果 null 说明移除
* 关联 {@link CrmPermissionLevelEnum}
*/
@Schema(description = "老负责人加入团队后的权限级别", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
private Integer permissionLevel;
private Integer oldOwnerPermissionLevel;
}

View File

@ -21,19 +21,11 @@ public class CrmContractTransferReqVO {
@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
* 老负责人加入团队后的权限级别如果 null 说明移除
* 关联 {@link CrmPermissionLevelEnum}
*/
@Schema(description = "老负责人加入团队后的权限级别", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
private Integer permissionLevel;
private Integer oldOwnerPermissionLevel;
}

View File

@ -21,19 +21,11 @@ public class CrmCustomerTransferReqVO {
@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
* 老负责人加入团队后的权限级别如果 null 说明移除
* 关联 {@link CrmPermissionLevelEnum}
*/
@Schema(description = "老负责人加入团队后的权限级别", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
private Integer permissionLevel;
private Integer oldOwnerPermissionLevel;
}

View File

@ -0,0 +1,32 @@
### 请求 /add
PUT {{baseUrl}}/crm/permission/add
Content-Type: application/json
Authorization: Bearer {{token}}
tenant-id: {{adminTenentId}}
{
"userId": 1,
"bizType": 2,
"bizId": 2,
"level": 1
}
### 请求 /update
PUT {{baseUrl}}/crm/permission/update
Content-Type: application/json
Authorization: Bearer {{token}}
tenant-id: {{adminTenentId}}
{
"userId": 1,
"bizType": 2,
"bizId": 2,
"level": 1,
"id": 1
}
### 请求 /delete
DELETE {{baseUrl}}/crm/permission/delete?bizType=2&bizId=1&id=1
Authorization: Bearer {{token}}
tenant-id: {{adminTenentId}}

View File

@ -8,8 +8,14 @@ import cn.iocoder.yudao.module.crm.controller.admin.permission.vo.CrmPermissionR
import cn.iocoder.yudao.module.crm.controller.admin.permission.vo.CrmPermissionUpdateReqVO;
import cn.iocoder.yudao.module.crm.convert.permission.CrmPermissionConvert;
import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO;
import cn.iocoder.yudao.module.crm.framework.core.service.CrmPermissionValidateService;
import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission;
import cn.iocoder.yudao.module.crm.framework.enums.CrmBizTypeEnum;
import cn.iocoder.yudao.module.crm.framework.enums.CrmPermissionLevelEnum;
import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService;
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
import cn.iocoder.yudao.module.system.api.dept.PostApi;
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
import cn.iocoder.yudao.module.system.api.dept.dto.PostRespDTO;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import io.swagger.v3.oas.annotations.Operation;
@ -24,15 +30,12 @@ import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CRM_PERMISSION_DENIED;
import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CRM_PERMISSION_MODEL_NOT_EXISTS;
import static cn.iocoder.yudao.module.crm.framework.enums.CrmBizTypeEnum.getNameByType;
import static cn.iocoder.yudao.module.crm.framework.enums.CrmPermissionLevelEnum.isOwner;
@Tag(name = "管理后台 - CRM 数据权限(数据团队成员操作)")
@RestController
@ -46,34 +49,16 @@ public class CrmPermissionController {
@Resource
private AdminUserApi adminUserApi;
@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));
}
});
// 3. 校验数据权限 如果存在则表示 bizId 也存在
CrmPermissionDO permission = crmPermissionService.getPermissionByBizTypeAndBizIdAndUserId(
bizType, bizId, getLoginUserId());
if (isOwner(permission.getPermissionLevel())) { // 只有负责人才可以操作团队成员
return;
}
throw exception(CRM_PERMISSION_DENIED, getNameByType(bizType));
}
private DeptApi deptApi;
@Resource
private PostApi postApi;
@PutMapping("/add")
@Operation(summary = "添加团队成员")
@PreAuthorize("@ss.hasPermission('crm:permission:create')")
@CrmPermission(bizType = CrmBizTypeEnum.CRM_PERMISSION, bizTypeValue = "#reqVO.bizType", bizId = "#reqVO.bizId"
, level = CrmPermissionLevelEnum.OWNER)
public CommonResult<Boolean> addPermission(@Valid @RequestBody CrmPermissionCreateReqVO reqVO) {
// 1. 前置校验
validatePermission(reqVO.getBizType(), reqVO.getBizId());
// 2. 加入成员
crmPermissionService.createPermission(CrmPermissionConvert.INSTANCE.convert(reqVO));
return success(true);
@ -83,53 +68,30 @@ public class CrmPermissionController {
@PutMapping("/update")
@Operation(summary = "编辑团队成员")
@PreAuthorize("@ss.hasPermission('crm:permission:update')")
@CrmPermission(bizType = CrmBizTypeEnum.CRM_PERMISSION, bizTypeValue = "#updateReqVO.bizType", bizId = "#updateReqVO.bizId"
, level = CrmPermissionLevelEnum.WRITE)
public CommonResult<Boolean> updatePermission(@Valid @RequestBody CrmPermissionUpdateReqVO updateReqVO) {
// 1. 前置校验
validatePermission(updateReqVO.getBizType(), updateReqVO.getBizId());
// 2. 编辑团队成员
crmPermissionService.updatePermission(CrmPermissionConvert.INSTANCE.convert(updateReqVO));
return success(true);
}
// TODO @puhui999deletemapping
@GetMapping("/delete")
@DeleteMapping("/delete")
@Operation(summary = "移除团队成员")
@Parameter(name = "id", description = "团队成员编号", required = true)
// TODO @puhui999是不是 id 参数就够了
@Parameters({
@Parameter(name = "bizType", description = "CRM 类型", required = true, example = "2"),
@Parameter(name = "bizId", description = "CRM 类型数据编号", required = true, example = "1024"),
@Parameter(name = "id", description = "团队成员编号", required = true, example = "1024")
})
@PreAuthorize("@ss.hasPermission('crm:permission:delete')")
@CrmPermission(bizType = CrmBizTypeEnum.CRM_PERMISSION, bizTypeValue = "#bizType", bizId = "#bizId"
, level = CrmPermissionLevelEnum.OWNER)
public CommonResult<Boolean> deletePermission(@RequestParam("bizType") Integer bizType,
@RequestParam("bizId") Long bizId,
@RequestParam("id") Long id) {
// 1. 前置校验
validatePermission(bizType, bizId);
// 2. 移除团队成员
crmPermissionService.deletePermission(id);
return success(true);
}
// TODO @puhui999这个是哪个地方使用到哈
// TODO @puhui999是不是 deletemapping
@GetMapping("/quit")
@Operation(summary = "退出团队")
@Parameters({
@Parameter(name = "bizType", description = "CRM 类型", required = true, example = "2"),
@Parameter(name = "bizId", description = "CRM 类型数据编号", required = true, example = "1024")
})
@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) {
return success(false);
}
crmPermissionService.deletePermission(permission.getId());
return success(true);
}
@GetMapping("/list")
@Operation(summary = "获取团队成员")
@Parameters({
@ -148,7 +110,10 @@ public class CrmPermissionController {
// 拼接数据
List<AdminUserRespDTO> userList = adminUserApi.getUserList(convertSet(permission, CrmPermissionDO::getUserId));
return success(CrmPermissionConvert.INSTANCE.convert(permission, userList));
Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userList, AdminUserRespDTO::getDeptId));
Set<Long> postIds = userList.stream().flatMap(item -> item.getPostIds().stream()).collect(Collectors.toSet());
Map<Long, PostRespDTO> postMap = postApi.getPostMap(postIds);
return success(CrmPermissionConvert.INSTANCE.convert(permission, userList, deptMap, postMap));
}
}

View File

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

View File

@ -12,18 +12,13 @@ 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;
@Schema(description = "部门名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "研发部")
private String deptName;
@Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿")
private String nickname;
@Schema(description = "岗位编号数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1,2,3]")
private Set<Long> postIds;
@Schema(description = "岗位名称数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "[BOOS,经理]")
private Set<String> postNames;
}

View File

@ -5,6 +5,8 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import javax.validation.constraints.NotNull;
@Schema(description = "管理后台 - CRM 数据权限更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ -12,9 +14,9 @@ import lombok.ToString;
public class CrmPermissionUpdateReqVO extends CrmPermissionBaseVO {
@Schema(description = "数据权限编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563")
// TODO @puhui999非空判断
@NotNull(message = "数据权限编号不能为空")
private Long id;
// TODO @puhui999是不是只更新 permission
// TODO @puhui999是不是只更新 permission 是的
}

View File

@ -4,7 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.*;
import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO;
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionPageReqBO;
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmTransferPermissionReqBO;
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
@ -36,7 +36,7 @@ public interface CrmBusinessConvert {
@Mapping(target = "bizId", source = "reqVO.id"),
@Mapping(target = "newOwnerUserId", source = "reqVO.id")
})
CrmTransferPermissionReqBO convert(CrmBusinessTransferReqVO reqVO, Long userId);
CrmPermissionTransferReqBO convert(CrmBusinessTransferReqVO reqVO, Long userId);
CrmPermissionPageReqBO convert(CrmBusinessPageReqVO pageReqVO);

View File

@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.crm.convert.contact;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.*;
import cn.iocoder.yudao.module.crm.dal.dataobject.contact.ContactDO;
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmTransferPermissionReqBO;
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
@ -37,6 +37,6 @@ public interface ContactConvert {
@Mapping(target = "bizId", source = "reqVO.id"),
@Mapping(target = "newOwnerUserId", source = "reqVO.id")
})
CrmTransferPermissionReqBO convert(CrmContactTransferReqVO reqVO, Long userId);
CrmPermissionTransferReqBO convert(CrmContactTransferReqVO reqVO, Long userId);
}

View File

@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.crm.convert.contract;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.*;
import cn.iocoder.yudao.module.crm.dal.dataobject.contract.ContractDO;
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmTransferPermissionReqBO;
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
@ -37,6 +37,6 @@ public interface ContractConvert {
@Mapping(target = "bizId", source = "reqVO.id"),
@Mapping(target = "newOwnerUserId", source = "reqVO.id")
})
CrmTransferPermissionReqBO convert(CrmContractTransferReqVO reqVO, Long userId);
CrmPermissionTransferReqBO convert(CrmContractTransferReqVO reqVO, Long userId);
}

View File

@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.crm.convert.customer;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.*;
import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmTransferPermissionReqBO;
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
@ -35,6 +35,6 @@ public interface CrmCustomerConvert {
@Mapping(target = "bizId", source = "reqVO.id"),
@Mapping(target = "newOwnerUserId", source = "reqVO.id")
})
CrmTransferPermissionReqBO convert(CrmCustomerTransferReqVO reqVO, Long userId);
CrmPermissionTransferReqBO convert(CrmCustomerTransferReqVO reqVO, Long userId);
}

View File

@ -8,15 +8,16 @@ import cn.iocoder.yudao.module.crm.controller.admin.permission.vo.CrmPermissionU
import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO;
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO;
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionUpdateReqBO;
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
import cn.iocoder.yudao.module.system.api.dept.dto.PostRespDTO;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import com.google.common.collect.Multimaps;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import java.util.List;
import java.util.Map;
import static cn.iocoder.yudao.module.crm.framework.enums.CrmPermissionLevelEnum.getNameByLevel;
/**
* Crm 数据权限 Convert
*
@ -37,12 +38,17 @@ public interface CrmPermissionConvert {
List<CrmPermissionRespVO> convert(List<CrmPermissionDO> permission);
default List<CrmPermissionRespVO> convert(List<CrmPermissionDO> permission, List<AdminUserRespDTO> userList) {
default List<CrmPermissionRespVO> convert(List<CrmPermissionDO> permission, List<AdminUserRespDTO> userList,
Map<Long, DeptRespDTO> deptMap, Map<Long, PostRespDTO> postMap) {
Map<Long, AdminUserRespDTO> userMap = CollectionUtils.convertMap(userList, AdminUserRespDTO::getId);
return CollectionUtils.convertList(convert(permission), item -> {
MapUtils.findAndThen(userMap, item.getId(), user -> {
item.setNickname(user.getNickname()).setDeptId(user.getDeptId()).setPostIds(user.getPostIds())
.setPermissionLevelName(getNameByLevel(item.getPermissionLevel()));
item.setNickname(user.getNickname());
MapUtils.findAndThen(deptMap, user.getDeptId(), deptRespDTO -> {
item.setDeptName(deptRespDTO.getName());
});
List<PostRespDTO> postRespList = MapUtils.getList(Multimaps.forMap(postMap), user.getPostIds());
item.setPostNames(CollectionUtils.convertSet(postRespList, PostRespDTO::getName));
});
return item;
});

View File

@ -23,7 +23,7 @@ import lombok.*;
@AllArgsConstructor
public class CrmPermissionDO extends BaseDO {
// TODO puhui999是不是公海的数据就不插入了
// TODO puhui999是不是公海的数据就不插入了这样方便获取公海数据鸭
/**
* 当数据变为公海数据时也就是数据团队成员中没有负责人的时候将原本的负责人 userId 设置为 POOL_USER_ID 方便查询公海数据
* 也就是说每条数据到最后都有一个负责人如果有人领取则 userId 为领取人
@ -59,12 +59,11 @@ public class CrmPermissionDO extends BaseDO {
*/
private Long userId;
// TODO @puhui999是不是搞成 level 字段简洁一点主要表明已经 perssmion 实体里了
/**
* 权限级别
*
* 关联 {@link CrmPermissionLevelEnum}
*/
private Integer permissionLevel;
private Integer level;
}

View File

@ -4,7 +4,6 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO;
import cn.iocoder.yudao.module.crm.framework.enums.CrmBizTypeEnum;
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionPageReqBO;
import org.apache.ibatis.annotations.Mapper;
@ -18,15 +17,6 @@ import java.util.List;
@Mapper
public interface CrmPermissionMapper extends BaseMapperX<CrmPermissionDO> {
// TODO @puhui999是不是不用谢这个注释因为方法名可以自解释
/**
* 获取用户数据权限通过 数据类型 x 某个数据 x 用户编号
*
* @param bizType 数据类型关联 {@link CrmBizTypeEnum}
* @param bizId 数据编号关联 {@link CrmBizTypeEnum} 对应模块 DO#getId()
* @param userId 用户编号AdminUser#id
* @return Crm 数据权限
*/
default CrmPermissionDO selectByBizTypeAndBizIdByUserId(Integer bizType, Long bizId, Long userId) {
return selectOne(new LambdaQueryWrapperX<CrmPermissionDO>()
.eq(CrmPermissionDO::getBizType, bizType)
@ -34,14 +24,6 @@ public interface CrmPermissionMapper extends BaseMapperX<CrmPermissionDO> {
.eq(CrmPermissionDO::getUserId, userId));
}
// TODO @puhui999是不是不用谢这个注释因为方法名可以自解释
/**
* 获取数据权限列表通过 数据类型 x 某个数据
*
* @param bizType 数据类型关联 {@link CrmBizTypeEnum}
* @param bizId 数据编号关联 {@link CrmBizTypeEnum} 对应模块 DO#getId()
* @return Crm 数据权限列表
*/
default List<CrmPermissionDO> selectByBizTypeAndBizId(Integer bizType, Long bizId) {
return selectList(new LambdaQueryWrapperX<CrmPermissionDO>()
.eq(CrmPermissionDO::getBizType, bizType)

View File

@ -26,17 +26,21 @@ public @interface CrmPermission {
*/
CrmBizTypeEnum bizType();
// TODO @puhui999id通过 spring el 表达式获取
/**
* 数据编号获取来源类确保数据 id 编号在此类中不能在父类中
* 如果在 baseVO 中需要把 id 弄到 updateVO
* crm 类型扩展
* 用于 CrmPermissionController 团队权限校验
*/
Class<?>[] getIdFor() default {};
String bizTypeValue() default "";
// TODO @puhui999是不是搞成 level 字段简洁一点主要表明已经 perssmion 实体里了
/**
* 操作类型
* 数据编号通过 spring el 表达式获取
* TODO 数据权限完成后去除 default ""
*/
CrmPermissionLevelEnum permissionLevel();
String bizId() default "";
/**
* 操作所需权限级别
*/
CrmPermissionLevelEnum level();
}

View File

@ -2,24 +2,32 @@ package cn.iocoder.yudao.module.crm.framework.core.aop;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import cn.iocoder.yudao.framework.common.core.KeyValue;
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO;
import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission;
import cn.iocoder.yudao.module.crm.framework.enums.CrmBizTypeEnum;
import cn.iocoder.yudao.module.crm.framework.enums.CrmPermissionLevelEnum;
import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CRM_PERMISSION_DENIED;
import static cn.iocoder.yudao.module.crm.framework.enums.CrmPermissionLevelEnum.*;
/**
* Crm 数据权限校验 AOP 切面
@ -31,6 +39,11 @@ import static cn.iocoder.yudao.module.crm.framework.enums.CrmPermissionLevelEnum
@Slf4j
public class CrmPermissionAspect {
@Resource
private LocalVariableTableParameterNameDiscoverer discoverer;
@Resource
private SpelExpressionParser parser;
@Resource
private CrmPermissionService crmPermissionService;
@ -43,83 +56,109 @@ 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) {
if (arg == null) {
continue;
}
if (ObjUtil.notEqual(arg.getClass().getName(), crmPermission.getIdFor()[0].getName())) {
continue;
}
// 使用反射获取id属性
Field idValue = arg.getClass().getDeclaredField("id");
// 设置字段为可访问
idValue.setAccessible(true);
return (Long) idValue.get(arg);
}
return null;
}
// TODO @puhui999一般核心的方法放到最前面private 放后面主要是主次要分出来哈
@Before("@annotation(crmPermission)")
public void doBefore(JoinPoint joinPoint, CrmPermission crmPermission) {
public void doBefore(JoinPoint joinPoint, CrmPermission crmPermission) throws NoSuchMethodException {
// TODO 芋艿临时方便大家调试
if (true) {
//if (true) {
// return;
//}
KeyValue<Long, Integer> bizIdAndBizType = getBizIdAndBizType(joinPoint, crmPermission);
Integer bizType = bizIdAndBizType.getValue(); // 模块类型
Long bizId = bizIdAndBizType.getKey(); // 模块数据编号
Integer permissionLevel = crmPermission.level().getLevel(); // 需要的权限级别
// TODO 如果是超级管理员则直接通过
//if (superAdmin){
// return;
//}
// 1. 获取数据权限
List<CrmPermissionDO> bizPermissions = crmPermissionService.getPermissionByBizTypeAndBizId(bizType, bizId);
// 2.1 情况一如果自己是负责人则默认有所有权限
// TODO @puhui999会不会存在空指针的问题
CrmPermissionDO userPermission = CollUtil.findOne(bizPermissions, item -> ObjUtil.equal(item.getUserId(), getUserId()));
if (CrmPermissionLevelEnum.isOwner(userPermission.getLevel())) {
return;
}
try {
Long bizId = crmPermission.getIdFor().length > 0 ? getBizId(joinPoint, crmPermission) : (Long) joinPoint.getArgs()[0]; // 获取操作数据的编号
Integer bizType = crmPermission.bizType().getType(); // 模块类型
Integer permissionLevel = crmPermission.permissionLevel().getLevel(); // 需要的权限级别
// TODO 如果是超级管理员则直接通过
//if (superAdmin){
// return;
//}
// 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())) {
// 2.2 情况二校验自己是否有读权限
if (CrmPermissionLevelEnum.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;
}
// 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;
}
if (isRead(userPermission.getPermissionLevel())) { // 校验当前用户是否有读权限
return;
}
// 如果查询数据的话拥有写权限的也能查询
if (isWrite(userPermission.getPermissionLevel())) { // 校验当前用户是否有写权限
return;
}
if (CrmPermissionLevelEnum.isRead(userPermission.getLevel())) { // 校验当前用户是否有读权限
return;
}
// 2.3 情况三校验自己是否有写权限
if (isWrite(permissionLevel)) {
if (isWrite(userPermission.getPermissionLevel())) { // 校验当前用户是否有写权限
return;
}
// 如果查询数据的话拥有写权限的也能查询
if (CrmPermissionLevelEnum.isWrite(userPermission.getLevel())) { // 校验当前用户是否有写权限
return;
}
// 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());
}
// 2.3 情况三校验自己是否有写权限
if (CrmPermissionLevelEnum.isWrite(permissionLevel)) {
if (CrmPermissionLevelEnum.isWrite(userPermission.getLevel())) { // 校验当前用户是否有写权限
return;
}
}
// 打个 info 日志方便后续排查问题审计
log.info("[doBefore][crmPermission({}) 数据校验错误]", toJsonString(userPermission));
throw exception(CRM_PERMISSION_DENIED, crmPermission.bizType().getName());
}
private KeyValue<Long, Integer> getBizIdAndBizType(JoinPoint joinPoint, CrmPermission crmPermission) throws NoSuchMethodException {
Method method = getMethod(joinPoint);
// 1. 获取方法的参数值
Object[] args = joinPoint.getArgs();
EvaluationContext context = bindParam(method, args);
// 2. 根据spel表达式获取值
KeyValue<Long, Integer> keyValue = new KeyValue<>();
// 2.1 获取模块数据编号
Expression expression = parser.parseExpression(crmPermission.bizId());
keyValue.setKey(expression.getValue(context, Long.class));
// 2.2 获取模块类型
if (ObjUtil.equal(crmPermission.bizType().getType(), CrmBizTypeEnum.CRM_PERMISSION.getType())) {
// 情况一用于 CrmPermissionController 中数据权限校验
Expression expression2 = parser.parseExpression(crmPermission.bizTypeValue());
keyValue.setValue(expression2.getValue(context, Integer.class));
return keyValue;
}
// 情况二正常数据权限校验
keyValue.setValue(crmPermission.bizType().getType());
return keyValue;
}
/**
* 获取当前执行的方法
*/
private Method getMethod(JoinPoint joinPoint) throws NoSuchMethodException {
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
Method method = methodSignature.getMethod();
return joinPoint.getTarget().getClass().getMethod(method.getName(), method.getParameterTypes());
}
/**
* 将方法的参数名和参数值绑定
*
* @param method 方法根据方法获取参数名
* @param args 方法的参数值
* @return 求值上下文
*/
private EvaluationContext bindParam(Method method, Object[] args) {
//获取方法的参数名
String[] params = discoverer.getParameterNames(method);
//将参数名与参数值对应起来
EvaluationContext context = new StandardEvaluationContext();
if (params != null) {
for (int len = 0; len < params.length; len++) {
context.setVariable(params[len], args[len]);
}
}
return context;
}
}

View File

@ -0,0 +1,20 @@
package cn.iocoder.yudao.module.crm.framework.core.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.expression.spel.standard.SpelExpressionParser;
/**
* 注册 Spel 所需 Bean
*
* @author HUIHUI
*/
@Configuration
public class SpelConfig {
@Bean
public SpelExpressionParser spelExpressionParser() {
return new SpelExpressionParser();
}
}

View File

@ -1,20 +0,0 @@
package cn.iocoder.yudao.module.crm.framework.core.service;
/**
* 校验数据是否存在 service 接口
* TODO 需要使用团队成员相关操作的业务接口都需要继承此接口
*
* @author HUIHUI
*/
public interface CrmPermissionValidateService {
/**
* 校验数据是否存在
*
* @param bizType CRM 类型
* @param bizId 数据编号
* @return /
*/
boolean validateBizIdExists(Integer bizType, Long bizId);
}

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.crm.framework.enums;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
import lombok.Getter;
@ -16,6 +17,7 @@ import java.util.Arrays;
@Getter
public enum CrmBizTypeEnum implements IntArrayValuable {
CRM_PERMISSION(0, "团队"), // CrmPermissionController 中使用
CRM_LEADS(1, "线索"),
CRM_CUSTOMER(2, "客户"),
CRM_CONTACTS(3, "联系人"),
@ -33,13 +35,9 @@ 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;
}
}
return "";
CrmBizTypeEnum typeEnum = CollUtil.findOne(CollUtil.newArrayList(CrmBizTypeEnum.values()),
item -> ObjUtil.equal(item.type, type));
return typeEnum == null ? null : typeEnum.getName();
}
@Override

View File

@ -48,14 +48,4 @@ public enum CrmPermissionLevelEnum implements IntArrayValuable {
return ObjUtil.equal(WRITE.level, level);
}
public static String getNameByLevel(Integer level) {
// TODO @puhui999可以 findone更简洁另外不存在返回 null 即可啦
for (CrmPermissionLevelEnum levelEnum : CrmPermissionLevelEnum.values()) {
if (ObjUtil.equal(levelEnum.level, level)) {
return levelEnum.name;
}
}
return "";
}
}

View File

@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.crm.service.business;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.*;
import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO;
import cn.iocoder.yudao.module.crm.framework.core.service.CrmPermissionValidateService;
import javax.validation.Valid;
import java.util.Collection;
@ -14,7 +13,7 @@ import java.util.List;
*
* @author ljlleo
*/
public interface CrmBusinessService extends CrmPermissionValidateService {
public interface CrmBusinessService {
/**
* 创建商机

View File

@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.crm.service.business;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ObjUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.*;
import cn.iocoder.yudao.module.crm.convert.business.CrmBusinessConvert;
@ -51,7 +50,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
// 创建数据权限
crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_BUSINESS.getType())
.setBizId(business.getId()).setUserId(userId).setPermissionLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 设置当前操作的人为负责人
.setBizId(business.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 设置当前操作的人为负责人
// 返回
return business.getId();
@ -59,8 +58,8 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
@Override
@Transactional(rollbackFor = Exception.class)
@CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, getIdFor = CrmBusinessUpdateReqVO.class,
permissionLevel = CrmPermissionLevelEnum.WRITE)
@CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, bizId = "#updateReqVO.id",
level = CrmPermissionLevelEnum.WRITE)
public void updateBusiness(CrmBusinessUpdateReqVO updateReqVO) {
// 校验存在
validateBusinessExists(updateReqVO.getId());
@ -71,7 +70,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
@Override
@Transactional(rollbackFor = Exception.class)
@CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, permissionLevel = CrmPermissionLevelEnum.WRITE)
@CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, level = CrmPermissionLevelEnum.WRITE)
public void deleteBusiness(Long id) {
// 校验存在
validateBusinessExists(id);
@ -88,7 +87,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
}
@Override
@CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, permissionLevel = CrmPermissionLevelEnum.READ)
@CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, level = CrmPermissionLevelEnum.READ)
public CrmBusinessDO getBusiness(Long id) {
return businessMapper.selectById(id);
}
@ -134,14 +133,4 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
// 3. TODO 记录转移日志
}
@Override
public boolean validateBizIdExists(Integer bizType, Long bizId) {
// 1. 校验模块类型
if (!ObjUtil.equal(CrmBizTypeEnum.CRM_BUSINESS.getType(), bizId)) {
return false;
}
// 2. 校验是否存在
return businessMapper.selectById(bizId) != null;
}
}

View File

@ -47,7 +47,7 @@ public class ContactServiceImpl implements ContactService {
// 创建数据权限
crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_CONTACTS.getType())
.setBizId(contact.getId()).setUserId(userId).setPermissionLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 设置当前操作的人为负责人
.setBizId(contact.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 设置当前操作的人为负责人
// 返回
return contact.getId();
@ -55,8 +55,7 @@ public class ContactServiceImpl implements ContactService {
@Override
@Transactional(rollbackFor = Exception.class)
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACTS, getIdFor = ContactUpdateReqVO.class,
permissionLevel = CrmPermissionLevelEnum.WRITE)
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACTS, level = CrmPermissionLevelEnum.WRITE)
public void updateContact(ContactUpdateReqVO updateReqVO) {
// 校验存在
validateContactExists(updateReqVO.getId());
@ -69,7 +68,7 @@ public class ContactServiceImpl implements ContactService {
@Override
@Transactional(rollbackFor = Exception.class)
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACTS, permissionLevel = CrmPermissionLevelEnum.WRITE)
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACTS, level = CrmPermissionLevelEnum.WRITE)
public void deleteContact(Long id) {
// 校验存在
validateContactExists(id);
@ -86,7 +85,7 @@ public class ContactServiceImpl implements ContactService {
}
@Override
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACTS, permissionLevel = CrmPermissionLevelEnum.READ)
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACTS, level = CrmPermissionLevelEnum.READ)
public ContactDO getContact(Long id) {
return contactMapper.selectById(id);
}

View File

@ -46,7 +46,7 @@ public class ContractServiceImpl implements ContractService {
// 创建数据权限
crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_CONTRACT.getType())
.setBizId(contract.getId()).setUserId(userId).setPermissionLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 设置当前操作的人为负责人
.setBizId(contract.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 设置当前操作的人为负责人
// 返回
return contract.getId();
@ -54,8 +54,7 @@ public class ContractServiceImpl implements ContractService {
@Override
@Transactional(rollbackFor = Exception.class)
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTRACT, getIdFor = ContractUpdateReqVO.class,
permissionLevel = CrmPermissionLevelEnum.WRITE)
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTRACT, level = CrmPermissionLevelEnum.WRITE)
public void updateContract(ContractUpdateReqVO updateReqVO) {
// 校验存在
validateContractExists(updateReqVO.getId());
@ -66,7 +65,7 @@ public class ContractServiceImpl implements ContractService {
@Override
@Transactional(rollbackFor = Exception.class)
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTRACT, permissionLevel = CrmPermissionLevelEnum.WRITE)
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTRACT, level = CrmPermissionLevelEnum.WRITE)
public void deleteContract(Long id) {
// 校验存在
validateContractExists(id);
@ -83,7 +82,7 @@ public class ContractServiceImpl implements ContractService {
}
@Override
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTRACT, permissionLevel = CrmPermissionLevelEnum.READ)
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTRACT, level = CrmPermissionLevelEnum.READ)
public ContractDO getContract(Long id) {
return contractMapper.selectById(id);
}

View File

@ -1,7 +1,5 @@
package cn.iocoder.yudao.module.crm.service.customer;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.*;
import cn.iocoder.yudao.module.crm.convert.customer.CrmCustomerConvert;
@ -12,13 +10,11 @@ import cn.iocoder.yudao.module.crm.framework.enums.CrmBizTypeEnum;
import cn.iocoder.yudao.module.crm.framework.enums.CrmPermissionLevelEnum;
import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService;
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO;
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
@ -47,7 +43,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
// 创建数据权限
crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType())
.setBizId(customer.getId()).setUserId(userId).setPermissionLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 设置当前操作的人为负责人
.setBizId(customer.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 设置当前操作的人为负责人
// 返回
return customer.getId();
@ -55,8 +51,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
@Override
@Transactional(rollbackFor = Exception.class)
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, getIdFor = CrmCustomerUpdateReqVO.class,
permissionLevel = CrmPermissionLevelEnum.WRITE)
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, level = CrmPermissionLevelEnum.WRITE)
public void updateCustomer(CrmCustomerUpdateReqVO updateReqVO) {
// 校验存在
validateCustomerExists(updateReqVO.getId());
@ -69,7 +64,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
@Override
@Transactional(rollbackFor = Exception.class)
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, permissionLevel = CrmPermissionLevelEnum.WRITE)
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, level = CrmPermissionLevelEnum.WRITE)
public void deleteCustomer(Long id) {
// 校验存在
validateCustomerExists(id);
@ -86,7 +81,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
}
@Override
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, permissionLevel = CrmPermissionLevelEnum.READ)
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, level = CrmPermissionLevelEnum.READ)
public CrmCustomerDO getCustomer(Long id) {
return customerMapper.selectById(id);
}

View File

@ -6,8 +6,8 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO;
import cn.iocoder.yudao.module.crm.framework.enums.CrmBizTypeEnum;
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO;
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionPageReqBO;
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO;
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionUpdateReqBO;
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmTransferPermissionReqBO;
import javax.validation.Valid;
import java.util.List;
@ -63,9 +63,9 @@ public interface CrmPermissionService {
/**
* 数据权限转移
*
* @param crmTransferPermissionReqBO 数据权限转移请求
* @param crmPermissionTransferReqBO 数据权限转移请求
*/
void transferPermission(@Valid CrmTransferPermissionReqBO crmTransferPermissionReqBO);
void transferPermission(@Valid CrmPermissionTransferReqBO crmPermissionTransferReqBO);
/**
* 获取数据权限分页数据

View File

@ -10,8 +10,8 @@ import cn.iocoder.yudao.module.crm.framework.enums.CrmBizTypeEnum;
import cn.iocoder.yudao.module.crm.framework.enums.CrmPermissionLevelEnum;
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO;
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionPageReqBO;
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO;
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionUpdateReqBO;
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmTransferPermissionReqBO;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -55,13 +55,12 @@ public class CrmPermissionServiceImpl implements CrmPermissionService {
@Override
@Transactional(rollbackFor = Exception.class)
public void updatePermission(CrmPermissionUpdateReqBO updateBO) {
// TODO @puhui999这里 1.1 1.2下面 2.这样更有序一点
// 1. 校验用户是否存在
// 1.1 校验用户是否存在
adminUserApi.validateUserList(Collections.singletonList(updateBO.getUserId()));
// 2. 校验存在
// 1.2 校验存在
validateCrmPermissionExists(updateBO.getId());
// 更新操作
// 2. 更新操作
CrmPermissionDO updateDO = CrmPermissionConvert.INSTANCE.convert(updateBO);
crmPermissionMapper.updateById(updateDO);
}
@ -93,43 +92,41 @@ public class CrmPermissionServiceImpl implements CrmPermissionService {
}
@Override
public void transferPermission(CrmTransferPermissionReqBO transferReqBO) {
public void transferPermission(CrmPermissionTransferReqBO transferReqBO) {
// 1. 校验数据权限-是否是负责人只有负责人才可以转移
CrmPermissionDO oldPermission = crmPermissionMapper.selectByBizTypeAndBizIdByUserId(transferReqBO.getBizType(),
transferReqBO.getBizId(), transferReqBO.getUserId());
String crmName = CrmBizTypeEnum.getNameByType(transferReqBO.getBizType());
// TODO 校验是否为超级管理员 || 1
if (oldPermission == null || !isOwner(oldPermission.getPermissionLevel())) {
if (oldPermission == null || !isOwner(oldPermission.getLevel())) {
throw exception(CRM_PERMISSION_DENIED, crmName);
}
// TODO @puhui999这个顺序编号看看调整下2. 后面是 2.1 结果没 2.2 有点怪
// 2. 校验转移对象是否已经是该负责人
// 1.1 校验转移对象是否已经是该负责人
if (ObjUtil.equal(transferReqBO.getNewOwnerUserId(), oldPermission.getUserId())) {
throw exception(CRM_PERMISSION_MODEL_TRANSFER_FAIL_OWNER_USER_EXISTS, crmName);
}
// 2.1 校验新负责人是否存在
// 1.2 校验新负责人是否存在
adminUserApi.validateUserList(Collections.singletonList(transferReqBO.getNewOwnerUserId()));
// 3. 权限转移
// 2. 权限转移
List<CrmPermissionDO> permissions = crmPermissionMapper.selectByBizTypeAndBizId(
transferReqBO.getBizType(), transferReqBO.getBizId()); // 获取所有团队成员
// 3.1 校验新负责人是否在团队成员中
// 2.1 校验新负责人是否在团队成员中
CrmPermissionDO permission = CollUtil.findOne(permissions,
item -> ObjUtil.equal(item.getUserId(), transferReqBO.getNewOwnerUserId()));
if (permission == null) { // 不存在则以负责人的级别加入这个团队
crmPermissionMapper.insert(new CrmPermissionDO().setBizType(transferReqBO.getBizType())
.setBizId(transferReqBO.getBizId()).setUserId(transferReqBO.getNewOwnerUserId())
.setPermissionLevel(CrmPermissionLevelEnum.OWNER.getLevel()));
.setLevel(CrmPermissionLevelEnum.OWNER.getLevel()));
} else { // 存在则修改权限级别
crmPermissionMapper.updateById(new CrmPermissionDO().setId(permission.getId())
.setPermissionLevel(CrmPermissionLevelEnum.OWNER.getLevel()));
.setLevel(CrmPermissionLevelEnum.OWNER.getLevel()));
}
// 4. 老负责人处理
if (transferReqBO.getJoinTeam()) { // 加入团队
// 2.2. 老负责人处理
if (transferReqBO.getOldOwnerPermissionLevel() != null) { // 加入团队
crmPermissionMapper.updateById(new CrmPermissionDO().setId(oldPermission.getId())
.setPermissionLevel(transferReqBO.getPermissionLevel())); // 设置加入团队后的级别
.setLevel(transferReqBO.getOldOwnerPermissionLevel())); // 设置加入团队后的级别
return;
}
crmPermissionMapper.deleteById(oldPermission.getId()); // 移除

View File

@ -33,12 +33,11 @@ public class CrmPermissionCreateReqBO {
@NotNull(message = "Crm 数据编号不能为空")
private Long bizId;
// TODO @puhui999简化成 level
/**
* 权限级别
*/
@NotNull(message = "权限级别不能为空")
@InEnum(CrmPermissionLevelEnum.class)
private Integer permissionLevel;
private Integer level;
}

View File

@ -7,14 +7,13 @@ import lombok.Data;
import javax.validation.constraints.NotNull;
// TODO @puhui999CrmPermissionTransferReqBO
/**
* 数据权限转移 Request BO
*
* @author HUIHUI
*/
@Data
public class CrmTransferPermissionReqBO {
public class CrmPermissionTransferReqBO {
/**
* 当前登录用户编号
@ -40,17 +39,10 @@ public class CrmTransferPermissionReqBO {
@NotNull(message = "新负责人的用户编号不能为空")
private Long newOwnerUserId;
// TODO @puhui999joinTeam 可以合并成 permissionLevel oldOwnerPermissionLevel这样 null 说明移除因为都换负责人啦
/**
* 老负责人是否加入团队/
*/
@NotNull(message = "老负责人是否加入团队不能为空")
private Boolean joinTeam;
/**
* 老负责人加入团队后的权限级别如果 {@link #joinTeam} false, permissionLevel null
* 老负责人加入团队后的权限级别如果 null 说明移除
* 关联 {@link CrmPermissionLevelEnum}
*/
private Integer permissionLevel;
private Integer oldOwnerPermissionLevel;
}

View File

@ -1,8 +1,6 @@
package cn.iocoder.yudao.module.crm.service.permission.bo;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO;
import cn.iocoder.yudao.module.crm.framework.enums.CrmBizTypeEnum;
import cn.iocoder.yudao.module.crm.framework.enums.CrmPermissionLevelEnum;
import lombok.Data;
@ -28,25 +26,11 @@ 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
/**
* 权限级别
*/
@NotNull(message = "权限级别不能为空")
@InEnum(CrmPermissionLevelEnum.class)
private Integer permissionLevel;
private Integer level;
}

View File

@ -1,6 +1,11 @@
package cn.iocoder.yudao.module.system.api.dept;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.module.system.api.dept.dto.PostRespDTO;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* 岗位 API 接口
@ -18,4 +23,11 @@ public interface PostApi {
*/
void validPostList(Collection<Long> ids);
List<PostRespDTO> getPostList(Collection<Long> ids);
default Map<Long, PostRespDTO> getPostMap(Collection<Long> ids) {
List<PostRespDTO> list = getPostList(ids);
return CollectionUtils.convertMap(list, PostRespDTO::getId);
}
}

View File

@ -0,0 +1,37 @@
package cn.iocoder.yudao.module.system.api.dept.dto;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import lombok.Data;
/**
* 岗位 Response DTO
*
* @author 芋道源码
*/
@Data
public class PostRespDTO {
/**
* 岗位序号
*/
private Long id;
/**
* 岗位名称
*/
private String name;
/**
* 岗位编码
*/
private String code;
/**
* 岗位排序
*/
private Integer sort;
/**
* 状态
*
* 枚举 {@link CommonStatusEnum}
*/
private Integer status;
}

View File

@ -1,10 +1,13 @@
package cn.iocoder.yudao.module.system.api.dept;
import cn.iocoder.yudao.module.system.api.dept.dto.PostRespDTO;
import cn.iocoder.yudao.module.system.convert.dept.PostConvert;
import cn.iocoder.yudao.module.system.service.dept.PostService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Collection;
import java.util.List;
/**
* 岗位 API 实现类
@ -22,4 +25,9 @@ public class PostApiImpl implements PostApi {
postService.validatePostList(ids);
}
@Override
public List<PostRespDTO> getPostList(Collection<Long> ids) {
return PostConvert.INSTANCE.convert(postService.getPostList(ids));
}
}

View File

@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.system.convert.dept;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.system.api.dept.dto.PostRespDTO;
import cn.iocoder.yudao.module.system.controller.admin.dept.vo.post.*;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.PostDO;
import org.mapstruct.Mapper;
@ -25,4 +26,6 @@ public interface PostConvert {
List<PostExcelVO> convertList03(List<PostDO> list);
List<PostRespDTO> convert(List<PostDO> postList);
}