mirror of
https://gitee.com/dromara/RuoYi-Vue-Plus.git
synced 2026-03-21 04:48:59 +08:00
[重大更新] 数据权限增加角色与菜单关联 实现 角色->菜单->数据权限 控制数据权限功能(实验性功能不稳定)
This commit is contained in:
@@ -157,7 +157,9 @@ public class SysLoginService {
|
|||||||
loginUser.setRolePermission(permissionService.getRolePermission(userId));
|
loginUser.setRolePermission(permissionService.getRolePermission(userId));
|
||||||
}, () -> {
|
}, () -> {
|
||||||
List<SysRoleVo> roles = roleService.selectRolesByUserId(userId);
|
List<SysRoleVo> roles = roleService.selectRolesByUserId(userId);
|
||||||
loginUser.setRoles(BeanUtil.copyToList(roles, RoleDTO.class));
|
List<RoleDTO> roleDtos = BeanUtil.copyToList(roles, RoleDTO.class);
|
||||||
|
loginUser.setRoles(roleDtos);
|
||||||
|
loginUser.setDataScopeRoleMap(permissionService.getDataScopeRoleMap(roleDtos));
|
||||||
}, () -> {
|
}, () -> {
|
||||||
List<SysPostVo> posts = postService.selectPostsByUserId(userId);
|
List<SysPostVo> posts = postService.selectPostsByUserId(userId);
|
||||||
loginUser.setPosts(BeanUtil.copyToList(posts, PostDTO.class));
|
loginUser.setPosts(BeanUtil.copyToList(posts, PostDTO.class));
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import org.dromara.common.core.domain.dto.RoleDTO;
|
|||||||
import java.io.Serial;
|
import java.io.Serial;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -107,6 +108,11 @@ public class LoginUser implements Serializable {
|
|||||||
*/
|
*/
|
||||||
private List<RoleDTO> roles;
|
private List<RoleDTO> roles;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据权限角色映射 key 为权限码 value 为可参与数据权限计算的角色
|
||||||
|
*/
|
||||||
|
private Map<String, List<RoleDTO>> dataScopeRoleMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 岗位对象
|
* 岗位对象
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
package org.dromara.common.core.service;
|
package org.dromara.common.core.service;
|
||||||
|
|
||||||
|
import org.dromara.common.core.domain.dto.RoleDTO;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -25,4 +29,12 @@ public interface PermissionService {
|
|||||||
*/
|
*/
|
||||||
Set<String> getMenuPermission(Long userId);
|
Set<String> getMenuPermission(Long userId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据角色列表构建数据权限角色映射
|
||||||
|
*
|
||||||
|
* @param roles 角色列表
|
||||||
|
* @return key 为权限码 value 为命中的角色列表
|
||||||
|
*/
|
||||||
|
Map<String, List<RoleDTO>> getDataScopeRoleMap(List<RoleDTO> roles);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -449,4 +449,15 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查字符串是否包含任意一个指定的字符序列
|
||||||
|
*
|
||||||
|
* @param cs 要检查的字符串
|
||||||
|
* @param searchCharSequences 需要查找的字符序列数组
|
||||||
|
* @return 如果包含任意一个字符序列返回 true,否则返回 false
|
||||||
|
*/
|
||||||
|
public static boolean containsAny(final CharSequence cs, final CharSequence... searchCharSequences) {
|
||||||
|
return Strings.CS.containsAny(cs, searchCharSequences);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,11 +30,4 @@ public @interface DataColumn {
|
|||||||
*/
|
*/
|
||||||
String[] value() default "dept_id";
|
String[] value() default "dept_id";
|
||||||
|
|
||||||
/**
|
|
||||||
* 权限标识符 用于通过菜单权限标识符来获取数据权限
|
|
||||||
* 拥有此标识符的角色 将不会拼接此角色的数据过滤sql
|
|
||||||
*
|
|
||||||
* @return 权限标识符
|
|
||||||
*/
|
|
||||||
String permission() default "";
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
package org.dromara.common.mybatis.handler;
|
package org.dromara.common.mybatis.handler;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||||
|
import cn.dev33.satoken.annotation.SaCheckRole;
|
||||||
|
import cn.hutool.core.annotation.AnnotationUtil;
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import net.sf.jsqlparser.JSQLParserException;
|
import net.sf.jsqlparser.JSQLParserException;
|
||||||
@@ -12,6 +16,7 @@ import net.sf.jsqlparser.parser.CCJSqlParserUtil;
|
|||||||
import org.dromara.common.core.domain.dto.RoleDTO;
|
import org.dromara.common.core.domain.dto.RoleDTO;
|
||||||
import org.dromara.common.core.domain.model.LoginUser;
|
import org.dromara.common.core.domain.model.LoginUser;
|
||||||
import org.dromara.common.core.exception.ServiceException;
|
import org.dromara.common.core.exception.ServiceException;
|
||||||
|
import org.dromara.common.core.utils.ServletUtils;
|
||||||
import org.dromara.common.core.utils.SpringUtils;
|
import org.dromara.common.core.utils.SpringUtils;
|
||||||
import org.dromara.common.core.utils.StreamUtils;
|
import org.dromara.common.core.utils.StreamUtils;
|
||||||
import org.dromara.common.core.utils.StringUtils;
|
import org.dromara.common.core.utils.StringUtils;
|
||||||
@@ -25,7 +30,10 @@ import org.springframework.expression.*;
|
|||||||
import org.springframework.expression.common.TemplateParserContext;
|
import org.springframework.expression.common.TemplateParserContext;
|
||||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||||
|
import org.springframework.web.method.HandlerMethod;
|
||||||
|
import org.springframework.web.servlet.HandlerMapping;
|
||||||
|
|
||||||
|
import java.lang.annotation.Annotation;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
@@ -57,20 +65,13 @@ public class PlusDataPermissionHandler {
|
|||||||
*/
|
*/
|
||||||
public Expression getSqlSegment(Expression where, boolean isSelect) {
|
public Expression getSqlSegment(Expression where, boolean isSelect) {
|
||||||
try {
|
try {
|
||||||
// 获取数据权限配置
|
LoginUser currentUser = currentUser();
|
||||||
DataPermission dataPermission = getDataPermission();
|
|
||||||
// 获取当前登录用户信息
|
|
||||||
LoginUser currentUser = DataPermissionHelper.getVariable("user");
|
|
||||||
if (ObjectUtil.isNull(currentUser)) {
|
|
||||||
currentUser = LoginHelper.getLoginUser();
|
|
||||||
DataPermissionHelper.setVariable("user", currentUser);
|
|
||||||
}
|
|
||||||
// 如果是超级管理员或租户管理员,则不过滤数据
|
// 如果是超级管理员或租户管理员,则不过滤数据
|
||||||
if (LoginHelper.isSuperAdmin()) {
|
if (LoginHelper.isSuperAdmin()) {
|
||||||
return where;
|
return where;
|
||||||
}
|
}
|
||||||
// 构造数据过滤条件的 SQL 片段
|
// 构造数据过滤条件的 SQL 片段
|
||||||
String dataFilterSql = buildDataFilter(dataPermission, isSelect);
|
String dataFilterSql = buildDataFilter(getDataPermission(), currentUser, isSelect);
|
||||||
if (StringUtils.isBlank(dataFilterSql)) {
|
if (StringUtils.isBlank(dataFilterSql)) {
|
||||||
return where;
|
return where;
|
||||||
}
|
}
|
||||||
@@ -97,33 +98,32 @@ public class PlusDataPermissionHandler {
|
|||||||
* @return 构建的数据过滤条件的 SQL 语句
|
* @return 构建的数据过滤条件的 SQL 语句
|
||||||
* @throws ServiceException 如果角色的数据范围异常或者 key 与 value 的长度不匹配,则抛出 ServiceException 异常
|
* @throws ServiceException 如果角色的数据范围异常或者 key 与 value 的长度不匹配,则抛出 ServiceException 异常
|
||||||
*/
|
*/
|
||||||
private String buildDataFilter(DataPermission dataPermission, boolean isSelect) {
|
private String buildDataFilter(DataPermission dataPermission, LoginUser user, boolean isSelect) {
|
||||||
// 更新或删除需满足所有条件
|
// 更新或删除需满足所有条件
|
||||||
String joinStr = isSelect ? " OR " : " AND ";
|
String joinStr = isSelect ? " OR " : " AND ";
|
||||||
if (StringUtils.isNotBlank(dataPermission.joinStr())) {
|
if (StringUtils.isNotBlank(dataPermission.joinStr())) {
|
||||||
joinStr = " " + dataPermission.joinStr() + " ";
|
joinStr = " " + dataPermission.joinStr() + " ";
|
||||||
}
|
}
|
||||||
LoginUser user = DataPermissionHelper.getVariable("user");
|
|
||||||
Object defaultValue = "-1";
|
Object defaultValue = "-1";
|
||||||
NullSafeStandardEvaluationContext context = new NullSafeStandardEvaluationContext(defaultValue);
|
NullSafeStandardEvaluationContext context = new NullSafeStandardEvaluationContext(defaultValue);
|
||||||
context.addPropertyAccessor(new NullSafePropertyAccessor(context.getPropertyAccessors().get(0), defaultValue));
|
context.addPropertyAccessor(new NullSafePropertyAccessor(context.getPropertyAccessors().get(0), defaultValue));
|
||||||
context.setBeanResolver(beanResolver);
|
context.setBeanResolver(beanResolver);
|
||||||
DataPermissionHelper.getContext().forEach(context::setVariable);
|
DataPermissionHelper.getContext().forEach(context::setVariable);
|
||||||
Set<String> conditions = new HashSet<>();
|
Set<String> conditions = new HashSet<>();
|
||||||
|
RequestAccess access = currentAccess();
|
||||||
|
List<RoleDTO> scopeRoles = scopeRoles(user, access);
|
||||||
|
if (CollUtil.isEmpty(scopeRoles)) {
|
||||||
|
if (access.constrained()) {
|
||||||
|
return " 1 = 0 ";
|
||||||
|
}
|
||||||
|
return StringUtils.EMPTY;
|
||||||
|
}
|
||||||
// 优先设置变量
|
// 优先设置变量
|
||||||
List<String> keys = new ArrayList<>();
|
List<String> keys = new ArrayList<>();
|
||||||
Map<DataColumn, Boolean> ignoreMap = new HashMap<>();
|
|
||||||
for (DataColumn dataColumn : dataPermission.value()) {
|
for (DataColumn dataColumn : dataPermission.value()) {
|
||||||
if (dataColumn.key().length != dataColumn.value().length) {
|
if (dataColumn.key().length != dataColumn.value().length) {
|
||||||
throw new ServiceException("角色数据范围异常 => key与value长度不匹配");
|
throw new ServiceException("角色数据范围异常 => key与value长度不匹配");
|
||||||
}
|
}
|
||||||
// 包含权限标识符 这直接跳过
|
|
||||||
if (StringUtils.isNotBlank(dataColumn.permission()) &&
|
|
||||||
CollUtil.contains(user.getMenuPermission(), dataColumn.permission())
|
|
||||||
) {
|
|
||||||
ignoreMap.put(dataColumn, Boolean.TRUE);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// 设置注解变量 key 为表达式变量 value 为变量值
|
// 设置注解变量 key 为表达式变量 value 为变量值
|
||||||
for (int i = 0; i < dataColumn.key().length; i++) {
|
for (int i = 0; i < dataColumn.key().length; i++) {
|
||||||
context.setVariable(dataColumn.key()[i], dataColumn.value()[i]);
|
context.setVariable(dataColumn.key()[i], dataColumn.value()[i]);
|
||||||
@@ -131,7 +131,7 @@ public class PlusDataPermissionHandler {
|
|||||||
keys.addAll(Arrays.stream(dataColumn.key()).map(key -> "#" + key).toList());
|
keys.addAll(Arrays.stream(dataColumn.key()).map(key -> "#" + key).toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (RoleDTO role : user.getRoles()) {
|
for (RoleDTO role : scopeRoles) {
|
||||||
user.setRoleId(role.getRoleId());
|
user.setRoleId(role.getRoleId());
|
||||||
// 获取角色权限泛型
|
// 获取角色权限泛型
|
||||||
DataScopeType type = DataScopeType.findCode(role.getDataScope());
|
DataScopeType type = DataScopeType.findCode(role.getDataScope());
|
||||||
@@ -144,13 +144,6 @@ public class PlusDataPermissionHandler {
|
|||||||
}
|
}
|
||||||
boolean isSuccess = false;
|
boolean isSuccess = false;
|
||||||
for (DataColumn dataColumn : dataPermission.value()) {
|
for (DataColumn dataColumn : dataPermission.value()) {
|
||||||
// 包含权限标识符 这直接跳过
|
|
||||||
if (ignoreMap.containsKey(dataColumn)) {
|
|
||||||
// 修复多角色与权限标识符共用问题 https://gitee.com/dromara/RuoYi-Vue-Plus/issues/IB4CS4
|
|
||||||
conditions.add(joinStr + " 1 = 1 ");
|
|
||||||
isSuccess = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// 不包含 key 变量 则不处理
|
// 不包含 key 变量 则不处理
|
||||||
if (!StringUtils.containsAny(type.getSqlTemplate(), keys.toArray(String[]::new))) {
|
if (!StringUtils.containsAny(type.getSqlTemplate(), keys.toArray(String[]::new))) {
|
||||||
continue;
|
continue;
|
||||||
@@ -180,6 +173,78 @@ public class PlusDataPermissionHandler {
|
|||||||
return StringUtils.EMPTY;
|
return StringUtils.EMPTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private LoginUser currentUser() {
|
||||||
|
LoginUser currentUser = DataPermissionHelper.getVariable("user");
|
||||||
|
if (ObjectUtil.isNull(currentUser)) {
|
||||||
|
currentUser = LoginHelper.getLoginUser();
|
||||||
|
DataPermissionHelper.setVariable("user", currentUser);
|
||||||
|
}
|
||||||
|
return currentUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
private RequestAccess currentAccess() {
|
||||||
|
HttpServletRequest request = ServletUtils.getRequest();
|
||||||
|
if (request == null) {
|
||||||
|
return RequestAccess.EMPTY;
|
||||||
|
}
|
||||||
|
Object handler = request.getAttribute(HandlerMapping.BEST_MATCHING_HANDLER_ATTRIBUTE);
|
||||||
|
if (!(handler instanceof HandlerMethod handlerMethod)) {
|
||||||
|
return RequestAccess.EMPTY;
|
||||||
|
}
|
||||||
|
SaCheckPermission saCheckPermission = findAnnotation(handlerMethod, SaCheckPermission.class);
|
||||||
|
SaCheckRole saCheckRole = findAnnotation(handlerMethod, SaCheckRole.class);
|
||||||
|
Set<String> perms = saCheckPermission == null ? Set.of() : toSet(saCheckPermission.value());
|
||||||
|
Set<String> roleKeys = new LinkedHashSet<>();
|
||||||
|
if (saCheckPermission != null) {
|
||||||
|
roleKeys.addAll(toSet(saCheckPermission.orRole()));
|
||||||
|
}
|
||||||
|
if (saCheckRole != null) {
|
||||||
|
roleKeys.addAll(toSet(saCheckRole.value()));
|
||||||
|
}
|
||||||
|
return new RequestAccess(perms, roleKeys);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<RoleDTO> scopeRoles(LoginUser user, RequestAccess access) {
|
||||||
|
List<RoleDTO> roles = user.getRoles();
|
||||||
|
if (!access.constrained()) {
|
||||||
|
return roles;
|
||||||
|
}
|
||||||
|
Map<Long, RoleDTO> roleMap = new LinkedHashMap<>();
|
||||||
|
Map<String, List<RoleDTO>> dataScopeRoleMap = user.getDataScopeRoleMap();
|
||||||
|
if (CollUtil.isNotEmpty(dataScopeRoleMap)) {
|
||||||
|
access.perms.forEach(perm -> {
|
||||||
|
List<RoleDTO> roleList = dataScopeRoleMap.get(perm);
|
||||||
|
if (CollUtil.isNotEmpty(roleList)) {
|
||||||
|
roleList.forEach(role -> roleMap.putIfAbsent(role.getRoleId(), role));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (CollUtil.isNotEmpty(roles) && CollUtil.isNotEmpty(access.roleKeys)) {
|
||||||
|
roles.stream()
|
||||||
|
.filter(role -> StringUtils.isNotBlank(role.getRoleKey()))
|
||||||
|
.filter(role -> StringUtils.splitList(role.getRoleKey()).stream().anyMatch(access.roleKeys::contains))
|
||||||
|
.forEach(role -> roleMap.putIfAbsent(role.getRoleId(), role));
|
||||||
|
}
|
||||||
|
return new ArrayList<>(roleMap.values());
|
||||||
|
}
|
||||||
|
|
||||||
|
private <A extends Annotation> A findAnnotation(HandlerMethod handlerMethod, Class<A> annotationType) {
|
||||||
|
A annotation = AnnotationUtil.getAnnotation(handlerMethod.getMethod(), annotationType);
|
||||||
|
if (annotation != null) {
|
||||||
|
return annotation;
|
||||||
|
}
|
||||||
|
return AnnotationUtil.getAnnotation(handlerMethod.getBeanType(), annotationType);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<String> toSet(String[] values) {
|
||||||
|
if (values == null || values.length == 0) {
|
||||||
|
return Set.of();
|
||||||
|
}
|
||||||
|
Set<String> result = new LinkedHashSet<>();
|
||||||
|
Arrays.stream(values).filter(StringUtils::isNotBlank).forEach(result::add);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据映射语句 ID 或类名获取对应的 DataPermission 注解对象
|
* 根据映射语句 ID 或类名获取对应的 DataPermission 注解对象
|
||||||
*
|
*
|
||||||
@@ -258,4 +323,13 @@ public class PlusDataPermissionHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private record RequestAccess(Set<String> perms, Set<String> roleKeys) {
|
||||||
|
|
||||||
|
private static final RequestAccess EMPTY = new RequestAccess(Set.of(), Set.of());
|
||||||
|
|
||||||
|
private boolean constrained() {
|
||||||
|
return CollUtil.isNotEmpty(perms) || CollUtil.isNotEmpty(roleKeys);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -124,7 +124,11 @@ public class SysRoleController extends BaseController {
|
|||||||
public R<Void> dataScope(@RequestBody SysRoleBo role) {
|
public R<Void> dataScope(@RequestBody SysRoleBo role) {
|
||||||
roleService.checkRoleAllowed(role);
|
roleService.checkRoleAllowed(role);
|
||||||
roleService.checkRoleDataScope(role.getRoleId());
|
roleService.checkRoleDataScope(role.getRoleId());
|
||||||
return toAjax(roleService.authDataScope(role));
|
if (roleService.authDataScope(role) > 0) {
|
||||||
|
roleService.cleanOnlineUserByRole(role.getRoleId());
|
||||||
|
return R.ok();
|
||||||
|
}
|
||||||
|
return R.fail("修改角色'" + role.getRoleName() + "'数据权限失败,请联系管理员");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -137,7 +141,11 @@ public class SysRoleController extends BaseController {
|
|||||||
public R<Void> changeStatus(@RequestBody SysRoleBo role) {
|
public R<Void> changeStatus(@RequestBody SysRoleBo role) {
|
||||||
roleService.checkRoleAllowed(role);
|
roleService.checkRoleAllowed(role);
|
||||||
roleService.checkRoleDataScope(role.getRoleId());
|
roleService.checkRoleDataScope(role.getRoleId());
|
||||||
return toAjax(roleService.updateRoleStatus(role.getRoleId(), role.getStatus()));
|
if (roleService.updateRoleStatus(role.getRoleId(), role.getStatus()) > 0) {
|
||||||
|
roleService.cleanOnlineUserByRole(role.getRoleId());
|
||||||
|
return R.ok();
|
||||||
|
}
|
||||||
|
return R.fail("修改角色'" + role.getRoleName() + "'状态失败,请联系管理员");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package org.dromara.system.mapper;
|
package org.dromara.system.mapper;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import org.dromara.common.core.constant.SystemConstants;
|
import org.dromara.common.core.constant.SystemConstants;
|
||||||
import org.dromara.common.core.utils.StreamUtils;
|
import org.dromara.common.core.utils.StreamUtils;
|
||||||
@@ -8,9 +9,7 @@ import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
|
|||||||
import org.dromara.system.domain.SysMenu;
|
import org.dromara.system.domain.SysMenu;
|
||||||
import org.dromara.system.domain.vo.SysMenuVo;
|
import org.dromara.system.domain.vo.SysMenuVo;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 菜单表 数据层
|
* 菜单表 数据层
|
||||||
@@ -111,6 +110,21 @@ public interface SysMenuMapper extends BaseMapperPlus<SysMenu, SysMenuVo> {
|
|||||||
return new HashSet<>(StreamUtils.filter(list, StringUtils::isNotBlank));
|
return new HashSet<>(StreamUtils.filter(list, StringUtils::isNotBlank));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据角色ID列表批量查询权限
|
||||||
|
*
|
||||||
|
* @param roleIds 角色ID列表
|
||||||
|
* @return 角色权限映射
|
||||||
|
*/
|
||||||
|
default Map<Long, Set<String>> selectMenuPermsByRoleIds(List<Long> roleIds) {
|
||||||
|
if (CollUtil.isEmpty(roleIds)) {
|
||||||
|
return Map.of();
|
||||||
|
}
|
||||||
|
Map<Long, Set<String>> result = new LinkedHashMap<>();
|
||||||
|
roleIds.forEach(roleId -> result.put(roleId, this.selectMenuPermsByRoleId(roleId)));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据用户ID查询菜单
|
* 根据用户ID查询菜单
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import org.dromara.system.domain.bo.SysMenuBo;
|
|||||||
import org.dromara.system.domain.vo.RouterVo;
|
import org.dromara.system.domain.vo.RouterVo;
|
||||||
import org.dromara.system.domain.vo.SysMenuVo;
|
import org.dromara.system.domain.vo.SysMenuVo;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@@ -49,6 +50,14 @@ public interface ISysMenuService {
|
|||||||
*/
|
*/
|
||||||
Set<String> selectMenuPermsByRoleId(Long roleId);
|
Set<String> selectMenuPermsByRoleId(Long roleId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据角色ID列表批量查询权限
|
||||||
|
*
|
||||||
|
* @param roleIds 角色ID列表
|
||||||
|
* @return 角色权限映射
|
||||||
|
*/
|
||||||
|
Map<Long, Set<String>> selectMenuPermsByRoleIds(List<Long> roleIds);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据用户ID查询菜单树信息
|
* 根据用户ID查询菜单树信息
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
package org.dromara.system.service;
|
package org.dromara.system.service;
|
||||||
|
|
||||||
|
import org.dromara.common.core.domain.dto.RoleDTO;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -25,4 +29,12 @@ public interface ISysPermissionService {
|
|||||||
*/
|
*/
|
||||||
Set<String> getMenuPermission(Long userId);
|
Set<String> getMenuPermission(Long userId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据角色列表构建数据权限角色映射
|
||||||
|
*
|
||||||
|
* @param roles 角色列表
|
||||||
|
* @return key 为权限码 value 为命中的角色列表
|
||||||
|
*/
|
||||||
|
Map<String, List<RoleDTO>> getDataScopeRoleMap(List<RoleDTO> roles);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -105,6 +106,17 @@ public class SysMenuServiceImpl implements ISysMenuService {
|
|||||||
return baseMapper.selectMenuPermsByRoleId(roleId);
|
return baseMapper.selectMenuPermsByRoleId(roleId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据角色ID列表批量查询权限
|
||||||
|
*
|
||||||
|
* @param roleIds 角色ID列表
|
||||||
|
* @return 角色权限映射
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Map<Long, Set<String>> selectMenuPermsByRoleIds(List<Long> roleIds) {
|
||||||
|
return baseMapper.selectMenuPermsByRoleIds(roleIds);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据用户ID查询菜单
|
* 根据用户ID查询菜单
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,16 +1,18 @@
|
|||||||
package org.dromara.system.service.impl;
|
package org.dromara.system.service.impl;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.dromara.common.core.constant.SystemConstants;
|
import org.dromara.common.core.constant.SystemConstants;
|
||||||
|
import org.dromara.common.core.domain.dto.RoleDTO;
|
||||||
import org.dromara.common.core.service.PermissionService;
|
import org.dromara.common.core.service.PermissionService;
|
||||||
|
import org.dromara.common.core.utils.StreamUtils;
|
||||||
import org.dromara.common.satoken.utils.LoginHelper;
|
import org.dromara.common.satoken.utils.LoginHelper;
|
||||||
import org.dromara.system.service.ISysMenuService;
|
import org.dromara.system.service.ISysMenuService;
|
||||||
import org.dromara.system.service.ISysPermissionService;
|
import org.dromara.system.service.ISysPermissionService;
|
||||||
import org.dromara.system.service.ISysRoleService;
|
import org.dromara.system.service.ISysRoleService;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.*;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户权限处理
|
* 用户权限处理
|
||||||
@@ -59,4 +61,21 @@ public class SysPermissionServiceImpl implements ISysPermissionService, Permissi
|
|||||||
}
|
}
|
||||||
return perms;
|
return perms;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, List<RoleDTO>> getDataScopeRoleMap(List<RoleDTO> roles) {
|
||||||
|
if (CollUtil.isEmpty(roles)) {
|
||||||
|
return Map.of();
|
||||||
|
}
|
||||||
|
Map<Long, RoleDTO> roleMap = StreamUtils.toIdentityMap(roles, RoleDTO::getRoleId);
|
||||||
|
List<Long> roleIds = StreamUtils.toList(roles, RoleDTO::getRoleId);
|
||||||
|
Map<Long, Set<String>> permsRoleIds = menuService.selectMenuPermsByRoleIds(roleIds);
|
||||||
|
Map<String, List<RoleDTO>> rolePermsMap = new LinkedHashMap<>();
|
||||||
|
permsRoleIds.forEach((roleId, perms) -> {
|
||||||
|
perms.forEach(perm -> {
|
||||||
|
rolePermsMap.computeIfAbsent(perm, k -> new ArrayList<>()).add(roleMap.get(roleId));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return rolePermsMap;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user