From eaac3a6c6227363ebb5996d1ac90f445cf782b31 Mon Sep 17 00:00:00 2001 From: colin Date: Fri, 12 Jul 2024 15:24:48 +0800 Subject: [PATCH] =?UTF-8?q?=E6=89=A9=E5=B1=95=20=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E6=9D=83=E9=99=90=EF=BC=8C=E8=AF=A6=E7=BB=86=E8=AF=B4=E6=98=8E?= =?UTF-8?q?=E5=9C=A8org.dromara.test.mapper.CustomSqlTest?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dromara/test/mapper/CustomSqlTest.java | 41 +++++++++++++++++++ .../common/mybatis/annotation/DataColumn.java | 1 + .../common/mybatis/enums/DataScopeType.java | 8 +++- .../handler/PlusDataPermissionHandler.java | 20 ++++++--- 4 files changed, 63 insertions(+), 7 deletions(-) create mode 100644 ruoyi-admin/src/test/java/org/dromara/test/mapper/CustomSqlTest.java diff --git a/ruoyi-admin/src/test/java/org/dromara/test/mapper/CustomSqlTest.java b/ruoyi-admin/src/test/java/org/dromara/test/mapper/CustomSqlTest.java new file mode 100644 index 000000000..5c6a0a3a8 --- /dev/null +++ b/ruoyi-admin/src/test/java/org/dromara/test/mapper/CustomSqlTest.java @@ -0,0 +1,41 @@ +package org.dromara.test.mapper; + +public class CustomSqlTest { + /** + * mapper 接口 + * @Mapper + * public interface ILoanMapper extends BaseMapper { + * @DataPermission({ + * @DataColumn(key = DataColumn.CUSTOM_SQL, value = "(#{#trackerId} = #{#user.userId} or #{#salespersonId} = #{#user.userId})"), + * @DataColumn(key = {"trackerId", "salespersonId"}, value = {"l.tracker_id", "l.salesperson_id"}), + * }) + * Page selectPageLoanList(@Param("page") Page page, @Param(Constants.WRAPPER) Wrapper queryWrapper); + * } + * + * mapper 文件 + * + * + * 实体 + * public class Loan extends TenantEntity { + * private Long id; + * //业务员 + * private Long salespersonId; + * //跟单员 + * private Long trackerId; + * ..... + * } + * + * //结果: 业务员 与 跟单员都只能看自己的数据,但每条数据 既有跟单员也有业务员 + * select * from zr_loan where (l.tracker_id = 1 or l.salesperson_id = 1) + */ +} diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/annotation/DataColumn.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/annotation/DataColumn.java index f8c5cd009..8ff00210f 100644 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/annotation/DataColumn.java +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/annotation/DataColumn.java @@ -15,6 +15,7 @@ import java.lang.annotation.*; @Retention(RetentionPolicy.RUNTIME) @Documented public @interface DataColumn { + String CUSTOM_SQL = "CustomSql"; /** * 数据权限模板的占位符关键字,默认为 "deptName" diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/enums/DataScopeType.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/enums/DataScopeType.java index 455cecb2e..d50ad352f 100644 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/enums/DataScopeType.java +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/enums/DataScopeType.java @@ -4,6 +4,7 @@ import lombok.AllArgsConstructor; import lombok.Getter; import org.dromara.common.core.domain.model.LoginUser; import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.mybatis.annotation.DataColumn; import org.dromara.common.mybatis.helper.DataPermissionHelper; /** @@ -56,7 +57,12 @@ public enum DataScopeType { * 使用 SpEL 表达式:`#{#userName} = #{#user.userId}` * 如果不满足条件,则使用默认 SQL 表达式:`1 = 0` */ - SELF("5", " #{#userName} = #{#user.userId} ", " 1 = 0 "); + SELF("5", " #{#userName} = #{#user.userId} ", " 1 = 0 "), + + /** + * 弹性数据权限(通过自定义SQL实现) + */ + CUSTOM_SQL("6", " {" + DataColumn.CUSTOM_SQL + "} ", " 1 = 0 "); private final String code; diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/PlusDataPermissionHandler.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/PlusDataPermissionHandler.java index 74279bde0..17a9a1302 100644 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/PlusDataPermissionHandler.java +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/PlusDataPermissionHandler.java @@ -3,6 +3,7 @@ package org.dromara.common.mybatis.handler; import cn.hutool.core.annotation.AnnotationUtil; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; import lombok.extern.slf4j.Slf4j; import net.sf.jsqlparser.JSQLParserException; import net.sf.jsqlparser.expression.Expression; @@ -37,10 +38,7 @@ import org.springframework.expression.spel.support.StandardEvaluationContext; import org.springframework.util.ClassUtils; import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Function; @@ -144,13 +142,23 @@ public class PlusDataPermissionHandler { if (type == DataScopeType.ALL) { return ""; } + + String sqlTemplate = type.getSqlTemplate(); + if (type == DataScopeType.CUSTOM_SQL) { + //自定义SQL逻辑 + DataColumn customColum = Arrays.stream(dataColumns).filter(c -> Arrays.asList(c.key()).contains(DataColumn.CUSTOM_SQL)).findFirst().orElseThrow(() -> new ServiceException("角色数据范围异常key配置异常 => " + role.getDataScope())); + Map map = new HashMap<>(); + map.put(DataColumn.CUSTOM_SQL, customColum.value()[0]); + sqlTemplate = StrUtil.format(sqlTemplate, map); + } + boolean isSuccess = false; for (DataColumn dataColumn : dataColumns) { if (dataColumn.key().length != dataColumn.value().length) { throw new ServiceException("角色数据范围异常 => key与value长度不匹配"); } // 不包含 key 变量 则不处理 - if (!StringUtils.containsAny(type.getSqlTemplate(), + if (!StringUtils.containsAny(sqlTemplate, Arrays.stream(dataColumn.key()).map(key -> "#" + key).toArray(String[]::new) )) { continue; @@ -161,7 +169,7 @@ public class PlusDataPermissionHandler { } // 解析sql模板并填充 - String sql = parser.parseExpression(type.getSqlTemplate(), parserContext).getValue(context, String.class); + String sql = parser.parseExpression(sqlTemplate, parserContext).getValue(context, String.class); conditions.add(joinStr + sql); isSuccess = true; }