From 3d47e951be2742390c6087253bbda45cc2b90a9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90li?= <15040126243@163.com> Date: Tue, 7 Dec 2021 21:31:55 +0800 Subject: [PATCH] =?UTF-8?q?update=20[=E9=87=8D=E5=A4=A7=E6=9B=B4=E6=96=B0]?= =?UTF-8?q?=20=E9=87=8D=E5=86=99=E6=95=B0=E6=8D=AE=E6=9D=83=E9=99=90?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 7 + ruoyi-common/pom.xml | 5 + .../ruoyi/common/annotation/DataScope.java | 8 +- .../com/ruoyi/common/enums/DataScopeType.java | 61 ++++ .../com/ruoyi/demo/mapper/TestDemoMapper.java | 13 + .../com/ruoyi/demo/mapper/TestTreeMapper.java | 9 + .../service/impl/TestDemoServiceImpl.java | 8 +- .../service/impl/TestTreeServiceImpl.java | 2 - .../framework/aspectj/DataScopeAspect.java | 280 +++++++++--------- .../framework/config/MybatisPlusConfig.java | 13 + .../handler/PlusDataPermissionHandler.java | 117 ++++++++ .../ruoyi/system/mapper/SysDeptMapper.java | 8 + .../ruoyi/system/mapper/SysRoleMapper.java | 3 + .../ruoyi/system/mapper/SysUserMapper.java | 5 + .../service/impl/SysDeptServiceImpl.java | 5 +- .../service/impl/SysMenuServiceImpl.java | 1 + .../service/impl/SysRoleServiceImpl.java | 3 - .../service/impl/SysUserServiceImpl.java | 5 - .../resources/mapper/system/SysDeptMapper.xml | 8 +- .../resources/mapper/system/SysRoleMapper.xml | 16 +- .../resources/mapper/system/SysUserMapper.xml | 16 +- 21 files changed, 409 insertions(+), 184 deletions(-) create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/enums/DataScopeType.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/handler/PlusDataPermissionHandler.java diff --git a/pom.xml b/pom.xml index 0dd48a3b3..6ee5b9e67 100644 --- a/pom.xml +++ b/pom.xml @@ -25,6 +25,7 @@ 4.1.2 2.2.11 3.3.0 + 1.9 2.3 3.4.3.4 3.9.1 @@ -121,6 +122,12 @@ ${cglib.version} + + org.apache.commons + commons-text + ${common-text.version} + + org.apache.velocity diff --git a/ruoyi-common/pom.xml b/ruoyi-common/pom.xml index 2111510a7..35b5c5742 100644 --- a/ruoyi-common/pom.xml +++ b/ruoyi-common/pom.xml @@ -47,6 +47,11 @@ commons-lang3 + + org.apache.commons + commons-text + + com.fasterxml.jackson.core diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java index feaa3f42c..c5fbc7f3b 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java @@ -14,15 +14,11 @@ public @interface DataScope { /** * 部门表的别名 */ - String deptAlias() default ""; + String deptName() default ""; /** * 用户表的别名 */ - String userAlias() default ""; + String userName() default ""; - /** - * 是否过滤用户权限 - */ - boolean isUser() default false; } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/DataScopeType.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/DataScopeType.java new file mode 100644 index 000000000..3d182709b --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/DataScopeType.java @@ -0,0 +1,61 @@ +package com.ruoyi.common.enums; + +import com.ruoyi.common.utils.StringUtils; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 数据权限类型 + * + * 语法支持 spel 模板表达式 + * + * @author Lion Li + */ +@Getter +@AllArgsConstructor +public enum DataScopeType { + + /** + * 全部数据权限 + */ + DATA_SCOPE_ALL("1", ""), + + /** + * 自定数据权限 + */ + DATA_SCOPE_CUSTOM("2", " OR #{#deptName} IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = #{#roleId} ) "), + + /** + * 部门数据权限 + */ + DATA_SCOPE_DEPT("3", " OR #{#deptName} = #{#deptId} "), + + /** + * 部门及以下数据权限 + */ + DATA_SCOPE_DEPT_AND_CHILD("4", " OR #{#deptName} IN ( SELECT dept_id FROM sys_dept WHERE dept_id = #{#deptId} OR find_in_set( #{#deptId} , ancestors ) )"), + + /** + * 仅本人数据权限 + */ + DATA_SCOPE_SELF("5", " OR #{#userName?:1} = #{#userId?:0} "); + + private final String code; + + /** + * 语法 采用 spel 模板表达式 + */ + private final String sql; + + public static DataScopeType findCode(String code) { + if (StringUtils.isBlank(code)) { + return null; + } + for (DataScopeType type : values()) { + if (type.getCode().equals(code)) { + return type; + } + } + return null; + } +} diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/mapper/TestDemoMapper.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/mapper/TestDemoMapper.java index dccea6154..de597aae5 100644 --- a/ruoyi-demo/src/main/java/com/ruoyi/demo/mapper/TestDemoMapper.java +++ b/ruoyi-demo/src/main/java/com/ruoyi/demo/mapper/TestDemoMapper.java @@ -1,12 +1,17 @@ package com.ruoyi.demo.mapper; import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.Constants; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ruoyi.common.annotation.DataScope; import com.ruoyi.common.core.mybatisplus.core.BaseMapperPlus; import com.ruoyi.demo.domain.TestDemo; import com.ruoyi.demo.domain.vo.TestDemoVo; import org.apache.ibatis.annotations.Param; +import java.util.List; + /** * 测试单表Mapper接口 * @@ -15,6 +20,14 @@ import org.apache.ibatis.annotations.Param; */ public interface TestDemoMapper extends BaseMapperPlus { + @DataScope(deptName = "dept_id", userName = "user_id") Page customPageList(@Param("page") Page page, @Param("ew") Wrapper wrapper); + @Override + @DataScope(deptName = "dept_id", userName = "user_id") +

> P selectPage(P page, @Param(Constants.WRAPPER) Wrapper queryWrapper); + + @Override + @DataScope(deptName = "dept_id", userName = "user_id") + List selectList(@Param(Constants.WRAPPER) Wrapper queryWrapper); } diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/mapper/TestTreeMapper.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/mapper/TestTreeMapper.java index 05b0153b8..315dad771 100644 --- a/ruoyi-demo/src/main/java/com/ruoyi/demo/mapper/TestTreeMapper.java +++ b/ruoyi-demo/src/main/java/com/ruoyi/demo/mapper/TestTreeMapper.java @@ -1,7 +1,13 @@ package com.ruoyi.demo.mapper; +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Constants; +import com.ruoyi.common.annotation.DataScope; import com.ruoyi.common.core.mybatisplus.core.BaseMapperPlus; import com.ruoyi.demo.domain.TestTree; +import org.apache.ibatis.annotations.Param; + +import java.util.List; /** * 测试树表Mapper接口 @@ -11,4 +17,7 @@ import com.ruoyi.demo.domain.TestTree; */ public interface TestTreeMapper extends BaseMapperPlus { + @Override + @DataScope(deptName = "dept_id", userName = "user_id") + List selectList(@Param(Constants.WRAPPER) Wrapper queryWrapper); } diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/service/impl/TestDemoServiceImpl.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/service/impl/TestDemoServiceImpl.java index f717bfffd..1fa2057d5 100644 --- a/ruoyi-demo/src/main/java/com/ruoyi/demo/service/impl/TestDemoServiceImpl.java +++ b/ruoyi-demo/src/main/java/com/ruoyi/demo/service/impl/TestDemoServiceImpl.java @@ -1,16 +1,15 @@ package com.ruoyi.demo.service.impl; import cn.hutool.core.bean.BeanUtil; -import com.ruoyi.common.core.domain.PageQuery; -import com.ruoyi.common.utils.StringUtils; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.ruoyi.common.annotation.DataScope; +import com.ruoyi.common.core.domain.PageQuery; import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl; import com.ruoyi.common.core.page.PagePlus; import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.utils.PageUtils; +import com.ruoyi.common.utils.StringUtils; import com.ruoyi.demo.domain.TestDemo; import com.ruoyi.demo.domain.bo.TestDemoBo; import com.ruoyi.demo.domain.vo.TestDemoVo; @@ -36,7 +35,6 @@ public class TestDemoServiceImpl extends ServicePlusImpl queryPageList(TestDemoBo bo, PageQuery pageQuery) { LambdaQueryWrapper lqw = buildQueryWrapper(bo); @@ -47,7 +45,6 @@ public class TestDemoServiceImpl extends ServicePlusImpl customPageList(TestDemoBo bo, PageQuery pageQuery) { LambdaQueryWrapper lqw = buildQueryWrapper(bo); @@ -55,7 +52,6 @@ public class TestDemoServiceImpl extends ServicePlusImpl queryList(TestDemoBo bo) { return listVo(buildQueryWrapper(bo)); diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/service/impl/TestTreeServiceImpl.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/service/impl/TestTreeServiceImpl.java index 2cb93ad27..3b5774011 100644 --- a/ruoyi-demo/src/main/java/com/ruoyi/demo/service/impl/TestTreeServiceImpl.java +++ b/ruoyi-demo/src/main/java/com/ruoyi/demo/service/impl/TestTreeServiceImpl.java @@ -3,7 +3,6 @@ package com.ruoyi.demo.service.impl; import cn.hutool.core.bean.BeanUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; -import com.ruoyi.common.annotation.DataScope; import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.demo.domain.TestTree; @@ -33,7 +32,6 @@ public class TestTreeServiceImpl extends ServicePlusImpl queryList(TestTreeBo bo) { LambdaQueryWrapper lqw = buildQueryWrapper(bo); diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java index 7392d833e..9af991d29 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java @@ -1,140 +1,140 @@ -package com.ruoyi.framework.aspectj; - -import com.ruoyi.common.annotation.DataScope; -import com.ruoyi.common.core.domain.BaseEntity; -import com.ruoyi.common.core.domain.entity.SysRole; -import com.ruoyi.common.core.domain.entity.SysUser; -import com.ruoyi.common.core.domain.model.LoginUser; -import com.ruoyi.common.core.service.UserService; -import com.ruoyi.common.utils.SecurityUtils; -import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.common.utils.spring.SpringUtils; -import org.aspectj.lang.JoinPoint; -import org.aspectj.lang.annotation.Aspect; -import org.aspectj.lang.annotation.Before; -import org.springframework.stereotype.Component; - -/** - * 数据过滤处理 - * - * @author Lion Li - */ -@Aspect -@Component -public class DataScopeAspect { - - /** - * 全部数据权限 - */ - public static final String DATA_SCOPE_ALL = "1"; - - /** - * 自定数据权限 - */ - public static final String DATA_SCOPE_CUSTOM = "2"; - - /** - * 部门数据权限 - */ - public static final String DATA_SCOPE_DEPT = "3"; - - /** - * 部门及以下数据权限 - */ - public static final String DATA_SCOPE_DEPT_AND_CHILD = "4"; - - /** - * 仅本人数据权限 - */ - public static final String DATA_SCOPE_SELF = "5"; - - /** - * 数据权限过滤关键字 - */ - public static final String DATA_SCOPE = "dataScope"; - - @Before("@annotation(controllerDataScope)") - public void doBefore(JoinPoint point, DataScope controllerDataScope) throws Throwable { - clearDataScope(point); - handleDataScope(point, controllerDataScope); - } - - protected void handleDataScope(final JoinPoint joinPoint, DataScope controllerDataScope) { - // 获取当前的用户 - LoginUser loginUser = SecurityUtils.getLoginUser(); - if (StringUtils.isNotNull(loginUser)) { - SysUser currentUser = SpringUtils.getBean(UserService.class).selectUserById(loginUser.getUserId()); - // 如果是超级管理员,则不过滤数据 - if (StringUtils.isNotNull(currentUser) && !currentUser.isAdmin()) { - dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(), - controllerDataScope.userAlias(), controllerDataScope.isUser()); - } - } - } - - /** - * 数据范围过滤 - * - * @param joinPoint 切点 - * @param user 用户 - * @param userAlias 别名 - */ - public static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String deptAlias, String userAlias, boolean isUser) { - StringBuilder sqlString = new StringBuilder(); - - // 将 "." 提取出,不写别名为单表查询,写别名为多表查询 - deptAlias = StringUtils.isNotBlank(deptAlias) ? deptAlias + "." : ""; - userAlias = StringUtils.isNotBlank(userAlias) ? userAlias + "." : ""; - - for (SysRole role : user.getRoles()) { - String dataScope = role.getDataScope(); - if (DATA_SCOPE_ALL.equals(dataScope)) { - sqlString = new StringBuilder(); - break; - } else if (DATA_SCOPE_CUSTOM.equals(dataScope)) { - sqlString.append(StringUtils.format( - " OR {}dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", - deptAlias, role.getRoleId())); - } else if (DATA_SCOPE_DEPT.equals(dataScope)) { - sqlString.append(StringUtils.format(" OR {}dept_id = {} ", - deptAlias, user.getDeptId())); - } else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope)) { - sqlString.append(StringUtils.format( - " OR {}dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = {} or find_in_set( {} , ancestors ) )", - deptAlias, user.getDeptId(), user.getDeptId())); - } else if (DATA_SCOPE_SELF.equals(dataScope)) { - if (isUser) { - sqlString.append(StringUtils.format(" OR {}user_id = {} ", - userAlias, user.getUserId())); - } else { - // 数据权限为仅本人且没有userAlias别名不查询任何数据 - sqlString.append(" OR 1=0 "); - } - } - } - - if (StringUtils.isNotBlank(sqlString.toString())) { - putDataScope(joinPoint, sqlString.substring(4)); - } - } - - /** - * 拼接权限sql前先清空params.dataScope参数防止注入 - */ - private void clearDataScope(final JoinPoint joinPoint) { - Object params = joinPoint.getArgs()[0]; - if (StringUtils.isNotNull(params)) { - putDataScope(joinPoint, ""); - } - } - - private static void putDataScope(JoinPoint joinPoint, String sql) { - Object params = joinPoint.getArgs()[0]; - if (StringUtils.isNotNull(params)) { - if (params instanceof BaseEntity) { - BaseEntity baseEntity = (BaseEntity) params; - baseEntity.getParams().put(DATA_SCOPE, sql); - } - } - } -} +//package com.ruoyi.framework.aspectj; +// +//import com.ruoyi.common.annotation.DataScope; +//import com.ruoyi.common.core.domain.BaseEntity; +//import com.ruoyi.common.core.domain.entity.SysRole; +//import com.ruoyi.common.core.domain.entity.SysUser; +//import com.ruoyi.common.core.domain.model.LoginUser; +//import com.ruoyi.common.core.service.UserService; +//import com.ruoyi.common.utils.SecurityUtils; +//import com.ruoyi.common.utils.StringUtils; +//import com.ruoyi.common.utils.spring.SpringUtils; +//import org.aspectj.lang.JoinPoint; +//import org.aspectj.lang.annotation.Aspect; +//import org.aspectj.lang.annotation.Before; +//import org.springframework.stereotype.Component; +// +///** +// * 数据过滤处理 +// * +// * @author Lion Li +// */ +//@Aspect +//@Component +//public class DataScopeAspect { +// +// /** +// * 全部数据权限 +// */ +// public static final String DATA_SCOPE_ALL = "1"; +// +// /** +// * 自定数据权限 +// */ +// public static final String DATA_SCOPE_CUSTOM = "2"; +// +// /** +// * 部门数据权限 +// */ +// public static final String DATA_SCOPE_DEPT = "3"; +// +// /** +// * 部门及以下数据权限 +// */ +// public static final String DATA_SCOPE_DEPT_AND_CHILD = "4"; +// +// /** +// * 仅本人数据权限 +// */ +// public static final String DATA_SCOPE_SELF = "5"; +// +// /** +// * 数据权限过滤关键字 +// */ +// public static final String DATA_SCOPE = "dataScope"; +// +// @Before("@annotation(controllerDataScope)") +// public void doBefore(JoinPoint point, DataScope controllerDataScope) throws Throwable { +// clearDataScope(point); +// handleDataScope(point, controllerDataScope); +// } +// +// protected void handleDataScope(final JoinPoint joinPoint, DataScope controllerDataScope) { +// // 获取当前的用户 +// LoginUser loginUser = SecurityUtils.getLoginUser(); +// if (StringUtils.isNotNull(loginUser)) { +// SysUser currentUser = SpringUtils.getBean(UserService.class).selectUserById(loginUser.getUserId()); +// // 如果是超级管理员,则不过滤数据 +// if (StringUtils.isNotNull(currentUser) && !currentUser.isAdmin()) { +// dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(), +// controllerDataScope.userAlias(), controllerDataScope.isUser()); +// } +// } +// } +// +// /** +// * 数据范围过滤 +// * +// * @param joinPoint 切点 +// * @param user 用户 +// * @param userAlias 别名 +// */ +// public static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String deptAlias, String userAlias, boolean isUser) { +// StringBuilder sqlString = new StringBuilder(); +// +// // 将 "." 提取出,不写别名为单表查询,写别名为多表查询 +// deptAlias = StringUtils.isNotBlank(deptAlias) ? deptAlias + "." : ""; +// userAlias = StringUtils.isNotBlank(userAlias) ? userAlias + "." : ""; +// +// for (SysRole role : user.getRoles()) { +// String dataScope = role.getDataScope(); +// if (DATA_SCOPE_ALL.equals(dataScope)) { +// sqlString = new StringBuilder(); +// break; +// } else if (DATA_SCOPE_CUSTOM.equals(dataScope)) { +// sqlString.append(StringUtils.format( +// " OR {}dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", +// deptAlias, role.getRoleId())); +// } else if (DATA_SCOPE_DEPT.equals(dataScope)) { +// sqlString.append(StringUtils.format(" OR {}dept_id = {} ", +// deptAlias, user.getDeptId())); +// } else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope)) { +// sqlString.append(StringUtils.format( +// " OR {}dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = {} or find_in_set( {} , ancestors ) )", +// deptAlias, user.getDeptId(), user.getDeptId())); +// } else if (DATA_SCOPE_SELF.equals(dataScope)) { +// if (isUser) { +// sqlString.append(StringUtils.format(" OR {}user_id = {} ", +// userAlias, user.getUserId())); +// } else { +// // 数据权限为仅本人且没有userAlias别名不查询任何数据 +// sqlString.append(" OR 1=0 "); +// } +// } +// } +// +// if (StringUtils.isNotBlank(sqlString.toString())) { +// putDataScope(joinPoint, sqlString.substring(4)); +// } +// } +// +// /** +// * 拼接权限sql前先清空params.dataScope参数防止注入 +// */ +// private void clearDataScope(final JoinPoint joinPoint) { +// Object params = joinPoint.getArgs()[0]; +// if (StringUtils.isNotNull(params)) { +// putDataScope(joinPoint, ""); +// } +// } +// +// private static void putDataScope(JoinPoint joinPoint, String sql) { +// Object params = joinPoint.getArgs()[0]; +// if (StringUtils.isNotNull(params)) { +// if (params instanceof BaseEntity) { +// BaseEntity baseEntity = (BaseEntity) params; +// baseEntity.getParams().put(DATA_SCOPE, sql); +// } +// } +// } +//} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/MybatisPlusConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/MybatisPlusConfig.java index db81b7437..539cc1d61 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/MybatisPlusConfig.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/MybatisPlusConfig.java @@ -6,10 +6,12 @@ import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector; import com.baomidou.mybatisplus.core.injector.ISqlInjector; import com.baomidou.mybatisplus.core.metadata.TableInfo; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.DataPermissionInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; import com.ruoyi.common.core.mybatisplus.methods.InsertAll; import com.ruoyi.framework.handler.CreateAndUpdateMetaObjectHandler; +import com.ruoyi.framework.handler.PlusDataPermissionHandler; import org.mybatis.spring.annotation.MapperScan; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -30,6 +32,8 @@ public class MybatisPlusConfig { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); + // 数据权限处理 + interceptor.addInnerInterceptor(dataPermissionInterceptor()); // 分页插件 interceptor.addInnerInterceptor(paginationInnerInterceptor()); // 乐观锁插件 @@ -37,6 +41,15 @@ public class MybatisPlusConfig { return interceptor; } + /** + * 分页插件,自动识别数据库类型 + */ + public DataPermissionInterceptor dataPermissionInterceptor() { + DataPermissionInterceptor dataPermissionInterceptor = new DataPermissionInterceptor(); + dataPermissionInterceptor.setDataPermissionHandler(new PlusDataPermissionHandler()); + return dataPermissionInterceptor; + } + /** * 分页插件,自动识别数据库类型 */ diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/handler/PlusDataPermissionHandler.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/handler/PlusDataPermissionHandler.java new file mode 100644 index 000000000..7bb1e3a40 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/handler/PlusDataPermissionHandler.java @@ -0,0 +1,117 @@ +package com.ruoyi.framework.handler; + +import cn.hutool.core.annotation.AnnotationUtil; +import cn.hutool.core.util.ClassUtil; +import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.extension.plugins.handler.DataPermissionHandler; +import com.ruoyi.common.annotation.DataScope; +import com.ruoyi.common.core.domain.entity.SysRole; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.core.service.UserService; +import com.ruoyi.common.enums.DataScopeType; +import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.common.utils.SecurityUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.spring.SpringUtils; +import lombok.extern.slf4j.Slf4j; +import net.sf.jsqlparser.JSQLParserException; +import net.sf.jsqlparser.expression.Expression; +import net.sf.jsqlparser.expression.operators.conditional.AndExpression; +import net.sf.jsqlparser.parser.CCJSqlParserUtil; +import org.springframework.expression.EvaluationContext; +import org.springframework.expression.ExpressionParser; +import org.springframework.expression.common.TemplateParserContext; +import org.springframework.expression.spel.standard.SpelExpressionParser; +import org.springframework.expression.spel.support.StandardEvaluationContext; + +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 数据权限过滤 + * + * @author Lion Li + */ +@Slf4j +public class PlusDataPermissionHandler implements DataPermissionHandler { + + @Override + public Expression getSqlSegment(Expression where, String mappedStatementId) { + DataScope dataScope = findDataScopeAnnotation(mappedStatementId); + if (ObjectUtil.isNull(dataScope)) { + return where; + } + SysUser currentUser = SpringUtils.getBean(UserService.class).selectUserById(SecurityUtils.getUserId()); + // 如果是超级管理员,则不过滤数据 + if (StringUtils.isNotNull(currentUser) && !currentUser.isAdmin()) { + String dataScopeSql = dataScopeFilter(currentUser, dataScope); + if (StringUtils.isNotBlank(dataScopeSql)) { + try { + Expression expression = CCJSqlParserUtil.parseExpression(dataScopeSql); + return new AndExpression(where, expression); + } catch (JSQLParserException e) { + throw new ServiceException("数据权限解析异常 => " + e.getMessage()); + } + } + } + return where; + } + + private DataScope findDataScopeAnnotation(String mappedStatementId) { + StringBuilder sb = new StringBuilder(mappedStatementId); + int index = sb.lastIndexOf("."); + String clazzName = sb.substring(0, index); + String methodName = sb.substring(index + 1, sb.length()); + Class clazz = ClassUtil.loadClass(clazzName); + List methods = Arrays.stream(ClassUtil.getDeclaredMethods(clazz)) + .filter(method -> method.getName().equals(methodName)).collect(Collectors.toList()); + DataScope dataScope = null; + for (Method method : methods) { + if (AnnotationUtil.hasAnnotation(method, DataScope.class)) { + dataScope = AnnotationUtil.getAnnotation(method, DataScope.class); + break; + } + } + return dataScope; + } + + /** + * 数据范围过滤 + * + * @param user 用户 + */ + public static String dataScopeFilter(SysUser user, DataScope annotation) { + StringBuilder sqlString = new StringBuilder(); + + ExpressionParser parser = new SpelExpressionParser(); + TemplateParserContext parserContext = new TemplateParserContext(); + EvaluationContext context = new StandardEvaluationContext(new HashMap<>()); + context.setVariable("deptName", annotation.deptName()); + context.setVariable("userName", annotation.userName()); + context.setVariable("userId", user.getUserId()); + context.setVariable("deptId", user.getDeptId()); + + + for (SysRole role : user.getRoles()) { + context.setVariable("roleId", role.getRoleId()); + DataScopeType type = DataScopeType.findCode(role.getDataScope()); + if (ObjectUtil.isNull(type)) { + throw new ServiceException("角色数据范围异常 => " + role.getDataScope()); + } + if (type == DataScopeType.DATA_SCOPE_ALL) { + break; + } + org.springframework.expression.Expression expression = parser.parseExpression(type.getSql(), parserContext); + String sql = expression.getValue(context, String.class); + sqlString.append(sql); + } + + if (StringUtils.isNotBlank(sqlString.toString())) { + return sqlString.substring(4); + } + return ""; + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java index d0ae46dcd..95a4a3e14 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java @@ -1,5 +1,8 @@ package com.ruoyi.system.mapper; +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Constants; +import com.ruoyi.common.annotation.DataScope; import com.ruoyi.common.core.domain.entity.SysDept; import com.ruoyi.common.core.mybatisplus.core.BaseMapperPlus; import org.apache.ibatis.annotations.Param; @@ -19,8 +22,13 @@ public interface SysDeptMapper extends BaseMapperPlus { * @param dept 部门信息 * @return 部门信息集合 */ + @DataScope(deptName = "d.dept_id") List selectDeptList(SysDept dept); + @Override + @DataScope(deptName = "dept_id") + List selectList(@Param(Constants.WRAPPER) Wrapper queryWrapper); + /** * 根据角色ID查询部门树信息 * diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMapper.java index eb440065f..cbd216ac0 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMapper.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMapper.java @@ -1,6 +1,7 @@ package com.ruoyi.system.mapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ruoyi.common.annotation.DataScope; import com.ruoyi.common.core.domain.entity.SysRole; import com.ruoyi.common.core.mybatisplus.core.BaseMapperPlus; import org.apache.ibatis.annotations.Param; @@ -14,6 +15,7 @@ import java.util.List; */ public interface SysRoleMapper extends BaseMapperPlus { + @DataScope(deptName = "d.dept_id") Page selectPageRoleList(@Param("page") Page page, @Param("role") SysRole role); /** @@ -22,6 +24,7 @@ public interface SysRoleMapper extends BaseMapperPlus { * @param role 角色信息 * @return 角色数据集合信息 */ + @DataScope(deptName = "d.dept_id") List selectRoleList(SysRole role); /** diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java index e930d879a..b3780df71 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java @@ -1,6 +1,7 @@ package com.ruoyi.system.mapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ruoyi.common.annotation.DataScope; import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.core.mybatisplus.core.BaseMapperPlus; import org.apache.ibatis.annotations.Param; @@ -14,6 +15,7 @@ import java.util.List; */ public interface SysUserMapper extends BaseMapperPlus { + @DataScope(deptName = "d.dept_id", userName = "u.user_id") Page selectPageUserList(@Param("page") Page page, @Param("user") SysUser user); /** @@ -22,6 +24,7 @@ public interface SysUserMapper extends BaseMapperPlus { * @param sysUser 用户信息 * @return 用户信息集合信息 */ + @DataScope(deptName = "d.dept_id", userName = "u.user_id") List selectUserList(SysUser sysUser); /** @@ -30,6 +33,7 @@ public interface SysUserMapper extends BaseMapperPlus { * @param user 用户信息 * @return 用户信息集合信息 */ + @DataScope(deptName = "d.dept_id", userName = "u.user_id") Page selectAllocatedList(@Param("page") Page page, @Param("user") SysUser user); /** @@ -38,6 +42,7 @@ public interface SysUserMapper extends BaseMapperPlus { * @param user 用户信息 * @return 用户信息集合信息 */ + @DataScope(deptName = "d.dept_id", userName = "u.user_id") Page selectUnallocatedList(@Param("page") Page page, @Param("user") SysUser user); /** diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java index c73092625..0f8897fe4 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java @@ -1,10 +1,10 @@ package com.ruoyi.system.service.impl; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.convert.Convert; import cn.hutool.core.lang.tree.Tree; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; -import com.ruoyi.common.annotation.DataScope; import com.ruoyi.common.constant.UserConstants; import com.ruoyi.common.core.domain.entity.SysDept; import com.ruoyi.common.core.domain.entity.SysRole; @@ -46,8 +46,9 @@ public class SysDeptServiceImpl extends ServicePlusImpl selectDeptList(SysDept dept) { +// return baseMapper.selectList(); +// return baseMapper.selectList(new LambdaQueryWrapper<>()); return baseMapper.selectDeptList(dept); } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java index 8ebed8183..6c2cc8e95 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java @@ -1,5 +1,6 @@ package com.ruoyi.system.service.impl; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.tree.Tree; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.ruoyi.common.constant.Constants; diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java index de47ff0ba..cea08c8e2 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java @@ -2,7 +2,6 @@ package com.ruoyi.system.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.ruoyi.common.annotation.DataScope; import com.ruoyi.common.constant.UserConstants; import com.ruoyi.common.core.domain.PageQuery; import com.ruoyi.common.core.domain.entity.SysRole; @@ -46,7 +45,6 @@ public class SysRoleServiceImpl extends ServicePlusImpl selectPageRoleList(SysRole role, PageQuery pageQuery) { Page page = baseMapper.selectPageRoleList(PageUtils.buildPage(pageQuery), role); return PageUtils.buildDataInfo(page); @@ -59,7 +57,6 @@ public class SysRoleServiceImpl extends ServicePlusImpl selectRoleList(SysRole role) { return baseMapper.selectRoleList(role); } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java index be9999424..3af2fa818 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java @@ -4,7 +4,6 @@ import cn.hutool.core.collection.CollUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.ruoyi.common.annotation.DataScope; import com.ruoyi.common.constant.UserConstants; import com.ruoyi.common.core.domain.PageQuery; import com.ruoyi.common.core.domain.entity.SysRole; @@ -54,7 +53,6 @@ public class SysUserServiceImpl extends ServicePlusImpl selectPageUserList(SysUser user, PageQuery pageQuery) { Page page = baseMapper.selectPageUserList(PageUtils.buildPage(pageQuery), user); return PageUtils.buildDataInfo(page); @@ -67,7 +65,6 @@ public class SysUserServiceImpl extends ServicePlusImpl selectUserList(SysUser user) { return baseMapper.selectUserList(user); } @@ -79,7 +76,6 @@ public class SysUserServiceImpl extends ServicePlusImpl selectAllocatedList(SysUser user, PageQuery pageQuery) { Page page = baseMapper.selectAllocatedList(PageUtils.buildPage(pageQuery), user); return PageUtils.buildDataInfo(page); @@ -92,7 +88,6 @@ public class SysUserServiceImpl extends ServicePlusImpl selectUnallocatedList(SysUser user, PageQuery pageQuery) { Page page = baseMapper.selectUnallocatedList(PageUtils.buildPage(pageQuery), user); return PageUtils.buildDataInfo(page); diff --git a/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml index 346332c76..2c1fc7590 100644 --- a/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml +++ b/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml @@ -42,10 +42,10 @@ AND status = #{status} - - - AND ( ${params.dataScope} ) - + + + + order by d.parent_id, d.order_num diff --git a/ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml index 94b161b3b..c13bd68bb 100644 --- a/ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml +++ b/ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml @@ -60,10 +60,10 @@ and date_format(r.create_time,'%y%m%d') <= date_format(#{role.params.endTime},'%y%m%d') - - - AND ( ${role.params.dataScope} ) - + + + + order by r.role_sort @@ -88,10 +88,10 @@ and date_format(r.create_time,'%y%m%d') <= date_format(#{params.endTime},'%y%m%d') - - - AND ( ${params.dataScope} ) - + + + + order by r.role_sort diff --git a/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml index 5d9a18568..d9a927fb2 100644 --- a/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml +++ b/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml @@ -108,10 +108,10 @@ AND (u.dept_id = #{user.deptId} OR u.dept_id IN ( SELECT t.dept_id FROM sys_dept t WHERE find_in_set(#{user.deptId}, ancestors) )) - - - AND ( ${user.params.dataScope} ) - + + + +