feat(permission): 重构权限系统实现对象级别权限控制
- 在PermissionService中新增getScopedMenusByRoleId和getScopedPermissionsByRoleId方法 - 实现getScopedMenusByRoleId方法用于获取角色的对象范围菜单列表 - 实现getScopedPermissionsByRoleId方法用于获取角色的对象范围权限集合 - 添加getEnabledScopedRole私有方法确保只处理启用状态的角色对象 - 在ProductMemberServiceImpl中替换SystemRoleMapper为ObjectPermissionApi调用 - 将验证产品角色的方法改为调用远程权限接口验证 - 更新ProductObjectPermissionService使用远程权限接口替代本地查询 - 修改ProductServiceImpl中权限获取逻辑使用新的对象权限API - 移除原有的系统菜单和角色相关的数据对象依赖 - 在测试类中更新模拟对象和断言逻辑适配新的权限接口调用
This commit is contained in:
@@ -1,42 +0,0 @@
|
||||
package com.njcn.rdms.module.project.dal.dataobject.permission;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.njcn.rdms.framework.mybatis.core.dataobject.BaseDO;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 对象菜单表
|
||||
*/
|
||||
@TableName("system_menu")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class SystemMenuDO extends BaseDO {
|
||||
|
||||
@TableId
|
||||
private Long id;
|
||||
|
||||
private String name;
|
||||
|
||||
private String permission;
|
||||
|
||||
private String scopeType;
|
||||
|
||||
private String objectType;
|
||||
|
||||
private Integer type;
|
||||
|
||||
private Integer sort;
|
||||
|
||||
private Long parentId;
|
||||
|
||||
private String path;
|
||||
|
||||
private String icon;
|
||||
|
||||
private Integer status;
|
||||
|
||||
private Boolean visible;
|
||||
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
package com.njcn.rdms.module.project.dal.dataobject.permission;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.njcn.rdms.framework.mybatis.core.dataobject.BaseDO;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 角色信息表
|
||||
*/
|
||||
@TableName("system_role")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class SystemRoleDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 角色ID
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
/**
|
||||
* 角色名称
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 角色编码
|
||||
*/
|
||||
private String code;
|
||||
/**
|
||||
* 作用域类型
|
||||
*/
|
||||
private String scopeType;
|
||||
/**
|
||||
* 对象类型
|
||||
*/
|
||||
private String objectType;
|
||||
/**
|
||||
* 显示顺序
|
||||
*/
|
||||
private Integer sort;
|
||||
/**
|
||||
* 角色状态
|
||||
*/
|
||||
private Integer status;
|
||||
/**
|
||||
* 角色类型
|
||||
*/
|
||||
private Integer type;
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package com.njcn.rdms.module.project.dal.dataobject.permission;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.njcn.rdms.framework.mybatis.core.dataobject.BaseDO;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 对象角色菜单关联表
|
||||
*/
|
||||
@TableName("system_role_menu")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class SystemRoleMenuDO extends BaseDO {
|
||||
|
||||
@TableId
|
||||
private Long id;
|
||||
|
||||
private Long roleId;
|
||||
|
||||
private Long menuId;
|
||||
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
package com.njcn.rdms.module.project.dal.mysql.permission;
|
||||
|
||||
import com.njcn.rdms.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import com.njcn.rdms.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import com.njcn.rdms.module.project.dal.dataobject.permission.SystemMenuDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface SystemMenuMapper extends BaseMapperX<SystemMenuDO> {
|
||||
|
||||
default List<SystemMenuDO> selectListByIdsAndScopeAndObjectType(Collection<Long> ids,
|
||||
String scopeType,
|
||||
String objectType) {
|
||||
return selectList(new LambdaQueryWrapperX<SystemMenuDO>()
|
||||
.inIfPresent(SystemMenuDO::getId, ids)
|
||||
.eq(SystemMenuDO::getScopeType, scopeType)
|
||||
.eq(SystemMenuDO::getObjectType, objectType));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
package com.njcn.rdms.module.project.dal.mysql.permission;
|
||||
|
||||
import com.njcn.rdms.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import com.njcn.rdms.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import com.njcn.rdms.module.project.dal.dataobject.permission.SystemRoleDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface SystemRoleMapper extends BaseMapperX<SystemRoleDO> {
|
||||
|
||||
default SystemRoleDO selectByIdAndScopeAndObjectType(Long id, String scopeType, String objectType) {
|
||||
return selectOne(new LambdaQueryWrapperX<SystemRoleDO>()
|
||||
.eq(SystemRoleDO::getId, id)
|
||||
.eq(SystemRoleDO::getScopeType, scopeType)
|
||||
.eq(SystemRoleDO::getObjectType, objectType)
|
||||
.eq(SystemRoleDO::getStatus, 0));
|
||||
}
|
||||
|
||||
default List<SystemRoleDO> selectListByIdsAndScopeAndObjectType(Collection<Long> ids,
|
||||
String scopeType,
|
||||
String objectType) {
|
||||
return selectList(new LambdaQueryWrapperX<SystemRoleDO>()
|
||||
.inIfPresent(SystemRoleDO::getId, ids)
|
||||
.eq(SystemRoleDO::getScopeType, scopeType)
|
||||
.eq(SystemRoleDO::getObjectType, objectType)
|
||||
.eq(SystemRoleDO::getStatus, 0));
|
||||
}
|
||||
|
||||
default SystemRoleDO selectByScopeAndObjectTypeAndCode(String scopeType, String objectType, String code) {
|
||||
return selectOne(new LambdaQueryWrapperX<SystemRoleDO>()
|
||||
.eq(SystemRoleDO::getScopeType, scopeType)
|
||||
.eq(SystemRoleDO::getObjectType, objectType)
|
||||
.eq(SystemRoleDO::getCode, code)
|
||||
.eq(SystemRoleDO::getStatus, 0));
|
||||
}
|
||||
|
||||
default SystemRoleDO selectByScopeAndObjectTypeAndName(String scopeType, String objectType, String name) {
|
||||
return selectOne(new LambdaQueryWrapperX<SystemRoleDO>()
|
||||
.eq(SystemRoleDO::getScopeType, scopeType)
|
||||
.eq(SystemRoleDO::getObjectType, objectType)
|
||||
.eq(SystemRoleDO::getName, name)
|
||||
.eq(SystemRoleDO::getStatus, 0));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package com.njcn.rdms.module.project.dal.mysql.permission;
|
||||
|
||||
import com.njcn.rdms.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import com.njcn.rdms.module.project.dal.dataobject.permission.SystemRoleMenuDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface SystemRoleMenuMapper extends BaseMapperX<SystemRoleMenuDO> {
|
||||
|
||||
default List<SystemRoleMenuDO> selectListByRoleId(Long roleId) {
|
||||
return selectList(SystemRoleMenuDO::getRoleId, roleId);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.njcn.rdms.module.project.framework.rpc.config;
|
||||
|
||||
import com.njcn.rdms.module.system.api.permission.ObjectPermissionApi;
|
||||
import com.njcn.rdms.module.system.api.user.AdminUserApi;
|
||||
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -8,6 +9,6 @@ import org.springframework.context.annotation.Configuration;
|
||||
* Project 模块的 RPC 配置
|
||||
*/
|
||||
@Configuration(value = "projectRpcConfiguration", proxyBeanMethods = false)
|
||||
@EnableFeignClients(clients = {AdminUserApi.class})
|
||||
@EnableFeignClients(clients = {AdminUserApi.class, ObjectPermissionApi.class})
|
||||
public class RpcConfiguration {
|
||||
}
|
||||
|
||||
@@ -2,12 +2,9 @@ package com.njcn.rdms.module.project.framework.security.service;
|
||||
|
||||
import com.njcn.rdms.framework.security.core.util.SecurityFrameworkUtils;
|
||||
import com.njcn.rdms.module.project.dal.dataobject.member.UserObjectRoleDO;
|
||||
import com.njcn.rdms.module.project.dal.dataobject.permission.SystemMenuDO;
|
||||
import com.njcn.rdms.module.project.dal.dataobject.permission.SystemRoleMenuDO;
|
||||
import com.njcn.rdms.module.project.dal.mysql.member.UserObjectRoleMapper;
|
||||
import com.njcn.rdms.module.project.dal.mysql.permission.SystemMenuMapper;
|
||||
import com.njcn.rdms.module.project.dal.mysql.permission.SystemRoleMenuMapper;
|
||||
import com.njcn.rdms.module.project.enums.ErrorCodeConstants;
|
||||
import com.njcn.rdms.module.system.api.permission.ObjectPermissionApi;
|
||||
import com.njcn.rdms.module.system.enums.permission.PermissionScopeTypeEnum;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -15,7 +12,6 @@ import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -34,9 +30,7 @@ public class ProductObjectPermissionService implements ObjectPermissionService {
|
||||
@Resource
|
||||
private UserObjectRoleMapper userObjectRoleMapper;
|
||||
@Resource
|
||||
private SystemRoleMenuMapper systemRoleMenuMapper;
|
||||
@Resource
|
||||
private SystemMenuMapper systemMenuMapper;
|
||||
private ObjectPermissionApi objectPermissionApi;
|
||||
|
||||
@Override
|
||||
public String getObjectType() {
|
||||
@@ -65,26 +59,13 @@ public class ProductObjectPermissionService implements ObjectPermissionService {
|
||||
}
|
||||
|
||||
private Set<String> getRolePermissions(Long roleId) {
|
||||
List<SystemRoleMenuDO> roleMenus = systemRoleMenuMapper.selectListByRoleId(roleId);
|
||||
if (roleMenus == null || roleMenus.isEmpty()) {
|
||||
Set<String> permissions = objectPermissionApi
|
||||
.getObjectRolePermissions(roleId, ROLE_SCOPE_OBJECT, PRODUCT_OBJECT_TYPE)
|
||||
.getCheckedData();
|
||||
if (permissions == null || permissions.isEmpty()) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
Set<Long> menuIds = roleMenus.stream()
|
||||
.map(SystemRoleMenuDO::getMenuId)
|
||||
.collect(Collectors.toCollection(LinkedHashSet::new));
|
||||
if (menuIds.isEmpty()) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
List<SystemMenuDO> menus = systemMenuMapper.selectListByIdsAndScopeAndObjectType(
|
||||
menuIds, ROLE_SCOPE_OBJECT, PRODUCT_OBJECT_TYPE);
|
||||
if (menus == null || menus.isEmpty()) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
return menus.stream()
|
||||
.filter(menu -> ROLE_SCOPE_OBJECT.equals(menu.getScopeType()))
|
||||
.filter(menu -> PRODUCT_OBJECT_TYPE.equals(menu.getObjectType()))
|
||||
.filter(menu -> Integer.valueOf(0).equals(menu.getStatus()))
|
||||
.map(SystemMenuDO::getPermission)
|
||||
return permissions.stream()
|
||||
.filter(StringUtils::hasText)
|
||||
.map(String::trim)
|
||||
.collect(Collectors.toCollection(LinkedHashSet::new));
|
||||
|
||||
@@ -9,13 +9,13 @@ import com.njcn.rdms.module.project.controller.admin.product.vo.member.ProductMe
|
||||
import com.njcn.rdms.module.project.framework.security.annotation.CheckObjectPermission;
|
||||
import com.njcn.rdms.module.project.dal.dataobject.audit.BizAuditLogDO;
|
||||
import com.njcn.rdms.module.project.dal.dataobject.member.UserObjectRoleDO;
|
||||
import com.njcn.rdms.module.project.dal.dataobject.permission.SystemRoleDO;
|
||||
import com.njcn.rdms.module.project.dal.dataobject.product.ProductDO;
|
||||
import com.njcn.rdms.module.project.dal.mysql.audit.BizAuditLogMapper;
|
||||
import com.njcn.rdms.module.project.dal.mysql.member.UserObjectRoleMapper;
|
||||
import com.njcn.rdms.module.project.dal.mysql.permission.SystemRoleMapper;
|
||||
import com.njcn.rdms.module.project.dal.mysql.product.ProductMapper;
|
||||
import com.njcn.rdms.module.project.enums.ErrorCodeConstants;
|
||||
import com.njcn.rdms.module.system.api.permission.ObjectPermissionApi;
|
||||
import com.njcn.rdms.module.system.api.permission.dto.ObjectRoleRespDTO;
|
||||
import com.njcn.rdms.module.system.api.user.AdminUserApi;
|
||||
import com.njcn.rdms.module.system.api.user.dto.AdminUserRespDTO;
|
||||
import jakarta.annotation.Resource;
|
||||
@@ -63,7 +63,7 @@ public class ProductMemberServiceImpl implements ProductMemberService {
|
||||
@Resource
|
||||
private UserObjectRoleMapper userObjectRoleMapper;
|
||||
@Resource
|
||||
private SystemRoleMapper systemRoleMapper;
|
||||
private ObjectPermissionApi objectPermissionApi;
|
||||
@Resource
|
||||
private BizAuditLogMapper bizAuditLogMapper;
|
||||
@Resource
|
||||
@@ -75,7 +75,7 @@ public class ProductMemberServiceImpl implements ProductMemberService {
|
||||
public List<ProductMemberRespVO> getProductMemberList(Long productId) {
|
||||
ProductDO product = validateProductExists(productId);
|
||||
List<UserObjectRoleDO> members = userObjectRoleMapper.selectListByObject(PRODUCT_OBJECT_TYPE, productId);
|
||||
Map<Long, SystemRoleDO> roleMap = getRoleMap(members.stream().map(UserObjectRoleDO::getRoleId).collect(Collectors.toSet()));
|
||||
Map<Long, ObjectRoleRespDTO> roleMap = getRoleMap(members.stream().map(UserObjectRoleDO::getRoleId).collect(Collectors.toSet()));
|
||||
Map<Long, AdminUserRespDTO> userMap = getUserMap(members.stream().map(UserObjectRoleDO::getUserId).collect(Collectors.toSet()));
|
||||
return members.stream().map(member -> {
|
||||
ProductMemberRespVO respVO = new ProductMemberRespVO();
|
||||
@@ -84,7 +84,7 @@ public class ProductMemberServiceImpl implements ProductMemberService {
|
||||
AdminUserRespDTO user = userMap.get(member.getUserId());
|
||||
respVO.setUserNickname(user == null ? null : user.getNickname());
|
||||
respVO.setRoleId(member.getRoleId());
|
||||
SystemRoleDO role = roleMap.get(member.getRoleId());
|
||||
ObjectRoleRespDTO role = roleMap.get(member.getRoleId());
|
||||
respVO.setRoleName(role == null ? null : role.getName());
|
||||
respVO.setRoleCode(role == null ? null : role.getCode());
|
||||
respVO.setManagerFlag(Objects.equals(member.getUserId(), product.getManagerUserId())
|
||||
@@ -103,7 +103,7 @@ public class ProductMemberServiceImpl implements ProductMemberService {
|
||||
permission = PRODUCT_UPDATE_PERMISSION)
|
||||
public Long createProductMember(Long productId, ProductMemberSaveReqVO reqVO) {
|
||||
ProductDO product = validateProductExists(productId);
|
||||
SystemRoleDO targetRole = validateProductRole(reqVO.getRoleId());
|
||||
ObjectRoleRespDTO targetRole = validateProductRole(reqVO.getRoleId());
|
||||
UserObjectRoleDO existingMember = userObjectRoleMapper
|
||||
.selectByObjectAndUserId(PRODUCT_OBJECT_TYPE, productId, reqVO.getUserId());
|
||||
if (existingMember != null && Objects.equals(existingMember.getStatus(), MEMBER_STATUS_ACTIVE)) {
|
||||
@@ -153,7 +153,7 @@ public class ProductMemberServiceImpl implements ProductMemberService {
|
||||
throw exception(ErrorCodeConstants.PRODUCT_MEMBER_NOT_ACTIVE);
|
||||
}
|
||||
|
||||
SystemRoleDO targetRole = validateProductRole(reqVO.getRoleId());
|
||||
ObjectRoleRespDTO targetRole = validateProductRole(reqVO.getRoleId());
|
||||
UserObjectRoleDO before = cloneMember(member);
|
||||
member.setRemark(normalizeNullableText(reqVO.getRemark()));
|
||||
|
||||
@@ -215,8 +215,10 @@ public class ProductMemberServiceImpl implements ProductMemberService {
|
||||
return member;
|
||||
}
|
||||
|
||||
private SystemRoleDO validateProductRole(Long roleId) {
|
||||
SystemRoleDO role = systemRoleMapper.selectByIdAndScopeAndObjectType(roleId, ROLE_SCOPE_OBJECT, PRODUCT_OBJECT_TYPE);
|
||||
private ObjectRoleRespDTO validateProductRole(Long roleId) {
|
||||
ObjectRoleRespDTO role = objectPermissionApi
|
||||
.getObjectRoleById(roleId, ROLE_SCOPE_OBJECT, PRODUCT_OBJECT_TYPE)
|
||||
.getCheckedData();
|
||||
if (role == null) {
|
||||
throw exception(ErrorCodeConstants.PRODUCT_MEMBER_ROLE_INVALID);
|
||||
}
|
||||
@@ -236,7 +238,7 @@ public class ProductMemberServiceImpl implements ProductMemberService {
|
||||
return;
|
||||
}
|
||||
|
||||
SystemRoleDO previousManagerRole = validatePreviousManagerTransfer(currentManagerUserId,
|
||||
ObjectRoleRespDTO previousManagerRole = validatePreviousManagerTransfer(currentManagerUserId,
|
||||
previousManagerUserId, previousManagerRoleId);
|
||||
transferPreviousManager(product.getId(), previousManagerUserId, previousManagerRole.getId(), reason);
|
||||
|
||||
@@ -245,9 +247,9 @@ public class ProductMemberServiceImpl implements ProductMemberService {
|
||||
writeManagerChangeAuditLog(product.getId(), currentManagerUserId, targetManagerUserId, reason);
|
||||
}
|
||||
|
||||
private SystemRoleDO validatePreviousManagerTransfer(Long currentManagerUserId,
|
||||
Long previousManagerUserId,
|
||||
Long previousManagerRoleId) {
|
||||
private ObjectRoleRespDTO validatePreviousManagerTransfer(Long currentManagerUserId,
|
||||
Long previousManagerUserId,
|
||||
Long previousManagerRoleId) {
|
||||
if (currentManagerUserId == null
|
||||
|| previousManagerUserId == null
|
||||
|| previousManagerRoleId == null) {
|
||||
@@ -256,7 +258,7 @@ public class ProductMemberServiceImpl implements ProductMemberService {
|
||||
if (!Objects.equals(currentManagerUserId, previousManagerUserId)) {
|
||||
throw exception(ErrorCodeConstants.PRODUCT_MANAGER_TRANSFER_SOURCE_INVALID);
|
||||
}
|
||||
SystemRoleDO previousManagerRole = validateProductRole(previousManagerRoleId);
|
||||
ObjectRoleRespDTO previousManagerRole = validateProductRole(previousManagerRoleId);
|
||||
if (isManagerRole(previousManagerRole)) {
|
||||
throw exception(ErrorCodeConstants.PRODUCT_MANAGER_TRANSFER_ROLE_INVALID);
|
||||
}
|
||||
@@ -298,17 +300,21 @@ public class ProductMemberServiceImpl implements ProductMemberService {
|
||||
writeMemberAuditLog(member, actionType, before, member, reason);
|
||||
}
|
||||
|
||||
private boolean isManagerRole(SystemRoleDO role) {
|
||||
private boolean isManagerRole(ObjectRoleRespDTO role) {
|
||||
return Objects.equals(PRODUCT_MANAGER_ROLE_CODE, role.getCode());
|
||||
}
|
||||
|
||||
private Map<Long, SystemRoleDO> getRoleMap(Set<Long> roleIds) {
|
||||
private Map<Long, ObjectRoleRespDTO> getRoleMap(Set<Long> roleIds) {
|
||||
if (roleIds.isEmpty()) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
List<SystemRoleDO> roles = systemRoleMapper
|
||||
.selectListByIdsAndScopeAndObjectType(roleIds, ROLE_SCOPE_OBJECT, PRODUCT_OBJECT_TYPE);
|
||||
return roles.stream().collect(Collectors.toMap(SystemRoleDO::getId, Function.identity()));
|
||||
List<ObjectRoleRespDTO> roles = objectPermissionApi
|
||||
.getObjectRoleList(roleIds, ROLE_SCOPE_OBJECT, PRODUCT_OBJECT_TYPE)
|
||||
.getCheckedData();
|
||||
if (roles == null || roles.isEmpty()) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
return roles.stream().collect(Collectors.toMap(ObjectRoleRespDTO::getId, Function.identity()));
|
||||
}
|
||||
|
||||
private Map<Long, AdminUserRespDTO> getUserMap(Set<Long> userIds) {
|
||||
|
||||
@@ -17,21 +17,19 @@ import com.njcn.rdms.module.project.controller.admin.product.vo.setting.ProductS
|
||||
import com.njcn.rdms.module.project.framework.security.annotation.CheckObjectPermission;
|
||||
import com.njcn.rdms.module.project.dal.dataobject.audit.BizAuditLogDO;
|
||||
import com.njcn.rdms.module.project.dal.dataobject.member.UserObjectRoleDO;
|
||||
import com.njcn.rdms.module.project.dal.dataobject.permission.SystemMenuDO;
|
||||
import com.njcn.rdms.module.project.dal.dataobject.permission.SystemRoleDO;
|
||||
import com.njcn.rdms.module.project.dal.dataobject.permission.SystemRoleMenuDO;
|
||||
import com.njcn.rdms.module.project.dal.dataobject.product.ProductDO;
|
||||
import com.njcn.rdms.module.project.dal.dataobject.product.ProductStatusLogDO;
|
||||
import com.njcn.rdms.module.project.dal.dataobject.status.ObjectStatusTransitionDO;
|
||||
import com.njcn.rdms.module.project.dal.mysql.audit.BizAuditLogMapper;
|
||||
import com.njcn.rdms.module.project.dal.mysql.member.UserObjectRoleMapper;
|
||||
import com.njcn.rdms.module.project.dal.mysql.permission.SystemMenuMapper;
|
||||
import com.njcn.rdms.module.project.dal.mysql.permission.SystemRoleMapper;
|
||||
import com.njcn.rdms.module.project.dal.mysql.permission.SystemRoleMenuMapper;
|
||||
import com.njcn.rdms.module.project.dal.mysql.product.ProductMapper;
|
||||
import com.njcn.rdms.module.project.dal.mysql.product.ProductStatusLogMapper;
|
||||
import com.njcn.rdms.module.project.dal.mysql.status.ObjectStatusTransitionMapper;
|
||||
import com.njcn.rdms.module.project.enums.ErrorCodeConstants;
|
||||
import com.njcn.rdms.module.system.api.permission.ObjectPermissionApi;
|
||||
import com.njcn.rdms.module.system.api.permission.dto.ObjectMenuRespDTO;
|
||||
import com.njcn.rdms.module.system.api.permission.dto.ObjectRolePermissionRespDTO;
|
||||
import com.njcn.rdms.module.system.api.permission.dto.ObjectRoleRespDTO;
|
||||
import com.njcn.rdms.module.system.api.user.AdminUserApi;
|
||||
import com.njcn.rdms.module.system.enums.permission.MenuTypeEnum;
|
||||
import com.njcn.rdms.module.system.enums.permission.PermissionScopeTypeEnum;
|
||||
@@ -45,7 +43,6 @@ import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -99,11 +96,7 @@ public class ProductServiceImpl implements ProductService {
|
||||
@Resource
|
||||
private UserObjectRoleMapper userObjectRoleMapper;
|
||||
@Resource
|
||||
private SystemRoleMapper systemRoleMapper;
|
||||
@Resource
|
||||
private SystemRoleMenuMapper systemRoleMenuMapper;
|
||||
@Resource
|
||||
private SystemMenuMapper systemMenuMapper;
|
||||
private ObjectPermissionApi objectPermissionApi;
|
||||
@Resource
|
||||
private AdminUserApi adminUserApi;
|
||||
|
||||
@@ -174,23 +167,14 @@ public class ProductServiceImpl implements ProductService {
|
||||
return respVO;
|
||||
}
|
||||
|
||||
SystemRoleDO currentRole = systemRoleMapper
|
||||
.selectByIdAndScopeAndObjectType(currentMember.getRoleId(), ROLE_SCOPE_OBJECT, PRODUCT_OBJECT_TYPE);
|
||||
ObjectRolePermissionRespDTO permissionDetail = objectPermissionApi
|
||||
.getObjectRolePermissionDetail(currentMember.getRoleId(), ROLE_SCOPE_OBJECT, PRODUCT_OBJECT_TYPE)
|
||||
.getCheckedData();
|
||||
ObjectRoleRespDTO currentRole = permissionDetail == null ? null : permissionDetail.getCurrentRole();
|
||||
List<ObjectMenuRespDTO> menus = permissionDetail == null || permissionDetail.getMenus() == null
|
||||
? Collections.emptyList()
|
||||
: permissionDetail.getMenus();
|
||||
respVO.setCurrentRole(buildCurrentRole(currentMember, currentRole));
|
||||
|
||||
List<SystemRoleMenuDO> roleMenus = systemRoleMenuMapper.selectListByRoleId(currentMember.getRoleId());
|
||||
if (roleMenus.isEmpty()) {
|
||||
respVO.setNavs(Collections.emptyList());
|
||||
respVO.setButtons(Collections.emptyList());
|
||||
return respVO;
|
||||
}
|
||||
|
||||
Set<Long> menuIds = roleMenus.stream()
|
||||
.map(SystemRoleMenuDO::getMenuId)
|
||||
.collect(Collectors.toCollection(LinkedHashSet::new));
|
||||
List<SystemMenuDO> menus = filterEnableProductObjectMenus(
|
||||
systemMenuMapper.selectListByIdsAndScopeAndObjectType(menuIds, ROLE_SCOPE_OBJECT, PRODUCT_OBJECT_TYPE));
|
||||
|
||||
respVO.setNavs(buildContextNavs(menus));
|
||||
respVO.setButtons(buildContextButtons(menus));
|
||||
return respVO;
|
||||
@@ -386,8 +370,9 @@ public class ProductServiceImpl implements ProductService {
|
||||
}
|
||||
|
||||
private void initManagerMemberRelation(ProductDO product) {
|
||||
SystemRoleDO managerRole = systemRoleMapper
|
||||
.selectByScopeAndObjectTypeAndCode(ROLE_SCOPE_OBJECT, PRODUCT_OBJECT_TYPE, PRODUCT_MANAGER_ROLE_CODE);
|
||||
ObjectRoleRespDTO managerRole = objectPermissionApi
|
||||
.getObjectRoleByCode(PRODUCT_MANAGER_ROLE_CODE, ROLE_SCOPE_OBJECT, PRODUCT_OBJECT_TYPE)
|
||||
.getCheckedData();
|
||||
if (managerRole == null) {
|
||||
throw invalidParamException("未找到产品经理对象角色配置:{}", PRODUCT_MANAGER_ROLE_CODE);
|
||||
}
|
||||
@@ -406,22 +391,11 @@ public class ProductServiceImpl implements ProductService {
|
||||
writeManagerInitAuditLog(product.getId(), product.getManagerUserId());
|
||||
}
|
||||
|
||||
private List<SystemMenuDO> filterEnableProductObjectMenus(List<SystemMenuDO> menus) {
|
||||
if (menus == null || menus.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return menus.stream()
|
||||
.filter(menu -> Objects.equals(ROLE_SCOPE_OBJECT, menu.getScopeType()))
|
||||
.filter(menu -> Objects.equals(PRODUCT_OBJECT_TYPE, menu.getObjectType()))
|
||||
.filter(menu -> Objects.equals(0, menu.getStatus()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private ProductContextProductRespVO buildCurrentProduct(ProductDO product) {
|
||||
return BeanUtils.toBean(product, ProductContextProductRespVO.class);
|
||||
}
|
||||
|
||||
private ProductContextRoleRespVO buildCurrentRole(UserObjectRoleDO currentMember, SystemRoleDO currentRole) {
|
||||
private ProductContextRoleRespVO buildCurrentRole(UserObjectRoleDO currentMember, ObjectRoleRespDTO currentRole) {
|
||||
ProductContextRoleRespVO roleRespVO = new ProductContextRoleRespVO();
|
||||
roleRespVO.setRoleId(currentMember.getRoleId());
|
||||
if (currentRole != null) {
|
||||
@@ -431,7 +405,7 @@ public class ProductServiceImpl implements ProductService {
|
||||
return roleRespVO;
|
||||
}
|
||||
|
||||
private List<ProductContextNavRespVO> buildContextNavs(List<SystemMenuDO> menus) {
|
||||
private List<ProductContextNavRespVO> buildContextNavs(List<ObjectMenuRespDTO> menus) {
|
||||
if (menus.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
@@ -455,13 +429,13 @@ public class ProductServiceImpl implements ProductService {
|
||||
return navs;
|
||||
}
|
||||
|
||||
private List<String> buildContextButtons(List<SystemMenuDO> menus) {
|
||||
private List<String> buildContextButtons(List<ObjectMenuRespDTO> menus) {
|
||||
if (menus.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return menus.stream()
|
||||
.filter(menu -> MenuTypeEnum.BUTTON.getType().equals(menu.getType()))
|
||||
.map(SystemMenuDO::getPermission)
|
||||
.map(ObjectMenuRespDTO::getPermission)
|
||||
.filter(StringUtils::hasText)
|
||||
.map(String::trim)
|
||||
.distinct()
|
||||
|
||||
@@ -4,26 +4,21 @@ import com.njcn.rdms.framework.common.exception.ServiceException;
|
||||
import com.njcn.rdms.framework.security.core.util.SecurityFrameworkUtils;
|
||||
import com.njcn.rdms.framework.test.core.ut.BaseMockitoUnitTest;
|
||||
import com.njcn.rdms.module.project.dal.dataobject.member.UserObjectRoleDO;
|
||||
import com.njcn.rdms.module.project.dal.dataobject.permission.SystemMenuDO;
|
||||
import com.njcn.rdms.module.project.dal.dataobject.permission.SystemRoleMenuDO;
|
||||
import com.njcn.rdms.module.project.dal.mysql.member.UserObjectRoleMapper;
|
||||
import com.njcn.rdms.module.project.dal.mysql.permission.SystemMenuMapper;
|
||||
import com.njcn.rdms.module.project.dal.mysql.permission.SystemRoleMenuMapper;
|
||||
import com.njcn.rdms.module.project.enums.ErrorCodeConstants;
|
||||
import com.njcn.rdms.module.system.enums.permission.MenuTypeEnum;
|
||||
import com.njcn.rdms.module.system.api.permission.ObjectPermissionApi;
|
||||
import com.njcn.rdms.module.system.enums.permission.PermissionScopeTypeEnum;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockedStatic;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.njcn.rdms.framework.common.pojo.CommonResult.success;
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mockStatic;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
@@ -35,9 +30,7 @@ class ProductObjectPermissionServiceTest extends BaseMockitoUnitTest {
|
||||
@Mock
|
||||
private UserObjectRoleMapper userObjectRoleMapper;
|
||||
@Mock
|
||||
private SystemRoleMenuMapper systemRoleMenuMapper;
|
||||
@Mock
|
||||
private SystemMenuMapper systemMenuMapper;
|
||||
private ObjectPermissionApi objectPermissionApi;
|
||||
|
||||
@Test
|
||||
void checkPermission_whenMemberOnlyAndCurrentUserIsMember_shouldPass() {
|
||||
@@ -50,20 +43,18 @@ class ProductObjectPermissionServiceTest extends BaseMockitoUnitTest {
|
||||
assertDoesNotThrow(() -> permissionService.checkPermission(productId, null, true));
|
||||
}
|
||||
|
||||
verifyNoInteractions(systemRoleMenuMapper, systemMenuMapper);
|
||||
verifyNoInteractions(objectPermissionApi);
|
||||
}
|
||||
|
||||
@Test
|
||||
void checkPermission_whenQueryPermissionConfiguredOnMenuNode_shouldPass() {
|
||||
void checkPermission_whenCurrentRolePermissionsContainTarget_shouldPass() {
|
||||
Long productId = 1002L;
|
||||
Long loginUserId = 2002L;
|
||||
when(userObjectRoleMapper.selectActiveByObjectAndUserId("product", productId, loginUserId))
|
||||
.thenReturn(createMember(productId, loginUserId, 3002L));
|
||||
when(systemRoleMenuMapper.selectListByRoleId(3002L))
|
||||
.thenReturn(List.of(createRoleMenu(3002L, 4002L)));
|
||||
when(systemMenuMapper.selectListByIdsAndScopeAndObjectType(any(),
|
||||
eq(PermissionScopeTypeEnum.OBJECT.getScopeType()), eq("product")))
|
||||
.thenReturn(List.of(createMenu(4002L, MenuTypeEnum.MENU.getType(), "project:product:query")));
|
||||
when(objectPermissionApi.getObjectRolePermissions(3002L,
|
||||
PermissionScopeTypeEnum.OBJECT.getScopeType(), "product"))
|
||||
.thenReturn(success(Set.of("project:product:query")));
|
||||
|
||||
try (MockedStatic<SecurityFrameworkUtils> mockedStatic = mockLoginUser(loginUserId)) {
|
||||
assertDoesNotThrow(() -> permissionService.checkPermission(productId, "project:product:query", false));
|
||||
@@ -76,11 +67,9 @@ class ProductObjectPermissionServiceTest extends BaseMockitoUnitTest {
|
||||
Long loginUserId = 2003L;
|
||||
when(userObjectRoleMapper.selectActiveByObjectAndUserId("product", productId, loginUserId))
|
||||
.thenReturn(createMember(productId, loginUserId, 3003L));
|
||||
when(systemRoleMenuMapper.selectListByRoleId(3003L))
|
||||
.thenReturn(List.of(createRoleMenu(3003L, 4003L)));
|
||||
when(systemMenuMapper.selectListByIdsAndScopeAndObjectType(any(),
|
||||
eq(PermissionScopeTypeEnum.OBJECT.getScopeType()), eq("product")))
|
||||
.thenReturn(List.of(createMenu(4003L, MenuTypeEnum.BUTTON.getType(), "project:product:update")));
|
||||
when(objectPermissionApi.getObjectRolePermissions(3003L,
|
||||
PermissionScopeTypeEnum.OBJECT.getScopeType(), "product"))
|
||||
.thenReturn(success(Set.of("project:product:update")));
|
||||
|
||||
try (MockedStatic<SecurityFrameworkUtils> mockedStatic = mockLoginUser(loginUserId)) {
|
||||
ServiceException ex = assertThrows(ServiceException.class,
|
||||
@@ -89,6 +78,22 @@ class ProductObjectPermissionServiceTest extends BaseMockitoUnitTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void checkPermission_whenCurrentUserIsNotMember_shouldThrowException() {
|
||||
Long productId = 1004L;
|
||||
Long loginUserId = 2004L;
|
||||
when(userObjectRoleMapper.selectActiveByObjectAndUserId("product", productId, loginUserId))
|
||||
.thenReturn(null);
|
||||
|
||||
try (MockedStatic<SecurityFrameworkUtils> mockedStatic = mockLoginUser(loginUserId)) {
|
||||
ServiceException ex = assertThrows(ServiceException.class,
|
||||
() -> permissionService.checkPermission(productId, "project:product:query", false));
|
||||
assertEquals(ErrorCodeConstants.PRODUCT_OBJECT_PERMISSION_DENIED.getCode(), ex.getCode());
|
||||
}
|
||||
|
||||
verifyNoInteractions(objectPermissionApi);
|
||||
}
|
||||
|
||||
private UserObjectRoleDO createMember(Long productId, Long loginUserId, Long roleId) {
|
||||
UserObjectRoleDO member = new UserObjectRoleDO();
|
||||
member.setId(9001L);
|
||||
@@ -100,25 +105,6 @@ class ProductObjectPermissionServiceTest extends BaseMockitoUnitTest {
|
||||
return member;
|
||||
}
|
||||
|
||||
private SystemRoleMenuDO createRoleMenu(Long roleId, Long menuId) {
|
||||
SystemRoleMenuDO roleMenu = new SystemRoleMenuDO();
|
||||
roleMenu.setId(9101L);
|
||||
roleMenu.setRoleId(roleId);
|
||||
roleMenu.setMenuId(menuId);
|
||||
return roleMenu;
|
||||
}
|
||||
|
||||
private SystemMenuDO createMenu(Long menuId, Integer type, String permission) {
|
||||
SystemMenuDO menu = new SystemMenuDO();
|
||||
menu.setId(menuId);
|
||||
menu.setType(type);
|
||||
menu.setPermission(permission);
|
||||
menu.setScopeType(PermissionScopeTypeEnum.OBJECT.getScopeType());
|
||||
menu.setObjectType("product");
|
||||
menu.setStatus(0);
|
||||
return menu;
|
||||
}
|
||||
|
||||
private MockedStatic<SecurityFrameworkUtils> mockLoginUser(Long loginUserId) {
|
||||
MockedStatic<SecurityFrameworkUtils> mockedStatic = mockStatic(SecurityFrameworkUtils.class);
|
||||
mockedStatic.when(SecurityFrameworkUtils::getLoginUserId).thenReturn(loginUserId);
|
||||
|
||||
@@ -5,29 +5,27 @@ import com.njcn.rdms.framework.common.exception.ServiceException;
|
||||
import com.njcn.rdms.framework.security.core.util.SecurityFrameworkUtils;
|
||||
import com.njcn.rdms.framework.common.util.json.JsonUtils;
|
||||
import com.njcn.rdms.framework.test.core.ut.BaseMockitoUnitTest;
|
||||
import com.njcn.rdms.module.project.controller.admin.product.vo.product.ProductContextRespVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.product.vo.product.ProductDeleteReqVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.product.vo.product.ProductSaveReqVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.product.vo.product.ProductStatusActionReqVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.product.vo.setting.ProductSettingBaseInfoUpdateReqVO;
|
||||
import com.njcn.rdms.module.project.dal.dataobject.audit.BizAuditLogDO;
|
||||
import com.njcn.rdms.module.project.dal.dataobject.member.UserObjectRoleDO;
|
||||
import com.njcn.rdms.module.project.dal.dataobject.permission.SystemMenuDO;
|
||||
import com.njcn.rdms.module.project.dal.dataobject.permission.SystemRoleMenuDO;
|
||||
import com.njcn.rdms.module.project.dal.dataobject.product.ProductDO;
|
||||
import com.njcn.rdms.module.project.dal.dataobject.product.ProductStatusLogDO;
|
||||
import com.njcn.rdms.module.project.dal.dataobject.status.ObjectStatusTransitionDO;
|
||||
import com.njcn.rdms.module.project.dal.mysql.audit.BizAuditLogMapper;
|
||||
import com.njcn.rdms.module.project.dal.mysql.member.UserObjectRoleMapper;
|
||||
import com.njcn.rdms.module.project.dal.mysql.permission.SystemMenuMapper;
|
||||
import com.njcn.rdms.module.project.dal.mysql.permission.SystemRoleMapper;
|
||||
import com.njcn.rdms.module.project.dal.mysql.permission.SystemRoleMenuMapper;
|
||||
import com.njcn.rdms.module.project.dal.mysql.product.ProductMapper;
|
||||
import com.njcn.rdms.module.project.dal.mysql.product.ProductStatusLogMapper;
|
||||
import com.njcn.rdms.module.project.dal.mysql.status.ObjectStatusTransitionMapper;
|
||||
import com.njcn.rdms.module.project.enums.ErrorCodeConstants;
|
||||
import com.njcn.rdms.module.system.api.permission.ObjectPermissionApi;
|
||||
import com.njcn.rdms.module.system.api.permission.dto.ObjectMenuRespDTO;
|
||||
import com.njcn.rdms.module.system.api.permission.dto.ObjectRolePermissionRespDTO;
|
||||
import com.njcn.rdms.module.system.api.permission.dto.ObjectRoleRespDTO;
|
||||
import com.njcn.rdms.module.system.api.user.AdminUserApi;
|
||||
import com.njcn.rdms.module.system.enums.permission.MenuTypeEnum;
|
||||
import com.njcn.rdms.module.system.enums.permission.PermissionScopeTypeEnum;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.InjectMocks;
|
||||
@@ -35,13 +33,15 @@ import org.mockito.MockedStatic;
|
||||
import org.mockito.Mock;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.njcn.rdms.framework.common.pojo.CommonResult.success;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mockStatic;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
@@ -63,11 +63,7 @@ class ProductServiceImplTest extends BaseMockitoUnitTest {
|
||||
@Mock
|
||||
private UserObjectRoleMapper userObjectRoleMapper;
|
||||
@Mock
|
||||
private SystemRoleMapper systemRoleMapper;
|
||||
@Mock
|
||||
private SystemRoleMenuMapper systemRoleMenuMapper;
|
||||
@Mock
|
||||
private SystemMenuMapper systemMenuMapper;
|
||||
private ObjectPermissionApi objectPermissionApi;
|
||||
@Mock
|
||||
private AdminUserApi adminUserApi;
|
||||
|
||||
@@ -343,6 +339,42 @@ class ProductServiceImplTest extends BaseMockitoUnitTest {
|
||||
assertEquals(ErrorCodeConstants.PRODUCT_STATUS_NOT_ALLOW_EDIT.getCode(), ex.getCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getProductContext_shouldAssembleCurrentRoleNavsAndButtonsFromObjectPermissionApi() {
|
||||
Long productId = 1014L;
|
||||
Long loginUserId = 3014L;
|
||||
Long roleId = 9101L;
|
||||
ProductDO product = createProduct(productId, "direction_value", "产品上下文", 2017L, "旧描述", "active");
|
||||
UserObjectRoleDO currentMember = createMember(productId, loginUserId, roleId);
|
||||
ObjectRolePermissionRespDTO detail = new ObjectRolePermissionRespDTO();
|
||||
detail.setCurrentRole(createRole(roleId, "product_manager", "产品经理"));
|
||||
detail.setMenus(List.of(
|
||||
createMenu(9303L, "保存", "project:product:update", 3, 30, null, null, true),
|
||||
createMenu(9302L, "隐藏导航", null, 2, 20, "/product/hidden", "mdi:hidden", false),
|
||||
createMenu(9301L, "概览", null, 2, 10, "/product/overview", "mdi:view-dashboard-outline", true)
|
||||
));
|
||||
detail.setPermissions(Set.of("project:product:update"));
|
||||
|
||||
when(productMapper.selectById(productId)).thenReturn(product);
|
||||
when(userObjectRoleMapper.selectActiveByObjectAndUserId("product", productId, loginUserId))
|
||||
.thenReturn(currentMember);
|
||||
when(objectPermissionApi.getObjectRolePermissionDetail(roleId, "object", "product"))
|
||||
.thenReturn(success(detail));
|
||||
|
||||
ProductContextRespVO respVO;
|
||||
try (MockedStatic<SecurityFrameworkUtils> mockedStatic = mockLoginUser(loginUserId, "测试人")) {
|
||||
respVO = productService.getProductContext(productId);
|
||||
}
|
||||
|
||||
assertNotNull(respVO.getCurrentProduct());
|
||||
assertEquals(roleId, respVO.getCurrentRole().getRoleId());
|
||||
assertEquals("product_manager", respVO.getCurrentRole().getRoleCode());
|
||||
assertEquals("产品经理", respVO.getCurrentRole().getRoleName());
|
||||
assertEquals(1, respVO.getNavs().size());
|
||||
assertEquals(9301L, respVO.getNavs().get(0).getId());
|
||||
assertEquals(List.of("project:product:update"), respVO.getButtons());
|
||||
}
|
||||
|
||||
private ProductDO createProduct(Long id, String directionCode, String name, Long managerUserId,
|
||||
String description, String statusCode) {
|
||||
ProductDO product = new ProductDO();
|
||||
@@ -356,35 +388,39 @@ class ProductServiceImplTest extends BaseMockitoUnitTest {
|
||||
return product;
|
||||
}
|
||||
|
||||
private void mockObjectPermission(Long productId, Long loginUserId, String permission) {
|
||||
private UserObjectRoleDO createMember(Long productId, Long userId, Long roleId) {
|
||||
UserObjectRoleDO currentMember = new UserObjectRoleDO();
|
||||
currentMember.setId(9001L);
|
||||
currentMember.setUserId(loginUserId);
|
||||
currentMember.setUserId(userId);
|
||||
currentMember.setObjectType("product");
|
||||
currentMember.setObjectId(productId);
|
||||
currentMember.setRoleId(9101L);
|
||||
currentMember.setRoleId(roleId);
|
||||
currentMember.setStatus(0);
|
||||
return currentMember;
|
||||
}
|
||||
|
||||
SystemRoleMenuDO roleMenu = new SystemRoleMenuDO();
|
||||
roleMenu.setId(9201L);
|
||||
roleMenu.setRoleId(9101L);
|
||||
roleMenu.setMenuId(9301L);
|
||||
private ObjectRoleRespDTO createRole(Long roleId, String roleCode, String roleName) {
|
||||
ObjectRoleRespDTO role = new ObjectRoleRespDTO();
|
||||
role.setId(roleId);
|
||||
role.setCode(roleCode);
|
||||
role.setName(roleName);
|
||||
role.setScopeType("object");
|
||||
role.setObjectType("product");
|
||||
return role;
|
||||
}
|
||||
|
||||
SystemMenuDO menu = new SystemMenuDO();
|
||||
menu.setId(9301L);
|
||||
private ObjectMenuRespDTO createMenu(Long menuId, String name, String permission, Integer type, Integer sort,
|
||||
String path, String icon, Boolean visible) {
|
||||
ObjectMenuRespDTO menu = new ObjectMenuRespDTO();
|
||||
menu.setId(menuId);
|
||||
menu.setName(name);
|
||||
menu.setPermission(permission);
|
||||
menu.setScopeType(PermissionScopeTypeEnum.OBJECT.getScopeType());
|
||||
menu.setObjectType("product");
|
||||
menu.setType(MenuTypeEnum.BUTTON.getType());
|
||||
menu.setStatus(0);
|
||||
menu.setVisible(true);
|
||||
|
||||
when(userObjectRoleMapper.selectActiveByObjectAndUserId("product", productId, loginUserId))
|
||||
.thenReturn(currentMember);
|
||||
when(systemRoleMenuMapper.selectListByRoleId(9101L)).thenReturn(List.of(roleMenu));
|
||||
when(systemMenuMapper.selectListByIdsAndScopeAndObjectType(
|
||||
any(), eq(PermissionScopeTypeEnum.OBJECT.getScopeType()), eq("product")))
|
||||
.thenReturn(List.of(menu));
|
||||
menu.setType(type);
|
||||
menu.setSort(sort);
|
||||
menu.setPath(path);
|
||||
menu.setIcon(icon);
|
||||
menu.setVisible(visible);
|
||||
return menu;
|
||||
}
|
||||
|
||||
private ObjectStatusTransitionDO createTransition(String actionCode, String toStatus, boolean needReason) {
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package com.njcn.rdms.module.system.service.permission;
|
||||
|
||||
import com.njcn.rdms.module.system.dal.dataobject.permission.MenuDO;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
@@ -81,6 +84,10 @@ public interface PermissionService {
|
||||
return getRoleMenuListByRoleId(roleIds);
|
||||
}
|
||||
|
||||
List<MenuDO> getScopedMenusByRoleId(Long roleId, String scopeType, String objectType);
|
||||
|
||||
Set<String> getScopedPermissionsByRoleId(Long roleId, String scopeType, String objectType);
|
||||
|
||||
/**
|
||||
* 获得拥有指定菜单的角色编号数组,从缓存中获取
|
||||
*
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.njcn.rdms.module.system.service.permission;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
import com.njcn.rdms.framework.common.enums.CommonStatusEnum;
|
||||
import com.njcn.rdms.framework.common.util.collection.CollectionUtils;
|
||||
@@ -248,7 +249,9 @@ public class PermissionServiceImpl implements PermissionService {
|
||||
}
|
||||
|
||||
// 统一按角色实际授权返回当前仍然有效的菜单,并补齐其父链
|
||||
Set<Long> scopedRoleIds = convertSet(roleService.getRoleList(roleIds, scopeType, objectType), RoleDO::getId);
|
||||
Set<Long> scopedRoleIds = convertSet(roleService.getRoleList(roleIds, scopeType, objectType).stream()
|
||||
.filter(role -> CommonStatusEnum.ENABLE.getStatus().equals(role.getStatus()))
|
||||
.toList(), RoleDO::getId);
|
||||
if (CollUtil.isEmpty(scopedRoleIds)) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
@@ -257,6 +260,34 @@ public class PermissionServiceImpl implements PermissionService {
|
||||
return expandMenuIdsWithAncestors(convertSet(menus, MenuDO::getId), scopeType, objectType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MenuDO> getScopedMenusByRoleId(Long roleId, String scopeType, String objectType) {
|
||||
RoleDO role = getEnabledScopedRole(roleId, scopeType, objectType);
|
||||
if (role == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
Set<Long> menuIds = getRoleMenuListByRoleId(Collections.singleton(roleId), scopeType, objectType);
|
||||
if (CollUtil.isEmpty(menuIds)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return menuService.filterDisableMenus(menuService.getMenuList(menuIds, scopeType, objectType));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getScopedPermissionsByRoleId(Long roleId, String scopeType, String objectType) {
|
||||
List<MenuDO> menus = getScopedMenusByRoleId(roleId, scopeType, objectType);
|
||||
if (CollUtil.isEmpty(menus)) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
Set<String> permissions = new LinkedHashSet<>();
|
||||
menus.forEach(menu -> {
|
||||
if (StrUtil.isNotBlank(menu.getPermission())) {
|
||||
permissions.add(menu.getPermission());
|
||||
}
|
||||
});
|
||||
return permissions;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Cacheable(value = RedisKeyConstants.MENU_ROLE_ID_LIST, key = "#menuId")
|
||||
public Set<Long> getMenuRoleIdListByMenuIdFromCache(Long menuId) {
|
||||
@@ -357,6 +388,18 @@ public class PermissionServiceImpl implements PermissionService {
|
||||
return role;
|
||||
}
|
||||
|
||||
/**
|
||||
* scoped 权限查询只消费当前仍然有效的对象角色;缺失、作用域不匹配或已禁用时都返回 null,
|
||||
* 由上层统一收口为空菜单/空权限结果。
|
||||
*/
|
||||
private RoleDO getEnabledScopedRole(Long roleId, String scopeType, String objectType) {
|
||||
RoleDO role = roleService.getRole(roleId, scopeType, objectType);
|
||||
if (role == null || !CommonStatusEnum.ENABLE.getStatus().equals(role.getStatus())) {
|
||||
return null;
|
||||
}
|
||||
return role;
|
||||
}
|
||||
|
||||
private PermissionServiceImpl getSelf() {
|
||||
return SpringUtil.getBean(getClass());
|
||||
}
|
||||
|
||||
@@ -54,6 +54,10 @@ public interface RoleService {
|
||||
*/
|
||||
RoleDO getRole(Long id);
|
||||
|
||||
RoleDO getRole(Long roleId, String scopeType, String objectType);
|
||||
|
||||
RoleDO getRoleByCode(String code, String scopeType, String objectType);
|
||||
|
||||
/**
|
||||
* 获得角色,从缓存中
|
||||
*
|
||||
|
||||
@@ -208,6 +208,17 @@ public class RoleServiceImpl implements RoleService {
|
||||
return roleMapper.selectById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RoleDO getRole(Long roleId, String scopeType, String objectType) {
|
||||
RoleDO role = roleMapper.selectById(roleId);
|
||||
return matchesScope(role, scopeType, objectType) ? role : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RoleDO getRoleByCode(String code, String scopeType, String objectType) {
|
||||
return roleMapper.selectByCode(code, scopeType, objectType);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Cacheable(value = RedisKeyConstants.ROLE, key = "#id", unless = "#result == null")
|
||||
public RoleDO getRoleFromCache(Long id) {
|
||||
|
||||
Reference in New Issue
Block a user