Commit 5794780c4e11da7868d90a9f4c635889ea6a906f
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
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
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
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() { | ... | ... |