Commit 5794780c4e11da7868d90a9f4c635889ea6a906f

Authored by YunaiV
1 parent 49b4eedf

调整 SecurityPermissionFrameworkService 的实现,完善 PermissionServiceTest 的单元测试

Showing 18 changed files with 246 additions and 88 deletions
yudao-framework/yudao-spring-boot-starter-biz-data-permission/pom.xml
... ... @@ -34,6 +34,13 @@
34 34 <artifactId>yudao-spring-boot-starter-mybatis</artifactId>
35 35 </dependency>
36 36  
  37 + <!-- 业务组件 -->
  38 + <dependency>
  39 + <groupId>cn.iocoder.boot</groupId>
  40 + <artifactId>yudao-module-system-api</artifactId> <!-- 需要使用它,进行数据权限的获取 -->
  41 + <version>${revision}</version>
  42 + </dependency>
  43 +
37 44 <!-- Test 测试相关 -->
38 45 <dependency>
39 46 <groupId>cn.iocoder.boot</groupId>
... ...
yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/config/YudaoDeptDataPermissionAutoConfiguration.java
1 1 package cn.iocoder.yudao.framework.datapermission.config;
2 2  
3   -import cn.iocoder.yudao.framework.datapermission.core.dept.rule.DeptDataPermissionRule;
4   -import cn.iocoder.yudao.framework.datapermission.core.dept.rule.DeptDataPermissionRuleCustomizer;
5   -import cn.iocoder.yudao.framework.datapermission.core.dept.service.DeptDataPermissionFrameworkService;
  3 +import cn.iocoder.yudao.framework.datapermission.core.rule.dept.DeptDataPermissionRule;
  4 +import cn.iocoder.yudao.framework.datapermission.core.rule.dept.DeptDataPermissionRuleCustomizer;
6 5 import cn.iocoder.yudao.framework.security.core.LoginUser;
  6 +import cn.iocoder.yudao.module.system.api.permission.PermissionApi;
7 7 import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
8 8 import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
9 9 import org.springframework.context.annotation.Bean;
... ... @@ -18,14 +18,14 @@ import java.util.List;
18 18 */
19 19 @Configuration
20 20 @ConditionalOnClass(LoginUser.class)
21   -@ConditionalOnBean(value = {DeptDataPermissionFrameworkService.class, DeptDataPermissionRuleCustomizer.class})
  21 +@ConditionalOnBean(value = {PermissionApi.class, DeptDataPermissionRuleCustomizer.class})
