diff --git a/yudao-dependencies/pom.xml b/yudao-dependencies/pom.xml
index 5a7e152ae..63913572a 100644
--- a/yudao-dependencies/pom.xml
+++ b/yudao-dependencies/pom.xml
@@ -22,7 +22,6 @@
1.5.22
2.5
- 5.1.46
1.2.8
3.4.3.4
3.5.2
@@ -76,12 +75,6 @@
${spring.boot.version}
pom
import
-
-
- mysql
- mysql-connector-java
-
-
diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java
index 1ea74ee29..a6466ab44 100644
--- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java
+++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java
@@ -54,6 +54,13 @@ public class CollectionUtils {
return from.stream().map(func).filter(Objects::nonNull).collect(Collectors.toList());
}
+ public static List convertList(Collection from, Function func, Predicate filter) {
+ if (CollUtil.isEmpty(from)) {
+ return new ArrayList<>();
+ }
+ return from.stream().filter(filter).map(func).filter(Objects::nonNull).collect(Collectors.toList());
+ }
+
public static Set convertSet(Collection from, Function func) {
if (CollUtil.isEmpty(from)) {
return new HashSet<>();
diff --git a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/dept/rule/DeptDataPermissionRule.java b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/dept/rule/DeptDataPermissionRule.java
index ed9168ba0..2a0c9aefa 100644
--- a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/dept/rule/DeptDataPermissionRule.java
+++ b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/dept/rule/DeptDataPermissionRule.java
@@ -1,11 +1,13 @@
package cn.iocoder.yudao.framework.datapermission.core.dept.rule;
import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
-import cn.iocoder.yudao.framework.datapermission.core.dept.service.DeptDataPermissionFrameworkService;
-import cn.iocoder.yudao.framework.datapermission.core.dept.service.dto.DeptDataPermissionRespDTO;
+import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
+import cn.iocoder.yudao.framework.datapermission.core.dept.service.DeptDataPermissionFrameworkService;
+import cn.iocoder.yudao.framework.datapermission.core.dept.service.dto.DeptDataPermissionRespDTO;
import cn.iocoder.yudao.framework.datapermission.core.rule.DataPermissionRule;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils;
@@ -13,7 +15,6 @@ import cn.iocoder.yudao.framework.security.core.LoginUser;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import lombok.AllArgsConstructor;
-import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.Alias;
import net.sf.jsqlparser.expression.Expression;
@@ -24,10 +25,7 @@ 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 java.util.*;
/**
* 基于部门的 {@link DataPermissionRule} 数据权限规则实现
@@ -50,6 +48,11 @@ import java.util.Set;
@Slf4j
public class DeptDataPermissionRule implements DataPermissionRule {
+ /**
+ * LoginUser 的 Context 缓存 Key
+ */
+ protected static final String CONTEXT_KEY = DeptDataPermissionRule.class.getSimpleName();
+
private static final String DEPT_COLUMN_NAME = "dept_id";
private static final String USER_COLUMN_NAME = "user_id";
@@ -90,13 +93,23 @@ public class DeptDataPermissionRule implements DataPermissionRule {
if (loginUser == null) {
return null;
}
+ // 只有管理员类型的用户,才进行数据权限的处理
+ if (ObjectUtil.notEqual(loginUser.getUserType(), UserTypeEnum.ADMIN.getValue())) {
+ return null;
+ }
// 获得数据权限
- DeptDataPermissionRespDTO deptDataPermission = deptDataPermissionService.getDeptDataPermission(loginUser);
+ DeptDataPermissionRespDTO deptDataPermission = loginUser.getContext(CONTEXT_KEY, DeptDataPermissionRespDTO.class);
+ // 从上下文中拿不到,则调用逻辑进行获取
if (deptDataPermission == null) {
- log.error("[getExpression][LoginUser({}) 获取数据权限为 null]", JsonUtils.toJsonString(loginUser));
- throw new NullPointerException(String.format("LoginUser(%d) Table(%s/%s) 未返回数据权限",
- loginUser.getId(), tableName, tableAlias.getName()));
+ deptDataPermission = deptDataPermissionService.getDeptDataPermission(loginUser.getId());
+ if (deptDataPermission == 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, deptDataPermission);
}
// 情况一,如果是 ALL 可查看全部,则无需拼接条件
@@ -111,8 +124,8 @@ public class DeptDataPermissionRule implements DataPermissionRule {
}
// 情况三,拼接 Dept 和 User 的条件,最后组合
- Expression deptExpression = this.buildDeptExpression(tableName,tableAlias, deptDataPermission.getDeptIds());
- Expression userExpression = this.buildUserExpression(tableName, tableAlias, deptDataPermission.getSelf(), loginUser.getId());
+ Expression deptExpression = buildDeptExpression(tableName,tableAlias, deptDataPermission.getDeptIds());
+ Expression userExpression = buildUserExpression(tableName, tableAlias, deptDataPermission.getSelf(), loginUser.getId());
if (deptExpression == null && userExpression == null) {
// TODO 芋艿:获得不到条件的时候,暂时不抛出异常,而是不返回数据
log.warn("[getExpression][LoginUser({}) Table({}/{}) DeptDataPermission({}) 构建的条件为空]",
diff --git a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/dept/service/DeptDataPermissionFrameworkService.java b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/dept/service/DeptDataPermissionFrameworkService.java
index 3ee616755..e491aa036 100644
--- a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/dept/service/DeptDataPermissionFrameworkService.java
+++ b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/dept/service/DeptDataPermissionFrameworkService.java
@@ -1,7 +1,6 @@
package cn.iocoder.yudao.framework.datapermission.core.dept.service;
import cn.iocoder.yudao.framework.datapermission.core.dept.service.dto.DeptDataPermissionRespDTO;
-import cn.iocoder.yudao.framework.security.core.LoginUser;
/**
* 基于部门的数据权限 Framework Service 接口
@@ -14,9 +13,9 @@ public interface DeptDataPermissionFrameworkService {
/**
* 获得登陆用户的部门数据权限
*
- * @param loginUser 登陆用户
+ * @param userId 用户编号
* @return 部门数据权限
*/
- DeptDataPermissionRespDTO getDeptDataPermission(LoginUser loginUser);
+ DeptDataPermissionRespDTO getDeptDataPermission(Long userId);
}
diff --git a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/test/java/cn/iocoder/yudao/framework/datapermission/core/dept/rule/DeptDataPermissionRuleTest.java b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/test/java/cn/iocoder/yudao/framework/datapermission/core/dept/rule/DeptDataPermissionRuleTest.java
index 7282c1816..ef5ff16ac 100644
--- a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/test/java/cn/iocoder/yudao/framework/datapermission/core/dept/rule/DeptDataPermissionRuleTest.java
+++ b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/test/java/cn/iocoder/yudao/framework/datapermission/core/dept/rule/DeptDataPermissionRuleTest.java
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.framework.datapermission.core.dept.rule;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ReflectUtil;
+import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
import cn.iocoder.yudao.framework.datapermission.core.dept.service.DeptDataPermissionFrameworkService;
import cn.iocoder.yudao.framework.datapermission.core.dept.service.dto.DeptDataPermissionRespDTO;
@@ -69,7 +70,8 @@ class DeptDataPermissionRuleTest extends BaseMockitoUnitTest {
String tableName = "t_user";
Alias tableAlias = new Alias("u");
// mock 方法
- LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setId(1L));
+ LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setId(1L)
+ .setUserType(UserTypeEnum.ADMIN.getValue()));
securityFrameworkUtilsMock.when(SecurityFrameworkUtils::getLoginUser).thenReturn(loginUser);
// 调用
@@ -88,16 +90,18 @@ class DeptDataPermissionRuleTest extends BaseMockitoUnitTest {
String tableName = "t_user";
Alias tableAlias = new Alias("u");
// mock 方法(LoginUser)
- LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setId(1L));
+ LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setId(1L)
+ .setUserType(UserTypeEnum.ADMIN.getValue()));
securityFrameworkUtilsMock.when(SecurityFrameworkUtils::getLoginUser).thenReturn(loginUser);
// mock 方法(DeptDataPermissionRespDTO)
DeptDataPermissionRespDTO deptDataPermission = new DeptDataPermissionRespDTO().setAll(true);
- when(deptDataPermissionFrameworkService.getDeptDataPermission(same(loginUser))).thenReturn(deptDataPermission);
+ when(deptDataPermissionFrameworkService.getDeptDataPermission(same(1L))).thenReturn(deptDataPermission);
// 调用
Expression expression = rule.getExpression(tableName, tableAlias);
// 断言
assertNull(expression);
+ assertSame(deptDataPermission, loginUser.getContext(DeptDataPermissionRule.CONTEXT_KEY, DeptDataPermissionRespDTO.class));
}
}
@@ -109,16 +113,18 @@ class DeptDataPermissionRuleTest extends BaseMockitoUnitTest {
String tableName = "t_user";
Alias tableAlias = new Alias("u");
// mock 方法(LoginUser)
- LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setId(1L));
+ LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setId(1L)
+ .setUserType(UserTypeEnum.ADMIN.getValue()));
securityFrameworkUtilsMock.when(SecurityFrameworkUtils::getLoginUser).thenReturn(loginUser);
// mock 方法(DeptDataPermissionRespDTO)
DeptDataPermissionRespDTO deptDataPermission = new DeptDataPermissionRespDTO();
- when(deptDataPermissionFrameworkService.getDeptDataPermission(same(loginUser))).thenReturn(deptDataPermission);
+ when(deptDataPermissionFrameworkService.getDeptDataPermission(same(1L))).thenReturn(deptDataPermission);
// 调用
Expression expression = rule.getExpression(tableName, tableAlias);
// 断言
assertEquals("null = null", expression.toString());
+ assertSame(deptDataPermission, loginUser.getContext(DeptDataPermissionRule.CONTEXT_KEY, DeptDataPermissionRespDTO.class));
}
}
@@ -130,17 +136,19 @@ class DeptDataPermissionRuleTest extends BaseMockitoUnitTest {
String tableName = "t_user";
Alias tableAlias = new Alias("u");
// mock 方法(LoginUser)
- LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setId(1L));
+ LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setId(1L)
+ .setUserType(UserTypeEnum.ADMIN.getValue()));
securityFrameworkUtilsMock.when(SecurityFrameworkUtils::getLoginUser).thenReturn(loginUser);
// mock 方法(DeptDataPermissionRespDTO)
DeptDataPermissionRespDTO deptDataPermission = new DeptDataPermissionRespDTO()
.setDeptIds(SetUtils.asSet(10L, 20L)).setSelf(true);
- when(deptDataPermissionFrameworkService.getDeptDataPermission(same(loginUser))).thenReturn(deptDataPermission);
+ when(deptDataPermissionFrameworkService.getDeptDataPermission(same(1L))).thenReturn(deptDataPermission);
// 调用
Expression expression = rule.getExpression(tableName, tableAlias);
// 断言
assertSame(EXPRESSION_NULL, expression);
+ assertSame(deptDataPermission, loginUser.getContext(DeptDataPermissionRule.CONTEXT_KEY, DeptDataPermissionRespDTO.class));
}
}
@@ -152,12 +160,13 @@ class DeptDataPermissionRuleTest extends BaseMockitoUnitTest {
String tableName = "t_user";
Alias tableAlias = new Alias("u");
// mock 方法(LoginUser)
- LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setId(1L));
+ LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setId(1L)
+ .setUserType(UserTypeEnum.ADMIN.getValue()));
securityFrameworkUtilsMock.when(SecurityFrameworkUtils::getLoginUser).thenReturn(loginUser);
// mock 方法(DeptDataPermissionRespDTO)
DeptDataPermissionRespDTO deptDataPermission = new DeptDataPermissionRespDTO()
.setSelf(true);
- when(deptDataPermissionFrameworkService.getDeptDataPermission(same(loginUser))).thenReturn(deptDataPermission);
+ when(deptDataPermissionFrameworkService.getDeptDataPermission(same(1L))).thenReturn(deptDataPermission);
// 添加 user 字段配置
rule.addUserColumn("t_user", "id");
@@ -165,6 +174,7 @@ class DeptDataPermissionRuleTest extends BaseMockitoUnitTest {
Expression expression = rule.getExpression(tableName, tableAlias);
// 断言
assertEquals("u.id = 1", expression.toString());
+ assertSame(deptDataPermission, loginUser.getContext(DeptDataPermissionRule.CONTEXT_KEY, DeptDataPermissionRespDTO.class));
}
}
@@ -176,12 +186,13 @@ class DeptDataPermissionRuleTest extends BaseMockitoUnitTest {
String tableName = "t_user";
Alias tableAlias = new Alias("u");
// mock 方法(LoginUser)
- LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setId(1L));
+ LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setId(1L)
+ .setUserType(UserTypeEnum.ADMIN.getValue()));
securityFrameworkUtilsMock.when(SecurityFrameworkUtils::getLoginUser).thenReturn(loginUser);
// mock 方法(DeptDataPermissionRespDTO)
DeptDataPermissionRespDTO deptDataPermission = new DeptDataPermissionRespDTO()
.setDeptIds(CollUtil.newLinkedHashSet(10L, 20L));
- when(deptDataPermissionFrameworkService.getDeptDataPermission(same(loginUser))).thenReturn(deptDataPermission);
+ when(deptDataPermissionFrameworkService.getDeptDataPermission(same(1L))).thenReturn(deptDataPermission);
// 添加 dept 字段配置
rule.addDeptColumn("t_user", "dept_id");
@@ -189,6 +200,7 @@ class DeptDataPermissionRuleTest extends BaseMockitoUnitTest {
Expression expression = rule.getExpression(tableName, tableAlias);
// 断言
assertEquals("u.dept_id IN (10, 20)", expression.toString());
+ assertSame(deptDataPermission, loginUser.getContext(DeptDataPermissionRule.CONTEXT_KEY, DeptDataPermissionRespDTO.class));
}
}
@@ -200,12 +212,13 @@ class DeptDataPermissionRuleTest extends BaseMockitoUnitTest {
String tableName = "t_user";
Alias tableAlias = new Alias("u");
// mock 方法(LoginUser)
- LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setId(1L));
+ LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setId(1L)
+ .setUserType(UserTypeEnum.ADMIN.getValue()));
securityFrameworkUtilsMock.when(SecurityFrameworkUtils::getLoginUser).thenReturn(loginUser);
// mock 方法(DeptDataPermissionRespDTO)
DeptDataPermissionRespDTO deptDataPermission = new DeptDataPermissionRespDTO()
.setDeptIds(CollUtil.newLinkedHashSet(10L, 20L)).setSelf(true);
- when(deptDataPermissionFrameworkService.getDeptDataPermission(same(loginUser))).thenReturn(deptDataPermission);
+ when(deptDataPermissionFrameworkService.getDeptDataPermission(same(1L))).thenReturn(deptDataPermission);
// 添加 user 字段配置
rule.addUserColumn("t_user", "id");
// 添加 dept 字段配置
@@ -215,6 +228,7 @@ class DeptDataPermissionRuleTest extends BaseMockitoUnitTest {
Expression expression = rule.getExpression(tableName, tableAlias);
// 断言
assertEquals("u.dept_id IN (10, 20) OR u.id = 1", expression.toString());
+ assertSame(deptDataPermission, loginUser.getContext(DeptDataPermissionRule.CONTEXT_KEY, DeptDataPermissionRespDTO.class));
}
}
diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/LoginUser.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/LoginUser.java
index 84c7f94c4..c78148a46 100644
--- a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/LoginUser.java
+++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/LoginUser.java
@@ -50,17 +50,6 @@ public class LoginUser implements UserDetails {
*/
private Long tenantId;
- // ========== UserTypeEnum.ADMIN 独有字段 ==========
- // TODO 芋艿:可以通过定义一个 Map exts 的方式,去除管理员的字段。不过这样会导致系统比较复杂,所以暂时不去掉先;
- /**
- * 角色编号数组
- */
- private Set roleIds;
- /**
- * 部门编号
- */
- private Long deptId;
-
// ========== 上下文 ==========
/**
* 上下文字段,不进行持久化
diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/util/SecurityFrameworkUtils.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/util/SecurityFrameworkUtils.java
index 562c6ed9f..bbc1a9435 100644
--- a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/util/SecurityFrameworkUtils.java
+++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/util/SecurityFrameworkUtils.java
@@ -11,7 +11,6 @@ import org.springframework.security.web.authentication.WebAuthenticationDetailsS
import org.springframework.util.StringUtils;
import javax.servlet.http.HttpServletRequest;
-import java.util.Set;
/**
* 安全服务工具类
@@ -79,17 +78,6 @@ public class SecurityFrameworkUtils {
return loginUser != null ? loginUser.getId() : null;
}
- /**
- * 获得当前用户的角色编号数组
- *
- * @return 角色编号数组
- */
- @Nullable
- public static Set getLoginUserRoleIds() {
- LoginUser loginUser = getLoginUser();
- return loginUser != null ? loginUser.getRoleIds() : null;
- }
-
/**
* 设置当前用户
*
diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceImpl.java
index 5c2788df9..f82028f39 100644
--- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceImpl.java
+++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceImpl.java
@@ -84,7 +84,7 @@ public class MemberAuthServiceImpl implements MemberAuthService {
@Override
public String login(AppAuthLoginReqVO reqVO, String userIp, String userAgent) {
// 使用手机 + 密码,进行登录。
- LoginUser loginUser = this.login0(reqVO.getMobile(), reqVO.getPassword());
+ LoginUser loginUser = login0(reqVO.getMobile(), reqVO.getPassword());
// 缓存登录用户到 Redis 中,返回 Token 令牌
return createUserSessionAfterLoginSuccess(loginUser, LoginLogTypeEnum.LOGIN_USERNAME, userIp, userAgent);
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java
index 6fbf2a21a..0e26674f8 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java
@@ -26,12 +26,13 @@ import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.List;
+import java.util.Set;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getUserAgent;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
-import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserRoleIds;
+import static java.util.Collections.singleton;
@Api(tags = "管理后台 - 认证")
@RestController
@@ -69,12 +70,12 @@ public class AuthController {
return null;
}
// 获得角色列表
- List roleList = roleService.getRolesFromCache(getLoginUserRoleIds());
+ Set roleIds = permissionService.getUserRoleIds(getLoginUserId(), singleton(CommonStatusEnum.ENABLE.getStatus()));
+ List roleList = roleService.getRolesFromCache(roleIds);
// 获得菜单列表
- List menuList = permissionService.getRoleMenuListFromCache(
- getLoginUserRoleIds(), // 注意,基于登录的角色,因为后续的权限判断也是基于它
+ List menuList = permissionService.getRoleMenuListFromCache(roleIds,
SetUtils.asSet(MenuTypeEnum.DIR.getType(), MenuTypeEnum.MENU.getType(), MenuTypeEnum.BUTTON.getType()),
- SetUtils.asSet(CommonStatusEnum.ENABLE.getStatus()));
+ singleton(CommonStatusEnum.ENABLE.getStatus())); // 只要开启的
// 拼接结果返回
return success(AuthConvert.INSTANCE.convert(user, roleList, menuList));
}
@@ -82,11 +83,12 @@ public class AuthController {
@GetMapping("/list-menus")
@ApiOperation("获得登录用户的菜单列表")
public CommonResult> getMenus() {
+ // 获得角色列表
+ Set roleIds = permissionService.getUserRoleIds(getLoginUserId(), singleton(CommonStatusEnum.ENABLE.getStatus()));
// 获得用户拥有的菜单列表
- List menuList = permissionService.getRoleMenuListFromCache(
- getLoginUserRoleIds(), // 注意,基于登录的角色,因为后续的权限判断也是基于它
+ List menuList = permissionService.getRoleMenuListFromCache(roleIds,
SetUtils.asSet(MenuTypeEnum.DIR.getType(), MenuTypeEnum.MENU.getType()), // 只要目录和菜单类型
- SetUtils.asSet(CommonStatusEnum.ENABLE.getStatus())); // 只要开启的
+ singleton(CommonStatusEnum.ENABLE.getStatus())); // 只要开启的
// 转换成 Tree 结构返回
return success(AuthConvert.INSTANCE.buildMenuTree(menuList));
}
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/UserSessionController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/UserSessionController.java
index 023532e08..9ce2edca9 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/UserSessionController.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/UserSessionController.java
@@ -1,15 +1,16 @@
package cn.iocoder.yudao.module.system.controller.admin.auth;
+import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.session.UserSessionPageItemRespVO;
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.session.UserSessionPageReqVO;
import cn.iocoder.yudao.module.system.convert.auth.UserSessionConvert;
import cn.iocoder.yudao.module.system.dal.dataobject.auth.UserSessionDO;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
-import cn.iocoder.yudao.module.system.service.auth.UserSessionService;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
-import cn.iocoder.yudao.framework.common.pojo.CommonResult;
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
+import cn.iocoder.yudao.module.system.service.auth.UserSessionService;
import cn.iocoder.yudao.module.system.service.dept.DeptService;
import cn.iocoder.yudao.module.system.service.user.AdminUserService;
import io.swagger.annotations.Api;
@@ -49,7 +50,8 @@ public class UserSessionController {
// 获得拼接需要的数据
Map userMap = userService.getUserMap(
- convertList(pageResult.getList(), UserSessionDO::getUserId));
+ convertList(pageResult.getList(), UserSessionDO::getUserId,
+ session -> session.getUserType().equals(UserTypeEnum.ADMIN.getValue())));
Map deptMap = deptService.getDeptMap(
convertList(userMap.values(), AdminUserDO::getDeptId));
// 拼接结果返回
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java
index 6476102bf..ebbfb6dfa 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java
@@ -17,7 +17,6 @@ import cn.iocoder.yudao.module.system.enums.logger.LoginResultEnum;
import cn.iocoder.yudao.module.system.enums.sms.SmsSceneEnum;
import cn.iocoder.yudao.module.system.service.common.CaptchaService;
import cn.iocoder.yudao.module.system.service.logger.LoginLogService;
-import cn.iocoder.yudao.module.system.service.permission.PermissionService;
import cn.iocoder.yudao.module.system.service.social.SocialUserService;
import cn.iocoder.yudao.module.system.service.user.AdminUserService;
import lombok.extern.slf4j.Slf4j;
@@ -36,12 +35,10 @@ import org.springframework.util.Assert;
import javax.annotation.Resource;
import javax.validation.Validator;
import java.util.Objects;
-import java.util.Set;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
-import static java.util.Collections.singleton;
/**
* Auth Service 实现类
@@ -60,8 +57,6 @@ public class AdminAuthServiceImpl implements AdminAuthService {
@SuppressWarnings("SpringJavaAutowiredFieldsWarningInspection") // UserService 存在重名
private AdminUserService userService;
@Resource
- private PermissionService permissionService;
- @Resource
private CaptchaService captchaService;
@Resource
private LoginLogService loginLogService;
@@ -211,16 +206,6 @@ public class AdminAuthServiceImpl implements AdminAuthService {
}
}
- /**
- * 获得 User 拥有的角色编号数组
- *
- * @param userId 用户编号
- * @return 角色编号数组
- */
- private Set getUserRoleIds(Long userId) {
- return permissionService.getUserRoleIds(userId, singleton(CommonStatusEnum.ENABLE.getStatus()));
- }
-
@Override
public String socialQuickLogin(AuthSocialQuickLoginReqVO reqVO, String userIp, String userAgent) {
// 使用 code 授权码,进行登录。然后,获得到绑定的用户编号
@@ -318,17 +303,13 @@ public class AdminAuthServiceImpl implements AdminAuthService {
}
// 刷新 LoginUser 缓存
- LoginUser newLoginUser= this.buildLoginUser(user);
+ LoginUser newLoginUser= buildLoginUser(user);
userSessionService.refreshUserSession(token, newLoginUser);
return newLoginUser;
}
private LoginUser buildLoginUser(AdminUserDO user) {
- LoginUser loginUser = AuthConvert.INSTANCE.convert(user);
- // 补全字段
- loginUser.setDeptId(user.getDeptId());
- loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId()));
- return loginUser;
+ return AuthConvert.INSTANCE.convert(user);
}
}
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceImpl.java
index 08473d8cc..76e2055b3 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceImpl.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceImpl.java
@@ -3,12 +3,12 @@ package cn.iocoder.yudao.module.system.service.permission;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ArrayUtil;
+import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
+import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;
import cn.iocoder.yudao.framework.datapermission.core.dept.service.dto.DeptDataPermissionRespDTO;
-import cn.iocoder.yudao.framework.security.core.LoginUser;
-import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO;
@@ -22,6 +22,8 @@ import cn.iocoder.yudao.module.system.dal.mysql.permission.UserRoleMapper;
import cn.iocoder.yudao.module.system.enums.permission.DataScopeEnum;
import cn.iocoder.yudao.module.system.mq.producer.permission.PermissionProducer;
import cn.iocoder.yudao.module.system.service.dept.DeptService;
+import cn.iocoder.yudao.module.system.service.user.AdminUserService;
+import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
@@ -36,6 +38,10 @@ import org.springframework.transaction.support.TransactionSynchronizationManager
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.*;
+import java.util.function.Supplier;
+
+import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
+import static java.util.Collections.singleton;
/**
* 权限 Service 实现类
@@ -46,11 +52,6 @@ import java.util.*;
@Slf4j
public class PermissionServiceImpl implements PermissionService {
- /**
- * LoginUser 的 Context 缓存 Key
- */
- public static final String CONTEXT_KEY = PermissionServiceImpl.class.getSimpleName();
-
/**
* 定时执行 {@link #schedulePeriodicRefresh()} 的周期
* 因为已经通过 Redis Pub/Sub 机制,所以频率不需要高
@@ -93,6 +94,8 @@ public class PermissionServiceImpl implements PermissionService {
private MenuService menuService;
@Resource
private DeptService deptService;
+ @Resource
+ private AdminUserService userService;
@Resource
private PermissionProducer permissionProducer;
@@ -319,7 +322,7 @@ public class PermissionServiceImpl implements PermissionService {
}
// 获得当前登录的角色。如果为空,说明没有权限
- Set roleIds = SecurityFrameworkUtils.getLoginUserRoleIds();
+ Set roleIds = getUserRoleIds(getLoginUserId(), singleton(CommonStatusEnum.ENABLE.getStatus()));
if (CollUtil.isEmpty(roleIds)) {
return false;
}
@@ -354,7 +357,7 @@ public class PermissionServiceImpl implements PermissionService {
}
// 获得当前登录的角色。如果为空,说明没有权限
- Set roleIds = SecurityFrameworkUtils.getLoginUserRoleIds();
+ Set roleIds = getUserRoleIds(getLoginUserId(), singleton(CommonStatusEnum.ENABLE.getStatus()));
if (CollUtil.isEmpty(roleIds)) {
return false;
}
@@ -368,16 +371,18 @@ public class PermissionServiceImpl implements PermissionService {
}
@Override
- public DeptDataPermissionRespDTO getDeptDataPermission(LoginUser loginUser) {
- // 判断是否 context 已经缓存
- DeptDataPermissionRespDTO result = loginUser.getContext(CONTEXT_KEY, DeptDataPermissionRespDTO.class);
- if (result != null) {
+ @DataPermission(enable = false) // 关闭数据权限,不然就会出现递归获取数据权限的问题
+ public DeptDataPermissionRespDTO getDeptDataPermission(Long userId) {
+ DeptDataPermissionRespDTO result = new DeptDataPermissionRespDTO();
+ // 获得用户的角色
+ Set roleIds = getUserRoleIds(userId, singleton(CommonStatusEnum.ENABLE.getStatus()));
+ if (CollUtil.isEmpty(roleIds)) {
return result;
}
-
- // 创建 DeptDataPermissionRespDTO 对象
- result = new DeptDataPermissionRespDTO();
- List roles = roleService.getRolesFromCache(loginUser.getRoleIds());
+ List roles = roleService.getRolesFromCache(roleIds);
+ // 获得用户的部门编号的缓存,通过 Guava 的 Suppliers 惰性求值,即有且仅有第一次发起 DB 的查询
+ Supplier userDeptIdCache = Suppliers.memoize(() -> userService.getUser(userId).getDeptId());
+ // 遍历每个角色,计算
for (RoleDO role : roles) {
// 为空时,跳过
if (role.getDataScope() == null) {
@@ -393,20 +398,20 @@ public class PermissionServiceImpl implements PermissionService {
CollUtil.addAll(result.getDeptIds(), role.getDataScopeDeptIds());
// 自定义可见部门时,保证可以看到自己所在的部门。否则,一些场景下可能会有问题。
// 例如说,登录时,基于 t_user 的 username 查询会可能被 dept_id 过滤掉
- CollUtil.addAll(result.getDeptIds(), loginUser.getDeptId());
+ CollUtil.addAll(result.getDeptIds(), userDeptIdCache.get());
continue;
}
// 情况三,DEPT_ONLY
if (Objects.equals(role.getDataScope(), DataScopeEnum.DEPT_ONLY.getScope())) {
- CollectionUtils.addIfNotNull(result.getDeptIds(), loginUser.getDeptId());
+ CollectionUtils.addIfNotNull(result.getDeptIds(), userDeptIdCache.get());
continue;
}
// 情况四,DEPT_DEPT_AND_CHILD
if (Objects.equals(role.getDataScope(), DataScopeEnum.DEPT_AND_CHILD.getScope())) {
- List depts = deptService.getDeptsByParentIdFromCache(loginUser.getDeptId(), true);
+ List depts = deptService.getDeptsByParentIdFromCache(userDeptIdCache.get(), true);
CollUtil.addAll(result.getDeptIds(), CollectionUtils.convertList(depts, DeptDO::getId));
- //添加本身部门id
- CollUtil.addAll(result.getDeptIds(), loginUser.getDeptId());
+ // 添加本身部门编号
+ CollUtil.addAll(result.getDeptIds(), userDeptIdCache.get());
continue;
}
// 情况五,SELF
@@ -415,11 +420,8 @@ public class PermissionServiceImpl implements PermissionService {
continue;
}
// 未知情况,error log 即可
- log.error("[getDeptDataPermission][LoginUser({}) role({}) 无法处理]", loginUser.getId(), JsonUtils.toJsonString(result));
+ log.error("[getDeptDataPermission][LoginUser({}) role({}) 无法处理]", userId, JsonUtils.toJsonString(result));
}
-
- // 添加到缓存,并返回
- loginUser.setContext(CONTEXT_KEY, result);
return result;
}
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java
index e0038ffcd..160ffe824 100755
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java
@@ -81,6 +81,7 @@ public class TenantServiceImpl implements TenantService {
@Getter
private volatile Date maxUpdateTime;
+ @SuppressWarnings("SpringJavaAutowiredFieldsWarningInspection")
@Autowired(required = false) // 由于 yudao.tenant.enable 配置项,可以关闭多租户的功能,所以这里只能不强制注入
private TenantProperties tenantProperties;
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java
index 44934c6fa..9208b2e69 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java
@@ -25,6 +25,7 @@ import cn.iocoder.yudao.module.system.service.tenant.TenantService;
import com.google.common.annotations.VisibleForTesting;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Lazy;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -61,6 +62,7 @@ public class AdminUserServiceImpl implements AdminUserService {
@Resource
private PasswordEncoder passwordEncoder;
@Resource
+ @Lazy // 延迟,避免循环依赖报错
private TenantService tenantService;
@Resource
diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/auth/AuthServiceImplTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/auth/AuthServiceImplTest.java
index 47b767eb5..0cb376668 100644
--- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/auth/AuthServiceImplTest.java
+++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/auth/AuthServiceImplTest.java
@@ -1,6 +1,5 @@
package cn.iocoder.yudao.module.system.service.auth;
-import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.security.core.LoginUser;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.framework.test.core.util.AssertUtils;
@@ -12,7 +11,6 @@ import cn.iocoder.yudao.module.system.enums.logger.LoginResultEnum;
import cn.iocoder.yudao.module.system.service.common.CaptchaService;
import cn.iocoder.yudao.module.system.service.dept.PostService;
import cn.iocoder.yudao.module.system.service.logger.LoginLogService;
-import cn.iocoder.yudao.module.system.service.permission.PermissionService;
import cn.iocoder.yudao.module.system.service.social.SocialUserService;
import cn.iocoder.yudao.module.system.service.user.AdminUserService;
import org.junit.jupiter.api.BeforeEach;
@@ -34,7 +32,6 @@ import java.util.Set;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
-import static java.util.Collections.singleton;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.eq;
@@ -49,8 +46,6 @@ public class AuthServiceImplTest extends BaseDbUnitTest {
@MockBean
private AdminUserService userService;
@MockBean
- private PermissionService permissionService;
- @MockBean
private AuthenticationManager authenticationManager;
@MockBean
private Authentication authentication;
@@ -108,16 +103,11 @@ public class AuthServiceImplTest extends BaseDbUnitTest {
// mock 方法 01
AdminUserDO user = randomPojo(AdminUserDO.class, o -> o.setId(userId));
when(userService.getUser(eq(userId))).thenReturn(user);
- // mock 方法 02
- Set roleIds = randomSet(Long.class);
- when(permissionService.getUserRoleIds(eq(userId), eq(singleton(CommonStatusEnum.ENABLE.getStatus()))))
- .thenReturn(roleIds);
// 调用
LoginUser loginUser = authService.mockLogin(userId);
// 断言
AssertUtils.assertPojoEquals(user, loginUser, "updateTime");
- assertEquals(roleIds, loginUser.getRoleIds());
}
@Test
@@ -247,15 +237,10 @@ public class AuthServiceImplTest extends BaseDbUnitTest {
// mock authentication
Long userId = randomLongId();
Set userRoleIds = randomSet(Long.class);
- LoginUser loginUser = randomPojo(LoginUser.class, o -> {
- o.setId(userId);
- o.setRoleIds(userRoleIds);
- });
+ LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setId(userId));
when(authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(reqVO.getUsername(), reqVO.getPassword())))
.thenReturn(authentication);
when(authentication.getPrincipal()).thenReturn(loginUser);
- // mock 获得 User 拥有的角色编号数组
- when(permissionService.getUserRoleIds(userId, singleton(CommonStatusEnum.ENABLE.getStatus()))).thenReturn(userRoleIds);
// mock 缓存登录用户到 Redis
String token = randomString();
when(userSessionService.createUserSession(loginUser, userIp, userAgent)).thenReturn(token);
diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceTest.java
index 7ac339f54..12fddf38a 100644
--- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceTest.java
+++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceTest.java
@@ -1,20 +1,22 @@
package cn.iocoder.yudao.module.system.service.permission;
import cn.hutool.core.collection.CollUtil;
+import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
+import cn.iocoder.yudao.framework.datapermission.core.dept.service.dto.DeptDataPermissionRespDTO;
+import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleMenuDO;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.UserRoleDO;
+import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.dal.mysql.permission.RoleMenuBatchInsertMapper;
import cn.iocoder.yudao.module.system.dal.mysql.permission.RoleMenuMapper;
import cn.iocoder.yudao.module.system.dal.mysql.permission.UserRoleBatchInsertMapper;
import cn.iocoder.yudao.module.system.dal.mysql.permission.UserRoleMapper;
+import cn.iocoder.yudao.module.system.enums.permission.DataScopeEnum;
import cn.iocoder.yudao.module.system.mq.producer.permission.PermissionProducer;
import cn.iocoder.yudao.module.system.service.dept.DeptService;
-import cn.iocoder.yudao.framework.datapermission.core.dept.service.dto.DeptDataPermissionRespDTO;
-import cn.iocoder.yudao.framework.security.core.LoginUser;
-import cn.iocoder.yudao.module.system.enums.permission.DataScopeEnum;
-import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
+import cn.iocoder.yudao.module.system.service.user.AdminUserService;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.Import;
@@ -25,10 +27,10 @@ import java.util.List;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
+import static java.util.Collections.singleton;
import static java.util.Collections.singletonList;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.ArgumentMatchers.same;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -54,6 +56,9 @@ public class PermissionServiceTest extends BaseDbUnitTest {
private MenuService menuService;
@MockBean
private DeptService deptService;
+ @MockBean
+ private AdminUserService userService;
+
@MockBean
private PermissionProducer permissionProducer;
@@ -124,112 +129,119 @@ public class PermissionServiceTest extends BaseDbUnitTest {
assertPojoEquals(dbUserRoles.get(0), userRoleDO02);
}
- @Test // 测试从 context 获取的场景
- public void testGetDeptDataPermission_fromContext() {
- // 准备参数
- LoginUser loginUser = randomPojo(LoginUser.class);
- // mock 方法
- DeptDataPermissionRespDTO respDTO = new DeptDataPermissionRespDTO();
- loginUser.setContext(PermissionServiceImpl.CONTEXT_KEY, respDTO);
-
- // 调用
- DeptDataPermissionRespDTO result = permissionService.getDeptDataPermission(loginUser);
- // 断言
- assertSame(respDTO, result);
- }
-
@Test
public void testGetDeptDataPermission_All() {
// 准备参数
- LoginUser loginUser = randomPojo(LoginUser.class);
- // mock 方法
- RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setDataScope(DataScopeEnum.ALL.getScope()));
- when(roleService.getRolesFromCache(same(loginUser.getRoleIds()))).thenReturn(singletonList(roleDO));
+ Long userId = 1L;
+ // mock 用户的角色编号
+ userRoleMapper.insert(new UserRoleDO().setUserId(userId).setRoleId(2L));
+ // mock 获得用户的角色
+ RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setDataScope(DataScopeEnum.ALL.getScope())
+ .setStatus(CommonStatusEnum.ENABLE.getStatus()));
+ when(roleService.getRolesFromCache(eq(singleton(2L)))).thenReturn(singletonList(roleDO));
+ when(roleService.getRoleFromCache(eq(2L))).thenReturn(roleDO);
// 调用
- DeptDataPermissionRespDTO result = permissionService.getDeptDataPermission(loginUser);
+ DeptDataPermissionRespDTO result = permissionService.getDeptDataPermission(userId);
// 断言
assertTrue(result.getAll());
assertFalse(result.getSelf());
assertTrue(CollUtil.isEmpty(result.getDeptIds()));
- assertSame(result, loginUser.getContext(PermissionServiceImpl.CONTEXT_KEY, DeptDataPermissionRespDTO.class));
}
@Test
public void testGetDeptDataPermission_DeptCustom() {
// 准备参数
- LoginUser loginUser = randomPojo(LoginUser.class);
- // mock 方法
- RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setDataScope(DataScopeEnum.DEPT_CUSTOM.getScope()));
- when(roleService.getRolesFromCache(same(loginUser.getRoleIds()))).thenReturn(singletonList(roleDO));
+ Long userId = 1L;
+ // mock 用户的角色编号
+ userRoleMapper.insert(new UserRoleDO().setUserId(userId).setRoleId(2L));
+ // mock 获得用户的角色
+ RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setDataScope(DataScopeEnum.DEPT_CUSTOM.getScope())
+ .setStatus(CommonStatusEnum.ENABLE.getStatus()));
+ when(roleService.getRolesFromCache(eq(singleton(2L)))).thenReturn(singletonList(roleDO));
+ when(roleService.getRoleFromCache(eq(2L))).thenReturn(roleDO);
+ // mock 部门的返回
+ when(userService.getUser(eq(1L))).thenReturn(new AdminUserDO().setDeptId(3L), null, null); // 最后返回 null 的目的,看看会不会重复调用
// 调用
- DeptDataPermissionRespDTO result = permissionService.getDeptDataPermission(loginUser);
+ DeptDataPermissionRespDTO result = permissionService.getDeptDataPermission(1L);
// 断言
assertFalse(result.getAll());
assertFalse(result.getSelf());
assertEquals(roleDO.getDataScopeDeptIds().size() + 1, result.getDeptIds().size());
assertTrue(CollUtil.containsAll(result.getDeptIds(), roleDO.getDataScopeDeptIds()));
- assertTrue(CollUtil.contains(result.getDeptIds(), loginUser.getDeptId()));
- assertSame(result, loginUser.getContext(PermissionServiceImpl.CONTEXT_KEY, DeptDataPermissionRespDTO.class));
+ assertTrue(CollUtil.contains(result.getDeptIds(), 3L));
}
@Test
public void testGetDeptDataPermission_DeptOnly() {
// 准备参数
- LoginUser loginUser = randomPojo(LoginUser.class);
- // mock 方法
- RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setDataScope(DataScopeEnum.DEPT_ONLY.getScope()));
- when(roleService.getRolesFromCache(same(loginUser.getRoleIds()))).thenReturn(singletonList(roleDO));
+ Long userId = 1L;
+ // mock 用户的角色编号
+ userRoleMapper.insert(new UserRoleDO().setUserId(userId).setRoleId(2L));
+ // mock 获得用户的角色
+ RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setDataScope(DataScopeEnum.DEPT_ONLY.getScope())
+ .setStatus(CommonStatusEnum.ENABLE.getStatus()));
+ when(roleService.getRolesFromCache(eq(singleton(2L)))).thenReturn(singletonList(roleDO));
+ when(roleService.getRoleFromCache(eq(2L))).thenReturn(roleDO);
+ // mock 部门的返回
+ when(userService.getUser(eq(1L))).thenReturn(new AdminUserDO().setDeptId(3L), null, null); // 最后返回 null 的目的,看看会不会重复调用
// 调用
- DeptDataPermissionRespDTO result = permissionService.getDeptDataPermission(loginUser);
+ DeptDataPermissionRespDTO result = permissionService.getDeptDataPermission(1L);
// 断言
assertFalse(result.getAll());
assertFalse(result.getSelf());
assertEquals(1, result.getDeptIds().size());
- assertTrue(CollUtil.contains(result.getDeptIds(), loginUser.getDeptId()));
- assertSame(result, loginUser.getContext(PermissionServiceImpl.CONTEXT_KEY, DeptDataPermissionRespDTO.class));
+ assertTrue(CollUtil.contains(result.getDeptIds(), 3L));
}
@Test
public void testGetDeptDataPermission_DeptAndChild() {
// 准备参数
- LoginUser loginUser = randomPojo(LoginUser.class);
- // mock 方法(角色)
- RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setDataScope(DataScopeEnum.DEPT_AND_CHILD.getScope()));
- when(roleService.getRolesFromCache(same(loginUser.getRoleIds()))).thenReturn(singletonList(roleDO));
+ Long userId = 1L;
+ // mock 用户的角色编号
+ userRoleMapper.insert(new UserRoleDO().setUserId(userId).setRoleId(2L));
+ // mock 获得用户的角色
+ RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setDataScope(DataScopeEnum.DEPT_AND_CHILD.getScope())
+ .setStatus(CommonStatusEnum.ENABLE.getStatus()));
+ when(roleService.getRolesFromCache(eq(singleton(2L)))).thenReturn(singletonList(roleDO));
+ when(roleService.getRoleFromCache(eq(2L))).thenReturn(roleDO);
+ // mock 部门的返回
+ when(userService.getUser(eq(1L))).thenReturn(new AdminUserDO().setDeptId(3L), null, null); // 最后返回 null 的目的,看看会不会重复调用
// mock 方法(部门)
DeptDO deptDO = randomPojo(DeptDO.class);
- when(deptService.getDeptsByParentIdFromCache(eq(loginUser.getDeptId()), eq(true)))
+ when(deptService.getDeptsByParentIdFromCache(eq(3L), eq(true)))
.thenReturn(singletonList(deptDO));
// 调用
- DeptDataPermissionRespDTO result = permissionService.getDeptDataPermission(loginUser);
+ DeptDataPermissionRespDTO result = permissionService.getDeptDataPermission(userId);
// 断言
assertFalse(result.getAll());
assertFalse(result.getSelf());
assertEquals(2, result.getDeptIds().size());
assertTrue(CollUtil.contains(result.getDeptIds(), deptDO.getId()));
- assertTrue(CollUtil.contains(result.getDeptIds(), loginUser.getDeptId()));
- assertSame(result, loginUser.getContext(PermissionServiceImpl.CONTEXT_KEY, DeptDataPermissionRespDTO.class));
+ assertTrue(CollUtil.contains(result.getDeptIds(), 3L));
}
@Test
public void testGetDeptDataPermission_Self() {
// 准备参数
- LoginUser loginUser = randomPojo(LoginUser.class);
- // mock 方法
- RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setDataScope(DataScopeEnum.SELF.getScope()));
- when(roleService.getRolesFromCache(same(loginUser.getRoleIds()))).thenReturn(singletonList(roleDO));
+ Long userId = 1L;
+ // mock 用户的角色编号
+ userRoleMapper.insert(new UserRoleDO().setUserId(userId).setRoleId(2L));
+ // mock 获得用户的角色
+ RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setDataScope(DataScopeEnum.SELF.getScope())
+ .setStatus(CommonStatusEnum.ENABLE.getStatus()));
+ when(roleService.getRolesFromCache(eq(singleton(2L)))).thenReturn(singletonList(roleDO));
+ when(roleService.getRoleFromCache(eq(2L))).thenReturn(roleDO);
// 调用
- DeptDataPermissionRespDTO result = permissionService.getDeptDataPermission(loginUser);
+ DeptDataPermissionRespDTO result = permissionService.getDeptDataPermission(userId);
// 断言
assertFalse(result.getAll());
assertTrue(result.getSelf());
assertTrue(CollUtil.isEmpty(result.getDeptIds()));
- assertSame(result, loginUser.getContext(PermissionServiceImpl.CONTEXT_KEY, DeptDataPermissionRespDTO.class));
}
}