From 34b479fe1a629ec40ca33caa4deda890149cdfb7 Mon Sep 17 00:00:00 2001 From: cjw Date: Thu, 11 Jul 2024 13:53:47 +0800 Subject: [PATCH] =?UTF-8?q?=E6=A1=86=E6=9E=B6=E6=96=B0=E5=A2=9E=E7=AC=AC?= =?UTF-8?q?=E4=B8=89=E6=96=B9=E7=99=BB=E5=BD=95=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 +- pom.xml | 54 +++-- ruoyi-admin/Dockerfile | 6 +- ruoyi-admin/pom.xml | 28 +-- .../java/org/dromara/DromaraApplication.java | 1 + .../web/controller/AuthController.java | 84 +++++++- .../dromara/web/service/IAuthStrategy.java | 1 + .../web/service/impl/EmailAuthStrategy.java | 1 + .../service/impl/PasswordAuthStrategy.java | 2 +- .../web/service/impl/SmsAuthStrategy.java | 1 + .../web/service/impl/SocialAuthStrategy.java | 133 ++++++++++++ .../web/service/impl/XcxAuthStrategy.java | 1 + .../src/main/resources/application-dev.yml | 89 ++++++++- .../src/main/resources/application-prod.yml | 11 +- .../src/main/resources/application-test.yml | 77 +++++++ .../src/main/resources/application.yml | 21 +- ruoyi-common/pom.xml | 1 + ruoyi-common/ruoyi-common-bom/pom.xml | 2 +- .../common/core/config/ApplicationConfig.java | 3 +- .../common/core/constant/CacheNames.java | 2 - .../core/domain/event/ProcessEvent.java | 41 ++++ .../core/domain/event/ProcessTaskEvent.java | 40 ++++ .../common/core/enums/BusinessStatusEnum.java | 152 ++++++++++++++ .../common/core/service/DeptService.java | 1 + .../common/core/service/WorkflowService.java | 76 +++++++ .../common/core/utils/SpringUtils.java | 3 +- .../common/core/utils/StreamUtils.java | 29 +++ .../common/doc/handler/OpenApiHandler.java | 3 +- .../common/job/config/SnailJobConfig.java | 2 +- .../dromara/common/log/aspect/LogAspect.java | 2 +- .../common/mybatis/annotation/DataColumn.java | 13 +- .../mybatis/annotation/DataPermission.java | 7 +- .../mybatis/core/domain/BaseEntity.java | 1 - .../mybatis/core/mapper/BaseMapperPlus.java | 189 +++++++++++++++--- .../common/mybatis/core/page/PageQuery.java | 6 +- .../mybatis/core/page/TableDataInfo.java | 10 +- .../common/mybatis/enums/DataBaseType.java | 11 +- .../common/mybatis/enums/DataScopeType.java | 37 +++- .../handler/InjectionMetaObjectHandler.java | 30 ++- .../handler/MybatisExceptionHandler.java | 5 +- .../handler/PlusDataPermissionHandler.java | 55 ++++- .../common/mybatis/helper/DataBaseHelper.java | 5 +- .../mybatis/helper/DataPermissionHelper.java | 22 +- .../PlusDataPermissionInterceptor.java | 70 ++++++- .../src/main/resources/spy.properties | 2 +- .../dromara/common/oss/core/OssClient.java | 22 +- .../common/oss/factory/OssFactory.java | 5 +- .../redis/handler/RedisExceptionHandler.java | 2 +- .../common/redis/utils/QueueUtils.java | 7 +- .../satoken/core/dao/PlusSaTokenDao.java | 9 +- .../common/satoken/utils/LoginHelper.java | 24 ++- .../sms/config/SmsAutoConfiguration.java | 9 + .../sms/handler/SmsExceptionHandler.java | 30 +++ ruoyi-common/ruoyi-common-social/pom.xml | 34 ++++ .../config/SocialAutoConfiguration.java | 23 +++ .../SocialLoginConfigProperties.java | 75 +++++++ .../config/properties/SocialProperties.java | 24 +++ .../social/maxkey/AuthMaxKeyRequest.java | 80 ++++++++ .../social/maxkey/AuthMaxKeySource.java | 52 +++++ .../social/topiam/AuthTopIamRequest.java | 100 +++++++++ .../social/topiam/AuthTopiamSource.java | 51 +++++ .../social/utils/AuthRedisStateCache.java | 61 ++++++ .../common/social/utils/SocialUtils.java | 73 +++++++ ...ot.autoconfigure.AutoConfiguration.imports | 1 + .../common/tenant/config/TenantConfig.java | 2 +- .../common/tenant/helper/TenantHelper.java | 21 +- .../common/web/config/UndertowConfig.java | 6 +- .../websocket/config/WebSocketConfig.java | 7 +- .../constant/WebSocketConstants.java | 1 + .../handler/PlusWebSocketHandler.java | 60 ++++-- .../holder/WebSocketSessionHolder.java | 28 +++ .../interceptor/PlusWebSocketInterceptor.java | 58 ++++-- .../listener/WebSocketTopicListener.java | 9 +- .../websocket/utils/WebSocketUtils.java | 35 +++- ruoyi-extend/ruoyi-monitor-admin/Dockerfile | 6 +- .../src/main/resources/application.yml | 4 +- ruoyi-extend/ruoyi-snailjob-server/Dockerfile | 8 +- .../src/main/resources/application-dev.yml | 4 +- .../src/main/resources/application-prod.yml | 4 +- .../service/GenTableServiceImpl.java | 4 +- .../resources/vm/java/serviceImpl.java.vm | 2 +- ruoyi-modules/ruoyi-system/pom.xml | 17 -- .../controller/system/SysDeptController.java | 4 - .../controller/system/SysOssController.java | 2 - .../system/SysProfileController.java | 11 +- .../system/SysTenantController.java | 7 +- .../controller/system/SysUserController.java | 6 +- .../org/dromara/system/domain/SysPost.java | 3 +- .../org/dromara/system/domain/SysSocial.java | 3 +- .../org/dromara/system/domain/SysTenant.java | 2 +- .../system/domain/SysTenantPackage.java | 2 +- .../dromara/system/domain/bo/OssFileBo.java | 35 ---- .../dromara/system/domain/bo/SysTenantBo.java | 3 +- .../dromara/system/domain/bo/SysUserBo.java | 5 - .../system/domain/bo/SysUserProfileBo.java | 16 +- .../system/domain/vo/SysOssUploadVo.java | 10 +- .../dromara/system/domain/vo/SysOssVo.java | 2 +- .../dromara/system/domain/vo/SysTenantVo.java | 8 +- .../dromara/system/domain/vo/SysUserVo.java | 5 - .../dromara/system/mapper/SysMenuMapper.java | 7 - .../system/service/ISysDeptService.java | 15 -- .../system/service/ISysOssService.java | 23 +-- .../service/impl/SysClientServiceImpl.java | 2 +- .../service/impl/SysConfigServiceImpl.java | 2 +- .../service/impl/SysDataScopeServiceImpl.java | 18 +- .../service/impl/SysDeptServiceImpl.java | 23 +-- .../service/impl/SysDictTypeServiceImpl.java | 2 +- .../impl/SysLogininforServiceImpl.java | 2 +- .../service/impl/SysMenuServiceImpl.java | 12 +- .../service/impl/SysNoticeServiceImpl.java | 2 +- .../service/impl/SysOperLogServiceImpl.java | 2 +- .../service/impl/SysOssConfigServiceImpl.java | 2 +- .../service/impl/SysOssServiceImpl.java | 30 +-- .../impl/SysOssTextbookServiceImpl.java | 11 + .../service/impl/SysPostServiceImpl.java | 2 +- .../service/impl/SysRoleServiceImpl.java | 15 +- .../impl/SysTenantPackageServiceImpl.java | 2 +- .../service/impl/SysTenantServiceImpl.java | 9 +- .../service/impl/SysUserServiceImpl.java | 32 ++- .../resources/mapper/system/SysMenuMapper.xml | 33 +-- .../resources/mapper/system/SysRoleMapper.xml | 4 +- 121 files changed, 2155 insertions(+), 513 deletions(-) create mode 100644 ruoyi-admin/src/main/java/org/dromara/web/service/impl/SocialAuthStrategy.java create mode 100644 ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/event/ProcessEvent.java create mode 100644 ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/event/ProcessTaskEvent.java create mode 100644 ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/enums/BusinessStatusEnum.java create mode 100644 ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/WorkflowService.java create mode 100644 ruoyi-common/ruoyi-common-sms/src/main/java/org/dromara/common/sms/handler/SmsExceptionHandler.java create mode 100644 ruoyi-common/ruoyi-common-social/pom.xml create mode 100644 ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/config/SocialAutoConfiguration.java create mode 100644 ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/config/properties/SocialLoginConfigProperties.java create mode 100644 ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/config/properties/SocialProperties.java create mode 100644 ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/maxkey/AuthMaxKeyRequest.java create mode 100644 ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/maxkey/AuthMaxKeySource.java create mode 100644 ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopIamRequest.java create mode 100644 ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopiamSource.java create mode 100644 ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/utils/AuthRedisStateCache.java create mode 100644 ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/utils/SocialUtils.java create mode 100644 ruoyi-common/ruoyi-common-social/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports delete mode 100644 ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/OssFileBo.java diff --git a/README.md b/README.md index 05dd679..ad9c2ce 100644 --- a/README.md +++ b/README.md @@ -9,8 +9,8 @@ [![License](https://img.shields.io/badge/License-MIT-blue.svg)](https://gitee.com/dromara/RuoYi-Vue-Plus/blob/master/LICENSE) [![使用IntelliJ IDEA开发维护](https://img.shields.io/badge/IntelliJ%20IDEA-提供支持-blue.svg)](https://www.jetbrains.com/?from=RuoYi-Vue-Plus)
-[![RuoYi-Vue-Plus](https://img.shields.io/badge/RuoYi_Vue_Plus-5.2.0-success.svg)](https://gitee.com/dromara/RuoYi-Vue-Plus) -[![Spring Boot](https://img.shields.io/badge/Spring%20Boot-3.1-blue.svg)]() +[![RuoYi-Vue-Plus](https://img.shields.io/badge/RuoYi_Vue_Plus-5.2.1-success.svg)](https://gitee.com/dromara/RuoYi-Vue-Plus) +[![Spring Boot](https://img.shields.io/badge/Spring%20Boot-3.2-blue.svg)]() [![JDK-17](https://img.shields.io/badge/JDK-17-green.svg)]() [![JDK-21](https://img.shields.io/badge/JDK-21-green.svg)]() @@ -56,7 +56,7 @@ CCFlow 驰聘低代码-流程-表单 - https://gitee.com/opencc/RuoYi-JFlow
| 数据加解密 | 采用 注解 + mybatis 拦截器 对存取数据期间自动加解密
支持多种策略 如BASE64、AES、RSA、SM2、SM4等 | 无 | | 接口传输加密 | 采用 动态 AES + RSA 加密请求 body 每一次请求秘钥都不同大幅度降低可破解性 | 无 | | 数据翻译 | 采用 注解 + jackson 序列化期间动态修改数据 数据进行翻译
支持多种模式: `映射翻译` `直接翻译` `其他扩展条件翻译` 接口化两步即可完成自定义扩展 内置多种翻译实现 | 无 | -| 多数据源框架 | 采用 dynamic-datasource 支持世面大部分数据库
通过yml配置即可动态管理异构不同种类的数据库 也可通过前端页面添加数据源
支持spel表达式从请求头参数等条件切换数据源 | 基于 druid 手动编写代码配置数据源 配置繁琐 支持性差 | +| 多数据源框架 | 采用 dynamic-datasource 支持市面大部分数据库
通过yml配置即可动态管理异构不同种类的数据库 也可通过前端页面添加数据源
支持spel表达式从请求头参数等条件切换数据源 | 基于 druid 手动编写代码配置数据源 配置繁琐 支持性差 | | 多数据源事务 | 采用 dynamic-datasource 支持多数据源不同种类的数据库事务回滚 | 不支持 | | 数据库连接池 | 采用 HikariCP Spring官方内置连接池 配置简单 以性能与稳定性闻名天下 | 采用 druid bug众多 社区维护差 活跃度低 配置众多繁琐性能一般 | | 数据库主键 | 采用 雪花ID 基于时间戳的 有序增长 唯一ID 再也不用为分库分表 数据合并主键冲突重复而发愁 | 采用 数据库自增ID 支持数据量有限 不支持多数据源主键唯一 | diff --git a/pom.xml b/pom.xml index ef52a0c..7746f01 100644 --- a/pom.xml +++ b/pom.xml @@ -9,12 +9,11 @@ ${revision} RuoYi-Vue-Plus - https://gitee.com/dromara/RuoYi-Vue-Plus - RuoYi-Vue-Plus多租户管理系统 + 校本资源管理系统 - 5.2.0-BETA - 3.2.5 + 5.2.1 + 3.2.6 UTF-8 UTF-8 17 @@ -25,16 +24,16 @@ 3.3.4 2.3 1.38.0 - 3.5.6 + 3.5.7 3.9.1 5.8.27 4.10.0 3.2.3 - 3.29.0 + 3.31.0 2.2.7 - 4.3.0 + 4.3.1 2.14.4 - 1.0.0-beta1 + 1.0.1 1.3.6 0.2.0 1.18.32 @@ -50,6 +49,8 @@ 3.2.1 1.2.83 + + 7.0.0 3.2.2 @@ -57,7 +58,6 @@ 3.11.0 3.1.2 1.3.0 - @@ -111,6 +111,14 @@ import + + org.flowable + flowable-bom + ${flowable.version} + pom + import + + me.zhyd.oauth @@ -347,27 +355,13 @@ ${revision} - - - - - - - - - - - - - - - - - - - - - + + + org.dromara + ruoyi-workflow + ${revision} + + diff --git a/ruoyi-admin/Dockerfile b/ruoyi-admin/Dockerfile index 609b04a..737cbfc 100644 --- a/ruoyi-admin/Dockerfile +++ b/ruoyi-admin/Dockerfile @@ -1,7 +1,9 @@ +# 贝尔实验室 Spring 官方推荐镜像 JDK下载地址 https://bell-sw.com/pages/downloads/ +FROM bellsoft/liberica-openjdk-debian:17.0.11-cds +#FROM bellsoft/liberica-openjdk-debian:21.0.3-cds #FROM findepi/graalvm:java17-native -FROM openjdk:17.0.2-oraclelinux8 -MAINTAINER Lion Li +LABEL maintainer="Lion Li" RUN mkdir -p /ruoyi/server/logs \ /ruoyi/server/temp \ diff --git a/ruoyi-admin/pom.xml b/ruoyi-admin/pom.xml index 0bc96c3..9924c69 100644 --- a/ruoyi-admin/pom.xml +++ b/ruoyi-admin/pom.xml @@ -23,10 +23,10 @@ mysql-connector-j - - - - + + com.oracle.database.jdbc + ojdbc8 + @@ -43,6 +43,11 @@ ruoyi-common-doc + + org.dromara + ruoyi-common-social + + org.dromara ruoyi-common-ratelimiter @@ -80,21 +85,6 @@ test - - me.zhyd.oauth - JustAuth - - - - - com.aizuda - snail-job-client-starter - - - com.aizuda - snail-job-client-job-core - - diff --git a/ruoyi-admin/src/main/java/org/dromara/DromaraApplication.java b/ruoyi-admin/src/main/java/org/dromara/DromaraApplication.java index 4fb31c0..8ef33fe 100644 --- a/ruoyi-admin/src/main/java/org/dromara/DromaraApplication.java +++ b/ruoyi-admin/src/main/java/org/dromara/DromaraApplication.java @@ -17,6 +17,7 @@ public class DromaraApplication { SpringApplication application = new SpringApplication(DromaraApplication.class); application.setApplicationStartup(new BufferingApplicationStartup(2048)); application.run(args); + System.out.println("(♥◠‿◠)ノ゙ RuoYi-Vue-Plus启动成功 ლ(´ڡ`ლ)゙"); } } diff --git a/ruoyi-admin/src/main/java/org/dromara/web/controller/AuthController.java b/ruoyi-admin/src/main/java/org/dromara/web/controller/AuthController.java index d4dd44d..cc0420a 100644 --- a/ruoyi-admin/src/main/java/org/dromara/web/controller/AuthController.java +++ b/ruoyi-admin/src/main/java/org/dromara/web/controller/AuthController.java @@ -1,19 +1,29 @@ package org.dromara.web.controller; import cn.dev33.satoken.annotation.SaIgnore; +import cn.dev33.satoken.exception.NotLoginException; +import cn.hutool.core.codec.Base64; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import me.zhyd.oauth.model.AuthResponse; +import me.zhyd.oauth.model.AuthUser; +import me.zhyd.oauth.request.AuthRequest; +import me.zhyd.oauth.utils.AuthStateUtils; import org.dromara.common.core.constant.UserConstants; import org.dromara.common.core.domain.R; import org.dromara.common.core.domain.model.LoginBody; import org.dromara.common.core.domain.model.RegisterBody; +import org.dromara.common.core.domain.model.SocialLoginBody; import org.dromara.common.core.utils.*; import org.dromara.common.encrypt.annotation.ApiEncrypt; import org.dromara.common.json.utils.JsonUtils; import org.dromara.common.satoken.utils.LoginHelper; +import org.dromara.common.social.config.properties.SocialLoginConfigProperties; +import org.dromara.common.social.config.properties.SocialProperties; +import org.dromara.common.social.utils.SocialUtils; import org.dromara.common.tenant.helper.TenantHelper; import org.dromara.common.websocket.dto.WebSocketMessageDto; import org.dromara.common.websocket.utils.WebSocketUtils; @@ -34,7 +44,10 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -50,6 +63,7 @@ import java.util.concurrent.TimeUnit; @RequestMapping("/auth") public class AuthController { + private final SocialProperties socialProperties; private final SysLoginService loginService; private final SysRegisterService registerService; private final ISysConfigService configService; @@ -89,13 +103,56 @@ public class AuthController { Long userId = LoginHelper.getUserId(); scheduledExecutorService.schedule(() -> { WebSocketMessageDto dto = new WebSocketMessageDto(); - //dto.setMessage("欢迎登录RuoYi-Vue-Plus后台管理系统"); + dto.setMessage("欢迎登录校本资源平台"); dto.setSessionKeys(List.of(userId)); WebSocketUtils.publishMessage(dto); }, 3, TimeUnit.SECONDS); return R.ok(loginVo); } + /** + * 第三方登录请求 + * + * @param source 登录来源 + * @return 结果 + */ + @GetMapping("/binding/{source}") + public R authBinding(@PathVariable("source") String source, + @RequestParam String tenantId, @RequestParam String domain) { + SocialLoginConfigProperties obj = socialProperties.getType().get(source); + if (ObjectUtil.isNull(obj)) { + return R.fail(source + "平台账号暂不支持"); + } + AuthRequest authRequest = SocialUtils.getAuthRequest(source, socialProperties); + Map map = new HashMap<>(); + map.put("tenantId", tenantId); + map.put("domain", domain); + map.put("state", AuthStateUtils.createState()); + String authorizeUrl = authRequest.authorize(Base64.encode(JsonUtils.toJsonString(map), StandardCharsets.UTF_8)); + return R.ok("操作成功", authorizeUrl); + } + + /** + * 第三方登录回调业务处理 绑定授权 + * + * @param loginBody 请求体 + * @return 结果 + */ + @PostMapping("/social/callback") + public R socialCallback(@RequestBody SocialLoginBody loginBody) { + // 获取第三方登录信息 + AuthResponse response = SocialUtils.loginAuth( + loginBody.getSource(), loginBody.getSocialCode(), + loginBody.getSocialState(), socialProperties); + AuthUser authUserData = response.getData(); + // 判断授权响应是否成功 + if (!response.ok()) { + return R.fail(response.getMsg()); + } + loginService.socialRegister(authUserData); + return R.ok(); + } + /** * 取消授权 @@ -138,8 +195,26 @@ public class AuthController { */ @GetMapping("/tenant/list") public R tenantList(HttpServletRequest request) throws Exception { + // 返回对象 + LoginTenantVo result = new LoginTenantVo(); + boolean enable = TenantHelper.isEnable(); + result.setTenantEnabled(enable); + // 如果未开启租户这直接返回 + if (!enable) { + return R.ok(result); + } + List tenantList = tenantService.queryList(new SysTenantBo()); List voList = MapstructUtils.convert(tenantList, TenantListVo.class); + try { + // 如果只超管返回所有租户 + if (LoginHelper.isSuperAdmin()) { + result.setVoList(voList); + return R.ok(result); + } + } catch (NotLoginException ignored) { + } + // 获取域名 String host; String referer = request.getHeader("referer"); @@ -152,11 +227,8 @@ public class AuthController { // 根据域名进行筛选 List list = StreamUtils.filter(voList, vo -> StringUtils.equals(vo.getDomain(), host)); - // 返回对象 - LoginTenantVo vo = new LoginTenantVo(); - vo.setVoList(CollUtil.isNotEmpty(list) ? list : voList); - vo.setTenantEnabled(TenantHelper.isEnable()); - return R.ok(vo); + result.setVoList(CollUtil.isNotEmpty(list) ? list : voList); + return R.ok(result); } } diff --git a/ruoyi-admin/src/main/java/org/dromara/web/service/IAuthStrategy.java b/ruoyi-admin/src/main/java/org/dromara/web/service/IAuthStrategy.java index a16414f..a75b913 100644 --- a/ruoyi-admin/src/main/java/org/dromara/web/service/IAuthStrategy.java +++ b/ruoyi-admin/src/main/java/org/dromara/web/service/IAuthStrategy.java @@ -3,6 +3,7 @@ package org.dromara.web.service; import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.utils.SpringUtils; +import org.dromara.system.domain.SysClient; import org.dromara.system.domain.vo.SysClientVo; import org.dromara.web.domain.vo.LoginVo; diff --git a/ruoyi-admin/src/main/java/org/dromara/web/service/impl/EmailAuthStrategy.java b/ruoyi-admin/src/main/java/org/dromara/web/service/impl/EmailAuthStrategy.java index 755c9ac..38fdc44 100644 --- a/ruoyi-admin/src/main/java/org/dromara/web/service/impl/EmailAuthStrategy.java +++ b/ruoyi-admin/src/main/java/org/dromara/web/service/impl/EmailAuthStrategy.java @@ -21,6 +21,7 @@ import org.dromara.common.json.utils.JsonUtils; import org.dromara.common.redis.utils.RedisUtils; import org.dromara.common.satoken.utils.LoginHelper; import org.dromara.common.tenant.helper.TenantHelper; +import org.dromara.system.domain.SysClient; import org.dromara.system.domain.SysUser; import org.dromara.system.domain.vo.SysClientVo; import org.dromara.system.domain.vo.SysUserVo; diff --git a/ruoyi-admin/src/main/java/org/dromara/web/service/impl/PasswordAuthStrategy.java b/ruoyi-admin/src/main/java/org/dromara/web/service/impl/PasswordAuthStrategy.java index 7896a4f..5d3ebd7 100644 --- a/ruoyi-admin/src/main/java/org/dromara/web/service/impl/PasswordAuthStrategy.java +++ b/ruoyi-admin/src/main/java/org/dromara/web/service/impl/PasswordAuthStrategy.java @@ -94,7 +94,7 @@ public class PasswordAuthStrategy implements IAuthStrategy { * @param uuid 唯一标识 */ private void validateCaptcha(String tenantId, String username, String code, String uuid) { - String verifyKey = GlobalConstants.CAPTCHA_CODE_KEY + StringUtils.defaultString(uuid, ""); + String verifyKey = GlobalConstants.CAPTCHA_CODE_KEY + StringUtils.blankToDefault(uuid, ""); String captcha = RedisUtils.getCacheObject(verifyKey); RedisUtils.deleteObject(verifyKey); if (captcha == null) { diff --git a/ruoyi-admin/src/main/java/org/dromara/web/service/impl/SmsAuthStrategy.java b/ruoyi-admin/src/main/java/org/dromara/web/service/impl/SmsAuthStrategy.java index fe4ed52..f883632 100644 --- a/ruoyi-admin/src/main/java/org/dromara/web/service/impl/SmsAuthStrategy.java +++ b/ruoyi-admin/src/main/java/org/dromara/web/service/impl/SmsAuthStrategy.java @@ -21,6 +21,7 @@ import org.dromara.common.json.utils.JsonUtils; import org.dromara.common.redis.utils.RedisUtils; import org.dromara.common.satoken.utils.LoginHelper; import org.dromara.common.tenant.helper.TenantHelper; +import org.dromara.system.domain.SysClient; import org.dromara.system.domain.SysUser; import org.dromara.system.domain.vo.SysClientVo; import org.dromara.system.domain.vo.SysUserVo; diff --git a/ruoyi-admin/src/main/java/org/dromara/web/service/impl/SocialAuthStrategy.java b/ruoyi-admin/src/main/java/org/dromara/web/service/impl/SocialAuthStrategy.java new file mode 100644 index 0000000..01db200 --- /dev/null +++ b/ruoyi-admin/src/main/java/org/dromara/web/service/impl/SocialAuthStrategy.java @@ -0,0 +1,133 @@ +package org.dromara.web.service.impl; + +import cn.dev33.satoken.stp.SaLoginModel; +import cn.dev33.satoken.stp.StpUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.map.MapUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.http.HttpUtil; +import cn.hutool.http.Method; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import me.zhyd.oauth.model.AuthResponse; +import me.zhyd.oauth.model.AuthUser; +import org.dromara.common.core.domain.model.LoginUser; +import org.dromara.common.core.domain.model.SocialLoginBody; +import org.dromara.common.core.enums.UserStatus; +import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.exception.user.UserException; +import org.dromara.common.core.utils.StreamUtils; +import org.dromara.common.core.utils.ValidatorUtils; +import org.dromara.common.json.utils.JsonUtils; +import org.dromara.common.satoken.utils.LoginHelper; +import org.dromara.common.social.config.properties.SocialProperties; +import org.dromara.common.social.utils.SocialUtils; +import org.dromara.common.tenant.helper.TenantHelper; +import org.dromara.system.domain.vo.SysClientVo; +import org.dromara.system.domain.vo.SysSocialVo; +import org.dromara.system.domain.vo.SysUserVo; +import org.dromara.system.mapper.SysUserMapper; +import org.dromara.system.service.ISysSocialService; +import org.dromara.web.domain.vo.LoginVo; +import org.dromara.web.service.IAuthStrategy; +import org.dromara.web.service.SysLoginService; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Optional; + +/** + * 第三方授权策略 + * + * @author thiszhc is 三三 + */ +@Slf4j +@Service("social" + IAuthStrategy.BASE_NAME) +@RequiredArgsConstructor +public class SocialAuthStrategy implements IAuthStrategy { + + private final SocialProperties socialProperties; + private final ISysSocialService sysSocialService; + private final SysUserMapper userMapper; + private final SysLoginService loginService; + + /** + * 登录-第三方授权登录 + * + * @param body 登录信息 + * @param client 客户端信息 + */ + @Override + public LoginVo login(String body, SysClientVo client) { + SocialLoginBody loginBody = JsonUtils.parseObject(body, SocialLoginBody.class); + ValidatorUtils.validate(loginBody); + AuthResponse response = SocialUtils.loginAuth( + loginBody.getSource(), loginBody.getSocialCode(), + loginBody.getSocialState(), socialProperties); + if (!response.ok()) { + throw new ServiceException(response.getMsg()); + } + AuthUser authUserData = response.getData(); + if ("GITEE".equals(authUserData.getSource())) { + // 如用户使用 gitee 登录顺手 star 给作者一点支持 拒绝白嫖 + HttpUtil.createRequest(Method.PUT, "https://gitee.com/api/v5/user/starred/dromara/RuoYi-Vue-Plus") + .formStr(MapUtil.of("access_token", authUserData.getToken().getAccessToken())) + .executeAsync(); + HttpUtil.createRequest(Method.PUT, "https://gitee.com/api/v5/user/starred/dromara/RuoYi-Cloud-Plus") + .formStr(MapUtil.of("access_token", authUserData.getToken().getAccessToken())) + .executeAsync(); + } + + List list = sysSocialService.selectByAuthId(authUserData.getSource() + authUserData.getUuid()); + if (CollUtil.isEmpty(list)) { + throw new ServiceException("你还没有绑定第三方账号,绑定后才可以登录!"); + } + SysSocialVo social; + if (TenantHelper.isEnable()) { + Optional opt = StreamUtils.findAny(list, x -> x.getTenantId().equals(loginBody.getTenantId())); + if (opt.isEmpty()) { + throw new ServiceException("对不起,你没有权限登录当前租户!"); + } + social = opt.get(); + } else { + social = list.get(0); + } + // 查找用户 + SysUserVo user = loadUser(social.getTenantId(), social.getUserId()); + + // 此处可根据登录用户的数据不同 自行创建 loginUser 属性不够用继承扩展就行了 + LoginUser loginUser = loginService.buildLoginUser(user); + loginUser.setClientKey(client.getClientKey()); + loginUser.setDeviceType(client.getDeviceType()); + SaLoginModel model = new SaLoginModel(); + model.setDevice(client.getDeviceType()); + // 自定义分配 不同用户体系 不同 token 授权时间 不设置默认走全局 yml 配置 + // 例如: 后台用户30分钟过期 app用户1天过期 + model.setTimeout(client.getTimeout()); + model.setActiveTimeout(client.getActiveTimeout()); + model.setExtra(LoginHelper.CLIENT_KEY, client.getClientId()); + // 生成token + LoginHelper.login(loginUser, model); + + LoginVo loginVo = new LoginVo(); + loginVo.setAccessToken(StpUtil.getTokenValue()); + loginVo.setExpireIn(StpUtil.getTokenTimeout()); + loginVo.setClientId(client.getClientId()); + return loginVo; + } + + private SysUserVo loadUser(String tenantId, Long userId) { + return TenantHelper.dynamic(tenantId, () -> { + SysUserVo user = userMapper.selectVoById(userId); + if (ObjectUtil.isNull(user)) { + log.info("登录用户:{} 不存在.", ""); + throw new UserException("user.not.exists", ""); + } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) { + log.info("登录用户:{} 已被停用.", ""); + throw new UserException("user.blocked", ""); + } + return user; + }); + } + +} diff --git a/ruoyi-admin/src/main/java/org/dromara/web/service/impl/XcxAuthStrategy.java b/ruoyi-admin/src/main/java/org/dromara/web/service/impl/XcxAuthStrategy.java index 42b2fa5..aa8be73 100644 --- a/ruoyi-admin/src/main/java/org/dromara/web/service/impl/XcxAuthStrategy.java +++ b/ruoyi-admin/src/main/java/org/dromara/web/service/impl/XcxAuthStrategy.java @@ -11,6 +11,7 @@ import org.dromara.common.core.enums.UserStatus; import org.dromara.common.core.utils.ValidatorUtils; import org.dromara.common.json.utils.JsonUtils; import org.dromara.common.satoken.utils.LoginHelper; +import org.dromara.system.domain.SysClient; import org.dromara.system.domain.vo.SysClientVo; import org.dromara.system.domain.vo.SysUserVo; import org.dromara.web.domain.vo.LoginVo; diff --git a/ruoyi-admin/src/main/resources/application-dev.yml b/ruoyi-admin/src/main/resources/application-dev.yml index 7736b77..449b705 100644 --- a/ruoyi-admin/src/main/resources/application-dev.yml +++ b/ruoyi-admin/src/main/resources/application-dev.yml @@ -1,7 +1,7 @@ --- # 监控中心配置 spring.boot.admin.client: # 增加客户端开关 - enabled: false + enabled: true url: http://localhost:9090/admin instance: service-host-type: IP @@ -12,15 +12,16 @@ spring.boot.admin.client: snail-job: enabled: false # 需要在 SnailJob 后台组管理创建对应名称的组,然后创建任务的时候选择对应的组,才能正确分派任务 - group-name: "ruoyi_group" + group: "ruoyi_group" # SnailJob 接入验证令牌 详见 script/sql/snail_job.sql `sj_group_config` 表 token: "SJ_cKqBTPzCsWA3VyuCfFoccmuIEGXjr5KT" server: host: 127.0.0.1 - port: 1788 + port: 17888 # 详见 script/sql/snail_job.sql `sj_namespace` 表 namespace: ${spring.profiles.active} - + # 随主应用端口飘逸 + port: 2${server.port} --- # 数据源配置 spring: @@ -95,13 +96,14 @@ spring.data: port: 6379 # 数据库索引 database: 1 - # 密码(如没有密码请注释掉) + # redis 密码必须配置 password: Mz123456* # 连接超时时间 timeout: 10s # 是否开启ssl ssl.enabled: false +# redisson 配置 redisson: # redis key前缀 keyPrefix: @@ -177,3 +179,80 @@ sms: access-key-secret: 您的accessKeySecret signature: 您的短信签名 sdk-app-id: 您的sdkAppId + + +--- # 三方授权 +justauth: + # 前端外网访问地址 + address: http://localhost:80 + type: + maxkey: + # maxkey 服务器地址 + # 注意 如下均配置均不需要修改 maxkey 已经内置好了数据 + server-url: http://sso.maxkey.top + client-id: 876892492581044224 + client-secret: x1Y5MTMwNzIwMjMxNTM4NDc3Mzche8 + redirect-uri: ${justauth.address}/social-callback?source=maxkey + topiam: + # topiam 服务器地址 + server-url: http://127.0.0.1:1989/api/v1/authorize/y0q************spq***********8ol + client-id: 449c4*********937************759 + client-secret: ac7***********1e0************28d + redirect-uri: ${justauth.address}/social-callback?source=topiam + scopes: [openid, email, phone, profile] + qq: + client-id: 10**********6 + client-secret: 1f7d08**********5b7**********29e + redirect-uri: ${justauth.address}/social-callback?source=qq + union-id: false + weibo: + client-id: 10**********6 + client-secret: 1f7d08**********5b7**********29e + redirect-uri: ${justauth.address}/social-callback?source=weibo + gitee: + client-id: 91436b7940090d09c72c7daf85b959cfd5f215d67eea73acbf61b6b590751a98 + client-secret: 02c6fcfd70342980cd8dd2f2c06c1a350645d76c754d7a264c4e125f9ba915ac + redirect-uri: ${justauth.address}/social-callback?source=gitee + dingtalk: + client-id: 10**********6 + client-secret: 1f7d08**********5b7**********29e + redirect-uri: ${justauth.address}/social-callback?source=dingtalk + baidu: + client-id: 10**********6 + client-secret: 1f7d08**********5b7**********29e + redirect-uri: ${justauth.address}/social-callback?source=baidu + csdn: + client-id: 10**********6 + client-secret: 1f7d08**********5b7**********29e + redirect-uri: ${justauth.address}/social-callback?source=csdn + coding: + client-id: 10**********6 + client-secret: 1f7d08**********5b7**********29e + redirect-uri: ${justauth.address}/social-callback?source=coding + coding-group-name: xx + oschina: + client-id: 10**********6 + client-secret: 1f7d08**********5b7**********29e + redirect-uri: ${justauth.address}/social-callback?source=oschina + alipay_wallet: + client-id: 10**********6 + client-secret: 1f7d08**********5b7**********29e + redirect-uri: ${justauth.address}/social-callback?source=alipay_wallet + alipay-public-key: MIIB**************DAQAB + wechat_open: + client-id: 10**********6 + client-secret: 1f7d08**********5b7**********29e + redirect-uri: ${justauth.address}/social-callback?source=wechat_open + wechat_mp: + client-id: 10**********6 + client-secret: 1f7d08**********5b7**********29e + redirect-uri: ${justauth.address}/social-callback?source=wechat_mp + wechat_enterprise: + client-id: 10**********6 + client-secret: 1f7d08**********5b7**********29e + redirect-uri: ${justauth.address}/social-callback?source=wechat_enterprise + agent-id: 1000002 + gitlab: + client-id: 10**********6 + client-secret: 1f7d08**********5b7**********29e + redirect-uri: ${justauth.address}/social-callback?source=gitlab diff --git a/ruoyi-admin/src/main/resources/application-prod.yml b/ruoyi-admin/src/main/resources/application-prod.yml index 14b8097..ae23f03 100644 --- a/ruoyi-admin/src/main/resources/application-prod.yml +++ b/ruoyi-admin/src/main/resources/application-prod.yml @@ -15,14 +15,16 @@ spring.boot.admin.client: snail-job: enabled: false # 需要在 SnailJob 后台组管理创建对应名称的组,然后创建任务的时候选择对应的组,才能正确分派任务 - group-name: "ruoyi_group" + group: "ruoyi_group" # SnailJob 接入验证令牌 详见 script/sql/snail_job.sql `sj_group_config` 表 token: "SJ_cKqBTPzCsWA3VyuCfFoccmuIEGXjr5KT" server: host: 127.0.0.1 - port: 1788 + port: 17888 # 详见 script/sql/snail_job.sql `sj_namespace` 表 namespace: ${spring.profiles.active} + # 随主应用端口飘逸 + port: 2${server.port} --- # 数据源配置 spring: @@ -97,13 +99,14 @@ spring.data: port: 6379 # 数据库索引 database: 0 - # 密码(如没有密码请注释掉) - # password: + # redis 密码必须配置 + password: ruoyi123 # 连接超时时间 timeout: 10s # 是否开启ssl ssl.enabled: false +# redisson 配置 redisson: # redis key前缀 keyPrefix: diff --git a/ruoyi-admin/src/main/resources/application-test.yml b/ruoyi-admin/src/main/resources/application-test.yml index 450bb2d..15c4716 100644 --- a/ruoyi-admin/src/main/resources/application-test.yml +++ b/ruoyi-admin/src/main/resources/application-test.yml @@ -177,3 +177,80 @@ sms: access-key-secret: 您的accessKeySecret signature: 您的短信签名 sdk-app-id: 您的sdkAppId + + +--- # 三方授权 +justauth: + # 前端外网访问地址 + address: http://localhost:80 + type: + maxkey: + # maxkey 服务器地址 + # 注意 如下均配置均不需要修改 maxkey 已经内置好了数据 + server-url: http://sso.maxkey.top + client-id: 876892492581044224 + client-secret: x1Y5MTMwNzIwMjMxNTM4NDc3Mzche8 + redirect-uri: ${justauth.address}/social-callback?source=maxkey + topiam: + # topiam 服务器地址 + server-url: http://127.0.0.1:1989/api/v1/authorize/y0q************spq***********8ol + client-id: 449c4*********937************759 + client-secret: ac7***********1e0************28d + redirect-uri: ${justauth.address}/social-callback?source=topiam + scopes: [openid, email, phone, profile] + qq: + client-id: 10**********6 + client-secret: 1f7d08**********5b7**********29e + redirect-uri: ${justauth.address}/social-callback?source=qq + union-id: false + weibo: + client-id: 10**********6 + client-secret: 1f7d08**********5b7**********29e + redirect-uri: ${justauth.address}/social-callback?source=weibo + gitee: + client-id: 91436b7940090d09c72c7daf85b959cfd5f215d67eea73acbf61b6b590751a98 + client-secret: 02c6fcfd70342980cd8dd2f2c06c1a350645d76c754d7a264c4e125f9ba915ac + redirect-uri: ${justauth.address}/social-callback?source=gitee + dingtalk: + client-id: 10**********6 + client-secret: 1f7d08**********5b7**********29e + redirect-uri: ${justauth.address}/social-callback?source=dingtalk + baidu: + client-id: 10**********6 + client-secret: 1f7d08**********5b7**********29e + redirect-uri: ${justauth.address}/social-callback?source=baidu + csdn: + client-id: 10**********6 + client-secret: 1f7d08**********5b7**********29e + redirect-uri: ${justauth.address}/social-callback?source=csdn + coding: + client-id: 10**********6 + client-secret: 1f7d08**********5b7**********29e + redirect-uri: ${justauth.address}/social-callback?source=coding + coding-group-name: xx + oschina: + client-id: 10**********6 + client-secret: 1f7d08**********5b7**********29e + redirect-uri: ${justauth.address}/social-callback?source=oschina + alipay_wallet: + client-id: 10**********6 + client-secret: 1f7d08**********5b7**********29e + redirect-uri: ${justauth.address}/social-callback?source=alipay_wallet + alipay-public-key: MIIB**************DAQAB + wechat_open: + client-id: 10**********6 + client-secret: 1f7d08**********5b7**********29e + redirect-uri: ${justauth.address}/social-callback?source=wechat_open + wechat_mp: + client-id: 10**********6 + client-secret: 1f7d08**********5b7**********29e + redirect-uri: ${justauth.address}/social-callback?source=wechat_mp + wechat_enterprise: + client-id: 10**********6 + client-secret: 1f7d08**********5b7**********29e + redirect-uri: ${justauth.address}/social-callback?source=wechat_enterprise + agent-id: 1000002 + gitlab: + client-id: 10**********6 + client-secret: 1f7d08**********5b7**********29e + redirect-uri: ${justauth.address}/social-callback?source=gitlab diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml index 98c10d3..92d22c9 100644 --- a/ruoyi-admin/src/main/resources/application.yml +++ b/ruoyi-admin/src/main/resources/application.yml @@ -75,9 +75,9 @@ spring: servlet: multipart: # 单个文件大小 - max-file-size: 1024MB + max-file-size: 10MB # 设置总上传的文件大小 - max-request-size: 1024MB + max-request-size: 20MB mvc: # 设置静态资源路径 防止所有请求都去查静态资源 static-path-pattern: /static/** @@ -269,3 +269,20 @@ websocket: # 设置访问源地址 allowedOrigins: '*' +#--- #flowable配置 +#flowable: +# async-executor-activate: false #关闭定时任务JOB +# # 将databaseSchemaUpdate设置为true。当Flowable发现库与数据库表结构不一致时,会自动将数据库表结构升级至新版本。 +# database-schema-update: true +# activity-font-name: 宋体 +# label-font-name: 宋体 +# annotation-font-name: 宋体 +# # 关闭各个模块生成表,目前只使用工作流基础表 +# idm: +# enabled: false +# cmmn: +# enabled: false +# dmn: +# enabled: false +# app: +# enabled: false diff --git a/ruoyi-common/pom.xml b/ruoyi-common/pom.xml index 0428aea..45493d3 100644 --- a/ruoyi-common/pom.xml +++ b/ruoyi-common/pom.xml @@ -11,6 +11,7 @@ ruoyi-common-bom + ruoyi-common-social ruoyi-common-core ruoyi-common-doc ruoyi-common-excel diff --git a/ruoyi-common/ruoyi-common-bom/pom.xml b/ruoyi-common/ruoyi-common-bom/pom.xml index f9af9de..5388d8c 100644 --- a/ruoyi-common/ruoyi-common-bom/pom.xml +++ b/ruoyi-common/ruoyi-common-bom/pom.xml @@ -14,7 +14,7 @@ - 5.2.0-BETA + 5.2.1 diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/config/ApplicationConfig.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/config/ApplicationConfig.java index d120087..d9f70e4 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/config/ApplicationConfig.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/config/ApplicationConfig.java @@ -10,8 +10,7 @@ import org.springframework.scheduling.annotation.EnableAsync; * @author Lion Li */ @AutoConfiguration -// 表示通过aop框架暴露该代理对象,AopContext能够访问 -@EnableAspectJAutoProxy(exposeProxy = true) +@EnableAspectJAutoProxy @EnableAsync(proxyTargetClass = true) public class ApplicationConfig { diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/CacheNames.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/CacheNames.java index cf30aae..d9c2de4 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/CacheNames.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/CacheNames.java @@ -64,7 +64,6 @@ public interface CacheNames { * OSS内容 */ String SYS_OSS = "sys_oss#30d"; - String SYS_OSS_IDENTIFIER = "sys_oss_identifier#30d"; /** * OSS配置 @@ -79,5 +78,4 @@ public interface CacheNames { String SYS_CATALOG_TEXTBOOK = "sys_catalog_textbook#30d"; String SYS_CATALOG_RESOURCE = "sys_catalog_resource#30d"; String SYS_CATALOG_PERSON = "sys_catalog_person#30d"; - } diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/event/ProcessEvent.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/event/ProcessEvent.java new file mode 100644 index 0000000..61c7efc --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/event/ProcessEvent.java @@ -0,0 +1,41 @@ +package org.dromara.common.core.domain.event; + +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; + +/** + * 总体流程监听 + * + * @author may + */ + +@Data +public class ProcessEvent implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 流程定义key + */ + private String key; + + /** + * 业务id + */ + private String businessKey; + + /** + * 状态 + */ + private String status; + + /** + * 当为true时为申请人节点办理 + */ + private boolean submit; + + +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/event/ProcessTaskEvent.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/event/ProcessTaskEvent.java new file mode 100644 index 0000000..019ca82 --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/event/ProcessTaskEvent.java @@ -0,0 +1,40 @@ +package org.dromara.common.core.domain.event; + +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; + +/** + * 流程办理监听 + * + * @author may + */ + +@Data +public class ProcessTaskEvent implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 流程定义key + */ + private String key; + + /** + * 审批节点key + */ + private String taskDefinitionKey; + + /** + * 任务id + */ + private String taskId; + + /** + * 业务id + */ + private String businessKey; + +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/enums/BusinessStatusEnum.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/enums/BusinessStatusEnum.java new file mode 100644 index 0000000..0af943a --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/enums/BusinessStatusEnum.java @@ -0,0 +1,152 @@ +package org.dromara.common.core.enums; + +import cn.hutool.core.util.StrUtil; +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.utils.StringUtils; + +import java.util.Arrays; + +/** + * 业务状态枚举 + * + * @author may + */ +@Getter +@AllArgsConstructor +public enum BusinessStatusEnum { + /** + * 已撤销 + */ + CANCEL("cancel", "已撤销"), + /** + * 草稿 + */ + DRAFT("draft", "草稿"), + /** + * 待审核 + */ + WAITING("waiting", "待审核"), + /** + * 已完成 + */ + FINISH("finish", "已完成"), + /** + * 已作废 + */ + INVALID("invalid", "已作废"), + /** + * 已退回 + */ + BACK("back", "已退回"), + /** + * 已终止 + */ + TERMINATION("termination", "已终止"); + + /** + * 状态 + */ + private final String status; + + /** + * 描述 + */ + private final String desc; + + /** + * 获取业务状态 + * + * @param status 状态 + */ + public static String findByStatus(String status) { + if (StringUtils.isBlank(status)) { + return StrUtil.EMPTY; + } + return Arrays.stream(BusinessStatusEnum.values()) + .filter(statusEnum -> statusEnum.getStatus().equals(status)) + .findFirst() + .map(BusinessStatusEnum::getDesc) + .orElse(StrUtil.EMPTY); + } + + /** + * 启动流程校验 + * + * @param status 状态 + */ + public static void checkStartStatus(String status) { + if (WAITING.getStatus().equals(status)) { + throw new ServiceException("该单据已提交过申请,正在审批中!"); + } else if (FINISH.getStatus().equals(status)) { + throw new ServiceException("该单据已完成申请!"); + } else if (INVALID.getStatus().equals(status)) { + throw new ServiceException("该单据已作废!"); + } else if (TERMINATION.getStatus().equals(status)) { + throw new ServiceException("该单据已终止!"); + } else if (StringUtils.isBlank(status)) { + throw new ServiceException("流程状态为空!"); + } + } + + /** + * 撤销流程校验 + * + * @param status 状态 + */ + public static void checkCancelStatus(String status) { + if (CANCEL.getStatus().equals(status)) { + throw new ServiceException("该单据已撤销!"); + } else if (FINISH.getStatus().equals(status)) { + throw new ServiceException("该单据已完成申请!"); + } else if (INVALID.getStatus().equals(status)) { + throw new ServiceException("该单据已作废!"); + } else if (TERMINATION.getStatus().equals(status)) { + throw new ServiceException("该单据已终止!"); + } else if (BACK.getStatus().equals(status)) { + throw new ServiceException("该单据已退回!"); + } else if (StringUtils.isBlank(status)) { + throw new ServiceException("流程状态为空!"); + } + } + + /** + * 驳回流程校验 + * + * @param status 状态 + */ + public static void checkBackStatus(String status) { + if (BACK.getStatus().equals(status)) { + throw new ServiceException("该单据已退回!"); + } else if (FINISH.getStatus().equals(status)) { + throw new ServiceException("该单据已完成申请!"); + } else if (INVALID.getStatus().equals(status)) { + throw new ServiceException("该单据已作废!"); + } else if (TERMINATION.getStatus().equals(status)) { + throw new ServiceException("该单据已终止!"); + } else if (CANCEL.getStatus().equals(status)) { + throw new ServiceException("该单据已撤销!"); + } else if (StringUtils.isBlank(status)) { + throw new ServiceException("流程状态为空!"); + } + } + + /** + * 作废,终止流程校验 + * + * @param status 状态 + */ + public static void checkInvalidStatus(String status) { + if (FINISH.getStatus().equals(status)) { + throw new ServiceException("该单据已完成申请!"); + } else if (INVALID.getStatus().equals(status)) { + throw new ServiceException("该单据已作废!"); + } else if (TERMINATION.getStatus().equals(status)) { + throw new ServiceException("该单据已终止!"); + } else if (StringUtils.isBlank(status)) { + throw new ServiceException("流程状态为空!"); + } + } +} + diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/DeptService.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/DeptService.java index 2531b52..c0886db 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/DeptService.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/DeptService.java @@ -14,6 +14,7 @@ public interface DeptService { * @return 部门名称串逗号分隔 */ String selectDeptNameByIds(String deptIds); + /** * 通过部门名称查询租户部门Id * diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/WorkflowService.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/WorkflowService.java new file mode 100644 index 0000000..4e556c9 --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/WorkflowService.java @@ -0,0 +1,76 @@ +package org.dromara.common.core.service; + +import java.util.List; +import java.util.Map; + +/** + * 通用 工作流服务 + * + * @author may + */ +public interface WorkflowService { + + /** + * 运行中的实例 删除程实例,删除历史记录,删除业务与流程关联信息 + * + * @param businessKeys 业务id + * @return 结果 + */ + boolean deleteRunAndHisInstance(List businessKeys); + + /** + * 获取当前流程状态 + * + * @param taskId 任务id + */ + String getBusinessStatusByTaskId(String taskId); + + /** + * 获取当前流程状态 + * + * @param businessKey 业务id + */ + String getBusinessStatus(String businessKey); + + /** + * 设置流程变量(全局变量) + * + * @param taskId 任务id + * @param variableName 变量名称 + * @param value 变量值 + */ + void setVariable(String taskId, String variableName, Object value); + + /** + * 设置流程变量(全局变量) + * + * @param taskId 任务id + * @param variables 流程变量 + */ + void setVariables(String taskId, Map variables); + + /** + * 设置流程变量(本地变量,非全局变量) + * + * @param taskId 任务id + * @param variableName 变量名称 + * @param value 变量值 + */ + void setVariableLocal(String taskId, String variableName, Object value); + + /** + * 设置流程变量(本地变量,非全局变量) + * + * @param taskId 任务id + * @param variables 流程变量 + */ + void setVariablesLocal(String taskId, Map variables); + + /** + * 按照业务id查询流程实例id + * + * @param businessKey 业务id + * @return 结果 + */ + String getInstanceIdByBusinessKey(String businessKey); +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/SpringUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/SpringUtils.java index e58c394..169c6e2 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/SpringUtils.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/SpringUtils.java @@ -1,7 +1,6 @@ package org.dromara.common.core.utils; import cn.hutool.extra.spring.SpringUtil; -import org.springframework.aop.framework.AopContext; import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.boot.autoconfigure.thread.Threading; import org.springframework.context.ApplicationContext; @@ -50,7 +49,7 @@ public final class SpringUtils extends SpringUtil { */ @SuppressWarnings("unchecked") public static T getAopProxy(T invoker) { - return (T) AopContext.currentProxy(); + return (T) getBean(invoker.getClass()); } diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/StreamUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/StreamUtils.java index 967612e..1342deb 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/StreamUtils.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/StreamUtils.java @@ -7,6 +7,7 @@ import lombok.NoArgsConstructor; import java.util.*; import java.util.function.BiFunction; +import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Collectors; @@ -34,6 +35,34 @@ public class StreamUtils { return collection.stream().filter(function).collect(Collectors.toList()); } + /** + * 找到流中满足条件的第一个元素 + * + * @param collection 需要查询的集合 + * @param function 过滤方法 + * @return 找到符合条件的第一个元素,没有则返回null + */ + public static E findFirst(Collection collection, Predicate function) { + if (CollUtil.isEmpty(collection)) { + return null; + } + return collection.stream().filter(function).findFirst().orElse(null); + } + + /** + * 找到流中任意一个满足条件的元素 + * + * @param collection 需要查询的集合 + * @param function 过滤方法 + * @return 找到符合条件的任意一个元素,没有则返回null + */ + public static Optional findAny(Collection collection, Predicate function) { + if (CollUtil.isEmpty(collection)) { + return Optional.empty(); + } + return collection.stream().filter(function).findAny(); + } + /** * 将collection拼接 * diff --git a/ruoyi-common/ruoyi-common-doc/src/main/java/org/dromara/common/doc/handler/OpenApiHandler.java b/ruoyi-common/ruoyi-common-doc/src/main/java/org/dromara/common/doc/handler/OpenApiHandler.java index a35cc64..56b7369 100644 --- a/ruoyi-common/ruoyi-common-doc/src/main/java/org/dromara/common/doc/handler/OpenApiHandler.java +++ b/ruoyi-common/ruoyi-common-doc/src/main/java/org/dromara/common/doc/handler/OpenApiHandler.java @@ -11,6 +11,7 @@ import io.swagger.v3.oas.models.Paths; import io.swagger.v3.oas.models.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.dromara.common.core.utils.StreamUtils; import org.springdoc.core.customizers.OpenApiBuilderCustomizer; import org.springdoc.core.customizers.ServerBaseUrlCustomizer; import org.springdoc.core.properties.SpringDocConfigProperties; @@ -230,7 +231,7 @@ public class OpenApiHandler extends OpenAPIService { .flatMap(x -> Stream.of(x.value())).collect(Collectors.toSet()); methodTags.addAll(AnnotatedElementUtils.findAllMergedAnnotations(method, io.swagger.v3.oas.annotations.tags.Tag.class)); if (!CollectionUtils.isEmpty(methodTags)) { - tagsStr.addAll(methodTags.stream().map(tag -> propertyResolverUtils.resolve(tag.name(), locale)).collect(Collectors.toSet())); + tagsStr.addAll(StreamUtils.toSet(methodTags, tag -> propertyResolverUtils.resolve(tag.name(), locale))); List allTags = new ArrayList<>(methodTags); addTags(allTags, tags, locale); } diff --git a/ruoyi-common/ruoyi-common-job/src/main/java/org/dromara/common/job/config/SnailJobConfig.java b/ruoyi-common/ruoyi-common-job/src/main/java/org/dromara/common/job/config/SnailJobConfig.java index d671f0e..cba3753 100644 --- a/ruoyi-common/ruoyi-common-job/src/main/java/org/dromara/common/job/config/SnailJobConfig.java +++ b/ruoyi-common/ruoyi-common-job/src/main/java/org/dromara/common/job/config/SnailJobConfig.java @@ -21,7 +21,7 @@ import org.springframework.scheduling.annotation.EnableScheduling; @AutoConfiguration @ConditionalOnProperty(prefix = "snail-job", name = "enabled", havingValue = "true") @EnableScheduling -@EnableSnailJob(group = "${snail-job.group-name}") +@EnableSnailJob public class SnailJobConfig { @EventListener(SnailClientStartingEvent.class) diff --git a/ruoyi-common/ruoyi-common-log/src/main/java/org/dromara/common/log/aspect/LogAspect.java b/ruoyi-common/ruoyi-common-log/src/main/java/org/dromara/common/log/aspect/LogAspect.java index 8724072..cdbd00f 100644 --- a/ruoyi-common/ruoyi-common-log/src/main/java/org/dromara/common/log/aspect/LogAspect.java +++ b/ruoyi-common/ruoyi-common-log/src/main/java/org/dromara/common/log/aspect/LogAspect.java @@ -56,7 +56,7 @@ public class LogAspect { * 处理请求前执行 */ @Before(value = "@annotation(controllerLog)") - public void boBefore(JoinPoint joinPoint, Log controllerLog) { + public void doBefore(JoinPoint joinPoint, Log controllerLog) { StopWatch stopWatch = new StopWatch(); KEY_CACHE.set(stopWatch); stopWatch.start(); diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/annotation/DataColumn.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/annotation/DataColumn.java index aca470f..f8c5cd0 100644 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/annotation/DataColumn.java +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/annotation/DataColumn.java @@ -3,9 +3,10 @@ package org.dromara.common.mybatis.annotation; import java.lang.annotation.*; /** - * 数据权限 - * + * 数据权限注解,用于标记数据权限的占位符关键字和替换值 + *

* 一个注解只能对应一个模板 + *

* * @author Lion Li * @version 3.5.0 @@ -16,12 +17,16 @@ import java.lang.annotation.*; public @interface DataColumn { /** - * 占位符关键字 + * 数据权限模板的占位符关键字,默认为 "deptName" + * + * @return 占位符关键字数组 */ String[] key() default "deptName"; /** - * 占位符替换值 + * 数据权限模板的占位符替换值,默认为 "dept_id" + * + * @return 占位符替换值数组 */ String[] value() default "dept_id"; diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/annotation/DataPermission.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/annotation/DataPermission.java index f4351e3..6fd3c3e 100644 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/annotation/DataPermission.java +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/annotation/DataPermission.java @@ -3,7 +3,7 @@ package org.dromara.common.mybatis.annotation; import java.lang.annotation.*; /** - * 数据权限组 + * 数据权限组注解,用于标记数据权限配置数组 * * @author Lion Li * @version 3.5.0 @@ -13,6 +13,11 @@ import java.lang.annotation.*; @Documented public @interface DataPermission { + /** + * 数据权限配置数组,用于指定数据权限的占位符关键字和替换值 + * + * @return 数据权限配置数组 + */ DataColumn[] value(); } diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/core/domain/BaseEntity.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/core/domain/BaseEntity.java index 820b49a..13a7941 100644 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/core/domain/BaseEntity.java +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/core/domain/BaseEntity.java @@ -17,7 +17,6 @@ import java.util.Map; * * @author Lion Li */ - @Data public class BaseEntity implements Serializable { diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/core/mapper/BaseMapperPlus.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/core/mapper/BaseMapperPlus.java index 08723f6..956be9f 100644 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/core/mapper/BaseMapperPlus.java +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/core/mapper/BaseMapperPlus.java @@ -12,6 +12,7 @@ import com.baomidou.mybatisplus.extension.toolkit.Db; import org.apache.ibatis.logging.Log; import org.apache.ibatis.logging.LogFactory; import org.dromara.common.core.utils.MapstructUtils; +import org.dromara.common.core.utils.StreamUtils; import java.io.Serializable; import java.util.Collection; @@ -34,73 +35,125 @@ public interface BaseMapperPlus extends BaseMapper { Log log = LogFactory.getLog(BaseMapperPlus.class); + /** + * 获取当前实例对象关联的泛型类型 V 的 Class 对象 + * + * @return 返回当前实例对象关联的泛型类型 V 的 Class 对象 + */ default Class currentVoClass() { return (Class) GenericTypeUtils.resolveTypeArguments(this.getClass(), BaseMapperPlus.class)[1]; } + /** + * 获取当前实例对象关联的泛型类型 T 的 Class 对象 + * + * @return 返回当前实例对象关联的泛型类型 T 的 Class 对象 + */ default Class currentModelClass() { return (Class) GenericTypeUtils.resolveTypeArguments(this.getClass(), BaseMapperPlus.class)[0]; } + /** + * 使用默认的查询条件查询并返回结果列表 + * + * @return 返回查询结果的列表 + */ default List selectList() { return this.selectList(new QueryWrapper<>()); } /** - * 批量插入 + * 批量插入实体对象集合 + * + * @param entityList 实体对象集合 + * @return 插入操作是否成功的布尔值 */ default boolean insertBatch(Collection entityList) { - return Db.saveBatch(entityList); + Db.saveBatch(entityList); + // 临时解决 新版本 mp 插入状态判断错误问题 + return true; } /** - * 批量更新 + * 批量根据ID更新实体对象集合 + * + * @param entityList 实体对象集合 + * @return 更新操作是否成功的布尔值 */ default boolean updateBatchById(Collection entityList) { - return Db.updateBatchById(entityList); + Db.updateBatchById(entityList); + // 临时解决 新版本 mp 插入状态判断错误问题 + return true; } /** - * 批量插入或更新 + * 批量插入或更新实体对象集合 + * + * @param entityList 实体对象集合 + * @return 插入或更新操作是否成功的布尔值 */ default boolean insertOrUpdateBatch(Collection entityList) { - return Db.saveOrUpdateBatch(entityList); + Db.saveOrUpdateBatch(entityList); + // 临时解决 新版本 mp 插入状态判断错误问题 + return true; } /** - * 批量插入(包含限制条数) + * 批量插入实体对象集合并指定批处理大小 + * + * @param entityList 实体对象集合 + * @param batchSize 批处理大小 + * @return 插入操作是否成功的布尔值 */ default boolean insertBatch(Collection entityList, int batchSize) { - return Db.saveBatch(entityList, batchSize); + Db.saveBatch(entityList, batchSize); + // 临时解决 新版本 mp 插入状态判断错误问题 + return true; } /** - * 批量更新(包含限制条数) + * 批量根据ID更新实体对象集合并指定批处理大小 + * + * @param entityList 实体对象集合 + * @param batchSize 批处理大小 + * @return 更新操作是否成功的布尔值 */ default boolean updateBatchById(Collection entityList, int batchSize) { - return Db.updateBatchById(entityList, batchSize); + Db.updateBatchById(entityList, batchSize); + // 临时解决 新版本 mp 插入状态判断错误问题 + return true; } /** - * 批量插入或更新(包含限制条数) + * 批量插入或更新实体对象集合并指定批处理大小 + * + * @param entityList 实体对象集合 + * @param batchSize 批处理大小 + * @return 插入或更新操作是否成功的布尔值 */ default boolean insertOrUpdateBatch(Collection entityList, int batchSize) { - return Db.saveOrUpdateBatch(entityList, batchSize); + Db.saveOrUpdateBatch(entityList, batchSize); + // 临时解决 新版本 mp 插入状态判断错误问题 + return true; } /** - * 插入或更新(包含限制条数) + * 根据ID查询单个VO对象 + * + * @param id 主键ID + * @return 查询到的单个VO对象 */ - default boolean insertOrUpdate(T entity) { - return Db.saveOrUpdate(entity); - } - default V selectVoById(Serializable id) { return selectVoById(id, this.currentVoClass()); } /** - * 根据 ID 查询 + * 根据ID查询单个VO对象并将其转换为指定的VO类 + * + * @param id 主键ID + * @param voClass 要转换的VO类的Class对象 + * @param VO类的类型 + * @return 查询到的单个VO对象,经过转换为指定的VO类后返回 */ default C selectVoById(Serializable id, Class voClass) { T obj = this.selectById(id); @@ -110,12 +163,23 @@ public interface BaseMapperPlus extends BaseMapper { return MapstructUtils.convert(obj, voClass); } + /** + * 根据ID集合批量查询VO对象列表 + * + * @param idList 主键ID集合 + * @return 查询到的VO对象列表 + */ default List selectVoBatchIds(Collection idList) { return selectVoBatchIds(idList, this.currentVoClass()); } /** - * 查询(根据ID 批量查询) + * 根据ID集合批量查询实体对象列表,并将其转换为指定的VO对象列表 + * + * @param idList 主键ID集合 + * @param voClass 要转换的VO类的Class对象 + * @param VO类的类型 + * @return 查询到的VO对象列表,经过转换为指定的VO类后返回 */ default List selectVoBatchIds(Collection idList, Class voClass) { List list = this.selectBatchIds(idList); @@ -125,12 +189,23 @@ public interface BaseMapperPlus extends BaseMapper { return MapstructUtils.convert(list, voClass); } + /** + * 根据查询条件Map查询VO对象列表 + * + * @param map 查询条件Map + * @return 查询到的VO对象列表 + */ default List selectVoByMap(Map map) { return selectVoByMap(map, this.currentVoClass()); } /** - * 查询(根据 columnMap 条件) + * 根据查询条件Map查询实体对象列表,并将其转换为指定的VO对象列表 + * + * @param map 查询条件Map + * @param voClass 要转换的VO类的Class对象 + * @param VO类的类型 + * @return 查询到的VO对象列表,经过转换为指定的VO类后返回 */ default List selectVoByMap(Map map, Class voClass) { List list = this.selectByMap(map); @@ -140,23 +215,47 @@ public interface BaseMapperPlus extends BaseMapper { return MapstructUtils.convert(list, voClass); } + /** + * 根据条件查询单个VO对象 + * + * @param wrapper 查询条件Wrapper + * @return 查询到的单个VO对象 + */ default V selectVoOne(Wrapper wrapper) { return selectVoOne(wrapper, this.currentVoClass()); } + /** + * 根据条件查询单个VO对象,并根据需要决定是否抛出异常 + * + * @param wrapper 查询条件Wrapper + * @param throwEx 是否抛出异常的标志 + * @return 查询到的单个VO对象 + */ default V selectVoOne(Wrapper wrapper, boolean throwEx) { return selectVoOne(wrapper, this.currentVoClass(), throwEx); } /** - * 根据 entity 条件,查询一条记录 + * 根据条件查询单个VO对象,并指定返回的VO对象的类型 + * + * @param wrapper 查询条件Wrapper + * @param voClass 返回的VO对象的Class对象 + * @param 返回的VO对象的类型 + * @return 查询到的单个VO对象,经过类型转换为指定的VO类后返回 */ default C selectVoOne(Wrapper wrapper, Class voClass) { return selectVoOne(wrapper, voClass, true); } /** - * 根据 entity 条件,查询一条记录 + * 根据条件查询单个实体对象,并将其转换为指定的VO对象 + * + * @param wrapper 查询条件Wrapper + * @param voClass 要转换的VO类的Class对象 + * @param throwEx 是否抛出异常的标志 + * @param VO类的类型 + * @return 查询到的单个VO对象,经过转换为指定的VO类后返回 */ default C selectVoOne(Wrapper wrapper, Class voClass, boolean throwEx) { T obj = this.selectOne(wrapper, throwEx); @@ -166,16 +265,32 @@ public interface BaseMapperPlus extends BaseMapper { return MapstructUtils.convert(obj, voClass); } + /** + * 查询所有VO对象列表 + * + * @return 查询到的VO对象列表 + */ default List selectVoList() { return selectVoList(new QueryWrapper<>(), this.currentVoClass()); } + /** + * 根据条件查询VO对象列表 + * + * @param wrapper 查询条件Wrapper + * @return 查询到的VO对象列表 + */ default List selectVoList(Wrapper wrapper) { return selectVoList(wrapper, this.currentVoClass()); } /** - * 根据 entity 条件,查询全部记录 + * 根据条件查询实体对象列表,并将其转换为指定的VO对象列表 + * + * @param wrapper 查询条件Wrapper + * @param voClass 要转换的VO类的Class对象 + * @param VO类的类型 + * @return 查询到的VO对象列表,经过转换为指定的VO类后返回 */ default List selectVoList(Wrapper wrapper, Class voClass) { List list = this.selectList(wrapper); @@ -185,15 +300,31 @@ public interface BaseMapperPlus extends BaseMapper { return MapstructUtils.convert(list, voClass); } + /** + * 根据条件分页查询VO对象列表 + * + * @param page 分页信息 + * @param wrapper 查询条件Wrapper + * @return 查询到的VO对象分页列表 + */ default

> P selectVoPage(IPage page, Wrapper wrapper) { return selectVoPage(page, wrapper, this.currentVoClass()); } /** - * 分页查询VO + * 根据条件分页查询实体对象列表,并将其转换为指定的VO对象分页列表 + * + * @param page 分页信息 + * @param wrapper 查询条件Wrapper + * @param voClass 要转换的VO类的Class对象 + * @param VO类的类型 + * @param

VO对象分页列表的类型 + * @return 查询到的VO对象分页列表,经过转换为指定的VO类后返回 */ default > P selectVoPage(IPage page, Wrapper wrapper, Class voClass) { + // 根据条件分页查询实体对象列表 List list = this.selectList(page, wrapper); + // 创建一个新的VO对象分页列表,并设置分页信息 IPage voPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal()); if (CollUtil.isEmpty(list)) { return (P) voPage; @@ -202,8 +333,16 @@ public interface BaseMapperPlus extends BaseMapper { return (P) voPage; } + /** + * 根据条件查询符合条件的对象,并将其转换为指定类型的对象列表 + * + * @param wrapper 查询条件Wrapper + * @param mapper 转换函数,用于将查询到的对象转换为指定类型的对象 + * @param 要转换的对象的类型 + * @return 查询到的符合条件的对象列表,经过转换为指定类型的对象后返回 + */ default List selectObjs(Wrapper wrapper, Function mapper) { - return this.selectObjs(wrapper).stream().filter(Objects::nonNull).map(mapper).collect(Collectors.toList()); + return StreamUtils.toList(this.selectObjs(wrapper), mapper); } } diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/core/page/PageQuery.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/core/page/PageQuery.java index 40b7530..6ca9b27 100644 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/core/page/PageQuery.java +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/core/page/PageQuery.java @@ -4,10 +4,10 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.metadata.OrderItem; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import lombok.Data; import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.core.utils.sql.SqlUtil; -import lombok.Data; import java.io.Serial; import java.io.Serializable; @@ -19,7 +19,6 @@ import java.util.List; * * @author Lion Li */ - @Data public class PageQuery implements Serializable { @@ -56,6 +55,9 @@ public class PageQuery implements Serializable { */ public static final int DEFAULT_PAGE_SIZE = Integer.MAX_VALUE; + /** + * 构建分页对象 + */ public Page build() { Integer pageNum = ObjectUtil.defaultIfNull(getPageNum(), DEFAULT_PAGE_NUM); Integer pageSize = ObjectUtil.defaultIfNull(getPageSize(), DEFAULT_PAGE_SIZE); diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/core/page/TableDataInfo.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/core/page/TableDataInfo.java index a4b6799..8ecfb54 100644 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/core/page/TableDataInfo.java +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/core/page/TableDataInfo.java @@ -14,7 +14,6 @@ import java.util.List; * * @author Lion Li */ - @Data @NoArgsConstructor public class TableDataInfo implements Serializable { @@ -53,6 +52,9 @@ public class TableDataInfo implements Serializable { this.total = total; } + /** + * 根据分页对象构建表格分页数据对象 + */ public static TableDataInfo build(IPage page) { TableDataInfo rspData = new TableDataInfo<>(); rspData.setCode(HttpStatus.HTTP_OK); @@ -62,6 +64,9 @@ public class TableDataInfo implements Serializable { return rspData; } + /** + * 根据数据列表构建表格分页数据对象 + */ public static TableDataInfo build(List list) { TableDataInfo rspData = new TableDataInfo<>(); rspData.setCode(HttpStatus.HTTP_OK); @@ -71,6 +76,9 @@ public class TableDataInfo implements Serializable { return rspData; } + /** + * 构建表格分页数据对象 + */ public static TableDataInfo build() { TableDataInfo rspData = new TableDataInfo<>(); rspData.setCode(HttpStatus.HTTP_OK); diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/enums/DataBaseType.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/enums/DataBaseType.java index 93487e9..5084424 100644 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/enums/DataBaseType.java +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/enums/DataBaseType.java @@ -1,8 +1,8 @@ package org.dromara.common.mybatis.enums; -import org.dromara.common.core.utils.StringUtils; import lombok.AllArgsConstructor; import lombok.Getter; +import org.dromara.common.core.utils.StringUtils; /** * 数据库类型 @@ -33,8 +33,17 @@ public enum DataBaseType { */ SQL_SERVER("Microsoft SQL Server"); + /** + * 数据库类型 + */ private final String type; + /** + * 根据数据库产品名称查找对应的数据库类型 + * + * @param databaseProductName 数据库产品名称 + * @return 对应的数据库类型枚举值,如果未找到则返回 null + */ public static DataBaseType find(String databaseProductName) { if (StringUtils.isBlank(databaseProductName)) { return null; diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/enums/DataScopeType.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/enums/DataScopeType.java index 9ea66b0..455cecb 100644 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/enums/DataScopeType.java +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/enums/DataScopeType.java @@ -1,19 +1,22 @@ package org.dromara.common.mybatis.enums; -import org.dromara.common.core.utils.StringUtils; import lombok.AllArgsConstructor; import lombok.Getter; +import org.dromara.common.core.domain.model.LoginUser; +import org.dromara.common.core.utils.StringUtils; import org.dromara.common.mybatis.helper.DataPermissionHelper; /** - * 数据权限类型 + * 数据权限类型枚举 *

- * 语法支持 spel 模板表达式 - *

- * 内置数据 user 当前用户 内容参考 LoginUser - * 如需扩展数据 可使用 {@link DataPermissionHelper} 操作 - * 内置服务 sdss 系统数据权限服务 内容参考 SysDataScopeService - * 如需扩展更多自定义服务 可以参考 sdss 自行编写 + * 支持使用 SpEL 模板表达式定义 SQL 查询条件 + * 内置数据: + * - {@code user}: 当前登录用户信息,参考 {@link LoginUser} + * 内置服务: + * - {@code sdss}: 系统数据权限服务,参考 {@link ISysDataScopeService} + * 如需扩展数据,可以通过 {@link DataPermissionHelper} 进行操作 + * 如需扩展服务,可以通过 {@link ISysDataScopeService} 自行编写 + *

* * @author Lion Li * @version 3.5.0 @@ -29,36 +32,50 @@ public enum DataScopeType { /** * 自定数据权限 + * 使用 SpEL 表达式:`#{#deptName} IN ( #{@sdss.getRoleCustom( #user.roleId )} )` + * 如果不满足条件,则使用默认 SQL 表达式:`1 = 0` */ CUSTOM("2", " #{#deptName} IN ( #{@sdss.getRoleCustom( #user.roleId )} ) ", " 1 = 0 "), /** * 部门数据权限 + * 使用 SpEL 表达式:`#{#deptName} = #{#user.deptId}` + * 如果不满足条件,则使用默认 SQL 表达式:`1 = 0` */ DEPT("3", " #{#deptName} = #{#user.deptId} ", " 1 = 0 "), /** * 部门及以下数据权限 + * 使用 SpEL 表达式:`#{#deptName} IN ( #{@sdss.getDeptAndChild( #user.deptId )}` + * 如果不满足条件,则使用默认 SQL 表达式:`1 = 0` */ DEPT_AND_CHILD("4", " #{#deptName} IN ( #{@sdss.getDeptAndChild( #user.deptId )} )", " 1 = 0 "), /** * 仅本人数据权限 + * 使用 SpEL 表达式:`#{#userName} = #{#user.userId}` + * 如果不满足条件,则使用默认 SQL 表达式:`1 = 0` */ SELF("5", " #{#userName} = #{#user.userId} ", " 1 = 0 "); private final String code; /** - * 语法 采用 spel 模板表达式 + * SpEL 模板表达式,用于构建 SQL 查询条件 */ private final String sqlTemplate; /** - * 不满足 sqlTemplate 则填充 + * 如果不满足 {@code sqlTemplate} 的条件,则使用此默认 SQL 表达式 */ private final String elseSql; + /** + * 根据枚举代码查找对应的枚举值 + * + * @param code 枚举代码 + * @return 对应的枚举值,如果未找到则返回 null + */ public static DataScopeType findCode(String code) { if (StringUtils.isBlank(code)) { return null; diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/InjectionMetaObjectHandler.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/InjectionMetaObjectHandler.java index a66908f..99e6b38 100644 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/InjectionMetaObjectHandler.java +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/InjectionMetaObjectHandler.java @@ -3,12 +3,12 @@ package org.dromara.common.mybatis.handler; import cn.hutool.core.util.ObjectUtil; import cn.hutool.http.HttpStatus; import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; +import lombok.extern.slf4j.Slf4j; +import org.apache.ibatis.reflection.MetaObject; import org.dromara.common.core.domain.model.LoginUser; import org.dromara.common.core.exception.ServiceException; import org.dromara.common.mybatis.core.domain.BaseEntity; import org.dromara.common.satoken.utils.LoginHelper; -import lombok.extern.slf4j.Slf4j; -import org.apache.ibatis.reflection.MetaObject; import java.util.Date; @@ -21,21 +21,28 @@ import java.util.Date; @Slf4j public class InjectionMetaObjectHandler implements MetaObjectHandler { + /** + * 插入填充方法,用于在插入数据时自动填充实体对象中的创建时间、更新时间、创建人、更新人等信息 + * + * @param metaObject 元对象,用于获取原始对象并进行填充 + */ @Override public void insertFill(MetaObject metaObject) { try { if (ObjectUtil.isNotNull(metaObject) && metaObject.getOriginalObject() instanceof BaseEntity baseEntity) { + // 获取当前时间作为创建时间和更新时间,如果创建时间不为空,则使用创建时间,否则使用当前时间 Date current = ObjectUtil.isNotNull(baseEntity.getCreateTime()) ? baseEntity.getCreateTime() : new Date(); baseEntity.setCreateTime(current); baseEntity.setUpdateTime(current); + + // 如果创建人为空,则填充当前登录用户的信息 if (ObjectUtil.isNull(baseEntity.getCreateBy())) { LoginUser loginUser = getLoginUser(); if (ObjectUtil.isNotNull(loginUser)) { Long userId = loginUser.getUserId(); - // 当前已登录 且 创建人为空 则填充 + // 填充创建人、更新人和创建部门信息 baseEntity.setCreateBy(userId); - // 当前已登录 且 更新人为空 则填充 baseEntity.setUpdateBy(userId); baseEntity.setCreateDept(ObjectUtil.isNotNull(baseEntity.getCreateDept()) ? baseEntity.getCreateDept() : loginUser.getDeptId()); @@ -47,19 +54,24 @@ public class InjectionMetaObjectHandler implements MetaObjectHandler { } } + /** + * 更新填充方法,用于在更新数据时自动填充实体对象中的更新时间和更新人信息 + * + * @param metaObject 元对象,用于获取原始对象并进行填充 + */ @Override public void updateFill(MetaObject metaObject) { try { if (ObjectUtil.isNotNull(metaObject) && metaObject.getOriginalObject() instanceof BaseEntity baseEntity) { + // 获取当前时间作为更新时间,无论原始对象中的更新时间是否为空都填充 Date current = new Date(); - // 更新时间填充(不管为不为空) baseEntity.setUpdateTime(current); - // 当前已登录 更新人填充(不管为不为空) + + // 获取当前登录用户的ID,并填充更新人信息 Long userId = LoginHelper.getUserId(); if (ObjectUtil.isNotNull(userId)) { baseEntity.setUpdateBy(userId); } - } } catch (Exception e) { throw new ServiceException("自动注入异常 => " + e.getMessage(), HttpStatus.HTTP_UNAUTHORIZED); @@ -67,7 +79,9 @@ public class InjectionMetaObjectHandler implements MetaObjectHandler { } /** - * 获取登录用户名 + * 获取当前登录用户信息 + * + * @return 当前登录用户的信息,如果用户未登录则返回 null */ private LoginUser getLoginUser() { LoginUser loginUser; diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/MybatisExceptionHandler.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/MybatisExceptionHandler.java index ec3ee0d..518d52d 100644 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/MybatisExceptionHandler.java +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/MybatisExceptionHandler.java @@ -1,15 +1,14 @@ package org.dromara.common.mybatis.handler; -import org.dromara.common.core.domain.R; +import jakarta.servlet.http.HttpServletRequest; import lombok.extern.slf4j.Slf4j; +import org.dromara.common.core.domain.R; import org.dromara.common.core.utils.StringUtils; import org.mybatis.spring.MyBatisSystemException; import org.springframework.dao.DuplicateKeyException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; -import jakarta.servlet.http.HttpServletRequest; - /** * Mybatis异常处理器 * diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/PlusDataPermissionHandler.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/PlusDataPermissionHandler.java index 7d7fd84..74279bd 100644 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/PlusDataPermissionHandler.java +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/PlusDataPermissionHandler.java @@ -68,13 +68,27 @@ public class PlusDataPermissionHandler { */ private final BeanResolver beanResolver = new BeanFactoryResolver(SpringUtils.getBeanFactory()); + /** + * 构造方法,扫描指定包下的 Mapper 类并初始化缓存 + * + * @param mapperPackage Mapper 类所在的包路径 + */ public PlusDataPermissionHandler(String mapperPackage) { scanMapperClasses(mapperPackage); } - + /** + * 获取数据过滤条件的 SQL 片段 + * + * @param where 原始的查询条件表达式 + * @param mappedStatementId Mapper 方法的 ID + * @param isSelect 是否为查询语句 + * @return 数据过滤条件的 SQL 片段 + */ public Expression getSqlSegment(Expression where, String mappedStatementId, boolean isSelect) { + // 获取数据权限配置 DataPermission dataPermission = getDataPermission(mappedStatementId); + // 获取当前登录用户信息 LoginUser currentUser = DataPermissionHelper.getVariable("user"); if (ObjectUtil.isNull(currentUser)) { currentUser = LoginHelper.getLoginUser(); @@ -84,6 +98,7 @@ public class PlusDataPermissionHandler { if (LoginHelper.isSuperAdmin() || LoginHelper.isTenantAdmin()) { return where; } + // 构造数据过滤条件的 SQL 片段 String dataFilterSql = buildDataFilter(dataPermission.value(), isSelect); if (StringUtils.isBlank(dataFilterSql)) { return where; @@ -103,7 +118,12 @@ public class PlusDataPermissionHandler { } /** - * 构造数据过滤sql + * 构建数据过滤条件的 SQL 语句 + * + * @param dataColumns 数据权限注解中的列信息 + * @param isSelect 标志当前操作是否为查询操作,查询操作和更新或删除操作在处理过滤条件时会有不同的处理方式 + * @return 构建的数据过滤条件的 SQL 语句 + * @throws ServiceException 如果角色的数据范围异常或者 key 与 value 的长度不匹配,则抛出 ServiceException 异常 */ private String buildDataFilter(DataColumn[] dataColumns, boolean isSelect) { // 更新或删除需满足所有条件 @@ -159,20 +179,29 @@ public class PlusDataPermissionHandler { } /** - * 通过 mapperPackage 设置的扫描包 扫描缓存有注解的方法与类 + * 扫描指定包下的 Mapper 类,并查找其中带有特定注解的方法或类 + * + * @param mapperPackage Mapper 类所在的包路径 */ private void scanMapperClasses(String mapperPackage) { + // 创建资源解析器和元数据读取工厂 PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory(); + // 将 Mapper 包路径按分隔符拆分为数组 String[] packagePatternArray = StringUtils.splitPreserveAllTokens(mapperPackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS); String classpath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX; try { for (String packagePattern : packagePatternArray) { + // 将包路径转换为资源路径 String path = ClassUtils.convertClassNameToResourcePath(packagePattern); + // 获取指定路径下的所有 .class 文件资源 Resource[] resources = resolver.getResources(classpath + path + "/*.class"); for (Resource resource : resources) { + // 获取资源的类元数据 ClassMetadata classMetadata = factory.getMetadataReader(resource).getClassMetadata(); + // 获取资源对应的类对象 Class clazz = Resources.classForName(classMetadata.getClassName()); + // 查找类中的特定注解 findAnnotation(clazz); } } @@ -181,9 +210,13 @@ public class PlusDataPermissionHandler { } } + /** + * 在指定的类中查找特定的注解 DataPermission,并将带有这个注解的方法或类存储到 dataPermissionCacheMap 中 + * + * @param clazz 要查找的类 + */ private void findAnnotation(Class clazz) { DataPermission dataPermission; - // 获取方法注解 for (Method method : clazz.getMethods()) { if (method.isDefault() || method.isVarArgs()) { continue; @@ -194,17 +227,24 @@ public class PlusDataPermissionHandler { dataPermissionCacheMap.put(mappedStatementId, dataPermission); } } - // 获取类注解 if (AnnotationUtil.hasAnnotation(clazz, DataPermission.class)) { dataPermission = AnnotationUtil.getAnnotation(clazz, DataPermission.class); dataPermissionCacheMap.put(clazz.getName(), dataPermission); } } + /** + * 根据映射语句 ID 或类名获取对应的 DataPermission 注解对象 + * + * @param mapperId 映射语句 ID + * @return DataPermission 注解对象,如果不存在则返回 null + */ public DataPermission getDataPermission(String mapperId) { + // 检查缓存中是否包含映射语句 ID 对应的 DataPermission 注解对象 if (dataPermissionCacheMap.containsKey(mapperId)) { return dataPermissionCacheMap.get(mapperId); } + // 如果缓存中不包含映射语句 ID 对应的 DataPermission 注解对象,则尝试使用类名作为键查找 String clazzName = mapperId.substring(0, mapperId.lastIndexOf(".")); if (dataPermissionCacheMap.containsKey(clazzName)) { return dataPermissionCacheMap.get(clazzName); @@ -213,7 +253,10 @@ public class PlusDataPermissionHandler { } /** - * 是否无效 + * 检查给定的映射语句 ID 是否有效,即是否能够找到对应的 DataPermission 注解对象 + * + * @param mapperId 映射语句 ID + * @return 如果找到对应的 DataPermission 注解对象,则返回 false;否则返回 true */ public boolean invalid(String mapperId) { return getDataPermission(mapperId) == null; diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/helper/DataBaseHelper.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/helper/DataBaseHelper.java index bb20f4b..a7cfee5 100644 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/helper/DataBaseHelper.java +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/helper/DataBaseHelper.java @@ -2,11 +2,11 @@ package org.dromara.common.mybatis.helper; import cn.hutool.core.convert.Convert; import com.baomidou.dynamic.datasource.DynamicRoutingDataSource; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.utils.SpringUtils; import org.dromara.common.mybatis.enums.DataBaseType; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; import javax.sql.DataSource; import java.sql.Connection; @@ -14,7 +14,6 @@ import java.sql.DatabaseMetaData; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; -import java.util.Set; /** * 数据库助手 diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/helper/DataPermissionHelper.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/helper/DataPermissionHelper.java index 7f6ab1f..2afe9ee 100644 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/helper/DataPermissionHelper.java +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/helper/DataPermissionHelper.java @@ -24,17 +24,35 @@ public class DataPermissionHelper { private static final String DATA_PERMISSION_KEY = "data:permission"; + /** + * 从上下文中获取指定键的变量值,并将其转换为指定的类型 + * + * @param key 变量的键 + * @param 变量值的类型 + * @return 指定键的变量值,如果不存在则返回 null + */ public static T getVariable(String key) { Map context = getContext(); return (T) context.get(key); } - + /** + * 向上下文中设置指定键的变量值 + * + * @param key 要设置的变量的键 + * @param value 要设置的变量值 + */ public static void setVariable(String key, Object value) { Map context = getContext(); context.put(key, value); } + /** + * 获取数据权限上下文 + * + * @return 存储在SaStorage中的Map对象,用于存储数据权限相关的上下文信息 + * @throws NullPointerException 如果数据权限上下文类型异常,则抛出NullPointerException + */ public static Map getContext() { SaStorage saStorage = SaHolder.getStorage(); Object attribute = saStorage.get(DATA_PERMISSION_KEY); @@ -64,6 +82,7 @@ public class DataPermissionHelper { /** * 在忽略数据权限中执行 + *

禁止在忽略数据权限中执行忽略数据权限

* * @param handle 处理执行方法 */ @@ -78,6 +97,7 @@ public class DataPermissionHelper { /** * 在忽略数据权限中执行 + *

禁止在忽略数据权限中执行忽略数据权限

* * @param handle 处理执行方法 */ diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/interceptor/PlusDataPermissionInterceptor.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/interceptor/PlusDataPermissionInterceptor.java index 6eed8f7..85a4d0a 100644 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/interceptor/PlusDataPermissionInterceptor.java +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/interceptor/PlusDataPermissionInterceptor.java @@ -37,17 +37,33 @@ public class PlusDataPermissionInterceptor extends BaseMultiTableInnerIntercepto private final PlusDataPermissionHandler dataPermissionHandler; + /** + * 构造函数,初始化 PlusDataPermissionHandler 实例 + * + * @param mapperPackage 扫描的映射器包 + */ public PlusDataPermissionInterceptor(String mapperPackage) { this.dataPermissionHandler = new PlusDataPermissionHandler(mapperPackage); } + /** + * 在执行查询之前,检查并处理数据权限相关逻辑 + * + * @param executor MyBatis 执行器对象 + * @param ms 映射语句对象 + * @param parameter 方法参数 + * @param rowBounds 分页对象 + * @param resultHandler 结果处理器 + * @param boundSql 绑定的 SQL 对象 + * @throws SQLException 如果发生 SQL 异常 + */ @Override public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException { - // 检查忽略注解 + // 检查是否需要忽略数据权限处理 if (InterceptorIgnoreHelper.willIgnoreDataPermission(ms.getId())) { return; } - // 检查是否无效 无数据权限注解 + // 检查是否缺少有效的数据权限注解 if (dataPermissionHandler.invalid(ms.getId())) { return; } @@ -56,16 +72,26 @@ public class PlusDataPermissionInterceptor extends BaseMultiTableInnerIntercepto mpBs.sql(parserSingle(mpBs.sql(), ms.getId())); } + /** + * 在准备 SQL 语句之前,检查并处理更新和删除操作的数据权限相关逻辑 + * + * @param sh MyBatis StatementHandler 对象 + * @param connection 数据库连接对象 + * @param transactionTimeout 事务超时时间 + */ @Override public void beforePrepare(StatementHandler sh, Connection connection, Integer transactionTimeout) { PluginUtils.MPStatementHandler mpSh = PluginUtils.mpStatementHandler(sh); MappedStatement ms = mpSh.mappedStatement(); + // 获取 SQL 命令类型(增、删、改、查) SqlCommandType sct = ms.getSqlCommandType(); + + // 只处理更新和删除操作的 SQL 语句 if (sct == SqlCommandType.UPDATE || sct == SqlCommandType.DELETE) { if (InterceptorIgnoreHelper.willIgnoreDataPermission(ms.getId())) { return; } - // 检查是否无效 无数据权限注解 + // 检查是否缺少有效的数据权限注解 if (dataPermissionHandler.invalid(ms.getId())) { return; } @@ -74,6 +100,14 @@ public class PlusDataPermissionInterceptor extends BaseMultiTableInnerIntercepto } } + /** + * 处理 SELECT 查询语句中的 WHERE 条件 + * + * @param select SELECT 查询对象 + * @param index 查询语句的索引 + * @param sql 查询语句 + * @param obj WHERE 条件参数 + */ @Override protected void processSelect(Select select, int index, String sql, Object obj) { if (select instanceof PlainSelect) { @@ -84,6 +118,14 @@ public class PlusDataPermissionInterceptor extends BaseMultiTableInnerIntercepto } } + /** + * 处理 UPDATE 语句中的 WHERE 条件 + * + * @param update UPDATE 查询对象 + * @param index 查询语句的索引 + * @param sql 查询语句 + * @param obj WHERE 条件参数 + */ @Override protected void processUpdate(Update update, int index, String sql, Object obj) { Expression sqlSegment = dataPermissionHandler.getSqlSegment(update.getWhere(), (String) obj, false); @@ -92,6 +134,14 @@ public class PlusDataPermissionInterceptor extends BaseMultiTableInnerIntercepto } } + /** + * 处理 DELETE 语句中的 WHERE 条件 + * + * @param delete DELETE 查询对象 + * @param index 查询语句的索引 + * @param sql 查询语句 + * @param obj WHERE 条件参数 + */ @Override protected void processDelete(Delete delete, int index, String sql, Object obj) { Expression sqlSegment = dataPermissionHandler.getSqlSegment(delete.getWhere(), (String) obj, false); @@ -101,10 +151,10 @@ public class PlusDataPermissionInterceptor extends BaseMultiTableInnerIntercepto } /** - * 设置 where 条件 + * 设置 SELECT 语句的 WHERE 条件 * - * @param plainSelect 查询对象 - * @param mappedStatementId 执行方法id + * @param plainSelect SELECT 查询对象 + * @param mappedStatementId 映射语句的 ID */ protected void setWhere(PlainSelect plainSelect, String mappedStatementId) { Expression sqlSegment = dataPermissionHandler.getSqlSegment(plainSelect.getWhere(), mappedStatementId, true); @@ -113,6 +163,14 @@ public class PlusDataPermissionInterceptor extends BaseMultiTableInnerIntercepto } } + /** + * 构建表达式,用于处理表的数据权限 + * + * @param table 表对象 + * @param where WHERE 条件表达式 + * @param whereSegment WHERE 条件片段 + * @return 构建的表达式 + */ @Override public Expression buildTableExpression(Table table, Expression where, String whereSegment) { // 只有新版数据权限处理器才会执行到这里 diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/resources/spy.properties b/ruoyi-common/ruoyi-common-mybatis/src/main/resources/spy.properties index e9d10f3..f3ed7d8 100644 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/resources/spy.properties +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/resources/spy.properties @@ -17,4 +17,4 @@ databaseDialectTimestampFormat=yyyy-MM-dd HH:mm:ss # 是否过滤 Log filter=true # 过滤 Log 时所排除的 sql 关键字,以逗号分隔 -exclude=SELECT 1 +exclude= diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java index fcad35b..5e300da 100644 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java +++ b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java @@ -162,13 +162,14 @@ public class OssClient { /** * 上传文件到 Amazon S3,并返回上传结果 * - * @param filePath 本地文件路径 - * @param key 在 Amazon S3 中的对象键 - * @param md5Digest 本地文件的 MD5 哈希值(可选) + * @param filePath 本地文件路径 + * @param key 在 Amazon S3 中的对象键 + * @param md5Digest 本地文件的 MD5 哈希值(可选) + * @param contentType 文件内容类型 * @return UploadResult 包含上传后的文件信息 * @throws OssException 如果上传失败,抛出自定义异常 */ - public UploadResult upload(Path filePath, String key, String md5Digest) { + public UploadResult upload(Path filePath, String key, String md5Digest, String contentType) { try { // 构建上传请求对象 FileUpload fileUpload = transferManager.uploadFile( @@ -176,6 +177,8 @@ public class OssClient { y -> y.bucket(properties.getBucketName()) .key(key) .contentMD5(StringUtils.isNotEmpty(md5Digest) ? md5Digest : null) + .contentType(contentType) + .acl(getAccessPolicy().getObjectCannedACL()) .build()) .addTransferListener(LoggingTransferListener.create()) .source(filePath).build()); @@ -201,10 +204,11 @@ public class OssClient { * @param inputStream 要上传的输入流 * @param key 在 Amazon S3 中的对象键 * @param length 输入流的长度 + * @param contentType 文件内容类型 * @return UploadResult 包含上传后的文件信息 * @throws OssException 如果上传失败,抛出自定义异常 */ - public UploadResult upload(InputStream inputStream, String key, Long length) { + public UploadResult upload(InputStream inputStream, String key, Long length, String contentType) { // 如果输入流不是 ByteArrayInputStream,则将其读取为字节数组再创建 ByteArrayInputStream if (!(inputStream instanceof ByteArrayInputStream)) { inputStream = new ByteArrayInputStream(IoUtil.readBytes(inputStream)); @@ -219,6 +223,8 @@ public class OssClient { .putObjectRequest( y -> y.bucket(properties.getBucketName()) .key(key) + .contentType(contentType) + .acl(getAccessPolicy().getObjectCannedACL()) .build()) .build()); @@ -335,7 +341,7 @@ public class OssClient { * @throws OssException 如果上传失败,抛出自定义异常 */ public UploadResult uploadSuffix(byte[] data, String suffix) { - return upload(new ByteArrayInputStream(data), getPath(properties.getPrefix(), suffix), Long.valueOf(data.length)); + return upload(new ByteArrayInputStream(data), getPath(properties.getPrefix(), suffix), Long.valueOf(data.length), FileUtils.getMimeType(suffix)); } /** @@ -348,7 +354,7 @@ public class OssClient { * @throws OssException 如果上传失败,抛出自定义异常 */ public UploadResult uploadSuffix(InputStream inputStream, String suffix, Long length) { - return upload(inputStream, getPath(properties.getPrefix(), suffix), length); + return upload(inputStream, getPath(properties.getPrefix(), suffix), length, FileUtils.getMimeType(suffix)); } /** @@ -360,7 +366,7 @@ public class OssClient { * @throws OssException 如果上传失败,抛出自定义异常 */ public UploadResult uploadSuffix(File file, String suffix) { - return upload(file.toPath(), getPath(properties.getPrefix(), suffix), null); + return upload(file.toPath(), getPath(properties.getPrefix(), suffix), null, FileUtils.getMimeType(suffix)); } /** diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/factory/OssFactory.java b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/factory/OssFactory.java index d70270a..3da1ba5 100644 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/factory/OssFactory.java +++ b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/factory/OssFactory.java @@ -48,7 +48,10 @@ public class OssFactory { } OssProperties properties = JsonUtils.parseObject(json, OssProperties.class); // 使用租户标识避免多个租户相同key实例覆盖 - String key = properties.getTenantId() + ":" + configKey; + String key = configKey; + if (StringUtils.isNotBlank(properties.getTenantId())) { + key = properties.getTenantId() + ":" + configKey; + } OssClient client = CLIENT_CACHE.get(key); // 客户端不存在或配置不相同则重新构建 if (client == null || !client.checkPropertiesSame(properties)) { diff --git a/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/handler/RedisExceptionHandler.java b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/handler/RedisExceptionHandler.java index 5ed12a6..5e904f3 100644 --- a/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/handler/RedisExceptionHandler.java +++ b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/handler/RedisExceptionHandler.java @@ -23,7 +23,7 @@ public class RedisExceptionHandler { @ExceptionHandler(LockFailureException.class) public R handleLockFailureException(LockFailureException e, HttpServletRequest request) { String requestURI = request.getRequestURI(); - log.error("获取锁失败了'{}',发生Lock4j异常." + requestURI, e.getMessage()); + log.error("获取锁失败了'{}',发生Lock4j异常.", requestURI, e); return R.fail(HttpStatus.HTTP_UNAVAILABLE, "业务处理中,请稍后再试..."); } diff --git a/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/QueueUtils.java b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/QueueUtils.java index 4587e64..e436a46 100644 --- a/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/QueueUtils.java +++ b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/QueueUtils.java @@ -1,12 +1,13 @@ package org.dromara.common.redis.utils; -import org.dromara.common.core.utils.SpringUtils; import lombok.AccessLevel; import lombok.NoArgsConstructor; +import org.dromara.common.core.utils.SpringUtils; import org.redisson.api.*; +import java.util.concurrent.CompletionStage; import java.util.concurrent.TimeUnit; -import java.util.function.Consumer; +import java.util.function.Function; /** * 分布式队列工具 @@ -224,7 +225,7 @@ public class QueueUtils { /** * 订阅阻塞队列(可订阅所有实现类 例如: 延迟 优先 有界 等) */ - public static void subscribeBlockingQueue(String queueName, Consumer consumer, boolean isDelayed) { + public static void subscribeBlockingQueue(String queueName, Function> consumer, boolean isDelayed) { RBlockingQueue queue = CLIENT.getBlockingQueue(queueName); if (isDelayed) { // 订阅延迟队列 diff --git a/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/core/dao/PlusSaTokenDao.java b/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/core/dao/PlusSaTokenDao.java index 0664755..38e12c3 100644 --- a/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/core/dao/PlusSaTokenDao.java +++ b/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/core/dao/PlusSaTokenDao.java @@ -2,7 +2,6 @@ package org.dromara.common.satoken.core.dao; import cn.dev33.satoken.dao.SaTokenDao; import cn.dev33.satoken.util.SaFoxUtil; -import cn.hutool.core.lang.Console; import com.github.benmanes.caffeine.cache.Cache; import com.github.benmanes.caffeine.cache.Caffeine; import org.dromara.common.redis.utils.RedisUtils; @@ -54,7 +53,7 @@ public class PlusSaTokenDao implements SaTokenDao { } else { RedisUtils.setCacheObject(key, value, Duration.ofSeconds(timeout)); } - CAFFEINE.put(key, value); + CAFFEINE.invalidate(key); } /** @@ -64,7 +63,7 @@ public class PlusSaTokenDao implements SaTokenDao { public void update(String key, String value) { if (RedisUtils.hasKey(key)) { RedisUtils.setCacheObject(key, value, true); - CAFFEINE.put(key, value); + CAFFEINE.invalidate(key); } } @@ -117,7 +116,7 @@ public class PlusSaTokenDao implements SaTokenDao { } else { RedisUtils.setCacheObject(key, object, Duration.ofSeconds(timeout)); } - CAFFEINE.put(key, object); + CAFFEINE.invalidate(key); } /** @@ -127,7 +126,7 @@ public class PlusSaTokenDao implements SaTokenDao { public void updateObject(String key, Object object) { if (RedisUtils.hasKey(key)) { RedisUtils.setCacheObject(key, object, true); - CAFFEINE.put(key, object); + CAFFEINE.invalidate(key); } } diff --git a/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/utils/LoginHelper.java b/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/utils/LoginHelper.java index 1e0d8a7..4ab7d4e 100644 --- a/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/utils/LoginHelper.java +++ b/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/utils/LoginHelper.java @@ -3,6 +3,7 @@ package org.dromara.common.satoken.utils; import cn.dev33.satoken.session.SaSession; import cn.dev33.satoken.stp.SaLoginModel; import cn.dev33.satoken.stp.StpUtil; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.convert.Convert; import cn.hutool.core.util.ObjectUtil; import lombok.AccessLevel; @@ -87,6 +88,13 @@ public class LoginHelper { return Convert.toLong(getExtra(USER_KEY)); } + /** + * 获取用户账户 + */ + public static String getUsername() { + return Convert.toStr(getExtra(USER_NAME_KEY)); + } + /** * 获取租户ID */ @@ -129,13 +137,6 @@ public class LoginHelper { } } - /** - * 获取用户账户 - */ - public static String getUsername() { - return getLoginUser().getUsername(); - } - /** * 获取用户类型 */ @@ -170,6 +171,9 @@ public class LoginHelper { * @return 结果 */ public static boolean isTenantAdmin(Set rolePermission) { + if (CollUtil.isEmpty(rolePermission)) { + return false; + } return rolePermission.contains(TenantConstants.TENANT_ADMIN_ROLE_KEY); } @@ -188,7 +192,11 @@ public class LoginHelper { * @return 结果 */ public static boolean isLogin() { - return getLoginUser() != null; + try { + return getLoginUser() != null; + } catch (Exception e) { + return false; + } } } diff --git a/ruoyi-common/ruoyi-common-sms/src/main/java/org/dromara/common/sms/config/SmsAutoConfiguration.java b/ruoyi-common/ruoyi-common-sms/src/main/java/org/dromara/common/sms/config/SmsAutoConfiguration.java index 1e88407..3a39cc2 100644 --- a/ruoyi-common/ruoyi-common-sms/src/main/java/org/dromara/common/sms/config/SmsAutoConfiguration.java +++ b/ruoyi-common/ruoyi-common-sms/src/main/java/org/dromara/common/sms/config/SmsAutoConfiguration.java @@ -1,6 +1,7 @@ package org.dromara.common.sms.config; import org.dromara.common.sms.core.dao.PlusSmsDao; +import org.dromara.common.sms.handler.SmsExceptionHandler; import org.dromara.sms4j.api.dao.SmsDao; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; @@ -21,4 +22,12 @@ public class SmsAutoConfiguration { return new PlusSmsDao(); } + /** + * 异常处理器 + */ + @Bean + public SmsExceptionHandler smsExceptionHandler() { + return new SmsExceptionHandler(); + } + } diff --git a/ruoyi-common/ruoyi-common-sms/src/main/java/org/dromara/common/sms/handler/SmsExceptionHandler.java b/ruoyi-common/ruoyi-common-sms/src/main/java/org/dromara/common/sms/handler/SmsExceptionHandler.java new file mode 100644 index 0000000..2c619a3 --- /dev/null +++ b/ruoyi-common/ruoyi-common-sms/src/main/java/org/dromara/common/sms/handler/SmsExceptionHandler.java @@ -0,0 +1,30 @@ +package org.dromara.common.sms.handler; + +import cn.hutool.http.HttpStatus; +import jakarta.servlet.http.HttpServletRequest; +import lombok.extern.slf4j.Slf4j; +import org.dromara.common.core.domain.R; +import org.dromara.sms4j.comm.exception.SmsBlendException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +/** + * SMS异常处理器 + * + * @author AprilWind + */ +@Slf4j +@RestControllerAdvice +public class SmsExceptionHandler { + + /** + * sms异常 + */ + @ExceptionHandler(SmsBlendException.class) + public R handleSmsBlendException(SmsBlendException e, HttpServletRequest request) { + String requestURI = request.getRequestURI(); + log.error("请求地址'{}',发生sms短信异常.", requestURI, e); + return R.fail(HttpStatus.HTTP_INTERNAL_ERROR, "短信发送失败,请稍后再试..."); + } + +} diff --git a/ruoyi-common/ruoyi-common-social/pom.xml b/ruoyi-common/ruoyi-common-social/pom.xml new file mode 100644 index 0000000..9f9a965 --- /dev/null +++ b/ruoyi-common/ruoyi-common-social/pom.xml @@ -0,0 +1,34 @@ + + + + org.dromara + ruoyi-common + ${revision} + + 4.0.0 + + ruoyi-common-social + + + ruoyi-common-social 授权认证 + + + + + me.zhyd.oauth + JustAuth + + + + org.dromara + ruoyi-common-json + + + + org.dromara + ruoyi-common-redis + + + diff --git a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/config/SocialAutoConfiguration.java b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/config/SocialAutoConfiguration.java new file mode 100644 index 0000000..19b39d8 --- /dev/null +++ b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/config/SocialAutoConfiguration.java @@ -0,0 +1,23 @@ +package org.dromara.common.social.config; + +import me.zhyd.oauth.cache.AuthStateCache; +import org.dromara.common.social.config.properties.SocialProperties; +import org.dromara.common.social.utils.AuthRedisStateCache; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; + +/** + * Social 配置属性 + * @author thiszhc + */ +@AutoConfiguration +@EnableConfigurationProperties(SocialProperties.class) +public class SocialAutoConfiguration { + + @Bean + public AuthStateCache authStateCache() { + return new AuthRedisStateCache(); + } + +} diff --git a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/config/properties/SocialLoginConfigProperties.java b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/config/properties/SocialLoginConfigProperties.java new file mode 100644 index 0000000..5f49d9c --- /dev/null +++ b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/config/properties/SocialLoginConfigProperties.java @@ -0,0 +1,75 @@ +package org.dromara.common.social.config.properties; + +import lombok.Data; + +import java.util.List; + +/** + * 社交登录配置 + * + * @author thiszhc + */ +@Data +public class SocialLoginConfigProperties { + + /** + * 应用 ID + */ + private String clientId; + + /** + * 应用密钥 + */ + private String clientSecret; + + /** + * 回调地址 + */ + private String redirectUri; + + /** + * 是否获取unionId + */ + private boolean unionId; + + /** + * Coding 企业名称 + */ + private String codingGroupName; + + /** + * 支付宝公钥 + */ + private String alipayPublicKey; + + /** + * 企业微信应用ID + */ + private String agentId; + + /** + * stackoverflow api key + */ + private String stackOverflowKey; + + /** + * 设备ID + */ + private String deviceId; + + /** + * 客户端系统类型 + */ + private String clientOsType; + + /** + * maxkey 服务器地址 + */ + private String serverUrl; + + /** + * 请求范围 + */ + private List scopes; + +} diff --git a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/config/properties/SocialProperties.java b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/config/properties/SocialProperties.java new file mode 100644 index 0000000..1487a6a --- /dev/null +++ b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/config/properties/SocialProperties.java @@ -0,0 +1,24 @@ +package org.dromara.common.social.config.properties; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.Map; + +/** + * Social 配置属性 + * + * @author thiszhc + */ +@Data +@Component +@ConfigurationProperties(prefix = "justauth") +public class SocialProperties { + + /** + * 授权类型 + */ + private Map type; + +} diff --git a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/maxkey/AuthMaxKeyRequest.java b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/maxkey/AuthMaxKeyRequest.java new file mode 100644 index 0000000..b95c19e --- /dev/null +++ b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/maxkey/AuthMaxKeyRequest.java @@ -0,0 +1,80 @@ +package org.dromara.common.social.maxkey; + +import cn.hutool.core.lang.Dict; +import me.zhyd.oauth.cache.AuthStateCache; +import me.zhyd.oauth.config.AuthConfig; +import me.zhyd.oauth.exception.AuthException; +import me.zhyd.oauth.model.AuthCallback; +import me.zhyd.oauth.model.AuthToken; +import me.zhyd.oauth.model.AuthUser; +import me.zhyd.oauth.request.AuthDefaultRequest; +import org.dromara.common.core.utils.SpringUtils; +import org.dromara.common.json.utils.JsonUtils; + +/** + * @author 长春叭哥 2023年03月26日 + */ +public class AuthMaxKeyRequest extends AuthDefaultRequest { + + public static final String SERVER_URL = SpringUtils.getProperty("justauth.type.maxkey.server-url"); + + /** + * 设定归属域 + */ + public AuthMaxKeyRequest(AuthConfig config) { + super(config, AuthMaxKeySource.MAXKEY); + } + + public AuthMaxKeyRequest(AuthConfig config, AuthStateCache authStateCache) { + super(config, AuthMaxKeySource.MAXKEY, authStateCache); + } + + @Override + protected AuthToken getAccessToken(AuthCallback authCallback) { + String body = doPostAuthorizationCode(authCallback.getCode()); + Dict object = JsonUtils.parseMap(body); + // oauth/token 验证异常 + if (object.containsKey("error")) { + throw new AuthException(object.getStr("error_description")); + } + // user 验证异常 + if (object.containsKey("message")) { + throw new AuthException(object.getStr("message")); + } + return AuthToken.builder() + .accessToken(object.getStr("access_token")) + .refreshToken(object.getStr("refresh_token")) + .idToken(object.getStr("id_token")) + .tokenType(object.getStr("token_type")) + .scope(object.getStr("scope")) + .build(); + } + + @Override + protected AuthUser getUserInfo(AuthToken authToken) { + String body = doGetUserInfo(authToken); + Dict object = JsonUtils.parseMap(body); + // oauth/token 验证异常 + if (object.containsKey("error")) { + throw new AuthException(object.getStr("error_description")); + } + // user 验证异常 + if (object.containsKey("message")) { + throw new AuthException(object.getStr("message")); + } + return AuthUser.builder() + .uuid(object.getStr("userId")) + .username(object.getStr("username")) + .nickname(object.getStr("displayName")) + .avatar(object.getStr("avatar_url")) + .blog(object.getStr("web_url")) + .company(object.getStr("organization")) + .location(object.getStr("location")) + .email(object.getStr("email")) + .remark(object.getStr("bio")) + .token(authToken) + .source(source.toString()) + .build(); + } + +} diff --git a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/maxkey/AuthMaxKeySource.java b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/maxkey/AuthMaxKeySource.java new file mode 100644 index 0000000..1ff57f7 --- /dev/null +++ b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/maxkey/AuthMaxKeySource.java @@ -0,0 +1,52 @@ +package org.dromara.common.social.maxkey; + +import me.zhyd.oauth.config.AuthSource; +import me.zhyd.oauth.request.AuthDefaultRequest; + +/** + * Oauth2 默认接口说明 + * + * @author 长春叭哥 2023年03月26日 + * + */ +public enum AuthMaxKeySource implements AuthSource { + + /** + * 自己搭建的 maxkey 私服 + */ + MAXKEY { + + /** + * 授权的api + */ + @Override + public String authorize() { + return AuthMaxKeyRequest.SERVER_URL + "/sign/authz/oauth/v20/authorize"; + } + + /** + * 获取accessToken的api + */ + @Override + public String accessToken() { + return AuthMaxKeyRequest.SERVER_URL + "/sign/authz/oauth/v20/token"; + } + + /** + * 获取用户信息的api + */ + @Override + public String userInfo() { + return AuthMaxKeyRequest.SERVER_URL + "/sign/api/oauth/v20/me"; + } + + /** + * 平台对应的 AuthRequest 实现类,必须继承自 {@link AuthDefaultRequest} + */ + @Override + public Class getTargetClass() { + return AuthMaxKeyRequest.class; + } + + } +} diff --git a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopIamRequest.java b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopIamRequest.java new file mode 100644 index 0000000..13649f9 --- /dev/null +++ b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopIamRequest.java @@ -0,0 +1,100 @@ +package org.dromara.common.social.topiam; + +import cn.hutool.core.lang.Dict; +import cn.hutool.core.util.StrUtil; +import com.xkcoding.http.support.HttpHeader; +import lombok.extern.slf4j.Slf4j; +import me.zhyd.oauth.cache.AuthStateCache; +import me.zhyd.oauth.config.AuthConfig; +import me.zhyd.oauth.exception.AuthException; +import me.zhyd.oauth.model.AuthCallback; +import me.zhyd.oauth.model.AuthToken; +import me.zhyd.oauth.model.AuthUser; +import me.zhyd.oauth.request.AuthDefaultRequest; +import me.zhyd.oauth.utils.HttpUtils; +import me.zhyd.oauth.utils.UrlBuilder; +import org.dromara.common.core.utils.SpringUtils; +import org.dromara.common.json.utils.JsonUtils; + +import static org.dromara.common.social.topiam.AuthTopiamSource.TOPIAM; + +/** + * TopIAM 认证请求 + * + * @author xlsea + * @since 2024-01-06 + */ +@Slf4j +public class AuthTopIamRequest extends AuthDefaultRequest { + + public static final String SERVER_URL = SpringUtils.getProperty("justauth.type.topiam.server-url"); + + /** + * 设定归属域 + */ + public AuthTopIamRequest(AuthConfig config) { + super(config, TOPIAM); + } + + public AuthTopIamRequest(AuthConfig config, AuthStateCache authStateCache) { + super(config, TOPIAM, authStateCache); + } + + @Override + protected AuthToken getAccessToken(AuthCallback authCallback) { + String body = doPostAuthorizationCode(authCallback.getCode()); + Dict object = JsonUtils.parseMap(body); + checkResponse(object); + return AuthToken.builder() + .accessToken(object.getStr("access_token")) + .refreshToken(object.getStr("refresh_token")) + .idToken(object.getStr("id_token")) + .tokenType(object.getStr("token_type")) + .scope(object.getStr("scope")) + .build(); + } + + @Override + protected AuthUser getUserInfo(AuthToken authToken) { + String body = doGetUserInfo(authToken); + Dict object = JsonUtils.parseMap(body); + checkResponse(object); + return AuthUser.builder() + .uuid(object.getStr("sub")) + .username(object.getStr("preferred_username")) + .nickname(object.getStr("nickname")) + .avatar(object.getStr("picture")) + .email(object.getStr("email")) + .token(authToken) + .source(source.toString()) + .build(); + } + + + @Override + protected String doGetUserInfo(AuthToken authToken) { + return new HttpUtils(config.getHttpConfig()).get(source.userInfo(), null, new HttpHeader() + .add("Content-Type", "application/json") + .add("Authorization", "Bearer " + authToken.getAccessToken()), false).getBody(); + } + + + @Override + public String authorize(String state) { + return UrlBuilder.fromBaseUrl(super.authorize(state)) + .queryParam("scope", StrUtil.join("%20", config.getScopes())) + .build(); + } + + public static void checkResponse(Dict object) { + // oauth/token 验证异常 + if (object.containsKey("error")) { + throw new AuthException(object.getStr("error_description")); + } + // user 验证异常 + if (object.containsKey("message")) { + throw new AuthException(object.getStr("message")); + } + } + +} diff --git a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopiamSource.java b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopiamSource.java new file mode 100644 index 0000000..e47d6c6 --- /dev/null +++ b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopiamSource.java @@ -0,0 +1,51 @@ +package org.dromara.common.social.topiam; + +import me.zhyd.oauth.config.AuthSource; +import me.zhyd.oauth.request.AuthDefaultRequest; + +/** + * Oauth2 默认接口说明 + * + * @author xlsea + * @since 2024-01-06 + */ +public enum AuthTopiamSource implements AuthSource { + + /** + * 测试 + */ + TOPIAM { + /** + * 授权的api + */ + @Override + public String authorize() { + return AuthTopIamRequest.SERVER_URL + "/oauth2/auth"; + } + + /** + * 获取accessToken的api + */ + @Override + public String accessToken() { + return AuthTopIamRequest.SERVER_URL + "/oauth2/token"; + } + + /** + * 获取用户信息的api + */ + @Override + public String userInfo() { + return AuthTopIamRequest.SERVER_URL + "/oauth2/userinfo"; + } + + /** + * 平台对应的 AuthRequest 实现类,必须继承自 {@link AuthDefaultRequest} + */ + @Override + public Class getTargetClass() { + return AuthTopIamRequest.class; + } + + } +} diff --git a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/utils/AuthRedisStateCache.java b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/utils/AuthRedisStateCache.java new file mode 100644 index 0000000..0b6ec20 --- /dev/null +++ b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/utils/AuthRedisStateCache.java @@ -0,0 +1,61 @@ +package org.dromara.common.social.utils; + +import lombok.AllArgsConstructor; +import me.zhyd.oauth.cache.AuthStateCache; +import org.dromara.common.core.constant.GlobalConstants; +import org.dromara.common.redis.utils.RedisUtils; + +import java.time.Duration; + +/** + * 授权状态缓存 + */ +@AllArgsConstructor +public class AuthRedisStateCache implements AuthStateCache { + + /** + * 存入缓存 + * + * @param key 缓存key + * @param value 缓存内容 + */ + @Override + public void cache(String key, String value) { + // 授权超时时间 默认三分钟 + RedisUtils.setCacheObject(GlobalConstants.SOCIAL_AUTH_CODE_KEY + key, value, Duration.ofMinutes(3)); + } + + /** + * 存入缓存 + * + * @param key 缓存key + * @param value 缓存内容 + * @param timeout 指定缓存过期时间(毫秒) + */ + @Override + public void cache(String key, String value, long timeout) { + RedisUtils.setCacheObject(GlobalConstants.SOCIAL_AUTH_CODE_KEY + key, value, Duration.ofMillis(timeout)); + } + + /** + * 获取缓存内容 + * + * @param key 缓存key + * @return 缓存内容 + */ + @Override + public String get(String key) { + return RedisUtils.getCacheObject(GlobalConstants.SOCIAL_AUTH_CODE_KEY + key); + } + + /** + * 是否存在key,如果对应key的value值已过期,也返回false + * + * @param key 缓存key + * @return true:存在key,并且value没过期;false:key不存在或者已过期 + */ + @Override + public boolean containsKey(String key) { + return RedisUtils.hasKey(GlobalConstants.SOCIAL_AUTH_CODE_KEY + key); + } +} diff --git a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/utils/SocialUtils.java b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/utils/SocialUtils.java new file mode 100644 index 0000000..04f6214 --- /dev/null +++ b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/utils/SocialUtils.java @@ -0,0 +1,73 @@ +package org.dromara.common.social.utils; + +import cn.hutool.core.util.ObjectUtil; +import me.zhyd.oauth.config.AuthConfig; +import me.zhyd.oauth.exception.AuthException; +import me.zhyd.oauth.model.AuthCallback; +import me.zhyd.oauth.model.AuthResponse; +import me.zhyd.oauth.model.AuthUser; +import me.zhyd.oauth.request.*; +import org.dromara.common.core.utils.SpringUtils; +import org.dromara.common.social.config.properties.SocialLoginConfigProperties; +import org.dromara.common.social.config.properties.SocialProperties; +import org.dromara.common.social.maxkey.AuthMaxKeyRequest; +import org.dromara.common.social.topiam.AuthTopIamRequest; + +/** + * 认证授权工具类 + * + * @author thiszhc + */ +public class SocialUtils { + + private static final AuthRedisStateCache STATE_CACHE = SpringUtils.getBean(AuthRedisStateCache.class); + + @SuppressWarnings("unchecked") + public static AuthResponse loginAuth(String source, String code, String state, SocialProperties socialProperties) throws AuthException { + AuthRequest authRequest = getAuthRequest(source, socialProperties); + AuthCallback callback = new AuthCallback(); + callback.setCode(code); + callback.setState(state); + return authRequest.login(callback); + } + + public static AuthRequest getAuthRequest(String source, SocialProperties socialProperties) throws AuthException { + SocialLoginConfigProperties obj = socialProperties.getType().get(source); + if (ObjectUtil.isNull(obj)) { + throw new AuthException("不支持的第三方登录类型"); + } + AuthConfig.AuthConfigBuilder builder = AuthConfig.builder() + .clientId(obj.getClientId()) + .clientSecret(obj.getClientSecret()) + .redirectUri(obj.getRedirectUri()) + .scopes(obj.getScopes()); + return switch (source.toLowerCase()) { + case "dingtalk" -> new AuthDingTalkRequest(builder.build(), STATE_CACHE); + case "baidu" -> new AuthBaiduRequest(builder.build(), STATE_CACHE); + case "github" -> new AuthGithubRequest(builder.build(), STATE_CACHE); + case "gitee" -> new AuthGiteeRequest(builder.build(), STATE_CACHE); + case "weibo" -> new AuthWeiboRequest(builder.build(), STATE_CACHE); + case "coding" -> new AuthCodingRequest(builder.build(), STATE_CACHE); + case "oschina" -> new AuthOschinaRequest(builder.build(), STATE_CACHE); + // 支付宝在创建回调地址时,不允许使用localhost或者127.0.0.1,所以这儿的回调地址使用的局域网内的ip + case "alipay_wallet" -> new AuthAlipayRequest(builder.build(), socialProperties.getType().get("alipay_wallet").getAlipayPublicKey(), STATE_CACHE); + case "qq" -> new AuthQqRequest(builder.build(), STATE_CACHE); + case "wechat_open" -> new AuthWeChatOpenRequest(builder.build(), STATE_CACHE); + case "taobao" -> new AuthTaobaoRequest(builder.build(), STATE_CACHE); + case "douyin" -> new AuthDouyinRequest(builder.build(), STATE_CACHE); + case "linkedin" -> new AuthLinkedinRequest(builder.build(), STATE_CACHE); + case "microsoft" -> new AuthMicrosoftRequest(builder.build(), STATE_CACHE); + case "renren" -> new AuthRenrenRequest(builder.build(), STATE_CACHE); + case "stack_overflow" -> new AuthStackOverflowRequest(builder.stackOverflowKey("").build(), STATE_CACHE); + case "huawei" -> new AuthHuaweiRequest(builder.build(), STATE_CACHE); + case "wechat_enterprise" -> new AuthWeChatEnterpriseQrcodeRequest(builder.agentId("").build(), STATE_CACHE); + case "gitlab" -> new AuthGitlabRequest(builder.build(), STATE_CACHE); + case "wechat_mp" -> new AuthWeChatMpRequest(builder.build(), STATE_CACHE); + case "aliyun" -> new AuthAliyunRequest(builder.build(), STATE_CACHE); + case "maxkey" -> new AuthMaxKeyRequest(builder.build(), STATE_CACHE); + case "topiam" -> new AuthTopIamRequest(builder.build(), STATE_CACHE); + default -> throw new AuthException("未获取到有效的Auth配置"); + }; + } +} + diff --git a/ruoyi-common/ruoyi-common-social/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/ruoyi-common/ruoyi-common-social/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 0000000..fc544a0 --- /dev/null +++ b/ruoyi-common/ruoyi-common-social/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +org.dromara.common.social.config.SocialAutoConfiguration diff --git a/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/config/TenantConfig.java b/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/config/TenantConfig.java index 3fb99c5..07302bc 100644 --- a/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/config/TenantConfig.java +++ b/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/config/TenantConfig.java @@ -35,7 +35,7 @@ public class TenantConfig { @ConditionalOnBean(MybatisPlusConfig.class) @AutoConfiguration(after = {MybatisPlusConfig.class}) - static class MybatisPlusConfigation { + static class MybatisPlusConfiguration { /** * 多租户插件 diff --git a/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/helper/TenantHelper.java b/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/helper/TenantHelper.java index e830c19..9d087e1 100644 --- a/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/helper/TenantHelper.java +++ b/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/helper/TenantHelper.java @@ -1,6 +1,5 @@ package org.dromara.common.tenant.helper; -import cn.dev33.satoken.context.SaHolder; import cn.dev33.satoken.stp.StpUtil; import cn.hutool.core.convert.Convert; import com.alibaba.ttl.TransmittableThreadLocal; @@ -79,22 +78,28 @@ public class TenantHelper { } } + public static void setDynamic(String tenantId) { + setDynamic(tenantId, false); + } + /** * 设置动态租户(一直有效 需要手动清理) *

* 如果为未登录状态下 那么只在当前线程内生效 + * + * @param tenantId 租户id + * @param global 是否全局生效 */ - public static void setDynamic(String tenantId) { + public static void setDynamic(String tenantId, boolean global) { if (!isEnable()) { return; } - if (!isLogin()) { + if (!isLogin() || !global) { TEMP_DYNAMIC_TENANT.set(tenantId); return; } String cacheKey = DYNAMIC_TENANT_KEY + ":" + LoginHelper.getUserId(); RedisUtils.setCacheObject(cacheKey, tenantId); - SaHolder.getStorage().set(cacheKey, tenantId); } /** @@ -109,13 +114,13 @@ public class TenantHelper { if (!isLogin()) { return TEMP_DYNAMIC_TENANT.get(); } - String cacheKey = DYNAMIC_TENANT_KEY + ":" + LoginHelper.getUserId(); - String tenantId = (String) SaHolder.getStorage().get(cacheKey); + // 如果线程内有值 优先返回 + String tenantId = TEMP_DYNAMIC_TENANT.get(); if (StringUtils.isNotBlank(tenantId)) { return tenantId; } + String cacheKey = DYNAMIC_TENANT_KEY + ":" + LoginHelper.getUserId(); tenantId = RedisUtils.getCacheObject(cacheKey); - SaHolder.getStorage().set(cacheKey, tenantId); return tenantId; } @@ -130,9 +135,9 @@ public class TenantHelper { TEMP_DYNAMIC_TENANT.remove(); return; } + TEMP_DYNAMIC_TENANT.remove(); String cacheKey = DYNAMIC_TENANT_KEY + ":" + LoginHelper.getUserId(); RedisUtils.deleteObject(cacheKey); - SaHolder.getStorage().delete(cacheKey); } /** diff --git a/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/config/UndertowConfig.java b/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/config/UndertowConfig.java index 0f78928..ac50dd2 100644 --- a/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/config/UndertowConfig.java +++ b/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/config/UndertowConfig.java @@ -16,15 +16,11 @@ import org.springframework.core.task.VirtualThreadTaskExecutor; @AutoConfiguration public class UndertowConfig implements WebServerFactoryCustomizer { - /** - * 设置 Undertow 的 websocket 缓冲池 - */ @Override public void customize(UndertowServletWebServerFactory factory) { - // 默认不直接分配内存 如果项目中使用了 websocket 建议直接分配 factory.addDeploymentInfoCustomizers(deploymentInfo -> { WebSocketDeploymentInfo webSocketDeploymentInfo = new WebSocketDeploymentInfo(); - webSocketDeploymentInfo.setBuffers(new DefaultByteBufferPool(false, 512)); + webSocketDeploymentInfo.setBuffers(new DefaultByteBufferPool(true, 1024)); deploymentInfo.addServletContextAttribute("io.undertow.websockets.jsr.WebSocketDeploymentInfo", webSocketDeploymentInfo); // 使用虚拟线程 if (SpringUtils.isVirtual()) { diff --git a/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/config/WebSocketConfig.java b/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/config/WebSocketConfig.java index 30d109e..ef5cfc9 100644 --- a/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/config/WebSocketConfig.java +++ b/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/config/WebSocketConfig.java @@ -27,17 +27,20 @@ public class WebSocketConfig { @Bean public WebSocketConfigurer webSocketConfigurer(HandshakeInterceptor handshakeInterceptor, - WebSocketHandler webSocketHandler, - WebSocketProperties webSocketProperties) { + WebSocketHandler webSocketHandler, WebSocketProperties webSocketProperties) { + // 如果WebSocket的路径为空,则设置默认路径为 "/websocket" if (StrUtil.isBlank(webSocketProperties.getPath())) { webSocketProperties.setPath("/websocket"); } + // 如果允许跨域访问的地址为空,则设置为 "*",表示允许所有来源的跨域请求 if (StrUtil.isBlank(webSocketProperties.getAllowedOrigins())) { webSocketProperties.setAllowedOrigins("*"); } + // 返回一个WebSocketConfigurer对象,用于配置WebSocket return registry -> registry + // 添加WebSocket处理程序和拦截器到指定路径,设置允许的跨域来源 .addHandler(webSocketHandler, webSocketProperties.getPath()) .addInterceptors(handshakeInterceptor) .setAllowedOrigins(webSocketProperties.getAllowedOrigins()); diff --git a/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/constant/WebSocketConstants.java b/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/constant/WebSocketConstants.java index 54eb447..e243279 100644 --- a/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/constant/WebSocketConstants.java +++ b/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/constant/WebSocketConstants.java @@ -6,6 +6,7 @@ package org.dromara.common.websocket.constant; * @author zendwang */ public interface WebSocketConstants { + /** * websocketSession中的参数的key */ diff --git a/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/handler/PlusWebSocketHandler.java b/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/handler/PlusWebSocketHandler.java index a53583f..8b1cc5d 100644 --- a/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/handler/PlusWebSocketHandler.java +++ b/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/handler/PlusWebSocketHandler.java @@ -1,5 +1,6 @@ package org.dromara.common.websocket.handler; +import cn.hutool.core.util.ObjectUtil; import lombok.extern.slf4j.Slf4j; import org.dromara.common.core.domain.model.LoginUser; import org.dromara.common.websocket.dto.WebSocketMessageDto; @@ -8,6 +9,7 @@ import org.dromara.common.websocket.utils.WebSocketUtils; import org.springframework.web.socket.*; import org.springframework.web.socket.handler.AbstractWebSocketHandler; +import java.io.IOException; import java.util.List; import static org.dromara.common.websocket.constant.WebSocketConstants.LOGIN_USER_KEY; @@ -24,40 +26,54 @@ public class PlusWebSocketHandler extends AbstractWebSocketHandler { * 连接成功后 */ @Override - public void afterConnectionEstablished(WebSocketSession session) { + public void afterConnectionEstablished(WebSocketSession session) throws IOException { LoginUser loginUser = (LoginUser) session.getAttributes().get(LOGIN_USER_KEY); + if (ObjectUtil.isNull(loginUser)) { + session.close(CloseStatus.BAD_DATA); + log.info("[connect] invalid token received. sessionId: {}", session.getId()); + return; + } WebSocketSessionHolder.addSession(loginUser.getUserId(), session); log.info("[connect] sessionId: {},userId:{},userType:{}", session.getId(), loginUser.getUserId(), loginUser.getUserType()); } /** - * 处理发送来的文本消息 + * 处理接收到的文本消息 * - * @param session - * @param message - * @throws Exception + * @param session WebSocket会话 + * @param message 接收到的文本消息 + * @throws Exception 处理消息过程中可能抛出的异常 */ @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { + // 从WebSocket会话中获取登录用户信息 LoginUser loginUser = (LoginUser) session.getAttributes().get(LOGIN_USER_KEY); - List userIds = List.of(loginUser.getUserId()); + + // 创建WebSocket消息DTO对象 WebSocketMessageDto webSocketMessageDto = new WebSocketMessageDto(); - webSocketMessageDto.setSessionKeys(userIds); + webSocketMessageDto.setSessionKeys(List.of(loginUser.getUserId())); webSocketMessageDto.setMessage(message.getPayload()); WebSocketUtils.publishMessage(webSocketMessageDto); } + /** + * 处理接收到的二进制消息 + * + * @param session WebSocket会话 + * @param message 接收到的二进制消息 + * @throws Exception 处理消息过程中可能抛出的异常 + */ @Override protected void handleBinaryMessage(WebSocketSession session, BinaryMessage message) throws Exception { super.handleBinaryMessage(session, message); } /** - * 心跳监测的回复 + * 处理接收到的Pong消息(心跳监测) * - * @param session - * @param message - * @throws Exception + * @param session WebSocket会话 + * @param message 接收到的Pong消息 + * @throws Exception 处理消息过程中可能抛出的异常 */ @Override protected void handlePongMessage(WebSocketSession session, PongMessage message) throws Exception { @@ -65,11 +81,11 @@ public class PlusWebSocketHandler extends AbstractWebSocketHandler { } /** - * 连接出错时 + * 处理WebSocket传输错误 * - * @param session - * @param exception - * @throws Exception + * @param session WebSocket会话 + * @param exception 发生的异常 + * @throws Exception 处理过程中可能抛出的异常 */ @Override public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception { @@ -77,22 +93,26 @@ public class PlusWebSocketHandler extends AbstractWebSocketHandler { } /** - * 连接关闭后 + * 在WebSocket连接关闭后执行清理操作 * - * @param session - * @param status + * @param session WebSocket会话 + * @param status 关闭状态信息 */ @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus status) { LoginUser loginUser = (LoginUser) session.getAttributes().get(LOGIN_USER_KEY); + if (ObjectUtil.isNull(loginUser)) { + log.info("[disconnect] invalid token received. sessionId: {}", session.getId()); + return; + } WebSocketSessionHolder.removeSession(loginUser.getUserId()); log.info("[disconnect] sessionId: {},userId:{},userType:{}", session.getId(), loginUser.getUserId(), loginUser.getUserType()); } /** - * 是否支持分片消息 + * 指示处理程序是否支持接收部分消息 * - * @return + * @return 如果支持接收部分消息,则返回true;否则返回false */ @Override public boolean supportsPartialMessages() { diff --git a/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/holder/WebSocketSessionHolder.java b/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/holder/WebSocketSessionHolder.java index de8c5a7..368801c 100644 --- a/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/holder/WebSocketSessionHolder.java +++ b/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/holder/WebSocketSessionHolder.java @@ -18,24 +18,52 @@ public class WebSocketSessionHolder { private static final Map USER_SESSION_MAP = new ConcurrentHashMap<>(); + /** + * 将WebSocket会话添加到用户会话Map中 + * + * @param sessionKey 会话键,用于检索会话 + * @param session 要添加的WebSocket会话 + */ public static void addSession(Long sessionKey, WebSocketSession session) { USER_SESSION_MAP.put(sessionKey, session); } + /** + * 从用户会话Map中移除指定会话键对应的WebSocket会话 + * + * @param sessionKey 要移除的会话键 + */ public static void removeSession(Long sessionKey) { if (USER_SESSION_MAP.containsKey(sessionKey)) { USER_SESSION_MAP.remove(sessionKey); } } + /** + * 根据会话键从用户会话Map中获取WebSocket会话 + * + * @param sessionKey 要获取的会话键 + * @return 与给定会话键对应的WebSocket会话,如果不存在则返回null + */ public static WebSocketSession getSessions(Long sessionKey) { return USER_SESSION_MAP.get(sessionKey); } + /** + * 获取存储在用户会话Map中所有WebSocket会话的会话键集合 + * + * @return 所有WebSocket会话的会话键集合 + */ public static Set getSessionsAll() { return USER_SESSION_MAP.keySet(); } + /** + * 检查给定的会话键是否存在于用户会话Map中 + * + * @param sessionKey 要检查的会话键 + * @return 如果存在对应的会话键,则返回true;否则返回false + */ public static Boolean existSession(Long sessionKey) { return USER_SESSION_MAP.containsKey(sessionKey); } diff --git a/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/interceptor/PlusWebSocketInterceptor.java b/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/interceptor/PlusWebSocketInterceptor.java index 1dc4120..c70e377 100644 --- a/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/interceptor/PlusWebSocketInterceptor.java +++ b/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/interceptor/PlusWebSocketInterceptor.java @@ -1,8 +1,12 @@ package org.dromara.common.websocket.interceptor; -import org.dromara.common.core.domain.model.LoginUser; -import org.dromara.common.satoken.utils.LoginHelper; +import cn.dev33.satoken.exception.NotLoginException; +import cn.dev33.satoken.stp.StpUtil; import lombok.extern.slf4j.Slf4j; +import org.dromara.common.core.domain.model.LoginUser; +import org.dromara.common.core.utils.ServletUtils; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.satoken.utils.LoginHelper; import org.springframework.http.server.ServerHttpRequest; import org.springframework.http.server.ServerHttpResponse; import org.springframework.web.socket.WebSocketHandler; @@ -21,31 +25,51 @@ import static org.dromara.common.websocket.constant.WebSocketConstants.LOGIN_USE public class PlusWebSocketInterceptor implements HandshakeInterceptor { /** - * 握手前 + * WebSocket握手之前执行的前置处理方法 * - * @param request request - * @param response response - * @param wsHandler wsHandler - * @param attributes attributes - * @return 是否握手成功 + * @param request WebSocket握手请求 + * @param response WebSocket握手响应 + * @param wsHandler WebSocket处理程序 + * @param attributes 与WebSocket会话关联的属性 + * @return 如果允许握手继续进行,则返回true;否则返回false */ @Override public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map attributes) { - LoginUser loginUser = LoginHelper.getLoginUser(); - attributes.put(LOGIN_USER_KEY, loginUser); - return true; + try { + // 检查是否登录 是否有token + LoginUser loginUser = LoginHelper.getLoginUser(); + + // 解决 ws 不走 mvc 拦截器问题(cloud 版本不受影响) + // 检查 header 与 param 里的 clientid 与 token 里的是否一致 + String headerCid = ServletUtils.getRequest().getHeader(LoginHelper.CLIENT_KEY); + String paramCid = ServletUtils.getParameter(LoginHelper.CLIENT_KEY); + String clientId = StpUtil.getExtra(LoginHelper.CLIENT_KEY).toString(); + if (!StringUtils.equalsAny(clientId, headerCid, paramCid)) { + // token 无效 + throw NotLoginException.newInstance(StpUtil.getLoginType(), + "-100", "客户端ID与Token不匹配", + StpUtil.getTokenValue()); + } + + attributes.put(LOGIN_USER_KEY, loginUser); + return true; + } catch (NotLoginException e) { + log.error("WebSocket 认证失败'{}',无法访问系统资源", e.getMessage()); + return false; + } } /** - * 握手后 + * WebSocket握手成功后执行的后置处理方法 * - * @param request request - * @param response response - * @param wsHandler wsHandler - * @param exception 异常 + * @param request WebSocket握手请求 + * @param response WebSocket握手响应 + * @param wsHandler WebSocket处理程序 + * @param exception 握手过程中可能出现的异常 */ @Override public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) { - + // 在这个方法中可以执行一些握手成功后的后续处理逻辑,比如记录日志或者其他操作 } + } diff --git a/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/listener/WebSocketTopicListener.java b/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/listener/WebSocketTopicListener.java index 01528d0..0ad39af 100644 --- a/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/listener/WebSocketTopicListener.java +++ b/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/listener/WebSocketTopicListener.java @@ -1,9 +1,9 @@ package org.dromara.common.websocket.listener; import cn.hutool.core.collection.CollUtil; +import lombok.extern.slf4j.Slf4j; import org.dromara.common.websocket.holder.WebSocketSessionHolder; import org.dromara.common.websocket.utils.WebSocketUtils; -import lombok.extern.slf4j.Slf4j; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.core.Ordered; @@ -16,8 +16,15 @@ import org.springframework.core.Ordered; @Slf4j public class WebSocketTopicListener implements ApplicationRunner, Ordered { + /** + * 在Spring Boot应用程序启动时初始化WebSocket主题订阅监听器 + * + * @param args 应用程序参数 + * @throws Exception 初始化过程中可能抛出的异常 + */ @Override public void run(ApplicationArguments args) throws Exception { + // 订阅WebSocket消息 WebSocketUtils.subscribeMessage((message) -> { log.info("WebSocket主题订阅收到消息session keys={} message={}", message.getSessionKeys(), message.getMessage()); // 如果key不为空就按照key发消息 如果为空就群发 diff --git a/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/utils/WebSocketUtils.java b/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/utils/WebSocketUtils.java index 086599c..afe76e0 100644 --- a/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/utils/WebSocketUtils.java +++ b/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/utils/WebSocketUtils.java @@ -29,10 +29,10 @@ import static org.dromara.common.websocket.constant.WebSocketConstants.WEB_SOCKE public class WebSocketUtils { /** - * 发送消息 + * 向指定的WebSocket会话发送消息 * - * @param sessionKey session主键 一般为用户id - * @param message 消息文本 + * @param sessionKey 要发送消息的用户id + * @param message 要发送的消息内容 */ public static void sendMessage(Long sessionKey, String message) { WebSocketSession session = WebSocketSessionHolder.getSessions(sessionKey); @@ -40,18 +40,18 @@ public class WebSocketUtils { } /** - * 订阅消息 + * 订阅WebSocket消息主题,并提供一个消费者函数来处理接收到的消息 * - * @param consumer 自定义处理 + * @param consumer 处理WebSocket消息的消费者函数 */ public static void subscribeMessage(Consumer consumer) { RedisUtils.subscribe(WEB_SOCKET_TOPIC, WebSocketMessageDto.class, consumer); } /** - * 发布订阅的消息 + * 发布WebSocket订阅消息 * - * @param webSocketMessage 消息对象 + * @param webSocketMessage 要发布的WebSocket消息对象 */ public static void publishMessage(WebSocketMessageDto webSocketMessage) { List unsentSessionKeys = new ArrayList<>(); @@ -76,9 +76,9 @@ public class WebSocketUtils { } /** - * 发布订阅的消息(群发) + * 向所有的WebSocket会话发布订阅的消息(群发) * - * @param message 消息内容 + * @param message 要发布的消息内容 */ public static void publishAll(String message) { WebSocketMessageDto broadcastMessage = new WebSocketMessageDto(); @@ -88,14 +88,31 @@ public class WebSocketUtils { }); } + /** + * 向指定的WebSocket会话发送Pong消息 + * + * @param session 要发送Pong消息的WebSocket会话 + */ public static void sendPongMessage(WebSocketSession session) { sendMessage(session, new PongMessage()); } + /** + * 向指定的WebSocket会话发送文本消息 + * + * @param session WebSocket会话 + * @param message 要发送的文本消息内容 + */ public static void sendMessage(WebSocketSession session, String message) { sendMessage(session, new TextMessage(message)); } + /** + * 向指定的WebSocket会话发送WebSocket消息对象 + * + * @param session WebSocket会话 + * @param message 要发送的WebSocket消息对象 + */ private static void sendMessage(WebSocketSession session, WebSocketMessage message) { if (session == null || !session.isOpen()) { log.warn("[send] session会话已经关闭"); diff --git a/ruoyi-extend/ruoyi-monitor-admin/Dockerfile b/ruoyi-extend/ruoyi-monitor-admin/Dockerfile index a54f816..99aaa74 100644 --- a/ruoyi-extend/ruoyi-monitor-admin/Dockerfile +++ b/ruoyi-extend/ruoyi-monitor-admin/Dockerfile @@ -1,7 +1,9 @@ +# 贝尔实验室 Spring 官方推荐镜像 JDK下载地址 https://bell-sw.com/pages/downloads/ +FROM bellsoft/liberica-openjdk-debian:17.0.11-cds +#FROM bellsoft/liberica-openjdk-debian:21.0.3-cds #FROM findepi/graalvm:java17-native -FROM openjdk:17.0.2-oraclelinux8 -MAINTAINER Lion Li +LABEL maintainer="Lion Li" RUN mkdir -p /ruoyi/monitor/logs diff --git a/ruoyi-extend/ruoyi-monitor-admin/src/main/resources/application.yml b/ruoyi-extend/ruoyi-monitor-admin/src/main/resources/application.yml index e0b53e2..1b729ef 100644 --- a/ruoyi-extend/ruoyi-monitor-admin/src/main/resources/application.yml +++ b/ruoyi-extend/ruoyi-monitor-admin/src/main/resources/application.yml @@ -14,7 +14,7 @@ spring: security: user: name: ruoyi - password: Mz123456! + password: 123456 boot: admin: ui: @@ -42,4 +42,4 @@ spring.boot.admin.client: instance: service-host-type: IP username: ruoyi - password: Mz123456! + password: 123456 diff --git a/ruoyi-extend/ruoyi-snailjob-server/Dockerfile b/ruoyi-extend/ruoyi-snailjob-server/Dockerfile index 1fda8db..a66ca66 100644 --- a/ruoyi-extend/ruoyi-snailjob-server/Dockerfile +++ b/ruoyi-extend/ruoyi-snailjob-server/Dockerfile @@ -1,7 +1,9 @@ +# 贝尔实验室 Spring 官方推荐镜像 JDK下载地址 https://bell-sw.com/pages/downloads/ +FROM bellsoft/liberica-openjdk-debian:17.0.11-cds +#FROM bellsoft/liberica-openjdk-debian:21.0.3-cds #FROM findepi/graalvm:java17-native -FROM openjdk:17.0.2-oraclelinux8 -MAINTAINER Lion Li +LABEL maintainer="Lion Li" RUN mkdir -p /ruoyi/snailjob/logs @@ -10,7 +12,7 @@ WORKDIR /ruoyi/snailjob ENV LANG=C.UTF-8 LC_ALL=C.UTF-8 JAVA_OPTS="-Xms512m -Xmx1024m" EXPOSE 8800 -EXPOSE 1788 +EXPOSE 17888 ADD ./target/ruoyi-snailjob-server.jar ./app.jar diff --git a/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/application-dev.yml b/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/application-dev.yml index 66bbeea..3c65077 100644 --- a/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/application-dev.yml +++ b/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/application-dev.yml @@ -21,7 +21,7 @@ snail-job: # 拉取重试数据的每批次的大小 job-pull-page-size: 1000 # 服务端netty端口 - netty-port: 1788 + netty-port: 17888 # 一个客户端每秒最多接收的重试数量指令 limiter: 1000 # 号段模式下步长配置 @@ -44,4 +44,4 @@ spring.boot.admin.client: instance: service-host-type: IP username: ruoyi - password: Mz123456! + password: 123456 diff --git a/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/application-prod.yml b/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/application-prod.yml index 719fd6d..37ab887 100644 --- a/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/application-prod.yml +++ b/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/application-prod.yml @@ -21,7 +21,7 @@ snail-job: # 拉取重试数据的每批次的大小 job-pull-page-size: 1000 # 服务端 netty 端口 - netty-port: 1788 + netty-port: 17888 # 一个客户端每秒最多接收的重试数量指令 limiter: 1000 # 号段模式下步长配置 @@ -44,4 +44,4 @@ spring.boot.admin.client: instance: service-host-type: IP username: ruoyi - password: Mz123456! + password: 123456 diff --git a/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java index d418815..02a9fa7 100644 --- a/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java +++ b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java @@ -165,7 +165,7 @@ public class GenTableServiceImpl implements IGenTableService { @Override public void deleteGenTableByIds(Long[] tableIds) { List ids = Arrays.asList(tableIds); - baseMapper.deleteBatchIds(ids); + baseMapper.deleteByIds(ids); genTableColumnMapper.delete(new LambdaQueryWrapper().in(GenTableColumn::getTableId, ids)); } @@ -332,7 +332,7 @@ public class GenTableServiceImpl implements IGenTableService { if (CollUtil.isNotEmpty(delColumns)) { List ids = StreamUtils.toList(delColumns, GenTableColumn::getColumnId); if (CollUtil.isNotEmpty(ids)) { - genTableColumnMapper.deleteBatchIds(ids); + genTableColumnMapper.deleteByIds(ids); } } } diff --git a/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm index e7236fd..67690ca 100644 --- a/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm +++ b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm @@ -149,6 +149,6 @@ public class ${ClassName}ServiceImpl implements I${ClassName}Service { if(isValid){ //TODO 做一些业务上的校验,判断是否需要校验 } - return baseMapper.deleteBatchIds(ids) > 0; + return baseMapper.deleteByIds(ids) > 0; } } diff --git a/ruoyi-modules/ruoyi-system/pom.xml b/ruoyi-modules/ruoyi-system/pom.xml index 3ae509b..acf33ce 100644 --- a/ruoyi-modules/ruoyi-system/pom.xml +++ b/ruoyi-modules/ruoyi-system/pom.xml @@ -95,23 +95,6 @@ ruoyi-common-websocket - - - - - - - - - - - - - - - - - diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysDeptController.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysDeptController.java index 98b76e4..4f5f23f 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysDeptController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysDeptController.java @@ -75,8 +75,6 @@ public class SysDeptController extends BaseController { public R add(@Validated @RequestBody SysDeptBo dept) { if (!deptService.checkDeptNameUnique(dept)) { return R.fail("新增部门'" + dept.getDeptName() + "'失败,部门名称已存在"); - } else if (StringUtils.isNotBlank(dept.getDeptCategory()) && !deptService.checkDeptCategoryUnique(dept)) { - return R.fail("新增部门'" + dept.getDeptName() + "'失败,部门类别编码已存在"); } return toAjax(deptService.insertDept(dept)); } @@ -92,8 +90,6 @@ public class SysDeptController extends BaseController { deptService.checkDeptDataScope(deptId); if (!deptService.checkDeptNameUnique(dept)) { return R.fail("修改部门'" + dept.getDeptName() + "'失败,部门名称已存在"); - } else if (StringUtils.isNotBlank(dept.getDeptCategory()) && !deptService.checkDeptCategoryUnique(dept)) { - return R.fail("修改部门'" + dept.getDeptName() + "'失败,部门类别编码已存在"); } else if (dept.getParentId().equals(deptId)) { return R.fail("修改部门'" + dept.getDeptName() + "'失败,上级部门不能是自己"); } else if (StringUtils.equals(UserConstants.DEPT_DISABLE, dept.getStatus())) { diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysOssController.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysOssController.java index c04fc73..9b94116 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysOssController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysOssController.java @@ -125,7 +125,6 @@ public class SysOssController extends BaseController { @PathVariable Long[] ossIds) { return toAjax(ossService.deleteWithValidByIds(List.of(ossIds), true)); } - /** * 查询OSS对象基于md5 * @@ -149,5 +148,4 @@ public class SysOssController extends BaseController { SysOssVolumeVo oss = ossService.getVolumeVoByType(type); return R.ok(oss); } - } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysProfileController.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysProfileController.java index ad24f30..c82dd03 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysProfileController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysProfileController.java @@ -9,6 +9,7 @@ import org.dromara.common.core.utils.StringUtils; import org.dromara.common.core.utils.file.MimeTypeUtils; import org.dromara.common.core.utils.regex.RegexValidator; import org.dromara.common.encrypt.annotation.ApiEncrypt; +import org.dromara.common.idempotent.annotation.RepeatSubmit; import org.dromara.common.log.annotation.Log; import org.dromara.common.log.enums.BusinessType; import org.dromara.common.satoken.utils.LoginHelper; @@ -57,12 +58,14 @@ public class SysProfileController extends BaseController { } /** - * 修改用户 + * 修改用户信息 */ + @RepeatSubmit @Log(title = "个人信息", businessType = BusinessType.UPDATE) @PutMapping - public R updateProfile(@RequestBody SysUserProfileBo profile) { + public R updateProfile(@Validated @RequestBody SysUserProfileBo profile) { SysUserBo user = BeanUtil.toBean(profile, SysUserBo.class); + user.setUserId(LoginHelper.getUserId()); String username = LoginHelper.getUsername(); if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) { return R.fail("修改用户'" + username + "'失败,手机号码已存在"); @@ -70,7 +73,6 @@ public class SysProfileController extends BaseController { if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) { return R.fail("修改用户'" + username + "'失败,邮箱账号已存在"); } - user.setUserId(LoginHelper.getUserId()); if (userService.updateUserProfile(user) > 0) { return R.ok(); } @@ -82,11 +84,11 @@ public class SysProfileController extends BaseController { * * @param bo 新旧密码 */ + @RepeatSubmit @ApiEncrypt @Log(title = "个人信息", businessType = BusinessType.UPDATE) @PutMapping("/updatePwd") public R updatePwd(@Validated @RequestBody SysUserPasswordBo bo) { - String newPassword = bo.getNewPassword(); if (!RegexValidator.isPassword(newPassword)) { return R.fail("修改密码失败,新密码复杂度不合规"); @@ -111,6 +113,7 @@ public class SysProfileController extends BaseController { * * @param avatarfile 用户头像 */ + @RepeatSubmit @Log(title = "用户头像", businessType = BusinessType.UPDATE) @PostMapping(value = "/avatar", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) public R avatar(@RequestPart("avatarfile") MultipartFile avatarfile) { diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysTenantController.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysTenantController.java index d7bdbcc..60be68a 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysTenantController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysTenantController.java @@ -10,7 +10,6 @@ import jakarta.validation.constraints.NotNull; import lombok.RequiredArgsConstructor; import org.dromara.common.core.constant.TenantConstants; import org.dromara.common.core.domain.R; -import org.dromara.common.core.utils.regex.RegexValidator; import org.dromara.common.core.validate.AddGroup; import org.dromara.common.core.validate.EditGroup; import org.dromara.common.encrypt.annotation.ApiEncrypt; @@ -92,10 +91,6 @@ public class SysTenantController extends BaseController { if (!tenantService.checkCompanyNameUnique(bo)) { return R.fail("新增租户'" + bo.getCompanyName() + "'失败,企业名称已存在"); } - String password = bo.getPassword(); - if (!RegexValidator.isPassword(password)) { - return R.fail("密码复杂度不合规"); - } return toAjax(TenantHelper.ignore(() -> tenantService.insertByBo(bo))); } @@ -149,7 +144,7 @@ public class SysTenantController extends BaseController { @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY) @GetMapping("/dynamic/{tenantId}") public R dynamicTenant(@NotBlank(message = "租户ID不能为空") @PathVariable String tenantId) { - TenantHelper.setDynamic(tenantId); + TenantHelper.setDynamic(tenantId, true); return R.ok(); } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysUserController.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysUserController.java index dbe1b6a..e32f4f3 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysUserController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysUserController.java @@ -165,7 +165,7 @@ public class SysUserController extends BaseController { return R.fail("新增用户'" + user.getUserName() + "'失败,手机号码已存在"); } else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) { return R.fail("新增用户'" + user.getUserName() + "'失败,邮箱账号已存在"); - } else if (!RegexValidator.isPassword(password)) { + }else if (!RegexValidator.isPassword(password)) { return R.fail("新增用户'" + user.getUserName() + "'失败,密码复杂度不合规"); } if (TenantHelper.isEnable()) { @@ -173,7 +173,7 @@ public class SysUserController extends BaseController { return R.fail("当前租户下用户名额不足,请联系管理员"); } } - user.setPassword(BCrypt.hashpw(password)); + user.setPassword(BCrypt.hashpw(user.getPassword())); return toAjax(userService.insertUser(user)); } @@ -239,7 +239,7 @@ public class SysUserController extends BaseController { if (!RegexValidator.isPassword(password)) { return R.fail("密码复杂度不合规"); } - user.setPassword(BCrypt.hashpw(password)); + user.setPassword(BCrypt.hashpw(user.getPassword())); return toAjax(userService.resetUserPwd(user.getUserId(), user.getPassword())); } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysPost.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysPost.java index 2c985da..12b4987 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysPost.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysPost.java @@ -1,5 +1,6 @@ package org.dromara.system.domain; +import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import org.dromara.common.tenant.core.TenantEntity; @@ -20,7 +21,7 @@ public class SysPost extends TenantEntity { /** * 岗位序号 */ - @TableId(value = "post_id") + @TableId(value = "post_id",type = IdType.AUTO) private Long postId; /** diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysSocial.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysSocial.java index 10f2936..4bfe0bf 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysSocial.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysSocial.java @@ -1,5 +1,6 @@ package org.dromara.system.domain; +import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; @@ -24,7 +25,7 @@ public class SysSocial extends TenantEntity { /** * 主键 */ - @TableId(value = "id") + @TableId(value = "id",type = IdType.AUTO) private Long id; /** diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysTenant.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysTenant.java index aa67062..e38d7a0 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysTenant.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysTenant.java @@ -27,7 +27,7 @@ public class SysTenant extends BaseEntity { /** * id */ - @TableId(value = "id", type = IdType.AUTO) + @TableId(value = "id",type = IdType.AUTO) private Long id; /** diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysTenantPackage.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysTenantPackage.java index 1b1b1e8..b387632 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysTenantPackage.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysTenantPackage.java @@ -26,7 +26,7 @@ public class SysTenantPackage extends BaseEntity { /** * 租户套餐id */ - @TableId(value = "package_id", type = IdType.AUTO) + @TableId(value = "package_id",type = IdType.AUTO) private Long packageId; /** * 套餐名称 diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/OssFileBo.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/OssFileBo.java deleted file mode 100644 index cad825a..0000000 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/OssFileBo.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.dromara.system.domain.bo; - -import io.github.linpeilie.annotations.AutoMapper; -import io.github.linpeilie.annotations.AutoMappers; -import org.dromara.system.domain.SysOssResource; -import org.dromara.system.domain.SysOssTextbook; - -/** - *

TODO

- * - * @author cjw - * @version V1.0.0 - * @date 2024/6/3 16:45 - */ -@AutoMappers({ - @AutoMapper(target = SysOssResource.class, reverseConvertGenerate = false), - @AutoMapper(target = SysOssTextbook.class, reverseConvertGenerate = false) -}) -public class OssFileBo { - - /** - * - */ - private Long ossId; - - /** - * - */ - private Long catalogId; - - /** - * 1课件,2课堂,3作业,4试卷 - */ - private Integer type; -} diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysTenantBo.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysTenantBo.java index bd0b8e9..d86e799 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysTenantBo.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysTenantBo.java @@ -109,10 +109,11 @@ public class SysTenantBo extends BaseEntity { * 租户状态(0正常 1停用) */ private String status; + @NotNull(message = "我的空间总容量不能为空", groups = { AddGroup.class }) private Long personTotalVolume; + @NotNull(message = "学校资源总容量不能为空", groups = { AddGroup.class }) private Long schoolTotalVolume; - } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysUserBo.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysUserBo.java index 3681b19..7ad2759 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysUserBo.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysUserBo.java @@ -34,11 +34,6 @@ public class SysUserBo extends BaseEntity { */ private Long deptId; - /** - * 教职工ID - */ - private Long teacherId; - /** * 用户账号 */ diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysUserProfileBo.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysUserProfileBo.java index fb4c605..846dd79 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysUserProfileBo.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysUserProfileBo.java @@ -1,14 +1,16 @@ package org.dromara.system.domain.bo; -import org.dromara.common.core.xss.Xss; -import org.dromara.common.mybatis.core.domain.BaseEntity; -import org.dromara.common.sensitive.annotation.Sensitive; -import org.dromara.common.sensitive.core.SensitiveStrategy; import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.Pattern; import jakarta.validation.constraints.Size; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import org.dromara.common.core.constant.RegexConstants; +import org.dromara.common.core.xss.Xss; +import org.dromara.common.mybatis.core.domain.BaseEntity; +import org.dromara.common.sensitive.annotation.Sensitive; +import org.dromara.common.sensitive.core.SensitiveStrategy; /** * 个人信息业务处理 @@ -21,11 +23,6 @@ import lombok.NoArgsConstructor; @EqualsAndHashCode(callSuper = true) public class SysUserProfileBo extends BaseEntity { - /** - * 用户ID - */ - private Long userId; - /** * 用户昵称 */ @@ -44,6 +41,7 @@ public class SysUserProfileBo extends BaseEntity { /** * 手机号码 */ + @Pattern(regexp = RegexConstants.MOBILE, message = "手机号格式不正确") @Sensitive(strategy = SensitiveStrategy.PHONE) private String phonenumber; diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysOssUploadVo.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysOssUploadVo.java index cf87fdc..11e0ff8 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysOssUploadVo.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysOssUploadVo.java @@ -15,14 +15,14 @@ public class SysOssUploadVo { */ private String url; - /** - * 对象存储主键 - */ - private String ossId; - /** * 文件名 */ private String fileName; + /** + * 对象存储主键 + */ + private String ossId; + } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysOssVo.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysOssVo.java index 18b8b80..c8e6b93 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysOssVo.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysOssVo.java @@ -67,7 +67,7 @@ public class SysOssVo implements Serializable { /** * 上传人名称 */ - @Translation(type = TransConstant.USER_ID_TO_NAME, mapper = "createBy") + @Translation(type = TransConstant.USER_ID_TO_NICKNAME, mapper = "createBy") private String createByName; /** diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysTenantVo.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysTenantVo.java index f058015..6a45315 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysTenantVo.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysTenantVo.java @@ -1,16 +1,16 @@ package org.dromara.system.domain.vo; +import java.util.Date; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelProperty; -import io.github.linpeilie.annotations.AutoMapper; -import lombok.Data; import org.dromara.common.excel.annotation.ExcelDictFormat; import org.dromara.common.excel.convert.ExcelDictConvert; import org.dromara.system.domain.SysTenant; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; import java.io.Serial; import java.io.Serializable; -import java.util.Date; /** @@ -111,7 +111,5 @@ public class SysTenantVo implements Serializable { @ExcelDictFormat(readConverterExp = "0=正常,1=停用") private String status; - private Date createTime; - } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysUserVo.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysUserVo.java index 7589376..d1f4059 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysUserVo.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysUserVo.java @@ -43,11 +43,6 @@ public class SysUserVo implements Serializable { */ private Long deptId; - /** - * 教职工ID - */ - private Long teacherId; - /** * 用户账号 */ diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysMenuMapper.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysMenuMapper.java index b2be0e9..ac646c0 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysMenuMapper.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysMenuMapper.java @@ -18,13 +18,6 @@ import java.util.List; */ public interface SysMenuMapper extends BaseMapperPlus { - /** - * 根据用户所有权限 - * - * @return 权限列表 - */ - List selectMenuPerms(); - /** * 根据用户查询系统菜单列表 * diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysDeptService.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysDeptService.java index 1bacec4..0bd0a28 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysDeptService.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysDeptService.java @@ -93,14 +93,6 @@ public interface ISysDeptService { */ boolean checkDeptNameUnique(SysDeptBo dept); - /** - * 校验部门类别编码是否唯一 - * - * @param dept 部门信息 - * @return 结果 - */ - boolean checkDeptCategoryUnique(SysDeptBo dept); - /** * 校验部门是否有数据权限 * @@ -132,12 +124,5 @@ public interface ISysDeptService { */ int deleteDeptById(Long deptId); - - - /** - * 查询所有部门信息 - * - * @return 部门信息 - */ List selectAllDept(); } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysOssService.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysOssService.java index fd9a313..7c894e3 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysOssService.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysOssService.java @@ -1,10 +1,10 @@ package org.dromara.system.service; -import jakarta.servlet.http.HttpServletResponse; import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.system.domain.bo.SysOssBo; import org.dromara.system.domain.vo.SysOssVo; +import jakarta.servlet.http.HttpServletResponse; import org.dromara.system.domain.vo.SysOssVolumeVo; import org.springframework.web.multipart.MultipartFile; @@ -45,15 +45,6 @@ public interface ISysOssService { */ SysOssVo getById(Long ossId); - - /** - * 根据 ossId 从缓存或数据库中获取Url - * - * @param ossId 文件在数据库中的唯一标识 - * @return url 对象链接 - */ - String getUrlById(Long ossId); - /** * 上传 MultipartFile 到对象存储服务,并保存文件信息到数据库 * @@ -87,19 +78,13 @@ public interface ISysOssService { */ Boolean deleteWithValidByIds(Collection ids, Boolean isValid); + String getUrlById(Long ossId); - /** - * 根据 md5 从缓存或数据库中获取 SysOssVo 对象 - * - * @param md5 文件在数据库中的唯一标识 - * @return SysOssVo 对象,包含文件信息 - */ SysOssVo getByMd5(String md5); SysOssVolumeVo getVolumeVoByType(Integer type); - Boolean increase(int type ,Long use); - - Boolean decrease(int type ,Long use); + Boolean increase(int type, Long use); + Boolean decrease(int type, Long use); } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysClientServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysClientServiceImpl.java index 26bc491..1c69243 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysClientServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysClientServiceImpl.java @@ -146,6 +146,6 @@ public class SysClientServiceImpl implements ISysClientService { if (isValid) { //TODO 做一些业务上的校验,判断是否需要校验 } - return baseMapper.deleteBatchIds(ids) > 0; + return baseMapper.deleteByIds(ids) > 0; } } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysConfigServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysConfigServiceImpl.java index bebfdad..46526bd 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysConfigServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysConfigServiceImpl.java @@ -178,7 +178,7 @@ public class SysConfigServiceImpl implements ISysConfigService, ConfigService { } CacheUtils.evict(CacheNames.SYS_CONFIG, config.getConfigKey()); } - baseMapper.deleteBatchIds(Arrays.asList(configIds)); + baseMapper.deleteByIds(Arrays.asList(configIds)); } /** diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDataScopeServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDataScopeServiceImpl.java index d7ba934..a31c426 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDataScopeServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDataScopeServiceImpl.java @@ -3,14 +3,14 @@ package org.dromara.system.service.impl; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.convert.Convert; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import org.dromara.system.domain.SysDept; -import org.dromara.common.mybatis.helper.DataBaseHelper; +import lombok.RequiredArgsConstructor; import org.dromara.common.core.utils.StreamUtils; +import org.dromara.common.mybatis.helper.DataBaseHelper; +import org.dromara.system.domain.SysDept; import org.dromara.system.domain.SysRoleDept; import org.dromara.system.mapper.SysDeptMapper; import org.dromara.system.mapper.SysRoleDeptMapper; import org.dromara.system.service.ISysDataScopeService; -import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import java.util.List; @@ -30,6 +30,12 @@ public class SysDataScopeServiceImpl implements ISysDataScopeService { private final SysRoleDeptMapper roleDeptMapper; private final SysDeptMapper deptMapper; + /** + * 获取角色自定义权限 + * + * @param roleId 角色Id + * @return 部门Id组 + */ @Override public String getRoleCustom(Long roleId) { List list = roleDeptMapper.selectList( @@ -42,6 +48,12 @@ public class SysDataScopeServiceImpl implements ISysDataScopeService { return null; } + /** + * 获取部门及以下权限 + * + * @param deptId 部门Id + * @return 部门Id组 + */ @Override public String getDeptAndChild(Long deptId) { List deptList = deptMapper.selectList(new LambdaQueryWrapper() diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDeptServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDeptServiceImpl.java index 485995f..a11e4c8 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDeptServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDeptServiceImpl.java @@ -167,6 +167,12 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService { return String.join(StringUtils.SEPARATOR, list); } + /** + * 通过部门名称查询租户部门Id + * + * @param deptName 部门名称 + * @return 部门ID + */ @Override public Long selectDeptIdByName(String deptName) { List deptList = SpringUtils.getAopProxy(this).selectAllDept(); @@ -232,20 +238,6 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService { return !exist; } - /** - * 校验部门类别编码是否唯一 - * - * @param dept 部门信息 - * @return 结果 - */ - @Override - public boolean checkDeptCategoryUnique(SysDeptBo dept) { - boolean exist = baseMapper.exists(new LambdaQueryWrapper() - .eq(SysDept::getDeptCategory, dept.getDeptCategory()) - .ne(ObjectUtil.isNotNull(dept.getDeptId()), SysDept::getDeptId, dept.getDeptId())); - return !exist; - } - /** * 校验部门是否有数据权限 * @@ -288,7 +280,6 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService { * @param bo 部门信息 * @return 结果 */ - @Caching(evict = { @CacheEvict(cacheNames = CacheNames.SYS_DEPT, key = "#bo.deptId"), @CacheEvict(cacheNames = CacheNames.SYS_TENANT_DEPT, allEntries = true) @@ -369,10 +360,10 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService { return baseMapper.deleteById(deptId); } + @Cacheable(cacheNames = CacheNames.SYS_TENANT_DEPT) @Override public List selectAllDept() { return baseMapper.selectList(); } - } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDictTypeServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDictTypeServiceImpl.java index bc6663f..1be0b7f 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDictTypeServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDictTypeServiceImpl.java @@ -141,7 +141,7 @@ public class SysDictTypeServiceImpl implements ISysDictTypeService, DictService } CacheUtils.evict(CacheNames.SYS_DICT, dictType.getDictType()); } - baseMapper.deleteBatchIds(Arrays.asList(dictIds)); + baseMapper.deleteByIds(Arrays.asList(dictIds)); } /** diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysLogininforServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysLogininforServiceImpl.java index 9c930a0..b95baf4 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysLogininforServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysLogininforServiceImpl.java @@ -163,7 +163,7 @@ public class SysLogininforServiceImpl implements ISysLogininforService { */ @Override public int deleteLogininforByIds(Long[] infoIds) { - return baseMapper.deleteBatchIds(Arrays.asList(infoIds)); + return baseMapper.deleteByIds(Arrays.asList(infoIds)); } /** diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysMenuServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysMenuServiceImpl.java index 6e1765b..af844c9 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysMenuServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysMenuServiceImpl.java @@ -75,7 +75,7 @@ public class SysMenuServiceImpl implements ISysMenuService { .orderByAsc(SysMenu::getOrderNum)); } else { QueryWrapper wrapper = Wrappers.query(); - wrapper.eq("sur.user_id", userId) + wrapper.inSql("r.role_id", "select role_id from sys_user_role where user_id = " + userId) .like(StringUtils.isNotBlank(menu.getMenuName()), "m.menu_name", menu.getMenuName()) .eq(StringUtils.isNotBlank(menu.getVisible()), "m.visible", menu.getVisible()) .eq(StringUtils.isNotBlank(menu.getStatus()), "m.status", menu.getStatus()) @@ -178,6 +178,7 @@ public class SysMenuServiceImpl implements ISysMenuService { /** * 构建前端路由所需要的菜单 + * 路由name命名规则 path首字母转大写 + id * * @param menus 菜单列表 * @return 路由列表 @@ -186,9 +187,10 @@ public class SysMenuServiceImpl implements ISysMenuService { public List buildMenus(List menus) { List routers = new LinkedList<>(); for (SysMenu menu : menus) { + String name = menu.getRouteName() + menu.getMenuId(); RouterVo router = new RouterVo(); router.setHidden("1".equals(menu.getVisible())); - router.setName(menu.getRouteName()); + router.setName(name); router.setPath(menu.getRouterPath()); router.setComponent(menu.getComponentInfo()); router.setQuery(menu.getQueryParam()); @@ -199,12 +201,13 @@ public class SysMenuServiceImpl implements ISysMenuService { router.setRedirect("noRedirect"); router.setChildren(buildMenus(cMenus)); } else if (menu.isMenuFrame()) { + String frameName = StringUtils.capitalize(menu.getPath()) + menu.getMenuId(); router.setMeta(null); List childrenList = new ArrayList<>(); RouterVo children = new RouterVo(); children.setPath(menu.getPath()); children.setComponent(menu.getComponent()); - children.setName(StringUtils.capitalize(menu.getPath())); + children.setName(frameName); children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath())); children.setQuery(menu.getQueryParam()); childrenList.add(children); @@ -215,9 +218,10 @@ public class SysMenuServiceImpl implements ISysMenuService { List childrenList = new ArrayList<>(); RouterVo children = new RouterVo(); String routerPath = SysMenu.innerLinkReplaceEach(menu.getPath()); + String innerLinkName = StringUtils.capitalize(routerPath) + menu.getMenuId(); children.setPath(routerPath); children.setComponent(UserConstants.INNER_LINK); - children.setName(StringUtils.capitalize(routerPath)); + children.setName(innerLinkName); children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), menu.getPath())); childrenList.add(children); router.setChildren(childrenList); diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysNoticeServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysNoticeServiceImpl.java index 18b7a08..db63e61 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysNoticeServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysNoticeServiceImpl.java @@ -119,6 +119,6 @@ public class SysNoticeServiceImpl implements ISysNoticeService { */ @Override public int deleteNoticeByIds(Long[] noticeIds) { - return baseMapper.deleteBatchIds(Arrays.asList(noticeIds)); + return baseMapper.deleteByIds(Arrays.asList(noticeIds)); } } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOperLogServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOperLogServiceImpl.java index 2a76b82..b78b9dc 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOperLogServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOperLogServiceImpl.java @@ -122,7 +122,7 @@ public class SysOperLogServiceImpl implements ISysOperLogService { */ @Override public int deleteOperLogByIds(Long[] operIds) { - return baseMapper.deleteBatchIds(Arrays.asList(operIds)); + return baseMapper.deleteByIds(Arrays.asList(operIds)); } /** diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssConfigServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssConfigServiceImpl.java index 2ecd592..a1eefce 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssConfigServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssConfigServiceImpl.java @@ -135,7 +135,7 @@ public class SysOssConfigServiceImpl implements ISysOssConfigService { SysOssConfig config = baseMapper.selectById(configId); list.add(config); } - boolean flag = baseMapper.deleteBatchIds(ids) > 0; + boolean flag = baseMapper.deleteByIds(ids) > 0; if (flag) { list.forEach(sysOssConfig -> CacheUtils.evict(CacheNames.SYS_OSS_CONFIG, sysOssConfig.getConfigKey())); diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java index 682de87..0f6c3be 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java @@ -168,19 +168,6 @@ public class SysOssServiceImpl implements ISysOssService, OssService { return baseMapper.selectVoById(ossId); } - @Override - public String getUrlById(Long ossId) { - SysOssVo vo = SpringUtils.getAopProxy(this).getById(ossId); - if (ObjectUtil.isNotNull(vo)) { - try { - return this.matchingUrl(vo).getUrl(); - } catch (Exception ignored) { - // 如果oss异常无法连接则将数据直接返回 - return vo.getUrl(); - } - } - return null; - } /** * 文件下载方法,支持一次性下载完整文件 @@ -306,10 +293,9 @@ public class SysOssServiceImpl implements ISysOssService, OssService { OssClient storage = OssFactory.instance(sysOss.getService()); storage.delete(sysOss.getUrl()); } - return baseMapper.deleteBatchIds(ids) > 0; + return baseMapper.deleteByIds(ids) > 0; } - /** * 桶类型为 private 的URL 修改为临时URL时长为120s * @@ -325,6 +311,19 @@ public class SysOssServiceImpl implements ISysOssService, OssService { return oss; } + @Override + public String getUrlById(Long ossId) { + SysOssVo vo = SpringUtils.getAopProxy(this).getById(ossId); + if (ObjectUtil.isNotNull(vo)) { + try { + return this.matchingUrl(vo).getUrl(); + } catch (Exception ignored) { + // 如果oss异常无法连接则将数据直接返回 + return vo.getUrl(); + } + } + return null; + } /** * 根据 md5 从缓存或数据库中获取 SysOssVo 对象 * @@ -365,4 +364,5 @@ public class SysOssServiceImpl implements ISysOssService, OssService { int i = volumeMapper.decreaseUse(sysOssVolume.getId(), use); return i > 0; } + } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssTextbookServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssTextbookServiceImpl.java index 4f95e5e..8aaee50 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssTextbookServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssTextbookServiceImpl.java @@ -10,9 +10,12 @@ import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.utils.MapstructUtils; +import org.dromara.common.core.utils.StreamUtils; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.common.mybatis.helper.DataBaseHelper; +import org.dromara.system.domain.SysCatalogTextbook; import org.dromara.system.domain.SysOssTextbook; import org.dromara.system.domain.bo.SysOssTextbookBo; import org.dromara.system.domain.vo.SysCatalogTextbookVo; @@ -115,6 +118,14 @@ public class SysOssTextbookServiceImpl implements ISysOssTextbookService { .eq(ObjectUtil.isNotNull(bo.getStatus()), "ot.status", bo.getStatus()) .eq(StringUtils.isNotEmpty(bo.getFileSuffix()), "ot.file_suffix", bo.getFileSuffix()) .like(StringUtils.isNotEmpty(bo.getFileName()), "ot.file_name", bo.getFileName()) + .and(ObjectUtil.isNotNull(bo.getCatalogId()), w -> { + List list = catalogService.selectList(new LambdaQueryWrapper() + .select(SysCatalogTextbook::getCatalogId) + .apply(DataBaseHelper.findInSet(bo.getCatalogId(), "ancestors"))); + List ids = StreamUtils.toList(list, SysCatalogTextbook::getCatalogId); + ids.add(bo.getCatalogId()); + w.in("ot.catalog_id", ids); + }) .and(ObjectUtil.isNotNull(bo.getFormatSuffix()), w -> { Integer format = bo.getFormatSuffix(); List list = processFormatSuffixQuery(format); diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysPostServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysPostServiceImpl.java index 17cd5ca..b8a7e60 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysPostServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysPostServiceImpl.java @@ -202,7 +202,7 @@ public class SysPostServiceImpl implements ISysPostService { throw new ServiceException(String.format("%1$s已分配,不能删除!", post.getPostName())); } } - return baseMapper.deleteBatchIds(Arrays.asList(postIds)); + return baseMapper.deleteByIds(Arrays.asList(postIds)); } /** diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysRoleServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysRoleServiceImpl.java index abd294f..31f9498 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysRoleServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysRoleServiceImpl.java @@ -102,14 +102,13 @@ public class SysRoleServiceImpl implements ISysRoleService { */ @Override public List selectRolesAuthByUserId(Long userId) { - List userRoles = baseMapper.selectRolePermissionByUserId(userId); + List userRoles = baseMapper.selectRolesByUserId(userId); List roles = selectRoleAll(); + // 使用HashSet提高查找效率 + Set userRoleIds = StreamUtils.toSet(userRoles, SysRoleVo::getRoleId); for (SysRoleVo role : roles) { - for (SysRoleVo userRole : userRoles) { - if (role.getRoleId().longValue() == userRole.getRoleId().longValue()) { - role.setFlag(true); - break; - } + if (userRoleIds.contains(role.getRoleId())) { + role.setFlag(true); } } return roles; @@ -123,7 +122,7 @@ public class SysRoleServiceImpl implements ISysRoleService { */ @Override public Set selectRolePermissionByUserId(Long userId) { - List perms = baseMapper.selectRolePermissionByUserId(userId); + List perms = baseMapper.selectRolesByUserId(userId); Set permsSet = new HashSet<>(); for (SysRoleVo perm : perms) { if (ObjectUtil.isNotNull(perm)) { @@ -417,7 +416,7 @@ public class SysRoleServiceImpl implements ISysRoleService { roleMenuMapper.delete(new LambdaQueryWrapper().in(SysRoleMenu::getRoleId, ids)); // 删除角色与部门关联 roleDeptMapper.delete(new LambdaQueryWrapper().in(SysRoleDept::getRoleId, ids)); - return baseMapper.deleteBatchIds(ids); + return baseMapper.deleteByIds(ids); } /** diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTenantPackageServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTenantPackageServiceImpl.java index f7f8d46..5fd04af 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTenantPackageServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTenantPackageServiceImpl.java @@ -140,6 +140,6 @@ public class SysTenantPackageServiceImpl implements ISysTenantPackageService { throw new ServiceException("租户套餐已被使用"); } } - return baseMapper.deleteBatchIds(ids) > 0; + return baseMapper.deleteByIds(ids) > 0; } } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTenantServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTenantServiceImpl.java index 780e90f..f4dc5d2 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTenantServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTenantServiceImpl.java @@ -58,7 +58,6 @@ public class SysTenantServiceImpl implements ISysTenantService { private final SysCatalogResourceMapper catalogResourceMapper; private final SysOssVolumeMapper ossVolumeMapper; - /** * 查询租户 */ @@ -123,9 +122,7 @@ public class SysTenantServiceImpl implements ISysTenantService { // 获取所有租户编号 List tenantIds = baseMapper.selectObjs( - new LambdaQueryWrapper().select(SysTenant::getTenantId), x -> { - return Convert.toStr(x); - }); + new LambdaQueryWrapper().select(SysTenant::getTenantId), x -> {return Convert.toStr(x);}); String tenantId = generateTenantId(tenantIds); add.setTenantId(tenantId); boolean flag = baseMapper.insert(add) > 0; @@ -137,7 +134,6 @@ public class SysTenantServiceImpl implements ISysTenantService { // 根据套餐创建角色 Long roleId = createTenantRole(tenantId, bo.getPackageId()); - // 创建部门: 公司名是部门名称 SysDept dept = new SysDept(); dept.setTenantId(tenantId); @@ -172,7 +168,6 @@ public class SysTenantServiceImpl implements ISysTenantService { userRole.setUserId(user.getUserId()); userRole.setRoleId(roleId); userRoleMapper.insert(userRole); - //创建默认资源目录 SysCatalogPerson catalogPerson = new SysCatalogPerson(); catalogPerson.setTenantId(tenantId); @@ -347,7 +342,7 @@ public class SysTenantServiceImpl implements ISysTenantService { throw new ServiceException("超管租户不能删除"); } } - return baseMapper.deleteBatchIds(ids) > 0; + return baseMapper.deleteByIds(ids) > 0; } /** diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java index 57c128c..3cb4159 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java @@ -14,7 +14,6 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.dromara.common.core.constant.CacheNames; -import org.dromara.common.core.constant.Constants; import org.dromara.common.core.constant.UserConstants; import org.dromara.common.core.domain.dto.UserDTO; import org.dromara.common.core.exception.ServiceException; @@ -27,7 +26,10 @@ import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.mybatis.helper.DataBaseHelper; import org.dromara.common.satoken.utils.LoginHelper; -import org.dromara.system.domain.*; +import org.dromara.system.domain.SysDept; +import org.dromara.system.domain.SysUser; +import org.dromara.system.domain.SysUserPost; +import org.dromara.system.domain.SysUserRole; import org.dromara.system.domain.bo.SysUserBo; import org.dromara.system.domain.vo.SysPostVo; import org.dromara.system.domain.vo.SysRoleVo; @@ -35,6 +37,7 @@ import org.dromara.system.domain.vo.SysUserExportVo; import org.dromara.system.domain.vo.SysUserVo; import org.dromara.system.mapper.*; import org.dromara.system.service.ISysUserService; +import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -60,8 +63,6 @@ public class SysUserServiceImpl implements ISysUserService, UserService { private final SysUserRoleMapper userRoleMapper; private final SysUserPostMapper userPostMapper; - private final SysCatalogPersonMapper catalogPersonMapper; - @Override public TableDataInfo selectPageUserList(SysUserBo user, PageQuery pageQuery) { Page page = baseMapper.selectPageUserList(pageQuery.build(), this.buildQueryWrapper(user)); @@ -98,7 +99,7 @@ public class SysUserServiceImpl implements ISysUserService, UserService { w.in("u.dept_id", ids); }).orderByAsc("u.user_id"); if (StringUtils.isNotBlank(user.getExcludeUserIds())) { - wrapper.notIn("u.user_id", StringUtils.splitList(user.getExcludeUserIds())); + wrapper.notIn("u.user_id", StringUtils.splitTo(user.getExcludeUserIds(), Convert::toLong)); } return wrapper; } @@ -313,8 +314,6 @@ public class SysUserServiceImpl implements ISysUserService, UserService { insertUserPost(user, false); // 新增用户与角色管理 insertUserRole(user, false); - //新增我的空间 - insertPersonFile(user); return rows; } @@ -340,6 +339,7 @@ public class SysUserServiceImpl implements ISysUserService, UserService { * @return 结果 */ @Override + @CacheEvict(cacheNames = CacheNames.SYS_NICKNAME, key = "#user.userId") @Transactional(rollbackFor = Exception.class) public int updateUser(SysUserBo user) { // 新增用户与角色管理 @@ -388,6 +388,7 @@ public class SysUserServiceImpl implements ISysUserService, UserService { * @param user 用户信息 * @return 结果 */ + @CacheEvict(cacheNames = CacheNames.SYS_NICKNAME, key = "#user.userId") @Override public int updateUserProfile(SysUserBo user) { return baseMapper.update(null, @@ -540,7 +541,7 @@ public class SysUserServiceImpl implements ISysUserService, UserService { // 删除用户与岗位表 userPostMapper.delete(new LambdaQueryWrapper().in(SysUserPost::getUserId, ids)); // 防止更新失败导致的数据删除 - int flag = baseMapper.deleteBatchIds(ids); + int flag = baseMapper.deleteByIds(ids); if (flag < 1) { throw new ServiceException("删除用户失败!"); } @@ -638,7 +639,10 @@ public class SysUserServiceImpl implements ISysUserService, UserService { if (CollUtil.isEmpty(userIds)) { return List.of(); } - List list = this.selectUserByIds(userIds, null); + List list = baseMapper.selectVoList(new LambdaQueryWrapper() + .select(SysUser::getUserId, SysUser::getUserName, SysUser::getNickName) + .eq(SysUser::getStatus, UserConstants.USER_NORMAL) + .in(CollUtil.isNotEmpty(userIds), SysUser::getUserId, userIds)); return BeanUtil.copyToList(list, UserDTO.class); } @@ -649,14 +653,4 @@ public class SysUserServiceImpl implements ISysUserService, UserService { return StreamUtils.toList(userRoles, SysUserRole::getUserId); } - private void insertPersonFile(SysUserBo user) { - SysCatalogPerson catalogPerson = new SysCatalogPerson(); - catalogPerson.setCatalogName("我的空间"); - catalogPerson.setParentId(Constants.TOP_PARENT_ID); - catalogPerson.setAncestors(Constants.TOP_PARENT_ID.toString()); - catalogPerson.setCreateBy(user.getUserId()); - catalogPerson.setCreateDept(user.getDeptId()); - catalogPersonMapper.insert(catalogPerson); - } - } diff --git a/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml b/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml index fad1812..9dd3f2e 100644 --- a/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml +++ b/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml @@ -11,9 +11,8 @@ select distinct m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.query_param, m.visible, m.status, m.perms, m.is_frame, m.is_cache, m.menu_type, m.icon, m.order_num, m.create_time from sys_menu m - left join sys_role_menu rm on m.menu_id = rm.menu_id - left join sys_user_role sur on rm.role_id = sur.role_id - left join sys_role ro on sur.role_id = ro.role_id + left join sys_role_menu rm on m.menu_id = rm.menu_id + left join sys_role r on rm.role_id = r.role_id ${ew.getCustomSqlSegment} @@ -34,14 +33,10 @@ m.order_num, m.create_time from sys_menu m - left join sys_role_menu rm on m.menu_id = rm.menu_id - left join sys_user_role sur on rm.role_id = sur.role_id - left join sys_role ro on sur.role_id = ro.role_id - left join sys_user u on sur.user_id = u.user_id - where u.user_id = #{userId} - and m.menu_type in ('M', 'C') - and m.status = '0' - and ro.status = '0' + left join sys_role_menu rm on m.menu_id = rm.menu_id and m.status = '0' + left join sys_role r on rm.role_id = r.role_id and r.status = '0' + where m.menu_type in ('M', 'C') + and r.role_id in (select role_id from sys_user_role where user_id = #{userId}) order by m.parent_id, m.order_num @@ -57,22 +52,12 @@ order by m.parent_id, m.order_num - -