22 22 public class YudaoDeptDataPermissionAutoConfiguration {
23 23  
24 24 @Bean
25   - public DeptDataPermissionRule deptDataPermissionRule(DeptDataPermissionFrameworkService service,
  25 + public DeptDataPermissionRule deptDataPermissionRule(PermissionApi permissionApi,
26 26 List<DeptDataPermissionRuleCustomizer> customizers) {
27 27 // 创建 DeptDataPermissionRule 对象
28   - DeptDataPermissionRule rule = new DeptDataPermissionRule(service);
  28 + DeptDataPermissionRule rule = new DeptDataPermissionRule(permissionApi);
29 29 // 补全表配置
30 30 customizers.forEach(customizer -> customizer.customize(rule));
31 31 return rule;
... ...
yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/dept/service/DeptDataPermissionFrameworkService.java deleted
1   -package cn.iocoder.yudao.framework.datapermission.core.dept.service;
2   -
3   -import cn.iocoder.yudao.framework.datapermission.core.dept.service.dto.DeptDataPermissionRespDTO;
4   -
5   -/**
6   - * 基于部门的数据权限 Framework Service 接口
7   - * 目前的实现类是 SysPermissionServiceImpl 类
8   - *
9   - * @author 芋道源码
10   - */
11   -public interface DeptDataPermissionFrameworkService {
12   -
13   - /**
14   - * 获得登陆用户的部门数据权限
15   - *
16   - * @param userId 用户编号
17   - * @return 部门数据权限
18   - */
19   - DeptDataPermissionRespDTO getDeptDataPermission(Long userId);
20   -
21   -}
yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/dept/rule/DeptDataPermissionRule.java renamed to yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/rule/dept/DeptDataPermissionRule.java
1   -package cn.iocoder.yudao.framework.datapermission.core.dept.rule;
  1 +package cn.iocoder.yudao.framework.datapermission.core.rule.dept;
2 2  
3 3 import cn.hutool.core.collection.CollUtil;
4 4 import cn.hutool.core.util.ObjectUtil;
... ... @@ -6,13 +6,13 @@ import cn.hutool.core.util.StrUtil;
6 6 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
7 7 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
8 8 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
9   -import cn.iocoder.yudao.framework.datapermission.core.dept.service.DeptDataPermissionFrameworkService;
10   -import cn.iocoder.yudao.framework.datapermission.core.dept.service.dto.DeptDataPermissionRespDTO;
11 9 import cn.iocoder.yudao.framework.datapermission.core.rule.DataPermissionRule;
12 10 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
13 11 import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils;
14 12 import cn.iocoder.yudao.framework.security.core.LoginUser;
15 13 import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
  14 +import cn.iocoder.yudao.module.system.api.permission.PermissionApi;
  15 +import cn.iocoder.yudao.module.system.api.permission.dto.DeptDataPermissionRespDTO;
16 16 import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
17 17 import lombok.AllArgsConstructor;
18 18 import lombok.extern.slf4j.Slf4j;
... ... @@ -25,7 +25,10 @@ import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
25 25 import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
26 26 import net.sf.jsqlparser.expression.operators.relational.InExpression;
27 27  
28   -import java.util.*;
  28 +import java.util.HashMap;
  29 +import java.util.HashSet;
  30 +import java.util.Map;
  31 +import java.util.Set;
29 32  
30 33 /**
31 34 * 基于部门的 {@link DataPermissionRule} 数据权限规则实现
... ... @@ -58,7 +61,7 @@ public class DeptDataPermissionRule implements DataPermissionRule {
58 61  
59 62 static final Expression EXPRESSION_NULL = new NullValue();
60 63  
61   - private final DeptDataPermissionFrameworkService deptDataPermissionService;
  64 + private final PermissionApi permissionApi;
62 65  
63 66 /**
64 67 * 基于部门的表字段配置
... ... @@ -102,7 +105,7 @@ public class DeptDataPermissionRule implements DataPermissionRule {
102 105 DeptDataPermissionRespDTO deptDataPermission = loginUser.getContext(CONTEXT_KEY, DeptDataPermissionRespDTO.class);
103 106 // 从上下文中拿不到,则调用逻辑进行获取
104 107 if (deptDataPermission == null) {
105   - deptDataPermission = deptDataPermissionService.getDeptDataPermission(loginUser.getId());
  108 + deptDataPermission = permissionApi.getDeptDataPermission(loginUser.getId());
106 109 if (deptDataPermission == null) {
107 110 log.error("[getExpression][LoginUser({}) 获取数据权限为 null]", JsonUtils.toJsonString(loginUser));
108 111 throw new NullPointerException(String.format("LoginUser(%d) Table(%s/%s) 未返回数据权限",
... ...
yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/dept/rule/DeptDataPermissionRuleCustomizer.java renamed to yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/rule/dept/DeptDataPermissionRuleCustomizer.java
1   -package cn.iocoder.yudao.framework.datapermission.core.dept.rule;
  1 +package cn.iocoder.yudao.framework.datapermission.core.rule.dept;
2 2  
3 3 /**
4 4 * {@link DeptDataPermissionRule} 的自定义配置接口
... ...
yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/dept/package-info.java renamed to yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/rule/dept/package-info.java
... ... @@ -3,4 +3,4 @@
3 3 *
4 4 * @author 芋道源码
5 5 */
6   -package cn.iocoder.yudao.framework.datapermission.core.dept;
  6 +package cn.iocoder.yudao.framework.datapermission.core.rule.dept;
... ...
yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/test/java/cn/iocoder/yudao/framework/datapermission/core/dept/rule/DeptDataPermissionRuleTest.java renamed to yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/test/java/cn/iocoder/yudao/framework/datapermission/core/rule/dept/DeptDataPermissionRuleTest.java
1   -package cn.iocoder.yudao.framework.datapermission.core.dept.rule;
  1 +package cn.iocoder.yudao.framework.datapermission.core.rule.dept;
2 2  
3 3 import cn.hutool.core.collection.CollUtil;
4 4 import cn.hutool.core.util.ReflectUtil;
5 5 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
6 6 import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
7   -import cn.iocoder.yudao.framework.datapermission.core.dept.service.DeptDataPermissionFrameworkService;
8   -import cn.iocoder.yudao.framework.datapermission.core.dept.service.dto.DeptDataPermissionRespDTO;
  7 +import cn.iocoder.yudao.module.system.api.permission.PermissionApi;
  8 +import cn.iocoder.yudao.module.system.api.permission.dto.DeptDataPermissionRespDTO;
9 9 import cn.iocoder.yudao.framework.security.core.LoginUser;
10 10 import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
11 11 import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
... ... @@ -19,7 +19,7 @@ import org.mockito.MockedStatic;
19 19  
20 20 import java.util.Map;
21 21  
22   -import static cn.iocoder.yudao.framework.datapermission.core.dept.rule.DeptDataPermissionRule.EXPRESSION_NULL;
  22 +import static cn.iocoder.yudao.framework.datapermission.core.rule.dept.DeptDataPermissionRule.EXPRESSION_NULL;
23 23 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
24 24 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString;
25 25 import static org.junit.jupiter.api.Assertions.*;
... ... @@ -38,7 +38,7 @@ class DeptDataPermissionRuleTest extends BaseMockitoUnitTest {
38 38 private DeptDataPermissionRule rule;
39 39  
40 40 @Mock
41   - private DeptDataPermissionFrameworkService deptDataPermissionFrameworkService;
  41 + private PermissionApi permissionApi;
42 42  
43 43 @BeforeEach
44 44 @SuppressWarnings("unchecked")
... ... @@ -95,7 +95,7 @@ class DeptDataPermissionRuleTest extends BaseMockitoUnitTest {
95 95 securityFrameworkUtilsMock.when(SecurityFrameworkUtils::getLoginUser).thenReturn(loginUser);
96 96 // mock 方法(DeptDataPermissionRespDTO)
97 97 DeptDataPermissionRespDTO deptDataPermission = new DeptDataPermissionRespDTO().setAll(true);
98   - when(deptDataPermissionFrameworkService.getDeptDataPermission(same(1L))).thenReturn(deptDataPermission);
  98 + when(permissionApi.getDeptDataPermission(same(1L))).thenReturn(deptDataPermission);
99 99  
100 100 // 调用
101 101 Expression expression = rule.getExpression(tableName, tableAlias);
... ... @@ -118,7 +118,7 @@ class DeptDataPermissionRuleTest extends BaseMockitoUnitTest {
118 118 securityFrameworkUtilsMock.when(SecurityFrameworkUtils::getLoginUser).thenReturn(loginUser);
119 119 // mock 方法(DeptDataPermissionRespDTO)
120 120 DeptDataPermissionRespDTO deptDataPermission = new DeptDataPermissionRespDTO();
121   - when(deptDataPermissionFrameworkService.getDeptDataPermission(same(1L))).thenReturn(deptDataPermission);
  121 + when(permissionApi.getDeptDataPermission(same(1L))).thenReturn(deptDataPermission);
122 122  
123 123 // 调用
124 124 Expression expression = rule.getExpression(tableName, tableAlias);
... ... @@ -142,7 +142,7 @@ class DeptDataPermissionRuleTest extends BaseMockitoUnitTest {
142 142 // mock 方法(DeptDataPermissionRespDTO)
143 143 DeptDataPermissionRespDTO deptDataPermission = new DeptDataPermissionRespDTO()
144 144 .setDeptIds(SetUtils.asSet(10L, 20L)).setSelf(true);
145   - when(deptDataPermissionFrameworkService.getDeptDataPermission(same(1L))).thenReturn(deptDataPermission);
  145 + when(permissionApi.getDeptDataPermission(same(1L))).thenReturn(deptDataPermission);
146 146  
147 147 // 调用
148 148 Expression expression = rule.getExpression(tableName, tableAlias);
... ... @@ -166,7 +166,7 @@ class DeptDataPermissionRuleTest extends BaseMockitoUnitTest {
166 166 // mock 方法(DeptDataPermissionRespDTO)
167 167 DeptDataPermissionRespDTO deptDataPermission = new DeptDataPermissionRespDTO()
168 168 .setSelf(true);
169   - when(deptDataPermissionFrameworkService.getDeptDataPermission(same(1L))).thenReturn(deptDataPermission);
  169 + when(permissionApi.getDeptDataPermission(same(1L))).thenReturn(deptDataPermission);
170 170 // 添加 user 字段配置
171 171 rule.addUserColumn("t_user", "id");
172 172  
... ... @@ -192,7 +192,7 @@ class DeptDataPermissionRuleTest extends BaseMockitoUnitTest {
192 192 // mock 方法(DeptDataPermissionRespDTO)
193 193 DeptDataPermissionRespDTO deptDataPermission = new DeptDataPermissionRespDTO()
194 194 .setDeptIds(CollUtil.newLinkedHashSet(10L, 20L));
195   - when(deptDataPermissionFrameworkService.getDeptDataPermission(same(1L))).thenReturn(deptDataPermission);
  195 + when(permissionApi.getDeptDataPermission(same(1L))).thenReturn(deptDataPermission);
196 196 // 添加 dept 字段配置
197 197 rule.addDeptColumn("t_user", "dept_id");
198 198  
... ... @@ -218,7 +218,7 @@ class DeptDataPermissionRuleTest extends BaseMockitoUnitTest {
218 218 // mock 方法(DeptDataPermissionRespDTO)
219 219 DeptDataPermissionRespDTO deptDataPermission = new DeptDataPermissionRespDTO()
220 220 .setDeptIds(CollUtil.newLinkedHashSet(10L, 20L)).setSelf(true);
221   - when(deptDataPermissionFrameworkService.getDeptDataPermission(same(1L))).thenReturn(deptDataPermission);
  221 + when(permissionApi.getDeptDataPermission(same(1L))).thenReturn(deptDataPermission);
222 222 // 添加 user 字段配置
223 223 rule.addUserColumn("t_user", "id");
224 224 // 添加 dept 字段配置
... ...
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoSecurityAutoConfiguration.java
... ... @@ -5,8 +5,11 @@ import cn.iocoder.yudao.framework.security.core.context.TransmittableThreadLocal
5 5 import cn.iocoder.yudao.framework.security.core.filter.TokenAuthenticationFilter;
6 6 import cn.iocoder.yudao.framework.security.core.handler.AccessDeniedHandlerImpl;
7 7 import cn.iocoder.yudao.framework.security.core.handler.AuthenticationEntryPointImpl;
  8 +import cn.iocoder.yudao.framework.security.core.service.SecurityFrameworkService;
  9 +import cn.iocoder.yudao.framework.security.core.service.SecurityFrameworkServiceImpl;
8 10 import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler;
9 11 import cn.iocoder.yudao.module.system.api.auth.OAuth2TokenApi;
  12 +import cn.iocoder.yudao.module.system.api.permission.PermissionApi;
10 13 import org.springframework.beans.factory.config.MethodInvokingFactoryBean;
11 14 import org.springframework.boot.context.properties.EnableConfigurationProperties;
12 15 import org.springframework.context.annotation.Bean;
... ... @@ -78,6 +81,11 @@ public class YudaoSecurityAutoConfiguration {
78 81 return new TokenAuthenticationFilter(securityProperties, globalExceptionHandler, oauth2TokenApi);
79 82 }
80 83  
  84 + @Bean("ss") // 使用 Spring Security 的缩写,方便食用
  85 + public SecurityFrameworkService securityFrameworkService(PermissionApi permissionApi) {
  86 + return new SecurityFrameworkServiceImpl(permissionApi);
  87 + }
  88 +
81 89 /**
82 90 * 声明调用 {@link SecurityContextHolder#setStrategyName(String)} 方法,
83 91 * 设置使用 {@link TransmittableThreadLocalSecurityContextHolderStrategy} 作为 Security 的上下文策略
... ...
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/service/SecurityPermissionFrameworkService.java renamed to yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/service/SecurityFrameworkService.java
1 1 package cn.iocoder.yudao.framework.security.core.service;
2 2  
3 3 /**
4   - * Security 框架 Permission Service 接口,定义 security 组件需要的功能
  4 + * Security 框架 Service 接口,定义权限相关的校验操作
5 5 *
6 6 * @author 芋道源码
7 7 */
8   -public interface SecurityPermissionFrameworkService {
  8 +public interface SecurityFrameworkService {
9 9  
10 10 /**
11 11 * 判断是否有权限
... ...
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/service/SecurityFrameworkServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.security.core.service;
  2 +
  3 +import cn.iocoder.yudao.module.system.api.permission.PermissionApi;
  4 +import lombok.AllArgsConstructor;
  5 +
  6 +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
  7 +
  8 +/**
  9 + * 默认的 {@link SecurityFrameworkService} 实现类
  10 + *
  11 + * @author 芋道源码
  12 + */
  13 +@AllArgsConstructor
  14 +public class SecurityFrameworkServiceImpl implements SecurityFrameworkService {
  15 +
  16 + private final PermissionApi permissionApi;
  17 +
  18 + @Override
  19 + public boolean hasPermission(String permission) {
  20 + return hasAnyPermissions(permission);
  21 + }
  22 +
  23 + @Override
  24 + public boolean hasAnyPermissions(String... permissions) {
  25 + return permissionApi.hasAnyPermissions(getLoginUserId(), permissions);
  26 + }
  27 +
  28 + @Override
  29 + public boolean hasRole(String role) {
  30 + return hasAnyRoles(role);
  31 + }
  32 +
  33 + @Override
  34 + public boolean hasAnyRoles(String... roles) {
  35 + return permissionApi.hasAnyRoles(getLoginUserId(), roles);
  36 + }
  37 +
  38 +}
... ...
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/permission/PermissionApi.java
1 1 package cn.iocoder.yudao.module.system.api.permission;
2 2  
  3 +import cn.iocoder.yudao.module.system.api.permission.dto.DeptDataPermissionRespDTO;
  4 +
3 5 import java.util.Collection;
4 6 import java.util.Set;
5 7  
... ... @@ -18,4 +20,30 @@ public interface PermissionApi {
18 20 */
19 21 Set<Long> getUserRoleIdListByRoleIds(Collection<Long> roleIds);
20 22  
  23 + /**
  24 + * 判断是否有权限,任一一个即可
  25 + *
  26 + * @param userId 用户编号
  27 + * @param permissions 权限
  28 + * @return 是否
  29 + */
  30 + boolean hasAnyPermissions(Long userId, String... permissions);
  31 +
  32 + /**
  33 + * 判断是否有角色,任一一个即可
  34 + *
  35 + * @param userId 用户编号
  36 + * @param roles 角色数组
  37 + * @return 是否
  38 + */
  39 + boolean hasAnyRoles(Long userId, String... roles);
  40 +
  41 + /**
  42 + * 获得登陆用户的部门数据权限
  43 + *
  44 + * @param userId 用户编号
  45 + * @return 部门数据权限
  46 + */
  47 + DeptDataPermissionRespDTO getDeptDataPermission(Long userId);
  48 +
21 49 }
... ...
yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/dept/service/dto/DeptDataPermissionRespDTO.java renamed to yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/permission/dto/DeptDataPermissionRespDTO.java
1   -package cn.iocoder.yudao.framework.datapermission.core.dept.service.dto;
  1 +package cn.iocoder.yudao.module.system.api.permission.dto;
2 2  
3 3 import lombok.Data;
4 4  
... ...
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/permission/PermissionApiImpl.java
1 1 package cn.iocoder.yudao.module.system.api.permission;
2 2  
  3 +import cn.iocoder.yudao.module.system.api.permission.dto.DeptDataPermissionRespDTO;
3 4 import cn.iocoder.yudao.module.system.service.permission.PermissionService;
4 5 import org.springframework.stereotype.Service;
5 6  
... ... @@ -23,4 +24,19 @@ public class PermissionApiImpl implements PermissionApi {
23 24 return permissionService.getUserRoleIdListByRoleIds(roleIds);
24 25 }
25 26  
  27 + @Override
  28 + public boolean hasAnyPermissions(Long userId, String... permissions) {
  29 + return permissionService.hasAnyPermissions(userId, permissions);
  30 + }
  31 +
  32 + @Override
  33 + public boolean hasAnyRoles(Long userId, String... roles) {
  34 + return permissionService.hasAnyRoles(userId, roles);
  35 + }
  36 +
  37 + @Override
  38 + public DeptDataPermissionRespDTO getDeptDataPermission(Long userId) {
  39 + return permissionService.getDeptDataPermission(userId);
  40 + }
  41 +
26 42 }
... ...
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/datapermission/config/DataPermissionConfiguration.java
... ... @@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.system.framework.datapermission.config;
2 2  
3 3 import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
4 4 import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
5   -import cn.iocoder.yudao.framework.datapermission.core.dept.rule.DeptDataPermissionRuleCustomizer;
  5 +import cn.iocoder.yudao.framework.datapermission.core.rule.dept.DeptDataPermissionRuleCustomizer;
6 6 import org.springframework.context.annotation.Bean;
7 7 import org.springframework.context.annotation.Configuration;
8 8  
... ...
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/PermissionService.java
1 1 package cn.iocoder.yudao.module.system.service.permission;
2 2  
3   -import cn.iocoder.yudao.framework.datapermission.core.dept.service.DeptDataPermissionFrameworkService;
4   -import cn.iocoder.yudao.framework.security.core.service.SecurityPermissionFrameworkService;
  3 +import cn.iocoder.yudao.module.system.api.permission.dto.DeptDataPermissionRespDTO;
5 4 import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO;
6 5 import org.springframework.lang.Nullable;
7 6  
... ... @@ -16,7 +15,7 @@ import java.util.Set;
16 15 *
17 16 * @author 芋道源码
18 17 */
19   -public interface PermissionService extends SecurityPermissionFrameworkService, DeptDataPermissionFrameworkService {
  18 +public interface PermissionService {
20 19  
21 20 /**
22 21 * 初始化权限的本地缓存
... ... @@ -115,4 +114,29 @@ public interface PermissionService extends SecurityPermissionFrameworkService, D
115 114 */
116 115 void processUserDeleted(Long userId);
117 116  
  117 + /**
  118 + * 判断是否有权限,任一一个即可
  119 + *
  120 + * @param userId 用户编号
  121 + * @param permissions 权限
  122 + * @return 是否
  123 + */
  124 + boolean hasAnyPermissions(Long userId, String... permissions);
  125 +
  126 + /**
  127 + * 判断是否有角色,任一一个即可
  128 + *
  129 + * @param roles 角色数组
  130 + * @return 是否
  131 + */
  132 + boolean hasAnyRoles(Long userId, String... roles);
  133 +
  134 + /**
  135 + * 获得登陆用户的部门数据权限
  136 + *
  137 + * @param userId 用户编号
  138 + * @return 部门数据权限
  139 + */
  140 + DeptDataPermissionRespDTO getDeptDataPermission(Long userId);
  141 +
118 142 }
... ...
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceImpl.java
... ... @@ -8,7 +8,7 @@ import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
8 8 import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
9 9 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
10 10 import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;
11   -import cn.iocoder.yudao.framework.datapermission.core.dept.service.dto.DeptDataPermissionRespDTO;
  11 +import cn.iocoder.yudao.module.system.api.permission.dto.DeptDataPermissionRespDTO;
12 12 import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
13 13 import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
14 14 import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO;
... ... @@ -45,7 +45,6 @@ import java.util.function.Supplier;
45 45  
46 46 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
47 47 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getMaxValue;
48   -import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
49 48 import static java.util.Collections.singleton;
50 49  
51 50 /**
... ... @@ -53,7 +52,7 @@ import static java.util.Collections.singleton;
53 52 *
54 53 * @author 芋道源码
55 54 */
56   -@Service("ss") // 使用 Spring Security 的缩写,方便食用
  55 +@Service
57 56 @Slf4j
58 57 public class PermissionServiceImpl implements PermissionService {
59 58  
... ... @@ -71,7 +70,7 @@ public class PermissionServiceImpl implements PermissionService {
71 70 * 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向
72 71 */
73 72 @Getter
74   - @Setter // 单元测试
  73 + @Setter // 单元测试需要
75 74 private volatile Multimap<Long, Long> roleMenuCache;
76 75 /**
77 76 * 菜单编号与角色编号的缓存映射
... ... @@ -81,6 +80,7 @@ public class PermissionServiceImpl implements PermissionService {
81 80 * 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向
82 81 */
83 82 @Getter
  83 + @Setter // 单元测试需要
84 84 private volatile Multimap<Long, Long> menuRoleCache;
85 85 /**
86 86 * 缓存 RoleMenu 的最大更新时间,用于后续的增量轮询,判断是否有更新
... ... @@ -399,19 +399,14 @@ public class PermissionServiceImpl implements PermissionService {
399 399 }
400 400  
401 401 @Override
402   - public boolean hasPermission(String permission) {
403   - return hasAnyPermissions(permission);
404   - }
405   -
406   - @Override
407   - public boolean hasAnyPermissions(String... permissions) {
  402 + public boolean hasAnyPermissions(Long userId, String... permissions) {
408 403 // 如果为空,说明已经有权限
409 404 if (ArrayUtil.isEmpty(permissions)) {
410 405 return true;
411 406 }
412 407  
413 408 // 获得当前登录的角色。如果为空,说明没有权限
414   - Set<Long> roleIds = getUserRoleIdsFromCache(getLoginUserId(), singleton(CommonStatusEnum.ENABLE.getStatus()));
  409 + Set<Long> roleIds = getUserRoleIdsFromCache(userId, singleton(CommonStatusEnum.ENABLE.getStatus()));
415 410 if (CollUtil.isEmpty(roleIds)) {
416 411 return false;
417 412 }
... ... @@ -434,19 +429,14 @@ public class PermissionServiceImpl implements PermissionService {
434 429 }
435 430  
436 431 @Override
437   - public boolean hasRole(String role) {
438   - return hasAnyRoles(role);
439   - }
440   -
441   - @Override
442   - public boolean hasAnyRoles(String... roles) {
  432 + public boolean hasAnyRoles(Long userId, String... roles) {
443 433 // 如果为空,说明已经有权限
444 434 if (ArrayUtil.isEmpty(roles)) {
445 435 return true;
446 436 }
447 437  
448 438 // 获得当前登录的角色。如果为空,说明没有权限
449   - Set<Long> roleIds = getUserRoleIdsFromCache(getLoginUserId(), singleton(CommonStatusEnum.ENABLE.getStatus()));
  439 + Set<Long> roleIds = getUserRoleIdsFromCache(userId, singleton(CommonStatusEnum.ENABLE.getStatus()));
450 440 if (CollUtil.isEmpty(roleIds)) {
451 441 return false;
452 442 }
... ...
yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/auth/AuthServiceImplTest.java
... ... @@ -13,6 +13,7 @@ import cn.iocoder.yudao.module.system.enums.logger.LoginLogTypeEnum;
13 13 import cn.iocoder.yudao.module.system.enums.logger.LoginResultEnum;
14 14 import cn.iocoder.yudao.module.system.service.common.CaptchaService;
15 15 import cn.iocoder.yudao.module.system.service.logger.LoginLogService;
  16 +import cn.iocoder.yudao.module.system.service.member.MemberService;
16 17 import cn.iocoder.yudao.module.system.service.social.SocialUserService;
17 18 import cn.iocoder.yudao.module.system.service.user.AdminUserService;
18 19 import org.junit.jupiter.api.BeforeEach;
... ... @@ -49,6 +50,8 @@ public class AuthServiceImplTest extends BaseDbUnitTest {
49 50 private SmsCodeApi smsCodeApi;
50 51 @MockBean
51 52 private OAuth2TokenService oauth2TokenService;
  53 + @MockBean
  54 + private MemberService memberService;
52 55  
53 56 @MockBean
54 57 private Validator validator;
... ...
yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceTest.java
... ... @@ -4,7 +4,7 @@ import cn.hutool.core.collection.CollUtil;
4 4 import cn.hutool.core.map.MapUtil;
5 5 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
6 6 import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
7   -import cn.iocoder.yudao.framework.datapermission.core.dept.service.dto.DeptDataPermissionRespDTO;
  7 +import cn.iocoder.yudao.module.system.api.permission.dto.DeptDataPermissionRespDTO;
8 8 import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
9 9 import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
10 10 import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO;
... ... @@ -359,22 +359,84 @@ public class PermissionServiceTest extends BaseDbUnitTest {
359 359 verify(permissionProducer).sendUserRoleRefreshMessage();
360 360 }
361 361  
362   -// @Test
363   -// public void testHasAnyRoles_superAdmin() {
364   -// // 准备参数
365   -// String[] roles = new String[]{"yunai", "tudou"};
366   -// // mock 方法
367   -// List<RoleDO> roleList = singletonList(randomPojo(RoleDO.class, o -> o.setId(100L)));
368   -// when(roleService.getRolesFromCache(eq(roleIds))).thenReturn(roleList);
369   -// when(roleService.hasAnySuperAdmin(same(roleList))).thenReturn(true);
370   -// List<MenuDO> menuList = randomPojoList(MenuDO.class);
371   -// when(menuService.getMenuListFromCache(eq(menuTypes), eq(menusStatuses))).thenReturn(menuList);
372   -//
373   -// // 调用
374   -// List<MenuDO> result = permissionService.getRoleMenuListFromCache(roleIds, menuTypes, menusStatuses);
375   -// // 断言
376   -// assertSame(menuList, result);
377   -// }
  362 + @Test
  363 + public void testHasAnyPermissions_superAdmin() {
  364 + // 准备参数
  365 + Long userId = 1L;
  366 + String[] roles = new String[]{"system:user:query", "system:user:create"};
  367 + // mock 用户与角色的缓存
  368 + permissionService.setUserRoleCache(MapUtil.<Long, Set<Long>>builder().put(1L, asSet(100L)).build());
  369 + RoleDO role = randomPojo(RoleDO.class, o -> o.setId(100L)
  370 + .setStatus(CommonStatusEnum.ENABLE.getStatus()));
  371 + when(roleService.getRoleFromCache(eq(100L))).thenReturn(role);
  372 + // mock 其它方法
  373 + when(roleService.hasAnySuperAdmin(eq(asSet(100L)))).thenReturn(true);
  374 +
  375 + // 调用
  376 + boolean has = permissionService.hasAnyPermissions(userId, roles);
  377 + // 断言
  378 + assertTrue(has);
  379 + }
  380 +
  381 + @Test
  382 + public void testHasAnyPermissions_normal() {
  383 + // 准备参数
  384 + Long userId = 1L;
  385 + String[] roles = new String[]{"system:user:query", "system:user:create"};
  386 + // mock 用户与角色的缓存
  387 + permissionService.setUserRoleCache(MapUtil.<Long, Set<Long>>builder().put(1L, asSet(100L)).build());
  388 + RoleDO role = randomPojo(RoleDO.class, o -> o.setId(100L)
  389 + .setStatus(CommonStatusEnum.ENABLE.getStatus()));
  390 + when(roleService.getRoleFromCache(eq(100L))).thenReturn(role);
  391 + // mock 其它方法
  392 + MenuDO menu = randomPojo(MenuDO.class, o -> o.setId(1000L));
  393 + when(menuService.getMenuListByPermissionFromCache(eq("system:user:create"))).thenReturn(singletonList(menu));
  394 + permissionService.setMenuRoleCache(ImmutableMultimap.<Long, Long>builder().put(1000L, 100L).build());
  395 +
  396 +
  397 + // 调用
  398 + boolean has = permissionService.hasAnyPermissions(userId, roles);
  399 + // 断言
  400 + assertTrue(has);
  401 + }
  402 +
  403 + @Test
  404 + public void testHasAnyRoles_superAdmin() {
  405 + // 准备参数
  406 + Long userId = 1L;
  407 + String[] roles = new String[]{"yunai", "tudou"};
  408 + // mock 用户与角色的缓存
  409 + permissionService.setUserRoleCache(MapUtil.<Long, Set<Long>>builder().put(1L, asSet(100L)).build());
  410 + RoleDO role = randomPojo(RoleDO.class, o -> o.setId(100L)
  411 + .setStatus(CommonStatusEnum.ENABLE.getStatus()));
  412 + when(roleService.getRoleFromCache(eq(100L))).thenReturn(role);
  413 + // mock 其它方法
  414 + when(roleService.hasAnySuperAdmin(eq(asSet(100L)))).thenReturn(true);
  415 +
  416 + // 调用
  417 + boolean has = permissionService.hasAnyRoles(userId, roles);
  418 + // 断言
  419 + assertTrue(has);
  420 + }
  421 +
  422 + @Test
  423 + public void testHasAnyRoles_normal() {
  424 + // 准备参数
  425 + Long userId = 1L;
  426 + String[] roles = new String[]{"yunai", "tudou"};
  427 + // mock 用户与角色的缓存
  428 + permissionService.setUserRoleCache(MapUtil.<Long, Set<Long>>builder().put(1L, asSet(100L)).build());
  429 + RoleDO role = randomPojo(RoleDO.class, o -> o.setId(100L).setCode("yunai")
  430 + .setStatus(CommonStatusEnum.ENABLE.getStatus()));
  431 + when(roleService.getRoleFromCache(eq(100L))).thenReturn(role);
  432 + // mock 其它方法
  433 + when(roleService.getRolesFromCache(eq(asSet(100L)))).thenReturn(singletonList(role));
  434 +
  435 + // 调用
  436 + boolean has = permissionService.hasAnyRoles(userId, roles);
  437 + // 断言
  438 + assertTrue(has);
  439 + }
378 440  
379 441 @Test
380 442 public void testGetDeptDataPermission_All() {
... ...