diff --git a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/pom.xml b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/pom.xml index 802ff1904..09e878688 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/pom.xml @@ -34,6 +34,13 @@ yudao-spring-boot-starter-mybatis + + + cn.iocoder.boot + yudao-module-system-api + ${revision} + + cn.iocoder.boot diff --git a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/config/YudaoDeptDataPermissionAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/config/YudaoDeptDataPermissionAutoConfiguration.java index b66c17674..92da456ee 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/config/YudaoDeptDataPermissionAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/config/YudaoDeptDataPermissionAutoConfiguration.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.framework.datapermission.config; -import cn.iocoder.yudao.framework.datapermission.core.dept.rule.DeptDataPermissionRule; -import cn.iocoder.yudao.framework.datapermission.core.dept.rule.DeptDataPermissionRuleCustomizer; -import cn.iocoder.yudao.framework.datapermission.core.dept.service.DeptDataPermissionFrameworkService; +import cn.iocoder.yudao.framework.datapermission.core.rule.dept.DeptDataPermissionRule; +import cn.iocoder.yudao.framework.datapermission.core.rule.dept.DeptDataPermissionRuleCustomizer; import cn.iocoder.yudao.framework.security.core.LoginUser; +import cn.iocoder.yudao.module.system.api.permission.PermissionApi; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.context.annotation.Bean; @@ -18,14 +18,14 @@ import java.util.List; */ @Configuration @ConditionalOnClass(LoginUser.class) -@ConditionalOnBean(value = {DeptDataPermissionFrameworkService.class, DeptDataPermissionRuleCustomizer.class}) +@ConditionalOnBean(value = {PermissionApi.class, DeptDataPermissionRuleCustomizer.class}) public class YudaoDeptDataPermissionAutoConfiguration { @Bean - public DeptDataPermissionRule deptDataPermissionRule(DeptDataPermissionFrameworkService service, + public DeptDataPermissionRule deptDataPermissionRule(PermissionApi permissionApi, List customizers) { // 创建 DeptDataPermissionRule 对象 - DeptDataPermissionRule rule = new DeptDataPermissionRule(service); + DeptDataPermissionRule rule = new DeptDataPermissionRule(permissionApi); // 补全表配置 customizers.forEach(customizer -> customizer.customize(rule)); return rule; 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 deleted file mode 100644 index e491aa036..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/dept/service/DeptDataPermissionFrameworkService.java +++ /dev/null @@ -1,21 +0,0 @@ -package cn.iocoder.yudao.framework.datapermission.core.dept.service; - -import cn.iocoder.yudao.framework.datapermission.core.dept.service.dto.DeptDataPermissionRespDTO; - -/** - * 基于部门的数据权限 Framework Service 接口 - * 目前的实现类是 SysPermissionServiceImpl 类 - * - * @author 芋道源码 - */ -public interface DeptDataPermissionFrameworkService { - - /** - * 获得登陆用户的部门数据权限 - * - * @param userId 用户编号 - * @return 部门数据权限 - */ - DeptDataPermissionRespDTO getDeptDataPermission(Long userId); - -} 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/rule/dept/DeptDataPermissionRule.java similarity index 95% rename from yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/dept/rule/DeptDataPermissionRule.java rename to yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/rule/dept/DeptDataPermissionRule.java index 2a0c9aefa..7f9a74a61 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/rule/dept/DeptDataPermissionRule.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.datapermission.core.dept.rule; +package cn.iocoder.yudao.framework.datapermission.core.rule.dept; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; @@ -6,13 +6,13 @@ import cn.hutool.core.util.StrUtil; 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; import cn.iocoder.yudao.framework.security.core.LoginUser; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; +import cn.iocoder.yudao.module.system.api.permission.PermissionApi; +import cn.iocoder.yudao.module.system.api.permission.dto.DeptDataPermissionRespDTO; import com.baomidou.mybatisplus.core.metadata.TableInfoHelper; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -25,7 +25,10 @@ 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.*; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; /** * 基于部门的 {@link DataPermissionRule} 数据权限规则实现 @@ -58,7 +61,7 @@ public class DeptDataPermissionRule implements DataPermissionRule { static final Expression EXPRESSION_NULL = new NullValue(); - private final DeptDataPermissionFrameworkService deptDataPermissionService; + private final PermissionApi permissionApi; /** * 基于部门的表字段配置 @@ -102,7 +105,7 @@ public class DeptDataPermissionRule implements DataPermissionRule { DeptDataPermissionRespDTO deptDataPermission = loginUser.getContext(CONTEXT_KEY, DeptDataPermissionRespDTO.class); // 从上下文中拿不到,则调用逻辑进行获取 if (deptDataPermission == null) { - deptDataPermission = deptDataPermissionService.getDeptDataPermission(loginUser.getId()); + deptDataPermission = permissionApi.getDeptDataPermission(loginUser.getId()); if (deptDataPermission == null) { log.error("[getExpression][LoginUser({}) 获取数据权限为 null]", JsonUtils.toJsonString(loginUser)); throw new NullPointerException(String.format("LoginUser(%d) Table(%s/%s) 未返回数据权限", diff --git a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/dept/rule/DeptDataPermissionRuleCustomizer.java b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/rule/dept/DeptDataPermissionRuleCustomizer.java similarity index 89% rename from yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/dept/rule/DeptDataPermissionRuleCustomizer.java rename to yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/rule/dept/DeptDataPermissionRuleCustomizer.java index 5341ee5e4..e5e4f578c 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/dept/rule/DeptDataPermissionRuleCustomizer.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/rule/dept/DeptDataPermissionRuleCustomizer.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.datapermission.core.dept.rule; +package cn.iocoder.yudao.framework.datapermission.core.rule.dept; /** * {@link DeptDataPermissionRule} 的自定义配置接口 diff --git a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/dept/package-info.java b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/rule/dept/package-info.java similarity index 52% rename from yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/dept/package-info.java rename to yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/rule/dept/package-info.java index 20daa85c5..66e932680 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/dept/package-info.java +++ b/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 @@ * * @author 芋道源码 */ -package cn.iocoder.yudao.framework.datapermission.core.dept; +package cn.iocoder.yudao.framework.datapermission.core.rule.dept; 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/rule/dept/DeptDataPermissionRuleTest.java similarity index 90% rename from yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/test/java/cn/iocoder/yudao/framework/datapermission/core/dept/rule/DeptDataPermissionRuleTest.java rename to yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/test/java/cn/iocoder/yudao/framework/datapermission/core/rule/dept/DeptDataPermissionRuleTest.java index ef5ff16ac..a50e2382f 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/rule/dept/DeptDataPermissionRuleTest.java @@ -1,11 +1,11 @@ -package cn.iocoder.yudao.framework.datapermission.core.dept.rule; +package cn.iocoder.yudao.framework.datapermission.core.rule.dept; 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; +import cn.iocoder.yudao.module.system.api.permission.PermissionApi; +import cn.iocoder.yudao.module.system.api.permission.dto.DeptDataPermissionRespDTO; import cn.iocoder.yudao.framework.security.core.LoginUser; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; @@ -19,7 +19,7 @@ import org.mockito.MockedStatic; import java.util.Map; -import static cn.iocoder.yudao.framework.datapermission.core.dept.rule.DeptDataPermissionRule.EXPRESSION_NULL; +import static cn.iocoder.yudao.framework.datapermission.core.rule.dept.DeptDataPermissionRule.EXPRESSION_NULL; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString; import static org.junit.jupiter.api.Assertions.*; @@ -38,7 +38,7 @@ class DeptDataPermissionRuleTest extends BaseMockitoUnitTest { private DeptDataPermissionRule rule; @Mock - private DeptDataPermissionFrameworkService deptDataPermissionFrameworkService; + private PermissionApi permissionApi; @BeforeEach @SuppressWarnings("unchecked") @@ -95,7 +95,7 @@ class DeptDataPermissionRuleTest extends BaseMockitoUnitTest { securityFrameworkUtilsMock.when(SecurityFrameworkUtils::getLoginUser).thenReturn(loginUser); // mock 方法(DeptDataPermissionRespDTO) DeptDataPermissionRespDTO deptDataPermission = new DeptDataPermissionRespDTO().setAll(true); - when(deptDataPermissionFrameworkService.getDeptDataPermission(same(1L))).thenReturn(deptDataPermission); + when(permissionApi.getDeptDataPermission(same(1L))).thenReturn(deptDataPermission); // 调用 Expression expression = rule.getExpression(tableName, tableAlias); @@ -118,7 +118,7 @@ class DeptDataPermissionRuleTest extends BaseMockitoUnitTest { securityFrameworkUtilsMock.when(SecurityFrameworkUtils::getLoginUser).thenReturn(loginUser); // mock 方法(DeptDataPermissionRespDTO) DeptDataPermissionRespDTO deptDataPermission = new DeptDataPermissionRespDTO(); - when(deptDataPermissionFrameworkService.getDeptDataPermission(same(1L))).thenReturn(deptDataPermission); + when(permissionApi.getDeptDataPermission(same(1L))).thenReturn(deptDataPermission); // 调用 Expression expression = rule.getExpression(tableName, tableAlias); @@ -142,7 +142,7 @@ class DeptDataPermissionRuleTest extends BaseMockitoUnitTest { // mock 方法(DeptDataPermissionRespDTO) DeptDataPermissionRespDTO deptDataPermission = new DeptDataPermissionRespDTO() .setDeptIds(SetUtils.asSet(10L, 20L)).setSelf(true); - when(deptDataPermissionFrameworkService.getDeptDataPermission(same(1L))).thenReturn(deptDataPermission); + when(permissionApi.getDeptDataPermission(same(1L))).thenReturn(deptDataPermission); // 调用 Expression expression = rule.getExpression(tableName, tableAlias); @@ -166,7 +166,7 @@ class DeptDataPermissionRuleTest extends BaseMockitoUnitTest { // mock 方法(DeptDataPermissionRespDTO) DeptDataPermissionRespDTO deptDataPermission = new DeptDataPermissionRespDTO() .setSelf(true); - when(deptDataPermissionFrameworkService.getDeptDataPermission(same(1L))).thenReturn(deptDataPermission); + when(permissionApi.getDeptDataPermission(same(1L))).thenReturn(deptDataPermission); // 添加 user 字段配置 rule.addUserColumn("t_user", "id"); @@ -192,7 +192,7 @@ class DeptDataPermissionRuleTest extends BaseMockitoUnitTest { // mock 方法(DeptDataPermissionRespDTO) DeptDataPermissionRespDTO deptDataPermission = new DeptDataPermissionRespDTO() .setDeptIds(CollUtil.newLinkedHashSet(10L, 20L)); - when(deptDataPermissionFrameworkService.getDeptDataPermission(same(1L))).thenReturn(deptDataPermission); + when(permissionApi.getDeptDataPermission(same(1L))).thenReturn(deptDataPermission); // 添加 dept 字段配置 rule.addDeptColumn("t_user", "dept_id"); @@ -218,7 +218,7 @@ class DeptDataPermissionRuleTest extends BaseMockitoUnitTest { // mock 方法(DeptDataPermissionRespDTO) DeptDataPermissionRespDTO deptDataPermission = new DeptDataPermissionRespDTO() .setDeptIds(CollUtil.newLinkedHashSet(10L, 20L)).setSelf(true); - when(deptDataPermissionFrameworkService.getDeptDataPermission(same(1L))).thenReturn(deptDataPermission); + when(permissionApi.getDeptDataPermission(same(1L))).thenReturn(deptDataPermission); // 添加 user 字段配置 rule.addUserColumn("t_user", "id"); // 添加 dept 字段配置 diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoSecurityAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoSecurityAutoConfiguration.java index 4933969bc..c5f2ef033 100644 --- a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoSecurityAutoConfiguration.java +++ b/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 import cn.iocoder.yudao.framework.security.core.filter.TokenAuthenticationFilter; import cn.iocoder.yudao.framework.security.core.handler.AccessDeniedHandlerImpl; import cn.iocoder.yudao.framework.security.core.handler.AuthenticationEntryPointImpl; +import cn.iocoder.yudao.framework.security.core.service.SecurityFrameworkService; +import cn.iocoder.yudao.framework.security.core.service.SecurityFrameworkServiceImpl; import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler; import cn.iocoder.yudao.module.system.api.auth.OAuth2TokenApi; +import cn.iocoder.yudao.module.system.api.permission.PermissionApi; import org.springframework.beans.factory.config.MethodInvokingFactoryBean; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; @@ -78,6 +81,11 @@ public class YudaoSecurityAutoConfiguration { return new TokenAuthenticationFilter(securityProperties, globalExceptionHandler, oauth2TokenApi); } + @Bean("ss") // 使用 Spring Security 的缩写,方便食用 + public SecurityFrameworkService securityFrameworkService(PermissionApi permissionApi) { + return new SecurityFrameworkServiceImpl(permissionApi); + } + /** * 声明调用 {@link SecurityContextHolder#setStrategyName(String)} 方法, * 设置使用 {@link TransmittableThreadLocalSecurityContextHolderStrategy} 作为 Security 的上下文策略 diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/service/SecurityPermissionFrameworkService.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/service/SecurityFrameworkService.java similarity index 85% rename from yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/service/SecurityPermissionFrameworkService.java rename to yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/service/SecurityFrameworkService.java index 75f11b175..49cc9f972 100644 --- a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/service/SecurityPermissionFrameworkService.java +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/service/SecurityFrameworkService.java @@ -1,11 +1,11 @@ package cn.iocoder.yudao.framework.security.core.service; /** - * Security 框架 Permission Service 接口,定义 security 组件需要的功能 + * Security 框架 Service 接口,定义权限相关的校验操作 * * @author 芋道源码 */ -public interface SecurityPermissionFrameworkService { +public interface SecurityFrameworkService { /** * 判断是否有权限 diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/service/SecurityFrameworkServiceImpl.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/service/SecurityFrameworkServiceImpl.java new file mode 100644 index 000000000..2227ad3c2 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/service/SecurityFrameworkServiceImpl.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.framework.security.core.service; + +import cn.iocoder.yudao.module.system.api.permission.PermissionApi; +import lombok.AllArgsConstructor; + +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; + +/** + * 默认的 {@link SecurityFrameworkService} 实现类 + * + * @author 芋道源码 + */ +@AllArgsConstructor +public class SecurityFrameworkServiceImpl implements SecurityFrameworkService { + + private final PermissionApi permissionApi; + + @Override + public boolean hasPermission(String permission) { + return hasAnyPermissions(permission); + } + + @Override + public boolean hasAnyPermissions(String... permissions) { + return permissionApi.hasAnyPermissions(getLoginUserId(), permissions); + } + + @Override + public boolean hasRole(String role) { + return hasAnyRoles(role); + } + + @Override + public boolean hasAnyRoles(String... roles) { + return permissionApi.hasAnyRoles(getLoginUserId(), roles); + } + +} diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/permission/PermissionApi.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/permission/PermissionApi.java index 04e963869..ea16fe4ea 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/permission/PermissionApi.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/permission/PermissionApi.java @@ -1,5 +1,7 @@ package cn.iocoder.yudao.module.system.api.permission; +import cn.iocoder.yudao.module.system.api.permission.dto.DeptDataPermissionRespDTO; + import java.util.Collection; import java.util.Set; @@ -18,4 +20,30 @@ public interface PermissionApi { */ Set getUserRoleIdListByRoleIds(Collection roleIds); + /** + * 判断是否有权限,任一一个即可 + * + * @param userId 用户编号 + * @param permissions 权限 + * @return 是否 + */ + boolean hasAnyPermissions(Long userId, String... permissions); + + /** + * 判断是否有角色,任一一个即可 + * + * @param userId 用户编号 + * @param roles 角色数组 + * @return 是否 + */ + boolean hasAnyRoles(Long userId, String... roles); + + /** + * 获得登陆用户的部门数据权限 + * + * @param userId 用户编号 + * @return 部门数据权限 + */ + DeptDataPermissionRespDTO getDeptDataPermission(Long userId); + } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/dept/service/dto/DeptDataPermissionRespDTO.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/permission/dto/DeptDataPermissionRespDTO.java similarity index 88% rename from yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/dept/service/dto/DeptDataPermissionRespDTO.java rename to yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/permission/dto/DeptDataPermissionRespDTO.java index 897fb226a..5650e89b9 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/dept/service/dto/DeptDataPermissionRespDTO.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/permission/dto/DeptDataPermissionRespDTO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.datapermission.core.dept.service.dto; +package cn.iocoder.yudao.module.system.api.permission.dto; import lombok.Data; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/permission/PermissionApiImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/permission/PermissionApiImpl.java index 5d2b55078..52e30ea04 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/permission/PermissionApiImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/permission/PermissionApiImpl.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.system.api.permission; +import cn.iocoder.yudao.module.system.api.permission.dto.DeptDataPermissionRespDTO; import cn.iocoder.yudao.module.system.service.permission.PermissionService; import org.springframework.stereotype.Service; @@ -23,4 +24,19 @@ public class PermissionApiImpl implements PermissionApi { return permissionService.getUserRoleIdListByRoleIds(roleIds); } + @Override + public boolean hasAnyPermissions(Long userId, String... permissions) { + return permissionService.hasAnyPermissions(userId, permissions); + } + + @Override + public boolean hasAnyRoles(Long userId, String... roles) { + return permissionService.hasAnyRoles(userId, roles); + } + + @Override + public DeptDataPermissionRespDTO getDeptDataPermission(Long userId) { + return permissionService.getDeptDataPermission(userId); + } + } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/datapermission/config/DataPermissionConfiguration.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/datapermission/config/DataPermissionConfiguration.java index d7246f242..136866ca0 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/datapermission/config/DataPermissionConfiguration.java +++ b/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; import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; -import cn.iocoder.yudao.framework.datapermission.core.dept.rule.DeptDataPermissionRuleCustomizer; +import cn.iocoder.yudao.framework.datapermission.core.rule.dept.DeptDataPermissionRuleCustomizer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/PermissionService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/PermissionService.java index beee0947e..97174d629 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/PermissionService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/PermissionService.java @@ -1,7 +1,6 @@ package cn.iocoder.yudao.module.system.service.permission; -import cn.iocoder.yudao.framework.datapermission.core.dept.service.DeptDataPermissionFrameworkService; -import cn.iocoder.yudao.framework.security.core.service.SecurityPermissionFrameworkService; +import cn.iocoder.yudao.module.system.api.permission.dto.DeptDataPermissionRespDTO; import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO; import org.springframework.lang.Nullable; @@ -16,7 +15,7 @@ import java.util.Set; * * @author 芋道源码 */ -public interface PermissionService extends SecurityPermissionFrameworkService, DeptDataPermissionFrameworkService { +public interface PermissionService { /** * 初始化权限的本地缓存 @@ -115,4 +114,29 @@ public interface PermissionService extends SecurityPermissionFrameworkService, D */ void processUserDeleted(Long userId); + /** + * 判断是否有权限,任一一个即可 + * + * @param userId 用户编号 + * @param permissions 权限 + * @return 是否 + */ + boolean hasAnyPermissions(Long userId, String... permissions); + + /** + * 判断是否有角色,任一一个即可 + * + * @param roles 角色数组 + * @return 是否 + */ + boolean hasAnyRoles(Long userId, String... roles); + + /** + * 获得登陆用户的部门数据权限 + * + * @param userId 用户编号 + * @return 部门数据权限 + */ + DeptDataPermissionRespDTO getDeptDataPermission(Long userId); + } 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 294c9c978..74435cf48 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 @@ -8,7 +8,7 @@ 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.module.system.api.permission.dto.DeptDataPermissionRespDTO; 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; @@ -45,7 +45,6 @@ import java.util.function.Supplier; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getMaxValue; -import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; import static java.util.Collections.singleton; /** @@ -53,7 +52,7 @@ import static java.util.Collections.singleton; * * @author 芋道源码 */ -@Service("ss") // 使用 Spring Security 的缩写,方便食用 +@Service @Slf4j public class PermissionServiceImpl implements PermissionService { @@ -71,7 +70,7 @@ public class PermissionServiceImpl implements PermissionService { * 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向 */ @Getter - @Setter // 单元测试 + @Setter // 单元测试需要 private volatile Multimap roleMenuCache; /** * 菜单编号与角色编号的缓存映射 @@ -81,6 +80,7 @@ public class PermissionServiceImpl implements PermissionService { * 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向 */ @Getter + @Setter // 单元测试需要 private volatile Multimap menuRoleCache; /** * 缓存 RoleMenu 的最大更新时间,用于后续的增量轮询,判断是否有更新 @@ -399,19 +399,14 @@ public class PermissionServiceImpl implements PermissionService { } @Override - public boolean hasPermission(String permission) { - return hasAnyPermissions(permission); - } - - @Override - public boolean hasAnyPermissions(String... permissions) { + public boolean hasAnyPermissions(Long userId, String... permissions) { // 如果为空,说明已经有权限 if (ArrayUtil.isEmpty(permissions)) { return true; } // 获得当前登录的角色。如果为空,说明没有权限 - Set roleIds = getUserRoleIdsFromCache(getLoginUserId(), singleton(CommonStatusEnum.ENABLE.getStatus())); + Set roleIds = getUserRoleIdsFromCache(userId, singleton(CommonStatusEnum.ENABLE.getStatus())); if (CollUtil.isEmpty(roleIds)) { return false; } @@ -434,19 +429,14 @@ public class PermissionServiceImpl implements PermissionService { } @Override - public boolean hasRole(String role) { - return hasAnyRoles(role); - } - - @Override - public boolean hasAnyRoles(String... roles) { + public boolean hasAnyRoles(Long userId, String... roles) { // 如果为空,说明已经有权限 if (ArrayUtil.isEmpty(roles)) { return true; } // 获得当前登录的角色。如果为空,说明没有权限 - Set roleIds = getUserRoleIdsFromCache(getLoginUserId(), singleton(CommonStatusEnum.ENABLE.getStatus())); + Set roleIds = getUserRoleIdsFromCache(userId, singleton(CommonStatusEnum.ENABLE.getStatus())); if (CollUtil.isEmpty(roleIds)) { return false; } 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 a04a9719e..b68ef207b 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 @@ -13,6 +13,7 @@ import cn.iocoder.yudao.module.system.enums.logger.LoginLogTypeEnum; 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.logger.LoginLogService; +import cn.iocoder.yudao.module.system.service.member.MemberService; import cn.iocoder.yudao.module.system.service.social.SocialUserService; import cn.iocoder.yudao.module.system.service.user.AdminUserService; import org.junit.jupiter.api.BeforeEach; @@ -49,6 +50,8 @@ public class AuthServiceImplTest extends BaseDbUnitTest { private SmsCodeApi smsCodeApi; @MockBean private OAuth2TokenService oauth2TokenService; + @MockBean + private MemberService memberService; @MockBean private Validator validator; 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 d2ef99e80..324a415be 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 @@ -4,7 +4,7 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.map.MapUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; -import cn.iocoder.yudao.framework.datapermission.core.dept.service.dto.DeptDataPermissionRespDTO; +import cn.iocoder.yudao.module.system.api.permission.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.MenuDO; @@ -359,22 +359,84 @@ public class PermissionServiceTest extends BaseDbUnitTest { verify(permissionProducer).sendUserRoleRefreshMessage(); } -// @Test -// public void testHasAnyRoles_superAdmin() { -// // 准备参数 -// String[] roles = new String[]{"yunai", "tudou"}; -// // mock 方法 -// List roleList = singletonList(randomPojo(RoleDO.class, o -> o.setId(100L))); -// when(roleService.getRolesFromCache(eq(roleIds))).thenReturn(roleList); -// when(roleService.hasAnySuperAdmin(same(roleList))).thenReturn(true); -// List menuList = randomPojoList(MenuDO.class); -// when(menuService.getMenuListFromCache(eq(menuTypes), eq(menusStatuses))).thenReturn(menuList); -// -// // 调用 -// List result = permissionService.getRoleMenuListFromCache(roleIds, menuTypes, menusStatuses); -// // 断言 -// assertSame(menuList, result); -// } + @Test + public void testHasAnyPermissions_superAdmin() { + // 准备参数 + Long userId = 1L; + String[] roles = new String[]{"system:user:query", "system:user:create"}; + // mock 用户与角色的缓存 + permissionService.setUserRoleCache(MapUtil.>builder().put(1L, asSet(100L)).build()); + RoleDO role = randomPojo(RoleDO.class, o -> o.setId(100L) + .setStatus(CommonStatusEnum.ENABLE.getStatus())); + when(roleService.getRoleFromCache(eq(100L))).thenReturn(role); + // mock 其它方法 + when(roleService.hasAnySuperAdmin(eq(asSet(100L)))).thenReturn(true); + + // 调用 + boolean has = permissionService.hasAnyPermissions(userId, roles); + // 断言 + assertTrue(has); + } + + @Test + public void testHasAnyPermissions_normal() { + // 准备参数 + Long userId = 1L; + String[] roles = new String[]{"system:user:query", "system:user:create"}; + // mock 用户与角色的缓存 + permissionService.setUserRoleCache(MapUtil.>builder().put(1L, asSet(100L)).build()); + RoleDO role = randomPojo(RoleDO.class, o -> o.setId(100L) + .setStatus(CommonStatusEnum.ENABLE.getStatus())); + when(roleService.getRoleFromCache(eq(100L))).thenReturn(role); + // mock 其它方法 + MenuDO menu = randomPojo(MenuDO.class, o -> o.setId(1000L)); + when(menuService.getMenuListByPermissionFromCache(eq("system:user:create"))).thenReturn(singletonList(menu)); + permissionService.setMenuRoleCache(ImmutableMultimap.builder().put(1000L, 100L).build()); + + + // 调用 + boolean has = permissionService.hasAnyPermissions(userId, roles); + // 断言 + assertTrue(has); + } + + @Test + public void testHasAnyRoles_superAdmin() { + // 准备参数 + Long userId = 1L; + String[] roles = new String[]{"yunai", "tudou"}; + // mock 用户与角色的缓存 + permissionService.setUserRoleCache(MapUtil.>builder().put(1L, asSet(100L)).build()); + RoleDO role = randomPojo(RoleDO.class, o -> o.setId(100L) + .setStatus(CommonStatusEnum.ENABLE.getStatus())); + when(roleService.getRoleFromCache(eq(100L))).thenReturn(role); + // mock 其它方法 + when(roleService.hasAnySuperAdmin(eq(asSet(100L)))).thenReturn(true); + + // 调用 + boolean has = permissionService.hasAnyRoles(userId, roles); + // 断言 + assertTrue(has); + } + + @Test + public void testHasAnyRoles_normal() { + // 准备参数 + Long userId = 1L; + String[] roles = new String[]{"yunai", "tudou"}; + // mock 用户与角色的缓存 + permissionService.setUserRoleCache(MapUtil.>builder().put(1L, asSet(100L)).build()); + RoleDO role = randomPojo(RoleDO.class, o -> o.setId(100L).setCode("yunai") + .setStatus(CommonStatusEnum.ENABLE.getStatus())); + when(roleService.getRoleFromCache(eq(100L))).thenReturn(role); + // mock 其它方法 + when(roleService.getRolesFromCache(eq(asSet(100L)))).thenReturn(singletonList(role)); + + // 调用 + boolean has = permissionService.hasAnyRoles(userId, roles); + // 断言 + assertTrue(has); + } @Test public void testGetDeptDataPermission_All() {