diff --git a/continew-starter-extension/continew-starter-extension-datapermission/continew-starter-extension-datapermission-core/src/main/java/top/continew/starter/extension/datapermission/constant/DataPermissionConstants.java b/continew-starter-extension/continew-starter-extension-datapermission/continew-starter-extension-datapermission-core/src/main/java/top/continew/starter/extension/datapermission/constant/DataPermissionConstants.java
new file mode 100644
index 00000000..33e79c66
--- /dev/null
+++ b/continew-starter-extension/continew-starter-extension-datapermission/continew-starter-extension-datapermission-core/src/main/java/top/continew/starter/extension/datapermission/constant/DataPermissionConstants.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
+ *
+ * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package top.continew.starter.extension.datapermission.constant;
+
+/**
+ * 数据权限常量
+ *
+ * @author Charles7c
+ * @since 2.13.2
+ */
+public final class DataPermissionConstants {
+
+ /**
+ * 数据库字段:祖先节点
+ */
+ public static final String ANCESTORS_COLUMN = "ancestors";
+
+ /**
+ * 方法名后缀:COUNT
+ */
+ public static final String COUNT_METHOD_SUFFIX = "_COUNT";
+
+ private DataPermissionConstants() {
+ }
+}
\ No newline at end of file
diff --git a/continew-starter-extension/continew-starter-extension-datapermission/continew-starter-extension-datapermission-core/src/main/java/top/continew/starter/extension/datapermission/exception/DataPermissionException.java b/continew-starter-extension/continew-starter-extension-datapermission/continew-starter-extension-datapermission-core/src/main/java/top/continew/starter/extension/datapermission/exception/DataPermissionException.java
new file mode 100644
index 00000000..89d20d51
--- /dev/null
+++ b/continew-starter-extension/continew-starter-extension-datapermission/continew-starter-extension-datapermission-core/src/main/java/top/continew/starter/extension/datapermission/exception/DataPermissionException.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
+ *
+ * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package top.continew.starter.extension.datapermission.exception;
+
+import top.continew.starter.core.exception.BaseException;
+
+/**
+ * 数据权限异常
+ *
+ * @author Charles7c
+ * @since 2.13.2
+ */
+public class DataPermissionException extends BaseException {
+
+ public DataPermissionException(String message) {
+ super(message);
+ }
+
+ public DataPermissionException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public static DataPermissionException unsupportedDataScope(String dataScope) {
+ return new DataPermissionException("Unsupported data scope: " + dataScope);
+ }
+
+ public static DataPermissionException unsupportedDatabase(String database) {
+ return new DataPermissionException("Unsupported database for data permission: " + database);
+ }
+
+ public static DataPermissionException invalidUserData(String message) {
+ return new DataPermissionException("Invalid user data: " + message);
+ }
+
+ public static DataPermissionException methodNotFound(String mappedStatementId) {
+ return new DataPermissionException("Method not found for data permission: " + mappedStatementId);
+ }
+}
\ No newline at end of file
diff --git a/continew-starter-extension/continew-starter-extension-datapermission/continew-starter-extension-datapermission-core/src/main/java/top/continew/starter/extension/datapermission/model/RoleData.java b/continew-starter-extension/continew-starter-extension-datapermission/continew-starter-extension-datapermission-core/src/main/java/top/continew/starter/extension/datapermission/model/RoleData.java
index cbc6ef44..387c527a 100644
--- a/continew-starter-extension/continew-starter-extension-datapermission/continew-starter-extension-datapermission-core/src/main/java/top/continew/starter/extension/datapermission/model/RoleData.java
+++ b/continew-starter-extension/continew-starter-extension-datapermission/continew-starter-extension-datapermission-core/src/main/java/top/continew/starter/extension/datapermission/model/RoleData.java
@@ -29,7 +29,7 @@ public class RoleData {
/**
* 角色 ID
*/
- private String roleId;
+ private Long roleId;
/**
* 数据权限
@@ -39,16 +39,16 @@ public class RoleData {
public RoleData() {
}
- public RoleData(String roleId, DataScope dataScope) {
+ public RoleData(Long roleId, DataScope dataScope) {
this.roleId = roleId;
this.dataScope = dataScope;
}
- public String getRoleId() {
+ public Long getRoleId() {
return roleId;
}
- public void setRoleId(String roleId) {
+ public void setRoleId(Long roleId) {
this.roleId = roleId;
}
diff --git a/continew-starter-extension/continew-starter-extension-datapermission/continew-starter-extension-datapermission-core/src/main/java/top/continew/starter/extension/datapermission/model/UserData.java b/continew-starter-extension/continew-starter-extension-datapermission/continew-starter-extension-datapermission-core/src/main/java/top/continew/starter/extension/datapermission/model/UserData.java
index dbf69a01..5844a1cc 100644
--- a/continew-starter-extension/continew-starter-extension-datapermission/continew-starter-extension-datapermission-core/src/main/java/top/continew/starter/extension/datapermission/model/UserData.java
+++ b/continew-starter-extension/continew-starter-extension-datapermission/continew-starter-extension-datapermission-core/src/main/java/top/continew/starter/extension/datapermission/model/UserData.java
@@ -16,6 +16,7 @@
package top.continew.starter.extension.datapermission.model;
+import java.util.Collections;
import java.util.Set;
/**
@@ -29,23 +30,32 @@ public class UserData {
/**
* 用户 ID
*/
- private String userId;
+ private Long userId;
/**
* 角色列表
*/
- private Set roles;
+ private Set roles = Collections.emptySet();
/**
* 部门 ID
*/
- private String deptId;
+ private Long deptId;
- public String getUserId() {
+ public UserData() {
+ }
+
+ public UserData(Long userId, Long deptId, Set roles) {
+ this.userId = userId;
+ this.deptId = deptId;
+ this.roles = roles != null ? roles : Collections.emptySet();
+ }
+
+ public Long getUserId() {
return userId;
}
- public void setUserId(String userId) {
+ public void setUserId(Long userId) {
this.userId = userId;
}
@@ -54,14 +64,23 @@ public class UserData {
}
public void setRoles(Set roles) {
- this.roles = roles;
+ this.roles = roles != null ? roles : Collections.emptySet();
}
- public String getDeptId() {
+ public Long getDeptId() {
return deptId;
}
- public void setDeptId(String deptId) {
+ public void setDeptId(Long deptId) {
this.deptId = deptId;
}
+
+ /**
+ * 检查用户数据是否有效
+ *
+ * @return 是否有效
+ */
+ public boolean isValid() {
+ return userId != null && deptId != null && !roles.isEmpty();
+ }
}
diff --git a/continew-starter-extension/continew-starter-extension-datapermission/continew-starter-extension-datapermission-core/src/main/java/top/continew/starter/extension/datapermission/filter/DataPermissionUserDataProvider.java b/continew-starter-extension/continew-starter-extension-datapermission/continew-starter-extension-datapermission-core/src/main/java/top/continew/starter/extension/datapermission/provider/DataPermissionUserDataProvider.java
similarity index 94%
rename from continew-starter-extension/continew-starter-extension-datapermission/continew-starter-extension-datapermission-core/src/main/java/top/continew/starter/extension/datapermission/filter/DataPermissionUserDataProvider.java
rename to continew-starter-extension/continew-starter-extension-datapermission/continew-starter-extension-datapermission-core/src/main/java/top/continew/starter/extension/datapermission/provider/DataPermissionUserDataProvider.java
index 729b9fd8..8bbd0182 100644
--- a/continew-starter-extension/continew-starter-extension-datapermission/continew-starter-extension-datapermission-core/src/main/java/top/continew/starter/extension/datapermission/filter/DataPermissionUserDataProvider.java
+++ b/continew-starter-extension/continew-starter-extension-datapermission/continew-starter-extension-datapermission-core/src/main/java/top/continew/starter/extension/datapermission/provider/DataPermissionUserDataProvider.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package top.continew.starter.extension.datapermission.filter;
+package top.continew.starter.extension.datapermission.provider;
import top.continew.starter.extension.datapermission.model.UserData;
diff --git a/continew-starter-extension/continew-starter-extension-datapermission/continew-starter-extension-datapermission-mp/src/main/java/top/continew/starter/extension/datapermission/autoconfigure/DataPermissionAutoConfiguration.java b/continew-starter-extension/continew-starter-extension-datapermission/continew-starter-extension-datapermission-mp/src/main/java/top/continew/starter/extension/datapermission/autoconfigure/DataPermissionAutoConfiguration.java
index 0c03fa05..7d74fb22 100644
--- a/continew-starter-extension/continew-starter-extension-datapermission/continew-starter-extension-datapermission-mp/src/main/java/top/continew/starter/extension/datapermission/autoconfigure/DataPermissionAutoConfiguration.java
+++ b/continew-starter-extension/continew-starter-extension-datapermission/continew-starter-extension-datapermission-mp/src/main/java/top/continew/starter/extension/datapermission/autoconfigure/DataPermissionAutoConfiguration.java
@@ -28,7 +28,7 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.context.annotation.Bean;
import org.springframework.core.ResolvableType;
import top.continew.starter.core.constant.PropertiesConstants;
-import top.continew.starter.extension.datapermission.filter.DataPermissionUserDataProvider;
+import top.continew.starter.extension.datapermission.provider.DataPermissionUserDataProvider;
import top.continew.starter.extension.datapermission.handler.DefaultDataPermissionHandler;
/**
diff --git a/continew-starter-extension/continew-starter-extension-datapermission/continew-starter-extension-datapermission-mp/src/main/java/top/continew/starter/extension/datapermission/handler/DefaultDataPermissionHandler.java b/continew-starter-extension/continew-starter-extension-datapermission/continew-starter-extension-datapermission-mp/src/main/java/top/continew/starter/extension/datapermission/handler/DefaultDataPermissionHandler.java
index 8dfc0ff4..706cbab0 100644
--- a/continew-starter-extension/continew-starter-extension-datapermission/continew-starter-extension-datapermission-mp/src/main/java/top/continew/starter/extension/datapermission/handler/DefaultDataPermissionHandler.java
+++ b/continew-starter-extension/continew-starter-extension-datapermission/continew-starter-extension-datapermission-mp/src/main/java/top/continew/starter/extension/datapermission/handler/DefaultDataPermissionHandler.java
@@ -46,8 +46,10 @@ import top.continew.starter.core.constant.StringConstants;
import top.continew.starter.data.enums.DatabaseType;
import top.continew.starter.data.util.MetaUtils;
import top.continew.starter.extension.datapermission.annotation.DataPermission;
+import top.continew.starter.extension.datapermission.constant.DataPermissionConstants;
import top.continew.starter.extension.datapermission.enums.DataScope;
-import top.continew.starter.extension.datapermission.filter.DataPermissionUserDataProvider;
+import top.continew.starter.extension.datapermission.exception.DataPermissionException;
+import top.continew.starter.extension.datapermission.provider.DataPermissionUserDataProvider;
import top.continew.starter.extension.datapermission.model.RoleData;
import top.continew.starter.extension.datapermission.model.UserData;
@@ -62,7 +64,6 @@ public class DefaultDataPermissionHandler implements DataPermissionHandler {
private static final Logger log = LoggerFactory.getLogger(DefaultDataPermissionHandler.class);
private final DataPermissionUserDataProvider dataPermissionUserDataProvider;
- private static final DataSource dataSource = SpringUtil.getBean(DataSource.class);
public DefaultDataPermissionHandler(DataPermissionUserDataProvider dataPermissionUserDataProvider) {
this.dataPermissionUserDataProvider = dataPermissionUserDataProvider;
@@ -71,26 +72,47 @@ public class DefaultDataPermissionHandler implements DataPermissionHandler {
@Override
public Expression getSqlSegment(Expression where, String mappedStatementId) {
try {
- Class> clazz = Class.forName(mappedStatementId.substring(0, mappedStatementId
- .lastIndexOf(StringConstants.DOT)));
- String methodName = mappedStatementId.substring(mappedStatementId.lastIndexOf(StringConstants.DOT) + 1);
- Method[] methodArr = clazz.getMethods();
- for (Method method : methodArr) {
- DataPermission dataPermission = method.getAnnotation(DataPermission.class);
- String name = method.getName();
- if (dataPermission == null || !CharSequenceUtil.equalsAny(methodName, name, name + "_COUNT")) {
- continue;
- }
- if (dataPermissionUserDataProvider.isFilter()) {
- return buildDataScopeFilter(dataPermission, where);
- }
+ DataPermission dataPermission = findDataPermissionAnnotation(mappedStatementId);
+ if (dataPermission != null && dataPermissionUserDataProvider.isFilter()) {
+ return buildDataScopeFilter(dataPermission, where);
}
- } catch (ClassNotFoundException e) {
+ } catch (Exception e) {
log.error("Data permission handler build data scope filter occurred an error: {}.", e.getMessage(), e);
}
return where;
}
+ /**
+ * 查找数据权限注解
+ *
+ * @param mappedStatementId Mapper 方法 ID
+ * @return 数据权限注解
+ */
+ private DataPermission findDataPermissionAnnotation(String mappedStatementId) {
+ try {
+ int lastDotIndex = mappedStatementId.lastIndexOf(StringConstants.DOT);
+ if (lastDotIndex == -1) {
+ return null;
+ }
+
+ String className = mappedStatementId.substring(0, lastDotIndex);
+ String methodName = mappedStatementId.substring(lastDotIndex + 1);
+
+ Class> clazz = Class.forName(className);
+ Method[] methods = clazz.getMethods();
+
+ for (Method method : methods) {
+ String name = method.getName();
+ if (CharSequenceUtil.equalsAny(methodName, name, name + DataPermissionConstants.COUNT_METHOD_SUFFIX)) {
+ return method.getAnnotation(DataPermission.class);
+ }
+ }
+ } catch (ClassNotFoundException e) {
+ throw DataPermissionException.methodNotFound(mappedStatementId);
+ }
+ return null;
+ }
+
/**
* 构建数据范围过滤条件
*
@@ -99,23 +121,29 @@ public class DefaultDataPermissionHandler implements DataPermissionHandler {
* @return 构建后查询条件
*/
private Expression buildDataScopeFilter(DataPermission dataPermission, Expression where) {
- Expression expression = null;
UserData userData = dataPermissionUserDataProvider.getUserData();
+ if (userData == null || !userData.isValid()) {
+ throw DataPermissionException.invalidUserData("User data is null or invalid");
+ }
+
+ Expression expression = null;
Set roles = userData.getRoles();
+
for (RoleData roleData : roles) {
DataScope dataScope = roleData.getDataScope();
if (DataScope.ALL.equals(dataScope)) {
return where;
}
- switch (dataScope) {
- case DEPT_AND_CHILD -> expression = this
- .buildDeptAndChildExpression(dataPermission, userData, expression);
- case DEPT -> expression = this.buildDeptExpression(dataPermission, userData, expression);
- case SELF -> expression = this.buildSelfExpression(dataPermission, userData, expression);
- case CUSTOM -> expression = this.buildCustomExpression(dataPermission, roleData, expression);
- default -> throw new IllegalArgumentException("暂不支持 [%s] 数据权限".formatted(dataScope));
- }
+
+ expression = switch (dataScope) {
+ case DEPT_AND_CHILD -> buildDeptAndChildExpression(dataPermission, userData, expression);
+ case DEPT -> buildDeptExpression(dataPermission, userData, expression);
+ case SELF -> buildSelfExpression(dataPermission, userData, expression);
+ case CUSTOM -> buildCustomExpression(dataPermission, roleData, expression);
+ default -> throw DataPermissionException.unsupportedDataScope(dataScope.toString());
+ };
}
+
return where != null ? new AndExpression(where, new ParenthesedExpressionList<>(expression)) : expression;
}
@@ -144,18 +172,19 @@ public class DefaultDataPermissionHandler implements DataPermissionHandler {
equalsTo.setLeftExpression(new Column(dataPermission.id()));
equalsTo.setRightExpression(new LongValue(userData.getDeptId()));
- DatabaseType databaseType = MetaUtils.getDatabaseType(dataSource);
+ DatabaseType databaseType = MetaUtils.getDatabaseType(SpringUtil.getBean(DataSource.class));
Expression inSetExpression;
if (DatabaseType.MYSQL.getDatabase().equalsIgnoreCase(databaseType.getDatabase())) {
Function findInSetFunction = new Function();
findInSetFunction.setName("find_in_set");
findInSetFunction.setParameters(new ExpressionList(new LongValue(userData
- .getDeptId()), new Column("ancestors")));
+ .getDeptId()), new Column(DataPermissionConstants.ANCESTORS_COLUMN)));
inSetExpression = findInSetFunction;
} else if (DatabaseType.POSTGRE_SQL.getDatabase().equalsIgnoreCase(databaseType.getDatabase())) {
// 构建 concat 函数
Function concatFunction = new Function("concat");
- concatFunction.setParameters(new ExpressionList<>(new Column("ancestors"), new StringValue(",")));
+ concatFunction
+ .setParameters(new ExpressionList<>(new Column(DataPermissionConstants.ANCESTORS_COLUMN), new StringValue(",")));
// 创建 LIKE 函数
LikeExpression likeExpression = new LikeExpression();
@@ -163,7 +192,7 @@ public class DefaultDataPermissionHandler implements DataPermissionHandler {
likeExpression.setRightExpression(new StringValue("%," + userData.getDeptId() + ",%"));
inSetExpression = likeExpression;
} else {
- throw new IllegalArgumentException("暂不支持 [%s] 数据权限".formatted(""));
+ throw DataPermissionException.unsupportedDatabase(databaseType.getDatabase());
}
select.setWhere(new OrExpression(equalsTo, inSetExpression));