扩展 数据权限,详细说明在org.dromara.test.mapper.CustomSqlTest

This commit is contained in:
colin 2024-07-12 15:24:48 +08:00
parent 367d739e2d
commit eaac3a6c62
4 changed files with 63 additions and 7 deletions

View File

@ -0,0 +1,41 @@
package org.dromara.test.mapper;
public class CustomSqlTest {
/**
* mapper 接口
* @Mapper
* public interface ILoanMapper extends BaseMapper<Loan> {
* @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<Loan> selectPageLoanList(@Param("page") Page<Loan> page, @Param(Constants.WRAPPER) Wrapper<Loan> queryWrapper);
* }
*
* mapper 文件
* <select id="selectPageLoanList" resultType="com.smart330.zr.loan.domain.entity.Loan">
* select
* <if test="ew.getSqlSelect != null">
* ${ew.getSqlSelect}
* </if>
* <if test="ew.getSqlSelect == null">
* *
* </if>
* from zr_loan l
* ${ew.getCustomSqlSegment}
* </select>
*
* 实体
* 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)
*/
}

View File

@ -15,6 +15,7 @@ import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Documented @Documented
public @interface DataColumn { public @interface DataColumn {
String CUSTOM_SQL = "CustomSql";
/** /**
* 数据权限模板的占位符关键字默认为 "deptName" * 数据权限模板的占位符关键字默认为 "deptName"

View File

@ -4,6 +4,7 @@ import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import org.dromara.common.core.domain.model.LoginUser; import org.dromara.common.core.domain.model.LoginUser;
import org.dromara.common.core.utils.StringUtils; import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.annotation.DataColumn;
import org.dromara.common.mybatis.helper.DataPermissionHelper; import org.dromara.common.mybatis.helper.DataPermissionHelper;
/** /**
@ -56,7 +57,12 @@ public enum DataScopeType {
* 使用 SpEL 表达式`#{#userName} = #{#user.userId}` * 使用 SpEL 表达式`#{#userName} = #{#user.userId}`
* 如果不满足条件则使用默认 SQL 表达式`1 = 0` * 如果不满足条件则使用默认 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; private final String code;

View File

@ -3,6 +3,7 @@ package org.dromara.common.mybatis.handler;
import cn.hutool.core.annotation.AnnotationUtil; 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 cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.JSQLParserException; import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.Expression;
@ -37,10 +38,7 @@ import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.util.ClassUtils; import org.springframework.util.ClassUtils;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.Arrays; import java.util.*;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function; import java.util.function.Function;
@ -144,13 +142,23 @@ public class PlusDataPermissionHandler {
if (type == DataScopeType.ALL) { if (type == DataScopeType.ALL) {
return ""; 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<String, String> map = new HashMap<>();
map.put(DataColumn.CUSTOM_SQL, customColum.value()[0]);
sqlTemplate = StrUtil.format(sqlTemplate, map);
}
boolean isSuccess = false; boolean isSuccess = false;
for (DataColumn dataColumn : dataColumns) { for (DataColumn dataColumn : dataColumns) {
if (dataColumn.key().length != dataColumn.value().length) { if (dataColumn.key().length != dataColumn.value().length) {
throw new ServiceException("角色数据范围异常 => key与value长度不匹配"); throw new ServiceException("角色数据范围异常 => key与value长度不匹配");
} }
// 不包含 key 变量 则不处理 // 不包含 key 变量 则不处理
if (!StringUtils.containsAny(type.getSqlTemplate(), if (!StringUtils.containsAny(sqlTemplate,
Arrays.stream(dataColumn.key()).map(key -> "#" + key).toArray(String[]::new) Arrays.stream(dataColumn.key()).map(key -> "#" + key).toArray(String[]::new)
)) { )) {
continue; continue;
@ -161,7 +169,7 @@ public class PlusDataPermissionHandler {
} }
// 解析sql模板并填充 // 解析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); conditions.add(joinStr + sql);
isSuccess = true; isSuccess = true;
} }