From 1e2393c1c5e3ee1e1a55c22f90f973a7f293c8ff Mon Sep 17 00:00:00 2001 From: TanJ Date: Mon, 3 Jun 2024 16:41:27 +0800 Subject: [PATCH 01/27] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E6=9D=83=E9=99=90SDK?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- axzo-common-data-permission/pom.xml | 33 ++ .../annotation/DataPermission.java | 17 + .../aop/DataPermissionFilter.java | 16 + .../aop/DataPermissionMybatisInterceptor.java | 325 ++++++++++++++++++ .../config/DataPermissionConfig.java | 42 +++ .../context/DataPermissionContextFactory.java | 30 ++ .../context/DataPermissionContextHolder.java | 40 +++ .../rule/DataPermissionDefaultRule.java | 168 +++++++++ .../rule/DataPermissionRule.java | 20 ++ .../main/resources/META-INF/spring.factories | 2 + pom.xml | 1 + 11 files changed, 694 insertions(+) create mode 100644 axzo-common-data-permission/pom.xml create mode 100644 axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/annotation/DataPermission.java create mode 100644 axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionFilter.java create mode 100644 axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionMybatisInterceptor.java create mode 100644 axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/config/DataPermissionConfig.java create mode 100644 axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextFactory.java create mode 100644 axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextHolder.java create mode 100644 axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/rule/DataPermissionDefaultRule.java create mode 100644 axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/rule/DataPermissionRule.java create mode 100644 axzo-common-data-permission/src/main/resources/META-INF/spring.factories diff --git a/axzo-common-data-permission/pom.xml b/axzo-common-data-permission/pom.xml new file mode 100644 index 0000000..34ef42b --- /dev/null +++ b/axzo-common-data-permission/pom.xml @@ -0,0 +1,33 @@ + + + 4.0.0 + + cn.axzo.framework + axzo-framework-commons + 1.0.0-SNAPSHOT + + + axzo-common-data-permission + + + 8 + 8 + UTF-8 + + + + + com.baomidou + mybatis-plus-boot-starter + provided + + + cn.axzo.karma + karma-api + 2.0.0-SNAPSHOT + + + + \ No newline at end of file diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/annotation/DataPermission.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/annotation/DataPermission.java new file mode 100644 index 0000000..75b322e --- /dev/null +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/annotation/DataPermission.java @@ -0,0 +1,17 @@ +package cn.axzo.framework.datapermission.annotation; + +import cn.axzo.framework.datapermission.rule.DataPermissionRule; + +/** + * 数据权限注解 + * @author tanjie@axzo.cn + * @date 2024/5/30 17:57 + */ +public @interface DataPermission { + boolean enable() default false; + + Class[] includeRule() default {}; + + String bizCode() default ""; + +} diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionFilter.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionFilter.java new file mode 100644 index 0000000..ee41cad --- /dev/null +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionFilter.java @@ -0,0 +1,16 @@ +package cn.axzo.framework.datapermission.aop; + +import cn.axzo.framework.datapermission.annotation.DataPermission; +import cn.axzo.framework.datapermission.config.DataPermissionConfig; + +/** + * + * @author tanjie@axzo.cn + * @date 2024/5/31 16:37 + */ +public class DataPermissionFilter { + + // 拦截@DataPermission + // 设置DataPermissionContext + +} diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionMybatisInterceptor.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionMybatisInterceptor.java new file mode 100644 index 0000000..f579435 --- /dev/null +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionMybatisInterceptor.java @@ -0,0 +1,325 @@ +package cn.axzo.framework.datapermission.aop; + +import cn.axzo.framework.datapermission.annotation.DataPermission; +import cn.axzo.framework.datapermission.context.DataPermissionContextFactory; +import cn.axzo.framework.datapermission.context.DataPermissionContextHolder; +import cn.axzo.framework.datapermission.rule.DataPermissionRule; +import com.baomidou.mybatisplus.core.parser.SqlParserHelper; +import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; +import com.baomidou.mybatisplus.core.toolkit.PluginUtils; +import com.baomidou.mybatisplus.extension.parser.JsqlParserSupport; +import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor; +import lombok.RequiredArgsConstructor; +import net.sf.jsqlparser.expression.BinaryExpression; +import net.sf.jsqlparser.expression.Expression; +import net.sf.jsqlparser.expression.NotExpression; +import net.sf.jsqlparser.expression.Parenthesis; +import net.sf.jsqlparser.expression.operators.conditional.AndExpression; +import net.sf.jsqlparser.expression.operators.conditional.OrExpression; +import net.sf.jsqlparser.expression.operators.relational.ExistsExpression; +import net.sf.jsqlparser.expression.operators.relational.InExpression; +import net.sf.jsqlparser.expression.operators.relational.ItemsList; +import net.sf.jsqlparser.schema.Table; +import net.sf.jsqlparser.statement.delete.Delete; +import net.sf.jsqlparser.statement.select.FromItem; +import net.sf.jsqlparser.statement.select.Join; +import net.sf.jsqlparser.statement.select.LateralSubSelect; +import net.sf.jsqlparser.statement.select.PlainSelect; +import net.sf.jsqlparser.statement.select.Select; +import net.sf.jsqlparser.statement.select.SelectBody; +import net.sf.jsqlparser.statement.select.SetOperationList; +import net.sf.jsqlparser.statement.select.SubJoin; +import net.sf.jsqlparser.statement.select.SubSelect; +import net.sf.jsqlparser.statement.select.ValuesList; +import net.sf.jsqlparser.statement.select.WithItem; +import net.sf.jsqlparser.statement.update.Update; +import org.apache.ibatis.executor.Executor; +import org.apache.ibatis.executor.statement.StatementHandler; +import org.apache.ibatis.mapping.BoundSql; +import org.apache.ibatis.mapping.MappedStatement; +import org.apache.ibatis.mapping.SqlCommandType; +import org.apache.ibatis.session.ResultHandler; +import org.apache.ibatis.session.RowBounds; + +import java.sql.Connection; +import java.sql.SQLException; +import java.util.List; +import java.util.Optional; + +/** + * 参考 #{@link com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor} + * @author tanjie@axzo.cn + * @date 2024/5/31 11:41 + */ +@RequiredArgsConstructor +public class DataPermissionMybatisInterceptor extends JsqlParserSupport implements InnerInterceptor { + + private final DataPermissionContextFactory dataPermissionContextFactory; + @Override + public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException { + if (!filter()) { + return; + } + PluginUtils.MPBoundSql mpBs = PluginUtils.mpBoundSql(boundSql); + mpBs.sql(parserSingle(mpBs.sql(), null)); + } + + @Override + public void beforePrepare(StatementHandler sh, Connection connection, Integer transactionTimeout) { + PluginUtils.MPStatementHandler mpSh = PluginUtils.mpStatementHandler(sh); + MappedStatement ms = mpSh.mappedStatement(); + SqlCommandType sct = ms.getSqlCommandType(); + // 不管insert + if (sct == SqlCommandType.UPDATE || sct == SqlCommandType.DELETE) { + if (!filter()) return; + if (SqlParserHelper.getSqlParserInfo(ms)) return; + PluginUtils.MPBoundSql mpBs = mpSh.mPBoundSql(); + mpBs.sql(parserMulti(mpBs.sql(), null)); + } + } + + @Override + protected void processSelect(Select select, int index, String sql, Object obj) { + processSelectBody(select.getSelectBody()); + List withItemsList = select.getWithItemsList(); + if (!CollectionUtils.isEmpty(withItemsList)) { + withItemsList.forEach(this::processSelectBody); + } + } + + protected void processSelectBody(SelectBody selectBody) { + if (selectBody == null) { + return; + } + if (selectBody instanceof PlainSelect) { + processPlainSelect((PlainSelect) selectBody); + } else if (selectBody instanceof WithItem) { + WithItem withItem = (WithItem) selectBody; + processSelectBody(withItem.getSelectBody()); + } else { + SetOperationList operationList = (SetOperationList) selectBody; + if (operationList.getSelects() != null && operationList.getSelects().size() > 0) { + operationList.getSelects().forEach(this::processSelectBody); + } + } + } + + + /** + * update 语句处理 + */ + @Override + protected void processUpdate(Update update, int index, String sql, Object obj) { + final Table table = update.getTable(); + if (!filter()) { + // 过滤退出执行 + return; + } + update.setWhere(this.andExpression(table, update.getWhere())); + } + + /** + * delete 语句处理 + */ + @Override + protected void processDelete(Delete delete, int index, String sql, Object obj) { + if (!filter()) { + // 过滤退出执行 + return; + } + delete.setWhere(this.andExpression(delete.getTable(), delete.getWhere())); + } + + /** + * delete update 语句 where 处理 + */ + protected Expression andExpression(Table table, Expression where) { + + + DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.get(); + DataPermission dataPermission = dataPermissionContext.getDataPermission(); + List byDataPermission = dataPermissionContextFactory.getRuleByDataPermission(dataPermission); + Optional first = byDataPermission.stream().filter(rule -> rule.getTableName().contains(table.getName())).findFirst(); + if (!first.isPresent()) { + return where; + } + DataPermissionRule dataPermissionRule = first.get(); + Expression ruleExpression = dataPermissionRule.getExpression(table.getName(), table.getAlias()); + + if (null != where) { + if (where instanceof OrExpression) { + return new AndExpression(ruleExpression, new Parenthesis(where)); + } else { + return new AndExpression(ruleExpression, where); + } + } + return ruleExpression; + } + + + + + + /** + * 处理 PlainSelect + */ + protected void processPlainSelect(PlainSelect plainSelect) { + FromItem fromItem = plainSelect.getFromItem(); + Expression where = plainSelect.getWhere(); + processWhereSubSelect(where); + if (fromItem instanceof Table) { + Table fromTable = (Table) fromItem; + if (filter()) { + //#1186 github + plainSelect.setWhere(builderExpression(where, fromTable)); + } + } else { + processFromItem(fromItem); + } + List joins = plainSelect.getJoins(); + if (joins != null && joins.size() > 0) { + joins.forEach(j -> { + processJoin(j); + processFromItem(j.getRightItem()); + }); + } + } + + /** + * 处理where条件内的子查询 + *

+ * 支持如下: + * 1. in + * 2. = + * 3. > + * 4. < + * 5. >= + * 6. <= + * 7. <> + * 8. EXISTS + * 9. NOT EXISTS + *

+ * 前提条件: + * 1. 子查询必须放在小括号中 + * 2. 子查询一般放在比较操作符的右边 + * + * @param where where 条件 + */ + protected void processWhereSubSelect(Expression where) { + if (where == null) { + return; + } + if (where instanceof FromItem) { + processFromItem((FromItem) where); + return; + } + if (where.toString().indexOf("SELECT") > 0) { + // 有子查询 + if (where instanceof BinaryExpression) { + // 比较符号 , and , or , 等等 + BinaryExpression expression = (BinaryExpression) where; + processWhereSubSelect(expression.getLeftExpression()); + processWhereSubSelect(expression.getRightExpression()); + } else if (where instanceof InExpression) { + // in + InExpression expression = (InExpression) where; + ItemsList itemsList = expression.getRightItemsList(); + if (itemsList instanceof SubSelect) { + processSelectBody(((SubSelect) itemsList).getSelectBody()); + } + } else if (where instanceof ExistsExpression) { + // exists + ExistsExpression expression = (ExistsExpression) where; + processWhereSubSelect(expression.getRightExpression()); + } else if (where instanceof NotExpression) { + // not exists + NotExpression expression = (NotExpression) where; + processWhereSubSelect(expression.getExpression()); + } else if (where instanceof Parenthesis) { + Parenthesis expression = (Parenthesis) where; + processWhereSubSelect(expression.getExpression()); + } + } + } + + /** + * 处理子查询等 + */ + protected void processFromItem(FromItem fromItem) { + if (fromItem instanceof SubJoin) { + SubJoin subJoin = (SubJoin) fromItem; + if (subJoin.getJoinList() != null) { + subJoin.getJoinList().forEach(this::processJoin); + } + if (subJoin.getLeft() != null) { + processFromItem(subJoin.getLeft()); + } + } else if (fromItem instanceof SubSelect) { + SubSelect subSelect = (SubSelect) fromItem; + if (subSelect.getSelectBody() != null) { + processSelectBody(subSelect.getSelectBody()); + } + } else if (fromItem instanceof ValuesList) { + logger.debug("Perform a subquery, if you do not give us feedback"); + } else if (fromItem instanceof LateralSubSelect) { + LateralSubSelect lateralSubSelect = (LateralSubSelect) fromItem; + if (lateralSubSelect.getSubSelect() != null) { + SubSelect subSelect = lateralSubSelect.getSubSelect(); + if (subSelect.getSelectBody() != null) { + processSelectBody(subSelect.getSelectBody()); + } + } + } + } + + /** + * 处理联接语句 + */ + protected void processJoin(Join join) { + if (join.getRightItem() instanceof Table) { + Table fromTable = (Table) join.getRightItem(); + if (!filter()) { + // 过滤退出执行 + return; + } + join.setOnExpression(builderExpression(join.getOnExpression(), fromTable)); + } + } + + /** + * 处理条件 + */ + protected Expression builderExpression(Expression currentExpression, Table table) { + + DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.get(); + DataPermission dataPermission = dataPermissionContext.getDataPermission(); + List byDataPermission = dataPermissionContextFactory.getRuleByDataPermission(dataPermission); + Optional first = byDataPermission.stream().filter(rule -> rule.getTableName().contains(table.getName())).findFirst(); + if (!first.isPresent()) { + return currentExpression; + } + DataPermissionRule dataPermissionRule = first.get(); + Expression ruleExpression = dataPermissionRule.getExpression(table.getName(), table.getAlias()); + if (currentExpression == null) { + return ruleExpression; + } + if (currentExpression instanceof OrExpression) { + return new AndExpression(new Parenthesis(currentExpression), ruleExpression); + } else { + return new AndExpression(currentExpression, ruleExpression); + } + } + + + + + private boolean filter() { + DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.get(); + if (null == dataPermissionContext|| !dataPermissionContext.getDataPermission().enable()) { + return false; + } + + return true; + } + +} diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/config/DataPermissionConfig.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/config/DataPermissionConfig.java new file mode 100644 index 0000000..78c911f --- /dev/null +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/config/DataPermissionConfig.java @@ -0,0 +1,42 @@ +package cn.axzo.framework.datapermission.config; + +import cn.axzo.framework.datapermission.aop.DataPermissionMybatisInterceptor; +import cn.axzo.framework.datapermission.context.DataPermissionContextFactory; +import cn.axzo.framework.datapermission.rule.DataPermissionDefaultRule; +import cn.axzo.framework.datapermission.rule.DataPermissionRule; +import cn.axzo.karma.client.feign.FlowSupportApi; +import cn.hutool.extra.spring.SpringUtil; +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.context.annotation.Bean; + +import java.net.DatagramSocketImplFactory; +import java.util.List; + +/** + * @author tanjie@axzo.cn + * @date 2024/5/31 16:34 + */ +@ConditionalOnBean(MybatisPlusInterceptor.class) +public class DataPermissionConfig { + + @Bean + public DataPermissionDefaultRule deptDataPermissionRule(FlowSupportApi permissionApi) { + // 创建 DeptDataPermissionRule 对象 + return new DataPermissionDefaultRule(permissionApi); + } + + @Bean + @ConditionalOnBean(MybatisPlusInterceptor.class) + public DataPermissionMybatisInterceptor mybatisDataPermissionInterceptor(MybatisPlusInterceptor mybatisPlusInterceptor, DataPermissionContextFactory dataPermissionContextFactory) { + DataPermissionMybatisInterceptor dataPermissionMybatisInterceptor = new DataPermissionMybatisInterceptor(dataPermissionContextFactory); + mybatisPlusInterceptor.addInnerInterceptor(dataPermissionMybatisInterceptor); + return dataPermissionMybatisInterceptor; + } + + + @Bean + public DataPermissionContextFactory dataPermissionRuleFactory(List rules) { + return new DataPermissionContextFactory(rules); + } +} diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextFactory.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextFactory.java new file mode 100644 index 0000000..6c1c7c2 --- /dev/null +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextFactory.java @@ -0,0 +1,30 @@ +package cn.axzo.framework.datapermission.context; + +import cn.axzo.framework.datapermission.annotation.DataPermission; +import cn.axzo.framework.datapermission.rule.DataPermissionRule; +import lombok.AllArgsConstructor; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author tanjie@axzo.cn + * @date 2024/5/31 17:58 + */ +@AllArgsConstructor +public class DataPermissionContextFactory { + + List rules; + + + public List getRules() { + return rules; + } + + public List getRuleByDataPermission(DataPermission dataPermission) { + Class[] classes = dataPermission.includeRule(); + return rules.stream().filter(rule -> Arrays.stream(classes).anyMatch(e -> e.equals(rule.getClass()))).collect(Collectors.toList()); + } + +} diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextHolder.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextHolder.java new file mode 100644 index 0000000..af8919d --- /dev/null +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextHolder.java @@ -0,0 +1,40 @@ +package cn.axzo.framework.datapermission.context; + +import cn.axzo.framework.datapermission.annotation.DataPermission; +import lombok.Data; + +/** + * 数据权限上下文 + * + * @author tanjie@axzo.cn + * @date 2024/5/31 11:42 + */ +public class DataPermissionContextHolder { + + private final static ThreadLocal DATA_PERMISSION_CONTEXT = new ThreadLocal<>(); + + + public static void setContext(DataPermissionContext dataPermission) { + DATA_PERMISSION_CONTEXT.set(dataPermission); + } + + + @Data + public static class DataPermissionContext { + private DataPermission dataPermission; + private Long ouId; + private Long workspaceId; + private Long personId; + } + + public static void remove() { + DATA_PERMISSION_CONTEXT.remove(); + } + + public static DataPermissionContext get() { + return DATA_PERMISSION_CONTEXT.get(); + } + + +} + diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/rule/DataPermissionDefaultRule.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/rule/DataPermissionDefaultRule.java new file mode 100644 index 0000000..089988a --- /dev/null +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/rule/DataPermissionDefaultRule.java @@ -0,0 +1,168 @@ +package cn.axzo.framework.datapermission.rule; + +import cn.axzo.karma.client.feign.FlowSupportApi; +import cn.hutool.core.collection.ListUtil; +import com.baomidou.mybatisplus.core.metadata.TableInfo; +import com.baomidou.mybatisplus.core.metadata.TableInfoHelper; +import com.baomidou.mybatisplus.core.toolkit.StringPool; +import com.baomidou.mybatisplus.extension.activerecord.Model; +import lombok.AllArgsConstructor; +import lombok.RequiredArgsConstructor; +import net.sf.jsqlparser.expression.Alias; +import net.sf.jsqlparser.expression.Expression; +import net.sf.jsqlparser.expression.LongValue; +import net.sf.jsqlparser.expression.NullValue; +import net.sf.jsqlparser.expression.Parenthesis; +import net.sf.jsqlparser.expression.operators.conditional.OrExpression; +import net.sf.jsqlparser.expression.operators.relational.ExpressionList; +import net.sf.jsqlparser.expression.operators.relational.InExpression; +import net.sf.jsqlparser.schema.Column; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; +import org.springframework.util.StringUtils; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; + +/** + * @author tanjie@axzo.cn + * @date 2024/5/30 18:35 + */ +@RequiredArgsConstructor +public class DataPermissionDefaultRule implements DataPermissionRule { + static final Expression EXPRESSION_NULL = new NullValue(); + + private static final String DEFAULT_PERSON = "person_id"; + private static final String DEFAULT_NODE = "organizational_node_id"; + /** + * key 表名 + * value 组织节点字段 + */ + protected final Map nodeTable = new ConcurrentHashMap<>(); + + /** + * key 表名 + * value personId字段 + */ + protected final Map personTable = new ConcurrentHashMap<>(); + + protected final Set tableName =new HashSet<>(); + + + //// TODO: 2024/6/3 查询数据权限的api + private final FlowSupportApi permissionApi; + + @Override + public Set getTableName() { + return tableName; + } + + @Override + public Expression getExpression(String tableName, Alias tableAlias) { + + // TODO: 2024/5/31 可访问的数据 @李龙 + List nodeIds = ListUtil.of(1L, 2L, 3L); + List personIds = ListUtil.of(110L, 223L); + + Expression deptExpression = buildExpression(tableName, tableAlias, nodeIds); + Expression userExpression = buildExpression(tableName, tableAlias, personIds); + if (deptExpression == null && userExpression == null) { + // 未获取到数据权限 返回NULL 不查询数据 + return EXPRESSION_NULL; + } + if (deptExpression == null) { + return userExpression; + } + if (userExpression == null) { + return deptExpression; + } + // 如果两个都有,用or WHERE (organizational_Node_id IN ? OR person_id in ?) + return new Parenthesis(new OrExpression(deptExpression, userExpression)); + + } + + + /** + * 构建查询条件 + * + * @param tableName + * @param tableAlias + * @param ids 可能是nodeids 也可以是personIds + * @return + */ + private Expression buildExpression(String tableName, Alias tableAlias, List ids) { + // 如果不存在配置,则无需作为条件 + String columnName = nodeTable.get(tableName); + if (!StringUtils.hasText(columnName)) { + return null; + } + if (CollectionUtils.isEmpty(ids)) { + return null; + } + // 拼接条件 + return new InExpression( + getColumn(tableAlias, columnName) + , new ExpressionList(ids.stream().map(LongValue::new).collect(Collectors.toList()))); + } + + + private Column getColumn(Alias tableAlias, String columnName) { + String result = tableAlias.getName() + StringPool.DOT + + columnName; + return new Column(result); + } + + /** + * 添加组织节点所对应的字段 + * + * @param entityClass 表所对应的entity + * @param columnName 字段名称 如:organizational_node_id + */ + public void addNodeColumn(Class> entityClass, String columnName) { + TableInfo tableInfo = TableInfoHelper.getTableInfo(entityClass); + if (null == tableInfo) { + return; + } + nodeTable.put(tableInfo.getTableName(), columnName); + tableName.add(tableInfo.getTableName()); + } + + /** + * 添加组织节点所对应的字段 字段默认使用organizational_node_id + * + * @param entityClass 表所对应的entity + */ + public void addNodeColumn(Class> entityClass) { + addNodeColumn(entityClass, DEFAULT_NODE); + } + + /** + * 添加personId所对应的字段 + * + * @param entityClass 表所对应的entity + * @param columnName 字段名称 如:person_id + */ + public void addPersonColumn(Class> entityClass, String columnName) { + TableInfo tableInfo = TableInfoHelper.getTableInfo(entityClass); + if (null == tableInfo) { + return; + } + personTable.put(tableInfo.getTableName(), columnName); + tableName.add(tableInfo.getTableName()); + } + + /** + * 字段默认使用person_id + * + * @param entityClass 表所对应的entity + */ + public void addPersonColumn(Class> entityClass) { + addPersonColumn(entityClass, DEFAULT_PERSON); + } +} diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/rule/DataPermissionRule.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/rule/DataPermissionRule.java new file mode 100644 index 0000000..7a9ae2e --- /dev/null +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/rule/DataPermissionRule.java @@ -0,0 +1,20 @@ +package cn.axzo.framework.datapermission.rule; + +import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor; +import net.sf.jsqlparser.expression.Alias; +import net.sf.jsqlparser.expression.Expression; + +import java.util.List; +import java.util.Set; + +/** + * @author tanjie@axzo.cn + * @date 2024/5/30 18:31 + */ +public interface DataPermissionRule { + + Set getTableName(); + + Expression getExpression(String tableName, Alias tableAlias); + +} diff --git a/axzo-common-data-permission/src/main/resources/META-INF/spring.factories b/axzo-common-data-permission/src/main/resources/META-INF/spring.factories new file mode 100644 index 0000000..296079e --- /dev/null +++ b/axzo-common-data-permission/src/main/resources/META-INF/spring.factories @@ -0,0 +1,2 @@ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ +cn.axzo.framework.datapermission.config.DataPermissionConfig \ No newline at end of file diff --git a/pom.xml b/pom.xml index 0a8d372..705c95d 100644 --- a/pom.xml +++ b/pom.xml @@ -36,6 +36,7 @@ axzo-common-datas axzo-common-cache axzo-common-rocketmq + axzo-common-data-permission From e76f07798d119ed7872ce1279e3426b6580eaa7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E6=98=86=E9=B9=8F?= Date: Tue, 4 Jun 2024 18:08:35 +0800 Subject: [PATCH 02/27] =?UTF-8?q?feat(REQ-2300)=EF=BC=9A=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E6=9D=83=E9=99=90=E4=B8=8A=E4=B8=8B=E6=96=87=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E7=BC=93=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../context/DataPermissionContextHolder.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextHolder.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextHolder.java index af8919d..6dcabcf 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextHolder.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextHolder.java @@ -1,8 +1,11 @@ package cn.axzo.framework.datapermission.context; import cn.axzo.framework.datapermission.annotation.DataPermission; +import com.google.common.collect.Maps; import lombok.Data; +import java.util.Map; + /** * 数据权限上下文 * @@ -25,6 +28,26 @@ public class DataPermissionContextHolder { private Long ouId; private Long workspaceId; private Long personId; + + /** + * 数据权限cache + * key < - > cn.axzo.tyr.client.common.enums.RowPermissionEnum || cn.axzo.tyr.client.common.enums.AttrPermissionEnum 的名字 + * value < - > 规则校验需要的数据 + * + * 描述 | key | value结构和描述 + * 本人及下属数据 | SELF_SUBORDINATE | List本人及下属的personId列表 + * 仅本部门数据 | DEPARTMENT_ONLY | List本部门的organizationalNodeId(单个)列表 + * 本部门及以下数据 | DEPARTMENT_SUBORDINATE | List本部门及子孙级的organizationalNodeIds列表 + * 仅本单位数据(包含班组) | UNIT_ONLY | List本单位数据(包含班组)的organizationalNodeIds列表 + * 仅本单位数据(不包含班组) | UNIT_ONLY_EXCLUDE_TEAM | List本单位数据(不包含班组)的organizationalNodeIds列表 + * 本单位及下级直属单位数据 | UNIT_DIRECT_SUBORDINATE | List本单位及下级直属单位的organizationalNodeIds列表 + * 本单位及下级协同(直属+合作)单位数据 | UNIT_COOPERATE_SUBORDINATE | List本单位及下级协同(直属+合作)单位的organizationalNodeIds列表 + * 本单位及以下协同(直属+合作)单位数据 | UNIT_ALL_SUBORDINATE | List本单位及以下协同(直属+合作)单位的organizationalNodeIds列表 + * 本项目部数据 | WORKSPACE | List本项目部的workspaceId(单个)列表 + * 同行级数据权限 | EQUAL_TO_ROW | todo 是否不放缓存 + * + */ + private Map permissionDataCache = Maps.newConcurrentMap(); } public static void remove() { From 2323e7a2a0745200861401c8c6814992029c627d Mon Sep 17 00:00:00 2001 From: lilong Date: Wed, 5 Jun 2024 17:01:06 +0800 Subject: [PATCH 03/27] =?UTF-8?q?feat=EF=BC=9A(REQ-2300)=20=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E6=95=B0=E6=8D=AE=E5=BA=93=E6=9F=A5=E8=AF=A2=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E6=9D=83=E9=99=90sdk?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../annotation/DataPermission.java | 5 +- .../aop/DataPermissionFilter.java | 53 +++++++++- .../aop/DataPermissionMybatisInterceptor.java | 9 +- .../config/DataPermissionConfig.java | 10 -- .../context/DataPermissionContextFactory.java | 6 +- .../context/DataPermissionContextHolder.java | 19 ++++ .../dataObject/DataObjectRule.java | 65 ++++++++++++ .../DepartmentAndSubordinateRule.java | 79 +++++++++++++++ .../dataObject/DepartmentOnlyRule.java | 58 +++++++++++ .../dataObject/MatchRuleFactory.java | 38 +++++++ .../dataObject/SelfAndSubordinateRule.java | 82 ++++++++++++++++ .../dataObject/SelfOnlyRule.java | 28 ++++++ .../dataObject/UnitAllSubordinateRule.java | 58 +++++++++++ .../UnitCooperateSubordinateRule.java | 58 +++++++++++ .../dataObject/UnitDirectSubordinateRule.java | 58 +++++++++++ .../dataObject/UnitOnlyExcludeTeamRule.java | 57 +++++++++++ .../dataObject/UnitOnlyRule.java | 58 +++++++++++ .../dataObject/WorkspaceRule.java | 58 +++++++++++ .../rule/DataPermissionRule.java | 3 - ...onDefaultRule.java => OrgDefaultRule.java} | 98 +++++++++++++------ .../datapermission/rule/StringsUtil.java | 27 +++++ 21 files changed, 873 insertions(+), 54 deletions(-) create mode 100644 axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/DataObjectRule.java create mode 100644 axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/DepartmentAndSubordinateRule.java create mode 100644 axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/DepartmentOnlyRule.java create mode 100644 axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/MatchRuleFactory.java create mode 100644 axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/SelfAndSubordinateRule.java create mode 100644 axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/SelfOnlyRule.java create mode 100644 axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/UnitAllSubordinateRule.java create mode 100644 axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/UnitCooperateSubordinateRule.java create mode 100644 axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/UnitDirectSubordinateRule.java create mode 100644 axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/UnitOnlyExcludeTeamRule.java create mode 100644 axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/UnitOnlyRule.java create mode 100644 axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/WorkspaceRule.java rename axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/rule/{DataPermissionDefaultRule.java => OrgDefaultRule.java} (59%) create mode 100644 axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/rule/StringsUtil.java diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/annotation/DataPermission.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/annotation/DataPermission.java index 75b322e..5704da2 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/annotation/DataPermission.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/annotation/DataPermission.java @@ -1,5 +1,6 @@ package cn.axzo.framework.datapermission.annotation; +import cn.axzo.framework.datapermission.rule.OrgDefaultRule; import cn.axzo.framework.datapermission.rule.DataPermissionRule; /** @@ -8,9 +9,9 @@ import cn.axzo.framework.datapermission.rule.DataPermissionRule; * @date 2024/5/30 17:57 */ public @interface DataPermission { - boolean enable() default false; + boolean enable() default true; - Class[] includeRule() default {}; + Class includeRule() default OrgDefaultRule.class; String bizCode() default ""; diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionFilter.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionFilter.java index ee41cad..56a2001 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionFilter.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionFilter.java @@ -1,16 +1,61 @@ package cn.axzo.framework.datapermission.aop; +import cn.axzo.framework.auth.domain.ContextInfo; +import cn.axzo.framework.auth.domain.ContextInfoHolder; import cn.axzo.framework.datapermission.annotation.DataPermission; -import cn.axzo.framework.datapermission.config.DataPermissionConfig; +import cn.axzo.framework.datapermission.context.DataPermissionContextHolder; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.BooleanUtils; +import org.springframework.core.annotation.Order; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.HandlerInterceptor; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; /** * * @author tanjie@axzo.cn * @date 2024/5/31 16:37 */ -public class DataPermissionFilter { +@Order(2) +@Slf4j +public class DataPermissionFilter implements HandlerInterceptor { - // 拦截@DataPermission - // 设置DataPermissionContext + /** + * 拦截@DataPermission + * 设置DataPermissionContext + * @param request + * @param response + * @param handler + * @return + * @throws Exception + */ + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) + throws Exception { + if (handler instanceof HandlerMethod) { + HandlerMethod handlerMethod = (HandlerMethod) handler; + DataPermission dataPermission = handlerMethod.getMethodAnnotation(DataPermission.class); + if (dataPermission == null || BooleanUtils.isNotTrue(dataPermission.enable())) { + return true; + } + + DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.DataPermissionContext.builder() + .dataPermission(dataPermission) + .build(); + + // 有数据权限注解,但没用户信息,让后面拦截器做处理更合理(可以返回空数据或者不阻塞业务正常查询数据) + ContextInfo contextInfo = ContextInfoHolder.get(); + if (contextInfo != null) { + dataPermissionContext.setWorkspaceId(contextInfo.getWorkspaceId()); + dataPermissionContext.setOuId(contextInfo.getOuId()); + dataPermissionContext.setPersonId(contextInfo.getUserInfo().getPersonId()); + } + + DataPermissionContextHolder.setContext(dataPermissionContext); + } + return true; + } } diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionMybatisInterceptor.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionMybatisInterceptor.java index f579435..cb03997 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionMybatisInterceptor.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionMybatisInterceptor.java @@ -4,6 +4,8 @@ import cn.axzo.framework.datapermission.annotation.DataPermission; import cn.axzo.framework.datapermission.context.DataPermissionContextFactory; import cn.axzo.framework.datapermission.context.DataPermissionContextHolder; import cn.axzo.framework.datapermission.rule.DataPermissionRule; +import cn.axzo.karma.client.feign.tyr.response.MatchDataObjectResp; +import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.parser.SqlParserHelper; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.baomidou.mybatisplus.core.toolkit.PluginUtils; @@ -52,9 +54,10 @@ import java.util.Optional; * @date 2024/5/31 11:41 */ @RequiredArgsConstructor -public class DataPermissionMybatisInterceptor extends JsqlParserSupport implements InnerInterceptor { +public class DataPermissionMybatisInterceptor extends JsqlParserSupport implements InnerInterceptor { private final DataPermissionContextFactory dataPermissionContextFactory; + @Override public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException { if (!filter()) { @@ -315,7 +318,9 @@ public class DataPermissionMybatisInterceptor extends JsqlParserSupport implem private boolean filter() { DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.get(); - if (null == dataPermissionContext|| !dataPermissionContext.getDataPermission().enable()) { + if (null == dataPermissionContext + || dataPermissionContext.getDataPermission() == null + || !dataPermissionContext.getDataPermission().enable()) { return false; } diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/config/DataPermissionConfig.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/config/DataPermissionConfig.java index 78c911f..ceea116 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/config/DataPermissionConfig.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/config/DataPermissionConfig.java @@ -2,15 +2,11 @@ package cn.axzo.framework.datapermission.config; import cn.axzo.framework.datapermission.aop.DataPermissionMybatisInterceptor; import cn.axzo.framework.datapermission.context.DataPermissionContextFactory; -import cn.axzo.framework.datapermission.rule.DataPermissionDefaultRule; import cn.axzo.framework.datapermission.rule.DataPermissionRule; -import cn.axzo.karma.client.feign.FlowSupportApi; -import cn.hutool.extra.spring.SpringUtil; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.context.annotation.Bean; -import java.net.DatagramSocketImplFactory; import java.util.List; /** @@ -20,12 +16,6 @@ import java.util.List; @ConditionalOnBean(MybatisPlusInterceptor.class) public class DataPermissionConfig { - @Bean - public DataPermissionDefaultRule deptDataPermissionRule(FlowSupportApi permissionApi) { - // 创建 DeptDataPermissionRule 对象 - return new DataPermissionDefaultRule(permissionApi); - } - @Bean @ConditionalOnBean(MybatisPlusInterceptor.class) public DataPermissionMybatisInterceptor mybatisDataPermissionInterceptor(MybatisPlusInterceptor mybatisPlusInterceptor, DataPermissionContextFactory dataPermissionContextFactory) { diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextFactory.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextFactory.java index 6c1c7c2..5cc2dab 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextFactory.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextFactory.java @@ -4,8 +4,8 @@ import cn.axzo.framework.datapermission.annotation.DataPermission; import cn.axzo.framework.datapermission.rule.DataPermissionRule; import lombok.AllArgsConstructor; -import java.util.Arrays; import java.util.List; +import java.util.Objects; import java.util.stream.Collectors; /** @@ -23,8 +23,8 @@ public class DataPermissionContextFactory { } public List getRuleByDataPermission(DataPermission dataPermission) { - Class[] classes = dataPermission.includeRule(); - return rules.stream().filter(rule -> Arrays.stream(classes).anyMatch(e -> e.equals(rule.getClass()))).collect(Collectors.toList()); + Class classes = dataPermission.includeRule(); + return rules.stream().filter(rule -> Objects.equals(classes, rule.getClass())).collect(Collectors.toList()); } } diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextHolder.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextHolder.java index 6dcabcf..99abfce 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextHolder.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextHolder.java @@ -2,7 +2,10 @@ package cn.axzo.framework.datapermission.context; import cn.axzo.framework.datapermission.annotation.DataPermission; import com.google.common.collect.Maps; +import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Data; +import lombok.NoArgsConstructor; import java.util.Map; @@ -16,6 +19,15 @@ public class DataPermissionContextHolder { private final static ThreadLocal DATA_PERMISSION_CONTEXT = new ThreadLocal<>(); + public static final String SELF_SUBORDINATE = "SELF_SUBORDINATE"; + public static final String DEPARTMENT_ONLY = "DEPARTMENT_ONLY"; + public static final String DEPARTMENT_SUBORDINATE = "DEPARTMENT_SUBORDINATE"; + public static final String UNIT_ONLY = "UNIT_ONLY"; + public static final String UNIT_ONLY_EXCLUDE_TEAM = "UNIT_ONLY_EXCLUDE_TEAM"; + public static final String UNIT_DIRECT_SUBORDINATE = "UNIT_DIRECT_SUBORDINATE"; + public static final String UNIT_COOPERATE_SUBORDINATE = "UNIT_COOPERATE_SUBORDINATE"; + public static final String UNIT_ALL_SUBORDINATE = "UNIT_ALL_SUBORDINATE"; + public static final String WORKSPACE = "WORKSPACE"; public static void setContext(DataPermissionContext dataPermission) { DATA_PERMISSION_CONTEXT.set(dataPermission); @@ -23,6 +35,9 @@ public class DataPermissionContextHolder { @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor public static class DataPermissionContext { private DataPermission dataPermission; private Long ouId; @@ -48,6 +63,10 @@ public class DataPermissionContextHolder { * */ private Map permissionDataCache = Maps.newConcurrentMap(); + + public void putPermissionData(String key, Object value) { + permissionDataCache.put(key, value); + } } public static void remove() { diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/DataObjectRule.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/DataObjectRule.java new file mode 100644 index 0000000..87f74d1 --- /dev/null +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/DataObjectRule.java @@ -0,0 +1,65 @@ +package cn.axzo.framework.datapermission.dataObject; + +import cn.axzo.karma.client.feign.tyr.response.MatchDataObjectResp; +import com.google.common.collect.Sets; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.util.CollectionUtils; + +import java.util.List; +import java.util.Objects; +import java.util.Set; + +public interface DataObjectRule { + + /** + * 解析规则,返回解析后的数据 + * @param context + * @return + */ + void resolve(DataObjectRuleContext context); + + /** + * 查询规则的id + * @return + */ + Integer getRulePermissionId(); + + @Data + @Builder + @AllArgsConstructor + @NoArgsConstructor + class DataObjectRuleContext { + + /** + * 解析后的人员id + */ + @Builder.Default + private Set personIds = Sets.newHashSet(); + + /** + * 解析后的部门id + */ + @Builder.Default + private Set nodeIds = Sets.newHashSet(); + + public void addPersonIds(Set personIds) { + this.getPersonIds().addAll(personIds); + } + + public void addNodeIds(Set nodeIds) { + this.getNodeIds().addAll(nodeIds); + } + } + + default boolean match(List rules) { + if (CollectionUtils.isEmpty(rules)) { + return false; + } + + return rules.stream() + .anyMatch(e -> Objects.equals(e.getRowPermission(), getRulePermissionId())); + } +} diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/DepartmentAndSubordinateRule.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/DepartmentAndSubordinateRule.java new file mode 100644 index 0000000..f4f767b --- /dev/null +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/DepartmentAndSubordinateRule.java @@ -0,0 +1,79 @@ +package cn.axzo.framework.datapermission.dataObject; + +import cn.axzo.framework.datapermission.context.DataPermissionContextHolder; +import cn.axzo.karma.client.feign.organization.OrganizationalNodeApi; +import cn.axzo.karma.client.feign.organization.request.PageOrganizationNodeReq; +import cn.axzo.karma.client.feign.organization.response.OrganizationalNodeResp; +import lombok.RequiredArgsConstructor; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +import static cn.axzo.framework.datapermission.context.DataPermissionContextHolder.DEPARTMENT_SUBORDINATE; + +@RequiredArgsConstructor +public class DepartmentAndSubordinateRule implements DataObjectRule { + + private final OrganizationalNodeApi organizationalNodeApi; + + /** + * 本部门及以下数据规则id + */ + private static final Integer RULE_PERMISSION_ID = 4; + + @Override + public Integer getRulePermissionId() { + return RULE_PERMISSION_ID; + } + + @Override + public void resolve(DataObjectRuleContext context) { + DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.get(); + + List nodes = organizationalNodeApi.page(PageOrganizationNodeReq.builder() + .personId(dataPermissionContext.getPersonId()) + .ouId(dataPermissionContext.getOuId()) + .needSubordinate(true) + .build()) + .getData() + .getData(); + + if (CollectionUtils.isEmpty(nodes)) { + return; + } + + Set nodeIds = nodes.stream() + .map(OrganizationalNodeResp::getId) + .filter(Objects::nonNull) + .collect(Collectors.toSet()); + + resolveNodes(nodeIds, nodes); + + dataPermissionContext.putPermissionData(DEPARTMENT_SUBORDINATE, nodeIds); + context.addNodeIds(nodeIds); + } + + private void resolveNodes(Set nodeIds, List nodes) { + if (CollectionUtils.isEmpty(nodes)) { + return; + } + + Set subordinateIds = nodes.stream() + .map(OrganizationalNodeResp::getSubordinateOuNodes) + .filter(Objects::nonNull) + .flatMap(Collection::stream) + .map(OrganizationalNodeResp::getId) + .filter(Objects::nonNull) + .collect(Collectors.toSet()); + if (CollectionUtils.isEmpty(subordinateIds)) { + return; + } + nodeIds.addAll(subordinateIds); + + nodes.forEach(e -> resolveNodes(nodeIds, e.getSubordinateOuNodes())); + } +} diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/DepartmentOnlyRule.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/DepartmentOnlyRule.java new file mode 100644 index 0000000..7dd12db --- /dev/null +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/DepartmentOnlyRule.java @@ -0,0 +1,58 @@ +package cn.axzo.framework.datapermission.dataObject; + +import cn.axzo.framework.datapermission.context.DataPermissionContextHolder; +import cn.axzo.karma.client.feign.organization.OrganizationalNodeApi; +import cn.axzo.karma.client.feign.organization.request.PageOrganizationNodeReq; +import cn.axzo.karma.client.feign.organization.response.OrganizationalNodeResp; +import lombok.RequiredArgsConstructor; +import org.springframework.util.CollectionUtils; + +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +import static cn.axzo.framework.datapermission.context.DataPermissionContextHolder.DEPARTMENT_ONLY; + +/** + * 本部门数据规则 + */ +@RequiredArgsConstructor +public class DepartmentOnlyRule implements DataObjectRule { + + private final OrganizationalNodeApi organizationalNodeApi; + + /** + * 本部门数据规则id + */ + private static final Integer RULE_PERMISSION_ID = 3; + + @Override + public Integer getRulePermissionId() { + return RULE_PERMISSION_ID; + } + + @Override + public void resolve(DataObjectRuleContext context) { + DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.get(); + + List nodes = organizationalNodeApi.page(PageOrganizationNodeReq.builder() + .personId(dataPermissionContext.getPersonId()) + .ouId(dataPermissionContext.getOuId()) + .build()) + .getData() + .getData(); + + if (CollectionUtils.isEmpty(nodes)) { + return; + } + + Set nodeIds = nodes.stream() + .map(OrganizationalNodeResp::getId) + .filter(Objects::nonNull) + .collect(Collectors.toSet()); + + context.addNodeIds(nodeIds); + dataPermissionContext.putPermissionData(DEPARTMENT_ONLY, nodeIds); + } +} diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/MatchRuleFactory.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/MatchRuleFactory.java new file mode 100644 index 0000000..f795c3f --- /dev/null +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/MatchRuleFactory.java @@ -0,0 +1,38 @@ +package cn.axzo.framework.datapermission.dataObject; + +import cn.axzo.karma.client.feign.tyr.response.MatchDataObjectResp; +import lombok.AllArgsConstructor; +import org.springframework.util.CollectionUtils; + +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.stream.Collectors; + +@AllArgsConstructor +public class MatchRuleFactory { + + private final List dataObjectRules; + + public Optional matchAndResolve(MatchDataObjectResp matchDataObjectResp) { + + if (Objects.isNull(matchDataObjectResp) || CollectionUtils.isEmpty(matchDataObjectResp.getRules())) { + return Optional.empty(); + } + + List matchedRules = dataObjectRules.stream() + .filter(e -> e.match(matchDataObjectResp.getRules())) + .collect(Collectors.toList()); + + if (CollectionUtils.isEmpty(matchedRules)) { + return Optional.empty(); + } + + DataObjectRule.DataObjectRuleContext dataObjectRuleContext = DataObjectRule.DataObjectRuleContext.builder().build(); + for (DataObjectRule matchedRule : matchedRules) { + matchedRule.resolve(dataObjectRuleContext); + } + + return Optional.ofNullable(dataObjectRuleContext); + } +} diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/SelfAndSubordinateRule.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/SelfAndSubordinateRule.java new file mode 100644 index 0000000..f788bd5 --- /dev/null +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/SelfAndSubordinateRule.java @@ -0,0 +1,82 @@ +package cn.axzo.framework.datapermission.dataObject; + +import cn.axzo.framework.datapermission.context.DataPermissionContextHolder; +import cn.axzo.karma.client.feign.organization.OrganizationalNodeUserApi; +import cn.axzo.karma.client.feign.organization.request.PageOrganizationNodeUserReq; +import cn.axzo.karma.client.feign.organization.response.OrganizationalNodeUserResp; +import lombok.RequiredArgsConstructor; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +import static cn.axzo.framework.datapermission.context.DataPermissionContextHolder.SELF_SUBORDINATE; + +/** + * 本人及下属数据规则 + */ +@RequiredArgsConstructor +public class SelfAndSubordinateRule implements DataObjectRule { + + private final OrganizationalNodeUserApi organizationalNodeUserApi; + + /** + * 本人及下属数据规则id + */ + private static final Integer RULE_PERMISSION_ID = 2; + + @Override + public Integer getRulePermissionId() { + return RULE_PERMISSION_ID; + } + + @Override + public void resolve(DataObjectRuleContext context) { + DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.get(); + + List nodeUsers = organizationalNodeUserApi.page(PageOrganizationNodeUserReq.builder() + .personId(dataPermissionContext.getPersonId()) + .ouId(dataPermissionContext.getOuId()) + .needSubordinate(true) + .build()) + .getData() + .getData(); + + if (CollectionUtils.isEmpty(nodeUsers)) { + return; + } + + Set personIds = nodeUsers.stream() + .map(OrganizationalNodeUserResp::getPersonId) + .filter(Objects::nonNull) + .collect(Collectors.toSet()); + + resolveNodeUsers(personIds, nodeUsers); + + dataPermissionContext.putPermissionData(SELF_SUBORDINATE, personIds); + context.addPersonIds(personIds); + } + + private void resolveNodeUsers(Set personIds, List nodeUsers) { + if (CollectionUtils.isEmpty(nodeUsers)) { + return; + } + + Set subordinatePersonIds = nodeUsers.stream() + .map(OrganizationalNodeUserResp::getSubordinateOuNodeUsers) + .filter(Objects::nonNull) + .flatMap(Collection::stream) + .map(OrganizationalNodeUserResp::getPersonId) + .filter(Objects::nonNull) + .collect(Collectors.toSet()); + if (CollectionUtils.isEmpty(subordinatePersonIds)) { + return; + } + personIds.addAll(subordinatePersonIds); + + nodeUsers.forEach(e -> resolveNodeUsers(personIds, e.getSubordinateOuNodeUsers())); + } +} diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/SelfOnlyRule.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/SelfOnlyRule.java new file mode 100644 index 0000000..c42d917 --- /dev/null +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/SelfOnlyRule.java @@ -0,0 +1,28 @@ +package cn.axzo.framework.datapermission.dataObject; + +import cn.axzo.framework.datapermission.context.DataPermissionContextHolder; +import com.google.common.collect.Sets; +import lombok.RequiredArgsConstructor; + +/** + * 仅本人数据规则 + */ +@RequiredArgsConstructor +public class SelfOnlyRule implements DataObjectRule { + + /** + * 仅本人数据的规则id + */ + private static final Integer RULE_PERMISSION_ID = 1; + + @Override + public Integer getRulePermissionId() { + return RULE_PERMISSION_ID; + } + + @Override + public void resolve(DataObjectRuleContext context) { + DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.get(); + context.addPersonIds(Sets.newHashSet(dataPermissionContext.getPersonId())); + } +} diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/UnitAllSubordinateRule.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/UnitAllSubordinateRule.java new file mode 100644 index 0000000..6011abf --- /dev/null +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/UnitAllSubordinateRule.java @@ -0,0 +1,58 @@ +package cn.axzo.framework.datapermission.dataObject; + +import cn.axzo.framework.datapermission.context.DataPermissionContextHolder; +import cn.axzo.karma.client.feign.organization.OrganizationalNodeApi; +import cn.axzo.karma.client.feign.organization.request.QueryOuMultiConditionalReq; +import cn.axzo.karma.client.feign.organization.response.QueryOuMultiConditionalResp; +import lombok.RequiredArgsConstructor; +import org.springframework.util.CollectionUtils; + +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +import static cn.axzo.framework.datapermission.context.DataPermissionContextHolder.UNIT_ALL_SUBORDINATE; + +/** + * 本单位及以下协同(直属+合作)单位数据 + */ +@RequiredArgsConstructor +public class UnitAllSubordinateRule implements DataObjectRule { + + + private final OrganizationalNodeApi organizationalNodeApi; + + /** + * 本单位及以下协同(直属+合作)单位数据的规则id + */ + private static final Integer RULE_PERMISSION_ID = 8; + + @Override + public Integer getRulePermissionId() { + return RULE_PERMISSION_ID; + } + + @Override + public void resolve(DataObjectRuleContext context) { + DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.get(); + + QueryOuMultiConditionalResp node = organizationalNodeApi.queryOuMultiConditional(QueryOuMultiConditionalReq.builder() + .workspaceId(dataPermissionContext.getWorkspaceId()) + .ouId(dataPermissionContext.getOuId()) + .needDirectlyAndCooperateWithDescendant(true) + .build()) + .getData(); + + if (Objects.isNull(node) || CollectionUtils.isEmpty(node.getBasicNodeUsers())) { + return; + } + + Set nodeIds = node.getBasicNodeUsers().stream() + .map(QueryOuMultiConditionalResp.BasicNodeUser::getNodeId) + .filter(Objects::nonNull) + .collect(Collectors.toSet()); + + context.addNodeIds(nodeIds); + dataPermissionContext.putPermissionData(UNIT_ALL_SUBORDINATE, nodeIds); + } +} diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/UnitCooperateSubordinateRule.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/UnitCooperateSubordinateRule.java new file mode 100644 index 0000000..e5ce279 --- /dev/null +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/UnitCooperateSubordinateRule.java @@ -0,0 +1,58 @@ +package cn.axzo.framework.datapermission.dataObject; + +import cn.axzo.framework.datapermission.context.DataPermissionContextHolder; +import cn.axzo.karma.client.feign.organization.OrganizationalNodeApi; +import cn.axzo.karma.client.feign.organization.request.QueryOuMultiConditionalReq; +import cn.axzo.karma.client.feign.organization.response.QueryOuMultiConditionalResp; +import lombok.RequiredArgsConstructor; +import org.springframework.util.CollectionUtils; + +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +import static cn.axzo.framework.datapermission.context.DataPermissionContextHolder.UNIT_COOPERATE_SUBORDINATE; + +/** + * 本单位及下级协同(直属+合作)单位数据 + */ +@RequiredArgsConstructor +public class UnitCooperateSubordinateRule implements DataObjectRule { + + + private final OrganizationalNodeApi organizationalNodeApi; + + /** + * 本单位及下级协同(直属+合作)单位数据的规则id + */ + private static final Integer RULE_PERMISSION_ID = 7; + + @Override + public Integer getRulePermissionId() { + return RULE_PERMISSION_ID; + } + + @Override + public void resolve(DataObjectRuleContext context) { + DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.get(); + + QueryOuMultiConditionalResp node = organizationalNodeApi.queryOuMultiConditional(QueryOuMultiConditionalReq.builder() + .workspaceId(dataPermissionContext.getWorkspaceId()) + .ouId(dataPermissionContext.getOuId()) + .needDirectlyAndCooperate(true) + .build()) + .getData(); + + if (Objects.isNull(node) || CollectionUtils.isEmpty(node.getBasicNodeUsers())) { + return; + } + + Set nodeIds = node.getBasicNodeUsers().stream() + .map(QueryOuMultiConditionalResp.BasicNodeUser::getNodeId) + .filter(Objects::nonNull) + .collect(Collectors.toSet()); + + context.addNodeIds(nodeIds); + dataPermissionContext.putPermissionData(UNIT_COOPERATE_SUBORDINATE, nodeIds); + } +} diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/UnitDirectSubordinateRule.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/UnitDirectSubordinateRule.java new file mode 100644 index 0000000..d56f822 --- /dev/null +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/UnitDirectSubordinateRule.java @@ -0,0 +1,58 @@ +package cn.axzo.framework.datapermission.dataObject; + +import cn.axzo.framework.datapermission.context.DataPermissionContextHolder; +import cn.axzo.karma.client.feign.organization.OrganizationalNodeApi; +import cn.axzo.karma.client.feign.organization.request.QueryOuMultiConditionalReq; +import cn.axzo.karma.client.feign.organization.response.QueryOuMultiConditionalResp; +import lombok.RequiredArgsConstructor; +import org.springframework.util.CollectionUtils; + +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +import static cn.axzo.framework.datapermission.context.DataPermissionContextHolder.UNIT_DIRECT_SUBORDINATE; + +/** + * 本单位及下级直属单位数据 + */ +@RequiredArgsConstructor +public class UnitDirectSubordinateRule implements DataObjectRule { + + + private final OrganizationalNodeApi organizationalNodeApi; + + /** + * 本单位及下级直属单位数据的规则id + */ + private static final Integer RULE_PERMISSION_ID = 6; + + @Override + public Integer getRulePermissionId() { + return RULE_PERMISSION_ID; + } + + @Override + public void resolve(DataObjectRuleContext context) { + DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.get(); + + QueryOuMultiConditionalResp node = organizationalNodeApi.queryOuMultiConditional(QueryOuMultiConditionalReq.builder() + .workspaceId(dataPermissionContext.getWorkspaceId()) + .ouId(dataPermissionContext.getOuId()) + .needDirectlyUnder(true) + .build()) + .getData(); + + if (Objects.isNull(node) || CollectionUtils.isEmpty(node.getBasicNodeUsers())) { + return; + } + + Set nodeIds = node.getBasicNodeUsers().stream() + .map(QueryOuMultiConditionalResp.BasicNodeUser::getNodeId) + .filter(Objects::nonNull) + .collect(Collectors.toSet()); + + context.addNodeIds(nodeIds); + dataPermissionContext.putPermissionData(UNIT_DIRECT_SUBORDINATE, nodeIds); + } +} diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/UnitOnlyExcludeTeamRule.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/UnitOnlyExcludeTeamRule.java new file mode 100644 index 0000000..149bb9e --- /dev/null +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/UnitOnlyExcludeTeamRule.java @@ -0,0 +1,57 @@ +package cn.axzo.framework.datapermission.dataObject; + +import cn.axzo.framework.datapermission.context.DataPermissionContextHolder; +import cn.axzo.karma.client.feign.organization.OrganizationalNodeApi; +import cn.axzo.karma.client.feign.organization.request.QueryOuMultiConditionalReq; +import cn.axzo.karma.client.feign.organization.response.QueryOuMultiConditionalResp; +import lombok.RequiredArgsConstructor; +import org.springframework.util.CollectionUtils; + +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +import static cn.axzo.framework.datapermission.context.DataPermissionContextHolder.UNIT_ONLY_EXCLUDE_TEAM; + +/** + * 仅本单位数据(不包含班组) + */ +@RequiredArgsConstructor +public class UnitOnlyExcludeTeamRule implements DataObjectRule { + + + private final OrganizationalNodeApi organizationalNodeApi; + + /** + * 仅本单位数据(不包含班组)的规则id + */ + private static final Integer RULE_PERMISSION_ID = 10; + + @Override + public Integer getRulePermissionId() { + return RULE_PERMISSION_ID; + } + + @Override + public void resolve(DataObjectRuleContext context) { + DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.get(); + + QueryOuMultiConditionalResp node = organizationalNodeApi.queryOuMultiConditional(QueryOuMultiConditionalReq.builder() + .workspaceId(dataPermissionContext.getWorkspaceId()) + .ouId(dataPermissionContext.getOuId()) + .build()) + .getData(); + + if (Objects.isNull(node) || CollectionUtils.isEmpty(node.getBasicNodeUsers())) { + return; + } + + Set nodeIds = node.getBasicNodeUsers().stream() + .map(QueryOuMultiConditionalResp.BasicNodeUser::getNodeId) + .filter(Objects::nonNull) + .collect(Collectors.toSet()); + + context.addNodeIds(nodeIds); + dataPermissionContext.putPermissionData(UNIT_ONLY_EXCLUDE_TEAM, nodeIds); + } +} diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/UnitOnlyRule.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/UnitOnlyRule.java new file mode 100644 index 0000000..8b827ff --- /dev/null +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/UnitOnlyRule.java @@ -0,0 +1,58 @@ +package cn.axzo.framework.datapermission.dataObject; + +import cn.axzo.framework.datapermission.context.DataPermissionContextHolder; +import cn.axzo.karma.client.feign.organization.OrganizationalNodeApi; +import cn.axzo.karma.client.feign.organization.request.QueryOuMultiConditionalReq; +import cn.axzo.karma.client.feign.organization.response.QueryOuMultiConditionalResp; +import lombok.RequiredArgsConstructor; +import org.springframework.util.CollectionUtils; + +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +import static cn.axzo.framework.datapermission.context.DataPermissionContextHolder.UNIT_ONLY; + +/** + * 仅本单位数据(包含班组) + */ +@RequiredArgsConstructor +public class UnitOnlyRule implements DataObjectRule { + + + private final OrganizationalNodeApi organizationalNodeApi; + + /** + * 仅本单位数据(包含班组)的规则id + */ + private static final Integer RULE_PERMISSION_ID = 5; + + @Override + public Integer getRulePermissionId() { + return RULE_PERMISSION_ID; + } + + @Override + public void resolve(DataObjectRuleContext context) { + DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.get(); + + QueryOuMultiConditionalResp node = organizationalNodeApi.queryOuMultiConditional(QueryOuMultiConditionalReq.builder() + .workspaceId(dataPermissionContext.getWorkspaceId()) + .ouId(dataPermissionContext.getOuId()) + .needTeam(true) + .build()) + .getData(); + + if (Objects.isNull(node) || CollectionUtils.isEmpty(node.getBasicNodeUsers())) { + return; + } + + Set nodeIds = node.getBasicNodeUsers().stream() + .map(QueryOuMultiConditionalResp.BasicNodeUser::getNodeId) + .filter(Objects::nonNull) + .collect(Collectors.toSet()); + + context.addNodeIds(nodeIds); + dataPermissionContext.putPermissionData(UNIT_ONLY, nodeIds); + } +} diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/WorkspaceRule.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/WorkspaceRule.java new file mode 100644 index 0000000..3c418b0 --- /dev/null +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/WorkspaceRule.java @@ -0,0 +1,58 @@ +package cn.axzo.framework.datapermission.dataObject; + +import cn.axzo.framework.datapermission.context.DataPermissionContextHolder; +import cn.axzo.karma.client.feign.organization.OrganizationalNodeApi; +import cn.axzo.karma.client.feign.organization.request.PageOrganizationNodeReq; +import cn.axzo.karma.client.feign.organization.response.OrganizationalNodeResp; +import lombok.RequiredArgsConstructor; +import org.springframework.util.CollectionUtils; + +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +import static cn.axzo.framework.datapermission.context.DataPermissionContextHolder.WORKSPACE; + +/** + * 本项目部数据 + */ +@RequiredArgsConstructor +public class WorkspaceRule implements DataObjectRule { + + + private final OrganizationalNodeApi organizationalNodeApi; + + /** + * 本项目部数据的规则id + */ + private static final Integer RULE_PERMISSION_ID = 9; + + @Override + public Integer getRulePermissionId() { + return RULE_PERMISSION_ID; + } + + @Override + public void resolve(DataObjectRuleContext context) { + DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.get(); + + List nodes = organizationalNodeApi.page(PageOrganizationNodeReq.builder() + .workspaceId(dataPermissionContext.getWorkspaceId()) + .build()) + .getData() + .getData(); + + if (CollectionUtils.isEmpty(nodes)) { + return; + } + + Set nodeIds = nodes.stream() + .map(OrganizationalNodeResp::getId) + .filter(Objects::nonNull) + .collect(Collectors.toSet()); + + context.addNodeIds(nodeIds); + dataPermissionContext.putPermissionData(WORKSPACE, nodeIds); + } +} diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/rule/DataPermissionRule.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/rule/DataPermissionRule.java index 7a9ae2e..0a1d36a 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/rule/DataPermissionRule.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/rule/DataPermissionRule.java @@ -1,10 +1,8 @@ package cn.axzo.framework.datapermission.rule; -import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor; import net.sf.jsqlparser.expression.Alias; import net.sf.jsqlparser.expression.Expression; -import java.util.List; import java.util.Set; /** @@ -16,5 +14,4 @@ public interface DataPermissionRule { Set getTableName(); Expression getExpression(String tableName, Alias tableAlias); - } diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/rule/DataPermissionDefaultRule.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/rule/OrgDefaultRule.java similarity index 59% rename from axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/rule/DataPermissionDefaultRule.java rename to axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/rule/OrgDefaultRule.java index 089988a..7783a1b 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/rule/DataPermissionDefaultRule.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/rule/OrgDefaultRule.java @@ -1,13 +1,19 @@ package cn.axzo.framework.datapermission.rule; -import cn.axzo.karma.client.feign.FlowSupportApi; -import cn.hutool.core.collection.ListUtil; +import cn.axzo.framework.datapermission.context.DataPermissionContextHolder; +import cn.axzo.framework.datapermission.dataObject.DataObjectRule; +import cn.axzo.framework.datapermission.dataObject.MatchRuleFactory; +import cn.axzo.karma.client.feign.tyr.DataObjectApi; +import cn.axzo.karma.client.feign.tyr.request.MatchDataObjectReq; +import cn.axzo.karma.client.feign.tyr.response.MatchDataObjectResp; +import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.metadata.TableInfo; import com.baomidou.mybatisplus.core.metadata.TableInfoHelper; import com.baomidou.mybatisplus.core.toolkit.StringPool; import com.baomidou.mybatisplus.extension.activerecord.Model; -import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import net.sf.jsqlparser.expression.Alias; import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.LongValue; @@ -17,25 +23,25 @@ import net.sf.jsqlparser.expression.operators.conditional.OrExpression; import net.sf.jsqlparser.expression.operators.relational.ExpressionList; import net.sf.jsqlparser.expression.operators.relational.InExpression; import net.sf.jsqlparser.schema.Column; -import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; -import java.util.ArrayList; -import java.util.HashMap; import java.util.HashSet; -import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; /** + * 基于personId、租户、单位、部门的数据权限 * @author tanjie@axzo.cn * @date 2024/5/30 18:35 */ +@Builder @RequiredArgsConstructor -public class DataPermissionDefaultRule implements DataPermissionRule { +@Slf4j +public class OrgDefaultRule implements DataPermissionRule { static final Expression EXPRESSION_NULL = new NullValue(); private static final String DEFAULT_PERSON = "person_id"; @@ -54,9 +60,9 @@ public class DataPermissionDefaultRule implements DataPermissionRule { protected final Set tableName =new HashSet<>(); + private final DataObjectApi dataObjectApi; - //// TODO: 2024/6/3 查询数据权限的api - private final FlowSupportApi permissionApi; + private final MatchRuleFactory matchRuleFactory; @Override public Set getTableName() { @@ -66,22 +72,41 @@ public class DataPermissionDefaultRule implements DataPermissionRule { @Override public Expression getExpression(String tableName, Alias tableAlias) { - // TODO: 2024/5/31 可访问的数据 @李龙 - List nodeIds = ListUtil.of(1L, 2L, 3L); - List personIds = ListUtil.of(110L, 223L); + Optional matchDataObjectOptional = this.matchRule(); + if (!matchDataObjectOptional.isPresent() || CollectionUtils.isEmpty(matchDataObjectOptional.get().getRules())) { + log.warn("no match data rule, dataPermissionContext:{}", JSONObject.toJSONString(DataPermissionContextHolder.get())); + return EXPRESSION_NULL; + } + + MatchDataObjectResp matchDataObject = matchDataObjectOptional.get(); + + Optional dataObjectRuleContextOpt = matchRuleFactory.matchAndResolve(matchDataObject); + + if (!dataObjectRuleContextOpt.isPresent()) { + return EXPRESSION_NULL; + } + + DataObjectRule.DataObjectRuleContext dataObjectRuleContext = dataObjectRuleContextOpt.get(); + + Set nodeIds = dataObjectRuleContext.getNodeIds(); + Set personIds = dataObjectRuleContext.getPersonIds(); Expression deptExpression = buildExpression(tableName, tableAlias, nodeIds); Expression userExpression = buildExpression(tableName, tableAlias, personIds); + if (deptExpression == null && userExpression == null) { // 未获取到数据权限 返回NULL 不查询数据 return EXPRESSION_NULL; } + if (deptExpression == null) { return userExpression; } + if (userExpression == null) { return deptExpression; } + // 如果两个都有,用or WHERE (organizational_Node_id IN ? OR person_id in ?) return new Parenthesis(new OrExpression(deptExpression, userExpression)); @@ -96,7 +121,7 @@ public class DataPermissionDefaultRule implements DataPermissionRule { * @param ids 可能是nodeids 也可以是personIds * @return */ - private Expression buildExpression(String tableName, Alias tableAlias, List ids) { + private Expression buildExpression(String tableName, Alias tableAlias, Set ids) { // 如果不存在配置,则无需作为条件 String columnName = nodeTable.get(tableName); if (!StringUtils.hasText(columnName)) { @@ -133,15 +158,6 @@ public class DataPermissionDefaultRule implements DataPermissionRule { tableName.add(tableInfo.getTableName()); } - /** - * 添加组织节点所对应的字段 字段默认使用organizational_node_id - * - * @param entityClass 表所对应的entity - */ - public void addNodeColumn(Class> entityClass) { - addNodeColumn(entityClass, DEFAULT_NODE); - } - /** * 添加personId所对应的字段 * @@ -157,12 +173,34 @@ public class DataPermissionDefaultRule implements DataPermissionRule { tableName.add(tableInfo.getTableName()); } - /** - * 字段默认使用person_id - * - * @param entityClass 表所对应的entity - */ - public void addPersonColumn(Class> entityClass) { - addPersonColumn(entityClass, DEFAULT_PERSON); + private Optional matchRule() { + + if (invalidContext()) { + return Optional.empty(); + } + + DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.get(); + + MatchDataObjectReq matchDataObjectReq = MatchDataObjectReq.builder() + .dataObjectCode(dataPermissionContext.getDataPermission().bizCode()) + .ouId(dataPermissionContext.getOuId()) + .workspaceId(dataPermissionContext.getWorkspaceId()) + .personId(dataPermissionContext.getPersonId()) + .build(); + + return Optional.ofNullable(dataObjectApi.match(matchDataObjectReq).getData()); + } + + private boolean invalidContext() { + + DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.get(); + + return dataPermissionContext == null + || dataPermissionContext.getDataPermission() == null + || StringsUtil.isBlank(dataPermissionContext.getDataPermission().bizCode()) + || !dataPermissionContext.getDataPermission().enable() + || dataPermissionContext.getOuId() == null + || dataPermissionContext.getWorkspaceId() == null + || dataPermissionContext.getPersonId() == null; } } diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/rule/StringsUtil.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/rule/StringsUtil.java new file mode 100644 index 0000000..87d1a20 --- /dev/null +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/rule/StringsUtil.java @@ -0,0 +1,27 @@ +package cn.axzo.framework.datapermission.rule; + +public class StringsUtil { + + public static boolean isNotBlank(CharSequence cs) { + return !isBlank(cs); + } + + public static boolean isBlank(CharSequence cs) { + int strLen = length(cs); + if (strLen == 0) { + return true; + } else { + for(int i = 0; i < strLen; ++i) { + if (!Character.isWhitespace(cs.charAt(i))) { + return false; + } + } + + return true; + } + } + + public static int length(CharSequence cs) { + return cs == null ? 0 : cs.length(); + } +} From 0ca36efddae42707097fd1651a9433b1930c50ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E6=98=86=E9=B9=8F?= Date: Thu, 6 Jun 2024 14:54:44 +0800 Subject: [PATCH 04/27] =?UTF-8?q?feat(REQ-2300)=EF=BC=9A=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E6=9D=83=E9=99=90=E4=B8=8A=E4=B8=8B=E6=96=87=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E7=BC=93=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../framework/datapermission/annotation/DataPermission.java | 6 ++++++ .../datapermission/context/DataPermissionContextHolder.java | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/annotation/DataPermission.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/annotation/DataPermission.java index 5704da2..751e7e7 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/annotation/DataPermission.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/annotation/DataPermission.java @@ -3,11 +3,17 @@ package cn.axzo.framework.datapermission.annotation; import cn.axzo.framework.datapermission.rule.OrgDefaultRule; import cn.axzo.framework.datapermission.rule.DataPermissionRule; +import java.lang.annotation.*; + /** * 数据权限注解 * @author tanjie@axzo.cn * @date 2024/5/30 17:57 */ +@Inherited +@Documented +@Target({ElementType.METHOD, ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) public @interface DataPermission { boolean enable() default true; diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextHolder.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextHolder.java index 99abfce..4f79267 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextHolder.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextHolder.java @@ -1,6 +1,7 @@ package cn.axzo.framework.datapermission.context; import cn.axzo.framework.datapermission.annotation.DataPermission; +import cn.axzo.karma.client.feign.tyr.response.MatchDataObjectResp; import com.google.common.collect.Maps; import lombok.AllArgsConstructor; import lombok.Builder; @@ -67,6 +68,11 @@ public class DataPermissionContextHolder { public void putPermissionData(String key, Object value) { permissionDataCache.put(key, value); } + + /** + * 数据权限匹配结果 + */ + private MatchDataObjectResp matchDataObjectResp; } public static void remove() { From 2d06b6a4fe7e8ebe067512a8204056465a42b168 Mon Sep 17 00:00:00 2001 From: lilong Date: Thu, 13 Jun 2024 10:28:44 +0800 Subject: [PATCH 05/27] =?UTF-8?q?feat=EF=BC=9A(REQ-2300)=20=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E6=8A=8A=E4=B8=8A=E4=B8=8B=E6=96=87=E6=94=BE=E8=87=B3?= =?UTF-8?q?header=E5=92=8C=E4=BB=8Eheader=E8=A7=A3=E6=9E=90=E6=94=BE?= =?UTF-8?q?=E7=BD=AE=E4=B8=8A=E4=B8=8B=E6=96=87=E7=9A=84=E6=8B=A6=E6=88=AA?= =?UTF-8?q?=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../annotation/DataPermission.java | 9 ++ .../aop/DataPermissionFeignInterceptor.java | 27 ++++++ .../aop/DataPermissionFilter.java | 22 ++--- .../aop/ResolveDataPermissionRuleFilter.java | 93 +++++++++++++++++++ .../context/DataPermissionContextHolder.java | 57 ++++-------- .../dataObject/DataObjectRule.java | 65 ------------- .../DepartmentAndSubordinateRule.java | 79 ---------------- .../dataObject/DepartmentOnlyRule.java | 58 ------------ .../dataObject/MatchRuleFactory.java | 38 -------- .../dataObject/SelfAndSubordinateRule.java | 82 ---------------- .../dataObject/SelfOnlyRule.java | 28 ------ .../dataObject/UnitAllSubordinateRule.java | 58 ------------ .../UnitCooperateSubordinateRule.java | 58 ------------ .../dataObject/UnitDirectSubordinateRule.java | 58 ------------ .../dataObject/UnitOnlyExcludeTeamRule.java | 57 ------------ .../dataObject/UnitOnlyRule.java | 58 ------------ .../dataObject/WorkspaceRule.java | 58 ------------ .../datapermission/rule/OrgDefaultRule.java | 60 ++---------- .../datapermission/rule/StringsUtil.java | 27 ------ 19 files changed, 164 insertions(+), 828 deletions(-) create mode 100644 axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionFeignInterceptor.java create mode 100644 axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/ResolveDataPermissionRuleFilter.java delete mode 100644 axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/DataObjectRule.java delete mode 100644 axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/DepartmentAndSubordinateRule.java delete mode 100644 axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/DepartmentOnlyRule.java delete mode 100644 axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/MatchRuleFactory.java delete mode 100644 axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/SelfAndSubordinateRule.java delete mode 100644 axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/SelfOnlyRule.java delete mode 100644 axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/UnitAllSubordinateRule.java delete mode 100644 axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/UnitCooperateSubordinateRule.java delete mode 100644 axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/UnitDirectSubordinateRule.java delete mode 100644 axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/UnitOnlyExcludeTeamRule.java delete mode 100644 axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/UnitOnlyRule.java delete mode 100644 axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/WorkspaceRule.java delete mode 100644 axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/rule/StringsUtil.java diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/annotation/DataPermission.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/annotation/DataPermission.java index 751e7e7..45fc458 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/annotation/DataPermission.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/annotation/DataPermission.java @@ -17,8 +17,17 @@ import java.lang.annotation.*; public @interface DataPermission { boolean enable() default true; + /** + * 持久层使用规则解析组装数据权限的sql参数 + * 只有在提供sql查询的服务才会生效使用 + * @return + */ Class includeRule() default OrgDefaultRule.class; + /** + * 数据权限数据对象code + * @return + */ String bizCode() default ""; } diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionFeignInterceptor.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionFeignInterceptor.java new file mode 100644 index 0000000..1a07007 --- /dev/null +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionFeignInterceptor.java @@ -0,0 +1,27 @@ +package cn.axzo.framework.datapermission.aop; + +import cn.axzo.framework.datapermission.context.DataPermissionContextHolder; +import com.alibaba.fastjson.JSONObject; +import feign.RequestInterceptor; +import feign.RequestTemplate; +import org.springframework.stereotype.Component; + +import static cn.axzo.framework.datapermission.context.DataPermissionContextHolder.DATA_PERMISSION_HEADER; + +/** + * 上下文中有DataPermissionContext,则把数据放在header中 + */ +@Component +public class DataPermissionFeignInterceptor implements RequestInterceptor { + + @Override + public void apply(RequestTemplate requestTemplate) { + + DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.get(); + if (dataPermissionContext == null) { + return; + } + + requestTemplate.header(DATA_PERMISSION_HEADER, JSONObject.toJSONString(dataPermissionContext)); + } +} diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionFilter.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionFilter.java index 56a2001..b274a4c 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionFilter.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionFilter.java @@ -1,11 +1,11 @@ package cn.axzo.framework.datapermission.aop; -import cn.axzo.framework.auth.domain.ContextInfo; -import cn.axzo.framework.auth.domain.ContextInfoHolder; import cn.axzo.framework.datapermission.annotation.DataPermission; import cn.axzo.framework.datapermission.context.DataPermissionContextHolder; +import com.alibaba.fastjson.JSONObject; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.BooleanUtils; +import org.apache.commons.lang3.StringUtils; import org.springframework.core.annotation.Order; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerInterceptor; @@ -13,8 +13,10 @@ import org.springframework.web.servlet.HandlerInterceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import static cn.axzo.framework.datapermission.context.DataPermissionContextHolder.DATA_PERMISSION_HEADER; + /** - * + * 从header中获取数据权限的数据,并放置在上下文中 * @author tanjie@axzo.cn * @date 2024/5/31 16:37 */ @@ -42,18 +44,14 @@ public class DataPermissionFilter implements HandlerInterceptor { return true; } - DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.DataPermissionContext.builder() - .dataPermission(dataPermission) - .build(); + String dataPermissionHeader = request.getHeader(DATA_PERMISSION_HEADER); - // 有数据权限注解,但没用户信息,让后面拦截器做处理更合理(可以返回空数据或者不阻塞业务正常查询数据) - ContextInfo contextInfo = ContextInfoHolder.get(); - if (contextInfo != null) { - dataPermissionContext.setWorkspaceId(contextInfo.getWorkspaceId()); - dataPermissionContext.setOuId(contextInfo.getOuId()); - dataPermissionContext.setPersonId(contextInfo.getUserInfo().getPersonId()); + if (StringUtils.isBlank(dataPermissionHeader)) { + return true; } + DataPermissionContextHolder.DataPermissionContext dataPermissionContext = JSONObject.parseObject(dataPermissionHeader, DataPermissionContextHolder.DataPermissionContext.class); + DataPermissionContextHolder.setContext(dataPermissionContext); } return true; diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/ResolveDataPermissionRuleFilter.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/ResolveDataPermissionRuleFilter.java new file mode 100644 index 0000000..ece3064 --- /dev/null +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/ResolveDataPermissionRuleFilter.java @@ -0,0 +1,93 @@ +package cn.axzo.framework.datapermission.aop; + +import cn.axzo.framework.auth.domain.ContextInfo; +import cn.axzo.framework.auth.domain.ContextInfoHolder; +import cn.axzo.framework.datapermission.annotation.DataPermission; +import cn.axzo.framework.datapermission.context.DataPermissionContextHolder; +import cn.axzo.karma.client.feign.tyr.DataObjectApi; +import cn.axzo.karma.client.feign.tyr.request.MatchDataObjectReq; +import cn.axzo.karma.client.feign.tyr.response.MatchDataObjectResp; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.BooleanUtils; +import org.springframework.core.annotation.Order; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.HandlerInterceptor; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.Optional; + +/** + * 解析数据权限规则,把解析后的数据放置在上下文中DataPermissionContext + */ +@Order(2) +@Slf4j +@RequiredArgsConstructor +public class ResolveDataPermissionRuleFilter implements HandlerInterceptor { + + private final DataObjectApi dataObjectApi; + + /** + * 拦截@DataPermission + * 设置DataPermissionContext + * @param request + * @param response + * @param handler + * @return + * @throws Exception + */ + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) + throws Exception { + if (handler instanceof HandlerMethod) { + + HandlerMethod handlerMethod = (HandlerMethod) handler; + DataPermission dataPermission = handlerMethod.getMethodAnnotation(DataPermission.class); + if (dataPermission == null || BooleanUtils.isNotTrue(dataPermission.enable())) { + return true; + } + + ContextInfo contextInfo = ContextInfoHolder.get(); + if (contextInfo == null || contextInfo.getUserInfo() == null) { + return true; + } + + Optional matchDataObjectOptional = this.matchRule(dataPermission); + if (!matchDataObjectOptional.isPresent()) { + log.warn("no match data rule, bizCode:{}, personId:{}, ouId:{}, workspaceId:{}", + dataPermission.bizCode(), + contextInfo.getUserInfo().getPersonId(), + contextInfo.getOuId(), + contextInfo.getWorkspaceId()); + return true; + } + + DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.DataPermissionContext.builder() + .dataPermission(dataPermission) + .workspaceId(contextInfo.getWorkspaceId()) + .ouId(contextInfo.getOuId()) + .personId(contextInfo.getUserInfo().getPersonId()) + .dataPermissionNodeIds(matchDataObjectOptional.get().getNodeIds()) + .dataPermissionPersonIds(matchDataObjectOptional.get().getPersonIds()) + .build(); + + DataPermissionContextHolder.setContext(dataPermissionContext); + } + return true; + } + + private Optional matchRule(DataPermission dataPermission) { + + ContextInfo contextInfo = ContextInfoHolder.get(); + + MatchDataObjectReq matchDataObjectReq = MatchDataObjectReq.builder() + .dataObjectCode(dataPermission.bizCode()) + .ouId(contextInfo.getOuId()) + .workspaceId(contextInfo.getWorkspaceId()) + .personId(contextInfo.getUserInfo().getPersonId()) + .build(); + + return Optional.ofNullable(dataObjectApi.match(matchDataObjectReq).getData()); + } +} diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextHolder.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextHolder.java index 4f79267..9c75848 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextHolder.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextHolder.java @@ -1,14 +1,12 @@ package cn.axzo.framework.datapermission.context; import cn.axzo.framework.datapermission.annotation.DataPermission; -import cn.axzo.karma.client.feign.tyr.response.MatchDataObjectResp; -import com.google.common.collect.Maps; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; -import java.util.Map; +import java.util.Set; /** * 数据权限上下文 @@ -18,17 +16,9 @@ import java.util.Map; */ public class DataPermissionContextHolder { - private final static ThreadLocal DATA_PERMISSION_CONTEXT = new ThreadLocal<>(); + public static final String DATA_PERMISSION_HEADER = "dataPermission"; - public static final String SELF_SUBORDINATE = "SELF_SUBORDINATE"; - public static final String DEPARTMENT_ONLY = "DEPARTMENT_ONLY"; - public static final String DEPARTMENT_SUBORDINATE = "DEPARTMENT_SUBORDINATE"; - public static final String UNIT_ONLY = "UNIT_ONLY"; - public static final String UNIT_ONLY_EXCLUDE_TEAM = "UNIT_ONLY_EXCLUDE_TEAM"; - public static final String UNIT_DIRECT_SUBORDINATE = "UNIT_DIRECT_SUBORDINATE"; - public static final String UNIT_COOPERATE_SUBORDINATE = "UNIT_COOPERATE_SUBORDINATE"; - public static final String UNIT_ALL_SUBORDINATE = "UNIT_ALL_SUBORDINATE"; - public static final String WORKSPACE = "WORKSPACE"; + private final static ThreadLocal DATA_PERMISSION_CONTEXT = new ThreadLocal<>(); public static void setContext(DataPermissionContext dataPermission) { DATA_PERMISSION_CONTEXT.set(dataPermission); @@ -41,38 +31,31 @@ public class DataPermissionContextHolder { @AllArgsConstructor public static class DataPermissionContext { private DataPermission dataPermission; + + /** + * 当前单位id + */ private Long ouId; + + /** + * 当前项目id + */ private Long workspaceId; + + /** + * 登录人 + */ private Long personId; /** - * 数据权限cache - * key < - > cn.axzo.tyr.client.common.enums.RowPermissionEnum || cn.axzo.tyr.client.common.enums.AttrPermissionEnum 的名字 - * value < - > 规则校验需要的数据 - * - * 描述 | key | value结构和描述 - * 本人及下属数据 | SELF_SUBORDINATE | List本人及下属的personId列表 - * 仅本部门数据 | DEPARTMENT_ONLY | List本部门的organizationalNodeId(单个)列表 - * 本部门及以下数据 | DEPARTMENT_SUBORDINATE | List本部门及子孙级的organizationalNodeIds列表 - * 仅本单位数据(包含班组) | UNIT_ONLY | List本单位数据(包含班组)的organizationalNodeIds列表 - * 仅本单位数据(不包含班组) | UNIT_ONLY_EXCLUDE_TEAM | List本单位数据(不包含班组)的organizationalNodeIds列表 - * 本单位及下级直属单位数据 | UNIT_DIRECT_SUBORDINATE | List本单位及下级直属单位的organizationalNodeIds列表 - * 本单位及下级协同(直属+合作)单位数据 | UNIT_COOPERATE_SUBORDINATE | List本单位及下级协同(直属+合作)单位的organizationalNodeIds列表 - * 本单位及以下协同(直属+合作)单位数据 | UNIT_ALL_SUBORDINATE | List本单位及以下协同(直属+合作)单位的organizationalNodeIds列表 - * 本项目部数据 | WORKSPACE | List本项目部的workspaceId(单个)列表 - * 同行级数据权限 | EQUAL_TO_ROW | todo 是否不放缓存 - * + * 解析后的人员id */ - private Map permissionDataCache = Maps.newConcurrentMap(); - - public void putPermissionData(String key, Object value) { - permissionDataCache.put(key, value); - } + private Set dataPermissionPersonIds; /** - * 数据权限匹配结果 + * 解析后的部门id */ - private MatchDataObjectResp matchDataObjectResp; + private Set dataPermissionNodeIds; } public static void remove() { @@ -82,7 +65,5 @@ public class DataPermissionContextHolder { public static DataPermissionContext get() { return DATA_PERMISSION_CONTEXT.get(); } - - } diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/DataObjectRule.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/DataObjectRule.java deleted file mode 100644 index 87f74d1..0000000 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/DataObjectRule.java +++ /dev/null @@ -1,65 +0,0 @@ -package cn.axzo.framework.datapermission.dataObject; - -import cn.axzo.karma.client.feign.tyr.response.MatchDataObjectResp; -import com.google.common.collect.Sets; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; -import org.springframework.util.CollectionUtils; - -import java.util.List; -import java.util.Objects; -import java.util.Set; - -public interface DataObjectRule { - - /** - * 解析规则,返回解析后的数据 - * @param context - * @return - */ - void resolve(DataObjectRuleContext context); - - /** - * 查询规则的id - * @return - */ - Integer getRulePermissionId(); - - @Data - @Builder - @AllArgsConstructor - @NoArgsConstructor - class DataObjectRuleContext { - - /** - * 解析后的人员id - */ - @Builder.Default - private Set personIds = Sets.newHashSet(); - - /** - * 解析后的部门id - */ - @Builder.Default - private Set nodeIds = Sets.newHashSet(); - - public void addPersonIds(Set personIds) { - this.getPersonIds().addAll(personIds); - } - - public void addNodeIds(Set nodeIds) { - this.getNodeIds().addAll(nodeIds); - } - } - - default boolean match(List rules) { - if (CollectionUtils.isEmpty(rules)) { - return false; - } - - return rules.stream() - .anyMatch(e -> Objects.equals(e.getRowPermission(), getRulePermissionId())); - } -} diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/DepartmentAndSubordinateRule.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/DepartmentAndSubordinateRule.java deleted file mode 100644 index f4f767b..0000000 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/DepartmentAndSubordinateRule.java +++ /dev/null @@ -1,79 +0,0 @@ -package cn.axzo.framework.datapermission.dataObject; - -import cn.axzo.framework.datapermission.context.DataPermissionContextHolder; -import cn.axzo.karma.client.feign.organization.OrganizationalNodeApi; -import cn.axzo.karma.client.feign.organization.request.PageOrganizationNodeReq; -import cn.axzo.karma.client.feign.organization.response.OrganizationalNodeResp; -import lombok.RequiredArgsConstructor; -import org.springframework.util.CollectionUtils; - -import java.util.Collection; -import java.util.List; -import java.util.Objects; -import java.util.Set; -import java.util.stream.Collectors; - -import static cn.axzo.framework.datapermission.context.DataPermissionContextHolder.DEPARTMENT_SUBORDINATE; - -@RequiredArgsConstructor -public class DepartmentAndSubordinateRule implements DataObjectRule { - - private final OrganizationalNodeApi organizationalNodeApi; - - /** - * 本部门及以下数据规则id - */ - private static final Integer RULE_PERMISSION_ID = 4; - - @Override - public Integer getRulePermissionId() { - return RULE_PERMISSION_ID; - } - - @Override - public void resolve(DataObjectRuleContext context) { - DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.get(); - - List nodes = organizationalNodeApi.page(PageOrganizationNodeReq.builder() - .personId(dataPermissionContext.getPersonId()) - .ouId(dataPermissionContext.getOuId()) - .needSubordinate(true) - .build()) - .getData() - .getData(); - - if (CollectionUtils.isEmpty(nodes)) { - return; - } - - Set nodeIds = nodes.stream() - .map(OrganizationalNodeResp::getId) - .filter(Objects::nonNull) - .collect(Collectors.toSet()); - - resolveNodes(nodeIds, nodes); - - dataPermissionContext.putPermissionData(DEPARTMENT_SUBORDINATE, nodeIds); - context.addNodeIds(nodeIds); - } - - private void resolveNodes(Set nodeIds, List nodes) { - if (CollectionUtils.isEmpty(nodes)) { - return; - } - - Set subordinateIds = nodes.stream() - .map(OrganizationalNodeResp::getSubordinateOuNodes) - .filter(Objects::nonNull) - .flatMap(Collection::stream) - .map(OrganizationalNodeResp::getId) - .filter(Objects::nonNull) - .collect(Collectors.toSet()); - if (CollectionUtils.isEmpty(subordinateIds)) { - return; - } - nodeIds.addAll(subordinateIds); - - nodes.forEach(e -> resolveNodes(nodeIds, e.getSubordinateOuNodes())); - } -} diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/DepartmentOnlyRule.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/DepartmentOnlyRule.java deleted file mode 100644 index 7dd12db..0000000 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/DepartmentOnlyRule.java +++ /dev/null @@ -1,58 +0,0 @@ -package cn.axzo.framework.datapermission.dataObject; - -import cn.axzo.framework.datapermission.context.DataPermissionContextHolder; -import cn.axzo.karma.client.feign.organization.OrganizationalNodeApi; -import cn.axzo.karma.client.feign.organization.request.PageOrganizationNodeReq; -import cn.axzo.karma.client.feign.organization.response.OrganizationalNodeResp; -import lombok.RequiredArgsConstructor; -import org.springframework.util.CollectionUtils; - -import java.util.List; -import java.util.Objects; -import java.util.Set; -import java.util.stream.Collectors; - -import static cn.axzo.framework.datapermission.context.DataPermissionContextHolder.DEPARTMENT_ONLY; - -/** - * 本部门数据规则 - */ -@RequiredArgsConstructor -public class DepartmentOnlyRule implements DataObjectRule { - - private final OrganizationalNodeApi organizationalNodeApi; - - /** - * 本部门数据规则id - */ - private static final Integer RULE_PERMISSION_ID = 3; - - @Override - public Integer getRulePermissionId() { - return RULE_PERMISSION_ID; - } - - @Override - public void resolve(DataObjectRuleContext context) { - DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.get(); - - List nodes = organizationalNodeApi.page(PageOrganizationNodeReq.builder() - .personId(dataPermissionContext.getPersonId()) - .ouId(dataPermissionContext.getOuId()) - .build()) - .getData() - .getData(); - - if (CollectionUtils.isEmpty(nodes)) { - return; - } - - Set nodeIds = nodes.stream() - .map(OrganizationalNodeResp::getId) - .filter(Objects::nonNull) - .collect(Collectors.toSet()); - - context.addNodeIds(nodeIds); - dataPermissionContext.putPermissionData(DEPARTMENT_ONLY, nodeIds); - } -} diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/MatchRuleFactory.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/MatchRuleFactory.java deleted file mode 100644 index f795c3f..0000000 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/MatchRuleFactory.java +++ /dev/null @@ -1,38 +0,0 @@ -package cn.axzo.framework.datapermission.dataObject; - -import cn.axzo.karma.client.feign.tyr.response.MatchDataObjectResp; -import lombok.AllArgsConstructor; -import org.springframework.util.CollectionUtils; - -import java.util.List; -import java.util.Objects; -import java.util.Optional; -import java.util.stream.Collectors; - -@AllArgsConstructor -public class MatchRuleFactory { - - private final List dataObjectRules; - - public Optional matchAndResolve(MatchDataObjectResp matchDataObjectResp) { - - if (Objects.isNull(matchDataObjectResp) || CollectionUtils.isEmpty(matchDataObjectResp.getRules())) { - return Optional.empty(); - } - - List matchedRules = dataObjectRules.stream() - .filter(e -> e.match(matchDataObjectResp.getRules())) - .collect(Collectors.toList()); - - if (CollectionUtils.isEmpty(matchedRules)) { - return Optional.empty(); - } - - DataObjectRule.DataObjectRuleContext dataObjectRuleContext = DataObjectRule.DataObjectRuleContext.builder().build(); - for (DataObjectRule matchedRule : matchedRules) { - matchedRule.resolve(dataObjectRuleContext); - } - - return Optional.ofNullable(dataObjectRuleContext); - } -} diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/SelfAndSubordinateRule.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/SelfAndSubordinateRule.java deleted file mode 100644 index f788bd5..0000000 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/SelfAndSubordinateRule.java +++ /dev/null @@ -1,82 +0,0 @@ -package cn.axzo.framework.datapermission.dataObject; - -import cn.axzo.framework.datapermission.context.DataPermissionContextHolder; -import cn.axzo.karma.client.feign.organization.OrganizationalNodeUserApi; -import cn.axzo.karma.client.feign.organization.request.PageOrganizationNodeUserReq; -import cn.axzo.karma.client.feign.organization.response.OrganizationalNodeUserResp; -import lombok.RequiredArgsConstructor; -import org.springframework.util.CollectionUtils; - -import java.util.Collection; -import java.util.List; -import java.util.Objects; -import java.util.Set; -import java.util.stream.Collectors; - -import static cn.axzo.framework.datapermission.context.DataPermissionContextHolder.SELF_SUBORDINATE; - -/** - * 本人及下属数据规则 - */ -@RequiredArgsConstructor -public class SelfAndSubordinateRule implements DataObjectRule { - - private final OrganizationalNodeUserApi organizationalNodeUserApi; - - /** - * 本人及下属数据规则id - */ - private static final Integer RULE_PERMISSION_ID = 2; - - @Override - public Integer getRulePermissionId() { - return RULE_PERMISSION_ID; - } - - @Override - public void resolve(DataObjectRuleContext context) { - DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.get(); - - List nodeUsers = organizationalNodeUserApi.page(PageOrganizationNodeUserReq.builder() - .personId(dataPermissionContext.getPersonId()) - .ouId(dataPermissionContext.getOuId()) - .needSubordinate(true) - .build()) - .getData() - .getData(); - - if (CollectionUtils.isEmpty(nodeUsers)) { - return; - } - - Set personIds = nodeUsers.stream() - .map(OrganizationalNodeUserResp::getPersonId) - .filter(Objects::nonNull) - .collect(Collectors.toSet()); - - resolveNodeUsers(personIds, nodeUsers); - - dataPermissionContext.putPermissionData(SELF_SUBORDINATE, personIds); - context.addPersonIds(personIds); - } - - private void resolveNodeUsers(Set personIds, List nodeUsers) { - if (CollectionUtils.isEmpty(nodeUsers)) { - return; - } - - Set subordinatePersonIds = nodeUsers.stream() - .map(OrganizationalNodeUserResp::getSubordinateOuNodeUsers) - .filter(Objects::nonNull) - .flatMap(Collection::stream) - .map(OrganizationalNodeUserResp::getPersonId) - .filter(Objects::nonNull) - .collect(Collectors.toSet()); - if (CollectionUtils.isEmpty(subordinatePersonIds)) { - return; - } - personIds.addAll(subordinatePersonIds); - - nodeUsers.forEach(e -> resolveNodeUsers(personIds, e.getSubordinateOuNodeUsers())); - } -} diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/SelfOnlyRule.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/SelfOnlyRule.java deleted file mode 100644 index c42d917..0000000 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/SelfOnlyRule.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.axzo.framework.datapermission.dataObject; - -import cn.axzo.framework.datapermission.context.DataPermissionContextHolder; -import com.google.common.collect.Sets; -import lombok.RequiredArgsConstructor; - -/** - * 仅本人数据规则 - */ -@RequiredArgsConstructor -public class SelfOnlyRule implements DataObjectRule { - - /** - * 仅本人数据的规则id - */ - private static final Integer RULE_PERMISSION_ID = 1; - - @Override - public Integer getRulePermissionId() { - return RULE_PERMISSION_ID; - } - - @Override - public void resolve(DataObjectRuleContext context) { - DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.get(); - context.addPersonIds(Sets.newHashSet(dataPermissionContext.getPersonId())); - } -} diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/UnitAllSubordinateRule.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/UnitAllSubordinateRule.java deleted file mode 100644 index 6011abf..0000000 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/UnitAllSubordinateRule.java +++ /dev/null @@ -1,58 +0,0 @@ -package cn.axzo.framework.datapermission.dataObject; - -import cn.axzo.framework.datapermission.context.DataPermissionContextHolder; -import cn.axzo.karma.client.feign.organization.OrganizationalNodeApi; -import cn.axzo.karma.client.feign.organization.request.QueryOuMultiConditionalReq; -import cn.axzo.karma.client.feign.organization.response.QueryOuMultiConditionalResp; -import lombok.RequiredArgsConstructor; -import org.springframework.util.CollectionUtils; - -import java.util.Objects; -import java.util.Set; -import java.util.stream.Collectors; - -import static cn.axzo.framework.datapermission.context.DataPermissionContextHolder.UNIT_ALL_SUBORDINATE; - -/** - * 本单位及以下协同(直属+合作)单位数据 - */ -@RequiredArgsConstructor -public class UnitAllSubordinateRule implements DataObjectRule { - - - private final OrganizationalNodeApi organizationalNodeApi; - - /** - * 本单位及以下协同(直属+合作)单位数据的规则id - */ - private static final Integer RULE_PERMISSION_ID = 8; - - @Override - public Integer getRulePermissionId() { - return RULE_PERMISSION_ID; - } - - @Override - public void resolve(DataObjectRuleContext context) { - DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.get(); - - QueryOuMultiConditionalResp node = organizationalNodeApi.queryOuMultiConditional(QueryOuMultiConditionalReq.builder() - .workspaceId(dataPermissionContext.getWorkspaceId()) - .ouId(dataPermissionContext.getOuId()) - .needDirectlyAndCooperateWithDescendant(true) - .build()) - .getData(); - - if (Objects.isNull(node) || CollectionUtils.isEmpty(node.getBasicNodeUsers())) { - return; - } - - Set nodeIds = node.getBasicNodeUsers().stream() - .map(QueryOuMultiConditionalResp.BasicNodeUser::getNodeId) - .filter(Objects::nonNull) - .collect(Collectors.toSet()); - - context.addNodeIds(nodeIds); - dataPermissionContext.putPermissionData(UNIT_ALL_SUBORDINATE, nodeIds); - } -} diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/UnitCooperateSubordinateRule.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/UnitCooperateSubordinateRule.java deleted file mode 100644 index e5ce279..0000000 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/UnitCooperateSubordinateRule.java +++ /dev/null @@ -1,58 +0,0 @@ -package cn.axzo.framework.datapermission.dataObject; - -import cn.axzo.framework.datapermission.context.DataPermissionContextHolder; -import cn.axzo.karma.client.feign.organization.OrganizationalNodeApi; -import cn.axzo.karma.client.feign.organization.request.QueryOuMultiConditionalReq; -import cn.axzo.karma.client.feign.organization.response.QueryOuMultiConditionalResp; -import lombok.RequiredArgsConstructor; -import org.springframework.util.CollectionUtils; - -import java.util.Objects; -import java.util.Set; -import java.util.stream.Collectors; - -import static cn.axzo.framework.datapermission.context.DataPermissionContextHolder.UNIT_COOPERATE_SUBORDINATE; - -/** - * 本单位及下级协同(直属+合作)单位数据 - */ -@RequiredArgsConstructor -public class UnitCooperateSubordinateRule implements DataObjectRule { - - - private final OrganizationalNodeApi organizationalNodeApi; - - /** - * 本单位及下级协同(直属+合作)单位数据的规则id - */ - private static final Integer RULE_PERMISSION_ID = 7; - - @Override - public Integer getRulePermissionId() { - return RULE_PERMISSION_ID; - } - - @Override - public void resolve(DataObjectRuleContext context) { - DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.get(); - - QueryOuMultiConditionalResp node = organizationalNodeApi.queryOuMultiConditional(QueryOuMultiConditionalReq.builder() - .workspaceId(dataPermissionContext.getWorkspaceId()) - .ouId(dataPermissionContext.getOuId()) - .needDirectlyAndCooperate(true) - .build()) - .getData(); - - if (Objects.isNull(node) || CollectionUtils.isEmpty(node.getBasicNodeUsers())) { - return; - } - - Set nodeIds = node.getBasicNodeUsers().stream() - .map(QueryOuMultiConditionalResp.BasicNodeUser::getNodeId) - .filter(Objects::nonNull) - .collect(Collectors.toSet()); - - context.addNodeIds(nodeIds); - dataPermissionContext.putPermissionData(UNIT_COOPERATE_SUBORDINATE, nodeIds); - } -} diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/UnitDirectSubordinateRule.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/UnitDirectSubordinateRule.java deleted file mode 100644 index d56f822..0000000 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/UnitDirectSubordinateRule.java +++ /dev/null @@ -1,58 +0,0 @@ -package cn.axzo.framework.datapermission.dataObject; - -import cn.axzo.framework.datapermission.context.DataPermissionContextHolder; -import cn.axzo.karma.client.feign.organization.OrganizationalNodeApi; -import cn.axzo.karma.client.feign.organization.request.QueryOuMultiConditionalReq; -import cn.axzo.karma.client.feign.organization.response.QueryOuMultiConditionalResp; -import lombok.RequiredArgsConstructor; -import org.springframework.util.CollectionUtils; - -import java.util.Objects; -import java.util.Set; -import java.util.stream.Collectors; - -import static cn.axzo.framework.datapermission.context.DataPermissionContextHolder.UNIT_DIRECT_SUBORDINATE; - -/** - * 本单位及下级直属单位数据 - */ -@RequiredArgsConstructor -public class UnitDirectSubordinateRule implements DataObjectRule { - - - private final OrganizationalNodeApi organizationalNodeApi; - - /** - * 本单位及下级直属单位数据的规则id - */ - private static final Integer RULE_PERMISSION_ID = 6; - - @Override - public Integer getRulePermissionId() { - return RULE_PERMISSION_ID; - } - - @Override - public void resolve(DataObjectRuleContext context) { - DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.get(); - - QueryOuMultiConditionalResp node = organizationalNodeApi.queryOuMultiConditional(QueryOuMultiConditionalReq.builder() - .workspaceId(dataPermissionContext.getWorkspaceId()) - .ouId(dataPermissionContext.getOuId()) - .needDirectlyUnder(true) - .build()) - .getData(); - - if (Objects.isNull(node) || CollectionUtils.isEmpty(node.getBasicNodeUsers())) { - return; - } - - Set nodeIds = node.getBasicNodeUsers().stream() - .map(QueryOuMultiConditionalResp.BasicNodeUser::getNodeId) - .filter(Objects::nonNull) - .collect(Collectors.toSet()); - - context.addNodeIds(nodeIds); - dataPermissionContext.putPermissionData(UNIT_DIRECT_SUBORDINATE, nodeIds); - } -} diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/UnitOnlyExcludeTeamRule.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/UnitOnlyExcludeTeamRule.java deleted file mode 100644 index 149bb9e..0000000 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/UnitOnlyExcludeTeamRule.java +++ /dev/null @@ -1,57 +0,0 @@ -package cn.axzo.framework.datapermission.dataObject; - -import cn.axzo.framework.datapermission.context.DataPermissionContextHolder; -import cn.axzo.karma.client.feign.organization.OrganizationalNodeApi; -import cn.axzo.karma.client.feign.organization.request.QueryOuMultiConditionalReq; -import cn.axzo.karma.client.feign.organization.response.QueryOuMultiConditionalResp; -import lombok.RequiredArgsConstructor; -import org.springframework.util.CollectionUtils; - -import java.util.Objects; -import java.util.Set; -import java.util.stream.Collectors; - -import static cn.axzo.framework.datapermission.context.DataPermissionContextHolder.UNIT_ONLY_EXCLUDE_TEAM; - -/** - * 仅本单位数据(不包含班组) - */ -@RequiredArgsConstructor -public class UnitOnlyExcludeTeamRule implements DataObjectRule { - - - private final OrganizationalNodeApi organizationalNodeApi; - - /** - * 仅本单位数据(不包含班组)的规则id - */ - private static final Integer RULE_PERMISSION_ID = 10; - - @Override - public Integer getRulePermissionId() { - return RULE_PERMISSION_ID; - } - - @Override - public void resolve(DataObjectRuleContext context) { - DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.get(); - - QueryOuMultiConditionalResp node = organizationalNodeApi.queryOuMultiConditional(QueryOuMultiConditionalReq.builder() - .workspaceId(dataPermissionContext.getWorkspaceId()) - .ouId(dataPermissionContext.getOuId()) - .build()) - .getData(); - - if (Objects.isNull(node) || CollectionUtils.isEmpty(node.getBasicNodeUsers())) { - return; - } - - Set nodeIds = node.getBasicNodeUsers().stream() - .map(QueryOuMultiConditionalResp.BasicNodeUser::getNodeId) - .filter(Objects::nonNull) - .collect(Collectors.toSet()); - - context.addNodeIds(nodeIds); - dataPermissionContext.putPermissionData(UNIT_ONLY_EXCLUDE_TEAM, nodeIds); - } -} diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/UnitOnlyRule.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/UnitOnlyRule.java deleted file mode 100644 index 8b827ff..0000000 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/UnitOnlyRule.java +++ /dev/null @@ -1,58 +0,0 @@ -package cn.axzo.framework.datapermission.dataObject; - -import cn.axzo.framework.datapermission.context.DataPermissionContextHolder; -import cn.axzo.karma.client.feign.organization.OrganizationalNodeApi; -import cn.axzo.karma.client.feign.organization.request.QueryOuMultiConditionalReq; -import cn.axzo.karma.client.feign.organization.response.QueryOuMultiConditionalResp; -import lombok.RequiredArgsConstructor; -import org.springframework.util.CollectionUtils; - -import java.util.Objects; -import java.util.Set; -import java.util.stream.Collectors; - -import static cn.axzo.framework.datapermission.context.DataPermissionContextHolder.UNIT_ONLY; - -/** - * 仅本单位数据(包含班组) - */ -@RequiredArgsConstructor -public class UnitOnlyRule implements DataObjectRule { - - - private final OrganizationalNodeApi organizationalNodeApi; - - /** - * 仅本单位数据(包含班组)的规则id - */ - private static final Integer RULE_PERMISSION_ID = 5; - - @Override - public Integer getRulePermissionId() { - return RULE_PERMISSION_ID; - } - - @Override - public void resolve(DataObjectRuleContext context) { - DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.get(); - - QueryOuMultiConditionalResp node = organizationalNodeApi.queryOuMultiConditional(QueryOuMultiConditionalReq.builder() - .workspaceId(dataPermissionContext.getWorkspaceId()) - .ouId(dataPermissionContext.getOuId()) - .needTeam(true) - .build()) - .getData(); - - if (Objects.isNull(node) || CollectionUtils.isEmpty(node.getBasicNodeUsers())) { - return; - } - - Set nodeIds = node.getBasicNodeUsers().stream() - .map(QueryOuMultiConditionalResp.BasicNodeUser::getNodeId) - .filter(Objects::nonNull) - .collect(Collectors.toSet()); - - context.addNodeIds(nodeIds); - dataPermissionContext.putPermissionData(UNIT_ONLY, nodeIds); - } -} diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/WorkspaceRule.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/WorkspaceRule.java deleted file mode 100644 index 3c418b0..0000000 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/dataObject/WorkspaceRule.java +++ /dev/null @@ -1,58 +0,0 @@ -package cn.axzo.framework.datapermission.dataObject; - -import cn.axzo.framework.datapermission.context.DataPermissionContextHolder; -import cn.axzo.karma.client.feign.organization.OrganizationalNodeApi; -import cn.axzo.karma.client.feign.organization.request.PageOrganizationNodeReq; -import cn.axzo.karma.client.feign.organization.response.OrganizationalNodeResp; -import lombok.RequiredArgsConstructor; -import org.springframework.util.CollectionUtils; - -import java.util.List; -import java.util.Objects; -import java.util.Set; -import java.util.stream.Collectors; - -import static cn.axzo.framework.datapermission.context.DataPermissionContextHolder.WORKSPACE; - -/** - * 本项目部数据 - */ -@RequiredArgsConstructor -public class WorkspaceRule implements DataObjectRule { - - - private final OrganizationalNodeApi organizationalNodeApi; - - /** - * 本项目部数据的规则id - */ - private static final Integer RULE_PERMISSION_ID = 9; - - @Override - public Integer getRulePermissionId() { - return RULE_PERMISSION_ID; - } - - @Override - public void resolve(DataObjectRuleContext context) { - DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.get(); - - List nodes = organizationalNodeApi.page(PageOrganizationNodeReq.builder() - .workspaceId(dataPermissionContext.getWorkspaceId()) - .build()) - .getData() - .getData(); - - if (CollectionUtils.isEmpty(nodes)) { - return; - } - - Set nodeIds = nodes.stream() - .map(OrganizationalNodeResp::getId) - .filter(Objects::nonNull) - .collect(Collectors.toSet()); - - context.addNodeIds(nodeIds); - dataPermissionContext.putPermissionData(WORKSPACE, nodeIds); - } -} diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/rule/OrgDefaultRule.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/rule/OrgDefaultRule.java index 7783a1b..e0129be 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/rule/OrgDefaultRule.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/rule/OrgDefaultRule.java @@ -1,12 +1,7 @@ package cn.axzo.framework.datapermission.rule; import cn.axzo.framework.datapermission.context.DataPermissionContextHolder; -import cn.axzo.framework.datapermission.dataObject.DataObjectRule; -import cn.axzo.framework.datapermission.dataObject.MatchRuleFactory; import cn.axzo.karma.client.feign.tyr.DataObjectApi; -import cn.axzo.karma.client.feign.tyr.request.MatchDataObjectReq; -import cn.axzo.karma.client.feign.tyr.response.MatchDataObjectResp; -import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.metadata.TableInfo; import com.baomidou.mybatisplus.core.metadata.TableInfoHelper; import com.baomidou.mybatisplus.core.toolkit.StringPool; @@ -28,7 +23,6 @@ import org.springframework.util.StringUtils; import java.util.HashSet; import java.util.Map; -import java.util.Optional; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; @@ -62,8 +56,6 @@ public class OrgDefaultRule implements DataPermissionRule { private final DataObjectApi dataObjectApi; - private final MatchRuleFactory matchRuleFactory; - @Override public Set getTableName() { return tableName; @@ -72,24 +64,15 @@ public class OrgDefaultRule implements DataPermissionRule { @Override public Expression getExpression(String tableName, Alias tableAlias) { - Optional matchDataObjectOptional = this.matchRule(); - if (!matchDataObjectOptional.isPresent() || CollectionUtils.isEmpty(matchDataObjectOptional.get().getRules())) { - log.warn("no match data rule, dataPermissionContext:{}", JSONObject.toJSONString(DataPermissionContextHolder.get())); + DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.get(); + + if (dataPermissionContext == null) { + log.warn("not found dataPermissionContext"); return EXPRESSION_NULL; } - MatchDataObjectResp matchDataObject = matchDataObjectOptional.get(); - - Optional dataObjectRuleContextOpt = matchRuleFactory.matchAndResolve(matchDataObject); - - if (!dataObjectRuleContextOpt.isPresent()) { - return EXPRESSION_NULL; - } - - DataObjectRule.DataObjectRuleContext dataObjectRuleContext = dataObjectRuleContextOpt.get(); - - Set nodeIds = dataObjectRuleContext.getNodeIds(); - Set personIds = dataObjectRuleContext.getPersonIds(); + Set nodeIds = dataPermissionContext.getDataPermissionNodeIds(); + Set personIds = dataPermissionContext.getDataPermissionPersonIds(); Expression deptExpression = buildExpression(tableName, tableAlias, nodeIds); Expression userExpression = buildExpression(tableName, tableAlias, personIds); @@ -172,35 +155,4 @@ public class OrgDefaultRule implements DataPermissionRule { personTable.put(tableInfo.getTableName(), columnName); tableName.add(tableInfo.getTableName()); } - - private Optional matchRule() { - - if (invalidContext()) { - return Optional.empty(); - } - - DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.get(); - - MatchDataObjectReq matchDataObjectReq = MatchDataObjectReq.builder() - .dataObjectCode(dataPermissionContext.getDataPermission().bizCode()) - .ouId(dataPermissionContext.getOuId()) - .workspaceId(dataPermissionContext.getWorkspaceId()) - .personId(dataPermissionContext.getPersonId()) - .build(); - - return Optional.ofNullable(dataObjectApi.match(matchDataObjectReq).getData()); - } - - private boolean invalidContext() { - - DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.get(); - - return dataPermissionContext == null - || dataPermissionContext.getDataPermission() == null - || StringsUtil.isBlank(dataPermissionContext.getDataPermission().bizCode()) - || !dataPermissionContext.getDataPermission().enable() - || dataPermissionContext.getOuId() == null - || dataPermissionContext.getWorkspaceId() == null - || dataPermissionContext.getPersonId() == null; - } } diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/rule/StringsUtil.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/rule/StringsUtil.java deleted file mode 100644 index 87d1a20..0000000 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/rule/StringsUtil.java +++ /dev/null @@ -1,27 +0,0 @@ -package cn.axzo.framework.datapermission.rule; - -public class StringsUtil { - - public static boolean isNotBlank(CharSequence cs) { - return !isBlank(cs); - } - - public static boolean isBlank(CharSequence cs) { - int strLen = length(cs); - if (strLen == 0) { - return true; - } else { - for(int i = 0; i < strLen; ++i) { - if (!Character.isWhitespace(cs.charAt(i))) { - return false; - } - } - - return true; - } - } - - public static int length(CharSequence cs) { - return cs == null ? 0 : cs.length(); - } -} From 9771a5affa60f8e7c3abe18edf38d9ccf8ea69b4 Mon Sep 17 00:00:00 2001 From: lilong Date: Thu, 13 Jun 2024 14:35:51 +0800 Subject: [PATCH 06/27] =?UTF-8?q?feat=EF=BC=9A(REQ-2300)=20=E4=B8=8A?= =?UTF-8?q?=E4=B8=8B=E6=96=87=E4=B8=AD=E5=A2=9E=E5=8A=A0resultKey?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../aop/DataPermissionFilter.java | 13 +++++++++--- .../aop/ResolveDataPermissionRuleFilter.java | 20 +++++++++++++------ .../context/DataPermissionContextHolder.java | 5 +++++ 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionFilter.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionFilter.java index b274a4c..7caf6e2 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionFilter.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionFilter.java @@ -6,9 +6,11 @@ import com.alibaba.fastjson.JSONObject; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; -import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerInterceptor; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -20,9 +22,9 @@ import static cn.axzo.framework.datapermission.context.DataPermissionContextHold * @author tanjie@axzo.cn * @date 2024/5/31 16:37 */ -@Order(2) +@Component @Slf4j -public class DataPermissionFilter implements HandlerInterceptor { +public class DataPermissionFilter implements HandlerInterceptor, WebMvcConfigurer { /** * 拦截@DataPermission @@ -56,4 +58,9 @@ public class DataPermissionFilter implements HandlerInterceptor { } return true; } + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(this); + } } diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/ResolveDataPermissionRuleFilter.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/ResolveDataPermissionRuleFilter.java index ece3064..c32139d 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/ResolveDataPermissionRuleFilter.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/ResolveDataPermissionRuleFilter.java @@ -7,12 +7,14 @@ import cn.axzo.framework.datapermission.context.DataPermissionContextHolder; import cn.axzo.karma.client.feign.tyr.DataObjectApi; import cn.axzo.karma.client.feign.tyr.request.MatchDataObjectReq; import cn.axzo.karma.client.feign.tyr.response.MatchDataObjectResp; -import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.BooleanUtils; -import org.springframework.core.annotation.Order; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerInterceptor; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -21,12 +23,12 @@ import java.util.Optional; /** * 解析数据权限规则,把解析后的数据放置在上下文中DataPermissionContext */ -@Order(2) +@Component @Slf4j -@RequiredArgsConstructor -public class ResolveDataPermissionRuleFilter implements HandlerInterceptor { +public class ResolveDataPermissionRuleFilter implements HandlerInterceptor, WebMvcConfigurer { - private final DataObjectApi dataObjectApi; + @Autowired + private DataObjectApi dataObjectApi; /** * 拦截@DataPermission @@ -70,6 +72,7 @@ public class ResolveDataPermissionRuleFilter implements HandlerInterceptor { .personId(contextInfo.getUserInfo().getPersonId()) .dataPermissionNodeIds(matchDataObjectOptional.get().getNodeIds()) .dataPermissionPersonIds(matchDataObjectOptional.get().getPersonIds()) + .resultKey(matchDataObjectOptional.get().getResultKey()) .build(); DataPermissionContextHolder.setContext(dataPermissionContext); @@ -90,4 +93,9 @@ public class ResolveDataPermissionRuleFilter implements HandlerInterceptor { return Optional.ofNullable(dataObjectApi.match(matchDataObjectReq).getData()); } + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(this); + } } diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextHolder.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextHolder.java index 9c75848..56a3d6e 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextHolder.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextHolder.java @@ -56,6 +56,11 @@ public class DataPermissionContextHolder { * 解析后的部门id */ private Set dataPermissionNodeIds; + + /** + * 匹配的解析规则放在redis中的key + */ + private String resultKey; } public static void remove() { From 0198b168743640a637cef6932021ba24b61bdc2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E6=98=86=E9=B9=8F?= Date: Thu, 13 Jun 2024 15:29:04 +0800 Subject: [PATCH 07/27] =?UTF-8?q?feat(REQ-2300)=EF=BC=9A=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E6=9D=83=E9=99=90=E8=BF=94=E5=9B=9E=E6=95=B0=E6=8D=AE=E5=A4=84?= =?UTF-8?q?=E7=90=86Advice=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DataPermissionResponseBodyAdvice.java | 94 +++++++++++++ .../DataPermissionResponseExecutor.java | 123 ++++++++++++++++++ .../annotation/DataPermission.java | 11 ++ .../framework/datapermission/util/DPUtil.java | 36 +++++ .../datapermission/util/RpcInternalUtil.java | 62 +++++++++ 5 files changed, 326 insertions(+) create mode 100644 axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseBodyAdvice.java create mode 100644 axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseExecutor.java create mode 100644 axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/util/DPUtil.java create mode 100644 axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/util/RpcInternalUtil.java diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseBodyAdvice.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseBodyAdvice.java new file mode 100644 index 0000000..f056ef2 --- /dev/null +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseBodyAdvice.java @@ -0,0 +1,94 @@ +package cn.axzo.framework.datapermission.advice; + +import cn.axzo.framework.datapermission.annotation.DataPermission; +import cn.axzo.framework.datapermission.context.DataPermissionContextHolder; +import cn.axzo.framework.datapermission.util.DPUtil; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.extern.slf4j.Slf4j; +import org.springframework.core.MethodParameter; +import org.springframework.core.annotation.Order; +import org.springframework.http.MediaType; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.server.ServerHttpRequest; +import org.springframework.http.server.ServerHttpResponse; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; + +import java.util.Objects; + +/** + * @author likunpeng + * @version 1.0 + * @date 2024/6/7 + */ +@Slf4j +@Order(-9) +@RestControllerAdvice(annotations = RestController.class) +public class DataPermissionResponseBodyAdvice implements ResponseBodyAdvice { + + private final ObjectMapper objectMapper; + private final DataPermissionResponseExecutor dataPermissionResponseExecutor; + + public DataPermissionResponseBodyAdvice(ObjectMapper objectMapper, DataPermissionResponseExecutor dataPermissionResponseExecutor) { + log.debug("Add ResponseBodyAdvice: DataPermissionResponseBodyAdvice"); + this.objectMapper = objectMapper; + this.dataPermissionResponseExecutor = dataPermissionResponseExecutor; + } + + @Override + public boolean supports(MethodParameter returnType, Class> converterType) { + DataPermission dataPermission = returnType.getDeclaringClass().getAnnotation(DataPermission.class); + if (dataPermission != null) { + return dataPermission.enable(); + } else { + dataPermission = returnType.getMethodAnnotation(DataPermission.class); + return dataPermission != null && dataPermission.enable(); + } + } + + @Override + public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { + if (body == null || DPUtil.inIgnoreClass(body.getClass())) { + return body; + } + try { + JsonNode node = objectMapper.valueToTree(body); + JsonNode dataNode = getDataOrPageData(node); + if (Objects.isNull(dataNode)) { + log.warn("api result has no data element"); + return body; + } + if (!dataNode.isContainerNode()) { + log.warn("api result is not object or array"); + return body; + } + DataPermissionContextHolder.DataPermissionContext context = DataPermissionContextHolder.get(); + if (Objects.isNull(context) || Objects.isNull(context.getPersonId())) { + log.warn("threadLocal hos not DataPermissionContext or no personId"); + return body; + } + + dataPermissionResponseExecutor.processNode(context, dataNode); + } catch (Exception e) { + log.error("DataPermissionResponseBodyAdvice error", e); + } + + // 最终清除ThreadLocal的内容 + DataPermissionContextHolder.remove(); + return body; + } + + public JsonNode getDataOrPageData(JsonNode body) { + if (body.has("data")) { + JsonNode data = body.get("data"); + // 分页数据获取 + if (data.has("list") && data.has("page") && data.get("list").isArray()) { + return data.get("list"); + } + return body.get("data"); + } + return null; + } +} diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseExecutor.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseExecutor.java new file mode 100644 index 0000000..fd89177 --- /dev/null +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseExecutor.java @@ -0,0 +1,123 @@ +package cn.axzo.framework.datapermission.advice; + +import cn.axzo.framework.datapermission.annotation.DataPermission; +import cn.axzo.framework.datapermission.context.DataPermissionContextHolder; +import cn.axzo.framework.datapermission.util.RpcInternalUtil; +import cn.axzo.karma.client.feign.tyr.DataObjectApi; +import cn.axzo.karma.client.feign.tyr.request.ExamineDpColumnsReq; +import cn.axzo.karma.client.feign.tyr.response.ExamineDpColumnsResp; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.google.common.collect.Lists; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.MapUtils; +import org.springframework.stereotype.Component; + +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * @author likunpeng + * @version 1.0 + * @date 2024/6/7 + */ +@Slf4j +@Component +public class DataPermissionResponseExecutor { + + private static final Integer ATTRIBUTE_ISUNMASKABLE = 2; + private static final Integer ATTRIBUTE_ISEDITABLE = 2; + private static final String ATTRIBUTE_ADD_ALLOW_EDIT_PREFIX = "dp_allow_edit_"; + + private final DataObjectApi dataObjectApi; + + public DataPermissionResponseExecutor(DataObjectApi dataObjectApi) { + this.dataObjectApi = dataObjectApi; + } + + + public void processNode(DataPermissionContextHolder.DataPermissionContext context, JsonNode dataNode) { + DataPermission dataPermission = context.getDataPermission(); + List orgNodeIdAndPersonIds = Lists.newArrayList(); + recursiveGetOrgNodeIdAndPersonIds(dataPermission, dataNode, orgNodeIdAndPersonIds); + if (CollectionUtils.isEmpty(orgNodeIdAndPersonIds)) { + log.warn("api result has no organizationalNodeId and personId, not examine data permission for result columns."); + return; + } + ExamineDpColumnsReq request = ExamineDpColumnsReq.builder() + .resultKey(context.getResultKey()) + .ouId(context.getOuId()) + .personId(context.getPersonId()) + .workspaceId(context.getWorkspaceId()) + .build(); + // 调用karma获取数据列的校验结果 + ExamineDpColumnsResp examineDpColumnsResp = RpcInternalUtil.rpcProcessor(() -> dataObjectApi.examineDpColumns(request), "data permission processNode", request).getData(); + if (Objects.isNull(examineDpColumnsResp) || MapUtils.isEmpty(examineDpColumnsResp.getAttributeDpResultMap())) { + return; + } + // 根据karma数据列的校验结果,处理api结果的数据对象 + recursiveGetOrgNodeIdAndPersonIds(dataPermission, dataNode, examineDpColumnsResp.getAttributeDpResultMap()); + } + + private void recursiveGetOrgNodeIdAndPersonIds(DataPermission dataPermission, JsonNode dataNode, List orgNodeIdAndPersonIds) { + if (dataNode.isObject()) { + Long resultOrganizationalNodeId = Objects.nonNull(dataNode.get(dataPermission.key_organizationalNodeId())) ? dataNode.get(dataPermission.key_organizationalNodeId()).asLong() : 0L; + Long resultPersonId = Objects.nonNull(dataNode.get(dataPermission.key_personId())) ? dataNode.get(dataPermission.key_personId()).asLong() : 0L; + if (resultOrganizationalNodeId.equals(0L) && resultPersonId.equals(0L)) { + return; + } + orgNodeIdAndPersonIds.add(ExamineDpColumnsReq.OrgNodeIdAndPersonId.builder().organizationalNodeId(resultOrganizationalNodeId).personId(resultPersonId).build()); + } + if (dataNode.isArray()) { + ArrayNode arrayNode = (ArrayNode) dataNode; + Iterator elements = arrayNode.elements(); + while (elements.hasNext()) { + JsonNode element = elements.next(); + recursiveGetOrgNodeIdAndPersonIds(dataPermission, element, orgNodeIdAndPersonIds); + } + } + } + + private void recursiveGetOrgNodeIdAndPersonIds(DataPermission dataPermission, JsonNode dataNode, + Map> attributeDpResultMap) { + if (dataNode.isObject()) { + Long resultOrganizationalNodeId = Objects.nonNull(dataNode.get(dataPermission.key_organizationalNodeId())) ? dataNode.get(dataPermission.key_organizationalNodeId()).asLong() : 0L; + Long resultPersonId = Objects.nonNull(dataNode.get(dataPermission.key_personId())) ? dataNode.get(dataPermission.key_personId()).asLong() : 0L; + if (resultOrganizationalNodeId.equals(0L) && resultPersonId.equals(0L)) { + return; + } + + Map attributeMap = attributeDpResultMap.get(resultOrganizationalNodeId + "_" + resultPersonId); + if (MapUtils.isEmpty(attributeMap)) { + return; + } + + for (Map.Entry entry : attributeMap.entrySet()) { + ExamineDpColumnsResp.AttributePermissionBasicDTO basic = entry.getValue(); + if (dataNode.has(basic.getAttrCode())) { + if (!ATTRIBUTE_ISUNMASKABLE.equals(basic.getIsUnmaskable())) { + ObjectNode objectNode = (ObjectNode) dataNode; + objectNode.remove(basic.getAttrCode()); + } + if (Objects.nonNull(basic.getIsEditable())) { + ObjectNode objectNode = (ObjectNode) dataNode; + objectNode.put(ATTRIBUTE_ADD_ALLOW_EDIT_PREFIX + basic.getAttrCode(), ATTRIBUTE_ISEDITABLE.equals(basic.getIsEditable())); + } + } + } + } + + if (dataNode.isArray()) { + ArrayNode arrayNode = (ArrayNode) dataNode; + Iterator elements = arrayNode.elements(); + while (elements.hasNext()) { + JsonNode element = elements.next(); + recursiveGetOrgNodeIdAndPersonIds(dataPermission, element, attributeDpResultMap); + } + } + } +} diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/annotation/DataPermission.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/annotation/DataPermission.java index 45fc458..48f6a54 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/annotation/DataPermission.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/annotation/DataPermission.java @@ -30,4 +30,15 @@ public @interface DataPermission { */ String bizCode() default ""; + /** + * ApiResult返回的机构节点的ID + * @return + */ + String key_organizationalNodeId() default "organizationalNodeId"; + /** + * ApiResult返回的用户的ID + * @return + */ + String key_personId() default "personId"; + } diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/util/DPUtil.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/util/DPUtil.java new file mode 100644 index 0000000..d884500 --- /dev/null +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/util/DPUtil.java @@ -0,0 +1,36 @@ +package cn.axzo.framework.datapermission.util; + +import java.math.BigDecimal; +import java.util.HashSet; +import java.util.Set; + +/** + * @author likunpeng + * @version 1.0 + * @date 2024/6/6 + */ +public class DPUtil { + + /** + * 忽略的class列表 + */ + public static final Set> IGNORE_CLASS = new HashSet<>(); + + static { + // initIgnoreClass + IGNORE_CLASS.add(Byte.class); + IGNORE_CLASS.add(Short.class); + IGNORE_CLASS.add(Integer.class); + IGNORE_CLASS.add(Long.class); + IGNORE_CLASS.add(Float.class); + IGNORE_CLASS.add(BigDecimal.class); + IGNORE_CLASS.add(Double.class); + IGNORE_CLASS.add(Boolean.class); + IGNORE_CLASS.add(Character.class); + IGNORE_CLASS.add(String.class); + } + + public static boolean inIgnoreClass(Class cls) { + return IGNORE_CLASS.contains(cls); + } +} diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/util/RpcInternalUtil.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/util/RpcInternalUtil.java new file mode 100644 index 0000000..bb40353 --- /dev/null +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/util/RpcInternalUtil.java @@ -0,0 +1,62 @@ +package cn.axzo.framework.datapermission.util; + +import cn.axzo.basics.common.util.AssertUtil; +import cn.axzo.foundation.result.ApiResult; +import cn.axzo.framework.domain.ServiceException; +import cn.hutool.core.date.StopWatch; +import cn.hutool.core.lang.Assert; +import cn.hutool.json.JSONUtil; +import lombok.extern.slf4j.Slf4j; + +import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; +import java.util.function.Supplier; + +/** + * @author likunpeng + * @version 1.0 + * @date 2024/6/7 + */ +@Slf4j +public class RpcInternalUtil { + + /** + * 常用的RPC请求返回值解析,如果 被请求方 返回非200会抛出异常 + */ + public static ApiResult rpcProcessor(Supplier> supplier, String operationType, Object... param) { + + return rpcProcessorMayThrow(supplier, operationType, (msg) -> { + throw new ServiceException(msg); + }, param); + } + + public static ApiResult rpcProcessorMayThrow(Supplier> supplier, String operationType, Consumer throwConsumer, Object... param) { + AssertUtil.notNull(throwConsumer, "自定义的异常处理不可为空"); + log.info(operationType + "-Param: " + JSONUtil.toJsonStr(param)); + ApiResult result = null; + + try { + result = printLatency(supplier, operationType); + } catch (Throwable e) { + log.warn("rpc process error:{}", e.getMessage()); + throwConsumer.accept("服务调用异常"); + } + + log.info(operationType + "-Result: " + JSONUtil.toJsonStr(result)); + Assert.notNull(result, "服务调用异常"); + // 200自定义处理 + if (!result.isSuccess()) { + throwConsumer.accept(result.getMsg()); + } + return result; + } + + public static R printLatency(Supplier< R> function,String optType) { + StopWatch stopWatch = new StopWatch(optType); + stopWatch.start(optType); + R r = function.get(); + stopWatch.stop(); + log.info(stopWatch.shortSummary(TimeUnit.MILLISECONDS)); + return r; + } +} From f82f85f8fe63042f74715fc0186a8f6ab738d985 Mon Sep 17 00:00:00 2001 From: lilong Date: Thu, 13 Jun 2024 16:25:21 +0800 Subject: [PATCH 08/27] =?UTF-8?q?feat=EF=BC=9A(REQ-2300)=20=E6=8A=8A?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E6=9D=83=E9=99=90=E7=9A=84=E6=B3=A8=E8=A7=A3?= =?UTF-8?q?=E5=88=86=E4=B8=A4=E4=B8=AA=EF=BC=8C=E4=B8=80=E4=B8=AA=E9=A2=84?= =?UTF-8?q?=E5=88=B6=E6=95=B0=E6=8D=AE=EF=BC=8C=E4=B8=80=E4=B8=AA=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=E6=95=B0=E6=8D=AE=EF=BC=8C=E6=96=B9=E4=BE=BF=E6=8B=A6?= =?UTF-8?q?=E6=88=AA=E5=99=A8=E5=81=9A=E5=AE=9A=E5=88=B6=E6=8B=A6=E6=88=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DataPermissionResponseBodyAdvice.java | 18 ++--- .../DataPermissionResponseExecutor.java | 28 +++---- .../annotation/DataPermission.java | 33 +++------ .../annotation/DataPermissionPrepare.java | 34 +++++++++ .../aop/DataPermissionFeignInterceptor.java | 9 ++- ...er.java => DataPermissionInterceptor.java} | 13 ++-- .../aop/DataPermissionMybatisInterceptor.java | 37 +++++----- ... => DataPermissionPrepareInterceptor.java} | 25 ++++--- .../config/DataPermissionConfig.java | 4 +- .../context/DataPermissionContextFactory.java | 10 +-- .../context/DataPermissionContextHolder.java | 27 ------- .../DataPermissionPrepareContextHolder.java | 73 +++++++++++++++++++ ...le.java => DataPermissionRuleService.java} | 2 +- ...le.java => OrgDefaultRuleServiceImpl.java} | 12 +-- 14 files changed, 196 insertions(+), 129 deletions(-) create mode 100644 axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/annotation/DataPermissionPrepare.java rename axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/{DataPermissionFilter.java => DataPermissionInterceptor.java} (88%) rename axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/{ResolveDataPermissionRuleFilter.java => DataPermissionPrepareInterceptor.java} (76%) create mode 100644 axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionPrepareContextHolder.java rename axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/rule/{DataPermissionRule.java => DataPermissionRuleService.java} (87%) rename axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/rule/{OrgDefaultRule.java => OrgDefaultRuleServiceImpl.java} (90%) diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseBodyAdvice.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseBodyAdvice.java index f056ef2..c544536 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseBodyAdvice.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseBodyAdvice.java @@ -1,7 +1,7 @@ package cn.axzo.framework.datapermission.advice; -import cn.axzo.framework.datapermission.annotation.DataPermission; -import cn.axzo.framework.datapermission.context.DataPermissionContextHolder; +import cn.axzo.framework.datapermission.annotation.DataPermissionPrepare; +import cn.axzo.framework.datapermission.context.DataPermissionPrepareContextHolder; import cn.axzo.framework.datapermission.util.DPUtil; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; @@ -39,12 +39,12 @@ public class DataPermissionResponseBodyAdvice implements ResponseBodyAdvice> converterType) { - DataPermission dataPermission = returnType.getDeclaringClass().getAnnotation(DataPermission.class); - if (dataPermission != null) { - return dataPermission.enable(); + DataPermissionPrepare dataPermissionPrepare = returnType.getDeclaringClass().getAnnotation(DataPermissionPrepare.class); + if (dataPermissionPrepare != null) { + return dataPermissionPrepare.enable(); } else { - dataPermission = returnType.getMethodAnnotation(DataPermission.class); - return dataPermission != null && dataPermission.enable(); + dataPermissionPrepare = returnType.getMethodAnnotation(DataPermissionPrepare.class); + return dataPermissionPrepare != null && dataPermissionPrepare.enable(); } } @@ -64,7 +64,7 @@ public class DataPermissionResponseBodyAdvice implements ResponseBodyAdvice orgNodeIdAndPersonIds = Lists.newArrayList(); - recursiveGetOrgNodeIdAndPersonIds(dataPermission, dataNode, orgNodeIdAndPersonIds); + recursiveGetOrgNodeIdAndPersonIds(dataPermissionPrepare, dataNode, orgNodeIdAndPersonIds); if (CollectionUtils.isEmpty(orgNodeIdAndPersonIds)) { log.warn("api result has no organizationalNodeId and personId, not examine data permission for result columns."); return; @@ -60,13 +60,13 @@ public class DataPermissionResponseExecutor { return; } // 根据karma数据列的校验结果,处理api结果的数据对象 - recursiveGetOrgNodeIdAndPersonIds(dataPermission, dataNode, examineDpColumnsResp.getAttributeDpResultMap()); + recursiveGetOrgNodeIdAndPersonIds(dataPermissionPrepare, dataNode, examineDpColumnsResp.getAttributeDpResultMap()); } - private void recursiveGetOrgNodeIdAndPersonIds(DataPermission dataPermission, JsonNode dataNode, List orgNodeIdAndPersonIds) { + private void recursiveGetOrgNodeIdAndPersonIds(DataPermissionPrepare dataPermissionPrepare, JsonNode dataNode, List orgNodeIdAndPersonIds) { if (dataNode.isObject()) { - Long resultOrganizationalNodeId = Objects.nonNull(dataNode.get(dataPermission.key_organizationalNodeId())) ? dataNode.get(dataPermission.key_organizationalNodeId()).asLong() : 0L; - Long resultPersonId = Objects.nonNull(dataNode.get(dataPermission.key_personId())) ? dataNode.get(dataPermission.key_personId()).asLong() : 0L; + Long resultOrganizationalNodeId = Objects.nonNull(dataNode.get(dataPermissionPrepare.key_organizationalNodeId())) ? dataNode.get(dataPermissionPrepare.key_organizationalNodeId()).asLong() : 0L; + Long resultPersonId = Objects.nonNull(dataNode.get(dataPermissionPrepare.key_personId())) ? dataNode.get(dataPermissionPrepare.key_personId()).asLong() : 0L; if (resultOrganizationalNodeId.equals(0L) && resultPersonId.equals(0L)) { return; } @@ -77,16 +77,16 @@ public class DataPermissionResponseExecutor { Iterator elements = arrayNode.elements(); while (elements.hasNext()) { JsonNode element = elements.next(); - recursiveGetOrgNodeIdAndPersonIds(dataPermission, element, orgNodeIdAndPersonIds); + recursiveGetOrgNodeIdAndPersonIds(dataPermissionPrepare, element, orgNodeIdAndPersonIds); } } } - private void recursiveGetOrgNodeIdAndPersonIds(DataPermission dataPermission, JsonNode dataNode, + private void recursiveGetOrgNodeIdAndPersonIds(DataPermissionPrepare dataPermissionPrepare, JsonNode dataNode, Map> attributeDpResultMap) { if (dataNode.isObject()) { - Long resultOrganizationalNodeId = Objects.nonNull(dataNode.get(dataPermission.key_organizationalNodeId())) ? dataNode.get(dataPermission.key_organizationalNodeId()).asLong() : 0L; - Long resultPersonId = Objects.nonNull(dataNode.get(dataPermission.key_personId())) ? dataNode.get(dataPermission.key_personId()).asLong() : 0L; + Long resultOrganizationalNodeId = Objects.nonNull(dataNode.get(dataPermissionPrepare.key_organizationalNodeId())) ? dataNode.get(dataPermissionPrepare.key_organizationalNodeId()).asLong() : 0L; + Long resultPersonId = Objects.nonNull(dataNode.get(dataPermissionPrepare.key_personId())) ? dataNode.get(dataPermissionPrepare.key_personId()).asLong() : 0L; if (resultOrganizationalNodeId.equals(0L) && resultPersonId.equals(0L)) { return; } @@ -116,7 +116,7 @@ public class DataPermissionResponseExecutor { Iterator elements = arrayNode.elements(); while (elements.hasNext()) { JsonNode element = elements.next(); - recursiveGetOrgNodeIdAndPersonIds(dataPermission, element, attributeDpResultMap); + recursiveGetOrgNodeIdAndPersonIds(dataPermissionPrepare, element, attributeDpResultMap); } } } diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/annotation/DataPermission.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/annotation/DataPermission.java index 48f6a54..4a6ad8b 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/annotation/DataPermission.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/annotation/DataPermission.java @@ -1,20 +1,24 @@ package cn.axzo.framework.datapermission.annotation; -import cn.axzo.framework.datapermission.rule.OrgDefaultRule; -import cn.axzo.framework.datapermission.rule.DataPermissionRule; +import cn.axzo.framework.datapermission.rule.DataPermissionRuleService; +import cn.axzo.framework.datapermission.rule.OrgDefaultRuleServiceImpl; -import java.lang.annotation.*; +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; /** * 数据权限注解 - * @author tanjie@axzo.cn - * @date 2024/5/30 17:57 */ @Inherited @Documented @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface DataPermission { + boolean enable() default true; /** @@ -22,23 +26,6 @@ public @interface DataPermission { * 只有在提供sql查询的服务才会生效使用 * @return */ - Class includeRule() default OrgDefaultRule.class; - - /** - * 数据权限数据对象code - * @return - */ - String bizCode() default ""; - - /** - * ApiResult返回的机构节点的ID - * @return - */ - String key_organizationalNodeId() default "organizationalNodeId"; - /** - * ApiResult返回的用户的ID - * @return - */ - String key_personId() default "personId"; + Class includeRule() default OrgDefaultRuleServiceImpl.class; } diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/annotation/DataPermissionPrepare.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/annotation/DataPermissionPrepare.java new file mode 100644 index 0000000..b317b86 --- /dev/null +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/annotation/DataPermissionPrepare.java @@ -0,0 +1,34 @@ +package cn.axzo.framework.datapermission.annotation; + +import java.lang.annotation.*; + +/** + * 数据权限数据预制注解 + * @author tanjie@axzo.cn + * @date 2024/5/30 17:57 + */ +@Inherited +@Documented +@Target({ElementType.METHOD, ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +public @interface DataPermissionPrepare { + boolean enable() default true; + + /** + * 数据权限数据对象code + * @return + */ + String bizCode() default ""; + + /** + * ApiResult返回的机构节点的ID + * @return + */ + String key_organizationalNodeId() default "organizationalNodeId"; + /** + * ApiResult返回的用户的ID + * @return + */ + String key_personId() default "personId"; + +} diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionFeignInterceptor.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionFeignInterceptor.java index 1a07007..27e8ed9 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionFeignInterceptor.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionFeignInterceptor.java @@ -1,6 +1,7 @@ package cn.axzo.framework.datapermission.aop; import cn.axzo.framework.datapermission.context.DataPermissionContextHolder; +import cn.axzo.framework.datapermission.context.DataPermissionPrepareContextHolder; import com.alibaba.fastjson.JSONObject; import feign.RequestInterceptor; import feign.RequestTemplate; @@ -17,11 +18,15 @@ public class DataPermissionFeignInterceptor implements RequestInterceptor { @Override public void apply(RequestTemplate requestTemplate) { - DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.get(); - if (dataPermissionContext == null) { + DataPermissionPrepareContextHolder.DataPermissionPrepareContext dataPermissionPrepareContext = DataPermissionPrepareContextHolder.get(); + if (dataPermissionPrepareContext == null) { return; } + DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.DataPermissionContext.builder() + .dataPermissionNodeIds(dataPermissionPrepareContext.getDataPermissionNodeIds()) + .dataPermissionPersonIds(dataPermissionPrepareContext.getDataPermissionPersonIds()) + .build(); requestTemplate.header(DATA_PERMISSION_HEADER, JSONObject.toJSONString(dataPermissionContext)); } } diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionFilter.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionInterceptor.java similarity index 88% rename from axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionFilter.java rename to axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionInterceptor.java index 7caf6e2..28dcbf0 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionFilter.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionInterceptor.java @@ -4,7 +4,6 @@ import cn.axzo.framework.datapermission.annotation.DataPermission; import cn.axzo.framework.datapermission.context.DataPermissionContextHolder; import com.alibaba.fastjson.JSONObject; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Component; import org.springframework.web.method.HandlerMethod; @@ -24,7 +23,7 @@ import static cn.axzo.framework.datapermission.context.DataPermissionContextHold */ @Component @Slf4j -public class DataPermissionFilter implements HandlerInterceptor, WebMvcConfigurer { +public class DataPermissionInterceptor implements HandlerInterceptor, WebMvcConfigurer { /** * 拦截@DataPermission @@ -40,12 +39,6 @@ public class DataPermissionFilter implements HandlerInterceptor, WebMvcConfigure throws Exception { if (handler instanceof HandlerMethod) { - HandlerMethod handlerMethod = (HandlerMethod) handler; - DataPermission dataPermission = handlerMethod.getMethodAnnotation(DataPermission.class); - if (dataPermission == null || BooleanUtils.isNotTrue(dataPermission.enable())) { - return true; - } - String dataPermissionHeader = request.getHeader(DATA_PERMISSION_HEADER); if (StringUtils.isBlank(dataPermissionHeader)) { @@ -54,6 +47,10 @@ public class DataPermissionFilter implements HandlerInterceptor, WebMvcConfigure DataPermissionContextHolder.DataPermissionContext dataPermissionContext = JSONObject.parseObject(dataPermissionHeader, DataPermissionContextHolder.DataPermissionContext.class); + HandlerMethod handlerMethod = (HandlerMethod) handler; + DataPermission dataPermission = handlerMethod.getMethodAnnotation(DataPermission.class); + dataPermissionContext.setDataPermission(dataPermission); + DataPermissionContextHolder.setContext(dataPermissionContext); } return true; diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionMybatisInterceptor.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionMybatisInterceptor.java index cb03997..31ca079 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionMybatisInterceptor.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionMybatisInterceptor.java @@ -1,11 +1,11 @@ package cn.axzo.framework.datapermission.aop; import cn.axzo.framework.datapermission.annotation.DataPermission; +import cn.axzo.framework.datapermission.annotation.DataPermissionPrepare; import cn.axzo.framework.datapermission.context.DataPermissionContextFactory; import cn.axzo.framework.datapermission.context.DataPermissionContextHolder; -import cn.axzo.framework.datapermission.rule.DataPermissionRule; -import cn.axzo.karma.client.feign.tyr.response.MatchDataObjectResp; -import com.alibaba.fastjson.JSONObject; +import cn.axzo.framework.datapermission.context.DataPermissionPrepareContextHolder; +import cn.axzo.framework.datapermission.rule.DataPermissionRuleService; import com.baomidou.mybatisplus.core.parser.SqlParserHelper; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.baomidou.mybatisplus.core.toolkit.PluginUtils; @@ -139,15 +139,15 @@ public class DataPermissionMybatisInterceptor extends JsqlParserSupport implemen protected Expression andExpression(Table table, Expression where) { - DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.get(); - DataPermission dataPermission = dataPermissionContext.getDataPermission(); - List byDataPermission = dataPermissionContextFactory.getRuleByDataPermission(dataPermission); - Optional first = byDataPermission.stream().filter(rule -> rule.getTableName().contains(table.getName())).findFirst(); + DataPermissionPrepareContextHolder.DataPermissionPrepareContext dataPermissionPrepareContext = DataPermissionPrepareContextHolder.get(); + DataPermissionPrepare dataPermissionPrepare = dataPermissionPrepareContext.getDataPermissionPrepare(); + List byDataPermission = dataPermissionContextFactory.getRuleByDataPermission(dataPermissionPrepare); + Optional first = byDataPermission.stream().filter(rule -> rule.getTableName().contains(table.getName())).findFirst(); if (!first.isPresent()) { return where; } - DataPermissionRule dataPermissionRule = first.get(); - Expression ruleExpression = dataPermissionRule.getExpression(table.getName(), table.getAlias()); + DataPermissionRuleService dataPermissionRuleService = first.get(); + Expression ruleExpression = dataPermissionRuleService.getExpression(table.getName(), table.getAlias()); if (null != where) { if (where instanceof OrExpression) { @@ -296,13 +296,13 @@ public class DataPermissionMybatisInterceptor extends JsqlParserSupport implemen DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.get(); DataPermission dataPermission = dataPermissionContext.getDataPermission(); - List byDataPermission = dataPermissionContextFactory.getRuleByDataPermission(dataPermission); - Optional first = byDataPermission.stream().filter(rule -> rule.getTableName().contains(table.getName())).findFirst(); + List byDataPermission = dataPermissionContextFactory.getRuleByDataPermission(dataPermission); + Optional first = byDataPermission.stream().filter(rule -> rule.getTableName().contains(table.getName())).findFirst(); if (!first.isPresent()) { return currentExpression; } - DataPermissionRule dataPermissionRule = first.get(); - Expression ruleExpression = dataPermissionRule.getExpression(table.getName(), table.getAlias()); + DataPermissionRuleService dataPermissionRuleService = first.get(); + Expression ruleExpression = dataPermissionRuleService.getExpression(table.getName(), table.getAlias()); if (currentExpression == null) { return ruleExpression; } @@ -313,14 +313,11 @@ public class DataPermissionMybatisInterceptor extends JsqlParserSupport implemen } } - - - private boolean filter() { - DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.get(); - if (null == dataPermissionContext - || dataPermissionContext.getDataPermission() == null - || !dataPermissionContext.getDataPermission().enable()) { + DataPermissionPrepareContextHolder.DataPermissionPrepareContext dataPermissionPrepareContext = DataPermissionPrepareContextHolder.get(); + if (null == dataPermissionPrepareContext + || dataPermissionPrepareContext.getDataPermissionPrepare() == null + || !dataPermissionPrepareContext.getDataPermissionPrepare().enable()) { return false; } diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/ResolveDataPermissionRuleFilter.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionPrepareInterceptor.java similarity index 76% rename from axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/ResolveDataPermissionRuleFilter.java rename to axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionPrepareInterceptor.java index c32139d..f32ec61 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/ResolveDataPermissionRuleFilter.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionPrepareInterceptor.java @@ -2,13 +2,14 @@ package cn.axzo.framework.datapermission.aop; import cn.axzo.framework.auth.domain.ContextInfo; import cn.axzo.framework.auth.domain.ContextInfoHolder; -import cn.axzo.framework.datapermission.annotation.DataPermission; -import cn.axzo.framework.datapermission.context.DataPermissionContextHolder; +import cn.axzo.framework.datapermission.annotation.DataPermissionPrepare; +import cn.axzo.framework.datapermission.context.DataPermissionPrepareContextHolder; import cn.axzo.karma.client.feign.tyr.DataObjectApi; import cn.axzo.karma.client.feign.tyr.request.MatchDataObjectReq; import cn.axzo.karma.client.feign.tyr.response.MatchDataObjectResp; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.BooleanUtils; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.web.method.HandlerMethod; @@ -25,7 +26,7 @@ import java.util.Optional; */ @Component @Slf4j -public class ResolveDataPermissionRuleFilter implements HandlerInterceptor, WebMvcConfigurer { +public class DataPermissionPrepareInterceptor implements HandlerInterceptor, WebMvcConfigurer { @Autowired private DataObjectApi dataObjectApi; @@ -45,8 +46,8 @@ public class ResolveDataPermissionRuleFilter implements HandlerInterceptor, WebM if (handler instanceof HandlerMethod) { HandlerMethod handlerMethod = (HandlerMethod) handler; - DataPermission dataPermission = handlerMethod.getMethodAnnotation(DataPermission.class); - if (dataPermission == null || BooleanUtils.isNotTrue(dataPermission.enable())) { + DataPermissionPrepare dataPermissionPrepare = handlerMethod.getMethodAnnotation(DataPermissionPrepare.class); + if (dataPermissionPrepare == null || BooleanUtils.isNotTrue(dataPermissionPrepare.enable()) || StringUtils.isBlank(dataPermissionPrepare.bizCode())) { return true; } @@ -55,18 +56,18 @@ public class ResolveDataPermissionRuleFilter implements HandlerInterceptor, WebM return true; } - Optional matchDataObjectOptional = this.matchRule(dataPermission); + Optional matchDataObjectOptional = this.matchRule(dataPermissionPrepare); if (!matchDataObjectOptional.isPresent()) { log.warn("no match data rule, bizCode:{}, personId:{}, ouId:{}, workspaceId:{}", - dataPermission.bizCode(), + dataPermissionPrepare.bizCode(), contextInfo.getUserInfo().getPersonId(), contextInfo.getOuId(), contextInfo.getWorkspaceId()); return true; } - DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.DataPermissionContext.builder() - .dataPermission(dataPermission) + DataPermissionPrepareContextHolder.DataPermissionPrepareContext dataPermissionPrepareContext = DataPermissionPrepareContextHolder.DataPermissionPrepareContext.builder() + .dataPermissionPrepare(dataPermissionPrepare) .workspaceId(contextInfo.getWorkspaceId()) .ouId(contextInfo.getOuId()) .personId(contextInfo.getUserInfo().getPersonId()) @@ -75,17 +76,17 @@ public class ResolveDataPermissionRuleFilter implements HandlerInterceptor, WebM .resultKey(matchDataObjectOptional.get().getResultKey()) .build(); - DataPermissionContextHolder.setContext(dataPermissionContext); + DataPermissionPrepareContextHolder.setContext(dataPermissionPrepareContext); } return true; } - private Optional matchRule(DataPermission dataPermission) { + private Optional matchRule(DataPermissionPrepare dataPermissionPrepare) { ContextInfo contextInfo = ContextInfoHolder.get(); MatchDataObjectReq matchDataObjectReq = MatchDataObjectReq.builder() - .dataObjectCode(dataPermission.bizCode()) + .dataObjectCode(dataPermissionPrepare.bizCode()) .ouId(contextInfo.getOuId()) .workspaceId(contextInfo.getWorkspaceId()) .personId(contextInfo.getUserInfo().getPersonId()) diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/config/DataPermissionConfig.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/config/DataPermissionConfig.java index ceea116..015a57c 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/config/DataPermissionConfig.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/config/DataPermissionConfig.java @@ -2,7 +2,7 @@ package cn.axzo.framework.datapermission.config; import cn.axzo.framework.datapermission.aop.DataPermissionMybatisInterceptor; import cn.axzo.framework.datapermission.context.DataPermissionContextFactory; -import cn.axzo.framework.datapermission.rule.DataPermissionRule; +import cn.axzo.framework.datapermission.rule.DataPermissionRuleService; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.context.annotation.Bean; @@ -26,7 +26,7 @@ public class DataPermissionConfig { @Bean - public DataPermissionContextFactory dataPermissionRuleFactory(List rules) { + public DataPermissionContextFactory dataPermissionRuleFactory(List rules) { return new DataPermissionContextFactory(rules); } } diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextFactory.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextFactory.java index 5cc2dab..cb79d78 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextFactory.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextFactory.java @@ -1,7 +1,7 @@ package cn.axzo.framework.datapermission.context; import cn.axzo.framework.datapermission.annotation.DataPermission; -import cn.axzo.framework.datapermission.rule.DataPermissionRule; +import cn.axzo.framework.datapermission.rule.DataPermissionRuleService; import lombok.AllArgsConstructor; import java.util.List; @@ -15,15 +15,15 @@ import java.util.stream.Collectors; @AllArgsConstructor public class DataPermissionContextFactory { - List rules; + List rules; - public List getRules() { + public List getRules() { return rules; } - public List getRuleByDataPermission(DataPermission dataPermission) { - Class classes = dataPermission.includeRule(); + public List getRuleByDataPermission(DataPermission dataPermission) { + Class classes = dataPermission.includeRule(); return rules.stream().filter(rule -> Objects.equals(classes, rule.getClass())).collect(Collectors.toList()); } diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextHolder.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextHolder.java index 56a3d6e..ab3cc8a 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextHolder.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextHolder.java @@ -8,12 +8,6 @@ import lombok.NoArgsConstructor; import java.util.Set; -/** - * 数据权限上下文 - * - * @author tanjie@axzo.cn - * @date 2024/5/31 11:42 - */ public class DataPermissionContextHolder { public static final String DATA_PERMISSION_HEADER = "dataPermission"; @@ -32,21 +26,6 @@ public class DataPermissionContextHolder { public static class DataPermissionContext { private DataPermission dataPermission; - /** - * 当前单位id - */ - private Long ouId; - - /** - * 当前项目id - */ - private Long workspaceId; - - /** - * 登录人 - */ - private Long personId; - /** * 解析后的人员id */ @@ -56,11 +35,6 @@ public class DataPermissionContextHolder { * 解析后的部门id */ private Set dataPermissionNodeIds; - - /** - * 匹配的解析规则放在redis中的key - */ - private String resultKey; } public static void remove() { @@ -71,4 +45,3 @@ public class DataPermissionContextHolder { return DATA_PERMISSION_CONTEXT.get(); } } - diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionPrepareContextHolder.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionPrepareContextHolder.java new file mode 100644 index 0000000..b9e804c --- /dev/null +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionPrepareContextHolder.java @@ -0,0 +1,73 @@ +package cn.axzo.framework.datapermission.context; + +import cn.axzo.framework.datapermission.annotation.DataPermissionPrepare; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.Set; + +/** + * 数据权限上下文 + * + * @author tanjie@axzo.cn + * @date 2024/5/31 11:42 + */ +public class DataPermissionPrepareContextHolder { + + + private final static ThreadLocal DATA_PERMISSION_CONTEXT = new ThreadLocal<>(); + + public static void setContext(DataPermissionPrepareContext dataPermission) { + DATA_PERMISSION_CONTEXT.set(dataPermission); + } + + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class DataPermissionPrepareContext { + private DataPermissionPrepare dataPermissionPrepare; + + /** + * 当前单位id + */ + private Long ouId; + + /** + * 当前项目id + */ + private Long workspaceId; + + /** + * 登录人 + */ + private Long personId; + + /** + * 解析后的人员id + */ + private Set dataPermissionPersonIds; + + /** + * 解析后的部门id + */ + private Set dataPermissionNodeIds; + + /** + * 匹配的解析规则放在redis中的key + */ + private String resultKey; + } + + public static void remove() { + DATA_PERMISSION_CONTEXT.remove(); + } + + public static DataPermissionPrepareContext get() { + return DATA_PERMISSION_CONTEXT.get(); + } +} + diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/rule/DataPermissionRule.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/rule/DataPermissionRuleService.java similarity index 87% rename from axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/rule/DataPermissionRule.java rename to axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/rule/DataPermissionRuleService.java index 0a1d36a..a0a4d46 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/rule/DataPermissionRule.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/rule/DataPermissionRuleService.java @@ -9,7 +9,7 @@ import java.util.Set; * @author tanjie@axzo.cn * @date 2024/5/30 18:31 */ -public interface DataPermissionRule { +public interface DataPermissionRuleService { Set getTableName(); diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/rule/OrgDefaultRule.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/rule/OrgDefaultRuleServiceImpl.java similarity index 90% rename from axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/rule/OrgDefaultRule.java rename to axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/rule/OrgDefaultRuleServiceImpl.java index e0129be..d213404 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/rule/OrgDefaultRule.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/rule/OrgDefaultRuleServiceImpl.java @@ -1,6 +1,6 @@ package cn.axzo.framework.datapermission.rule; -import cn.axzo.framework.datapermission.context.DataPermissionContextHolder; +import cn.axzo.framework.datapermission.context.DataPermissionPrepareContextHolder; import cn.axzo.karma.client.feign.tyr.DataObjectApi; import com.baomidou.mybatisplus.core.metadata.TableInfo; import com.baomidou.mybatisplus.core.metadata.TableInfoHelper; @@ -35,7 +35,7 @@ import java.util.stream.Collectors; @Builder @RequiredArgsConstructor @Slf4j -public class OrgDefaultRule implements DataPermissionRule { +public class OrgDefaultRuleServiceImpl implements DataPermissionRuleService { static final Expression EXPRESSION_NULL = new NullValue(); private static final String DEFAULT_PERSON = "person_id"; @@ -64,15 +64,15 @@ public class OrgDefaultRule implements DataPermissionRule { @Override public Expression getExpression(String tableName, Alias tableAlias) { - DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.get(); + DataPermissionPrepareContextHolder.DataPermissionPrepareContext dataPermissionPrepareContext = DataPermissionPrepareContextHolder.get(); - if (dataPermissionContext == null) { + if (dataPermissionPrepareContext == null) { log.warn("not found dataPermissionContext"); return EXPRESSION_NULL; } - Set nodeIds = dataPermissionContext.getDataPermissionNodeIds(); - Set personIds = dataPermissionContext.getDataPermissionPersonIds(); + Set nodeIds = dataPermissionPrepareContext.getDataPermissionNodeIds(); + Set personIds = dataPermissionPrepareContext.getDataPermissionPersonIds(); Expression deptExpression = buildExpression(tableName, tableAlias, nodeIds); Expression userExpression = buildExpression(tableName, tableAlias, personIds); From dae702747d7d5a818c2f09301dba763172e372af Mon Sep 17 00:00:00 2001 From: lilong Date: Thu, 13 Jun 2024 17:11:22 +0800 Subject: [PATCH 09/27] =?UTF-8?q?feat=EF=BC=9A(REQ-2300)=20=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E6=9D=83=E9=99=90=E8=A7=A3=E6=9E=90=E7=9A=84=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E6=94=B9=E6=88=90=E4=BB=8Ekarma=E4=B8=AD=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2=EF=BC=8C=E5=87=8F=E5=B0=91io=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E9=87=8F=E5=92=8Cheader=E9=95=BF=E5=BA=A6=E6=8E=A7=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../aop/DataPermissionFeignInterceptor.java | 9 ++---- .../aop/DataPermissionInterceptor.java | 32 +++++++++++++++++-- .../aop/DataPermissionMybatisInterceptor.java | 7 ++-- .../aop/DataPermissionPrepareInterceptor.java | 10 ++++-- .../context/DataPermissionContextHolder.java | 4 +-- .../DataPermissionPrepareContextHolder.java | 12 ------- 6 files changed, 44 insertions(+), 30 deletions(-) diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionFeignInterceptor.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionFeignInterceptor.java index 27e8ed9..9a29f31 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionFeignInterceptor.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionFeignInterceptor.java @@ -1,8 +1,6 @@ package cn.axzo.framework.datapermission.aop; -import cn.axzo.framework.datapermission.context.DataPermissionContextHolder; import cn.axzo.framework.datapermission.context.DataPermissionPrepareContextHolder; -import com.alibaba.fastjson.JSONObject; import feign.RequestInterceptor; import feign.RequestTemplate; import org.springframework.stereotype.Component; @@ -23,10 +21,7 @@ public class DataPermissionFeignInterceptor implements RequestInterceptor { return; } - DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.DataPermissionContext.builder() - .dataPermissionNodeIds(dataPermissionPrepareContext.getDataPermissionNodeIds()) - .dataPermissionPersonIds(dataPermissionPrepareContext.getDataPermissionPersonIds()) - .build(); - requestTemplate.header(DATA_PERMISSION_HEADER, JSONObject.toJSONString(dataPermissionContext)); + // 存放缓存的key,是因为减少io数据量以及header有最大长度限制 + requestTemplate.header(DATA_PERMISSION_HEADER, dataPermissionPrepareContext.getResultKey()); } } diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionInterceptor.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionInterceptor.java index 28dcbf0..f1076d4 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionInterceptor.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionInterceptor.java @@ -2,9 +2,14 @@ package cn.axzo.framework.datapermission.aop; import cn.axzo.framework.datapermission.annotation.DataPermission; import cn.axzo.framework.datapermission.context.DataPermissionContextHolder; -import com.alibaba.fastjson.JSONObject; +import cn.axzo.framework.datapermission.util.RpcInternalUtil; +import cn.axzo.karma.client.feign.tyr.DataObjectApi; +import cn.axzo.karma.client.feign.tyr.request.GetMergeMatchDataReq; +import cn.axzo.karma.client.feign.tyr.response.MergeMatchDataResp; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerInterceptor; @@ -25,6 +30,10 @@ import static cn.axzo.framework.datapermission.context.DataPermissionContextHold @Slf4j public class DataPermissionInterceptor implements HandlerInterceptor, WebMvcConfigurer { + @Lazy + @Autowired + private DataObjectApi dataObjectApi; + /** * 拦截@DataPermission * 设置DataPermissionContext @@ -45,7 +54,7 @@ public class DataPermissionInterceptor implements HandlerInterceptor, WebMvcConf return true; } - DataPermissionContextHolder.DataPermissionContext dataPermissionContext = JSONObject.parseObject(dataPermissionHeader, DataPermissionContextHolder.DataPermissionContext.class); + DataPermissionContextHolder.DataPermissionContext dataPermissionContext = getCachedDataPermission(dataPermissionHeader); HandlerMethod handlerMethod = (HandlerMethod) handler; DataPermission dataPermission = handlerMethod.getMethodAnnotation(DataPermission.class); @@ -60,4 +69,23 @@ public class DataPermissionInterceptor implements HandlerInterceptor, WebMvcConf public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(this); } + + private DataPermissionContextHolder.DataPermissionContext getCachedDataPermission(String redisKey) { + + GetMergeMatchDataReq getMergeMatchDataReq = GetMergeMatchDataReq.builder() + .resultKey(redisKey) + .build(); + MergeMatchDataResp mergeMatchDataResp = RpcInternalUtil.rpcProcessor(() -> dataObjectApi.getCached(getMergeMatchDataReq), + "根据key查询数据权限规则的解析结果", getMergeMatchDataReq) + .getData(); + + DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.DataPermissionContext.builder().build(); + if (mergeMatchDataResp == null) { + return dataPermissionContext; + } + + dataPermissionContext.setNodeIds(mergeMatchDataResp.getNodeIds()); + dataPermissionContext.setPersonIds(mergeMatchDataResp.getPersonIds()); + return dataPermissionContext; + } } diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionMybatisInterceptor.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionMybatisInterceptor.java index 31ca079..39e73ca 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionMybatisInterceptor.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionMybatisInterceptor.java @@ -1,7 +1,6 @@ package cn.axzo.framework.datapermission.aop; import cn.axzo.framework.datapermission.annotation.DataPermission; -import cn.axzo.framework.datapermission.annotation.DataPermissionPrepare; import cn.axzo.framework.datapermission.context.DataPermissionContextFactory; import cn.axzo.framework.datapermission.context.DataPermissionContextHolder; import cn.axzo.framework.datapermission.context.DataPermissionPrepareContextHolder; @@ -139,9 +138,9 @@ public class DataPermissionMybatisInterceptor extends JsqlParserSupport implemen protected Expression andExpression(Table table, Expression where) { - DataPermissionPrepareContextHolder.DataPermissionPrepareContext dataPermissionPrepareContext = DataPermissionPrepareContextHolder.get(); - DataPermissionPrepare dataPermissionPrepare = dataPermissionPrepareContext.getDataPermissionPrepare(); - List byDataPermission = dataPermissionContextFactory.getRuleByDataPermission(dataPermissionPrepare); + DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.get(); + DataPermission dataPermission = dataPermissionContext.getDataPermission(); + List byDataPermission = dataPermissionContextFactory.getRuleByDataPermission(dataPermission); Optional first = byDataPermission.stream().filter(rule -> rule.getTableName().contains(table.getName())).findFirst(); if (!first.isPresent()) { return where; diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionPrepareInterceptor.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionPrepareInterceptor.java index f32ec61..46383c1 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionPrepareInterceptor.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionPrepareInterceptor.java @@ -4,6 +4,7 @@ import cn.axzo.framework.auth.domain.ContextInfo; import cn.axzo.framework.auth.domain.ContextInfoHolder; import cn.axzo.framework.datapermission.annotation.DataPermissionPrepare; import cn.axzo.framework.datapermission.context.DataPermissionPrepareContextHolder; +import cn.axzo.framework.datapermission.util.RpcInternalUtil; import cn.axzo.karma.client.feign.tyr.DataObjectApi; import cn.axzo.karma.client.feign.tyr.request.MatchDataObjectReq; import cn.axzo.karma.client.feign.tyr.response.MatchDataObjectResp; @@ -11,6 +12,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerInterceptor; @@ -28,6 +30,7 @@ import java.util.Optional; @Slf4j public class DataPermissionPrepareInterceptor implements HandlerInterceptor, WebMvcConfigurer { + @Lazy @Autowired private DataObjectApi dataObjectApi; @@ -71,8 +74,6 @@ public class DataPermissionPrepareInterceptor implements HandlerInterceptor, Web .workspaceId(contextInfo.getWorkspaceId()) .ouId(contextInfo.getOuId()) .personId(contextInfo.getUserInfo().getPersonId()) - .dataPermissionNodeIds(matchDataObjectOptional.get().getNodeIds()) - .dataPermissionPersonIds(matchDataObjectOptional.get().getPersonIds()) .resultKey(matchDataObjectOptional.get().getResultKey()) .build(); @@ -92,7 +93,10 @@ public class DataPermissionPrepareInterceptor implements HandlerInterceptor, Web .personId(contextInfo.getUserInfo().getPersonId()) .build(); - return Optional.ofNullable(dataObjectApi.match(matchDataObjectReq).getData()); + MatchDataObjectResp matchDataObjectResp = RpcInternalUtil.rpcProcessor(() -> dataObjectApi.match(matchDataObjectReq), + "匹配解析数据权限规则", matchDataObjectReq) + .getData(); + return Optional.ofNullable(matchDataObjectResp); } @Override diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextHolder.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextHolder.java index ab3cc8a..b55b74d 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextHolder.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextHolder.java @@ -29,12 +29,12 @@ public class DataPermissionContextHolder { /** * 解析后的人员id */ - private Set dataPermissionPersonIds; + private Set personIds; /** * 解析后的部门id */ - private Set dataPermissionNodeIds; + private Set nodeIds; } public static void remove() { diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionPrepareContextHolder.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionPrepareContextHolder.java index b9e804c..82c99ea 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionPrepareContextHolder.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionPrepareContextHolder.java @@ -6,8 +6,6 @@ import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; -import java.util.Set; - /** * 数据权限上下文 * @@ -46,16 +44,6 @@ public class DataPermissionPrepareContextHolder { */ private Long personId; - /** - * 解析后的人员id - */ - private Set dataPermissionPersonIds; - - /** - * 解析后的部门id - */ - private Set dataPermissionNodeIds; - /** * 匹配的解析规则放在redis中的key */ From 202c57700730f851d44b84f4e9b2bf171d5e77bf Mon Sep 17 00:00:00 2001 From: lilong Date: Thu, 13 Jun 2024 17:27:15 +0800 Subject: [PATCH 10/27] =?UTF-8?q?feat=EF=BC=9A(REQ-2300)=20=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E5=BA=93=E6=8B=A6=E6=88=AA=E5=99=A8=E6=9B=B4=E6=8D=A2?= =?UTF-8?q?=E4=B8=8A=E4=B8=8B=E6=96=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../datapermission/rule/OrgDefaultRuleServiceImpl.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/rule/OrgDefaultRuleServiceImpl.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/rule/OrgDefaultRuleServiceImpl.java index d213404..41467c4 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/rule/OrgDefaultRuleServiceImpl.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/rule/OrgDefaultRuleServiceImpl.java @@ -1,5 +1,6 @@ package cn.axzo.framework.datapermission.rule; +import cn.axzo.framework.datapermission.context.DataPermissionContextHolder; import cn.axzo.framework.datapermission.context.DataPermissionPrepareContextHolder; import cn.axzo.karma.client.feign.tyr.DataObjectApi; import com.baomidou.mybatisplus.core.metadata.TableInfo; @@ -64,15 +65,15 @@ public class OrgDefaultRuleServiceImpl implements DataPermissionRuleService { @Override public Expression getExpression(String tableName, Alias tableAlias) { - DataPermissionPrepareContextHolder.DataPermissionPrepareContext dataPermissionPrepareContext = DataPermissionPrepareContextHolder.get(); + DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.get(); - if (dataPermissionPrepareContext == null) { + if (dataPermissionContext == null) { log.warn("not found dataPermissionContext"); return EXPRESSION_NULL; } - Set nodeIds = dataPermissionPrepareContext.getDataPermissionNodeIds(); - Set personIds = dataPermissionPrepareContext.getDataPermissionPersonIds(); + Set nodeIds = dataPermissionContext.getNodeIds(); + Set personIds = dataPermissionContext.getPersonIds(); Expression deptExpression = buildExpression(tableName, tableAlias, nodeIds); Expression userExpression = buildExpression(tableName, tableAlias, personIds); From 0e9801177ce7494b8bcc1bdf09951ad4b249181f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E6=98=86=E9=B9=8F?= Date: Fri, 14 Jun 2024 09:41:20 +0800 Subject: [PATCH 11/27] =?UTF-8?q?feat(REQ-2300)=EF=BC=9A=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E6=9D=83=E9=99=90=E8=BF=94=E5=9B=9E=E6=95=B0=E6=8D=AE=E5=A4=84?= =?UTF-8?q?=E7=90=86Advice=E5=8A=9F=E8=83=BD=EF=BC=8C=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E5=AF=B9=E6=AF=8F=E4=B8=AA=E5=AD=90field=E7=9A=84=E9=80=92?= =?UTF-8?q?=E5=BD=92=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DataPermissionResponseExecutor.java | 61 +++++++++++-------- 1 file changed, 37 insertions(+), 24 deletions(-) diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseExecutor.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseExecutor.java index 5ec2816..a17094f 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseExecutor.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseExecutor.java @@ -60,17 +60,25 @@ public class DataPermissionResponseExecutor { return; } // 根据karma数据列的校验结果,处理api结果的数据对象 - recursiveGetOrgNodeIdAndPersonIds(dataPermissionPrepare, dataNode, examineDpColumnsResp.getAttributeDpResultMap()); + recursiveProcessOrgNodeIdAndPersonIds(dataPermissionPrepare, dataNode, examineDpColumnsResp.getAttributeDpResultMap()); } private void recursiveGetOrgNodeIdAndPersonIds(DataPermissionPrepare dataPermissionPrepare, JsonNode dataNode, List orgNodeIdAndPersonIds) { if (dataNode.isObject()) { Long resultOrganizationalNodeId = Objects.nonNull(dataNode.get(dataPermissionPrepare.key_organizationalNodeId())) ? dataNode.get(dataPermissionPrepare.key_organizationalNodeId()).asLong() : 0L; Long resultPersonId = Objects.nonNull(dataNode.get(dataPermissionPrepare.key_personId())) ? dataNode.get(dataPermissionPrepare.key_personId()).asLong() : 0L; - if (resultOrganizationalNodeId.equals(0L) && resultPersonId.equals(0L)) { - return; + if (!resultOrganizationalNodeId.equals(0L) || !resultPersonId.equals(0L)) { + orgNodeIdAndPersonIds.add(ExamineDpColumnsReq.OrgNodeIdAndPersonId.builder().organizationalNodeId(resultOrganizationalNodeId).personId(resultPersonId).build()); + } + // 循环处理子field + Iterator> fields = dataNode.fields(); + while (fields.hasNext()) { + Map.Entry entry = fields.next(); + JsonNode value = entry.getValue(); + if (value.isContainerNode()) { + recursiveGetOrgNodeIdAndPersonIds(dataPermissionPrepare, value, orgNodeIdAndPersonIds); + } } - orgNodeIdAndPersonIds.add(ExamineDpColumnsReq.OrgNodeIdAndPersonId.builder().organizationalNodeId(resultOrganizationalNodeId).personId(resultPersonId).build()); } if (dataNode.isArray()) { ArrayNode arrayNode = (ArrayNode) dataNode; @@ -82,31 +90,36 @@ public class DataPermissionResponseExecutor { } } - private void recursiveGetOrgNodeIdAndPersonIds(DataPermissionPrepare dataPermissionPrepare, JsonNode dataNode, + private void recursiveProcessOrgNodeIdAndPersonIds(DataPermissionPrepare dataPermissionPrepare, JsonNode dataNode, Map> attributeDpResultMap) { if (dataNode.isObject()) { Long resultOrganizationalNodeId = Objects.nonNull(dataNode.get(dataPermissionPrepare.key_organizationalNodeId())) ? dataNode.get(dataPermissionPrepare.key_organizationalNodeId()).asLong() : 0L; Long resultPersonId = Objects.nonNull(dataNode.get(dataPermissionPrepare.key_personId())) ? dataNode.get(dataPermissionPrepare.key_personId()).asLong() : 0L; - if (resultOrganizationalNodeId.equals(0L) && resultPersonId.equals(0L)) { - return; + if (!resultOrganizationalNodeId.equals(0L) || !resultPersonId.equals(0L)) { + Map attributeMap = attributeDpResultMap.get(resultOrganizationalNodeId + "_" + resultPersonId); + if (MapUtils.isNotEmpty(attributeMap)) { + for (Map.Entry entry : attributeMap.entrySet()) { + ExamineDpColumnsResp.AttributePermissionBasicDTO basic = entry.getValue(); + if (dataNode.has(basic.getAttrCode())) { + ObjectNode objectNode = (ObjectNode) dataNode; + if (!ATTRIBUTE_ISUNMASKABLE.equals(basic.getIsUnmaskable())) { + objectNode.remove(basic.getAttrCode()); + } + if (Objects.nonNull(basic.getIsEditable())) { + objectNode.put(ATTRIBUTE_ADD_ALLOW_EDIT_PREFIX + basic.getAttrCode(), ATTRIBUTE_ISEDITABLE.equals(basic.getIsEditable())); + } + } + } + } } - Map attributeMap = attributeDpResultMap.get(resultOrganizationalNodeId + "_" + resultPersonId); - if (MapUtils.isEmpty(attributeMap)) { - return; - } - - for (Map.Entry entry : attributeMap.entrySet()) { - ExamineDpColumnsResp.AttributePermissionBasicDTO basic = entry.getValue(); - if (dataNode.has(basic.getAttrCode())) { - if (!ATTRIBUTE_ISUNMASKABLE.equals(basic.getIsUnmaskable())) { - ObjectNode objectNode = (ObjectNode) dataNode; - objectNode.remove(basic.getAttrCode()); - } - if (Objects.nonNull(basic.getIsEditable())) { - ObjectNode objectNode = (ObjectNode) dataNode; - objectNode.put(ATTRIBUTE_ADD_ALLOW_EDIT_PREFIX + basic.getAttrCode(), ATTRIBUTE_ISEDITABLE.equals(basic.getIsEditable())); - } + // 循环处理子field + Iterator> fields = dataNode.fields(); + while (fields.hasNext()) { + Map.Entry entry = fields.next(); + JsonNode value = entry.getValue(); + if (value.isContainerNode()) { + recursiveProcessOrgNodeIdAndPersonIds(dataPermissionPrepare, value, attributeDpResultMap); } } } @@ -116,7 +129,7 @@ public class DataPermissionResponseExecutor { Iterator elements = arrayNode.elements(); while (elements.hasNext()) { JsonNode element = elements.next(); - recursiveGetOrgNodeIdAndPersonIds(dataPermissionPrepare, element, attributeDpResultMap); + recursiveProcessOrgNodeIdAndPersonIds(dataPermissionPrepare, element, attributeDpResultMap); } } } From e0505884dc7d0d4fad52af9ae6dc1a25b2b8f47e Mon Sep 17 00:00:00 2001 From: lilong Date: Fri, 14 Jun 2024 15:55:19 +0800 Subject: [PATCH 12/27] =?UTF-8?q?feat=EF=BC=9A(REQ-2300)=20=E6=8A=8A?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E6=9D=83=E9=99=90=E7=9A=84=E6=B3=A8=E8=A7=A3?= =?UTF-8?q?=E5=90=88=E5=B9=B6=EF=BC=8C=E5=87=8F=E5=B0=91=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=E5=9B=B0=E6=83=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DataPermissionResponseBodyAdvice.java | 18 +- .../DataPermissionResponseExecutor.java | 34 +-- .../annotation/DataPermission.java | 31 +-- .../annotation/DataPermissionPrepare.java | 34 --- .../aop/DataPermissionFeignInterceptor.java | 8 +- .../aop/DataPermissionInterceptor.java | 91 -------- .../aop/DataPermissionMybatisInterceptor.java | 24 ++- .../aop/DataPermissionPrepareInterceptor.java | 197 ++++++++++++------ .../context/DataPermissionContextFactory.java | 8 +- .../context/DataPermissionContextHolder.java | 27 +++ .../DataPermissionPrepareContextHolder.java | 61 ------ .../rule/OrgDefaultRuleServiceImpl.java | 1 - 12 files changed, 230 insertions(+), 304 deletions(-) delete mode 100644 axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/annotation/DataPermissionPrepare.java delete mode 100644 axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionInterceptor.java delete mode 100644 axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionPrepareContextHolder.java diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseBodyAdvice.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseBodyAdvice.java index c544536..f056ef2 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseBodyAdvice.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseBodyAdvice.java @@ -1,7 +1,7 @@ package cn.axzo.framework.datapermission.advice; -import cn.axzo.framework.datapermission.annotation.DataPermissionPrepare; -import cn.axzo.framework.datapermission.context.DataPermissionPrepareContextHolder; +import cn.axzo.framework.datapermission.annotation.DataPermission; +import cn.axzo.framework.datapermission.context.DataPermissionContextHolder; import cn.axzo.framework.datapermission.util.DPUtil; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; @@ -39,12 +39,12 @@ public class DataPermissionResponseBodyAdvice implements ResponseBodyAdvice> converterType) { - DataPermissionPrepare dataPermissionPrepare = returnType.getDeclaringClass().getAnnotation(DataPermissionPrepare.class); - if (dataPermissionPrepare != null) { - return dataPermissionPrepare.enable(); + DataPermission dataPermission = returnType.getDeclaringClass().getAnnotation(DataPermission.class); + if (dataPermission != null) { + return dataPermission.enable(); } else { - dataPermissionPrepare = returnType.getMethodAnnotation(DataPermissionPrepare.class); - return dataPermissionPrepare != null && dataPermissionPrepare.enable(); + dataPermission = returnType.getMethodAnnotation(DataPermission.class); + return dataPermission != null && dataPermission.enable(); } } @@ -64,7 +64,7 @@ public class DataPermissionResponseBodyAdvice implements ResponseBodyAdvice orgNodeIdAndPersonIds = Lists.newArrayList(); - recursiveGetOrgNodeIdAndPersonIds(dataPermissionPrepare, dataNode, orgNodeIdAndPersonIds); + recursiveGetOrgNodeIdAndPersonIds(dataPermission, dataNode, orgNodeIdAndPersonIds); if (CollectionUtils.isEmpty(orgNodeIdAndPersonIds)) { log.warn("api result has no organizationalNodeId and personId, not examine data permission for result columns."); return; @@ -60,13 +60,13 @@ public class DataPermissionResponseExecutor { return; } // 根据karma数据列的校验结果,处理api结果的数据对象 - recursiveProcessOrgNodeIdAndPersonIds(dataPermissionPrepare, dataNode, examineDpColumnsResp.getAttributeDpResultMap()); + recursiveProcessOrgNodeIdAndPersonIds(dataPermission, dataNode, examineDpColumnsResp.getAttributeDpResultMap()); } - private void recursiveGetOrgNodeIdAndPersonIds(DataPermissionPrepare dataPermissionPrepare, JsonNode dataNode, List orgNodeIdAndPersonIds) { + private void recursiveGetOrgNodeIdAndPersonIds(DataPermission dataPermission, JsonNode dataNode, List orgNodeIdAndPersonIds) { if (dataNode.isObject()) { - Long resultOrganizationalNodeId = Objects.nonNull(dataNode.get(dataPermissionPrepare.key_organizationalNodeId())) ? dataNode.get(dataPermissionPrepare.key_organizationalNodeId()).asLong() : 0L; - Long resultPersonId = Objects.nonNull(dataNode.get(dataPermissionPrepare.key_personId())) ? dataNode.get(dataPermissionPrepare.key_personId()).asLong() : 0L; + Long resultOrganizationalNodeId = Objects.nonNull(dataNode.get(dataPermission.key_organizationalNodeId())) ? dataNode.get(dataPermission.key_organizationalNodeId()).asLong() : 0L; + Long resultPersonId = Objects.nonNull(dataNode.get(dataPermission.key_personId())) ? dataNode.get(dataPermission.key_personId()).asLong() : 0L; if (!resultOrganizationalNodeId.equals(0L) || !resultPersonId.equals(0L)) { orgNodeIdAndPersonIds.add(ExamineDpColumnsReq.OrgNodeIdAndPersonId.builder().organizationalNodeId(resultOrganizationalNodeId).personId(resultPersonId).build()); } @@ -76,7 +76,7 @@ public class DataPermissionResponseExecutor { Map.Entry entry = fields.next(); JsonNode value = entry.getValue(); if (value.isContainerNode()) { - recursiveGetOrgNodeIdAndPersonIds(dataPermissionPrepare, value, orgNodeIdAndPersonIds); + recursiveGetOrgNodeIdAndPersonIds(dataPermission, value, orgNodeIdAndPersonIds); } } } @@ -85,16 +85,16 @@ public class DataPermissionResponseExecutor { Iterator elements = arrayNode.elements(); while (elements.hasNext()) { JsonNode element = elements.next(); - recursiveGetOrgNodeIdAndPersonIds(dataPermissionPrepare, element, orgNodeIdAndPersonIds); + recursiveGetOrgNodeIdAndPersonIds(dataPermission, element, orgNodeIdAndPersonIds); } } } - private void recursiveProcessOrgNodeIdAndPersonIds(DataPermissionPrepare dataPermissionPrepare, JsonNode dataNode, - Map> attributeDpResultMap) { + private void recursiveProcessOrgNodeIdAndPersonIds(DataPermission dataPermission, JsonNode dataNode, + Map> attributeDpResultMap) { if (dataNode.isObject()) { - Long resultOrganizationalNodeId = Objects.nonNull(dataNode.get(dataPermissionPrepare.key_organizationalNodeId())) ? dataNode.get(dataPermissionPrepare.key_organizationalNodeId()).asLong() : 0L; - Long resultPersonId = Objects.nonNull(dataNode.get(dataPermissionPrepare.key_personId())) ? dataNode.get(dataPermissionPrepare.key_personId()).asLong() : 0L; + Long resultOrganizationalNodeId = Objects.nonNull(dataNode.get(dataPermission.key_organizationalNodeId())) ? dataNode.get(dataPermission.key_organizationalNodeId()).asLong() : 0L; + Long resultPersonId = Objects.nonNull(dataNode.get(dataPermission.key_personId())) ? dataNode.get(dataPermission.key_personId()).asLong() : 0L; if (!resultOrganizationalNodeId.equals(0L) || !resultPersonId.equals(0L)) { Map attributeMap = attributeDpResultMap.get(resultOrganizationalNodeId + "_" + resultPersonId); if (MapUtils.isNotEmpty(attributeMap)) { @@ -119,7 +119,7 @@ public class DataPermissionResponseExecutor { Map.Entry entry = fields.next(); JsonNode value = entry.getValue(); if (value.isContainerNode()) { - recursiveProcessOrgNodeIdAndPersonIds(dataPermissionPrepare, value, attributeDpResultMap); + recursiveProcessOrgNodeIdAndPersonIds(dataPermission, value, attributeDpResultMap); } } } @@ -129,7 +129,7 @@ public class DataPermissionResponseExecutor { Iterator elements = arrayNode.elements(); while (elements.hasNext()) { JsonNode element = elements.next(); - recursiveProcessOrgNodeIdAndPersonIds(dataPermissionPrepare, element, attributeDpResultMap); + recursiveProcessOrgNodeIdAndPersonIds(dataPermission, element, attributeDpResultMap); } } } diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/annotation/DataPermission.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/annotation/DataPermission.java index 4a6ad8b..309d604 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/annotation/DataPermission.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/annotation/DataPermission.java @@ -1,31 +1,34 @@ package cn.axzo.framework.datapermission.annotation; -import cn.axzo.framework.datapermission.rule.DataPermissionRuleService; -import cn.axzo.framework.datapermission.rule.OrgDefaultRuleServiceImpl; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; +import java.lang.annotation.*; /** - * 数据权限注解 + * 数据权限数据预制注解 + * @author tanjie@axzo.cn + * @date 2024/5/30 17:57 */ @Inherited @Documented @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface DataPermission { - boolean enable() default true; /** - * 持久层使用规则解析组装数据权限的sql参数 - * 只有在提供sql查询的服务才会生效使用 + * 数据权限数据对象code * @return */ - Class includeRule() default OrgDefaultRuleServiceImpl.class; + String bizCode() default ""; + + /** + * ApiResult返回的机构节点的ID + * @return + */ + String key_organizationalNodeId() default "organizationalNodeId"; + /** + * ApiResult返回的用户的ID + * @return + */ + String key_personId() default "personId"; } diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/annotation/DataPermissionPrepare.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/annotation/DataPermissionPrepare.java deleted file mode 100644 index b317b86..0000000 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/annotation/DataPermissionPrepare.java +++ /dev/null @@ -1,34 +0,0 @@ -package cn.axzo.framework.datapermission.annotation; - -import java.lang.annotation.*; - -/** - * 数据权限数据预制注解 - * @author tanjie@axzo.cn - * @date 2024/5/30 17:57 - */ -@Inherited -@Documented -@Target({ElementType.METHOD, ElementType.TYPE}) -@Retention(RetentionPolicy.RUNTIME) -public @interface DataPermissionPrepare { - boolean enable() default true; - - /** - * 数据权限数据对象code - * @return - */ - String bizCode() default ""; - - /** - * ApiResult返回的机构节点的ID - * @return - */ - String key_organizationalNodeId() default "organizationalNodeId"; - /** - * ApiResult返回的用户的ID - * @return - */ - String key_personId() default "personId"; - -} diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionFeignInterceptor.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionFeignInterceptor.java index 9a29f31..87f7eb0 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionFeignInterceptor.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionFeignInterceptor.java @@ -1,6 +1,6 @@ package cn.axzo.framework.datapermission.aop; -import cn.axzo.framework.datapermission.context.DataPermissionPrepareContextHolder; +import cn.axzo.framework.datapermission.context.DataPermissionContextHolder; import feign.RequestInterceptor; import feign.RequestTemplate; import org.springframework.stereotype.Component; @@ -16,12 +16,12 @@ public class DataPermissionFeignInterceptor implements RequestInterceptor { @Override public void apply(RequestTemplate requestTemplate) { - DataPermissionPrepareContextHolder.DataPermissionPrepareContext dataPermissionPrepareContext = DataPermissionPrepareContextHolder.get(); - if (dataPermissionPrepareContext == null) { + DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.get(); + if (dataPermissionContext == null) { return; } // 存放缓存的key,是因为减少io数据量以及header有最大长度限制 - requestTemplate.header(DATA_PERMISSION_HEADER, dataPermissionPrepareContext.getResultKey()); + requestTemplate.header(DATA_PERMISSION_HEADER, dataPermissionContext.getResultKey()); } } diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionInterceptor.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionInterceptor.java deleted file mode 100644 index f1076d4..0000000 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionInterceptor.java +++ /dev/null @@ -1,91 +0,0 @@ -package cn.axzo.framework.datapermission.aop; - -import cn.axzo.framework.datapermission.annotation.DataPermission; -import cn.axzo.framework.datapermission.context.DataPermissionContextHolder; -import cn.axzo.framework.datapermission.util.RpcInternalUtil; -import cn.axzo.karma.client.feign.tyr.DataObjectApi; -import cn.axzo.karma.client.feign.tyr.request.GetMergeMatchDataReq; -import cn.axzo.karma.client.feign.tyr.response.MergeMatchDataResp; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Lazy; -import org.springframework.stereotype.Component; -import org.springframework.web.method.HandlerMethod; -import org.springframework.web.servlet.HandlerInterceptor; -import org.springframework.web.servlet.config.annotation.InterceptorRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import static cn.axzo.framework.datapermission.context.DataPermissionContextHolder.DATA_PERMISSION_HEADER; - -/** - * 从header中获取数据权限的数据,并放置在上下文中 - * @author tanjie@axzo.cn - * @date 2024/5/31 16:37 - */ -@Component -@Slf4j -public class DataPermissionInterceptor implements HandlerInterceptor, WebMvcConfigurer { - - @Lazy - @Autowired - private DataObjectApi dataObjectApi; - - /** - * 拦截@DataPermission - * 设置DataPermissionContext - * @param request - * @param response - * @param handler - * @return - * @throws Exception - */ - @Override - public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) - throws Exception { - if (handler instanceof HandlerMethod) { - - String dataPermissionHeader = request.getHeader(DATA_PERMISSION_HEADER); - - if (StringUtils.isBlank(dataPermissionHeader)) { - return true; - } - - DataPermissionContextHolder.DataPermissionContext dataPermissionContext = getCachedDataPermission(dataPermissionHeader); - - HandlerMethod handlerMethod = (HandlerMethod) handler; - DataPermission dataPermission = handlerMethod.getMethodAnnotation(DataPermission.class); - dataPermissionContext.setDataPermission(dataPermission); - - DataPermissionContextHolder.setContext(dataPermissionContext); - } - return true; - } - - @Override - public void addInterceptors(InterceptorRegistry registry) { - registry.addInterceptor(this); - } - - private DataPermissionContextHolder.DataPermissionContext getCachedDataPermission(String redisKey) { - - GetMergeMatchDataReq getMergeMatchDataReq = GetMergeMatchDataReq.builder() - .resultKey(redisKey) - .build(); - MergeMatchDataResp mergeMatchDataResp = RpcInternalUtil.rpcProcessor(() -> dataObjectApi.getCached(getMergeMatchDataReq), - "根据key查询数据权限规则的解析结果", getMergeMatchDataReq) - .getData(); - - DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.DataPermissionContext.builder().build(); - if (mergeMatchDataResp == null) { - return dataPermissionContext; - } - - dataPermissionContext.setNodeIds(mergeMatchDataResp.getNodeIds()); - dataPermissionContext.setPersonIds(mergeMatchDataResp.getPersonIds()); - return dataPermissionContext; - } -} diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionMybatisInterceptor.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionMybatisInterceptor.java index 39e73ca..dcb7aa6 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionMybatisInterceptor.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionMybatisInterceptor.java @@ -3,7 +3,6 @@ package cn.axzo.framework.datapermission.aop; import cn.axzo.framework.datapermission.annotation.DataPermission; import cn.axzo.framework.datapermission.context.DataPermissionContextFactory; import cn.axzo.framework.datapermission.context.DataPermissionContextHolder; -import cn.axzo.framework.datapermission.context.DataPermissionPrepareContextHolder; import cn.axzo.framework.datapermission.rule.DataPermissionRuleService; import com.baomidou.mybatisplus.core.parser.SqlParserHelper; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; @@ -140,7 +139,12 @@ public class DataPermissionMybatisInterceptor extends JsqlParserSupport implemen DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.get(); DataPermission dataPermission = dataPermissionContext.getDataPermission(); - List byDataPermission = dataPermissionContextFactory.getRuleByDataPermission(dataPermission); + // 接口未配置注解,就不需要自动增加sql + if (dataPermission == null) { + return where; + } + + List byDataPermission = dataPermissionContextFactory.getRuleByDataPermission(); Optional first = byDataPermission.stream().filter(rule -> rule.getTableName().contains(table.getName())).findFirst(); if (!first.isPresent()) { return where; @@ -295,7 +299,13 @@ public class DataPermissionMybatisInterceptor extends JsqlParserSupport implemen DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.get(); DataPermission dataPermission = dataPermissionContext.getDataPermission(); - List byDataPermission = dataPermissionContextFactory.getRuleByDataPermission(dataPermission); + + // 接口未配置注解,就不需要自动增加sql + if (dataPermission == null) { + return currentExpression; + } + + List byDataPermission = dataPermissionContextFactory.getRuleByDataPermission(); Optional first = byDataPermission.stream().filter(rule -> rule.getTableName().contains(table.getName())).findFirst(); if (!first.isPresent()) { return currentExpression; @@ -313,10 +323,10 @@ public class DataPermissionMybatisInterceptor extends JsqlParserSupport implemen } private boolean filter() { - DataPermissionPrepareContextHolder.DataPermissionPrepareContext dataPermissionPrepareContext = DataPermissionPrepareContextHolder.get(); - if (null == dataPermissionPrepareContext - || dataPermissionPrepareContext.getDataPermissionPrepare() == null - || !dataPermissionPrepareContext.getDataPermissionPrepare().enable()) { + DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.get(); + if (null == dataPermissionContext + || dataPermissionContext.getDataPermission() == null + || !dataPermissionContext.getDataPermission().enable()) { return false; } diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionPrepareInterceptor.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionPrepareInterceptor.java index 46383c1..daa0bfa 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionPrepareInterceptor.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionPrepareInterceptor.java @@ -1,93 +1,156 @@ package cn.axzo.framework.datapermission.aop; +import cn.axzo.framework.auth.AuthException; import cn.axzo.framework.auth.domain.ContextInfo; import cn.axzo.framework.auth.domain.ContextInfoHolder; -import cn.axzo.framework.datapermission.annotation.DataPermissionPrepare; -import cn.axzo.framework.datapermission.context.DataPermissionPrepareContextHolder; +import cn.axzo.framework.datapermission.annotation.DataPermission; +import cn.axzo.framework.datapermission.context.DataPermissionContextHolder; import cn.axzo.framework.datapermission.util.RpcInternalUtil; import cn.axzo.karma.client.feign.tyr.DataObjectApi; +import cn.axzo.karma.client.feign.tyr.request.GetMergeMatchDataReq; import cn.axzo.karma.client.feign.tyr.request.MatchDataObjectReq; import cn.axzo.karma.client.feign.tyr.response.MatchDataObjectResp; +import cn.axzo.karma.client.feign.tyr.response.MergeMatchDataResp; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.aspectj.lang.annotation.Pointcut; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; +import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; -import org.springframework.web.method.HandlerMethod; -import org.springframework.web.servlet.HandlerInterceptor; -import org.springframework.web.servlet.config.annotation.InterceptorRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import java.util.Objects; import java.util.Optional; +import static cn.axzo.framework.datapermission.context.DataPermissionContextHolder.DATA_PERMISSION_HEADER; + /** * 解析数据权限规则,把解析后的数据放置在上下文中DataPermissionContext */ -@Component @Slf4j -public class DataPermissionPrepareInterceptor implements HandlerInterceptor, WebMvcConfigurer { +@Aspect +@Order(100) +@Component +public class DataPermissionPrepareInterceptor { @Lazy @Autowired private DataObjectApi dataObjectApi; - /** - * 拦截@DataPermission - * 设置DataPermissionContext - * @param request - * @param response - * @param handler - * @return - * @throws Exception - */ - @Override - public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) - throws Exception { - if (handler instanceof HandlerMethod) { - HandlerMethod handlerMethod = (HandlerMethod) handler; - DataPermissionPrepare dataPermissionPrepare = handlerMethod.getMethodAnnotation(DataPermissionPrepare.class); - if (dataPermissionPrepare == null || BooleanUtils.isNotTrue(dataPermissionPrepare.enable()) || StringUtils.isBlank(dataPermissionPrepare.bizCode())) { - return true; - } - - ContextInfo contextInfo = ContextInfoHolder.get(); - if (contextInfo == null || contextInfo.getUserInfo() == null) { - return true; - } - - Optional matchDataObjectOptional = this.matchRule(dataPermissionPrepare); - if (!matchDataObjectOptional.isPresent()) { - log.warn("no match data rule, bizCode:{}, personId:{}, ouId:{}, workspaceId:{}", - dataPermissionPrepare.bizCode(), - contextInfo.getUserInfo().getPersonId(), - contextInfo.getOuId(), - contextInfo.getWorkspaceId()); - return true; - } - - DataPermissionPrepareContextHolder.DataPermissionPrepareContext dataPermissionPrepareContext = DataPermissionPrepareContextHolder.DataPermissionPrepareContext.builder() - .dataPermissionPrepare(dataPermissionPrepare) - .workspaceId(contextInfo.getWorkspaceId()) - .ouId(contextInfo.getOuId()) - .personId(contextInfo.getUserInfo().getPersonId()) - .resultKey(matchDataObjectOptional.get().getResultKey()) - .build(); - - DataPermissionPrepareContextHolder.setContext(dataPermissionPrepareContext); - } - return true; + @Pointcut(value = "@annotation(org.springframework.web.bind.annotation.RequestMapping)") + public void requestMapping() { } - private Optional matchRule(DataPermissionPrepare dataPermissionPrepare) { + @Pointcut(value = "@annotation(org.springframework.web.bind.annotation.PostMapping)") + public void postMapping() { + } + + @Pointcut(value = "@annotation(org.springframework.web.bind.annotation.GetMapping)") + public void getMapping() { + } + + @Pointcut(value = "@annotation(org.springframework.web.bind.annotation.PutMapping)") + public void putMapping() { + } + + @Pointcut(value = "@annotation(org.springframework.web.bind.annotation.DeleteMapping)") + public void deleteMapping() { + } + + @Pointcut(value = "@annotation(org.springframework.web.bind.annotation.PatchMapping)") + public void patchMapping() { + } + + @Pointcut("requestMapping() || postMapping() || getMapping() || putMapping() || deleteMapping()|| patchMapping()") + public void mappingAnnotations() { + } + + /** + * 切入含有@DataPermissiont && @RestController 注解的类 + */ + @Before(value = "@within(dataPermission) && @within(restController)") + public void classHandler(DataPermission dataPermission, RestController restController) { + handle(dataPermission); + } + + /** + * 切入含有@DataPermissiont && @RequestMapping/@PostMapping/@GetMapping/@PutMapping/@DeleteMapping/@PatchMapping 之一注解的方法 + */ + @Before(value = "@annotation(dataPermission) && mappingAnnotations()") + public void methodHandler(DataPermission dataPermission) { + handle(dataPermission); + } + + public void handle(DataPermission dataPermission) { + + HttpServletRequest httpRequest = null; + try { + // 获取request + httpRequest = ((ServletRequestAttributes) Objects + .requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest(); + } catch (Exception exception) { + log.error("can not get request,there is a error occurrence ==>" + exception.getCause().getMessage()); + } + AuthException.error(Objects.nonNull(httpRequest), "httpRequest cant be null, this is error"); + + + String dataPermissionHeader = httpRequest.getHeader(DATA_PERMISSION_HEADER); + // header中有值,表示数据权限规则已经被解析,只需要获取数据去使用 + if (StringUtils.isBlank(dataPermissionHeader)) { + resolveRule(dataPermission); + return; + } + + DataPermissionContextHolder.DataPermissionContext dataPermissionContext = getCachedDataPermission(dataPermissionHeader); + dataPermissionContext.setDataPermission(dataPermission); + DataPermissionContextHolder.setContext(dataPermissionContext); + } + + /** + * 解析数据权限规则 + * @param dataPermission + */ + private void resolveRule(DataPermission dataPermission) { + + ContextInfo contextInfo = ContextInfoHolder.get(); + if (contextInfo == null || contextInfo.getUserInfo() == null || StringUtils.isBlank(dataPermission.bizCode())) { + return; + } + + Optional matchDataObjectOptional = this.matchRule(dataPermission); + if (!matchDataObjectOptional.isPresent()) { + log.warn("no match data rule, bizCode:{}, personId:{}, ouId:{}, workspaceId:{}", + dataPermission.bizCode(), + contextInfo.getUserInfo().getPersonId(), + contextInfo.getOuId(), + contextInfo.getWorkspaceId()); + return; + } + + DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.DataPermissionContext.builder() + .dataPermission(dataPermission) + .workspaceId(contextInfo.getWorkspaceId()) + .ouId(contextInfo.getOuId()) + .personId(contextInfo.getUserInfo().getPersonId()) + .resultKey(matchDataObjectOptional.get().getResultKey()) + .build(); + + DataPermissionContextHolder.setContext(dataPermissionContext); + } + + private Optional matchRule(DataPermission dataPermission) { ContextInfo contextInfo = ContextInfoHolder.get(); MatchDataObjectReq matchDataObjectReq = MatchDataObjectReq.builder() - .dataObjectCode(dataPermissionPrepare.bizCode()) + .dataObjectCode(dataPermission.bizCode()) .ouId(contextInfo.getOuId()) .workspaceId(contextInfo.getWorkspaceId()) .personId(contextInfo.getUserInfo().getPersonId()) @@ -99,8 +162,22 @@ public class DataPermissionPrepareInterceptor implements HandlerInterceptor, Web return Optional.ofNullable(matchDataObjectResp); } - @Override - public void addInterceptors(InterceptorRegistry registry) { - registry.addInterceptor(this); + private DataPermissionContextHolder.DataPermissionContext getCachedDataPermission(String redisKey) { + + GetMergeMatchDataReq getMergeMatchDataReq = GetMergeMatchDataReq.builder() + .resultKey(redisKey) + .build(); + MergeMatchDataResp mergeMatchDataResp = RpcInternalUtil.rpcProcessor(() -> dataObjectApi.getCached(getMergeMatchDataReq), + "根据key查询数据权限规则的解析结果", getMergeMatchDataReq) + .getData(); + + DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.DataPermissionContext.builder().build(); + if (mergeMatchDataResp == null) { + return dataPermissionContext; + } + + dataPermissionContext.setNodeIds(mergeMatchDataResp.getNodeIds()); + dataPermissionContext.setPersonIds(mergeMatchDataResp.getPersonIds()); + return dataPermissionContext; } } diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextFactory.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextFactory.java index cb79d78..3822ef3 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextFactory.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextFactory.java @@ -1,12 +1,9 @@ package cn.axzo.framework.datapermission.context; -import cn.axzo.framework.datapermission.annotation.DataPermission; import cn.axzo.framework.datapermission.rule.DataPermissionRuleService; import lombok.AllArgsConstructor; import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; /** * @author tanjie@axzo.cn @@ -22,9 +19,8 @@ public class DataPermissionContextFactory { return rules; } - public List getRuleByDataPermission(DataPermission dataPermission) { - Class classes = dataPermission.includeRule(); - return rules.stream().filter(rule -> Objects.equals(classes, rule.getClass())).collect(Collectors.toList()); + public List getRuleByDataPermission() { + return rules; } } diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextHolder.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextHolder.java index b55b74d..20441a9 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextHolder.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextHolder.java @@ -8,6 +8,12 @@ import lombok.NoArgsConstructor; import java.util.Set; +/** + * 数据权限上下文 + * + * @author tanjie@axzo.cn + * @date 2024/5/31 11:42 + */ public class DataPermissionContextHolder { public static final String DATA_PERMISSION_HEADER = "dataPermission"; @@ -26,6 +32,26 @@ public class DataPermissionContextHolder { public static class DataPermissionContext { private DataPermission dataPermission; + /** + * 当前单位id + */ + private Long ouId; + + /** + * 当前项目id + */ + private Long workspaceId; + + /** + * 登录人 + */ + private Long personId; + + /** + * 匹配的解析规则放在redis中的key + */ + private String resultKey; + /** * 解析后的人员id */ @@ -45,3 +71,4 @@ public class DataPermissionContextHolder { return DATA_PERMISSION_CONTEXT.get(); } } + diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionPrepareContextHolder.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionPrepareContextHolder.java deleted file mode 100644 index 82c99ea..0000000 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionPrepareContextHolder.java +++ /dev/null @@ -1,61 +0,0 @@ -package cn.axzo.framework.datapermission.context; - -import cn.axzo.framework.datapermission.annotation.DataPermissionPrepare; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 数据权限上下文 - * - * @author tanjie@axzo.cn - * @date 2024/5/31 11:42 - */ -public class DataPermissionPrepareContextHolder { - - - private final static ThreadLocal DATA_PERMISSION_CONTEXT = new ThreadLocal<>(); - - public static void setContext(DataPermissionPrepareContext dataPermission) { - DATA_PERMISSION_CONTEXT.set(dataPermission); - } - - - @Data - @Builder - @NoArgsConstructor - @AllArgsConstructor - public static class DataPermissionPrepareContext { - private DataPermissionPrepare dataPermissionPrepare; - - /** - * 当前单位id - */ - private Long ouId; - - /** - * 当前项目id - */ - private Long workspaceId; - - /** - * 登录人 - */ - private Long personId; - - /** - * 匹配的解析规则放在redis中的key - */ - private String resultKey; - } - - public static void remove() { - DATA_PERMISSION_CONTEXT.remove(); - } - - public static DataPermissionPrepareContext get() { - return DATA_PERMISSION_CONTEXT.get(); - } -} - diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/rule/OrgDefaultRuleServiceImpl.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/rule/OrgDefaultRuleServiceImpl.java index 41467c4..10e088a 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/rule/OrgDefaultRuleServiceImpl.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/rule/OrgDefaultRuleServiceImpl.java @@ -1,7 +1,6 @@ package cn.axzo.framework.datapermission.rule; import cn.axzo.framework.datapermission.context.DataPermissionContextHolder; -import cn.axzo.framework.datapermission.context.DataPermissionPrepareContextHolder; import cn.axzo.karma.client.feign.tyr.DataObjectApi; import com.baomidou.mybatisplus.core.metadata.TableInfo; import com.baomidou.mybatisplus.core.metadata.TableInfoHelper; From 4f529ebf875c4dd573480de3eb0ca8d5a8ba70ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E6=98=86=E9=B9=8F?= Date: Fri, 14 Jun 2024 16:42:59 +0800 Subject: [PATCH 13/27] =?UTF-8?q?feat(REQ-2300)=EF=BC=9A=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E6=9D=83=E9=99=90=E8=BF=94=E5=9B=9E=E6=95=B0=E6=8D=AE=E5=A4=84?= =?UTF-8?q?=E7=90=86Advice=E5=8A=9F=E8=83=BD=EF=BC=8C=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E5=AF=B9=E6=AF=8F=E4=B8=AA=E5=AD=90field=E7=9A=84=E9=80=92?= =?UTF-8?q?=E5=BD=92=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../framework/datapermission/annotation/DataPermission.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/annotation/DataPermission.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/annotation/DataPermission.java index 309d604..33df9f7 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/annotation/DataPermission.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/annotation/DataPermission.java @@ -14,6 +14,8 @@ import java.lang.annotation.*; public @interface DataPermission { boolean enable() default true; + boolean processResponse() default false; + /** * 数据权限数据对象code * @return From 92e391b10a6fd03f442902a8e69d0f672db2b8ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E6=98=86=E9=B9=8F?= Date: Fri, 14 Jun 2024 16:44:21 +0800 Subject: [PATCH 14/27] =?UTF-8?q?feat(REQ-2300)=EF=BC=9A=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E6=9D=83=E9=99=90=E8=BF=94=E5=9B=9E=E6=95=B0=E6=8D=AE=E5=A4=84?= =?UTF-8?q?=E7=90=86Advice=E5=8A=9F=E8=83=BD=EF=BC=8C=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E5=AF=B9=E6=AF=8F=E4=B8=AA=E5=AD=90field=E7=9A=84=E9=80=92?= =?UTF-8?q?=E5=BD=92=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../advice/DataPermissionResponseBodyAdvice.java | 4 ++-- .../framework/datapermission/annotation/DataPermission.java | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseBodyAdvice.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseBodyAdvice.java index f056ef2..00fb904 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseBodyAdvice.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseBodyAdvice.java @@ -41,10 +41,10 @@ public class DataPermissionResponseBodyAdvice implements ResponseBodyAdvice> converterType) { DataPermission dataPermission = returnType.getDeclaringClass().getAnnotation(DataPermission.class); if (dataPermission != null) { - return dataPermission.enable(); + return dataPermission.enable() && dataPermission.processResponse(); } else { dataPermission = returnType.getMethodAnnotation(DataPermission.class); - return dataPermission != null && dataPermission.enable(); + return dataPermission != null && dataPermission.enable() && dataPermission.processResponse(); } } diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/annotation/DataPermission.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/annotation/DataPermission.java index 33df9f7..6d291ad 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/annotation/DataPermission.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/annotation/DataPermission.java @@ -14,6 +14,7 @@ import java.lang.annotation.*; public @interface DataPermission { boolean enable() default true; + /** 是否处理ApiResult,默认不处理 **/ boolean processResponse() default false; /** From 2bf9c7df07dcbc4bb73968b5ce54eb562e5ce437 Mon Sep 17 00:00:00 2001 From: lilong Date: Fri, 28 Jun 2024 14:56:33 +0800 Subject: [PATCH 15/27] =?UTF-8?q?feat=EF=BC=9A(REQ-2300)=20=E6=B3=A8?= =?UTF-8?q?=E9=87=8A=E6=95=B0=E6=8D=AE=E6=9D=83=E9=99=90=E8=A7=A3=E6=9E=90?= =?UTF-8?q?=EF=BC=8C=E7=94=B1=E7=94=A8=E6=88=B7=E6=98=BE=E7=A4=BA=E7=9A=84?= =?UTF-8?q?=E4=BC=A0=E9=80=92=E8=A7=A3=E6=9E=90=E7=BB=93=E6=9E=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../aop/DataPermissionFeignInterceptor.java | 3 +- ...or.java => DataPermissionInterceptor.java} | 25 +- .../aop/DataPermissionMybatisInterceptor.java | 560 +++++++++--------- .../config/DataPermissionConfig.java | 28 +- .../context/DataPermissionContextFactory.java | 2 +- .../context/DataPermissionContextHolder.java | 5 + 6 files changed, 319 insertions(+), 304 deletions(-) rename axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/{DataPermissionPrepareInterceptor.java => DataPermissionInterceptor.java} (88%) diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionFeignInterceptor.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionFeignInterceptor.java index 87f7eb0..641a20f 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionFeignInterceptor.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionFeignInterceptor.java @@ -9,8 +9,9 @@ import static cn.axzo.framework.datapermission.context.DataPermissionContextHold /** * 上下文中有DataPermissionContext,则把数据放在header中 + * 根据用户调研结果,选择BFF解析规则结果放在上下文,由用户显示的把上下文的数据传递到底层服务,方便排查问题和使用 */ -@Component +//@Component public class DataPermissionFeignInterceptor implements RequestInterceptor { @Override diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionPrepareInterceptor.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionInterceptor.java similarity index 88% rename from axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionPrepareInterceptor.java rename to axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionInterceptor.java index daa0bfa..179cb05 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionPrepareInterceptor.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionInterceptor.java @@ -11,8 +11,11 @@ import cn.axzo.karma.client.feign.tyr.request.GetMergeMatchDataReq; import cn.axzo.karma.client.feign.tyr.request.MatchDataObjectReq; import cn.axzo.karma.client.feign.tyr.response.MatchDataObjectResp; import cn.axzo.karma.client.feign.tyr.response.MergeMatchDataResp; +import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; @@ -37,7 +40,7 @@ import static cn.axzo.framework.datapermission.context.DataPermissionContextHold @Aspect @Order(100) @Component -public class DataPermissionPrepareInterceptor { +public class DataPermissionInterceptor { @Lazy @Autowired @@ -75,17 +78,21 @@ public class DataPermissionPrepareInterceptor { /** * 切入含有@DataPermissiont && @RestController 注解的类 */ - @Before(value = "@within(dataPermission) && @within(restController)") - public void classHandler(DataPermission dataPermission, RestController restController) { + @Around(value = "@within(dataPermission) && @within(restController)") + @SneakyThrows + public Object classHandler(ProceedingJoinPoint pjp, DataPermission dataPermission, RestController restController) { handle(dataPermission); + return pjp.proceed(pjp.getArgs()); } /** * 切入含有@DataPermissiont && @RequestMapping/@PostMapping/@GetMapping/@PutMapping/@DeleteMapping/@PatchMapping 之一注解的方法 */ - @Before(value = "@annotation(dataPermission) && mappingAnnotations()") - public void methodHandler(DataPermission dataPermission) { + @Around(value = "@annotation(dataPermission) && mappingAnnotations()") + @SneakyThrows + public Object methodHandler(ProceedingJoinPoint pjp, DataPermission dataPermission) { handle(dataPermission); + return pjp.proceed(pjp.getArgs()); } public void handle(DataPermission dataPermission) { @@ -105,12 +112,12 @@ public class DataPermissionPrepareInterceptor { // header中有值,表示数据权限规则已经被解析,只需要获取数据去使用 if (StringUtils.isBlank(dataPermissionHeader)) { resolveRule(dataPermission); - return; +// return; } - DataPermissionContextHolder.DataPermissionContext dataPermissionContext = getCachedDataPermission(dataPermissionHeader); - dataPermissionContext.setDataPermission(dataPermission); - DataPermissionContextHolder.setContext(dataPermissionContext); +// DataPermissionContextHolder.DataPermissionContext dataPermissionContext = getCachedDataPermission(dataPermissionHeader); +// dataPermissionContext.setDataPermission(dataPermission); +// DataPermissionContextHolder.setContext(dataPermissionContext); } /** diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionMybatisInterceptor.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionMybatisInterceptor.java index dcb7aa6..0726b71 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionMybatisInterceptor.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionMybatisInterceptor.java @@ -51,286 +51,288 @@ import java.util.Optional; * @author tanjie@axzo.cn * @date 2024/5/31 11:41 */ -@RequiredArgsConstructor -public class DataPermissionMybatisInterceptor extends JsqlParserSupport implements InnerInterceptor { +//@RequiredArgsConstructor +public class DataPermissionMybatisInterceptor +// extends JsqlParserSupport implements InnerInterceptor +{ - private final DataPermissionContextFactory dataPermissionContextFactory; +// private final DataPermissionContextFactory dataPermissionContextFactory; - @Override - public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException { - if (!filter()) { - return; - } - PluginUtils.MPBoundSql mpBs = PluginUtils.mpBoundSql(boundSql); - mpBs.sql(parserSingle(mpBs.sql(), null)); - } - - @Override - public void beforePrepare(StatementHandler sh, Connection connection, Integer transactionTimeout) { - PluginUtils.MPStatementHandler mpSh = PluginUtils.mpStatementHandler(sh); - MappedStatement ms = mpSh.mappedStatement(); - SqlCommandType sct = ms.getSqlCommandType(); - // 不管insert - if (sct == SqlCommandType.UPDATE || sct == SqlCommandType.DELETE) { - if (!filter()) return; - if (SqlParserHelper.getSqlParserInfo(ms)) return; - PluginUtils.MPBoundSql mpBs = mpSh.mPBoundSql(); - mpBs.sql(parserMulti(mpBs.sql(), null)); - } - } - - @Override - protected void processSelect(Select select, int index, String sql, Object obj) { - processSelectBody(select.getSelectBody()); - List withItemsList = select.getWithItemsList(); - if (!CollectionUtils.isEmpty(withItemsList)) { - withItemsList.forEach(this::processSelectBody); - } - } - - protected void processSelectBody(SelectBody selectBody) { - if (selectBody == null) { - return; - } - if (selectBody instanceof PlainSelect) { - processPlainSelect((PlainSelect) selectBody); - } else if (selectBody instanceof WithItem) { - WithItem withItem = (WithItem) selectBody; - processSelectBody(withItem.getSelectBody()); - } else { - SetOperationList operationList = (SetOperationList) selectBody; - if (operationList.getSelects() != null && operationList.getSelects().size() > 0) { - operationList.getSelects().forEach(this::processSelectBody); - } - } - } - - - /** - * update 语句处理 - */ - @Override - protected void processUpdate(Update update, int index, String sql, Object obj) { - final Table table = update.getTable(); - if (!filter()) { - // 过滤退出执行 - return; - } - update.setWhere(this.andExpression(table, update.getWhere())); - } - - /** - * delete 语句处理 - */ - @Override - protected void processDelete(Delete delete, int index, String sql, Object obj) { - if (!filter()) { - // 过滤退出执行 - return; - } - delete.setWhere(this.andExpression(delete.getTable(), delete.getWhere())); - } - - /** - * delete update 语句 where 处理 - */ - protected Expression andExpression(Table table, Expression where) { - - - DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.get(); - DataPermission dataPermission = dataPermissionContext.getDataPermission(); - // 接口未配置注解,就不需要自动增加sql - if (dataPermission == null) { - return where; - } - - List byDataPermission = dataPermissionContextFactory.getRuleByDataPermission(); - Optional first = byDataPermission.stream().filter(rule -> rule.getTableName().contains(table.getName())).findFirst(); - if (!first.isPresent()) { - return where; - } - DataPermissionRuleService dataPermissionRuleService = first.get(); - Expression ruleExpression = dataPermissionRuleService.getExpression(table.getName(), table.getAlias()); - - if (null != where) { - if (where instanceof OrExpression) { - return new AndExpression(ruleExpression, new Parenthesis(where)); - } else { - return new AndExpression(ruleExpression, where); - } - } - return ruleExpression; - } - - - - - - /** - * 处理 PlainSelect - */ - protected void processPlainSelect(PlainSelect plainSelect) { - FromItem fromItem = plainSelect.getFromItem(); - Expression where = plainSelect.getWhere(); - processWhereSubSelect(where); - if (fromItem instanceof Table) { - Table fromTable = (Table) fromItem; - if (filter()) { - //#1186 github - plainSelect.setWhere(builderExpression(where, fromTable)); - } - } else { - processFromItem(fromItem); - } - List joins = plainSelect.getJoins(); - if (joins != null && joins.size() > 0) { - joins.forEach(j -> { - processJoin(j); - processFromItem(j.getRightItem()); - }); - } - } - - /** - * 处理where条件内的子查询 - *

- * 支持如下: - * 1. in - * 2. = - * 3. > - * 4. < - * 5. >= - * 6. <= - * 7. <> - * 8. EXISTS - * 9. NOT EXISTS - *

- * 前提条件: - * 1. 子查询必须放在小括号中 - * 2. 子查询一般放在比较操作符的右边 - * - * @param where where 条件 - */ - protected void processWhereSubSelect(Expression where) { - if (where == null) { - return; - } - if (where instanceof FromItem) { - processFromItem((FromItem) where); - return; - } - if (where.toString().indexOf("SELECT") > 0) { - // 有子查询 - if (where instanceof BinaryExpression) { - // 比较符号 , and , or , 等等 - BinaryExpression expression = (BinaryExpression) where; - processWhereSubSelect(expression.getLeftExpression()); - processWhereSubSelect(expression.getRightExpression()); - } else if (where instanceof InExpression) { - // in - InExpression expression = (InExpression) where; - ItemsList itemsList = expression.getRightItemsList(); - if (itemsList instanceof SubSelect) { - processSelectBody(((SubSelect) itemsList).getSelectBody()); - } - } else if (where instanceof ExistsExpression) { - // exists - ExistsExpression expression = (ExistsExpression) where; - processWhereSubSelect(expression.getRightExpression()); - } else if (where instanceof NotExpression) { - // not exists - NotExpression expression = (NotExpression) where; - processWhereSubSelect(expression.getExpression()); - } else if (where instanceof Parenthesis) { - Parenthesis expression = (Parenthesis) where; - processWhereSubSelect(expression.getExpression()); - } - } - } - - /** - * 处理子查询等 - */ - protected void processFromItem(FromItem fromItem) { - if (fromItem instanceof SubJoin) { - SubJoin subJoin = (SubJoin) fromItem; - if (subJoin.getJoinList() != null) { - subJoin.getJoinList().forEach(this::processJoin); - } - if (subJoin.getLeft() != null) { - processFromItem(subJoin.getLeft()); - } - } else if (fromItem instanceof SubSelect) { - SubSelect subSelect = (SubSelect) fromItem; - if (subSelect.getSelectBody() != null) { - processSelectBody(subSelect.getSelectBody()); - } - } else if (fromItem instanceof ValuesList) { - logger.debug("Perform a subquery, if you do not give us feedback"); - } else if (fromItem instanceof LateralSubSelect) { - LateralSubSelect lateralSubSelect = (LateralSubSelect) fromItem; - if (lateralSubSelect.getSubSelect() != null) { - SubSelect subSelect = lateralSubSelect.getSubSelect(); - if (subSelect.getSelectBody() != null) { - processSelectBody(subSelect.getSelectBody()); - } - } - } - } - - /** - * 处理联接语句 - */ - protected void processJoin(Join join) { - if (join.getRightItem() instanceof Table) { - Table fromTable = (Table) join.getRightItem(); - if (!filter()) { - // 过滤退出执行 - return; - } - join.setOnExpression(builderExpression(join.getOnExpression(), fromTable)); - } - } - - /** - * 处理条件 - */ - protected Expression builderExpression(Expression currentExpression, Table table) { - - DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.get(); - DataPermission dataPermission = dataPermissionContext.getDataPermission(); - - // 接口未配置注解,就不需要自动增加sql - if (dataPermission == null) { - return currentExpression; - } - - List byDataPermission = dataPermissionContextFactory.getRuleByDataPermission(); - Optional first = byDataPermission.stream().filter(rule -> rule.getTableName().contains(table.getName())).findFirst(); - if (!first.isPresent()) { - return currentExpression; - } - DataPermissionRuleService dataPermissionRuleService = first.get(); - Expression ruleExpression = dataPermissionRuleService.getExpression(table.getName(), table.getAlias()); - if (currentExpression == null) { - return ruleExpression; - } - if (currentExpression instanceof OrExpression) { - return new AndExpression(new Parenthesis(currentExpression), ruleExpression); - } else { - return new AndExpression(currentExpression, ruleExpression); - } - } - - private boolean filter() { - DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.get(); - if (null == dataPermissionContext - || dataPermissionContext.getDataPermission() == null - || !dataPermissionContext.getDataPermission().enable()) { - return false; - } - - return true; - } +// @Override +// public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException { +// if (!filter()) { +// return; +// } +// PluginUtils.MPBoundSql mpBs = PluginUtils.mpBoundSql(boundSql); +// mpBs.sql(parserSingle(mpBs.sql(), null)); +// } +// +// @Override +// public void beforePrepare(StatementHandler sh, Connection connection, Integer transactionTimeout) { +// PluginUtils.MPStatementHandler mpSh = PluginUtils.mpStatementHandler(sh); +// MappedStatement ms = mpSh.mappedStatement(); +// SqlCommandType sct = ms.getSqlCommandType(); +// // 不管insert +// if (sct == SqlCommandType.UPDATE || sct == SqlCommandType.DELETE) { +// if (!filter()) return; +// if (SqlParserHelper.getSqlParserInfo(ms)) return; +// PluginUtils.MPBoundSql mpBs = mpSh.mPBoundSql(); +// mpBs.sql(parserMulti(mpBs.sql(), null)); +// } +// } +// +// @Override +// protected void processSelect(Select select, int index, String sql, Object obj) { +// processSelectBody(select.getSelectBody()); +// List withItemsList = select.getWithItemsList(); +// if (!CollectionUtils.isEmpty(withItemsList)) { +// withItemsList.forEach(this::processSelectBody); +// } +// } +// +// protected void processSelectBody(SelectBody selectBody) { +// if (selectBody == null) { +// return; +// } +// if (selectBody instanceof PlainSelect) { +// processPlainSelect((PlainSelect) selectBody); +// } else if (selectBody instanceof WithItem) { +// WithItem withItem = (WithItem) selectBody; +// processSelectBody(withItem.getSelectBody()); +// } else { +// SetOperationList operationList = (SetOperationList) selectBody; +// if (operationList.getSelects() != null && operationList.getSelects().size() > 0) { +// operationList.getSelects().forEach(this::processSelectBody); +// } +// } +// } +// +// +// /** +// * update 语句处理 +// */ +// @Override +// protected void processUpdate(Update update, int index, String sql, Object obj) { +// final Table table = update.getTable(); +// if (!filter()) { +// // 过滤退出执行 +// return; +// } +// update.setWhere(this.andExpression(table, update.getWhere())); +// } +// +// /** +// * delete 语句处理 +// */ +// @Override +// protected void processDelete(Delete delete, int index, String sql, Object obj) { +// if (!filter()) { +// // 过滤退出执行 +// return; +// } +// delete.setWhere(this.andExpression(delete.getTable(), delete.getWhere())); +// } +// +// /** +// * delete update 语句 where 处理 +// */ +// protected Expression andExpression(Table table, Expression where) { +// +// +// DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.get(); +// DataPermission dataPermission = dataPermissionContext.getDataPermission(); +// // 接口未配置注解,就不需要自动增加sql +// if (dataPermission == null) { +// return where; +// } +// +// List byDataPermission = dataPermissionContextFactory.getRuleByDataPermission(); +// Optional first = byDataPermission.stream().filter(rule -> rule.getTableName().contains(table.getName())).findFirst(); +// if (!first.isPresent()) { +// return where; +// } +// DataPermissionRuleService dataPermissionRuleService = first.get(); +// Expression ruleExpression = dataPermissionRuleService.getExpression(table.getName(), table.getAlias()); +// +// if (null != where) { +// if (where instanceof OrExpression) { +// return new AndExpression(ruleExpression, new Parenthesis(where)); +// } else { +// return new AndExpression(ruleExpression, where); +// } +// } +// return ruleExpression; +// } +// +// +// +// +// +// /** +// * 处理 PlainSelect +// */ +// protected void processPlainSelect(PlainSelect plainSelect) { +// FromItem fromItem = plainSelect.getFromItem(); +// Expression where = plainSelect.getWhere(); +// processWhereSubSelect(where); +// if (fromItem instanceof Table) { +// Table fromTable = (Table) fromItem; +// if (filter()) { +// //#1186 github +// plainSelect.setWhere(builderExpression(where, fromTable)); +// } +// } else { +// processFromItem(fromItem); +// } +// List joins = plainSelect.getJoins(); +// if (joins != null && joins.size() > 0) { +// joins.forEach(j -> { +// processJoin(j); +// processFromItem(j.getRightItem()); +// }); +// } +// } +// +// /** +// * 处理where条件内的子查询 +// *

+// * 支持如下: +// * 1. in +// * 2. = +// * 3. > +// * 4. < +// * 5. >= +// * 6. <= +// * 7. <> +// * 8. EXISTS +// * 9. NOT EXISTS +// *

+// * 前提条件: +// * 1. 子查询必须放在小括号中 +// * 2. 子查询一般放在比较操作符的右边 +// * +// * @param where where 条件 +// */ +// protected void processWhereSubSelect(Expression where) { +// if (where == null) { +// return; +// } +// if (where instanceof FromItem) { +// processFromItem((FromItem) where); +// return; +// } +// if (where.toString().indexOf("SELECT") > 0) { +// // 有子查询 +// if (where instanceof BinaryExpression) { +// // 比较符号 , and , or , 等等 +// BinaryExpression expression = (BinaryExpression) where; +// processWhereSubSelect(expression.getLeftExpression()); +// processWhereSubSelect(expression.getRightExpression()); +// } else if (where instanceof InExpression) { +// // in +// InExpression expression = (InExpression) where; +// ItemsList itemsList = expression.getRightItemsList(); +// if (itemsList instanceof SubSelect) { +// processSelectBody(((SubSelect) itemsList).getSelectBody()); +// } +// } else if (where instanceof ExistsExpression) { +// // exists +// ExistsExpression expression = (ExistsExpression) where; +// processWhereSubSelect(expression.getRightExpression()); +// } else if (where instanceof NotExpression) { +// // not exists +// NotExpression expression = (NotExpression) where; +// processWhereSubSelect(expression.getExpression()); +// } else if (where instanceof Parenthesis) { +// Parenthesis expression = (Parenthesis) where; +// processWhereSubSelect(expression.getExpression()); +// } +// } +// } +// +// /** +// * 处理子查询等 +// */ +// protected void processFromItem(FromItem fromItem) { +// if (fromItem instanceof SubJoin) { +// SubJoin subJoin = (SubJoin) fromItem; +// if (subJoin.getJoinList() != null) { +// subJoin.getJoinList().forEach(this::processJoin); +// } +// if (subJoin.getLeft() != null) { +// processFromItem(subJoin.getLeft()); +// } +// } else if (fromItem instanceof SubSelect) { +// SubSelect subSelect = (SubSelect) fromItem; +// if (subSelect.getSelectBody() != null) { +// processSelectBody(subSelect.getSelectBody()); +// } +// } else if (fromItem instanceof ValuesList) { +// logger.debug("Perform a subquery, if you do not give us feedback"); +// } else if (fromItem instanceof LateralSubSelect) { +// LateralSubSelect lateralSubSelect = (LateralSubSelect) fromItem; +// if (lateralSubSelect.getSubSelect() != null) { +// SubSelect subSelect = lateralSubSelect.getSubSelect(); +// if (subSelect.getSelectBody() != null) { +// processSelectBody(subSelect.getSelectBody()); +// } +// } +// } +// } +// +// /** +// * 处理联接语句 +// */ +// protected void processJoin(Join join) { +// if (join.getRightItem() instanceof Table) { +// Table fromTable = (Table) join.getRightItem(); +// if (!filter()) { +// // 过滤退出执行 +// return; +// } +// join.setOnExpression(builderExpression(join.getOnExpression(), fromTable)); +// } +// } +// +// /** +// * 处理条件 +// */ +// protected Expression builderExpression(Expression currentExpression, Table table) { +// +// DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.get(); +// DataPermission dataPermission = dataPermissionContext.getDataPermission(); +// +// // 接口未配置注解,就不需要自动增加sql +// if (dataPermission == null) { +// return currentExpression; +// } +// +// List byDataPermission = dataPermissionContextFactory.getRuleByDataPermission(); +// Optional first = byDataPermission.stream().filter(rule -> rule.getTableName().contains(table.getName())).findFirst(); +// if (!first.isPresent()) { +// return currentExpression; +// } +// DataPermissionRuleService dataPermissionRuleService = first.get(); +// Expression ruleExpression = dataPermissionRuleService.getExpression(table.getName(), table.getAlias()); +// if (currentExpression == null) { +// return ruleExpression; +// } +// if (currentExpression instanceof OrExpression) { +// return new AndExpression(new Parenthesis(currentExpression), ruleExpression); +// } else { +// return new AndExpression(currentExpression, ruleExpression); +// } +// } +// +// private boolean filter() { +// DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.get(); +// if (null == dataPermissionContext +// || dataPermissionContext.getDataPermission() == null +// || !dataPermissionContext.getDataPermission().enable()) { +// return false; +// } +// +// return true; +// } } diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/config/DataPermissionConfig.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/config/DataPermissionConfig.java index 015a57c..fa0d0e6 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/config/DataPermissionConfig.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/config/DataPermissionConfig.java @@ -13,20 +13,20 @@ import java.util.List; * @author tanjie@axzo.cn * @date 2024/5/31 16:34 */ -@ConditionalOnBean(MybatisPlusInterceptor.class) +//@ConditionalOnBean(MybatisPlusInterceptor.class) public class DataPermissionConfig { - @Bean - @ConditionalOnBean(MybatisPlusInterceptor.class) - public DataPermissionMybatisInterceptor mybatisDataPermissionInterceptor(MybatisPlusInterceptor mybatisPlusInterceptor, DataPermissionContextFactory dataPermissionContextFactory) { - DataPermissionMybatisInterceptor dataPermissionMybatisInterceptor = new DataPermissionMybatisInterceptor(dataPermissionContextFactory); - mybatisPlusInterceptor.addInnerInterceptor(dataPermissionMybatisInterceptor); - return dataPermissionMybatisInterceptor; - } - - - @Bean - public DataPermissionContextFactory dataPermissionRuleFactory(List rules) { - return new DataPermissionContextFactory(rules); - } +// @Bean +// @ConditionalOnBean(MybatisPlusInterceptor.class) +// public DataPermissionMybatisInterceptor mybatisDataPermissionInterceptor(MybatisPlusInterceptor mybatisPlusInterceptor, DataPermissionContextFactory dataPermissionContextFactory) { +// DataPermissionMybatisInterceptor dataPermissionMybatisInterceptor = new DataPermissionMybatisInterceptor(dataPermissionContextFactory); +// mybatisPlusInterceptor.addInnerInterceptor(dataPermissionMybatisInterceptor); +// return dataPermissionMybatisInterceptor; +// } +// +// +// @Bean +// public DataPermissionContextFactory dataPermissionRuleFactory(List rules) { +// return new DataPermissionContextFactory(rules); +// } } diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextFactory.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextFactory.java index 3822ef3..42226a5 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextFactory.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextFactory.java @@ -9,7 +9,7 @@ import java.util.List; * @author tanjie@axzo.cn * @date 2024/5/31 17:58 */ -@AllArgsConstructor +//@AllArgsConstructor public class DataPermissionContextFactory { List rules; diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextHolder.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextHolder.java index 20441a9..5a4af6a 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextHolder.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/context/DataPermissionContextHolder.java @@ -61,6 +61,11 @@ public class DataPermissionContextHolder { * 解析后的部门id */ private Set nodeIds; + + /** + * 数据权限解析后的单位id + */ + private Set ouIds; } public static void remove() { From 79cb3c315a787ee4582b5741eb61dcc4589bdaa6 Mon Sep 17 00:00:00 2001 From: lilong Date: Fri, 28 Jun 2024 14:58:55 +0800 Subject: [PATCH 16/27] =?UTF-8?q?feat=EF=BC=9A(REQ-2300)=20=E6=B3=A8?= =?UTF-8?q?=E9=87=8A=E6=95=B0=E6=8D=AE=E6=9D=83=E9=99=90=E8=A7=A3=E6=9E=90?= =?UTF-8?q?=EF=BC=8C=E7=94=B1=E7=94=A8=E6=88=B7=E6=98=BE=E7=A4=BA=E7=9A=84?= =?UTF-8?q?=E4=BC=A0=E9=80=92=E8=A7=A3=E6=9E=90=E7=BB=93=E6=9E=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../datapermission/aop/DataPermissionInterceptor.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionInterceptor.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionInterceptor.java index 179cb05..c023d2e 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionInterceptor.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionInterceptor.java @@ -108,12 +108,12 @@ public class DataPermissionInterceptor { AuthException.error(Objects.nonNull(httpRequest), "httpRequest cant be null, this is error"); - String dataPermissionHeader = httpRequest.getHeader(DATA_PERMISSION_HEADER); +// String dataPermissionHeader = httpRequest.getHeader(DATA_PERMISSION_HEADER); // header中有值,表示数据权限规则已经被解析,只需要获取数据去使用 - if (StringUtils.isBlank(dataPermissionHeader)) { +// if (StringUtils.isBlank(dataPermissionHeader)) { resolveRule(dataPermission); // return; - } +// } // DataPermissionContextHolder.DataPermissionContext dataPermissionContext = getCachedDataPermission(dataPermissionHeader); // dataPermissionContext.setDataPermission(dataPermission); From c176fbd9e20282d8a115594c8e0ee8d4986eac2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E6=98=86=E9=B9=8F?= Date: Thu, 11 Jul 2024 13:41:55 +0800 Subject: [PATCH 17/27] =?UTF-8?q?feat(REQ-2300)=EF=BC=9A=E8=BF=94=E5=9B=9E?= =?UTF-8?q?=E8=A7=A3=E6=9E=90=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../datapermission/advice/DataPermissionResponseExecutor.java | 1 + 1 file changed, 1 insertion(+) diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseExecutor.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseExecutor.java index 9b5d931..ab860e4 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseExecutor.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseExecutor.java @@ -53,6 +53,7 @@ public class DataPermissionResponseExecutor { .ouId(context.getOuId()) .personId(context.getPersonId()) .workspaceId(context.getWorkspaceId()) + .resultOrgNodeIdAndPersonIds(orgNodeIdAndPersonIds) .build(); // 调用karma获取数据列的校验结果 ExamineDpColumnsResp examineDpColumnsResp = RpcInternalUtil.rpcProcessor(() -> dataObjectApi.examineDpColumns(request), "data permission processNode", request).getData(); From 3f3d2bce500c6a4dd28506569a08ef6a8a4a7fb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E6=98=86=E9=B9=8F?= Date: Fri, 12 Jul 2024 10:42:21 +0800 Subject: [PATCH 18/27] =?UTF-8?q?feat(REQ-2300)=EF=BC=9A=E8=BF=94=E5=9B=9E?= =?UTF-8?q?=E8=A7=A3=E6=9E=90=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../datapermission/advice/DataPermissionResponseBodyAdvice.java | 1 + 1 file changed, 1 insertion(+) diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseBodyAdvice.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseBodyAdvice.java index 00fb904..55f8ea1 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseBodyAdvice.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseBodyAdvice.java @@ -71,6 +71,7 @@ public class DataPermissionResponseBodyAdvice implements ResponseBodyAdvice Date: Fri, 12 Jul 2024 10:54:37 +0800 Subject: [PATCH 19/27] =?UTF-8?q?feat(REQ-2300)=EF=BC=9A=E8=BF=94=E5=9B=9E?= =?UTF-8?q?=E8=A7=A3=E6=9E=90=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../advice/DataPermissionResponseBodyAdvice.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseBodyAdvice.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseBodyAdvice.java index 55f8ea1..9d9ce8a 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseBodyAdvice.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseBodyAdvice.java @@ -73,11 +73,11 @@ public class DataPermissionResponseBodyAdvice implements ResponseBodyAdvice Date: Fri, 12 Jul 2024 15:44:38 +0800 Subject: [PATCH 20/27] =?UTF-8?q?feat(REQ-2300)=EF=BC=9A=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E5=BC=82=E5=B8=B8=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../datapermission/aop/DataPermissionInterceptor.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionInterceptor.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionInterceptor.java index c023d2e..0dd7784 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionInterceptor.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionInterceptor.java @@ -15,10 +15,7 @@ import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.aspectj.lang.ProceedingJoinPoint; -import org.aspectj.lang.annotation.Around; -import org.aspectj.lang.annotation.Aspect; -import org.aspectj.lang.annotation.Before; -import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.annotation.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.core.annotation.Order; @@ -95,6 +92,12 @@ public class DataPermissionInterceptor { return pjp.proceed(pjp.getArgs()); } + @AfterThrowing(value = "(@within(cn.axzo.framework.datapermission.annotation.DataPermission) && @within(org.springframework.web.bind.annotation.RestController)) " + + "|| (@annotation(cn.axzo.framework.datapermission.annotation.DataPermission) && mappingAnnotations())", throwing = "e") + public void handleException(Exception e) { + DataPermissionContextHolder.remove(); + } + public void handle(DataPermission dataPermission) { HttpServletRequest httpRequest = null; From 87714c8798e065e55e03d61e8e5f5eec385cd66a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E6=98=86=E9=B9=8F?= Date: Mon, 22 Jul 2024 10:21:55 +0800 Subject: [PATCH 21/27] =?UTF-8?q?feat(REQ-2300)=EF=BC=9A=E5=8E=BB=E9=99=A4?= =?UTF-8?q?=E6=98=AF=E5=90=A6=E5=8F=AF=E8=A7=81=E5=AD=97=E6=AE=B5=E7=9A=84?= =?UTF-8?q?=E5=AD=97=E6=AE=B5=E5=8F=8A=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../advice/DataPermissionResponseExecutor.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseExecutor.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseExecutor.java index ab860e4..51cfbde 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseExecutor.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseExecutor.java @@ -103,9 +103,9 @@ public class DataPermissionResponseExecutor { ExamineDpColumnsResp.AttributePermissionBasicDTO basic = entry.getValue(); if (dataNode.has(basic.getAttrCode())) { ObjectNode objectNode = (ObjectNode) dataNode; - if (!ATTRIBUTE_ISUNMASKABLE.equals(basic.getIsUnmaskable())) { - objectNode.remove(basic.getAttrCode()); - } +// if (!ATTRIBUTE_ISUNMASKABLE.equals(basic.getIsUnmaskable())) { +// objectNode.remove(basic.getAttrCode()); +// } if (Objects.nonNull(basic.getIsEditable())) { objectNode.put(ATTRIBUTE_ADD_ALLOW_EDIT_PREFIX + basic.getAttrCode(), ATTRIBUTE_ISEDITABLE.equals(basic.getIsEditable())); } From 5b1b4c1b13252e615fb62871af4b31cc52d2158d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E6=98=86=E9=B9=8F?= Date: Tue, 23 Jul 2024 18:57:01 +0800 Subject: [PATCH 22/27] =?UTF-8?q?feat(REQ-2300)=EF=BC=9A=E6=81=A2=E5=A4=8D?= =?UTF-8?q?=E6=98=AF=E5=90=A6=E5=8F=AF=E8=A7=81=E5=AD=97=E6=AE=B5=E7=9A=84?= =?UTF-8?q?=E5=AD=97=E6=AE=B5=E5=8F=8A=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../advice/DataPermissionResponseExecutor.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseExecutor.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseExecutor.java index 51cfbde..ab860e4 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseExecutor.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseExecutor.java @@ -103,9 +103,9 @@ public class DataPermissionResponseExecutor { ExamineDpColumnsResp.AttributePermissionBasicDTO basic = entry.getValue(); if (dataNode.has(basic.getAttrCode())) { ObjectNode objectNode = (ObjectNode) dataNode; -// if (!ATTRIBUTE_ISUNMASKABLE.equals(basic.getIsUnmaskable())) { -// objectNode.remove(basic.getAttrCode()); -// } + if (!ATTRIBUTE_ISUNMASKABLE.equals(basic.getIsUnmaskable())) { + objectNode.remove(basic.getAttrCode()); + } if (Objects.nonNull(basic.getIsEditable())) { objectNode.put(ATTRIBUTE_ADD_ALLOW_EDIT_PREFIX + basic.getAttrCode(), ATTRIBUTE_ISEDITABLE.equals(basic.getIsEditable())); } From bf3e2c71e10618cb6b0090a4bd609e1c5c868f6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E6=98=86=E9=B9=8F?= Date: Wed, 24 Jul 2024 14:26:15 +0800 Subject: [PATCH 23/27] =?UTF-8?q?feat(REQ-2300)=EF=BC=9A=E5=AD=97=E6=AE=B5?= =?UTF-8?q?=E5=B1=95=E7=A4=BA=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../advice/DataPermissionResponseExecutor.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseExecutor.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseExecutor.java index ab860e4..803e873 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseExecutor.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseExecutor.java @@ -32,7 +32,8 @@ public class DataPermissionResponseExecutor { private static final Integer ATTRIBUTE_ISUNMASKABLE = 2; private static final Integer ATTRIBUTE_ISEDITABLE = 2; private static final String ATTRIBUTE_ADD_ALLOW_EDIT_PREFIX = "dp_allow_edit_"; - + private static final String ATTRIBUTE_ADD_ALLOW_DISPLAY_PREFIX = "dp_allow_display_"; + private final DataObjectApi dataObjectApi; public DataPermissionResponseExecutor(DataObjectApi dataObjectApi) { @@ -103,12 +104,12 @@ public class DataPermissionResponseExecutor { ExamineDpColumnsResp.AttributePermissionBasicDTO basic = entry.getValue(); if (dataNode.has(basic.getAttrCode())) { ObjectNode objectNode = (ObjectNode) dataNode; - if (!ATTRIBUTE_ISUNMASKABLE.equals(basic.getIsUnmaskable())) { - objectNode.remove(basic.getAttrCode()); - } if (Objects.nonNull(basic.getIsEditable())) { objectNode.put(ATTRIBUTE_ADD_ALLOW_EDIT_PREFIX + basic.getAttrCode(), ATTRIBUTE_ISEDITABLE.equals(basic.getIsEditable())); } + if (Objects.nonNull(basic.getIsUnmaskable())) { + objectNode.put(ATTRIBUTE_ADD_ALLOW_DISPLAY_PREFIX + basic.getAttrCode(), ATTRIBUTE_ISUNMASKABLE.equals(basic.getIsUnmaskable())); + } } } } From 7879529f1244e7b5db3e2098885b298dbca2b7cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E6=98=86=E9=B9=8F?= Date: Fri, 26 Jul 2024 15:42:21 +0800 Subject: [PATCH 24/27] =?UTF-8?q?feat(REQ-2300)=EF=BC=9A=E5=AD=97=E6=AE=B5?= =?UTF-8?q?=E5=B1=95=E7=A4=BA=E5=A4=84=E7=90=86=E8=A7=A3=E6=9E=90=E5=A4=84?= =?UTF-8?q?=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DataPermissionResponseExecutor.java | 47 +++++++++---------- 1 file changed, 21 insertions(+), 26 deletions(-) diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseExecutor.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseExecutor.java index 803e873..c7bbec0 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseExecutor.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseExecutor.java @@ -9,16 +9,13 @@ import cn.axzo.karma.client.feign.tyr.response.ExamineDpColumnsResp; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; -import com.google.common.collect.Lists; +import com.google.common.collect.Sets; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.MapUtils; import org.springframework.stereotype.Component; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Objects; +import java.util.*; /** * @author likunpeng @@ -43,10 +40,10 @@ public class DataPermissionResponseExecutor { public void processNode(DataPermissionContextHolder.DataPermissionContext context, JsonNode dataNode) { DataPermission dataPermission = context.getDataPermission(); - List orgNodeIdAndPersonIds = Lists.newArrayList(); - recursiveGetOrgNodeIdAndPersonIds(dataPermission, dataNode, orgNodeIdAndPersonIds); - if (CollectionUtils.isEmpty(orgNodeIdAndPersonIds)) { - log.warn("api result has no organizationalNodeId and personId, not examine data permission for result columns."); + Set personIds = Sets.newHashSet(); + recursiveGetPersonIds(dataPermission, dataNode, personIds); + if (CollectionUtils.isEmpty(personIds)) { + log.warn("api result has no personId, not examine data permission for result columns."); return; } ExamineDpColumnsReq request = ExamineDpColumnsReq.builder() @@ -54,7 +51,7 @@ public class DataPermissionResponseExecutor { .ouId(context.getOuId()) .personId(context.getPersonId()) .workspaceId(context.getWorkspaceId()) - .resultOrgNodeIdAndPersonIds(orgNodeIdAndPersonIds) + .resultPersonIds(personIds) .build(); // 调用karma获取数据列的校验结果 ExamineDpColumnsResp examineDpColumnsResp = RpcInternalUtil.rpcProcessor(() -> dataObjectApi.examineDpColumns(request), "data permission processNode", request).getData(); @@ -62,15 +59,13 @@ public class DataPermissionResponseExecutor { return; } // 根据karma数据列的校验结果,处理api结果的数据对象 - recursiveProcessOrgNodeIdAndPersonIds(dataPermission, dataNode, examineDpColumnsResp.getAttributeDpResultMap()); + recursiveProcessPersonIds(dataPermission, dataNode, examineDpColumnsResp.getAttributeDpResultMap()); } - private void recursiveGetOrgNodeIdAndPersonIds(DataPermission dataPermission, JsonNode dataNode, List orgNodeIdAndPersonIds) { + private void recursiveGetPersonIds(DataPermission dataPermission, JsonNode dataNode, Set personIds) { if (dataNode.isObject()) { - Long resultOrganizationalNodeId = Objects.nonNull(dataNode.get(dataPermission.key_organizationalNodeId())) ? dataNode.get(dataPermission.key_organizationalNodeId()).asLong() : 0L; - Long resultPersonId = Objects.nonNull(dataNode.get(dataPermission.key_personId())) ? dataNode.get(dataPermission.key_personId()).asLong() : 0L; - if (!resultOrganizationalNodeId.equals(0L) || !resultPersonId.equals(0L)) { - orgNodeIdAndPersonIds.add(ExamineDpColumnsReq.OrgNodeIdAndPersonId.builder().organizationalNodeId(resultOrganizationalNodeId).personId(resultPersonId).build()); + if (Objects.nonNull(dataNode.get(dataPermission.key_personId()))) { + personIds.add(dataNode.get(dataPermission.key_personId()).asLong()); } // 循环处理子field Iterator> fields = dataNode.fields(); @@ -78,7 +73,7 @@ public class DataPermissionResponseExecutor { Map.Entry entry = fields.next(); JsonNode value = entry.getValue(); if (value.isContainerNode()) { - recursiveGetOrgNodeIdAndPersonIds(dataPermission, value, orgNodeIdAndPersonIds); + recursiveGetPersonIds(dataPermission, value, personIds); } } } @@ -87,18 +82,18 @@ public class DataPermissionResponseExecutor { Iterator elements = arrayNode.elements(); while (elements.hasNext()) { JsonNode element = elements.next(); - recursiveGetOrgNodeIdAndPersonIds(dataPermission, element, orgNodeIdAndPersonIds); + recursiveGetPersonIds(dataPermission, element, personIds); } } } - private void recursiveProcessOrgNodeIdAndPersonIds(DataPermission dataPermission, JsonNode dataNode, - Map> attributeDpResultMap) { + private void recursiveProcessPersonIds(DataPermission dataPermission, JsonNode dataNode, + Map> attributeDpResultMap) { if (dataNode.isObject()) { - Long resultOrganizationalNodeId = Objects.nonNull(dataNode.get(dataPermission.key_organizationalNodeId())) ? dataNode.get(dataPermission.key_organizationalNodeId()).asLong() : 0L; - Long resultPersonId = Objects.nonNull(dataNode.get(dataPermission.key_personId())) ? dataNode.get(dataPermission.key_personId()).asLong() : 0L; - if (!resultOrganizationalNodeId.equals(0L) || !resultPersonId.equals(0L)) { - Map attributeMap = attributeDpResultMap.get(resultOrganizationalNodeId + "_" + resultPersonId); + Long resultPersonId = Objects.nonNull(dataNode.get(dataPermission.key_personId())) ? dataNode.get(dataPermission.key_personId()).asLong() : null; + + if (Objects.nonNull(resultPersonId)) { + Map attributeMap = attributeDpResultMap.get(resultPersonId); if (MapUtils.isNotEmpty(attributeMap)) { for (Map.Entry entry : attributeMap.entrySet()) { ExamineDpColumnsResp.AttributePermissionBasicDTO basic = entry.getValue(); @@ -121,7 +116,7 @@ public class DataPermissionResponseExecutor { Map.Entry entry = fields.next(); JsonNode value = entry.getValue(); if (value.isContainerNode()) { - recursiveProcessOrgNodeIdAndPersonIds(dataPermission, value, attributeDpResultMap); + recursiveProcessPersonIds(dataPermission, value, attributeDpResultMap); } } } @@ -131,7 +126,7 @@ public class DataPermissionResponseExecutor { Iterator elements = arrayNode.elements(); while (elements.hasNext()) { JsonNode element = elements.next(); - recursiveProcessOrgNodeIdAndPersonIds(dataPermission, element, attributeDpResultMap); + recursiveProcessPersonIds(dataPermission, element, attributeDpResultMap); } } } From 52f5e9b5464404fe6a9ed29b7169945c179a1970 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E6=98=86=E9=B9=8F?= Date: Fri, 26 Jul 2024 18:48:02 +0800 Subject: [PATCH 25/27] =?UTF-8?q?feat(REQ-2300)=EF=BC=9A=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E6=8F=90=E4=BA=A4=E6=95=B0=E6=8D=AE=E7=9A=84workspaceId?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../annotation/DataPermission.java | 6 ++++ .../aop/DataPermissionInterceptor.java | 36 ++++++++++++++++--- 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/annotation/DataPermission.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/annotation/DataPermission.java index 6d291ad..1f54bb3 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/annotation/DataPermission.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/annotation/DataPermission.java @@ -34,4 +34,10 @@ public @interface DataPermission { */ String key_personId() default "personId"; + /** + * 请求体的workspaceId + * + * @return + */ + String requestBodyWorkspaceId() default ""; } diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionInterceptor.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionInterceptor.java index 0dd7784..327de97 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionInterceptor.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionInterceptor.java @@ -11,6 +11,8 @@ import cn.axzo.karma.client.feign.tyr.request.GetMergeMatchDataReq; import cn.axzo.karma.client.feign.tyr.request.MatchDataObjectReq; import cn.axzo.karma.client.feign.tyr.response.MatchDataObjectResp; import cn.axzo.karma.client.feign.tyr.response.MergeMatchDataResp; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; @@ -27,6 +29,7 @@ import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; import java.util.Objects; import java.util.Optional; +import java.util.stream.Collectors; import static cn.axzo.framework.datapermission.context.DataPermissionContextHolder.DATA_PERMISSION_HEADER; @@ -114,7 +117,7 @@ public class DataPermissionInterceptor { // String dataPermissionHeader = httpRequest.getHeader(DATA_PERMISSION_HEADER); // header中有值,表示数据权限规则已经被解析,只需要获取数据去使用 // if (StringUtils.isBlank(dataPermissionHeader)) { - resolveRule(dataPermission); + resolveRule(dataPermission, httpRequest); // return; // } @@ -127,14 +130,14 @@ public class DataPermissionInterceptor { * 解析数据权限规则 * @param dataPermission */ - private void resolveRule(DataPermission dataPermission) { + private void resolveRule(DataPermission dataPermission, HttpServletRequest httpRequest) { ContextInfo contextInfo = ContextInfoHolder.get(); if (contextInfo == null || contextInfo.getUserInfo() == null || StringUtils.isBlank(dataPermission.bizCode())) { return; } - Optional matchDataObjectOptional = this.matchRule(dataPermission); + Optional matchDataObjectOptional = this.matchRule(dataPermission, httpRequest); if (!matchDataObjectOptional.isPresent()) { log.warn("no match data rule, bizCode:{}, personId:{}, ouId:{}, workspaceId:{}", dataPermission.bizCode(), @@ -155,14 +158,22 @@ public class DataPermissionInterceptor { DataPermissionContextHolder.setContext(dataPermissionContext); } - private Optional matchRule(DataPermission dataPermission) { + private Optional matchRule(DataPermission dataPermission, HttpServletRequest httpRequest) { ContextInfo contextInfo = ContextInfoHolder.get(); + Long workspaceId = null; + String requestBodyWorkspaceId = dataPermission.requestBodyWorkspaceId(); + if (StringUtils.isNotBlank(requestBodyWorkspaceId)) { + workspaceId = getRequestBodyWorkspaceId(httpRequest, requestBodyWorkspaceId); + } + if (Objects.isNull(workspaceId)) { + workspaceId = contextInfo.getWorkspaceId(); + } MatchDataObjectReq matchDataObjectReq = MatchDataObjectReq.builder() .dataObjectCode(dataPermission.bizCode()) .ouId(contextInfo.getOuId()) - .workspaceId(contextInfo.getWorkspaceId()) + .workspaceId(workspaceId) .personId(contextInfo.getUserInfo().getPersonId()) .build(); @@ -190,4 +201,19 @@ public class DataPermissionInterceptor { dataPermissionContext.setPersonIds(mergeMatchDataResp.getPersonIds()); return dataPermissionContext; } + + private Long getRequestBodyWorkspaceId(HttpServletRequest httpRequest, String requestBodyWorkspaceIdKey) { + try { + String requestBody = httpRequest.getReader().lines().collect(Collectors.joining(System.lineSeparator())); + ObjectMapper mapper = new ObjectMapper(); + JsonNode rootNode = mapper.readTree(requestBody); + String workspaceId = rootNode.path(requestBodyWorkspaceIdKey).asText(); + if (StringUtils.isNotBlank(workspaceId)) { + return Long.valueOf(workspaceId); + } + } catch (Exception e) { + log.warn("获取提交body里面的workspaceId出错", e); + } + return null; + } } From bcef59ffd2ac431f52a8588280024337718815fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E6=98=86=E9=B9=8F?= Date: Tue, 30 Jul 2024 10:23:44 +0800 Subject: [PATCH 26/27] =?UTF-8?q?feat(REQ-2300)=EF=BC=9A=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E6=8F=90=E4=BA=A4=E6=95=B0=E6=8D=AE=E7=9A=84workspaceId?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../aop/DataPermissionInterceptor.java | 26 +++++++++---------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionInterceptor.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionInterceptor.java index 327de97..0a0937d 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionInterceptor.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/aop/DataPermissionInterceptor.java @@ -137,7 +137,9 @@ public class DataPermissionInterceptor { return; } - Optional matchDataObjectOptional = this.matchRule(dataPermission, httpRequest); + Long responseBodyWorkspaceId = getRequestBodyWorkspaceId(httpRequest, dataPermission); + + Optional matchDataObjectOptional = this.matchRule(dataPermission, responseBodyWorkspaceId); if (!matchDataObjectOptional.isPresent()) { log.warn("no match data rule, bizCode:{}, personId:{}, ouId:{}, workspaceId:{}", dataPermission.bizCode(), @@ -149,7 +151,7 @@ public class DataPermissionInterceptor { DataPermissionContextHolder.DataPermissionContext dataPermissionContext = DataPermissionContextHolder.DataPermissionContext.builder() .dataPermission(dataPermission) - .workspaceId(contextInfo.getWorkspaceId()) + .workspaceId(Objects.nonNull(responseBodyWorkspaceId) ? responseBodyWorkspaceId : contextInfo.getWorkspaceId()) .ouId(contextInfo.getOuId()) .personId(contextInfo.getUserInfo().getPersonId()) .resultKey(matchDataObjectOptional.get().getResultKey()) @@ -158,22 +160,14 @@ public class DataPermissionInterceptor { DataPermissionContextHolder.setContext(dataPermissionContext); } - private Optional matchRule(DataPermission dataPermission, HttpServletRequest httpRequest) { + private Optional matchRule(DataPermission dataPermission, Long responseBodyWorkspaceId) { ContextInfo contextInfo = ContextInfoHolder.get(); - Long workspaceId = null; - String requestBodyWorkspaceId = dataPermission.requestBodyWorkspaceId(); - if (StringUtils.isNotBlank(requestBodyWorkspaceId)) { - workspaceId = getRequestBodyWorkspaceId(httpRequest, requestBodyWorkspaceId); - } - if (Objects.isNull(workspaceId)) { - workspaceId = contextInfo.getWorkspaceId(); - } MatchDataObjectReq matchDataObjectReq = MatchDataObjectReq.builder() .dataObjectCode(dataPermission.bizCode()) .ouId(contextInfo.getOuId()) - .workspaceId(workspaceId) + .workspaceId(Objects.nonNull(responseBodyWorkspaceId) ? responseBodyWorkspaceId : contextInfo.getWorkspaceId()) .personId(contextInfo.getUserInfo().getPersonId()) .build(); @@ -202,12 +196,16 @@ public class DataPermissionInterceptor { return dataPermissionContext; } - private Long getRequestBodyWorkspaceId(HttpServletRequest httpRequest, String requestBodyWorkspaceIdKey) { + private Long getRequestBodyWorkspaceId(HttpServletRequest httpRequest, DataPermission dataPermission) { try { + String requestBodyWorkspaceId = dataPermission.requestBodyWorkspaceId(); + if (StringUtils.isBlank(requestBodyWorkspaceId)) { + return null; + } String requestBody = httpRequest.getReader().lines().collect(Collectors.joining(System.lineSeparator())); ObjectMapper mapper = new ObjectMapper(); JsonNode rootNode = mapper.readTree(requestBody); - String workspaceId = rootNode.path(requestBodyWorkspaceIdKey).asText(); + String workspaceId = rootNode.path(requestBodyWorkspaceId).asText(); if (StringUtils.isNotBlank(workspaceId)) { return Long.valueOf(workspaceId); } From 834450c9330fa0c9ec7fbb9bdabbf7f0bd3630f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E6=98=86=E9=B9=8F?= Date: Wed, 31 Jul 2024 11:08:22 +0800 Subject: [PATCH 27/27] =?UTF-8?q?feat(REQ-2300)=EF=BC=9A=E5=88=97=E5=AD=97?= =?UTF-8?q?=E6=AE=B5=E5=A4=84=E7=90=86=E5=A2=9E=E5=8A=A0=E6=98=AF=E5=90=A6?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E9=9A=90=E8=97=8F=E5=AD=97=E6=AE=B5=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../datapermission/advice/DataPermissionResponseExecutor.java | 3 +++ .../framework/datapermission/annotation/DataPermission.java | 3 +++ 2 files changed, 6 insertions(+) diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseExecutor.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseExecutor.java index c7bbec0..4fbffba 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseExecutor.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/advice/DataPermissionResponseExecutor.java @@ -105,6 +105,9 @@ public class DataPermissionResponseExecutor { if (Objects.nonNull(basic.getIsUnmaskable())) { objectNode.put(ATTRIBUTE_ADD_ALLOW_DISPLAY_PREFIX + basic.getAttrCode(), ATTRIBUTE_ISUNMASKABLE.equals(basic.getIsUnmaskable())); } + if (dataPermission.removeNotDisplayColumn() && !ATTRIBUTE_ISUNMASKABLE.equals(basic.getIsUnmaskable())) { + objectNode.remove(basic.getAttrCode()); + } } } } diff --git a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/annotation/DataPermission.java b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/annotation/DataPermission.java index 1f54bb3..03eba83 100644 --- a/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/annotation/DataPermission.java +++ b/axzo-common-data-permission/src/main/java/cn/axzo/framework/datapermission/annotation/DataPermission.java @@ -40,4 +40,7 @@ public @interface DataPermission { * @return */ String requestBodyWorkspaceId() default ""; + + /** 是否删除不展示的字段列 **/ + boolean removeNotDisplayColumn() default false; }