|
@@ -1,197 +0,0 @@
|
|
|
-package com.citu.module.menduner.system.config.permission;
|
|
|
|
|
-
|
|
|
|
|
-import cn.hutool.core.collection.CollUtil;
|
|
|
|
|
-import cn.hutool.core.text.CharSequenceUtil;
|
|
|
|
|
-import cn.hutool.core.util.ObjectUtil;
|
|
|
|
|
-import cn.hutool.core.util.StrUtil;
|
|
|
|
|
-import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
|
|
|
|
|
-import com.citu.framework.common.enums.UserTypeEnum;
|
|
|
|
|
-import com.citu.framework.common.util.collection.CollectionUtils;
|
|
|
|
|
-import com.citu.framework.common.util.json.JsonUtils;
|
|
|
|
|
-import com.citu.framework.datapermission.core.rule.DataPermissionRule;
|
|
|
|
|
-import com.citu.framework.mybatis.core.dataobject.BaseDO;
|
|
|
|
|
-import com.citu.framework.mybatis.core.util.MyBatisUtils;
|
|
|
|
|
-import com.citu.framework.security.core.LoginUser;
|
|
|
|
|
-import com.citu.framework.security.core.util.SecurityFrameworkUtils;
|
|
|
|
|
-import com.citu.module.menduner.system.api.permission.MendunerPermissionApi;
|
|
|
|
|
-import com.citu.module.menduner.common.util.LoginUserContext;
|
|
|
|
|
-import com.citu.module.system.api.permission.dto.DataPermissionRespDTO;
|
|
|
|
|
-import lombok.AllArgsConstructor;
|
|
|
|
|
-import lombok.extern.slf4j.Slf4j;
|
|
|
|
|
-import net.sf.jsqlparser.expression.*;
|
|
|
|
|
-import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
|
|
|
|
|
-import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
|
|
|
|
|
-import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
|
|
|
|
|
-import net.sf.jsqlparser.expression.operators.relational.InExpression;
|
|
|
|
|
-
|
|
|
|
|
-import java.util.HashMap;
|
|
|
|
|
-import java.util.HashSet;
|
|
|
|
|
-import java.util.Map;
|
|
|
|
|
-import java.util.Set;
|
|
|
|
|
-
|
|
|
|
|
-import static com.citu.module.menduner.common.util.LoginUserContext.checkEnterprise;
|
|
|
|
|
-
|
|
|
|
|
-/**
|
|
|
|
|
- * @author Rayson
|
|
|
|
|
- * @description CustomDataPermissionRule
|
|
|
|
|
- * 基于自定义的 {@link DataPermissionRule} 数据权限规则实现
|
|
|
|
|
- * @create 2024/5/8 下午7:41
|
|
|
|
|
- **/
|
|
|
|
|
-@AllArgsConstructor
|
|
|
|
|
-@Slf4j
|
|
|
|
|
-public class CustomDataPermissionRule implements DataPermissionRule {
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * LoginUser 的 Context 缓存 Key
|
|
|
|
|
- */
|
|
|
|
|
- protected static final String CONTEXT_KEY = CustomDataPermissionRule.class.getSimpleName();
|
|
|
|
|
-
|
|
|
|
|
- static final Expression EXPRESSION_NULL = new NullValue();
|
|
|
|
|
- /**
|
|
|
|
|
- * 基于数据的表字段配置 TODO 目前只支持一个数据权限字段,xx_id 和 user_id 不能同时配置。
|
|
|
|
|
- * 如基于部门的数据编号字段是 自定义xx_id,基于店铺的数据编号字段是 shop_id,通过该配置自定义,如 group_id。
|
|
|
|
|
- * <p>
|
|
|
|
|
- * key:表名
|
|
|
|
|
- * value:字段名
|
|
|
|
|
- */
|
|
|
|
|
- private final static Map<String, String> DATA_COLUMNS = new HashMap<>();
|
|
|
|
|
- /**
|
|
|
|
|
- * 基于用户的表字段配置
|
|
|
|
|
- * 一般情况下,每个表的数据编号字段是 user_id,通过该配置自定义,如 admin_user_id。
|
|
|
|
|
- * <p>
|
|
|
|
|
- * key:表名
|
|
|
|
|
- * value:字段名
|
|
|
|
|
- */
|
|
|
|
|
- private final static Map<String, String> USER_COLUMNS = new HashMap<>();
|
|
|
|
|
- /**
|
|
|
|
|
- * 所有表名,是 {@link #DATA_COLUMNS} 和 {@link #USER_COLUMNS} 的合集
|
|
|
|
|
- */
|
|
|
|
|
- private final static Set<String> TABLE_NAMES = new HashSet<>();
|
|
|
|
|
-
|
|
|
|
|
- private final MendunerPermissionApi permissionApi;
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public Set<String> getTableNames() {
|
|
|
|
|
- return TABLE_NAMES;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public Expression getExpression(String tableName, Alias tableAlias) {
|
|
|
|
|
- // 只有登陆用户的情况下,才进行数据权限的处理
|
|
|
|
|
- LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
|
|
|
|
|
- if (loginUser == null) {
|
|
|
|
|
- return null;
|
|
|
|
|
- }
|
|
|
|
|
- // 只有MEMBER_ADMIN类型的用户,才进行数据权限的处理
|
|
|
|
|
- if (ObjectUtil.notEqual(loginUser.getUserType(), UserTypeEnum.MEMBER_ADMIN.getValue())) {
|
|
|
|
|
- return null;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (!checkEnterprise(loginUser)) {
|
|
|
|
|
- // 没有企业id
|
|
|
|
|
- return null;
|
|
|
|
|
- }
|
|
|
|
|
- // 获得数据权限
|
|
|
|
|
- DataPermissionRespDTO dataPermission = loginUser.getContext(CONTEXT_KEY, DataPermissionRespDTO.class);
|
|
|
|
|
- // 从上下文中拿不到,则调用逻辑进行获取
|
|
|
|
|
- if (dataPermission == null) {
|
|
|
|
|
- Long enterpriseId = LoginUserContext.getEnterpriseId(loginUser);
|
|
|
|
|
- dataPermission = permissionApi.getDataPermission(loginUser.getId(), enterpriseId).getCheckedData();
|
|
|
|
|
- if (dataPermission == null) {
|
|
|
|
|
- log.error("[getExpression][LoginUser({}) 获取数据权限为 null]", JsonUtils.toJsonString(loginUser));
|
|
|
|
|
- throw new NullPointerException(String.format("LoginUser(%d) Table(%s/%s) 未返回数据权限",
|
|
|
|
|
- loginUser.getId(), tableName, tableAlias.getName()));
|
|
|
|
|
- }
|
|
|
|
|
- // 添加到上下文中,避免重复计算
|
|
|
|
|
- loginUser.setContext(CONTEXT_KEY, dataPermission);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 情况一,如果是 ALL 可查看全部,则无需拼接条件
|
|
|
|
|
- if (dataPermission.getAll()) {
|
|
|
|
|
- return null;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 情况二,即不能查看部门,又不能查看自己,则说明 100% 无权限
|
|
|
|
|
- if (CollUtil.isEmpty(dataPermission.getDataIds())
|
|
|
|
|
- && Boolean.FALSE.equals(dataPermission.getSelf())) {
|
|
|
|
|
- return new EqualsTo(null, null); // WHERE null = null,可以保证返回的数据为空
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 情况三,拼接 Dept 和 User 的条件,最后组合
|
|
|
|
|
- Expression dataExpression = buildDeptExpression(tableName, tableAlias, dataPermission.getDataIds());
|
|
|
|
|
- Expression userExpression = buildUserExpression(tableName, tableAlias, dataPermission.getSelf(), loginUser.getId());
|
|
|
|
|
- if (dataExpression == null && userExpression == null) {
|
|
|
|
|
- // TODO 芋艿:获得不到条件的时候,暂时不抛出异常,而是不返回数据
|
|
|
|
|
- log.warn("[getExpression][LoginUser({}) Table({}/{}) DeptDataPermission({}) 构建的条件为空]",
|
|
|
|
|
- JsonUtils.toJsonString(loginUser), tableName, tableAlias, JsonUtils.toJsonString(dataPermission));
|
|
|
|
|
- return EXPRESSION_NULL; // AND NULL
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (dataExpression == null) {
|
|
|
|
|
- return userExpression;
|
|
|
|
|
- }
|
|
|
|
|
- if (userExpression == null) {
|
|
|
|
|
- return dataExpression;
|
|
|
|
|
- }
|
|
|
|
|
- // // 目前,如果有指定数据 + 可查看自己,采用 OR 条件。即,WHERE (xx_id IN ? OR user_id = ?)
|
|
|
|
|
- // return new Parenthesis(new OrExpression(dataExpression, userExpression));
|
|
|
|
|
- // 改为 AND 条件。即,WHERE (xx_id IN ? and user_id = ?)
|
|
|
|
|
- return new Parenthesis(new AndExpression(dataExpression, userExpression));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private Expression buildDeptExpression(String tableName, Alias tableAlias, Set<Long> dataIds) {
|
|
|
|
|
- // 如果不存在配置,则无需作为条件
|
|
|
|
|
- String columnName = DATA_COLUMNS.get(tableName);
|
|
|
|
|
- if (StrUtil.isEmpty(columnName)) {
|
|
|
|
|
- return null;
|
|
|
|
|
- }
|
|
|
|
|
- // 如果为空,则无条件
|
|
|
|
|
- if (CollUtil.isEmpty(dataIds)) {
|
|
|
|
|
- return null;
|
|
|
|
|
- }
|
|
|
|
|
- // 拼接条件
|
|
|
|
|
- return new InExpression(MyBatisUtils.buildColumn(tableName, tableAlias, columnName),
|
|
|
|
|
- new ExpressionList(CollectionUtils.convertList(dataIds, LongValue::new)));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private Expression buildUserExpression(String tableName, Alias tableAlias, Boolean self, Long userId) {
|
|
|
|
|
- // 如果不查看自己,则无需作为条件
|
|
|
|
|
- if (Boolean.FALSE.equals(self)) {
|
|
|
|
|
- return null;
|
|
|
|
|
- }
|
|
|
|
|
- String columnName = USER_COLUMNS.get(tableName);
|
|
|
|
|
- if (StrUtil.isEmpty(columnName)) {
|
|
|
|
|
- return null;
|
|
|
|
|
- }
|
|
|
|
|
- // 拼接条件
|
|
|
|
|
- return new EqualsTo(MyBatisUtils.buildColumn(tableName, tableAlias, columnName), new LongValue(userId));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // ==================== 添加配置 ====================
|
|
|
|
|
- public void addDataColumn(Class<? extends BaseDO> entityClass, String columnName) {
|
|
|
|
|
- String tableName = TableInfoHelper.getTableInfo(entityClass).getTableName();
|
|
|
|
|
- addDataColumn(tableName, columnName);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- public void addDataColumn(String tableName, String columnName) {
|
|
|
|
|
- if (CharSequenceUtil.isEmpty(tableName)) {
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- DATA_COLUMNS.put(tableName, columnName);
|
|
|
|
|
- TABLE_NAMES.add(tableName);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public void addUserColumn(Class<? extends BaseDO> entityClass, String columnName) {
|
|
|
|
|
- String tableName = TableInfoHelper.getTableInfo(entityClass).getTableName();
|
|
|
|
|
- addUserColumn(tableName, columnName);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public void addUserColumn(String tableName, String columnName) {
|
|
|
|
|
- if (CharSequenceUtil.isEmpty(tableName)) {
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- USER_COLUMNS.put(tableName, columnName);
|
|
|
|
|
- TABLE_NAMES.add(tableName);
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|