Commit 65cd56bcf751dc2172acccc7ba9e4e177d1c491f
Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into feature/iot
Showing
124 changed files
with
1621 additions
and
470 deletions
sql/mysql/ruoyi-vue-pro.sql
| @@ -1259,14 +1259,16 @@ CREATE TABLE `system_mail_log` ( | @@ -1259,14 +1259,16 @@ CREATE TABLE `system_mail_log` ( | ||
| 1259 | `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号', | 1259 | `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号', |
| 1260 | `user_id` bigint NULL DEFAULT NULL COMMENT '用户编号', | 1260 | `user_id` bigint NULL DEFAULT NULL COMMENT '用户编号', |
| 1261 | `user_type` tinyint NULL DEFAULT NULL COMMENT '用户类型', | 1261 | `user_type` tinyint NULL DEFAULT NULL COMMENT '用户类型', |
| 1262 | - `to_mail` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '接收邮箱地址', | 1262 | + `to_mails` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '接收邮箱地址', |
| 1263 | + `cc_mails` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '抄送邮箱地址', | ||
| 1264 | + `bcc_mails` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '密送邮箱地址', | ||
| 1263 | `account_id` bigint NOT NULL COMMENT '邮箱账号编号', | 1265 | `account_id` bigint NOT NULL COMMENT '邮箱账号编号', |
| 1264 | `from_mail` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '发送邮箱地址', | 1266 | `from_mail` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '发送邮箱地址', |
| 1265 | `template_id` bigint NOT NULL COMMENT '模板编号', | 1267 | `template_id` bigint NOT NULL COMMENT '模板编号', |
| 1266 | `template_code` varchar(63) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '模板编码', | 1268 | `template_code` varchar(63) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '模板编码', |
| 1267 | `template_nickname` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '模版发送人名称', | 1269 | `template_nickname` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '模版发送人名称', |
| 1268 | `template_title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '邮件标题', | 1270 | `template_title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '邮件标题', |
| 1269 | - `template_content` varchar(10240) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '邮件内容', | 1271 | + `template_content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '邮件内容', |
| 1270 | `template_params` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '邮件参数', | 1272 | `template_params` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '邮件参数', |
| 1271 | `send_status` tinyint NOT NULL DEFAULT 0 COMMENT '发送状态', | 1273 | `send_status` tinyint NOT NULL DEFAULT 0 COMMENT '发送状态', |
| 1272 | `send_time` datetime NULL DEFAULT NULL COMMENT '发送时间', | 1274 | `send_time` datetime NULL DEFAULT NULL COMMENT '发送时间', |
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/WebFilterOrderEnum.java
| @@ -15,6 +15,8 @@ public interface WebFilterOrderEnum { | @@ -15,6 +15,8 @@ public interface WebFilterOrderEnum { | ||
| 15 | 15 | ||
| 16 | int REQUEST_BODY_CACHE_FILTER = Integer.MIN_VALUE + 500; | 16 | int REQUEST_BODY_CACHE_FILTER = Integer.MIN_VALUE + 500; |
| 17 | 17 | ||
| 18 | + int API_ENCRYPT_FILTER = REQUEST_BODY_CACHE_FILTER + 1; | ||
| 19 | + | ||
| 18 | // OrderedRequestContextFilter 默认为 -105,用于国际化上下文等等 | 20 | // OrderedRequestContextFilter 默认为 -105,用于国际化上下文等等 |
| 19 | 21 | ||
| 20 | int TENANT_CONTEXT_FILTER = - 104; // 需要保证在 ApiAccessLogFilter 前面 | 22 | int TENANT_CONTEXT_FILTER = - 104; // 需要保证在 ApiAccessLogFilter 前面 |
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/pojo/CommonResult.java
| @@ -26,15 +26,15 @@ public class CommonResult<T> implements Serializable { | @@ -26,15 +26,15 @@ public class CommonResult<T> implements Serializable { | ||
| 26 | */ | 26 | */ |
| 27 | private Integer code; | 27 | private Integer code; |
| 28 | /** | 28 | /** |
| 29 | - * 返回数据 | ||
| 30 | - */ | ||
| 31 | - private T data; | ||
| 32 | - /** | ||
| 33 | * 错误提示,用户可阅读 | 29 | * 错误提示,用户可阅读 |
| 34 | * | 30 | * |
| 35 | * @see ErrorCode#getMsg() () | 31 | * @see ErrorCode#getMsg() () |
| 36 | */ | 32 | */ |
| 37 | private String msg; | 33 | private String msg; |
| 34 | + /** | ||
| 35 | + * 返回数据 | ||
| 36 | + */ | ||
| 37 | + private T data; | ||
| 38 | 38 | ||
| 39 | /** | 39 | /** |
| 40 | * 将传入的 result 对象,转换成另外一个泛型结果的对象 | 40 | * 将传入的 result 对象,转换成另外一个泛型结果的对象 |
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/pojo/PageResult.java
| @@ -11,12 +11,12 @@ import java.util.List; | @@ -11,12 +11,12 @@ import java.util.List; | ||
| 11 | @Data | 11 | @Data |
| 12 | public final class PageResult<T> implements Serializable { | 12 | public final class PageResult<T> implements Serializable { |
| 13 | 13 | ||
| 14 | - @Schema(description = "数据", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 15 | - private List<T> list; | ||
| 16 | - | ||
| 17 | @Schema(description = "总量", requiredMode = Schema.RequiredMode.REQUIRED) | 14 | @Schema(description = "总量", requiredMode = Schema.RequiredMode.REQUIRED) |
| 18 | private Long total; | 15 | private Long total; |
| 19 | 16 | ||
| 17 | + @Schema(description = "数据", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 18 | + private List<T> list; | ||
| 19 | + | ||
| 20 | public PageResult() { | 20 | public PageResult() { |
| 21 | } | 21 | } |
| 22 | 22 |
yudao-framework/yudao-spring-boot-starter-web/pom.xml
| @@ -53,7 +53,13 @@ | @@ -53,7 +53,13 @@ | ||
| 53 | <scope>provided</scope> <!-- 设置为 provided,主要是 GlobalExceptionHandler 使用 --> | 53 | <scope>provided</scope> <!-- 设置为 provided,主要是 GlobalExceptionHandler 使用 --> |
| 54 | </dependency> | 54 | </dependency> |
| 55 | 55 | ||
| 56 | - <!-- xss --> | 56 | + <!-- 工具类相关 --> |
| 57 | + <dependency> | ||
| 58 | + <groupId>com.google.guava</groupId> | ||
| 59 | + <artifactId>guava</artifactId> | ||
| 60 | + <scope>provided</scope> <!-- 设置为 provided,只有工具类需要使用到 --> | ||
| 61 | + </dependency> | ||
| 62 | + | ||
| 57 | <dependency> | 63 | <dependency> |
| 58 | <groupId>org.jsoup</groupId> | 64 | <groupId>org.jsoup</groupId> |
| 59 | <artifactId>jsoup</artifactId> | 65 | <artifactId>jsoup</artifactId> |
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/encrypt/config/ApiEncryptProperties.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.encrypt.config; | ||
| 2 | + | ||
| 3 | +import jakarta.validation.constraints.NotEmpty; | ||
| 4 | +import jakarta.validation.constraints.NotNull; | ||
| 5 | +import lombok.Data; | ||
| 6 | +import org.springframework.boot.context.properties.ConfigurationProperties; | ||
| 7 | +import org.springframework.validation.annotation.Validated; | ||
| 8 | + | ||
| 9 | +/** | ||
| 10 | + * HTTP API 加解密配置 | ||
| 11 | + * | ||
| 12 | + * @author 芋道源码 | ||
| 13 | + */ | ||
| 14 | +@ConfigurationProperties(prefix = "yudao.api-encrypt") | ||
| 15 | +@Validated | ||
| 16 | +@Data | ||
| 17 | +public class ApiEncryptProperties { | ||
| 18 | + | ||
| 19 | + /** | ||
| 20 | + * 是否开启 | ||
| 21 | + */ | ||
| 22 | + @NotNull(message = "是否开启不能为空") | ||
| 23 | + private Boolean enable; | ||
| 24 | + | ||
| 25 | + /** | ||
| 26 | + * 请求头(响应头)名称 | ||
| 27 | + * | ||
| 28 | + * 1. 如果该请求头非空,则表示请求参数已被「前端」加密,「后端」需要解密 | ||
| 29 | + * 2. 如果该响应头非空,则表示响应结果已被「后端」加密,「前端」需要解密 | ||
| 30 | + */ | ||
| 31 | + @NotEmpty(message = "请求头(响应头)名称不能为空") | ||
| 32 | + private String header = "X-Api-Encrypt"; | ||
| 33 | + | ||
| 34 | + /** | ||
| 35 | + * 对称加密算法,用于请求/响应的加解密 | ||
| 36 | + * | ||
| 37 | + * 目前支持 | ||
| 38 | + * 【对称加密】: | ||
| 39 | + * 1. {@link cn.hutool.crypto.symmetric.SymmetricAlgorithm#AES} | ||
| 40 | + * 2. {@link cn.hutool.crypto.symmetric.SM4#ALGORITHM_NAME} (需要自己二次开发,成本低) | ||
| 41 | + * 【非对称加密】 | ||
| 42 | + * 1. {@link cn.hutool.crypto.asymmetric.AsymmetricAlgorithm#RSA} | ||
| 43 | + * 2. {@link cn.hutool.crypto.asymmetric.SM2} (需要自己二次开发,成本低) | ||
| 44 | + * | ||
| 45 | + * @see <a href="https://help.aliyun.com/zh/ssl-certificate/what-are-a-public-key-and-a-private-key">什么是公钥和私钥?</a> | ||
| 46 | + */ | ||
| 47 | + @NotEmpty(message = "对称加密算法不能为空") | ||
| 48 | + private String algorithm; | ||
| 49 | + | ||
| 50 | + /** | ||
| 51 | + * 请求的解密密钥 | ||
| 52 | + * | ||
| 53 | + * 注意: | ||
| 54 | + * 1. 如果是【对称加密】时,它「后端」对应的是“密钥”。对应的,「前端」也对应的也是“密钥”。 | ||
| 55 | + * 2. 如果是【非对称加密】时,它「后端」对应的是“私钥”。对应的,「前端」对应的是“公钥”。(重要!!!) | ||
| 56 | + */ | ||
| 57 | + @NotEmpty(message = "请求的解密密钥不能为空") | ||
| 58 | + private String requestKey; | ||
| 59 | + | ||
| 60 | + /** | ||
| 61 | + * 响应的加密密钥 | ||
| 62 | + * | ||
| 63 | + * 注意: | ||
| 64 | + * 1. 如果是【对称加密】时,它「后端」对应的是“密钥”。对应的,「前端」也对应的也是“密钥”。 | ||
| 65 | + * 2. 如果是【非对称加密】时,它「后端」对应的是“公钥”。对应的,「前端」对应的是“私钥”。(重要!!!) | ||
| 66 | + */ | ||
| 67 | + @NotEmpty(message = "响应的加密密钥不能为空") | ||
| 68 | + private String responseKey; | ||
| 69 | + | ||
| 70 | +} |
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/encrypt/config/YudaoApiEncryptAutoConfiguration.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.encrypt.config; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum; | ||
| 4 | +import cn.iocoder.yudao.framework.encrypt.core.filter.ApiEncryptFilter; | ||
| 5 | +import cn.iocoder.yudao.framework.web.config.WebProperties; | ||
| 6 | +import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler; | ||
| 7 | +import lombok.extern.slf4j.Slf4j; | ||
| 8 | +import org.springframework.boot.autoconfigure.AutoConfiguration; | ||
| 9 | +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | ||
| 10 | +import org.springframework.boot.context.properties.EnableConfigurationProperties; | ||
| 11 | +import org.springframework.boot.web.servlet.FilterRegistrationBean; | ||
| 12 | +import org.springframework.context.annotation.Bean; | ||
| 13 | +import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; | ||
| 14 | + | ||
| 15 | +import static cn.iocoder.yudao.framework.web.config.YudaoWebAutoConfiguration.createFilterBean; | ||
| 16 | + | ||
| 17 | +@AutoConfiguration | ||
| 18 | +@Slf4j | ||
| 19 | +@EnableConfigurationProperties(ApiEncryptProperties.class) | ||
| 20 | +@ConditionalOnProperty(prefix = "yudao.api-encrypt", name = "enable", havingValue = "true") | ||
| 21 | +public class YudaoApiEncryptAutoConfiguration { | ||
| 22 | + | ||
| 23 | + @Bean | ||
| 24 | + public FilterRegistrationBean<ApiEncryptFilter> apiEncryptFilter(WebProperties webProperties, | ||
| 25 | + ApiEncryptProperties apiEncryptProperties, | ||
| 26 | + RequestMappingHandlerMapping requestMappingHandlerMapping, | ||
| 27 | + GlobalExceptionHandler globalExceptionHandler) { | ||
| 28 | + ApiEncryptFilter filter = new ApiEncryptFilter(webProperties, apiEncryptProperties, | ||
| 29 | + requestMappingHandlerMapping, globalExceptionHandler); | ||
| 30 | + return createFilterBean(filter, WebFilterOrderEnum.API_ENCRYPT_FILTER); | ||
| 31 | + | ||
| 32 | + } | ||
| 33 | + | ||
| 34 | +} |
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/encrypt/core/annotation/ApiEncrypt.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.encrypt.core.annotation; | ||
| 2 | + | ||
| 3 | +import java.lang.annotation.*; | ||
| 4 | + | ||
| 5 | +/** | ||
| 6 | + * HTTP API 加解密注解 | ||
| 7 | + */ | ||
| 8 | +@Documented | ||
| 9 | +@Target({ElementType.TYPE, ElementType.METHOD}) | ||
| 10 | +@Retention(RetentionPolicy.RUNTIME) | ||
| 11 | +public @interface ApiEncrypt { | ||
| 12 | + | ||
| 13 | + /** | ||
| 14 | + * 是否对请求参数进行解密,默认 true | ||
| 15 | + */ | ||
| 16 | + boolean request() default true; | ||
| 17 | + | ||
| 18 | + /** | ||
| 19 | + * 是否对响应结果进行加密,默认 true | ||
| 20 | + */ | ||
| 21 | + boolean response() default true; | ||
| 22 | + | ||
| 23 | +} |
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/encrypt/core/filter/ApiDecryptRequestWrapper.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.encrypt.core.filter; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.io.IoUtil; | ||
| 4 | +import cn.hutool.core.util.StrUtil; | ||
| 5 | +import cn.hutool.crypto.asymmetric.AsymmetricDecryptor; | ||
| 6 | +import cn.hutool.crypto.asymmetric.KeyType; | ||
| 7 | +import cn.hutool.crypto.symmetric.SymmetricDecryptor; | ||
| 8 | +import jakarta.servlet.ReadListener; | ||
| 9 | +import jakarta.servlet.ServletInputStream; | ||
| 10 | +import jakarta.servlet.http.HttpServletRequest; | ||
| 11 | +import jakarta.servlet.http.HttpServletRequestWrapper; | ||
| 12 | + | ||
| 13 | +import java.io.BufferedReader; | ||
| 14 | +import java.io.ByteArrayInputStream; | ||
| 15 | +import java.io.IOException; | ||
| 16 | +import java.io.InputStreamReader; | ||
| 17 | + | ||
| 18 | +/** | ||
| 19 | + * 解密请求 {@link HttpServletRequestWrapper} 实现类 | ||
| 20 | + * | ||
| 21 | + * @author 芋道源码 | ||
| 22 | + */ | ||
| 23 | +public class ApiDecryptRequestWrapper extends HttpServletRequestWrapper { | ||
| 24 | + | ||
| 25 | + private final byte[] body; | ||
| 26 | + | ||
| 27 | + public ApiDecryptRequestWrapper(HttpServletRequest request, | ||
| 28 | + SymmetricDecryptor symmetricDecryptor, | ||
| 29 | + AsymmetricDecryptor asymmetricDecryptor) throws IOException { | ||
| 30 | + super(request); | ||
| 31 | + // 读取 body,允许 HEX、BASE64 传输 | ||
| 32 | + String requestBody = StrUtil.utf8Str( | ||
| 33 | + IoUtil.readBytes(request.getInputStream(), false)); | ||
| 34 | + | ||
| 35 | + // 解密 body | ||
| 36 | + body = symmetricDecryptor != null ? symmetricDecryptor.decrypt(requestBody) | ||
| 37 | + : asymmetricDecryptor.decrypt(requestBody, KeyType.PrivateKey); | ||
| 38 | + } | ||
| 39 | + | ||
| 40 | + @Override | ||
| 41 | + public BufferedReader getReader() { | ||
| 42 | + return new BufferedReader(new InputStreamReader(this.getInputStream())); | ||
| 43 | + } | ||
| 44 | + | ||
| 45 | + @Override | ||
| 46 | + public int getContentLength() { | ||
| 47 | + return body.length; | ||
| 48 | + } | ||
| 49 | + | ||
| 50 | + @Override | ||
| 51 | + public long getContentLengthLong() { | ||
| 52 | + return body.length; | ||
| 53 | + } | ||
| 54 | + | ||
| 55 | + @Override | ||
| 56 | + public ServletInputStream getInputStream() { | ||
| 57 | + ByteArrayInputStream stream = new ByteArrayInputStream(body); | ||
| 58 | + return new ServletInputStream() { | ||
| 59 | + | ||
| 60 | + @Override | ||
| 61 | + public int read() { | ||
| 62 | + return stream.read(); | ||
| 63 | + } | ||
| 64 | + | ||
| 65 | + @Override | ||
| 66 | + public int available() { | ||
| 67 | + return body.length; | ||
| 68 | + } | ||
| 69 | + | ||
| 70 | + @Override | ||
| 71 | + public boolean isFinished() { | ||
| 72 | + return false; | ||
| 73 | + } | ||
| 74 | + | ||
| 75 | + @Override | ||
| 76 | + public boolean isReady() { | ||
| 77 | + return false; | ||
| 78 | + } | ||
| 79 | + | ||
| 80 | + @Override | ||
| 81 | + public void setReadListener(ReadListener readListener) { | ||
| 82 | + } | ||
| 83 | + | ||
| 84 | + }; | ||
| 85 | + } | ||
| 86 | +} |
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/encrypt/core/filter/ApiEncryptFilter.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.encrypt.core.filter; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.util.StrUtil; | ||
| 4 | +import cn.hutool.crypto.SecureUtil; | ||
| 5 | +import cn.hutool.crypto.asymmetric.AsymmetricDecryptor; | ||
| 6 | +import cn.hutool.crypto.asymmetric.AsymmetricEncryptor; | ||
| 7 | +import cn.hutool.crypto.symmetric.SymmetricDecryptor; | ||
| 8 | +import cn.hutool.crypto.symmetric.SymmetricEncryptor; | ||
| 9 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 10 | +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; | ||
| 11 | +import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; | ||
| 12 | +import cn.iocoder.yudao.framework.encrypt.config.ApiEncryptProperties; | ||
| 13 | +import cn.iocoder.yudao.framework.encrypt.core.annotation.ApiEncrypt; | ||
| 14 | +import cn.iocoder.yudao.framework.web.config.WebProperties; | ||
| 15 | +import cn.iocoder.yudao.framework.web.core.filter.ApiRequestFilter; | ||
| 16 | +import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler; | ||
| 17 | +import jakarta.servlet.FilterChain; | ||
| 18 | +import jakarta.servlet.ServletException; | ||
| 19 | +import jakarta.servlet.http.HttpServletRequest; | ||
| 20 | +import jakarta.servlet.http.HttpServletResponse; | ||
| 21 | +import lombok.extern.slf4j.Slf4j; | ||
| 22 | +import org.springframework.http.HttpMethod; | ||
| 23 | +import org.springframework.web.method.HandlerMethod; | ||
| 24 | +import org.springframework.web.servlet.HandlerExecutionChain; | ||
| 25 | +import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; | ||
| 26 | + | ||
| 27 | +import java.io.IOException; | ||
| 28 | + | ||
| 29 | +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.invalidParamException; | ||
| 30 | + | ||
| 31 | +/** | ||
| 32 | + * API 加密过滤器,处理 {@link ApiEncrypt} 注解。 | ||
| 33 | + * | ||
| 34 | + * 1. 解密请求参数 | ||
| 35 | + * 2. 加密响应结果 | ||
| 36 | + * | ||
| 37 | + * 疑问:为什么不使用 SpringMVC 的 RequestBodyAdvice 或 ResponseBodyAdvice 机制呢? | ||
| 38 | + * 回答:考虑到项目中会记录访问日志、异常日志,以及 HTTP API 签名等场景,最好是全局级、且提前做解析!!! | ||
| 39 | + * | ||
| 40 | + * @author 芋道源码 | ||
| 41 | + */ | ||
| 42 | +@Slf4j | ||
| 43 | +public class ApiEncryptFilter extends ApiRequestFilter { | ||
| 44 | + | ||
| 45 | + private final ApiEncryptProperties apiEncryptProperties; | ||
| 46 | + | ||
| 47 | + private final RequestMappingHandlerMapping requestMappingHandlerMapping; | ||
| 48 | + | ||
| 49 | + private final GlobalExceptionHandler globalExceptionHandler; | ||
| 50 | + | ||
| 51 | + private final SymmetricDecryptor requestSymmetricDecryptor; | ||
| 52 | + private final AsymmetricDecryptor requestAsymmetricDecryptor; | ||
| 53 | + | ||
| 54 | + private final SymmetricEncryptor responseSymmetricEncryptor; | ||
| 55 | + private final AsymmetricEncryptor responseAsymmetricEncryptor; | ||
| 56 | + | ||
| 57 | + public ApiEncryptFilter(WebProperties webProperties, | ||
| 58 | + ApiEncryptProperties apiEncryptProperties, | ||
| 59 | + RequestMappingHandlerMapping requestMappingHandlerMapping, | ||
| 60 | + GlobalExceptionHandler globalExceptionHandler) { | ||
| 61 | + super(webProperties); | ||
| 62 | + this.apiEncryptProperties = apiEncryptProperties; | ||
| 63 | + this.requestMappingHandlerMapping = requestMappingHandlerMapping; | ||
| 64 | + this.globalExceptionHandler = globalExceptionHandler; | ||
| 65 | + if (StrUtil.equalsIgnoreCase(apiEncryptProperties.getAlgorithm(), "AES")) { | ||
| 66 | + this.requestSymmetricDecryptor = SecureUtil.aes(StrUtil.utf8Bytes(apiEncryptProperties.getRequestKey())); | ||
| 67 | + this.requestAsymmetricDecryptor = null; | ||
| 68 | + this.responseSymmetricEncryptor = SecureUtil.aes(StrUtil.utf8Bytes(apiEncryptProperties.getResponseKey())); | ||
| 69 | + this.responseAsymmetricEncryptor = null; | ||
| 70 | + } else if (StrUtil.equalsIgnoreCase(apiEncryptProperties.getAlgorithm(), "RSA")) { | ||
| 71 | + this.requestSymmetricDecryptor = null; | ||
| 72 | + this.requestAsymmetricDecryptor = SecureUtil.rsa(apiEncryptProperties.getRequestKey(), null); | ||
| 73 | + this.responseSymmetricEncryptor = null; | ||
| 74 | + this.responseAsymmetricEncryptor = SecureUtil.rsa(null, apiEncryptProperties.getResponseKey()); | ||
| 75 | + } else { | ||
| 76 | + // 补充说明:如果要支持 SM2、SM4 等算法,可在此处增加对应实例的创建,并添加相应的 Maven 依赖即可。 | ||
| 77 | + throw new IllegalArgumentException("不支持的加密算法:" + apiEncryptProperties.getAlgorithm()); | ||
| 78 | + } | ||
| 79 | + } | ||
| 80 | + | ||
| 81 | + @Override | ||
| 82 | + @SuppressWarnings("NullableProblems") | ||
| 83 | + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) | ||
| 84 | + throws ServletException, IOException { | ||
| 85 | + // 获取 @ApiEncrypt 注解 | ||
| 86 | + ApiEncrypt apiEncrypt = getApiEncrypt(request); | ||
| 87 | + boolean requestEnable = apiEncrypt != null && apiEncrypt.request(); | ||
| 88 | + boolean responseEnable = apiEncrypt != null && apiEncrypt.response(); | ||
| 89 | + String encryptHeader = request.getHeader(apiEncryptProperties.getHeader()); | ||
| 90 | + if (!requestEnable && !responseEnable && StrUtil.isBlank(encryptHeader)) { | ||
| 91 | + chain.doFilter(request, response); | ||
| 92 | + return; | ||
| 93 | + } | ||
| 94 | + | ||
| 95 | + // 1. 解密请求 | ||
| 96 | + if (ObjectUtils.equalsAny(HttpMethod.valueOf(request.getMethod()), | ||
| 97 | + HttpMethod.POST, HttpMethod.PUT, HttpMethod.DELETE)) { | ||
| 98 | + try { | ||
| 99 | + if (StrUtil.isNotBlank(encryptHeader)) { | ||
| 100 | + request = new ApiDecryptRequestWrapper(request, | ||
| 101 | + requestSymmetricDecryptor, requestAsymmetricDecryptor); | ||
| 102 | + } else if (requestEnable) { | ||
| 103 | + throw invalidParamException("请求未包含加密标头,请检查是否正确配置了加密标头"); | ||
| 104 | + } | ||
| 105 | + } catch (Exception ex) { | ||
| 106 | + CommonResult<?> result = globalExceptionHandler.allExceptionHandler(request, ex); | ||
| 107 | + ServletUtils.writeJSON(response, result); | ||
| 108 | + return; | ||
| 109 | + } | ||
| 110 | + } | ||
| 111 | + | ||
| 112 | + // 2. 执行过滤器链 | ||
| 113 | + if (responseEnable) { | ||
| 114 | + // 特殊:仅包装,最后执行。目的:Response 内容可以被重复读取!!! | ||
| 115 | + response = new ApiEncryptResponseWrapper(response); | ||
| 116 | + } | ||
| 117 | + chain.doFilter(request, response); | ||
| 118 | + | ||
| 119 | + // 3. 加密响应(真正执行) | ||
| 120 | + if (responseEnable) { | ||
| 121 | + ((ApiEncryptResponseWrapper) response).encrypt(apiEncryptProperties, | ||
| 122 | + responseSymmetricEncryptor, responseAsymmetricEncryptor); | ||
| 123 | + } | ||
| 124 | + } | ||
| 125 | + | ||
| 126 | + /** | ||
| 127 | + * 获取 @ApiEncrypt 注解 | ||
| 128 | + * | ||
| 129 | + * @param request 请求 | ||
| 130 | + */ | ||
| 131 | + private ApiEncrypt getApiEncrypt(HttpServletRequest request) { | ||
| 132 | + try { | ||
| 133 | + HandlerExecutionChain mappingHandler = requestMappingHandlerMapping.getHandler(request); | ||
| 134 | + if (mappingHandler == null) { | ||
| 135 | + return null; | ||
| 136 | + } | ||
| 137 | + Object handler = mappingHandler.getHandler(); | ||
| 138 | + if (handler instanceof HandlerMethod handlerMethod) { | ||
| 139 | + ApiEncrypt annotation = handlerMethod.getMethodAnnotation(ApiEncrypt.class); | ||
| 140 | + if (annotation == null) { | ||
| 141 | + annotation = handlerMethod.getBeanType().getAnnotation(ApiEncrypt.class); | ||
| 142 | + } | ||
| 143 | + return annotation; | ||
| 144 | + } | ||
| 145 | + } catch (Exception e) { | ||
| 146 | + log.error("[getApiEncrypt][url({}/{}) 获取 @ApiEncrypt 注解失败]", | ||
| 147 | + request.getRequestURI(), request.getMethod(), e); | ||
| 148 | + } | ||
| 149 | + return null; | ||
| 150 | + } | ||
| 151 | + | ||
| 152 | +} |
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/encrypt/core/filter/ApiEncryptResponseWrapper.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.encrypt.core.filter; | ||
| 2 | + | ||
| 3 | +import cn.hutool.crypto.asymmetric.AsymmetricEncryptor; | ||
| 4 | +import cn.hutool.crypto.asymmetric.KeyType; | ||
| 5 | +import cn.hutool.crypto.symmetric.SymmetricEncryptor; | ||
| 6 | +import cn.iocoder.yudao.framework.encrypt.config.ApiEncryptProperties; | ||
| 7 | +import jakarta.servlet.ServletOutputStream; | ||
| 8 | +import jakarta.servlet.WriteListener; | ||
| 9 | +import jakarta.servlet.http.HttpServletResponse; | ||
| 10 | +import jakarta.servlet.http.HttpServletResponseWrapper; | ||
| 11 | + | ||
| 12 | +import java.io.ByteArrayOutputStream; | ||
| 13 | +import java.io.IOException; | ||
| 14 | +import java.io.OutputStreamWriter; | ||
| 15 | +import java.io.PrintWriter; | ||
| 16 | + | ||
| 17 | +/** | ||
| 18 | + * 加密响应 {@link HttpServletResponseWrapper} 实现类 | ||
| 19 | + * | ||
| 20 | + * @author 芋道源码 | ||
| 21 | + */ | ||
| 22 | +public class ApiEncryptResponseWrapper extends HttpServletResponseWrapper { | ||
| 23 | + | ||
| 24 | + private final ByteArrayOutputStream byteArrayOutputStream; | ||
| 25 | + private final ServletOutputStream servletOutputStream; | ||
| 26 | + private final PrintWriter printWriter; | ||
| 27 | + | ||
| 28 | + public ApiEncryptResponseWrapper(HttpServletResponse response) { | ||
| 29 | + super(response); | ||
| 30 | + this.byteArrayOutputStream = new ByteArrayOutputStream(); | ||
| 31 | + this.servletOutputStream = this.getOutputStream(); | ||
| 32 | + this.printWriter = new PrintWriter(new OutputStreamWriter(byteArrayOutputStream)); | ||
| 33 | + } | ||
| 34 | + | ||
| 35 | + public void encrypt(ApiEncryptProperties properties, | ||
| 36 | + SymmetricEncryptor symmetricEncryptor, | ||
| 37 | + AsymmetricEncryptor asymmetricEncryptor) throws IOException { | ||
| 38 | + // 1.1 清空 body | ||
| 39 | + HttpServletResponse response = (HttpServletResponse) this.getResponse(); | ||
| 40 | + response.resetBuffer(); | ||
| 41 | + // 1.2 获取 body | ||
| 42 | + this.flushBuffer(); | ||
| 43 | + byte[] body = byteArrayOutputStream.toByteArray(); | ||
| 44 | + | ||
| 45 | + // 2. 加密 body | ||
| 46 | + String encryptedBody = symmetricEncryptor != null ? symmetricEncryptor.encryptBase64(body) | ||
| 47 | + : asymmetricEncryptor.encryptBase64(body, KeyType.PublicKey); | ||
| 48 | + response.getWriter().write(encryptedBody); | ||
| 49 | + | ||
| 50 | + // 3. 添加加密 header 标识 | ||
| 51 | + this.addHeader(properties.getHeader(), "true"); | ||
| 52 | + // 特殊:特殊:https://juejin.cn/post/6867327674675625992 | ||
| 53 | + this.addHeader("Access-Control-Expose-Headers", properties.getHeader()); | ||
| 54 | + } | ||
| 55 | + | ||
| 56 | + @Override | ||
| 57 | + public PrintWriter getWriter() { | ||
| 58 | + return printWriter; | ||
| 59 | + } | ||
| 60 | + | ||
| 61 | + @Override | ||
| 62 | + public void flushBuffer() throws IOException { | ||
| 63 | + if (servletOutputStream != null) { | ||
| 64 | + servletOutputStream.flush(); | ||
| 65 | + } | ||
| 66 | + if (printWriter != null) { | ||
| 67 | + printWriter.flush(); | ||
| 68 | + } | ||
| 69 | + } | ||
| 70 | + | ||
| 71 | + @Override | ||
| 72 | + public void reset() { | ||
| 73 | + byteArrayOutputStream.reset(); | ||
| 74 | + } | ||
| 75 | + | ||
| 76 | + @Override | ||
| 77 | + public ServletOutputStream getOutputStream() { | ||
| 78 | + return new ServletOutputStream() { | ||
| 79 | + | ||
| 80 | + @Override | ||
| 81 | + public boolean isReady() { | ||
| 82 | + return false; | ||
| 83 | + } | ||
| 84 | + | ||
| 85 | + @Override | ||
| 86 | + public void setWriteListener(WriteListener writeListener) { | ||
| 87 | + } | ||
| 88 | + | ||
| 89 | + @Override | ||
| 90 | + public void write(int b) { | ||
| 91 | + byteArrayOutputStream.write(b); | ||
| 92 | + } | ||
| 93 | + | ||
| 94 | + @Override | ||
| 95 | + @SuppressWarnings("NullableProblems") | ||
| 96 | + public void write(byte[] b) throws IOException { | ||
| 97 | + byteArrayOutputStream.write(b); | ||
| 98 | + } | ||
| 99 | + | ||
| 100 | + @Override | ||
| 101 | + @SuppressWarnings("NullableProblems") | ||
| 102 | + public void write(byte[] b, int off, int len) { | ||
| 103 | + byteArrayOutputStream.write(b, off, len); | ||
| 104 | + } | ||
| 105 | + | ||
| 106 | + }; | ||
| 107 | + } | ||
| 108 | + | ||
| 109 | +} | ||
| 0 | \ No newline at end of file | 110 | \ No newline at end of file |
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/encrypt/package-info.java
0 → 100644
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/CacheRequestBodyWrapper.java
| 1 | package cn.iocoder.yudao.framework.web.core.filter; | 1 | package cn.iocoder.yudao.framework.web.core.filter; |
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; | 3 | import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; |
| 4 | - | ||
| 5 | import jakarta.servlet.ReadListener; | 4 | import jakarta.servlet.ReadListener; |
| 6 | import jakarta.servlet.ServletInputStream; | 5 | import jakarta.servlet.ServletInputStream; |
| 7 | import jakarta.servlet.http.HttpServletRequest; | 6 | import jakarta.servlet.http.HttpServletRequest; |
| 8 | import jakarta.servlet.http.HttpServletRequestWrapper; | 7 | import jakarta.servlet.http.HttpServletRequestWrapper; |
| 8 | + | ||
| 9 | import java.io.BufferedReader; | 9 | import java.io.BufferedReader; |
| 10 | import java.io.ByteArrayInputStream; | 10 | import java.io.ByteArrayInputStream; |
| 11 | -import java.io.IOException; | ||
| 12 | import java.io.InputStreamReader; | 11 | import java.io.InputStreamReader; |
| 13 | 12 | ||
| 14 | /** | 13 | /** |
| @@ -29,12 +28,22 @@ public class CacheRequestBodyWrapper extends HttpServletRequestWrapper { | @@ -29,12 +28,22 @@ public class CacheRequestBodyWrapper extends HttpServletRequestWrapper { | ||
| 29 | } | 28 | } |
| 30 | 29 | ||
| 31 | @Override | 30 | @Override |
| 32 | - public BufferedReader getReader() throws IOException { | 31 | + public BufferedReader getReader() { |
| 33 | return new BufferedReader(new InputStreamReader(this.getInputStream())); | 32 | return new BufferedReader(new InputStreamReader(this.getInputStream())); |
| 34 | } | 33 | } |
| 35 | 34 | ||
| 36 | @Override | 35 | @Override |
| 37 | - public ServletInputStream getInputStream() throws IOException { | 36 | + public int getContentLength() { |
| 37 | + return body.length; | ||
| 38 | + } | ||
| 39 | + | ||
| 40 | + @Override | ||
| 41 | + public long getContentLengthLong() { | ||
| 42 | + return body.length; | ||
| 43 | + } | ||
| 44 | + | ||
| 45 | + @Override | ||
| 46 | + public ServletInputStream getInputStream() { | ||
| 38 | final ByteArrayInputStream inputStream = new ByteArrayInputStream(body); | 47 | final ByteArrayInputStream inputStream = new ByteArrayInputStream(body); |
| 39 | // 返回 ServletInputStream | 48 | // 返回 ServletInputStream |
| 40 | return new ServletInputStream() { | 49 | return new ServletInputStream() { |
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java
| @@ -5,7 +5,6 @@ import cn.hutool.core.exceptions.ExceptionUtil; | @@ -5,7 +5,6 @@ import cn.hutool.core.exceptions.ExceptionUtil; | ||
| 5 | import cn.hutool.core.map.MapUtil; | 5 | import cn.hutool.core.map.MapUtil; |
| 6 | import cn.hutool.core.util.ObjUtil; | 6 | import cn.hutool.core.util.ObjUtil; |
| 7 | import cn.hutool.core.util.StrUtil; | 7 | import cn.hutool.core.util.StrUtil; |
| 8 | -import cn.hutool.extra.servlet.JakartaServletUtil; | ||
| 9 | import cn.iocoder.yudao.framework.common.biz.infra.logger.ApiErrorLogCommonApi; | 8 | import cn.iocoder.yudao.framework.common.biz.infra.logger.ApiErrorLogCommonApi; |
| 10 | import cn.iocoder.yudao.framework.common.biz.infra.logger.dto.ApiErrorLogCreateReqDTO; | 9 | import cn.iocoder.yudao.framework.common.biz.infra.logger.dto.ApiErrorLogCreateReqDTO; |
| 11 | import cn.iocoder.yudao.framework.common.exception.ServiceException; | 10 | import cn.iocoder.yudao.framework.common.exception.ServiceException; |
| @@ -17,6 +16,7 @@ import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; | @@ -17,6 +16,7 @@ import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; | ||
| 17 | import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; | 16 | import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; |
| 18 | import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; | 17 | import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; |
| 19 | import com.fasterxml.jackson.databind.exc.InvalidFormatException; | 18 | import com.fasterxml.jackson.databind.exc.InvalidFormatException; |
| 19 | +import com.google.common.util.concurrent.UncheckedExecutionException; | ||
| 20 | import jakarta.servlet.http.HttpServletRequest; | 20 | import jakarta.servlet.http.HttpServletRequest; |
| 21 | import jakarta.validation.ConstraintViolation; | 21 | import jakarta.validation.ConstraintViolation; |
| 22 | import jakarta.validation.ConstraintViolationException; | 22 | import jakarta.validation.ConstraintViolationException; |
| @@ -111,6 +111,9 @@ public class GlobalExceptionHandler { | @@ -111,6 +111,9 @@ public class GlobalExceptionHandler { | ||
| 111 | if (ex instanceof AccessDeniedException) { | 111 | if (ex instanceof AccessDeniedException) { |
| 112 | return accessDeniedExceptionHandler(request, (AccessDeniedException) ex); | 112 | return accessDeniedExceptionHandler(request, (AccessDeniedException) ex); |
| 113 | } | 113 | } |
| 114 | + if (ex instanceof UncheckedExecutionException && ex.getCause() != ex) { | ||
| 115 | + return allExceptionHandler(request, ex.getCause()); | ||
| 116 | + } | ||
| 114 | return defaultExceptionHandler(request, ex); | 117 | return defaultExceptionHandler(request, ex); |
| 115 | } | 118 | } |
| 116 | 119 | ||
| @@ -267,6 +270,16 @@ public class GlobalExceptionHandler { | @@ -267,6 +270,16 @@ public class GlobalExceptionHandler { | ||
| 267 | } | 270 | } |
| 268 | 271 | ||
| 269 | /** | 272 | /** |
| 273 | + * 处理 Guava UncheckedExecutionException | ||
| 274 | + * | ||
| 275 | + * 例如说,缓存加载报错,可见 <a href="https://t.zsxq.com/UszdH">https://t.zsxq.com/UszdH</a> | ||
| 276 | + */ | ||
| 277 | + @ExceptionHandler(value = UncheckedExecutionException.class) | ||
| 278 | + public CommonResult<?> uncheckedExecutionExceptionHandler(HttpServletRequest req, UncheckedExecutionException ex) { | ||
| 279 | + return allExceptionHandler(req, ex.getCause()); | ||
| 280 | + } | ||
| 281 | + | ||
| 282 | + /** | ||
| 270 | * 处理业务异常 ServiceException | 283 | * 处理业务异常 ServiceException |
| 271 | * | 284 | * |
| 272 | * 例如说,商品库存不足,用户手机号已存在。 | 285 | * 例如说,商品库存不足,用户手机号已存在。 |
| @@ -344,12 +357,12 @@ public class GlobalExceptionHandler { | @@ -344,12 +357,12 @@ public class GlobalExceptionHandler { | ||
| 344 | errorLog.setApplicationName(applicationName); | 357 | errorLog.setApplicationName(applicationName); |
| 345 | errorLog.setRequestUrl(request.getRequestURI()); | 358 | errorLog.setRequestUrl(request.getRequestURI()); |
| 346 | Map<String, Object> requestParams = MapUtil.<String, Object>builder() | 359 | Map<String, Object> requestParams = MapUtil.<String, Object>builder() |
| 347 | - .put("query", JakartaServletUtil.getParamMap(request)) | ||
| 348 | - .put("body", JakartaServletUtil.getBody(request)).build(); | 360 | + .put("query", ServletUtils.getParamMap(request)) |
| 361 | + .put("body", ServletUtils.getBody(request)).build(); | ||
| 349 | errorLog.setRequestParams(JsonUtils.toJsonString(requestParams)); | 362 | errorLog.setRequestParams(JsonUtils.toJsonString(requestParams)); |
| 350 | errorLog.setRequestMethod(request.getMethod()); | 363 | errorLog.setRequestMethod(request.getMethod()); |
| 351 | errorLog.setUserAgent(ServletUtils.getUserAgent(request)); | 364 | errorLog.setUserAgent(ServletUtils.getUserAgent(request)); |
| 352 | - errorLog.setUserIp(JakartaServletUtil.getClientIP(request)); | 365 | + errorLog.setUserIp(ServletUtils.getClientIP(request)); |
| 353 | errorLog.setExceptionTime(LocalDateTime.now()); | 366 | errorLog.setExceptionTime(LocalDateTime.now()); |
| 354 | } | 367 | } |
| 355 | 368 |
yudao-framework/yudao-spring-boot-starter-web/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
| @@ -3,4 +3,5 @@ cn.iocoder.yudao.framework.jackson.config.YudaoJacksonAutoConfiguration | @@ -3,4 +3,5 @@ cn.iocoder.yudao.framework.jackson.config.YudaoJacksonAutoConfiguration | ||
| 3 | cn.iocoder.yudao.framework.swagger.config.YudaoSwaggerAutoConfiguration | 3 | cn.iocoder.yudao.framework.swagger.config.YudaoSwaggerAutoConfiguration |
| 4 | cn.iocoder.yudao.framework.web.config.YudaoWebAutoConfiguration | 4 | cn.iocoder.yudao.framework.web.config.YudaoWebAutoConfiguration |
| 5 | cn.iocoder.yudao.framework.xss.config.YudaoXssAutoConfiguration | 5 | cn.iocoder.yudao.framework.xss.config.YudaoXssAutoConfiguration |
| 6 | -cn.iocoder.yudao.framework.banner.config.YudaoBannerAutoConfiguration | ||
| 7 | \ No newline at end of file | 6 | \ No newline at end of file |
| 7 | +cn.iocoder.yudao.framework.banner.config.YudaoBannerAutoConfiguration | ||
| 8 | +cn.iocoder.yudao.framework.encrypt.config.YudaoApiEncryptAutoConfiguration | ||
| 8 | \ No newline at end of file | 9 | \ No newline at end of file |
yudao-framework/yudao-spring-boot-starter-web/src/test/java/cn/iocoder/yudao/framework/encrypt/ApiEncryptTest.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.encrypt; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.util.RandomUtil; | ||
| 4 | +import cn.hutool.core.util.StrUtil; | ||
| 5 | +import cn.hutool.crypto.SecureUtil; | ||
| 6 | +import cn.hutool.crypto.asymmetric.AsymmetricAlgorithm; | ||
| 7 | +import cn.hutool.crypto.asymmetric.KeyType; | ||
| 8 | +import cn.hutool.crypto.asymmetric.RSA; | ||
| 9 | +import cn.hutool.crypto.symmetric.SymmetricAlgorithm; | ||
| 10 | +import org.junit.jupiter.api.Test; | ||
| 11 | + | ||
| 12 | +import java.util.Objects; | ||
| 13 | + | ||
| 14 | +/** | ||
| 15 | + * 各种 API 加解密的测试类:不是单测,而是方便大家生成密钥、加密、解密等操作。 | ||
| 16 | + * | ||
| 17 | + * @author 芋道源码 | ||
| 18 | + */ | ||
| 19 | +@SuppressWarnings("ConstantValue") | ||
| 20 | +public class ApiEncryptTest { | ||
| 21 | + | ||
| 22 | + @Test | ||
| 23 | + public void testGenerateAsymmetric() { | ||
| 24 | + String asymmetricAlgorithm = AsymmetricAlgorithm.RSA.getValue(); | ||
| 25 | +// String asymmetricAlgorithm = "SM2"; | ||
| 26 | +// String asymmetricAlgorithm = SM4.ALGORITHM_NAME; | ||
| 27 | +// String asymmetricAlgorithm = SymmetricAlgorithm.AES.getValue(); | ||
| 28 | + String requestClientKey = null; | ||
| 29 | + String requestServerKey = null; | ||
| 30 | + String responseClientKey = null; | ||
| 31 | + String responseServerKey = null; | ||
| 32 | + if (Objects.equals(asymmetricAlgorithm, AsymmetricAlgorithm.RSA.getValue())) { | ||
| 33 | + // 请求的密钥 | ||
| 34 | + RSA requestRsa = SecureUtil.rsa(); | ||
| 35 | + requestClientKey = requestRsa.getPublicKeyBase64(); | ||
| 36 | + requestServerKey = requestRsa.getPrivateKeyBase64(); | ||
| 37 | + // 响应的密钥 | ||
| 38 | + RSA responseRsa = new RSA(); | ||
| 39 | + responseClientKey = responseRsa.getPrivateKeyBase64(); | ||
| 40 | + responseServerKey = responseRsa.getPublicKeyBase64(); | ||
| 41 | + } else if (Objects.equals(asymmetricAlgorithm, SymmetricAlgorithm.AES.getValue())) { | ||
| 42 | + // AES 密钥可选 32、24、16 位 | ||
| 43 | + // 请求的密钥(前后端密钥一致) | ||
| 44 | + requestClientKey = RandomUtil.randomNumbers(32); | ||
| 45 | + requestServerKey = requestClientKey; | ||
| 46 | + // 响应的密钥(前后端密钥一致) | ||
| 47 | + responseClientKey = RandomUtil.randomNumbers(32); | ||
| 48 | + responseServerKey = responseClientKey; | ||
| 49 | + } | ||
| 50 | + | ||
| 51 | + // 打印结果 | ||
| 52 | + System.out.println("requestClientKey = " + requestClientKey); | ||
| 53 | + System.out.println("requestServerKey = " + requestServerKey); | ||
| 54 | + System.out.println("responseClientKey = " + responseClientKey); | ||
| 55 | + System.out.println("responseServerKey = " + responseServerKey); | ||
| 56 | + } | ||
| 57 | + | ||
| 58 | + @Test | ||
| 59 | + public void testEncrypt_aes() { | ||
| 60 | + String key = "52549111389893486934626385991395"; | ||
| 61 | + String body = "{\n" + | ||
| 62 | + " \"username\": \"admin\",\n" + | ||
| 63 | + " \"password\": \"admin123\",\n" + | ||
| 64 | + " \"uuid\": \"3acd87a09a4f48fb9118333780e94883\",\n" + | ||
| 65 | + " \"code\": \"1024\"\n" + | ||
| 66 | + "}"; | ||
| 67 | + String encrypt = SecureUtil.aes(StrUtil.utf8Bytes(key)) | ||
| 68 | + .encryptBase64(body); | ||
| 69 | + System.out.println("encrypt = " + encrypt); | ||
| 70 | + } | ||
| 71 | + | ||
| 72 | + @Test | ||
| 73 | + public void testEncrypt_rsa() { | ||
| 74 | + String key = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCls2rIpnGdYnLFgz1XU13GbNQ5DloyPpvW00FPGjqn5Z6JpK+kDtVlnkhwR87iRrE5Vf2WNqRX6vzbLSgveIQY8e8oqGCb829myjf1MuI+ZzN4ghf/7tEYhZJGPI9AbfxFqBUzm+kR3/HByAI22GLT96WM26QiMK8n3tIP/yiLswIDAQAB"; | ||
| 75 | + String body = "{\n" + | ||
| 76 | + " \"username\": \"admin\",\n" + | ||
| 77 | + " \"password\": \"admin123\",\n" + | ||
| 78 | + " \"uuid\": \"3acd87a09a4f48fb9118333780e94883\",\n" + | ||
| 79 | + " \"code\": \"1024\"\n" + | ||
| 80 | + "}"; | ||
| 81 | + String encrypt = SecureUtil.rsa(null, key) | ||
| 82 | + .encryptBase64(body, KeyType.PublicKey); | ||
| 83 | + System.out.println("encrypt = " + encrypt); | ||
| 84 | + } | ||
| 85 | + | ||
| 86 | +} |
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelMetaInfoVO.java
| @@ -72,6 +72,9 @@ public class BpmModelMetaInfoVO { | @@ -72,6 +72,9 @@ public class BpmModelMetaInfoVO { | ||
| 72 | @Schema(description = "允许撤销审批中的申请", example = "true") | 72 | @Schema(description = "允许撤销审批中的申请", example = "true") |
| 73 | private Boolean allowCancelRunningProcess; | 73 | private Boolean allowCancelRunningProcess; |
| 74 | 74 | ||
| 75 | + @Schema(description = "允许允许审批人撤回任务", example = "false") | ||
| 76 | + private Boolean allowWithdrawTask; | ||
| 77 | + | ||
| 75 | @Schema(description = "流程 ID 规则", example = "{}") | 78 | @Schema(description = "流程 ID 规则", example = "{}") |
| 76 | private ProcessIdRule processIdRule; | 79 | private ProcessIdRule processIdRule; |
| 77 | 80 |
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.java
| @@ -219,6 +219,14 @@ public class BpmTaskController { | @@ -219,6 +219,14 @@ public class BpmTaskController { | ||
| 219 | return success(true); | 219 | return success(true); |
| 220 | } | 220 | } |
| 221 | 221 | ||
| 222 | + @PutMapping("/withdraw") | ||
| 223 | + @Operation(summary = "撤回任务") | ||
| 224 | + @PreAuthorize("@ss.hasPermission('bpm:task:update')") | ||
| 225 | + public CommonResult<Boolean> withdrawTask(@RequestParam("taskId") String taskId) { | ||
| 226 | + taskService.withdrawTask(getLoginUserId(), taskId); | ||
| 227 | + return success(true); | ||
| 228 | + } | ||
| 229 | + | ||
| 222 | @GetMapping("/list-by-parent-task-id") | 230 | @GetMapping("/list-by-parent-task-id") |
| 223 | @Operation(summary = "获得指定父级任务的子任务列表") // 目前用于,减签的时候,获得子任务列表 | 231 | @Operation(summary = "获得指定父级任务的子任务列表") // 目前用于,减签的时候,获得子任务列表 |
| 224 | @Parameter(name = "parentTaskId", description = "父级任务编号", required = true) | 232 | @Parameter(name = "parentTaskId", description = "父级任务编号", required = true) |
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmProcessDefinitionInfoDO.java
| @@ -173,6 +173,11 @@ public class BpmProcessDefinitionInfoDO extends BaseDO { | @@ -173,6 +173,11 @@ public class BpmProcessDefinitionInfoDO extends BaseDO { | ||
| 173 | private Boolean allowCancelRunningProcess; | 173 | private Boolean allowCancelRunningProcess; |
| 174 | 174 | ||
| 175 | /** | 175 | /** |
| 176 | + * 是否允许审批人撤回任务 | ||
| 177 | + */ | ||
| 178 | + private Boolean allowWithdrawTask; | ||
| 179 | + | ||
| 180 | + /** | ||
| 176 | * 流程 ID 规则 | 181 | * 流程 ID 规则 |
| 177 | */ | 182 | */ |
| 178 | @TableField(typeHandler = JacksonTypeHandler.class) | 183 | @TableField(typeHandler = JacksonTypeHandler.class) |
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java
| @@ -60,6 +60,10 @@ public interface ErrorCodeConstants { | @@ -60,6 +60,10 @@ public interface ErrorCodeConstants { | ||
| 60 | ErrorCode TASK_TRANSFER_FAIL_USER_NOT_EXISTS = new ErrorCode(1_009_005_014, "任务转办失败,转办人不存在"); | 60 | ErrorCode TASK_TRANSFER_FAIL_USER_NOT_EXISTS = new ErrorCode(1_009_005_014, "任务转办失败,转办人不存在"); |
| 61 | ErrorCode TASK_SIGNATURE_NOT_EXISTS = new ErrorCode(1_009_005_015, "签名不能为空!"); | 61 | ErrorCode TASK_SIGNATURE_NOT_EXISTS = new ErrorCode(1_009_005_015, "签名不能为空!"); |
| 62 | ErrorCode TASK_REASON_REQUIRE = new ErrorCode(1_009_005_016, "审批意见不能为空!"); | 62 | ErrorCode TASK_REASON_REQUIRE = new ErrorCode(1_009_005_016, "审批意见不能为空!"); |
| 63 | + ErrorCode TASK_WITHDRAW_FAIL_PROCESS_NOT_RUNNING = new ErrorCode(1_009_005_017, "撤回失败,流程实例未运行!"); | ||
| 64 | + ErrorCode TASK_WITHDRAW_FAIL_TASK_NOT_EXISTS = new ErrorCode(1_009_005_018, "撤回失败,未查询到用户已办任务!"); | ||
| 65 | + ErrorCode TASK_WITHDRAW_FAIL_NOT_ALLOW = new ErrorCode(1_009_005_019, "撤回失败,此流程不允许撤回操作!"); | ||
| 66 | + ErrorCode TASK_WITHDRAW_FAIL_NEXT_TASK_NOT_ALLOW = new ErrorCode(1_009_005_019, "撤回失败,下一节点不满足撤回条件!"); | ||
| 63 | 67 | ||
| 64 | // ========== 动态表单模块 1-009-010-000 ========== | 68 | // ========== 动态表单模块 1-009-010-000 ========== |
| 65 | ErrorCode FORM_NOT_EXISTS = new ErrorCode(1_009_010_000, "动态表单不存在"); | 69 | ErrorCode FORM_NOT_EXISTS = new ErrorCode(1_009_010_000, "动态表单不存在"); |
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmReasonEnum.java
| @@ -35,6 +35,7 @@ public enum BpmReasonEnum { | @@ -35,6 +35,7 @@ public enum BpmReasonEnum { | ||
| 35 | APPROVE_TYPE_AUTO_APPROVE("非人工审核,自动通过"), | 35 | APPROVE_TYPE_AUTO_APPROVE("非人工审核,自动通过"), |
| 36 | APPROVE_TYPE_AUTO_REJECT("非人工审核,自动不通过"), | 36 | APPROVE_TYPE_AUTO_REJECT("非人工审核,自动不通过"), |
| 37 | CANCEL_BY_PROCESS_CLEAN("进程清理自动取消"), | 37 | CANCEL_BY_PROCESS_CLEAN("进程清理自动取消"), |
| 38 | + CANCEL_BY_WITHDRAW("前一任务撤回,系统自动取消"), | ||
| 38 | ; | 39 | ; |
| 39 | 40 | ||
| 40 | private final String reason; | 41 | private final String reason; |
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmSequentialMultiInstanceBehavior.java
| @@ -7,10 +7,7 @@ import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCand | @@ -7,10 +7,7 @@ import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCand | ||
| 7 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils; | 7 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils; |
| 8 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils; | 8 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils; |
| 9 | import lombok.Setter; | 9 | import lombok.Setter; |
| 10 | -import org.flowable.bpmn.model.Activity; | ||
| 11 | -import org.flowable.bpmn.model.CallActivity; | ||
| 12 | -import org.flowable.bpmn.model.FlowElement; | ||
| 13 | -import org.flowable.bpmn.model.UserTask; | 10 | +import org.flowable.bpmn.model.*; |
| 14 | import org.flowable.engine.delegate.DelegateExecution; | 11 | import org.flowable.engine.delegate.DelegateExecution; |
| 15 | import org.flowable.engine.impl.bpmn.behavior.AbstractBpmnActivityBehavior; | 12 | import org.flowable.engine.impl.bpmn.behavior.AbstractBpmnActivityBehavior; |
| 16 | import org.flowable.engine.impl.bpmn.behavior.SequentialMultiInstanceBehavior; | 13 | import org.flowable.engine.impl.bpmn.behavior.SequentialMultiInstanceBehavior; |
| @@ -85,6 +82,12 @@ public class BpmSequentialMultiInstanceBehavior extends SequentialMultiInstanceB | @@ -85,6 +82,12 @@ public class BpmSequentialMultiInstanceBehavior extends SequentialMultiInstanceB | ||
| 85 | 82 | ||
| 86 | @Override | 83 | @Override |
| 87 | protected void executeOriginalBehavior(DelegateExecution execution, ExecutionEntity multiInstanceRootExecution, int loopCounter) { | 84 | protected void executeOriginalBehavior(DelegateExecution execution, ExecutionEntity multiInstanceRootExecution, int loopCounter) { |
| 85 | + // 参见 https://t.zsxq.com/53Meo 情况 | ||
| 86 | + if (execution.getCurrentFlowElement() instanceof CallActivity | ||
| 87 | + || execution.getCurrentFlowElement() instanceof SubProcess) { | ||
| 88 | + super.executeOriginalBehavior(execution, multiInstanceRootExecution, loopCounter); | ||
| 89 | + return; | ||
| 90 | + } | ||
| 88 | // 参见 https://gitee.com/zhijiantianya/yudao-cloud/issues/IC239F | 91 | // 参见 https://gitee.com/zhijiantianya/yudao-cloud/issues/IC239F |
| 89 | super.collectionExpression = null; | 92 | super.collectionExpression = null; |
| 90 | super.collectionVariable = FlowableUtils.formatExecutionCollectionVariable(execution.getCurrentActivityId()); | 93 | super.collectionVariable = FlowableUtils.formatExecutionCollectionVariable(execution.getCurrentActivityId()); |
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java
| @@ -852,7 +852,7 @@ public class BpmnModelUtils { | @@ -852,7 +852,7 @@ public class BpmnModelUtils { | ||
| 852 | } else if (flowNode instanceof ScriptTask) { | 852 | } else if (flowNode instanceof ScriptTask) { |
| 853 | skipExpression = ((ScriptTask) flowNode).getSkipExpression(); | 853 | skipExpression = ((ScriptTask) flowNode).getSkipExpression(); |
| 854 | } | 854 | } |
| 855 | - | 855 | + |
| 856 | if (StrUtil.isEmpty(skipExpression)) { | 856 | if (StrUtil.isEmpty(skipExpression)) { |
| 857 | return false; | 857 | return false; |
| 858 | } | 858 | } |
| @@ -909,6 +909,49 @@ public class BpmnModelUtils { | @@ -909,6 +909,49 @@ public class BpmnModelUtils { | ||
| 909 | } | 909 | } |
| 910 | 910 | ||
| 911 | /** | 911 | /** |
| 912 | + * 查找起始节点下一个用户任务列表列表 | ||
| 913 | + * | ||
| 914 | + * @param source 起始节点 | ||
| 915 | + * @return 结果 | ||
| 916 | + */ | ||
| 917 | + public static List<UserTask> getNextUserTasks(FlowElement source) { | ||
| 918 | + return getNextUserTasks(source, null, null); | ||
| 919 | + } | ||
| 920 | + | ||
| 921 | + /** | ||
| 922 | + * 查找起始节点下一个用户任务列表列表 | ||
| 923 | + * @param source 起始节点 | ||
| 924 | + * @param hasSequenceFlow 已经经过的连线的 ID,用于判断线路是否重复 | ||
| 925 | + * @param userTaskList 用户任务列表 | ||
| 926 | + * @return 结果 | ||
| 927 | + */ | ||
| 928 | + public static List<UserTask> getNextUserTasks(FlowElement source, Set<String> hasSequenceFlow, List<UserTask> userTaskList) { | ||
| 929 | + hasSequenceFlow = Optional.ofNullable(hasSequenceFlow).orElse(new HashSet<>()); | ||
| 930 | + userTaskList = Optional.ofNullable(userTaskList).orElse(new ArrayList<>()); | ||
| 931 | + // 获取出口连线 | ||
| 932 | + List<SequenceFlow> sequenceFlows = getElementOutgoingFlows(source); | ||
| 933 | + if (!sequenceFlows.isEmpty()) { | ||
| 934 | + for (SequenceFlow sequenceFlow : sequenceFlows) { | ||
| 935 | + // 如果发现连线重复,说明循环了,跳过这个循环 | ||
| 936 | + if (hasSequenceFlow.contains(sequenceFlow.getId())) { | ||
| 937 | + continue; | ||
| 938 | + } | ||
| 939 | + // 添加已经走过的连线 | ||
| 940 | + hasSequenceFlow.add(sequenceFlow.getId()); | ||
| 941 | + FlowElement targetFlowElement = sequenceFlow.getTargetFlowElement(); | ||
| 942 | + if (targetFlowElement instanceof UserTask) { | ||
| 943 | + // 若节点为用户任务,加入到结果列表中 | ||
| 944 | + userTaskList.add((UserTask) targetFlowElement); | ||
| 945 | + } else { | ||
| 946 | + // 若节点非用户任务,继续递归查找下一个节点 | ||
| 947 | + getNextUserTasks(targetFlowElement, hasSequenceFlow, userTaskList); | ||
| 948 | + } | ||
| 949 | + } | ||
| 950 | + } | ||
| 951 | + return userTaskList; | ||
| 952 | + } | ||
| 953 | + | ||
| 954 | + /** | ||
| 912 | * 处理排它网关 | 955 | * 处理排它网关 |
| 913 | * | 956 | * |
| 914 | * @param gateway 排他网关 | 957 | * @param gateway 排他网关 |
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java
| @@ -67,7 +67,6 @@ import java.util.*; | @@ -67,7 +67,6 @@ import java.util.*; | ||
| 67 | 67 | ||
| 68 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 68 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 69 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; | 69 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; |
| 70 | -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | ||
| 71 | import static cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmApprovalDetailRespVO.ActivityNode; | 70 | import static cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmApprovalDetailRespVO.ActivityNode; |
| 72 | import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*; | 71 | import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*; |
| 73 | import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.START_USER_NODE_ID; | 72 | import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.START_USER_NODE_ID; |
| @@ -221,11 +220,6 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | @@ -221,11 +220,6 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | ||
| 221 | List<ActivityNode> simulateActivityNodes = getSimulateApproveNodeList(startUserId, bpmnModel, | 220 | List<ActivityNode> simulateActivityNodes = getSimulateApproveNodeList(startUserId, bpmnModel, |
| 222 | processDefinitionInfo, | 221 | processDefinitionInfo, |
| 223 | processVariables, activities); | 222 | processVariables, activities); |
| 224 | - // 3.3 如果是发起动作,activityId 为开始节点,不校验审批人自选节点 | ||
| 225 | - if (ObjUtil.equals(reqVO.getActivityId(), BpmnModelConstants.START_USER_NODE_ID)) { | ||
| 226 | - simulateActivityNodes.removeIf(node -> | ||
| 227 | - BpmTaskCandidateStrategyEnum.APPROVE_USER_SELECT.getStrategy().equals(node.getCandidateStrategy())); | ||
| 228 | - } | ||
| 229 | 223 | ||
| 230 | // 4. 拼接最终数据 | 224 | // 4. 拼接最终数据 |
| 231 | return buildApprovalDetail(reqVO, bpmnModel, processDefinition, processDefinitionInfo, historicProcessInstance, | 225 | return buildApprovalDetail(reqVO, bpmnModel, processDefinition, processDefinitionInfo, historicProcessInstance, |
| @@ -415,7 +409,9 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | @@ -415,7 +409,9 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | ||
| 415 | endActivities.forEach(activity -> { | 409 | endActivities.forEach(activity -> { |
| 416 | // StartEvent:只处理 BPMN 的场景。因为,SIMPLE 情况下,已经有 START_USER_NODE 节点 | 410 | // StartEvent:只处理 BPMN 的场景。因为,SIMPLE 情况下,已经有 START_USER_NODE 节点 |
| 417 | if (ELEMENT_EVENT_START.equals(activity.getActivityType()) | 411 | if (ELEMENT_EVENT_START.equals(activity.getActivityType()) |
| 418 | - && BpmModelTypeEnum.BPMN.getType().equals(processDefinitionInfo.getModelType())) { | 412 | + && BpmModelTypeEnum.BPMN.getType().equals(processDefinitionInfo.getModelType()) |
| 413 | + && !CollUtil.contains(activities, // 特殊:如果已经存在用户手动创建的 START_USER_NODE_ID 节点,则忽略 StartEvent | ||
| 414 | + historicActivity -> historicActivity.getActivityId().equals(START_USER_NODE_ID))) { | ||
| 419 | ActivityNodeTask startTask = new ActivityNodeTask().setId(BpmnModelConstants.START_USER_NODE_ID) | 415 | ActivityNodeTask startTask = new ActivityNodeTask().setId(BpmnModelConstants.START_USER_NODE_ID) |
| 420 | .setAssignee(startUserId).setStatus(BpmTaskStatusEnum.APPROVE.getStatus()); | 416 | .setAssignee(startUserId).setStatus(BpmTaskStatusEnum.APPROVE.getStatus()); |
| 421 | ActivityNode startNode = new ActivityNode().setId(startTask.getId()) | 417 | ActivityNode startNode = new ActivityNode().setId(startTask.getId()) |
| @@ -555,7 +551,8 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | @@ -555,7 +551,8 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | ||
| 555 | // 情况一:BPMN 设计器 | 551 | // 情况一:BPMN 设计器 |
| 556 | if (Objects.equals(BpmModelTypeEnum.BPMN.getType(), processDefinitionInfo.getModelType())) { | 552 | if (Objects.equals(BpmModelTypeEnum.BPMN.getType(), processDefinitionInfo.getModelType())) { |
| 557 | List<FlowElement> flowElements = BpmnModelUtils.simulateProcess(bpmnModel, processVariables); | 553 | List<FlowElement> flowElements = BpmnModelUtils.simulateProcess(bpmnModel, processVariables); |
| 558 | - return convertList(flowElements, flowElement -> buildNotRunApproveNodeForBpmn(startUserId, bpmnModel, | 554 | + return convertList(flowElements, flowElement -> buildNotRunApproveNodeForBpmn( |
| 555 | + startUserId, bpmnModel, flowElements, | ||
| 559 | processDefinitionInfo, processVariables, flowElement, runActivityIds)); | 556 | processDefinitionInfo, processVariables, flowElement, runActivityIds)); |
| 560 | } | 557 | } |
| 561 | // 情况二:SIMPLE 设计器 | 558 | // 情况二:SIMPLE 设计器 |
| @@ -563,7 +560,8 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | @@ -563,7 +560,8 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | ||
| 563 | BpmSimpleModelNodeVO simpleModel = JsonUtils.parseObject(processDefinitionInfo.getSimpleModel(), | 560 | BpmSimpleModelNodeVO simpleModel = JsonUtils.parseObject(processDefinitionInfo.getSimpleModel(), |
| 564 | BpmSimpleModelNodeVO.class); | 561 | BpmSimpleModelNodeVO.class); |
| 565 | List<BpmSimpleModelNodeVO> simpleNodes = SimpleModelUtils.simulateProcess(simpleModel, processVariables); | 562 | List<BpmSimpleModelNodeVO> simpleNodes = SimpleModelUtils.simulateProcess(simpleModel, processVariables); |
| 566 | - return convertList(simpleNodes, simpleNode -> buildNotRunApproveNodeForSimple(startUserId, bpmnModel, | 563 | + return convertList(simpleNodes, simpleNode -> buildNotRunApproveNodeForSimple( |
| 564 | + startUserId, bpmnModel, | ||
| 567 | processDefinitionInfo, processVariables, simpleNode, runActivityIds)); | 565 | processDefinitionInfo, processVariables, simpleNode, runActivityIds)); |
| 568 | } | 566 | } |
| 569 | throw new IllegalArgumentException("未知设计器类型:" + processDefinitionInfo.getModelType()); | 567 | throw new IllegalArgumentException("未知设计器类型:" + processDefinitionInfo.getModelType()); |
| @@ -618,8 +616,9 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | @@ -618,8 +616,9 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | ||
| 618 | return null; | 616 | return null; |
| 619 | } | 617 | } |
| 620 | 618 | ||
| 621 | - private ActivityNode buildNotRunApproveNodeForBpmn(Long startUserId, BpmnModel bpmnModel, | ||
| 622 | - BpmProcessDefinitionInfoDO processDefinitionInfo, Map<String, Object> processVariables, | 619 | + private ActivityNode buildNotRunApproveNodeForBpmn(Long startUserId, BpmnModel bpmnModel, List<FlowElement> flowElements, |
| 620 | + BpmProcessDefinitionInfoDO processDefinitionInfo, | ||
| 621 | + Map<String, Object> processVariables, | ||
| 623 | FlowElement node, Set<String> runActivityIds) { | 622 | FlowElement node, Set<String> runActivityIds) { |
| 624 | if (runActivityIds.contains(node.getId())) { | 623 | if (runActivityIds.contains(node.getId())) { |
| 625 | return null; | 624 | return null; |
| @@ -634,6 +633,10 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | @@ -634,6 +633,10 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | ||
| 634 | 633 | ||
| 635 | // 1. 开始节点 | 634 | // 1. 开始节点 |
| 636 | if (node instanceof StartEvent) { | 635 | if (node instanceof StartEvent) { |
| 636 | + if (CollUtil.contains(flowElements, // 特殊:如果已经存在用户手动创建的 START_USER_NODE_ID 节点,则忽略 StartEvent | ||
| 637 | + flowElement -> flowElement.getId().equals(START_USER_NODE_ID))) { | ||
| 638 | + return null; | ||
| 639 | + } | ||
| 637 | return activityNode.setName(BpmSimpleModelNodeTypeEnum.START_USER_NODE.getName()) | 640 | return activityNode.setName(BpmSimpleModelNodeTypeEnum.START_USER_NODE.getName()) |
| 638 | .setNodeType(BpmSimpleModelNodeTypeEnum.START_USER_NODE.getType()); | 641 | .setNodeType(BpmSimpleModelNodeTypeEnum.START_USER_NODE.getType()); |
| 639 | } | 642 | } |
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java
| @@ -250,6 +250,14 @@ public interface BpmTaskService { | @@ -250,6 +250,14 @@ public interface BpmTaskService { | ||
| 250 | */ | 250 | */ |
| 251 | void copyTask(Long userId, @Valid BpmTaskCopyReqVO reqVO); | 251 | void copyTask(Long userId, @Valid BpmTaskCopyReqVO reqVO); |
| 252 | 252 | ||
| 253 | + /** | ||
| 254 | + * 撤回任务 | ||
| 255 | + * | ||
| 256 | + * @param userId 用户编号 | ||
| 257 | + * @param taskId 任务编号 | ||
| 258 | + */ | ||
| 259 | + void withdrawTask(Long userId, String taskId); | ||
| 260 | + | ||
| 253 | // ========== Event 事件相关方法 ========== | 261 | // ========== Event 事件相关方法 ========== |
| 254 | 262 | ||
| 255 | /** | 263 | /** |
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java
| @@ -196,7 +196,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { | @@ -196,7 +196,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||
| 196 | /** | 196 | /** |
| 197 | * 获得用户指定 processInstanceId 流程编号下的首个“待办”(未审批、且可审核)的任务 | 197 | * 获得用户指定 processInstanceId 流程编号下的首个“待办”(未审批、且可审核)的任务 |
| 198 | * | 198 | * |
| 199 | - * @param userId 用户编号 | 199 | + * @param userId 用户编号 |
| 200 | * @param processInstanceId 流程编号 | 200 | * @param processInstanceId 流程编号 |
| 201 | * @return 任务 | 201 | * @return 任务 |
| 202 | */ | 202 | */ |
| @@ -599,15 +599,15 @@ public class BpmTaskServiceImpl implements BpmTaskService { | @@ -599,15 +599,15 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||
| 599 | 599 | ||
| 600 | /** | 600 | /** |
| 601 | * 校验选择的下一个节点的审批人,是否合法 | 601 | * 校验选择的下一个节点的审批人,是否合法 |
| 602 | - * | 602 | + * <p> |
| 603 | * 1. 是否有漏选:没有选择审批人 | 603 | * 1. 是否有漏选:没有选择审批人 |
| 604 | * 2. 是否有多选:非下一个节点 | 604 | * 2. 是否有多选:非下一个节点 |
| 605 | * | 605 | * |
| 606 | * @param taskDefinitionKey 当前任务节点标识 | 606 | * @param taskDefinitionKey 当前任务节点标识 |
| 607 | - * @param variables 流程变量 | ||
| 608 | - * @param bpmnModel 流程模型 | ||
| 609 | - * @param nextAssignees 下一个节点审批人集合(参数) | ||
| 610 | - * @param processInstance 流程实例 | 607 | + * @param variables 流程变量 |
| 608 | + * @param bpmnModel 流程模型 | ||
| 609 | + * @param nextAssignees 下一个节点审批人集合(参数) | ||
| 610 | + * @param processInstance 流程实例 | ||
| 611 | */ | 611 | */ |
| 612 | @SuppressWarnings("unchecked") | 612 | @SuppressWarnings("unchecked") |
| 613 | private Map<String, Object> validateAndSetNextAssignees(String taskDefinitionKey, Map<String, Object> variables, BpmnModel bpmnModel, | 613 | private Map<String, Object> validateAndSetNextAssignees(String taskDefinitionKey, Map<String, Object> variables, BpmnModel bpmnModel, |
| @@ -659,7 +659,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { | @@ -659,7 +659,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||
| 659 | approveUserSelectAssignees = new HashMap<>(); | 659 | approveUserSelectAssignees = new HashMap<>(); |
| 660 | } | 660 | } |
| 661 | approveUserSelectAssignees.put(nextFlowNode.getId(), assignees); | 661 | approveUserSelectAssignees.put(nextFlowNode.getId(), assignees); |
| 662 | - Map<String,List<Long>> existingApproveUserSelectAssignees = (Map<String,List<Long>>) variables.get( | 662 | + Map<String, List<Long>> existingApproveUserSelectAssignees = (Map<String, List<Long>>) variables.get( |
| 663 | BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_APPROVE_USER_SELECT_ASSIGNEES); | 663 | BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_APPROVE_USER_SELECT_ASSIGNEES); |
| 664 | if (CollUtil.isNotEmpty(existingApproveUserSelectAssignees)) { | 664 | if (CollUtil.isNotEmpty(existingApproveUserSelectAssignees)) { |
| 665 | approveUserSelectAssignees.putAll(existingApproveUserSelectAssignees); | 665 | approveUserSelectAssignees.putAll(existingApproveUserSelectAssignees); |
| @@ -1177,6 +1177,63 @@ public class BpmTaskServiceImpl implements BpmTaskService { | @@ -1177,6 +1177,63 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||
| 1177 | processInstanceCopyService.createProcessInstanceCopy(reqVO.getCopyUserIds(), reqVO.getReason(), reqVO.getId()); | 1177 | processInstanceCopyService.createProcessInstanceCopy(reqVO.getCopyUserIds(), reqVO.getReason(), reqVO.getId()); |
| 1178 | } | 1178 | } |
| 1179 | 1179 | ||
| 1180 | + @Override | ||
| 1181 | + @Transactional(rollbackFor = Exception.class) | ||
| 1182 | + public void withdrawTask(Long userId, String taskId) { | ||
| 1183 | + // 1.1 查询本人已办任务 | ||
| 1184 | + HistoricTaskInstance taskInstance = historyService.createHistoricTaskInstanceQuery() | ||
| 1185 | + .taskId(taskId).taskAssignee(userId.toString()).finished().singleResult(); | ||
| 1186 | + if (ObjUtil.isNull(taskInstance)) { | ||
| 1187 | + throw exception(TASK_WITHDRAW_FAIL_TASK_NOT_EXISTS); | ||
| 1188 | + } | ||
| 1189 | + // 1.2 校验流程是否结束 | ||
| 1190 | + ProcessInstance processInstance = processInstanceService.getProcessInstance(taskInstance.getProcessInstanceId()); | ||
| 1191 | + if (ObjUtil.isNull(processInstance)) { | ||
| 1192 | + throw exception(TASK_WITHDRAW_FAIL_PROCESS_NOT_RUNNING); | ||
| 1193 | + } | ||
| 1194 | + // 1.3 判断此流程是否允许撤回 | ||
| 1195 | + BpmProcessDefinitionInfoDO processDefinitionInfo = bpmProcessDefinitionService.getProcessDefinitionInfo( | ||
| 1196 | + processInstance.getProcessDefinitionId()); | ||
| 1197 | + if (ObjUtil.isNull(processDefinitionInfo) || !Boolean.TRUE.equals(processDefinitionInfo.getAllowWithdrawTask())) { | ||
| 1198 | + throw exception(TASK_WITHDRAW_FAIL_NOT_ALLOW); | ||
| 1199 | + } | ||
| 1200 | + // 1.4 判断下一个节点是否被审批过,如果是则无法撤回 | ||
| 1201 | + BpmnModel bpmnModel = modelService.getBpmnModelByDefinitionId(taskInstance.getProcessDefinitionId()); | ||
| 1202 | + UserTask userTask = (UserTask) BpmnModelUtils.getFlowElementById(bpmnModel, taskInstance.getTaskDefinitionKey()); | ||
| 1203 | + List<String> nextUserTaskKeys = convertList(BpmnModelUtils.getNextUserTasks(userTask), UserTask::getId); | ||
| 1204 | + if (CollUtil.isEmpty(nextUserTaskKeys)) { | ||
| 1205 | + throw exception(TASK_WITHDRAW_FAIL_NEXT_TASK_NOT_ALLOW); | ||
| 1206 | + } | ||
| 1207 | + // TODO @芋艿:是否选择升级flowable版本解决taskCreatedAfter、taskCreatedBefore问题,升级7.1.0可以;包括 todo 和 done 那边的查询哇??? 是的! | ||
| 1208 | + long nextUserTaskFinishedCount = historyService.createHistoricTaskInstanceQuery() | ||
| 1209 | + .processInstanceId(processInstance.getProcessInstanceId()).taskDefinitionKeys(nextUserTaskKeys) | ||
| 1210 | + .taskCreatedAfter(taskInstance.getEndTime()).finished().count(); | ||
| 1211 | + if (nextUserTaskFinishedCount > 0) { | ||
| 1212 | + throw exception(TASK_WITHDRAW_FAIL_NEXT_TASK_NOT_ALLOW); | ||
| 1213 | + } | ||
| 1214 | + // 1.5 获取需要撤回的运行任务 | ||
| 1215 | + List<Task> runningTasks = taskService.createTaskQuery().processInstanceId(processInstance.getProcessInstanceId()) | ||
| 1216 | + .taskDefinitionKeys(nextUserTaskKeys).active().list(); | ||
| 1217 | + if (CollUtil.isEmpty(runningTasks)) { | ||
| 1218 | + throw exception(TASK_WITHDRAW_FAIL_NEXT_TASK_NOT_ALLOW); | ||
| 1219 | + } | ||
| 1220 | + | ||
| 1221 | + // 2.1 取消当前任务 | ||
| 1222 | + List<String> withdrawExecutionIds = new ArrayList<>(); | ||
| 1223 | + for (Task task : runningTasks) { | ||
| 1224 | + // 标记撤回任务为取消 | ||
| 1225 | + taskService.addComment(task.getId(), taskInstance.getProcessInstanceId(), BpmCommentTypeEnum.CANCEL.getType(), | ||
| 1226 | + BpmCommentTypeEnum.CANCEL.formatComment("前一节点撤回")); | ||
| 1227 | + updateTaskStatusAndReason(task.getId(), BpmTaskStatusEnum.CANCEL.getStatus(), BpmReasonEnum.CANCEL_BY_WITHDRAW.getReason()); | ||
| 1228 | + withdrawExecutionIds.add(task.getExecutionId()); | ||
| 1229 | + } | ||
| 1230 | + // 2.2 执行撤回操作 | ||
| 1231 | + runtimeService.createChangeActivityStateBuilder() | ||
| 1232 | + .processInstanceId(processInstance.getProcessInstanceId()) | ||
| 1233 | + .moveExecutionsToSingleActivityId(withdrawExecutionIds, taskInstance.getTaskDefinitionKey()) | ||
| 1234 | + .changeState(); | ||
| 1235 | + } | ||
| 1236 | + | ||
| 1180 | /** | 1237 | /** |
| 1181 | * 校验任务是否能被减签 | 1238 | * 校验任务是否能被减签 |
| 1182 | * | 1239 | * |
| @@ -1223,7 +1280,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { | @@ -1223,7 +1280,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||
| 1223 | } | 1280 | } |
| 1224 | 1281 | ||
| 1225 | // 2. 任务前置通知 | 1282 | // 2. 任务前置通知 |
| 1226 | - if (ObjUtil.isNotNull(processDefinitionInfo.getTaskBeforeTriggerSetting())){ | 1283 | + if (ObjUtil.isNotNull(processDefinitionInfo.getTaskBeforeTriggerSetting())) { |
| 1227 | BpmModelMetaInfoVO.HttpRequestSetting setting = processDefinitionInfo.getTaskBeforeTriggerSetting(); | 1284 | BpmModelMetaInfoVO.HttpRequestSetting setting = processDefinitionInfo.getTaskBeforeTriggerSetting(); |
| 1228 | BpmHttpRequestUtils.executeBpmHttpRequest(processInstance, | 1285 | BpmHttpRequestUtils.executeBpmHttpRequest(processInstance, |
| 1229 | setting.getUrl(), setting.getHeader(), setting.getBody(), true, setting.getResponse()); | 1286 | setting.getUrl(), setting.getHeader(), setting.getBody(), true, setting.getResponse()); |
| @@ -1350,7 +1407,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { | @@ -1350,7 +1407,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||
| 1350 | .taskVariableValueEquals(BpmnVariableConstants.TASK_VARIABLE_STATUS, BpmTaskStatusEnum.APPROVE.getStatus()) | 1407 | .taskVariableValueEquals(BpmnVariableConstants.TASK_VARIABLE_STATUS, BpmTaskStatusEnum.APPROVE.getStatus()) |
| 1351 | .finished(); | 1408 | .finished(); |
| 1352 | if (BpmAutoApproveTypeEnum.APPROVE_ALL.getType().equals(processDefinitionInfo.getAutoApprovalType()) | 1409 | if (BpmAutoApproveTypeEnum.APPROVE_ALL.getType().equals(processDefinitionInfo.getAutoApprovalType()) |
| 1353 | - && sameAssigneeQuery.count() > 0) { | 1410 | + && sameAssigneeQuery.count() > 0) { |
| 1354 | getSelf().approveTask(Long.valueOf(task.getAssignee()), new BpmTaskApproveReqVO().setId(task.getId()) | 1411 | getSelf().approveTask(Long.valueOf(task.getAssignee()), new BpmTaskApproveReqVO().setId(task.getId()) |
| 1355 | .setReason(BpmAutoApproveTypeEnum.APPROVE_ALL.getName())); | 1412 | .setReason(BpmAutoApproveTypeEnum.APPROVE_ALL.getName())); |
| 1356 | return; | 1413 | return; |
| @@ -1362,7 +1419,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { | @@ -1362,7 +1419,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||
| 1362 | return; | 1419 | return; |
| 1363 | } | 1420 | } |
| 1364 | List<String> sourceTaskIds = convertList(BpmnModelUtils.getElementIncomingFlows( // 获取所有上一个节点 | 1421 | List<String> sourceTaskIds = convertList(BpmnModelUtils.getElementIncomingFlows( // 获取所有上一个节点 |
| 1365 | - BpmnModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey())), | 1422 | + BpmnModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey())), |
| 1366 | SequenceFlow::getSourceRef); | 1423 | SequenceFlow::getSourceRef); |
| 1367 | if (sameAssigneeQuery.taskDefinitionKeys(sourceTaskIds).count() > 0) { | 1424 | if (sameAssigneeQuery.taskDefinitionKeys(sourceTaskIds).count() > 0) { |
| 1368 | getSelf().approveTask(Long.valueOf(task.getAssignee()), new BpmTaskApproveReqVO().setId(task.getId()) | 1425 | getSelf().approveTask(Long.valueOf(task.getAssignee()), new BpmTaskApproveReqVO().setId(task.getId()) |
| @@ -1387,7 +1444,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { | @@ -1387,7 +1444,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||
| 1387 | PROCESS_INSTANCE_VARIABLE_SKIP_START_USER_NODE, String.class)); | 1444 | PROCESS_INSTANCE_VARIABLE_SKIP_START_USER_NODE, String.class)); |
| 1388 | if (userTaskElement.getId().equals(START_USER_NODE_ID) | 1445 | if (userTaskElement.getId().equals(START_USER_NODE_ID) |
| 1389 | && (skipStartUserNodeFlag == null // 目的:一般是“主流程”,发起人节点,自动通过审核 | 1446 | && (skipStartUserNodeFlag == null // 目的:一般是“主流程”,发起人节点,自动通过审核 |
| 1390 | - || BooleanUtil.isTrue(skipStartUserNodeFlag)) // 目的:一般是“子流程”,发起人节点,按配置自动通过审核 | 1447 | + || BooleanUtil.isTrue(skipStartUserNodeFlag)) // 目的:一般是“子流程”,发起人节点,按配置自动通过审核 |
| 1391 | && ObjUtil.notEqual(returnTaskFlag, Boolean.TRUE)) { | 1448 | && ObjUtil.notEqual(returnTaskFlag, Boolean.TRUE)) { |
| 1392 | getSelf().approveTask(Long.valueOf(task.getAssignee()), new BpmTaskApproveReqVO().setId(task.getId()) | 1449 | getSelf().approveTask(Long.valueOf(task.getAssignee()), new BpmTaskApproveReqVO().setId(task.getId()) |
| 1393 | .setReason(BpmReasonEnum.ASSIGN_START_USER_APPROVE_WHEN_SKIP_START_USER_NODE.getReason())); | 1450 | .setReason(BpmReasonEnum.ASSIGN_START_USER_APPROVE_WHEN_SKIP_START_USER_NODE.getReason())); |
| @@ -1456,7 +1513,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { | @@ -1456,7 +1513,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||
| 1456 | } | 1513 | } |
| 1457 | 1514 | ||
| 1458 | // 任务后置通知 | 1515 | // 任务后置通知 |
| 1459 | - if (ObjUtil.isNotNull(processDefinitionInfo.getTaskAfterTriggerSetting())){ | 1516 | + if (ObjUtil.isNotNull(processDefinitionInfo.getTaskAfterTriggerSetting())) { |
| 1460 | BpmModelMetaInfoVO.HttpRequestSetting setting = processDefinitionInfo.getTaskAfterTriggerSetting(); | 1517 | BpmModelMetaInfoVO.HttpRequestSetting setting = processDefinitionInfo.getTaskAfterTriggerSetting(); |
| 1461 | BpmHttpRequestUtils.executeBpmHttpRequest(processInstance, | 1518 | BpmHttpRequestUtils.executeBpmHttpRequest(processInstance, |
| 1462 | setting.getUrl(), setting.getHeader(), setting.getBody(), true, setting.getResponse()); | 1519 | setting.getUrl(), setting.getHeader(), setting.getBody(), true, setting.getResponse()); |
yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java
| @@ -14,7 +14,7 @@ public interface LogRecordConstants { | @@ -14,7 +14,7 @@ public interface LogRecordConstants { | ||
| 14 | String CRM_CLUE_CREATE_SUB_TYPE = "创建线索"; | 14 | String CRM_CLUE_CREATE_SUB_TYPE = "创建线索"; |
| 15 | String CRM_CLUE_CREATE_SUCCESS = "创建了线索{{#clue.name}}"; | 15 | String CRM_CLUE_CREATE_SUCCESS = "创建了线索{{#clue.name}}"; |
| 16 | String CRM_CLUE_UPDATE_SUB_TYPE = "更新线索"; | 16 | String CRM_CLUE_UPDATE_SUB_TYPE = "更新线索"; |
| 17 | - String CRM_CLUE_UPDATE_SUCCESS = "更新了线索【{{#clueName}}】: {_DIFF{#updateReq}}"; | 17 | + String CRM_CLUE_UPDATE_SUCCESS = "更新了线索【{{#clueName}}】: {_DIFF{#updateReqVO}}"; |
| 18 | String CRM_CLUE_DELETE_SUB_TYPE = "删除线索"; | 18 | String CRM_CLUE_DELETE_SUB_TYPE = "删除线索"; |
| 19 | String CRM_CLUE_DELETE_SUCCESS = "删除了线索【{{#clueName}}】"; | 19 | String CRM_CLUE_DELETE_SUCCESS = "删除了线索【{{#clueName}}】"; |
| 20 | String CRM_CLUE_TRANSFER_SUB_TYPE = "转移线索"; | 20 | String CRM_CLUE_TRANSFER_SUB_TYPE = "转移线索"; |
yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java
| @@ -106,7 +106,7 @@ public class CrmClueServiceImpl implements CrmClueService { | @@ -106,7 +106,7 @@ public class CrmClueServiceImpl implements CrmClueService { | ||
| 106 | 106 | ||
| 107 | // 3. 记录操作日志上下文 | 107 | // 3. 记录操作日志上下文 |
| 108 | updateReqVO.setOwnerUserId(oldClue.getOwnerUserId()); // 避免操作日志出现“删除负责人”的情况 | 108 | updateReqVO.setOwnerUserId(oldClue.getOwnerUserId()); // 避免操作日志出现“删除负责人”的情况 |
| 109 | - LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldClue, CrmCustomerSaveReqVO.class)); | 109 | + LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldClue, CrmClueSaveReqVO.class)); |
| 110 | LogRecordContext.putVariable("clueName", oldClue.getName()); | 110 | LogRecordContext.putVariable("clueName", oldClue.getName()); |
| 111 | } | 111 | } |
| 112 | 112 |
yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java
| @@ -159,10 +159,10 @@ public class CrmContactServiceImpl implements CrmContactService { | @@ -159,10 +159,10 @@ public class CrmContactServiceImpl implements CrmContactService { | ||
| 159 | // 2. 删除联系人 | 159 | // 2. 删除联系人 |
| 160 | contactMapper.deleteById(id); | 160 | contactMapper.deleteById(id); |
| 161 | 161 | ||
| 162 | - // 4.1 删除数据权限 | ||
| 163 | - permissionService.deletePermission(CrmBizTypeEnum.CRM_CONTACT.getType(), id); | ||
| 164 | - // 4.2 删除商机关联 | 162 | + // 4.1 删除商机关联 |
| 165 | contactBusinessService.deleteContactBusinessByContactId(id); | 163 | contactBusinessService.deleteContactBusinessByContactId(id); |
| 164 | + // 4.2 删除数据权限 | ||
| 165 | + permissionService.deletePermission(CrmBizTypeEnum.CRM_CONTACT.getType(), id); | ||
| 166 | 166 | ||
| 167 | // 记录操作日志上下文 | 167 | // 记录操作日志上下文 |
| 168 | LogRecordContext.putVariable("contactName", contact.getName()); | 168 | LogRecordContext.putVariable("contactName", contact.getName()); |
yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java
| @@ -43,7 +43,7 @@ public class FileController { | @@ -43,7 +43,7 @@ public class FileController { | ||
| 43 | 43 | ||
| 44 | @PostMapping("/upload") | 44 | @PostMapping("/upload") |
| 45 | @Operation(summary = "上传文件", description = "模式一:后端上传文件") | 45 | @Operation(summary = "上传文件", description = "模式一:后端上传文件") |
| 46 | - public CommonResult<String> uploadFile(FileUploadReqVO uploadReqVO) throws Exception { | 46 | + public CommonResult<String> uploadFile(@Valid FileUploadReqVO uploadReqVO) throws Exception { |
| 47 | MultipartFile file = uploadReqVO.getFile(); | 47 | MultipartFile file = uploadReqVO.getFile(); |
| 48 | byte[] content = IoUtil.readBytes(file.getInputStream()); | 48 | byte[] content = IoUtil.readBytes(file.getInputStream()); |
| 49 | return success(fileService.createFile(content, file.getOriginalFilename(), | 49 | return success(fileService.createFile(content, file.getOriginalFilename(), |
yudao-module-infra/src/main/resources/codegen/java/test/serviceTest.vm
| @@ -2,7 +2,6 @@ package ${basePackage}.module.${table.moduleName}.service.${table.businessName}; | @@ -2,7 +2,6 @@ package ${basePackage}.module.${table.moduleName}.service.${table.businessName}; | ||
| 2 | 2 | ||
| 3 | import org.junit.jupiter.api.Disabled; | 3 | import org.junit.jupiter.api.Disabled; |
| 4 | import org.junit.jupiter.api.Test; | 4 | import org.junit.jupiter.api.Test; |
| 5 | -import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 6 | 5 | ||
| 7 | import ${jakartaPackage}.annotation.Resource; | 6 | import ${jakartaPackage}.annotation.Resource; |
| 8 | 7 |
yudao-module-infra/src/main/resources/codegen/vue/views/components/list_sub_erp.vue.vm
| @@ -170,6 +170,7 @@ | @@ -170,6 +170,7 @@ | ||
| 170 | await this.#[[$modal]]#.confirm('是否确认删除?') | 170 | await this.#[[$modal]]#.confirm('是否确认删除?') |
| 171 | try { | 171 | try { |
| 172 | await ${simpleClassName}Api.delete${subSimpleClassName}List(this.checkedIds); | 172 | await ${simpleClassName}Api.delete${subSimpleClassName}List(this.checkedIds); |
| 173 | + this.checkedIds = []; | ||
| 173 | await this.getList(); | 174 | await this.getList(); |
| 174 | this.#[[$modal]]#.msgSuccess("删除成功"); | 175 | this.#[[$modal]]#.msgSuccess("删除成功"); |
| 175 | } catch {} | 176 | } catch {} |
yudao-module-infra/src/main/resources/codegen/vue/views/index.vue.vm
| @@ -338,6 +338,7 @@ export default { | @@ -338,6 +338,7 @@ export default { | ||
| 338 | await this.#[[$modal]]#.confirm('是否确认删除?') | 338 | await this.#[[$modal]]#.confirm('是否确认删除?') |
| 339 | try { | 339 | try { |
| 340 | await ${simpleClassName}Api.delete${simpleClassName}List(this.checkedIds); | 340 | await ${simpleClassName}Api.delete${simpleClassName}List(this.checkedIds); |
| 341 | + this.checkedIds = []; | ||
| 341 | await this.getList(); | 342 | await this.getList(); |
| 342 | this.#[[$modal]]#.msgSuccess("删除成功"); | 343 | this.#[[$modal]]#.msgSuccess("删除成功"); |
| 343 | } catch {} | 344 | } catch {} |
yudao-module-infra/src/main/resources/codegen/vue3/views/components/list_sub_erp.vue.vm
| @@ -209,6 +209,7 @@ const handleDeleteBatch = async () => { | @@ -209,6 +209,7 @@ const handleDeleteBatch = async () => { | ||
| 209 | // 删除的二次确认 | 209 | // 删除的二次确认 |
| 210 | await message.delConfirm() | 210 | await message.delConfirm() |
| 211 | await ${simpleClassName}Api.delete${subSimpleClassName}List(checkedIds.value); | 211 | await ${simpleClassName}Api.delete${subSimpleClassName}List(checkedIds.value); |
| 212 | + checkedIds.value = []; | ||
| 212 | message.success(t('common.delSuccess')) | 213 | message.success(t('common.delSuccess')) |
| 213 | await getList(); | 214 | await getList(); |
| 214 | } catch {} | 215 | } catch {} |
yudao-module-infra/src/main/resources/codegen/vue3/views/index.vue.vm
| @@ -366,6 +366,7 @@ const handleDeleteBatch = async () => { | @@ -366,6 +366,7 @@ const handleDeleteBatch = async () => { | ||
| 366 | // 删除的二次确认 | 366 | // 删除的二次确认 |
| 367 | await message.delConfirm() | 367 | await message.delConfirm() |
| 368 | await ${simpleClassName}Api.delete${simpleClassName}List(checkedIds.value); | 368 | await ${simpleClassName}Api.delete${simpleClassName}List(checkedIds.value); |
| 369 | + checkedIds.value = []; | ||
| 369 | message.success(t('common.delSuccess')) | 370 | message.success(t('common.delSuccess')) |
| 370 | await getList(); | 371 | await getList(); |
| 371 | } catch {} | 372 | } catch {} |
yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/general/views/index.vue.vm
| @@ -168,6 +168,7 @@ async function handleDeleteBatch() { | @@ -168,6 +168,7 @@ async function handleDeleteBatch() { | ||
| 168 | }); | 168 | }); |
| 169 | try { | 169 | try { |
| 170 | await delete${simpleClassName}List(checkedIds.value); | 170 | await delete${simpleClassName}List(checkedIds.value); |
| 171 | + checkedIds.value = []; | ||
| 171 | message.success( $t('ui.actionMessage.deleteSuccess') ); | 172 | message.success( $t('ui.actionMessage.deleteSuccess') ); |
| 172 | await getList(); | 173 | await getList(); |
| 173 | } finally { | 174 | } finally { |
yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/general/views/modules/list_sub_erp.vue.vm
| @@ -92,6 +92,7 @@ async function handleDeleteBatch() { | @@ -92,6 +92,7 @@ async function handleDeleteBatch() { | ||
| 92 | }); | 92 | }); |
| 93 | try { | 93 | try { |
| 94 | await delete${subSimpleClassName}List(checkedIds.value); | 94 | await delete${subSimpleClassName}List(checkedIds.value); |
| 95 | + checkedIds.value = []; | ||
| 95 | message.success( $t('ui.actionMessage.deleteSuccess') ); | 96 | message.success( $t('ui.actionMessage.deleteSuccess') ); |
| 96 | await getList(); | 97 | await getList(); |
| 97 | } finally { | 98 | } finally { |
yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/schema/views/index.vue.vm
| @@ -102,6 +102,7 @@ async function handleDeleteBatch() { | @@ -102,6 +102,7 @@ async function handleDeleteBatch() { | ||
| 102 | }); | 102 | }); |
| 103 | try { | 103 | try { |
| 104 | await delete${simpleClassName}List(checkedIds.value); | 104 | await delete${simpleClassName}List(checkedIds.value); |
| 105 | + checkedIds.value = []; | ||
| 105 | message.success({ | 106 | message.success({ |
| 106 | content: $t('ui.actionMessage.deleteSuccess'), | 107 | content: $t('ui.actionMessage.deleteSuccess'), |
| 107 | key: 'action_key_msg', | 108 | key: 'action_key_msg', |
yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/schema/views/modules/list_sub_erp.vue.vm
| @@ -82,6 +82,7 @@ async function handleDeleteBatch() { | @@ -82,6 +82,7 @@ async function handleDeleteBatch() { | ||
| 82 | }); | 82 | }); |
| 83 | try { | 83 | try { |
| 84 | await delete${subSimpleClassName}List(checkedIds.value); | 84 | await delete${subSimpleClassName}List(checkedIds.value); |
| 85 | + checkedIds.value = []; | ||
| 85 | message.success({ | 86 | message.success({ |
| 86 | content: $t('ui.actionMessage.deleteSuccess', [row.id]), | 87 | content: $t('ui.actionMessage.deleteSuccess', [row.id]), |
| 87 | key: 'action_key_msg', | 88 | key: 'action_key_msg', |
yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/general/views/index.vue.vm
| @@ -163,6 +163,7 @@ async function handleDeleteBatch() { | @@ -163,6 +163,7 @@ async function handleDeleteBatch() { | ||
| 163 | }); | 163 | }); |
| 164 | try { | 164 | try { |
| 165 | await delete${simpleClassName}List(checkedIds.value); | 165 | await delete${simpleClassName}List(checkedIds.value); |
| 166 | + checkedIds.value = []; | ||
| 166 | ElMessage.success($t('ui.actionMessage.deleteSuccess')); | 167 | ElMessage.success($t('ui.actionMessage.deleteSuccess')); |
| 167 | await getList(); | 168 | await getList(); |
| 168 | } finally { | 169 | } finally { |
yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/general/views/modules/list_sub_erp.vue.vm
| @@ -87,6 +87,7 @@ async function handleDeleteBatch() { | @@ -87,6 +87,7 @@ async function handleDeleteBatch() { | ||
| 87 | }); | 87 | }); |
| 88 | try { | 88 | try { |
| 89 | await delete${subSimpleClassName}List(checkedIds.value); | 89 | await delete${subSimpleClassName}List(checkedIds.value); |
| 90 | + checkedIds.value = []; | ||
| 90 | ElMessage.success($t('ui.actionMessage.deleteSuccess')); | 91 | ElMessage.success($t('ui.actionMessage.deleteSuccess')); |
| 91 | await getList(); | 92 | await getList(); |
| 92 | } finally { | 93 | } finally { |
yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/schema/views/index.vue.vm
| @@ -99,6 +99,7 @@ async function handleDeleteBatch() { | @@ -99,6 +99,7 @@ async function handleDeleteBatch() { | ||
| 99 | }); | 99 | }); |
| 100 | try { | 100 | try { |
| 101 | await delete${simpleClassName}List(checkedIds.value); | 101 | await delete${simpleClassName}List(checkedIds.value); |
| 102 | + checkedIds.value = []; | ||
| 102 | ElMessage.success($t('ui.actionMessage.deleteSuccess')); | 103 | ElMessage.success($t('ui.actionMessage.deleteSuccess')); |
| 103 | onRefresh(); | 104 | onRefresh(); |
| 104 | } finally { | 105 | } finally { |
yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/schema/views/modules/list_sub_erp.vue.vm
| @@ -79,6 +79,7 @@ async function handleDeleteBatch() { | @@ -79,6 +79,7 @@ async function handleDeleteBatch() { | ||
| 79 | }); | 79 | }); |
| 80 | try { | 80 | try { |
| 81 | await delete${subSimpleClassName}List(checkedIds.value); | 81 | await delete${subSimpleClassName}List(checkedIds.value); |
| 82 | + checkedIds.value = []; | ||
| 82 | ElMessage.success($t('ui.actionMessage.deleteSuccess')); | 83 | ElMessage.success($t('ui.actionMessage.deleteSuccess')); |
| 83 | onRefresh(); | 84 | onRefresh(); |
| 84 | } finally { | 85 | } finally { |
yudao-module-infra/src/test/java/cn/iocoder/yudao/module/infra/service/codegen/CodegenServiceImplTest.java
| @@ -24,8 +24,8 @@ import com.baomidou.mybatisplus.generator.config.po.TableField; | @@ -24,8 +24,8 @@ import com.baomidou.mybatisplus.generator.config.po.TableField; | ||
| 24 | import com.baomidou.mybatisplus.generator.config.po.TableInfo; | 24 | import com.baomidou.mybatisplus.generator.config.po.TableInfo; |
| 25 | import jakarta.annotation.Resource; | 25 | import jakarta.annotation.Resource; |
| 26 | import org.junit.jupiter.api.Test; | 26 | import org.junit.jupiter.api.Test; |
| 27 | -import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 28 | import org.springframework.context.annotation.Import; | 27 | import org.springframework.context.annotation.Import; |
| 28 | +import org.springframework.test.context.bean.override.mockito.MockitoBean; | ||
| 29 | 29 | ||
| 30 | import java.util.Arrays; | 30 | import java.util.Arrays; |
| 31 | import java.util.Collections; | 31 | import java.util.Collections; |
| @@ -60,15 +60,15 @@ public class CodegenServiceImplTest extends BaseDbUnitTest { | @@ -60,15 +60,15 @@ public class CodegenServiceImplTest extends BaseDbUnitTest { | ||
| 60 | @Resource | 60 | @Resource |
| 61 | private CodegenColumnMapper codegenColumnMapper; | 61 | private CodegenColumnMapper codegenColumnMapper; |
| 62 | 62 | ||
| 63 | - @MockBean | 63 | + @MockitoBean |
| 64 | private DatabaseTableService databaseTableService; | 64 | private DatabaseTableService databaseTableService; |
| 65 | 65 | ||
| 66 | - @MockBean | 66 | + @MockitoBean |
| 67 | private CodegenBuilder codegenBuilder; | 67 | private CodegenBuilder codegenBuilder; |
| 68 | - @MockBean | 68 | + @MockitoBean |
| 69 | private CodegenEngine codegenEngine; | 69 | private CodegenEngine codegenEngine; |
| 70 | 70 | ||
| 71 | - @MockBean | 71 | + @MockitoBean |
| 72 | private CodegenProperties codegenProperties; | 72 | private CodegenProperties codegenProperties; |
| 73 | 73 | ||
| 74 | @Test | 74 | @Test |
yudao-module-infra/src/test/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigServiceImplTest.java
| @@ -11,14 +11,14 @@ import cn.iocoder.yudao.module.infra.dal.dataobject.db.DataSourceConfigDO; | @@ -11,14 +11,14 @@ import cn.iocoder.yudao.module.infra.dal.dataobject.db.DataSourceConfigDO; | ||
| 11 | import cn.iocoder.yudao.module.infra.dal.mysql.db.DataSourceConfigMapper; | 11 | import cn.iocoder.yudao.module.infra.dal.mysql.db.DataSourceConfigMapper; |
| 12 | import com.baomidou.dynamic.datasource.creator.DataSourceProperty; | 12 | import com.baomidou.dynamic.datasource.creator.DataSourceProperty; |
| 13 | import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties; | 13 | import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties; |
| 14 | +import jakarta.annotation.Resource; | ||
| 14 | import org.junit.jupiter.api.BeforeEach; | 15 | import org.junit.jupiter.api.BeforeEach; |
| 15 | import org.junit.jupiter.api.Test; | 16 | import org.junit.jupiter.api.Test; |
| 16 | import org.mockito.MockedStatic; | 17 | import org.mockito.MockedStatic; |
| 17 | import org.mockito.stubbing.Answer; | 18 | import org.mockito.stubbing.Answer; |
| 18 | -import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 19 | import org.springframework.context.annotation.Import; | 19 | import org.springframework.context.annotation.Import; |
| 20 | +import org.springframework.test.context.bean.override.mockito.MockitoBean; | ||
| 20 | 21 | ||
| 21 | -import jakarta.annotation.Resource; | ||
| 22 | import java.util.List; | 22 | import java.util.List; |
| 23 | 23 | ||
| 24 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; | 24 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; |
| @@ -46,10 +46,10 @@ public class DataSourceConfigServiceImplTest extends BaseDbUnitTest { | @@ -46,10 +46,10 @@ public class DataSourceConfigServiceImplTest extends BaseDbUnitTest { | ||
| 46 | @Resource | 46 | @Resource |
| 47 | private DataSourceConfigMapper dataSourceConfigMapper; | 47 | private DataSourceConfigMapper dataSourceConfigMapper; |
| 48 | 48 | ||
| 49 | - @MockBean | 49 | + @MockitoBean |
| 50 | private AES aes; | 50 | private AES aes; |
| 51 | 51 | ||
| 52 | - @MockBean | 52 | + @MockitoBean |
| 53 | private DynamicDataSourceProperties dynamicDataSourceProperties; | 53 | private DynamicDataSourceProperties dynamicDataSourceProperties; |
| 54 | 54 | ||
| 55 | @BeforeEach | 55 | @BeforeEach |
yudao-module-infra/src/test/java/cn/iocoder/yudao/module/infra/service/db/DatabaseTableServiceImplTest.java
| @@ -5,12 +5,12 @@ import cn.iocoder.yudao.module.infra.dal.dataobject.db.DataSourceConfigDO; | @@ -5,12 +5,12 @@ import cn.iocoder.yudao.module.infra.dal.dataobject.db.DataSourceConfigDO; | ||
| 5 | import com.baomidou.mybatisplus.generator.config.po.TableField; | 5 | import com.baomidou.mybatisplus.generator.config.po.TableField; |
| 6 | import com.baomidou.mybatisplus.generator.config.po.TableInfo; | 6 | import com.baomidou.mybatisplus.generator.config.po.TableInfo; |
| 7 | import com.baomidou.mybatisplus.generator.config.rules.DbColumnType; | 7 | import com.baomidou.mybatisplus.generator.config.rules.DbColumnType; |
| 8 | +import jakarta.annotation.Resource; | ||
| 8 | import org.apache.ibatis.type.JdbcType; | 9 | import org.apache.ibatis.type.JdbcType; |
| 9 | import org.junit.jupiter.api.Test; | 10 | import org.junit.jupiter.api.Test; |
| 10 | -import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 11 | import org.springframework.context.annotation.Import; | 11 | import org.springframework.context.annotation.Import; |
| 12 | +import org.springframework.test.context.bean.override.mockito.MockitoBean; | ||
| 12 | 13 | ||
| 13 | -import jakarta.annotation.Resource; | ||
| 14 | import java.util.List; | 14 | import java.util.List; |
| 15 | 15 | ||
| 16 | import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; | 16 | import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; |
| @@ -24,7 +24,7 @@ public class DatabaseTableServiceImplTest extends BaseDbUnitTest { | @@ -24,7 +24,7 @@ public class DatabaseTableServiceImplTest extends BaseDbUnitTest { | ||
| 24 | @Resource | 24 | @Resource |
| 25 | private DatabaseTableServiceImpl databaseTableService; | 25 | private DatabaseTableServiceImpl databaseTableService; |
| 26 | 26 | ||
| 27 | - @MockBean | 27 | + @MockitoBean |
| 28 | private DataSourceConfigService dataSourceConfigService; | 28 | private DataSourceConfigService dataSourceConfigService; |
| 29 | 29 | ||
| 30 | @Test | 30 | @Test |
yudao-module-infra/src/test/java/cn/iocoder/yudao/module/infra/service/file/FileConfigServiceImplTest.java
| @@ -4,24 +4,24 @@ import cn.hutool.core.date.DatePattern; | @@ -4,24 +4,24 @@ import cn.hutool.core.date.DatePattern; | ||
| 4 | import cn.hutool.core.date.LocalDateTimeUtil; | 4 | import cn.hutool.core.date.LocalDateTimeUtil; |
| 5 | import cn.hutool.core.map.MapUtil; | 5 | import cn.hutool.core.map.MapUtil; |
| 6 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 6 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 7 | +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; | ||
| 8 | +import cn.iocoder.yudao.module.infra.controller.admin.file.vo.config.FileConfigPageReqVO; | ||
| 9 | +import cn.iocoder.yudao.module.infra.controller.admin.file.vo.config.FileConfigSaveReqVO; | ||
| 10 | +import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileConfigDO; | ||
| 11 | +import cn.iocoder.yudao.module.infra.dal.mysql.file.FileConfigMapper; | ||
| 7 | import cn.iocoder.yudao.module.infra.framework.file.core.client.FileClient; | 12 | import cn.iocoder.yudao.module.infra.framework.file.core.client.FileClient; |
| 8 | import cn.iocoder.yudao.module.infra.framework.file.core.client.FileClientConfig; | 13 | import cn.iocoder.yudao.module.infra.framework.file.core.client.FileClientConfig; |
| 9 | import cn.iocoder.yudao.module.infra.framework.file.core.client.FileClientFactory; | 14 | import cn.iocoder.yudao.module.infra.framework.file.core.client.FileClientFactory; |
| 10 | import cn.iocoder.yudao.module.infra.framework.file.core.client.local.LocalFileClient; | 15 | import cn.iocoder.yudao.module.infra.framework.file.core.client.local.LocalFileClient; |
| 11 | import cn.iocoder.yudao.module.infra.framework.file.core.client.local.LocalFileClientConfig; | 16 | import cn.iocoder.yudao.module.infra.framework.file.core.client.local.LocalFileClientConfig; |
| 12 | import cn.iocoder.yudao.module.infra.framework.file.core.enums.FileStorageEnum; | 17 | import cn.iocoder.yudao.module.infra.framework.file.core.enums.FileStorageEnum; |
| 13 | -import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; | ||
| 14 | -import cn.iocoder.yudao.module.infra.controller.admin.file.vo.config.FileConfigPageReqVO; | ||
| 15 | -import cn.iocoder.yudao.module.infra.controller.admin.file.vo.config.FileConfigSaveReqVO; | ||
| 16 | -import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileConfigDO; | ||
| 17 | -import cn.iocoder.yudao.module.infra.dal.mysql.file.FileConfigMapper; | 18 | +import jakarta.annotation.Resource; |
| 19 | +import jakarta.validation.Validator; | ||
| 18 | import lombok.Data; | 20 | import lombok.Data; |
| 19 | import org.junit.jupiter.api.Test; | 21 | import org.junit.jupiter.api.Test; |
| 20 | -import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 21 | import org.springframework.context.annotation.Import; | 22 | import org.springframework.context.annotation.Import; |
| 23 | +import org.springframework.test.context.bean.override.mockito.MockitoBean; | ||
| 22 | 24 | ||
| 23 | -import jakarta.annotation.Resource; | ||
| 24 | -import jakarta.validation.Validator; | ||
| 25 | import java.io.Serializable; | 25 | import java.io.Serializable; |
| 26 | import java.time.LocalDateTime; | 26 | import java.time.LocalDateTime; |
| 27 | import java.util.Map; | 27 | import java.util.Map; |
| @@ -53,9 +53,9 @@ public class FileConfigServiceImplTest extends BaseDbUnitTest { | @@ -53,9 +53,9 @@ public class FileConfigServiceImplTest extends BaseDbUnitTest { | ||
| 53 | @Resource | 53 | @Resource |
| 54 | private FileConfigMapper fileConfigMapper; | 54 | private FileConfigMapper fileConfigMapper; |
| 55 | 55 | ||
| 56 | - @MockBean | 56 | + @MockitoBean |
| 57 | private Validator validator; | 57 | private Validator validator; |
| 58 | - @MockBean | 58 | + @MockitoBean |
| 59 | private FileClientFactory fileClientFactory; | 59 | private FileClientFactory fileClientFactory; |
| 60 | 60 | ||
| 61 | @Test | 61 | @Test |
yudao-module-infra/src/test/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImplTest.java
| @@ -12,8 +12,8 @@ import cn.iocoder.yudao.module.infra.framework.file.core.client.FileClient; | @@ -12,8 +12,8 @@ import cn.iocoder.yudao.module.infra.framework.file.core.client.FileClient; | ||
| 12 | import jakarta.annotation.Resource; | 12 | import jakarta.annotation.Resource; |
| 13 | import org.junit.jupiter.api.BeforeEach; | 13 | import org.junit.jupiter.api.BeforeEach; |
| 14 | import org.junit.jupiter.api.Test; | 14 | import org.junit.jupiter.api.Test; |
| 15 | -import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 16 | import org.springframework.context.annotation.Import; | 15 | import org.springframework.context.annotation.Import; |
| 16 | +import org.springframework.test.context.bean.override.mockito.MockitoBean; | ||
| 17 | 17 | ||
| 18 | import java.time.LocalDateTime; | 18 | import java.time.LocalDateTime; |
| 19 | import java.util.concurrent.atomic.AtomicReference; | 19 | import java.util.concurrent.atomic.AtomicReference; |
| @@ -35,7 +35,7 @@ public class FileServiceImplTest extends BaseDbUnitTest { | @@ -35,7 +35,7 @@ public class FileServiceImplTest extends BaseDbUnitTest { | ||
| 35 | @Resource | 35 | @Resource |
| 36 | private FileMapper fileMapper; | 36 | private FileMapper fileMapper; |
| 37 | 37 | ||
| 38 | - @MockBean | 38 | + @MockitoBean |
| 39 | private FileConfigService fileConfigService; | 39 | private FileConfigService fileConfigService; |
| 40 | 40 | ||
| 41 | @BeforeEach | 41 | @BeforeEach |
yudao-module-infra/src/test/java/cn/iocoder/yudao/module/infra/service/job/JobServiceImplTest.java
| @@ -10,13 +10,12 @@ import cn.iocoder.yudao.module.infra.dal.dataobject.job.JobDO; | @@ -10,13 +10,12 @@ import cn.iocoder.yudao.module.infra.dal.dataobject.job.JobDO; | ||
| 10 | import cn.iocoder.yudao.module.infra.dal.mysql.job.JobMapper; | 10 | import cn.iocoder.yudao.module.infra.dal.mysql.job.JobMapper; |
| 11 | import cn.iocoder.yudao.module.infra.enums.job.JobStatusEnum; | 11 | import cn.iocoder.yudao.module.infra.enums.job.JobStatusEnum; |
| 12 | import cn.iocoder.yudao.module.infra.job.job.JobLogCleanJob; | 12 | import cn.iocoder.yudao.module.infra.job.job.JobLogCleanJob; |
| 13 | +import jakarta.annotation.Resource; | ||
| 13 | import org.junit.jupiter.api.Test; | 14 | import org.junit.jupiter.api.Test; |
| 14 | import org.mockito.MockedStatic; | 15 | import org.mockito.MockedStatic; |
| 15 | import org.quartz.SchedulerException; | 16 | import org.quartz.SchedulerException; |
| 16 | -import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 17 | import org.springframework.context.annotation.Import; | 17 | import org.springframework.context.annotation.Import; |
| 18 | - | ||
| 19 | -import jakarta.annotation.Resource; | 18 | +import org.springframework.test.context.bean.override.mockito.MockitoBean; |
| 20 | 19 | ||
| 21 | import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; | 20 | import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; |
| 22 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; | 21 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; |
| @@ -36,10 +35,10 @@ public class JobServiceImplTest extends BaseDbUnitTest { | @@ -36,10 +35,10 @@ public class JobServiceImplTest extends BaseDbUnitTest { | ||
| 36 | private JobServiceImpl jobService; | 35 | private JobServiceImpl jobService; |
| 37 | @Resource | 36 | @Resource |
| 38 | private JobMapper jobMapper; | 37 | private JobMapper jobMapper; |
| 39 | - @MockBean | 38 | + @MockitoBean |
| 40 | private SchedulerManager schedulerManager; | 39 | private SchedulerManager schedulerManager; |
| 41 | 40 | ||
| 42 | - @MockBean | 41 | + @MockitoBean |
| 43 | private JobLogCleanJob jobLogCleanJob; | 42 | private JobLogCleanJob jobLogCleanJob; |
| 44 | 43 | ||
| 45 | @Test | 44 | @Test |
yudao-module-infra/src/test/resources/codegen/windows10/vue2_master_erp/java/InfraStudentServiceImplTest
| @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.infra.service.demo; | @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.infra.service.demo; | ||
| 2 | 2 | ||
| 3 | import org.junit.jupiter.api.Disabled; | 3 | import org.junit.jupiter.api.Disabled; |
| 4 | import org.junit.jupiter.api.Test; | 4 | import org.junit.jupiter.api.Test; |
| 5 | -import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 6 | 5 | ||
| 7 | import javax.annotation.Resource; | 6 | import javax.annotation.Resource; |
| 8 | 7 |
yudao-module-infra/src/test/resources/codegen/windows10/vue2_master_inner/java/InfraStudentServiceImplTest
| @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.infra.service.demo; | @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.infra.service.demo; | ||
| 2 | 2 | ||
| 3 | import org.junit.jupiter.api.Disabled; | 3 | import org.junit.jupiter.api.Disabled; |
| 4 | import org.junit.jupiter.api.Test; | 4 | import org.junit.jupiter.api.Test; |
| 5 | -import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 6 | 5 | ||
| 7 | import javax.annotation.Resource; | 6 | import javax.annotation.Resource; |
| 8 | 7 |
yudao-module-infra/src/test/resources/codegen/windows10/vue2_master_normal/java/InfraStudentServiceImplTest
| @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.infra.service.demo; | @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.infra.service.demo; | ||
| 2 | 2 | ||
| 3 | import org.junit.jupiter.api.Disabled; | 3 | import org.junit.jupiter.api.Disabled; |
| 4 | import org.junit.jupiter.api.Test; | 4 | import org.junit.jupiter.api.Test; |
| 5 | -import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 6 | 5 | ||
| 7 | import javax.annotation.Resource; | 6 | import javax.annotation.Resource; |
| 8 | 7 |
yudao-module-infra/src/test/resources/codegen/windows10/vue2_one/java/InfraStudentServiceImplTest
| @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.infra.service.demo; | @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.infra.service.demo; | ||
| 2 | 2 | ||
| 3 | import org.junit.jupiter.api.Disabled; | 3 | import org.junit.jupiter.api.Disabled; |
| 4 | import org.junit.jupiter.api.Test; | 4 | import org.junit.jupiter.api.Test; |
| 5 | -import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 6 | 5 | ||
| 7 | import javax.annotation.Resource; | 6 | import javax.annotation.Resource; |
| 8 | 7 |
yudao-module-infra/src/test/resources/codegen/windows10/vue2_tree/java/InfraCategoryServiceImplTest
| @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.infra.service.demo; | @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.infra.service.demo; | ||
| 2 | 2 | ||
| 3 | import org.junit.jupiter.api.Disabled; | 3 | import org.junit.jupiter.api.Disabled; |
| 4 | import org.junit.jupiter.api.Test; | 4 | import org.junit.jupiter.api.Test; |
| 5 | -import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 6 | 5 | ||
| 7 | import javax.annotation.Resource; | 6 | import javax.annotation.Resource; |
| 8 | 7 |
yudao-module-infra/src/test/resources/codegen/windows10/vue3_master_erp/java/InfraStudentServiceImplTest
| @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.infra.service.demo; | @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.infra.service.demo; | ||
| 2 | 2 | ||
| 3 | import org.junit.jupiter.api.Disabled; | 3 | import org.junit.jupiter.api.Disabled; |
| 4 | import org.junit.jupiter.api.Test; | 4 | import org.junit.jupiter.api.Test; |
| 5 | -import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 6 | 5 | ||
| 7 | import javax.annotation.Resource; | 6 | import javax.annotation.Resource; |
| 8 | 7 |
yudao-module-infra/src/test/resources/codegen/windows10/vue3_master_inner/java/InfraStudentServiceImplTest
| @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.infra.service.demo; | @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.infra.service.demo; | ||
| 2 | 2 | ||
| 3 | import org.junit.jupiter.api.Disabled; | 3 | import org.junit.jupiter.api.Disabled; |
| 4 | import org.junit.jupiter.api.Test; | 4 | import org.junit.jupiter.api.Test; |
| 5 | -import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 6 | 5 | ||
| 7 | import javax.annotation.Resource; | 6 | import javax.annotation.Resource; |
| 8 | 7 |
yudao-module-infra/src/test/resources/codegen/windows10/vue3_master_normal/java/InfraStudentServiceImplTest
| @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.infra.service.demo; | @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.infra.service.demo; | ||
| 2 | 2 | ||
| 3 | import org.junit.jupiter.api.Disabled; | 3 | import org.junit.jupiter.api.Disabled; |
| 4 | import org.junit.jupiter.api.Test; | 4 | import org.junit.jupiter.api.Test; |
| 5 | -import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 6 | 5 | ||
| 7 | import javax.annotation.Resource; | 6 | import javax.annotation.Resource; |
| 8 | 7 |
yudao-module-infra/src/test/resources/codegen/windows10/vue3_one/java/InfraStudentServiceImplTest
| @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.infra.service.demo; | @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.infra.service.demo; | ||
| 2 | 2 | ||
| 3 | import org.junit.jupiter.api.Disabled; | 3 | import org.junit.jupiter.api.Disabled; |
| 4 | import org.junit.jupiter.api.Test; | 4 | import org.junit.jupiter.api.Test; |
| 5 | -import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 6 | 5 | ||
| 7 | import javax.annotation.Resource; | 6 | import javax.annotation.Resource; |
| 8 | 7 |
yudao-module-infra/src/test/resources/codegen/windows10/vue3_tree/java/InfraCategoryServiceImplTest
| @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.infra.service.demo; | @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.infra.service.demo; | ||
| 2 | 2 | ||
| 3 | import org.junit.jupiter.api.Disabled; | 3 | import org.junit.jupiter.api.Disabled; |
| 4 | import org.junit.jupiter.api.Test; | 4 | import org.junit.jupiter.api.Test; |
| 5 | -import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 6 | 5 | ||
| 7 | import javax.annotation.Resource; | 6 | import javax.annotation.Resource; |
| 8 | 7 |
yudao-module-mall/yudao-module-product/src/test/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImplTest.java
| @@ -18,9 +18,9 @@ import cn.iocoder.yudao.module.product.service.spu.ProductSpuService; | @@ -18,9 +18,9 @@ import cn.iocoder.yudao.module.product.service.spu.ProductSpuService; | ||
| 18 | import jakarta.annotation.Resource; | 18 | import jakarta.annotation.Resource; |
| 19 | import org.junit.jupiter.api.Disabled; | 19 | import org.junit.jupiter.api.Disabled; |
| 20 | import org.junit.jupiter.api.Test; | 20 | import org.junit.jupiter.api.Test; |
| 21 | -import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 22 | import org.springframework.context.annotation.Import; | 21 | import org.springframework.context.annotation.Import; |
| 23 | import org.springframework.context.annotation.Lazy; | 22 | import org.springframework.context.annotation.Lazy; |
| 23 | +import org.springframework.test.context.bean.override.mockito.MockitoBean; | ||
| 24 | 24 | ||
| 25 | import java.time.LocalDateTime; | 25 | import java.time.LocalDateTime; |
| 26 | import java.util.Date; | 26 | import java.util.Date; |
| @@ -48,9 +48,9 @@ public class ProductCommentServiceImplTest extends BaseDbUnitTest { | @@ -48,9 +48,9 @@ public class ProductCommentServiceImplTest extends BaseDbUnitTest { | ||
| 48 | @Lazy | 48 | @Lazy |
| 49 | private ProductCommentServiceImpl productCommentService; | 49 | private ProductCommentServiceImpl productCommentService; |
| 50 | 50 | ||
| 51 | - @MockBean | 51 | + @MockitoBean |
| 52 | private ProductSpuService productSpuService; | 52 | private ProductSpuService productSpuService; |
| 53 | - @MockBean | 53 | + @MockitoBean |
| 54 | private ProductSkuService productSkuService; | 54 | private ProductSkuService productSkuService; |
| 55 | 55 | ||
| 56 | public String generateNo() { | 56 | public String generateNo() { |
yudao-module-mall/yudao-module-product/src/test/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceTest.java
| @@ -10,12 +10,12 @@ import cn.iocoder.yudao.module.product.dal.mysql.sku.ProductSkuMapper; | @@ -10,12 +10,12 @@ import cn.iocoder.yudao.module.product.dal.mysql.sku.ProductSkuMapper; | ||
| 10 | import cn.iocoder.yudao.module.product.service.property.ProductPropertyService; | 10 | import cn.iocoder.yudao.module.product.service.property.ProductPropertyService; |
| 11 | import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService; | 11 | import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService; |
| 12 | import cn.iocoder.yudao.module.product.service.spu.ProductSpuService; | 12 | import cn.iocoder.yudao.module.product.service.spu.ProductSpuService; |
| 13 | +import jakarta.annotation.Resource; | ||
| 13 | import org.junit.jupiter.api.Disabled; | 14 | import org.junit.jupiter.api.Disabled; |
| 14 | import org.junit.jupiter.api.Test; | 15 | import org.junit.jupiter.api.Test; |
| 15 | -import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 16 | import org.springframework.context.annotation.Import; | 16 | import org.springframework.context.annotation.Import; |
| 17 | +import org.springframework.test.context.bean.override.mockito.MockitoBean; | ||
| 17 | 18 | ||
| 18 | -import jakarta.annotation.Resource; | ||
| 19 | import java.util.Arrays; | 19 | import java.util.Arrays; |
| 20 | import java.util.List; | 20 | import java.util.List; |
| 21 | 21 | ||
| @@ -44,11 +44,11 @@ public class ProductSkuServiceTest extends BaseDbUnitTest { | @@ -44,11 +44,11 @@ public class ProductSkuServiceTest extends BaseDbUnitTest { | ||
| 44 | @Resource | 44 | @Resource |
| 45 | private ProductSkuMapper productSkuMapper; | 45 | private ProductSkuMapper productSkuMapper; |
| 46 | 46 | ||
| 47 | - @MockBean | 47 | + @MockitoBean |
| 48 | private ProductSpuService productSpuService; | 48 | private ProductSpuService productSpuService; |
| 49 | - @MockBean | 49 | + @MockitoBean |
| 50 | private ProductPropertyService productPropertyService; | 50 | private ProductPropertyService productPropertyService; |
| 51 | - @MockBean | 51 | + @MockitoBean |
| 52 | private ProductPropertyValueService productPropertyValueService; | 52 | private ProductPropertyValueService productPropertyValueService; |
| 53 | 53 | ||
| 54 | public Long generateId() { | 54 | public Long generateId() { |
yudao-module-mall/yudao-module-product/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java
| @@ -22,8 +22,8 @@ import jakarta.annotation.Resource; | @@ -22,8 +22,8 @@ import jakarta.annotation.Resource; | ||
| 22 | import org.junit.jupiter.api.Assertions; | 22 | import org.junit.jupiter.api.Assertions; |
| 23 | import org.junit.jupiter.api.Disabled; | 23 | import org.junit.jupiter.api.Disabled; |
| 24 | import org.junit.jupiter.api.Test; | 24 | import org.junit.jupiter.api.Test; |
| 25 | -import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 26 | import org.springframework.context.annotation.Import; | 25 | import org.springframework.context.annotation.Import; |
| 26 | +import org.springframework.test.context.bean.override.mockito.MockitoBean; | ||
| 27 | 27 | ||
| 28 | import java.math.RoundingMode; | 28 | import java.math.RoundingMode; |
| 29 | import java.util.ArrayList; | 29 | import java.util.ArrayList; |
| @@ -58,15 +58,15 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest { | @@ -58,15 +58,15 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest { | ||
| 58 | @Resource | 58 | @Resource |
| 59 | private ProductSpuMapper productSpuMapper; | 59 | private ProductSpuMapper productSpuMapper; |
| 60 | 60 | ||
| 61 | - @MockBean | 61 | + @MockitoBean |
| 62 | private ProductSkuServiceImpl productSkuService; | 62 | private ProductSkuServiceImpl productSkuService; |
| 63 | - @MockBean | 63 | + @MockitoBean |
| 64 | private ProductCategoryServiceImpl categoryService; | 64 | private ProductCategoryServiceImpl categoryService; |
| 65 | - @MockBean | 65 | + @MockitoBean |
| 66 | private ProductBrandServiceImpl brandService; | 66 | private ProductBrandServiceImpl brandService; |
| 67 | - @MockBean | 67 | + @MockitoBean |
| 68 | private ProductPropertyService productPropertyService; | 68 | private ProductPropertyService productPropertyService; |
| 69 | - @MockBean | 69 | + @MockitoBean |
| 70 | private ProductPropertyValueService productPropertyValueService; | 70 | private ProductPropertyValueService productPropertyValueService; |
| 71 | 71 | ||
| 72 | public String generateNo() { | 72 | public String generateNo() { |
yudao-module-mall/yudao-module-trade/src/test/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleServiceTest.java
| @@ -20,12 +20,12 @@ import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum; | @@ -20,12 +20,12 @@ import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum; | ||
| 20 | import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; | 20 | import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; |
| 21 | import cn.iocoder.yudao.module.trade.service.order.TradeOrderQueryService; | 21 | import cn.iocoder.yudao.module.trade.service.order.TradeOrderQueryService; |
| 22 | import cn.iocoder.yudao.module.trade.service.order.TradeOrderUpdateService; | 22 | import cn.iocoder.yudao.module.trade.service.order.TradeOrderUpdateService; |
| 23 | +import jakarta.annotation.Resource; | ||
| 23 | import org.junit.jupiter.api.Disabled; | 24 | import org.junit.jupiter.api.Disabled; |
| 24 | import org.junit.jupiter.api.Test; | 25 | import org.junit.jupiter.api.Test; |
| 25 | -import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 26 | import org.springframework.context.annotation.Import; | 26 | import org.springframework.context.annotation.Import; |
| 27 | +import org.springframework.test.context.bean.override.mockito.MockitoBean; | ||
| 27 | 28 | ||
| 28 | -import jakarta.annotation.Resource; | ||
| 29 | import java.time.LocalDateTime; | 29 | import java.time.LocalDateTime; |
| 30 | 30 | ||
| 31 | import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime; | 31 | import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime; |
| @@ -54,15 +54,15 @@ public class AfterSaleServiceTest extends BaseDbUnitTest { | @@ -54,15 +54,15 @@ public class AfterSaleServiceTest extends BaseDbUnitTest { | ||
| 54 | @Resource | 54 | @Resource |
| 55 | private AfterSaleLogMapper tradeAfterSaleLogMapper; | 55 | private AfterSaleLogMapper tradeAfterSaleLogMapper; |
| 56 | 56 | ||
| 57 | - @MockBean | 57 | + @MockitoBean |
| 58 | private TradeOrderUpdateService tradeOrderUpdateService; | 58 | private TradeOrderUpdateService tradeOrderUpdateService; |
| 59 | @Resource | 59 | @Resource |
| 60 | private TradeOrderQueryService tradeOrderQueryService; | 60 | private TradeOrderQueryService tradeOrderQueryService; |
| 61 | 61 | ||
| 62 | - @MockBean | 62 | + @MockitoBean |
| 63 | private PayRefundApi payRefundApi; | 63 | private PayRefundApi payRefundApi; |
| 64 | 64 | ||
| 65 | - @MockBean | 65 | + @MockitoBean |
| 66 | private TradeOrderProperties tradeOrderProperties; | 66 | private TradeOrderProperties tradeOrderProperties; |
| 67 | 67 | ||
| 68 | @Test | 68 | @Test |
yudao-module-mall/yudao-module-trade/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageRecordServiceImplTest.java
| @@ -7,12 +7,12 @@ import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.record.Broker | @@ -7,12 +7,12 @@ import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.record.Broker | ||
| 7 | import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageRecordDO; | 7 | import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageRecordDO; |
| 8 | import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.BrokerageRecordMapper; | 8 | import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.BrokerageRecordMapper; |
| 9 | import cn.iocoder.yudao.module.trade.service.config.TradeConfigService; | 9 | import cn.iocoder.yudao.module.trade.service.config.TradeConfigService; |
| 10 | +import jakarta.annotation.Resource; | ||
| 10 | import org.junit.jupiter.api.Disabled; | 11 | import org.junit.jupiter.api.Disabled; |
| 11 | import org.junit.jupiter.api.Test; | 12 | import org.junit.jupiter.api.Test; |
| 12 | -import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 13 | import org.springframework.context.annotation.Import; | 13 | import org.springframework.context.annotation.Import; |
| 14 | +import org.springframework.test.context.bean.override.mockito.MockitoBean; | ||
| 14 | 15 | ||
| 15 | -import jakarta.annotation.Resource; | ||
| 16 | import java.math.RoundingMode; | 16 | import java.math.RoundingMode; |
| 17 | 17 | ||
| 18 | import static cn.hutool.core.util.RandomUtil.randomEle; | 18 | import static cn.hutool.core.util.RandomUtil.randomEle; |
| @@ -39,9 +39,9 @@ public class BrokerageRecordServiceImplTest extends BaseDbUnitTest { | @@ -39,9 +39,9 @@ public class BrokerageRecordServiceImplTest extends BaseDbUnitTest { | ||
| 39 | @Resource | 39 | @Resource |
| 40 | private BrokerageRecordMapper brokerageRecordMapper; | 40 | private BrokerageRecordMapper brokerageRecordMapper; |
| 41 | 41 | ||
| 42 | - @MockBean | 42 | + @MockitoBean |
| 43 | private TradeConfigService tradeConfigService; | 43 | private TradeConfigService tradeConfigService; |
| 44 | - @MockBean | 44 | + @MockitoBean |
| 45 | private BrokerageUserService brokerageUserService; | 45 | private BrokerageUserService brokerageUserService; |
| 46 | 46 | ||
| 47 | @Test | 47 | @Test |
yudao-module-mall/yudao-module-trade/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageWithdrawServiceImplTest.java
| @@ -11,8 +11,8 @@ import jakarta.annotation.Resource; | @@ -11,8 +11,8 @@ import jakarta.annotation.Resource; | ||
| 11 | import jakarta.validation.Validator; | 11 | import jakarta.validation.Validator; |
| 12 | import org.junit.jupiter.api.Disabled; | 12 | import org.junit.jupiter.api.Disabled; |
| 13 | import org.junit.jupiter.api.Test; | 13 | import org.junit.jupiter.api.Test; |
| 14 | -import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 15 | import org.springframework.context.annotation.Import; | 14 | import org.springframework.context.annotation.Import; |
| 15 | +import org.springframework.test.context.bean.override.mockito.MockitoBean; | ||
| 16 | 16 | ||
| 17 | import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime; | 17 | import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime; |
| 18 | import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; | 18 | import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; |
| @@ -36,14 +36,14 @@ public class BrokerageWithdrawServiceImplTest extends BaseDbUnitTest { | @@ -36,14 +36,14 @@ public class BrokerageWithdrawServiceImplTest extends BaseDbUnitTest { | ||
| 36 | @Resource | 36 | @Resource |
| 37 | private BrokerageWithdrawMapper brokerageWithdrawMapper; | 37 | private BrokerageWithdrawMapper brokerageWithdrawMapper; |
| 38 | 38 | ||
| 39 | - @MockBean | 39 | + @MockitoBean |
| 40 | private BrokerageRecordService brokerageRecordService; | 40 | private BrokerageRecordService brokerageRecordService; |
| 41 | - @MockBean | 41 | + @MockitoBean |
| 42 | private BrokerageUserService brokerageUserService; | 42 | private BrokerageUserService brokerageUserService; |
| 43 | - @MockBean | 43 | + @MockitoBean |
| 44 | private TradeConfigService tradeConfigService; | 44 | private TradeConfigService tradeConfigService; |
| 45 | 45 | ||
| 46 | - @MockBean | 46 | + @MockitoBean |
| 47 | private NotifyMessageSendApi notifyMessageSendApi; | 47 | private NotifyMessageSendApi notifyMessageSendApi; |
| 48 | 48 | ||
| 49 | @Resource | 49 | @Resource |
yudao-module-mall/yudao-module-trade/src/test/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceTest.java
| @@ -35,8 +35,8 @@ import jakarta.annotation.Resource; | @@ -35,8 +35,8 @@ import jakarta.annotation.Resource; | ||
| 35 | import org.junit.jupiter.api.BeforeEach; | 35 | import org.junit.jupiter.api.BeforeEach; |
| 36 | import org.junit.jupiter.api.Disabled; | 36 | import org.junit.jupiter.api.Disabled; |
| 37 | import org.junit.jupiter.api.Test; | 37 | import org.junit.jupiter.api.Test; |
| 38 | -import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 39 | import org.springframework.context.annotation.Import; | 38 | import org.springframework.context.annotation.Import; |
| 39 | +import org.springframework.test.context.bean.override.mockito.MockitoBean; | ||
| 40 | 40 | ||
| 41 | import java.time.Duration; | 41 | import java.time.Duration; |
| 42 | 42 | ||
| @@ -67,34 +67,34 @@ public class TradeOrderUpdateServiceTest extends BaseDbUnitTest { | @@ -67,34 +67,34 @@ public class TradeOrderUpdateServiceTest extends BaseDbUnitTest { | ||
| 67 | @Resource | 67 | @Resource |
| 68 | private TradeOrderItemMapper tradeOrderItemMapper; | 68 | private TradeOrderItemMapper tradeOrderItemMapper; |
| 69 | 69 | ||
| 70 | - @MockBean | 70 | + @MockitoBean |
| 71 | private MemberUserApi memberUserApi; | 71 | private MemberUserApi memberUserApi; |
| 72 | - @MockBean | 72 | + @MockitoBean |
| 73 | private ProductSpuApi productSpuApi; | 73 | private ProductSpuApi productSpuApi; |
| 74 | - @MockBean | 74 | + @MockitoBean |
| 75 | private ProductSkuApi productSkuApi; | 75 | private ProductSkuApi productSkuApi; |
| 76 | - @MockBean | 76 | + @MockitoBean |
| 77 | private ProductCommentApi productCommentApi; | 77 | private ProductCommentApi productCommentApi; |
| 78 | - // @MockBean | 78 | + // @MockitoBean |
| 79 | // private PriceApi priceApi; | 79 | // private PriceApi priceApi; |
| 80 | - @MockBean | 80 | + @MockitoBean |
| 81 | private PayOrderApi payOrderApi; | 81 | private PayOrderApi payOrderApi; |
| 82 | - @MockBean | 82 | + @MockitoBean |
| 83 | private MemberAddressApi addressApi; | 83 | private MemberAddressApi addressApi; |
| 84 | - @MockBean | 84 | + @MockitoBean |
| 85 | private CouponApi couponApi; | 85 | private CouponApi couponApi; |
| 86 | 86 | ||
| 87 | - @MockBean | 87 | + @MockitoBean |
| 88 | private TradeOrderProperties tradeOrderProperties; | 88 | private TradeOrderProperties tradeOrderProperties; |
| 89 | - @MockBean | 89 | + @MockitoBean |
| 90 | private TradeNoRedisDAO tradeNoRedisDAO; | 90 | private TradeNoRedisDAO tradeNoRedisDAO; |
| 91 | - @MockBean | 91 | + @MockitoBean |
| 92 | private TradeOrderHandler tradeOrderHandler; | 92 | private TradeOrderHandler tradeOrderHandler; |
| 93 | - @MockBean | 93 | + @MockitoBean |
| 94 | private TradePriceCalculator tradePriceCalculator; | 94 | private TradePriceCalculator tradePriceCalculator; |
| 95 | - @MockBean | 95 | + @MockitoBean |
| 96 | private NotifyMessageSendApi notifyMessageSendApi; | 96 | private NotifyMessageSendApi notifyMessageSendApi; |
| 97 | - @MockBean | 97 | + @MockitoBean |
| 98 | private DeliveryExpressService deliveryExpressService; | 98 | private DeliveryExpressService deliveryExpressService; |
| 99 | 99 | ||
| 100 | @BeforeEach | 100 | @BeforeEach |
yudao-module-member/src/test/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceTest.java
| 1 | package cn.iocoder.yudao.module.member.service.auth; | 1 | package cn.iocoder.yudao.module.member.service.auth; |
| 2 | 2 | ||
| 3 | +import cn.iocoder.yudao.framework.common.biz.system.oauth2.OAuth2TokenCommonApi; | ||
| 3 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | 4 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| 4 | import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; | 5 | import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; |
| 5 | import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration; | 6 | import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration; |
| @@ -8,14 +9,13 @@ import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; | @@ -8,14 +9,13 @@ import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; | ||
| 8 | import cn.iocoder.yudao.module.member.dal.mysql.user.MemberUserMapper; | 9 | import cn.iocoder.yudao.module.member.dal.mysql.user.MemberUserMapper; |
| 9 | import cn.iocoder.yudao.module.member.service.user.MemberUserService; | 10 | import cn.iocoder.yudao.module.member.service.user.MemberUserService; |
| 10 | import cn.iocoder.yudao.module.system.api.logger.LoginLogApi; | 11 | import cn.iocoder.yudao.module.system.api.logger.LoginLogApi; |
| 11 | -import cn.iocoder.yudao.framework.common.biz.system.oauth2.OAuth2TokenCommonApi; | ||
| 12 | import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi; | 12 | import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi; |
| 13 | import cn.iocoder.yudao.module.system.api.social.SocialUserApi; | 13 | import cn.iocoder.yudao.module.system.api.social.SocialUserApi; |
| 14 | -import org.springframework.boot.test.mock.mockito.MockBean; | 14 | +import jakarta.annotation.Resource; |
| 15 | import org.springframework.context.annotation.Import; | 15 | import org.springframework.context.annotation.Import; |
| 16 | import org.springframework.security.crypto.password.PasswordEncoder; | 16 | import org.springframework.security.crypto.password.PasswordEncoder; |
| 17 | +import org.springframework.test.context.bean.override.mockito.MockitoBean; | ||
| 17 | 18 | ||
| 18 | -import jakarta.annotation.Resource; | ||
| 19 | import java.util.function.Consumer; | 19 | import java.util.function.Consumer; |
| 20 | 20 | ||
| 21 | import static cn.hutool.core.util.RandomUtil.randomEle; | 21 | import static cn.hutool.core.util.RandomUtil.randomEle; |
| @@ -36,17 +36,17 @@ public class MemberAuthServiceTest extends BaseDbAndRedisUnitTest { | @@ -36,17 +36,17 @@ public class MemberAuthServiceTest extends BaseDbAndRedisUnitTest { | ||
| 36 | @Resource | 36 | @Resource |
| 37 | private MemberAuthServiceImpl authService; | 37 | private MemberAuthServiceImpl authService; |
| 38 | 38 | ||
| 39 | - @MockBean | 39 | + @MockitoBean |
| 40 | private MemberUserService userService; | 40 | private MemberUserService userService; |
| 41 | - @MockBean | 41 | + @MockitoBean |
| 42 | private SmsCodeApi smsCodeApi; | 42 | private SmsCodeApi smsCodeApi; |
| 43 | - @MockBean | 43 | + @MockitoBean |
| 44 | private LoginLogApi loginLogApi; | 44 | private LoginLogApi loginLogApi; |
| 45 | - @MockBean | 45 | + @MockitoBean |
| 46 | private OAuth2TokenCommonApi oauth2TokenApi; | 46 | private OAuth2TokenCommonApi oauth2TokenApi; |
| 47 | - @MockBean | 47 | + @MockitoBean |
| 48 | private SocialUserApi socialUserApi; | 48 | private SocialUserApi socialUserApi; |
| 49 | - @MockBean | 49 | + @MockitoBean |
| 50 | private PasswordEncoder passwordEncoder; | 50 | private PasswordEncoder passwordEncoder; |
| 51 | 51 | ||
| 52 | @Resource | 52 | @Resource |
yudao-module-member/src/test/java/cn/iocoder/yudao/module/member/service/group/MemberGroupServiceImplTest.java
| @@ -9,11 +9,10 @@ import cn.iocoder.yudao.module.member.controller.admin.group.vo.MemberGroupUpdat | @@ -9,11 +9,10 @@ import cn.iocoder.yudao.module.member.controller.admin.group.vo.MemberGroupUpdat | ||
| 9 | import cn.iocoder.yudao.module.member.dal.dataobject.group.MemberGroupDO; | 9 | import cn.iocoder.yudao.module.member.dal.dataobject.group.MemberGroupDO; |
| 10 | import cn.iocoder.yudao.module.member.dal.mysql.group.MemberGroupMapper; | 10 | import cn.iocoder.yudao.module.member.dal.mysql.group.MemberGroupMapper; |
| 11 | import cn.iocoder.yudao.module.member.service.user.MemberUserService; | 11 | import cn.iocoder.yudao.module.member.service.user.MemberUserService; |
| 12 | +import jakarta.annotation.Resource; | ||
| 12 | import org.junit.jupiter.api.Test; | 13 | import org.junit.jupiter.api.Test; |
| 13 | -import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 14 | import org.springframework.context.annotation.Import; | 14 | import org.springframework.context.annotation.Import; |
| 15 | - | ||
| 16 | -import jakarta.annotation.Resource; | 15 | +import org.springframework.test.context.bean.override.mockito.MockitoBean; |
| 17 | 16 | ||
| 18 | import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime; | 17 | import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime; |
| 19 | import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime; | 18 | import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime; |
| @@ -42,7 +41,7 @@ public class MemberGroupServiceImplTest extends BaseDbUnitTest { | @@ -42,7 +41,7 @@ public class MemberGroupServiceImplTest extends BaseDbUnitTest { | ||
| 42 | @Resource | 41 | @Resource |
| 43 | private MemberGroupMapper groupMapper; | 42 | private MemberGroupMapper groupMapper; |
| 44 | 43 | ||
| 45 | - @MockBean | 44 | + @MockitoBean |
| 46 | private MemberUserService memberUserService; | 45 | private MemberUserService memberUserService; |
| 47 | 46 | ||
| 48 | @Test | 47 | @Test |
yudao-module-member/src/test/java/cn/iocoder/yudao/module/member/service/level/MemberLevelServiceImplTest.java
| @@ -9,11 +9,11 @@ import cn.iocoder.yudao.module.member.controller.admin.level.vo.level.MemberLeve | @@ -9,11 +9,11 @@ import cn.iocoder.yudao.module.member.controller.admin.level.vo.level.MemberLeve | ||
| 9 | import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelDO; | 9 | import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelDO; |
| 10 | import cn.iocoder.yudao.module.member.dal.mysql.level.MemberLevelMapper; | 10 | import cn.iocoder.yudao.module.member.dal.mysql.level.MemberLevelMapper; |
| 11 | import cn.iocoder.yudao.module.member.service.user.MemberUserService; | 11 | import cn.iocoder.yudao.module.member.service.user.MemberUserService; |
| 12 | +import jakarta.annotation.Resource; | ||
| 12 | import org.junit.jupiter.api.Test; | 13 | import org.junit.jupiter.api.Test; |
| 13 | -import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 14 | import org.springframework.context.annotation.Import; | 14 | import org.springframework.context.annotation.Import; |
| 15 | +import org.springframework.test.context.bean.override.mockito.MockitoBean; | ||
| 15 | 16 | ||
| 16 | -import jakarta.annotation.Resource; | ||
| 17 | import java.util.List; | 17 | import java.util.List; |
| 18 | import java.util.function.Consumer; | 18 | import java.util.function.Consumer; |
| 19 | 19 | ||
| @@ -40,11 +40,11 @@ public class MemberLevelServiceImplTest extends BaseDbUnitTest { | @@ -40,11 +40,11 @@ public class MemberLevelServiceImplTest extends BaseDbUnitTest { | ||
| 40 | @Resource | 40 | @Resource |
| 41 | private MemberLevelMapper memberlevelMapper; | 41 | private MemberLevelMapper memberlevelMapper; |
| 42 | 42 | ||
| 43 | - @MockBean | 43 | + @MockitoBean |
| 44 | private MemberLevelRecordService memberLevelRecordService; | 44 | private MemberLevelRecordService memberLevelRecordService; |
| 45 | - @MockBean | 45 | + @MockitoBean |
| 46 | private MemberExperienceRecordService memberExperienceRecordService; | 46 | private MemberExperienceRecordService memberExperienceRecordService; |
| 47 | - @MockBean | 47 | + @MockitoBean |
| 48 | private MemberUserService memberUserService; | 48 | private MemberUserService memberUserService; |
| 49 | 49 | ||
| 50 | @Test | 50 | @Test |
yudao-module-member/src/test/java/cn/iocoder/yudao/module/member/service/tag/MemberTagServiceImplTest.java
| @@ -8,11 +8,10 @@ import cn.iocoder.yudao.module.member.controller.admin.tag.vo.MemberTagUpdateReq | @@ -8,11 +8,10 @@ import cn.iocoder.yudao.module.member.controller.admin.tag.vo.MemberTagUpdateReq | ||
| 8 | import cn.iocoder.yudao.module.member.dal.dataobject.tag.MemberTagDO; | 8 | import cn.iocoder.yudao.module.member.dal.dataobject.tag.MemberTagDO; |
| 9 | import cn.iocoder.yudao.module.member.dal.mysql.tag.MemberTagMapper; | 9 | import cn.iocoder.yudao.module.member.dal.mysql.tag.MemberTagMapper; |
| 10 | import cn.iocoder.yudao.module.member.service.user.MemberUserService; | 10 | import cn.iocoder.yudao.module.member.service.user.MemberUserService; |
| 11 | +import jakarta.annotation.Resource; | ||
| 11 | import org.junit.jupiter.api.Test; | 12 | import org.junit.jupiter.api.Test; |
| 12 | -import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 13 | import org.springframework.context.annotation.Import; | 13 | import org.springframework.context.annotation.Import; |
| 14 | - | ||
| 15 | -import jakarta.annotation.Resource; | 14 | +import org.springframework.test.context.bean.override.mockito.MockitoBean; |
| 16 | 15 | ||
| 17 | import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime; | 16 | import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime; |
| 18 | import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime; | 17 | import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime; |
| @@ -39,7 +38,7 @@ public class MemberTagServiceImplTest extends BaseDbUnitTest { | @@ -39,7 +38,7 @@ public class MemberTagServiceImplTest extends BaseDbUnitTest { | ||
| 39 | @Resource | 38 | @Resource |
| 40 | private MemberTagMapper tagMapper; | 39 | private MemberTagMapper tagMapper; |
| 41 | 40 | ||
| 42 | - @MockBean | 41 | + @MockitoBean |
| 43 | private MemberUserService memberUserService; | 42 | private MemberUserService memberUserService; |
| 44 | 43 | ||
| 45 | @Test | 44 | @Test |
yudao-module-member/src/test/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImplTest.java
| @@ -13,10 +13,10 @@ import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi; | @@ -13,10 +13,10 @@ import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi; | ||
| 13 | import jakarta.annotation.Resource; | 13 | import jakarta.annotation.Resource; |
| 14 | import org.junit.jupiter.api.Disabled; | 14 | import org.junit.jupiter.api.Disabled; |
| 15 | import org.junit.jupiter.api.Test; | 15 | import org.junit.jupiter.api.Test; |
| 16 | -import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 17 | import org.springframework.context.annotation.Import; | 16 | import org.springframework.context.annotation.Import; |
| 18 | import org.springframework.data.redis.core.StringRedisTemplate; | 17 | import org.springframework.data.redis.core.StringRedisTemplate; |
| 19 | import org.springframework.security.crypto.password.PasswordEncoder; | 18 | import org.springframework.security.crypto.password.PasswordEncoder; |
| 19 | +import org.springframework.test.context.bean.override.mockito.MockitoBean; | ||
| 20 | 20 | ||
| 21 | import java.util.function.Consumer; | 21 | import java.util.function.Consumer; |
| 22 | 22 | ||
| @@ -44,13 +44,13 @@ public class MemberUserServiceImplTest extends BaseDbAndRedisUnitTest { | @@ -44,13 +44,13 @@ public class MemberUserServiceImplTest extends BaseDbAndRedisUnitTest { | ||
| 44 | @Resource | 44 | @Resource |
| 45 | private MemberUserMapper userMapper; | 45 | private MemberUserMapper userMapper; |
| 46 | 46 | ||
| 47 | - @MockBean | 47 | + @MockitoBean |
| 48 | private MemberAuthServiceImpl authService; | 48 | private MemberAuthServiceImpl authService; |
| 49 | 49 | ||
| 50 | - @MockBean | 50 | + @MockitoBean |
| 51 | private PasswordEncoder passwordEncoder; | 51 | private PasswordEncoder passwordEncoder; |
| 52 | 52 | ||
| 53 | - @MockBean | 53 | + @MockitoBean |
| 54 | private SmsCodeApi smsCodeApi; | 54 | private SmsCodeApi smsCodeApi; |
| 55 | 55 | ||
| 56 | // TODO 芋艿:后续重构这个单测 | 56 | // TODO 芋艿:后续重构这个单测 |
yudao-module-mp/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/message/vo/message/MpMessagePageReqVO.java
| @@ -28,6 +28,9 @@ public class MpMessagePageReqVO extends PageParam { | @@ -28,6 +28,9 @@ public class MpMessagePageReqVO extends PageParam { | ||
| 28 | @Schema(description = "公众号粉丝标识", example = "o6_bmjrPTlm6_2sgVt7hMZOPfL2M") | 28 | @Schema(description = "公众号粉丝标识", example = "o6_bmjrPTlm6_2sgVt7hMZOPfL2M") |
| 29 | private String openid; | 29 | private String openid; |
| 30 | 30 | ||
| 31 | + @Schema(description = "公众号粉丝 UserId", example = "1") | ||
| 32 | + private String userId; | ||
| 33 | + | ||
| 31 | @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | 34 | @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) |
| 32 | @Schema(description = "创建时间") | 35 | @Schema(description = "创建时间") |
| 33 | private LocalDateTime[] createTime; | 36 | private LocalDateTime[] createTime; |
yudao-module-mp/src/main/java/cn/iocoder/yudao/module/mp/dal/mysql/message/MpMessageMapper.java
| @@ -15,6 +15,7 @@ public interface MpMessageMapper extends BaseMapperX<MpMessageDO> { | @@ -15,6 +15,7 @@ public interface MpMessageMapper extends BaseMapperX<MpMessageDO> { | ||
| 15 | .eqIfPresent(MpMessageDO::getAccountId, reqVO.getAccountId()) | 15 | .eqIfPresent(MpMessageDO::getAccountId, reqVO.getAccountId()) |
| 16 | .eqIfPresent(MpMessageDO::getType, reqVO.getType()) | 16 | .eqIfPresent(MpMessageDO::getType, reqVO.getType()) |
| 17 | .eqIfPresent(MpMessageDO::getOpenid, reqVO.getOpenid()) | 17 | .eqIfPresent(MpMessageDO::getOpenid, reqVO.getOpenid()) |
| 18 | + .eqIfPresent(MpMessageDO::getUserId, reqVO.getUserId()) | ||
| 18 | .betweenIfPresent(MpMessageDO::getCreateTime, reqVO.getCreateTime()) | 19 | .betweenIfPresent(MpMessageDO::getCreateTime, reqVO.getCreateTime()) |
| 19 | .orderByDesc(MpMessageDO::getId)); | 20 | .orderByDesc(MpMessageDO::getId)); |
| 20 | } | 21 | } |
yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/core/client/impl/alipay/AbstractAlipayPayClient.java
| @@ -353,7 +353,7 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient<AlipayPa | @@ -353,7 +353,7 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient<AlipayPa | ||
| 353 | } else if (Objects.equals(config.getMode(), MODE_CERTIFICATE)) { | 353 | } else if (Objects.equals(config.getMode(), MODE_CERTIFICATE)) { |
| 354 | // 由于 rsaCertCheckV1 的第二个参数是 path,所以不能这么调用!!!通过阅读源码,发现可以采用如下方式! | 354 | // 由于 rsaCertCheckV1 的第二个参数是 path,所以不能这么调用!!!通过阅读源码,发现可以采用如下方式! |
| 355 | X509Certificate cert = AntCertificationUtil.getCertFromContent(config.getAlipayPublicCertContent()); | 355 | X509Certificate cert = AntCertificationUtil.getCertFromContent(config.getAlipayPublicCertContent()); |
| 356 | - String publicKey = Base64.encodeBase64String(cert.getEncoded()); | 356 | + String publicKey = Base64.encodeBase64String(cert.getPublicKey().getEncoded()); |
| 357 | verify = AlipaySignature.rsaCheckV1(params, publicKey, | 357 | verify = AlipaySignature.rsaCheckV1(params, publicKey, |
| 358 | StandardCharsets.UTF_8.name(), config.getSignType()); | 358 | StandardCharsets.UTF_8.name(), config.getSignType()); |
| 359 | } else { | 359 | } else { |
yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java
| @@ -585,7 +585,7 @@ public class PayOrderServiceImpl implements PayOrderService { | @@ -585,7 +585,7 @@ public class PayOrderServiceImpl implements PayOrderService { | ||
| 585 | log.error("[expireOrder][order({}) 更新为支付关闭失败]", order.getId()); | 585 | log.error("[expireOrder][order({}) 更新为支付关闭失败]", order.getId()); |
| 586 | return false; | 586 | return false; |
| 587 | } | 587 | } |
| 588 | - log.info("[expireOrder][order({}) 更新为支付关闭失败]", order.getId()); | 588 | + log.info("[expireOrder][order({}) 更新为支付关闭成功]", order.getId()); |
| 589 | return true; | 589 | return true; |
| 590 | } catch (Throwable e) { | 590 | } catch (Throwable e) { |
| 591 | log.error("[expireOrder][order({}) 过期订单异常]", order.getId(), e); | 591 | log.error("[expireOrder][order({}) 过期订单异常]", order.getId(), e); |
yudao-module-pay/src/test/java/cn/iocoder/yudao/module/pay/service/app/PayAppServiceTest.java
| @@ -11,12 +11,12 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO; | @@ -11,12 +11,12 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO; | ||
| 11 | import cn.iocoder.yudao.module.pay.dal.mysql.app.PayAppMapper; | 11 | import cn.iocoder.yudao.module.pay.dal.mysql.app.PayAppMapper; |
| 12 | import cn.iocoder.yudao.module.pay.service.order.PayOrderService; | 12 | import cn.iocoder.yudao.module.pay.service.order.PayOrderService; |
| 13 | import cn.iocoder.yudao.module.pay.service.refund.PayRefundService; | 13 | import cn.iocoder.yudao.module.pay.service.refund.PayRefundService; |
| 14 | +import jakarta.annotation.Resource; | ||
| 14 | import org.junit.jupiter.api.Disabled; | 15 | import org.junit.jupiter.api.Disabled; |
| 15 | import org.junit.jupiter.api.Test; | 16 | import org.junit.jupiter.api.Test; |
| 16 | -import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 17 | import org.springframework.context.annotation.Import; | 17 | import org.springframework.context.annotation.Import; |
| 18 | +import org.springframework.test.context.bean.override.mockito.MockitoBean; | ||
| 18 | 19 | ||
| 19 | -import jakarta.annotation.Resource; | ||
| 20 | import java.util.Map; | 20 | import java.util.Map; |
| 21 | 21 | ||
| 22 | import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime; | 22 | import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime; |
| @@ -46,9 +46,9 @@ public class PayAppServiceTest extends BaseDbUnitTest { | @@ -46,9 +46,9 @@ public class PayAppServiceTest extends BaseDbUnitTest { | ||
| 46 | @Resource | 46 | @Resource |
| 47 | private PayAppMapper appMapper; | 47 | private PayAppMapper appMapper; |
| 48 | 48 | ||
| 49 | - @MockBean | 49 | + @MockitoBean |
| 50 | private PayOrderService orderService; | 50 | private PayOrderService orderService; |
| 51 | - @MockBean | 51 | + @MockitoBean |
| 52 | private PayRefundService refundService; | 52 | private PayRefundService refundService; |
| 53 | 53 | ||
| 54 | @Test | 54 | @Test |
yudao-module-pay/src/test/java/cn/iocoder/yudao/module/pay/service/channel/PayChannelServiceTest.java
| @@ -2,23 +2,23 @@ package cn.iocoder.yudao.module.pay.service.channel; | @@ -2,23 +2,23 @@ package cn.iocoder.yudao.module.pay.service.channel; | ||
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | 3 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| 4 | import cn.iocoder.yudao.framework.common.util.json.JsonUtils; | 4 | import cn.iocoder.yudao.framework.common.util.json.JsonUtils; |
| 5 | -import cn.iocoder.yudao.module.pay.enums.PayChannelEnum; | ||
| 6 | -import cn.iocoder.yudao.module.pay.framework.pay.core.client.PayClient; | ||
| 7 | -import cn.iocoder.yudao.module.pay.framework.pay.core.client.PayClientFactory; | ||
| 8 | -import cn.iocoder.yudao.module.pay.framework.pay.core.client.impl.alipay.AlipayPayClientConfig; | ||
| 9 | -import cn.iocoder.yudao.module.pay.framework.pay.core.client.impl.weixin.WxPayClientConfig; | ||
| 10 | import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; | 5 | import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; |
| 11 | import cn.iocoder.yudao.module.pay.controller.admin.channel.vo.PayChannelCreateReqVO; | 6 | import cn.iocoder.yudao.module.pay.controller.admin.channel.vo.PayChannelCreateReqVO; |
| 12 | import cn.iocoder.yudao.module.pay.controller.admin.channel.vo.PayChannelUpdateReqVO; | 7 | import cn.iocoder.yudao.module.pay.controller.admin.channel.vo.PayChannelUpdateReqVO; |
| 13 | import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO; | 8 | import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO; |
| 14 | import cn.iocoder.yudao.module.pay.dal.mysql.channel.PayChannelMapper; | 9 | import cn.iocoder.yudao.module.pay.dal.mysql.channel.PayChannelMapper; |
| 10 | +import cn.iocoder.yudao.module.pay.enums.PayChannelEnum; | ||
| 11 | +import cn.iocoder.yudao.module.pay.framework.pay.core.client.PayClient; | ||
| 12 | +import cn.iocoder.yudao.module.pay.framework.pay.core.client.PayClientFactory; | ||
| 13 | +import cn.iocoder.yudao.module.pay.framework.pay.core.client.impl.alipay.AlipayPayClientConfig; | ||
| 14 | +import cn.iocoder.yudao.module.pay.framework.pay.core.client.impl.weixin.WxPayClientConfig; | ||
| 15 | import com.alibaba.fastjson.JSON; | 15 | import com.alibaba.fastjson.JSON; |
| 16 | +import jakarta.annotation.Resource; | ||
| 17 | +import jakarta.validation.Validator; | ||
| 16 | import org.junit.jupiter.api.Test; | 18 | import org.junit.jupiter.api.Test; |
| 17 | -import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 18 | import org.springframework.context.annotation.Import; | 19 | import org.springframework.context.annotation.Import; |
| 20 | +import org.springframework.test.context.bean.override.mockito.MockitoBean; | ||
| 19 | 21 | ||
| 20 | -import jakarta.annotation.Resource; | ||
| 21 | -import jakarta.validation.Validator; | ||
| 22 | import java.util.Collections; | 22 | import java.util.Collections; |
| 23 | import java.util.List; | 23 | import java.util.List; |
| 24 | 24 | ||
| @@ -28,7 +28,8 @@ import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; | @@ -28,7 +28,8 @@ import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; | ||
| 28 | import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*; | 28 | import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*; |
| 29 | import static org.junit.jupiter.api.Assertions.*; | 29 | import static org.junit.jupiter.api.Assertions.*; |
| 30 | import static org.mockito.ArgumentMatchers.eq; | 30 | import static org.mockito.ArgumentMatchers.eq; |
| 31 | -import static org.mockito.Mockito.*; | 31 | +import static org.mockito.Mockito.mock; |
| 32 | +import static org.mockito.Mockito.when; | ||
| 32 | 33 | ||
| 33 | @Import({PayChannelServiceImpl.class}) | 34 | @Import({PayChannelServiceImpl.class}) |
| 34 | public class PayChannelServiceTest extends BaseDbUnitTest { | 35 | public class PayChannelServiceTest extends BaseDbUnitTest { |
| @@ -39,9 +40,9 @@ public class PayChannelServiceTest extends BaseDbUnitTest { | @@ -39,9 +40,9 @@ public class PayChannelServiceTest extends BaseDbUnitTest { | ||
| 39 | @Resource | 40 | @Resource |
| 40 | private PayChannelMapper channelMapper; | 41 | private PayChannelMapper channelMapper; |
| 41 | 42 | ||
| 42 | - @MockBean | 43 | + @MockitoBean |
| 43 | private PayClientFactory payClientFactory; | 44 | private PayClientFactory payClientFactory; |
| 44 | - @MockBean | 45 | + @MockitoBean |
| 45 | private Validator validator; | 46 | private Validator validator; |
| 46 | 47 | ||
| 47 | @Test | 48 | @Test |
yudao-module-pay/src/test/java/cn/iocoder/yudao/module/pay/service/notify/PayNotifyServiceTest.java
| @@ -18,15 +18,15 @@ import cn.iocoder.yudao.module.pay.framework.job.config.PayJobConfiguration; | @@ -18,15 +18,15 @@ import cn.iocoder.yudao.module.pay.framework.job.config.PayJobConfiguration; | ||
| 18 | import cn.iocoder.yudao.module.pay.service.order.PayOrderService; | 18 | import cn.iocoder.yudao.module.pay.service.order.PayOrderService; |
| 19 | import cn.iocoder.yudao.module.pay.service.refund.PayRefundService; | 19 | import cn.iocoder.yudao.module.pay.service.refund.PayRefundService; |
| 20 | import cn.iocoder.yudao.module.pay.service.refund.PayRefundServiceImpl; | 20 | import cn.iocoder.yudao.module.pay.service.refund.PayRefundServiceImpl; |
| 21 | +import jakarta.annotation.Resource; | ||
| 21 | import org.junit.jupiter.api.Disabled; | 22 | import org.junit.jupiter.api.Disabled; |
| 22 | import org.junit.jupiter.api.Test; | 23 | import org.junit.jupiter.api.Test; |
| 23 | import org.mockito.MockedStatic; | 24 | import org.mockito.MockedStatic; |
| 24 | import org.redisson.api.RLock; | 25 | import org.redisson.api.RLock; |
| 25 | import org.redisson.api.RedissonClient; | 26 | import org.redisson.api.RedissonClient; |
| 26 | -import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 27 | import org.springframework.context.annotation.Import; | 27 | import org.springframework.context.annotation.Import; |
| 28 | +import org.springframework.test.context.bean.override.mockito.MockitoBean; | ||
| 28 | 29 | ||
| 29 | -import jakarta.annotation.Resource; | ||
| 30 | import java.time.Duration; | 30 | import java.time.Duration; |
| 31 | import java.util.List; | 31 | import java.util.List; |
| 32 | 32 | ||
| @@ -54,9 +54,9 @@ public class PayNotifyServiceTest extends BaseDbUnitTest { | @@ -54,9 +54,9 @@ public class PayNotifyServiceTest extends BaseDbUnitTest { | ||
| 54 | @Resource | 54 | @Resource |
| 55 | private PayNotifyServiceImpl notifyService; | 55 | private PayNotifyServiceImpl notifyService; |
| 56 | 56 | ||
| 57 | - @MockBean | 57 | + @MockitoBean |
| 58 | private PayOrderService orderService; | 58 | private PayOrderService orderService; |
| 59 | - @MockBean | 59 | + @MockitoBean |
| 60 | private PayRefundService refundService; | 60 | private PayRefundService refundService; |
| 61 | 61 | ||
| 62 | @Resource | 62 | @Resource |
| @@ -64,7 +64,7 @@ public class PayNotifyServiceTest extends BaseDbUnitTest { | @@ -64,7 +64,7 @@ public class PayNotifyServiceTest extends BaseDbUnitTest { | ||
| 64 | @Resource | 64 | @Resource |
| 65 | private PayNotifyLogMapper notifyLogMapper; | 65 | private PayNotifyLogMapper notifyLogMapper; |
| 66 | 66 | ||
| 67 | - @MockBean | 67 | + @MockitoBean |
| 68 | private RedissonClient redissonClient; | 68 | private RedissonClient redissonClient; |
| 69 | 69 | ||
| 70 | @Test | 70 | @Test |
yudao-module-pay/src/test/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceTest.java
| @@ -2,10 +2,6 @@ package cn.iocoder.yudao.module.pay.service.order; | @@ -2,10 +2,6 @@ package cn.iocoder.yudao.module.pay.service.order; | ||
| 2 | 2 | ||
| 3 | import cn.hutool.extra.spring.SpringUtil; | 3 | import cn.hutool.extra.spring.SpringUtil; |
| 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 5 | -import cn.iocoder.yudao.module.pay.enums.PayChannelEnum; | ||
| 6 | -import cn.iocoder.yudao.module.pay.framework.pay.core.client.PayClient; | ||
| 7 | -import cn.iocoder.yudao.module.pay.framework.pay.core.client.dto.order.PayOrderRespDTO; | ||
| 8 | -import cn.iocoder.yudao.module.pay.framework.pay.core.enums.PayOrderDisplayModeEnum; | ||
| 9 | import cn.iocoder.yudao.framework.test.core.ut.BaseDbAndRedisUnitTest; | 5 | import cn.iocoder.yudao.framework.test.core.ut.BaseDbAndRedisUnitTest; |
| 10 | import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO; | 6 | import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO; |
| 11 | import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderExportReqVO; | 7 | import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderExportReqVO; |
| @@ -19,9 +15,13 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO; | @@ -19,9 +15,13 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO; | ||
| 19 | import cn.iocoder.yudao.module.pay.dal.mysql.order.PayOrderExtensionMapper; | 15 | import cn.iocoder.yudao.module.pay.dal.mysql.order.PayOrderExtensionMapper; |
| 20 | import cn.iocoder.yudao.module.pay.dal.mysql.order.PayOrderMapper; | 16 | import cn.iocoder.yudao.module.pay.dal.mysql.order.PayOrderMapper; |
| 21 | import cn.iocoder.yudao.module.pay.dal.redis.no.PayNoRedisDAO; | 17 | import cn.iocoder.yudao.module.pay.dal.redis.no.PayNoRedisDAO; |
| 18 | +import cn.iocoder.yudao.module.pay.enums.PayChannelEnum; | ||
| 22 | import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyTypeEnum; | 19 | import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyTypeEnum; |
| 23 | import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; | 20 | import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; |
| 24 | import cn.iocoder.yudao.module.pay.framework.pay.config.PayProperties; | 21 | import cn.iocoder.yudao.module.pay.framework.pay.config.PayProperties; |
| 22 | +import cn.iocoder.yudao.module.pay.framework.pay.core.client.PayClient; | ||
| 23 | +import cn.iocoder.yudao.module.pay.framework.pay.core.client.dto.order.PayOrderRespDTO; | ||
| 24 | +import cn.iocoder.yudao.module.pay.framework.pay.core.enums.PayOrderDisplayModeEnum; | ||
| 25 | import cn.iocoder.yudao.module.pay.service.app.PayAppService; | 25 | import cn.iocoder.yudao.module.pay.service.app.PayAppService; |
| 26 | import cn.iocoder.yudao.module.pay.service.channel.PayChannelService; | 26 | import cn.iocoder.yudao.module.pay.service.channel.PayChannelService; |
| 27 | import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService; | 27 | import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService; |
| @@ -29,8 +29,8 @@ import jakarta.annotation.Resource; | @@ -29,8 +29,8 @@ import jakarta.annotation.Resource; | ||
| 29 | import org.junit.jupiter.api.BeforeEach; | 29 | import org.junit.jupiter.api.BeforeEach; |
| 30 | import org.junit.jupiter.api.Test; | 30 | import org.junit.jupiter.api.Test; |
| 31 | import org.mockito.MockedStatic; | 31 | import org.mockito.MockedStatic; |
| 32 | -import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 33 | import org.springframework.context.annotation.Import; | 32 | import org.springframework.context.annotation.Import; |
| 33 | +import org.springframework.test.context.bean.override.mockito.MockitoBean; | ||
| 34 | 34 | ||
| 35 | import java.time.Duration; | 35 | import java.time.Duration; |
| 36 | import java.time.LocalDateTime; | 36 | import java.time.LocalDateTime; |
| @@ -65,13 +65,13 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest { | @@ -65,13 +65,13 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest { | ||
| 65 | @Resource | 65 | @Resource |
| 66 | private PayOrderExtensionMapper orderExtensionMapper; | 66 | private PayOrderExtensionMapper orderExtensionMapper; |
| 67 | 67 | ||
| 68 | - @MockBean | 68 | + @MockitoBean |
| 69 | private PayProperties properties; | 69 | private PayProperties properties; |
| 70 | - @MockBean | 70 | + @MockitoBean |
| 71 | private PayAppService appService; | 71 | private PayAppService appService; |
| 72 | - @MockBean | 72 | + @MockitoBean |
| 73 | private PayChannelService channelService; | 73 | private PayChannelService channelService; |
| 74 | - @MockBean | 74 | + @MockitoBean |
| 75 | private PayNotifyService notifyService; | 75 | private PayNotifyService notifyService; |
| 76 | 76 | ||
| 77 | @BeforeEach | 77 | @BeforeEach |
yudao-module-pay/src/test/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceTest.java
| @@ -2,10 +2,6 @@ package cn.iocoder.yudao.module.pay.service.refund; | @@ -2,10 +2,6 @@ package cn.iocoder.yudao.module.pay.service.refund; | ||
| 2 | 2 | ||
| 3 | import cn.hutool.extra.spring.SpringUtil; | 3 | import cn.hutool.extra.spring.SpringUtil; |
| 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 5 | -import cn.iocoder.yudao.module.pay.enums.PayChannelEnum; | ||
| 6 | -import cn.iocoder.yudao.module.pay.framework.pay.core.client.PayClient; | ||
| 7 | -import cn.iocoder.yudao.module.pay.framework.pay.core.client.dto.refund.PayRefundRespDTO; | ||
| 8 | -import cn.iocoder.yudao.module.pay.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO; | ||
| 9 | import cn.iocoder.yudao.framework.test.core.ut.BaseDbAndRedisUnitTest; | 5 | import cn.iocoder.yudao.framework.test.core.ut.BaseDbAndRedisUnitTest; |
| 10 | import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO; | 6 | import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO; |
| 11 | import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.PayRefundExportReqVO; | 7 | import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.PayRefundExportReqVO; |
| @@ -16,21 +12,25 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; | @@ -16,21 +12,25 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; | ||
| 16 | import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO; | 12 | import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO; |
| 17 | import cn.iocoder.yudao.module.pay.dal.mysql.refund.PayRefundMapper; | 13 | import cn.iocoder.yudao.module.pay.dal.mysql.refund.PayRefundMapper; |
| 18 | import cn.iocoder.yudao.module.pay.dal.redis.no.PayNoRedisDAO; | 14 | import cn.iocoder.yudao.module.pay.dal.redis.no.PayNoRedisDAO; |
| 15 | +import cn.iocoder.yudao.module.pay.enums.PayChannelEnum; | ||
| 19 | import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyTypeEnum; | 16 | import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyTypeEnum; |
| 20 | import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; | 17 | import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; |
| 21 | import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum; | 18 | import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum; |
| 22 | import cn.iocoder.yudao.module.pay.framework.pay.config.PayProperties; | 19 | import cn.iocoder.yudao.module.pay.framework.pay.config.PayProperties; |
| 20 | +import cn.iocoder.yudao.module.pay.framework.pay.core.client.PayClient; | ||
| 21 | +import cn.iocoder.yudao.module.pay.framework.pay.core.client.dto.refund.PayRefundRespDTO; | ||
| 22 | +import cn.iocoder.yudao.module.pay.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO; | ||
| 23 | import cn.iocoder.yudao.module.pay.service.app.PayAppService; | 23 | import cn.iocoder.yudao.module.pay.service.app.PayAppService; |
| 24 | import cn.iocoder.yudao.module.pay.service.channel.PayChannelService; | 24 | import cn.iocoder.yudao.module.pay.service.channel.PayChannelService; |
| 25 | import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService; | 25 | import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService; |
| 26 | import cn.iocoder.yudao.module.pay.service.order.PayOrderService; | 26 | import cn.iocoder.yudao.module.pay.service.order.PayOrderService; |
| 27 | +import jakarta.annotation.Resource; | ||
| 27 | import org.junit.jupiter.api.BeforeEach; | 28 | import org.junit.jupiter.api.BeforeEach; |
| 28 | import org.junit.jupiter.api.Test; | 29 | import org.junit.jupiter.api.Test; |
| 29 | import org.mockito.MockedStatic; | 30 | import org.mockito.MockedStatic; |
| 30 | -import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 31 | import org.springframework.context.annotation.Import; | 31 | import org.springframework.context.annotation.Import; |
| 32 | +import org.springframework.test.context.bean.override.mockito.MockitoBean; | ||
| 32 | 33 | ||
| 33 | -import jakarta.annotation.Resource; | ||
| 34 | import java.util.List; | 34 | import java.util.List; |
| 35 | 35 | ||
| 36 | import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime; | 36 | import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime; |
| @@ -62,15 +62,15 @@ public class PayRefundServiceTest extends BaseDbAndRedisUnitTest { | @@ -62,15 +62,15 @@ public class PayRefundServiceTest extends BaseDbAndRedisUnitTest { | ||
| 62 | @Resource | 62 | @Resource |
| 63 | private PayRefundMapper refundMapper; | 63 | private PayRefundMapper refundMapper; |
| 64 | 64 | ||
| 65 | - @MockBean | 65 | + @MockitoBean |
| 66 | private PayProperties payProperties; | 66 | private PayProperties payProperties; |
| 67 | - @MockBean | 67 | + @MockitoBean |
| 68 | private PayOrderService orderService; | 68 | private PayOrderService orderService; |
| 69 | - @MockBean | 69 | + @MockitoBean |
| 70 | private PayAppService appService; | 70 | private PayAppService appService; |
| 71 | - @MockBean | 71 | + @MockitoBean |
| 72 | private PayChannelService channelService; | 72 | private PayChannelService channelService; |
| 73 | - @MockBean | 73 | + @MockitoBean |
| 74 | private PayNotifyService notifyService; | 74 | private PayNotifyService notifyService; |
| 75 | 75 | ||
| 76 | @BeforeEach | 76 | @BeforeEach |
yudao-module-report/src/test/java/cn/iocoder/yudao/module/report/service/goview/GoViewDataServiceImplTest.java
| @@ -2,14 +2,14 @@ package cn.iocoder.yudao.module.report.service.goview; | @@ -2,14 +2,14 @@ package cn.iocoder.yudao.module.report.service.goview; | ||
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; | 3 | import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; |
| 4 | import cn.iocoder.yudao.module.report.controller.admin.goview.vo.data.GoViewDataRespVO; | 4 | import cn.iocoder.yudao.module.report.controller.admin.goview.vo.data.GoViewDataRespVO; |
| 5 | +import jakarta.annotation.Resource; | ||
| 5 | import org.junit.jupiter.api.Test; | 6 | import org.junit.jupiter.api.Test; |
| 6 | -import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 7 | import org.springframework.context.annotation.Import; | 7 | import org.springframework.context.annotation.Import; |
| 8 | import org.springframework.jdbc.core.JdbcTemplate; | 8 | import org.springframework.jdbc.core.JdbcTemplate; |
| 9 | import org.springframework.jdbc.support.rowset.SqlRowSet; | 9 | import org.springframework.jdbc.support.rowset.SqlRowSet; |
| 10 | import org.springframework.jdbc.support.rowset.SqlRowSetMetaData; | 10 | import org.springframework.jdbc.support.rowset.SqlRowSetMetaData; |
| 11 | +import org.springframework.test.context.bean.override.mockito.MockitoBean; | ||
| 11 | 12 | ||
| 12 | -import jakarta.annotation.Resource; | ||
| 13 | import java.util.Arrays; | 13 | import java.util.Arrays; |
| 14 | 14 | ||
| 15 | import static org.junit.jupiter.api.Assertions.assertEquals; | 15 | import static org.junit.jupiter.api.Assertions.assertEquals; |
| @@ -23,7 +23,7 @@ public class GoViewDataServiceImplTest extends BaseDbUnitTest { | @@ -23,7 +23,7 @@ public class GoViewDataServiceImplTest extends BaseDbUnitTest { | ||
| 23 | @Resource | 23 | @Resource |
| 24 | private GoViewDataServiceImpl goViewDataService; | 24 | private GoViewDataServiceImpl goViewDataService; |
| 25 | 25 | ||
| 26 | - @MockBean | 26 | + @MockitoBean |
| 27 | private JdbcTemplate jdbcTemplate; | 27 | private JdbcTemplate jdbcTemplate; |
| 28 | 28 | ||
| 29 | @Test | 29 | @Test |
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/api/mail/MailSendApiImpl.java
| @@ -21,13 +21,15 @@ public class MailSendApiImpl implements MailSendApi { | @@ -21,13 +21,15 @@ public class MailSendApiImpl implements MailSendApi { | ||
| 21 | 21 | ||
| 22 | @Override | 22 | @Override |
| 23 | public Long sendSingleMailToAdmin(MailSendSingleToUserReqDTO reqDTO) { | 23 | public Long sendSingleMailToAdmin(MailSendSingleToUserReqDTO reqDTO) { |
| 24 | - return mailSendService.sendSingleMailToAdmin(reqDTO.getMail(), reqDTO.getUserId(), | 24 | + return mailSendService.sendSingleMailToAdmin(reqDTO.getUserId(), |
| 25 | + reqDTO.getToMails(), reqDTO.getCcMails(), reqDTO.getBccMails(), | ||
| 25 | reqDTO.getTemplateCode(), reqDTO.getTemplateParams()); | 26 | reqDTO.getTemplateCode(), reqDTO.getTemplateParams()); |
| 26 | } | 27 | } |
| 27 | 28 | ||
| 28 | @Override | 29 | @Override |
| 29 | public Long sendSingleMailToMember(MailSendSingleToUserReqDTO reqDTO) { | 30 | public Long sendSingleMailToMember(MailSendSingleToUserReqDTO reqDTO) { |
| 30 | - return mailSendService.sendSingleMailToMember(reqDTO.getMail(), reqDTO.getUserId(), | 31 | + return mailSendService.sendSingleMailToMember(reqDTO.getUserId(), |
| 32 | + reqDTO.getToMails(), reqDTO.getCcMails(), reqDTO.getBccMails(), | ||
| 31 | reqDTO.getTemplateCode(), reqDTO.getTemplateParams()); | 33 | reqDTO.getTemplateCode(), reqDTO.getTemplateParams()); |
| 32 | } | 34 | } |
| 33 | 35 |
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/api/mail/dto/MailSendSingleToUserReqDTO.java
| @@ -4,6 +4,8 @@ import lombok.Data; | @@ -4,6 +4,8 @@ import lombok.Data; | ||
| 4 | 4 | ||
| 5 | import jakarta.validation.constraints.Email; | 5 | import jakarta.validation.constraints.Email; |
| 6 | import jakarta.validation.constraints.NotNull; | 6 | import jakarta.validation.constraints.NotNull; |
| 7 | + | ||
| 8 | +import java.util.List; | ||
| 7 | import java.util.Map; | 9 | import java.util.Map; |
| 8 | 10 | ||
| 9 | /** | 11 | /** |
| @@ -16,13 +18,24 @@ public class MailSendSingleToUserReqDTO { | @@ -16,13 +18,24 @@ public class MailSendSingleToUserReqDTO { | ||
| 16 | 18 | ||
| 17 | /** | 19 | /** |
| 18 | * 用户编号 | 20 | * 用户编号 |
| 21 | + * | ||
| 22 | + * 如果非空,则加载对应用户的邮箱,添加到 {@link #toMails} 中 | ||
| 19 | */ | 23 | */ |
| 20 | private Long userId; | 24 | private Long userId; |
| 25 | + | ||
| 26 | + /** | ||
| 27 | + * 收件邮箱 | ||
| 28 | + */ | ||
| 29 | + private List<@Email String> toMails; | ||
| 21 | /** | 30 | /** |
| 22 | - * 邮箱 | 31 | + * 抄送邮箱 |
| 23 | */ | 32 | */ |
| 24 | |||
| 25 | - private String mail; | 33 | + private List<@Email String> ccMails; |
| 34 | + /** | ||
| 35 | + * 密送邮箱 | ||
| 36 | + */ | ||
| 37 | + private List<@Email String> bccMails; | ||
| 38 | + | ||
| 26 | 39 | ||
| 27 | /** | 40 | /** |
| 28 | * 邮件模板编号 | 41 | * 邮件模板编号 |
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.http
| @@ -11,6 +11,24 @@ tag: Yunai.local | @@ -11,6 +11,24 @@ tag: Yunai.local | ||
| 11 | "code": "1024" | 11 | "code": "1024" |
| 12 | } | 12 | } |
| 13 | 13 | ||
| 14 | +### 请求 /login 接口【加密 AES】 => 成功 | ||
| 15 | +POST {{baseUrl}}/system/auth/login | ||
| 16 | +Content-Type: application/json | ||
| 17 | +tenant-id: {{adminTenantId}} | ||
| 18 | +tag: Yunai.local | ||
| 19 | +X-API-ENCRYPT: true | ||
| 20 | + | ||
| 21 | +WvSX9MOrenyGfBhEM0g1/hHgq8ocktMZ9OwAJ6MOG5FUrzYF/rG5JF1eMptQM1wT73VgDS05l/37WeRtad+JrqChAul/sR/SdOsUKqjBhvvQx1JVhzxr6s8uUP67aKTSZ6Psv7O32ELxXrzSaQvG5CInzz3w6sLtbNNLd1kXe6Q= | ||
| 22 | + | ||
| 23 | +### 请求 /login 接口【加密 RSA】 => 成功 | ||
| 24 | +POST {{baseUrl}}/system/auth/login | ||
| 25 | +Content-Type: application/json | ||
| 26 | +tenant-id: {{adminTenantId}} | ||
| 27 | +tag: Yunai.local | ||
| 28 | +X-API-ENCRYPT: true | ||
| 29 | + | ||
| 30 | +e7QZTork9ZV5CmgZvSd+cHZk3xdUxKtowLM02kOha+gxHK2H/daU8nVBYS3+bwuDRy5abf+Pz1QJJGVAEd27wwrXBmupOOA/bhpuzzDwcRuJRD+z+YgiNoEXFDRHERxPYlPqAe9zAHtihD0ceub1AjybQsEsROew4C3Q602XYW0= | ||
| 31 | + | ||
| 14 | ### 请求 /login 接口 => 成功(无验证码) | 32 | ### 请求 /login 接口 => 成功(无验证码) |
| 15 | POST {{baseUrl}}/system/auth/login | 33 | POST {{baseUrl}}/system/auth/login |
| 16 | Content-Type: application/json | 34 | Content-Type: application/json |
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/DeptController.java
| @@ -56,6 +56,15 @@ public class DeptController { | @@ -56,6 +56,15 @@ public class DeptController { | ||
| 56 | return success(true); | 56 | return success(true); |
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | + @DeleteMapping("/delete-list") | ||
| 60 | + @Operation(summary = "批量删除部门") | ||
| 61 | + @Parameter(name = "ids", description = "编号列表", required = true) | ||
| 62 | + @PreAuthorize("@ss.hasPermission('system:dept:delete')") | ||
| 63 | + public CommonResult<Boolean> deleteDeptList(@RequestParam("ids") List<Long> ids) { | ||
| 64 | + deptService.deleteDeptList(ids); | ||
| 65 | + return success(true); | ||
| 66 | + } | ||
| 67 | + | ||
| 59 | @GetMapping("/list") | 68 | @GetMapping("/list") |
| 60 | @Operation(summary = "获取部门列表") | 69 | @Operation(summary = "获取部门列表") |
| 61 | @PreAuthorize("@ss.hasPermission('system:dept:query')") | 70 | @PreAuthorize("@ss.hasPermission('system:dept:query')") |
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/MailTemplateController.java
| @@ -91,7 +91,8 @@ public class MailTemplateController { | @@ -91,7 +91,8 @@ public class MailTemplateController { | ||
| 91 | @Operation(summary = "发送短信") | 91 | @Operation(summary = "发送短信") |
| 92 | @PreAuthorize("@ss.hasPermission('system:mail-template:send-mail')") | 92 | @PreAuthorize("@ss.hasPermission('system:mail-template:send-mail')") |
| 93 | public CommonResult<Long> sendMail(@Valid @RequestBody MailTemplateSendReqVO sendReqVO) { | 93 | public CommonResult<Long> sendMail(@Valid @RequestBody MailTemplateSendReqVO sendReqVO) { |
| 94 | - return success(mailSendService.sendSingleMailToAdmin(sendReqVO.getMail(), getLoginUserId(), | 94 | + return success(mailSendService.sendSingleMailToAdmin(getLoginUserId(), |
| 95 | + sendReqVO.getToMails(), sendReqVO.getCcMails(), sendReqVO.getBccMails(), | ||
| 95 | sendReqVO.getTemplateCode(), sendReqVO.getTemplateParams())); | 96 | sendReqVO.getTemplateCode(), sendReqVO.getTemplateParams())); |
| 96 | } | 97 | } |
| 97 | 98 |
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/log/MailLogRespVO.java
| @@ -2,13 +2,11 @@ package cn.iocoder.yudao.module.system.controller.admin.mail.vo.log; | @@ -2,13 +2,11 @@ package cn.iocoder.yudao.module.system.controller.admin.mail.vo.log; | ||
| 2 | 2 | ||
| 3 | import io.swagger.v3.oas.annotations.media.Schema; | 3 | import io.swagger.v3.oas.annotations.media.Schema; |
| 4 | import lombok.Data; | 4 | import lombok.Data; |
| 5 | -import org.springframework.format.annotation.DateTimeFormat; | ||
| 6 | 5 | ||
| 7 | import java.time.LocalDateTime; | 6 | import java.time.LocalDateTime; |
| 7 | +import java.util.List; | ||
| 8 | import java.util.Map; | 8 | import java.util.Map; |
| 9 | 9 | ||
| 10 | -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | ||
| 11 | - | ||
| 12 | @Schema(description = "管理后台 - 邮件日志 Response VO") | 10 | @Schema(description = "管理后台 - 邮件日志 Response VO") |
| 13 | @Data | 11 | @Data |
| 14 | public class MailLogRespVO { | 12 | public class MailLogRespVO { |
| @@ -22,8 +20,14 @@ public class MailLogRespVO { | @@ -22,8 +20,14 @@ public class MailLogRespVO { | ||
| 22 | @Schema(description = "用户类型,参见 UserTypeEnum 枚举", example = "2") | 20 | @Schema(description = "用户类型,参见 UserTypeEnum 枚举", example = "2") |
| 23 | private Byte userType; | 21 | private Byte userType; |
| 24 | 22 | ||
| 25 | - @Schema(description = "接收邮箱地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "76854@qq.com") | ||
| 26 | - private String toMail; | 23 | + @Schema(description = "接收邮箱地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "user1@example.com, user2@example.com") |
| 24 | + private List<String> toMails; | ||
| 25 | + | ||
| 26 | + @Schema(description = "抄送邮箱地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "user3@example.com, user4@example.com") | ||
| 27 | + private List<String> ccMails; | ||
| 28 | + | ||
| 29 | + @Schema(description = "密送邮箱地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "user5@example.com, user6@example.com") | ||
| 30 | + private List<String> bccMails; | ||
| 27 | 31 | ||
| 28 | @Schema(description = "邮箱账号编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "18107") | 32 | @Schema(description = "邮箱账号编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "18107") |
| 29 | private Long accountId; | 33 | private Long accountId; |
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/template/MailTemplateSendReqVO.java
| @@ -5,15 +5,22 @@ import lombok.Data; | @@ -5,15 +5,22 @@ import lombok.Data; | ||
| 5 | 5 | ||
| 6 | import jakarta.validation.constraints.NotEmpty; | 6 | import jakarta.validation.constraints.NotEmpty; |
| 7 | import jakarta.validation.constraints.NotNull; | 7 | import jakarta.validation.constraints.NotNull; |
| 8 | +import java.util.List; | ||
| 8 | import java.util.Map; | 9 | import java.util.Map; |
| 9 | 10 | ||
| 10 | @Schema(description = "管理后台 - 邮件发送 Req VO") | 11 | @Schema(description = "管理后台 - 邮件发送 Req VO") |
| 11 | @Data | 12 | @Data |
| 12 | public class MailTemplateSendReqVO { | 13 | public class MailTemplateSendReqVO { |
| 13 | 14 | ||
| 14 | - @Schema(description = "接收邮箱", requiredMode = Schema.RequiredMode.REQUIRED, example = "7685413@qq.com") | 15 | + @Schema(description = "接收邮箱", requiredMode = Schema.RequiredMode.REQUIRED, example = "[user1@example.com, user2@example.com]") |
| 15 | @NotEmpty(message = "接收邮箱不能为空") | 16 | @NotEmpty(message = "接收邮箱不能为空") |
| 16 | - private String mail; | 17 | + private List<String> toMails; |
| 18 | + | ||
| 19 | + @Schema(description = "抄送邮箱", requiredMode = Schema.RequiredMode.REQUIRED, example = "[user3@example.com, user4@example.com]") | ||
| 20 | + private List<String> ccMails; | ||
| 21 | + | ||
| 22 | + @Schema(description = "密送邮箱", requiredMode = Schema.RequiredMode.REQUIRED, example = "[user5@example.com, user6@example.com]") | ||
| 23 | + private List<String> bccMails; | ||
| 17 | 24 | ||
| 18 | @Schema(description = "模板编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "test_01") | 25 | @Schema(description = "模板编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "test_01") |
| 19 | @NotNull(message = "模板编码不能为空") | 26 | @NotNull(message = "模板编码不能为空") |
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/mail/MailLogDO.java
| @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.system.dal.dataobject.mail; | @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.system.dal.dataobject.mail; | ||
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; | 3 | import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; |
| 4 | import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; | 4 | import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; |
| 5 | +import cn.iocoder.yudao.framework.mybatis.core.type.StringListTypeHandler; | ||
| 5 | import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; | 6 | import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; |
| 6 | import cn.iocoder.yudao.module.system.enums.mail.MailSendStatusEnum; | 7 | import cn.iocoder.yudao.module.system.enums.mail.MailSendStatusEnum; |
| 7 | import com.baomidou.mybatisplus.annotation.KeySequence; | 8 | import com.baomidou.mybatisplus.annotation.KeySequence; |
| @@ -12,6 +13,7 @@ import lombok.*; | @@ -12,6 +13,7 @@ import lombok.*; | ||
| 12 | 13 | ||
| 13 | import java.io.Serializable; | 14 | import java.io.Serializable; |
| 14 | import java.time.LocalDateTime; | 15 | import java.time.LocalDateTime; |
| 16 | +import java.util.List; | ||
| 15 | import java.util.Map; | 17 | import java.util.Map; |
| 16 | 18 | ||
| 17 | /** | 19 | /** |
| @@ -47,10 +49,22 @@ public class MailLogDO extends BaseDO implements Serializable { | @@ -47,10 +49,22 @@ public class MailLogDO extends BaseDO implements Serializable { | ||
| 47 | * 枚举 {@link UserTypeEnum} | 49 | * 枚举 {@link UserTypeEnum} |
| 48 | */ | 50 | */ |
| 49 | private Integer userType; | 51 | private Integer userType; |
| 52 | + | ||
| 53 | + /** | ||
| 54 | + * 接收邮箱地址 | ||
| 55 | + */ | ||
| 56 | + @TableField(typeHandler = StringListTypeHandler.class) | ||
| 57 | + private List<String> toMails; | ||
| 50 | /** | 58 | /** |
| 51 | * 接收邮箱地址 | 59 | * 接收邮箱地址 |
| 52 | */ | 60 | */ |
| 53 | - private String toMail; | 61 | + @TableField(typeHandler = StringListTypeHandler.class) |
| 62 | + private List<String> ccMails; | ||
| 63 | + /** | ||
| 64 | + * 密送邮箱地址 | ||
| 65 | + */ | ||
| 66 | + @TableField(typeHandler = StringListTypeHandler.class) | ||
| 67 | + private List<String> bccMails; | ||
| 54 | 68 | ||
| 55 | /** | 69 | /** |
| 56 | * 邮箱账号编号 | 70 | * 邮箱账号编号 |
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/mail/MailLogMapper.java
| 1 | package cn.iocoder.yudao.module.system.dal.mysql.mail; | 1 | package cn.iocoder.yudao.module.system.dal.mysql.mail; |
| 2 | 2 | ||
| 3 | +import cn.hutool.core.util.StrUtil; | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | 5 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| 5 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | 6 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; |
| 7 | +import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils; | ||
| 6 | import cn.iocoder.yudao.module.system.controller.admin.mail.vo.log.MailLogPageReqVO; | 8 | import cn.iocoder.yudao.module.system.controller.admin.mail.vo.log.MailLogPageReqVO; |
| 7 | import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailLogDO; | 9 | import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailLogDO; |
| 8 | import org.apache.ibatis.annotations.Mapper; | 10 | import org.apache.ibatis.annotations.Mapper; |
| @@ -14,11 +16,12 @@ public interface MailLogMapper extends BaseMapperX<MailLogDO> { | @@ -14,11 +16,12 @@ public interface MailLogMapper extends BaseMapperX<MailLogDO> { | ||
| 14 | return selectPage(reqVO, new LambdaQueryWrapperX<MailLogDO>() | 16 | return selectPage(reqVO, new LambdaQueryWrapperX<MailLogDO>() |
| 15 | .eqIfPresent(MailLogDO::getUserId, reqVO.getUserId()) | 17 | .eqIfPresent(MailLogDO::getUserId, reqVO.getUserId()) |
| 16 | .eqIfPresent(MailLogDO::getUserType, reqVO.getUserType()) | 18 | .eqIfPresent(MailLogDO::getUserType, reqVO.getUserType()) |
| 17 | - .likeIfPresent(MailLogDO::getToMail, reqVO.getToMail()) | ||
| 18 | .eqIfPresent(MailLogDO::getAccountId, reqVO.getAccountId()) | 19 | .eqIfPresent(MailLogDO::getAccountId, reqVO.getAccountId()) |
| 19 | .eqIfPresent(MailLogDO::getTemplateId, reqVO.getTemplateId()) | 20 | .eqIfPresent(MailLogDO::getTemplateId, reqVO.getTemplateId()) |
| 20 | .eqIfPresent(MailLogDO::getSendStatus, reqVO.getSendStatus()) | 21 | .eqIfPresent(MailLogDO::getSendStatus, reqVO.getSendStatus()) |
| 21 | .betweenIfPresent(MailLogDO::getSendTime, reqVO.getSendTime()) | 22 | .betweenIfPresent(MailLogDO::getSendTime, reqVO.getSendTime()) |
| 23 | + .apply(StrUtil.isNotBlank(reqVO.getToMail()), | ||
| 24 | + MyBatisUtils.findInSet("to_mails", reqVO.getToMail())) | ||
| 22 | .orderByDesc(MailLogDO::getId)); | 25 | .orderByDesc(MailLogDO::getId)); |
| 23 | } | 26 | } |
| 24 | 27 |
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/framework/captcha/core/PictureWordCaptchaServiceImpl.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.framework.captcha.core; | ||
| 2 | + | ||
| 3 | +import com.anji.captcha.model.common.RepCodeEnum; | ||
| 4 | +import com.anji.captcha.model.common.ResponseModel; | ||
| 5 | +import com.anji.captcha.model.vo.CaptchaVO; | ||
| 6 | +import com.anji.captcha.service.impl.AbstractCaptchaService; | ||
| 7 | +import com.anji.captcha.service.impl.CaptchaServiceFactory; | ||
| 8 | +import com.anji.captcha.util.AESUtil; | ||
| 9 | +import com.anji.captcha.util.ImageUtils; | ||
| 10 | +import com.anji.captcha.util.RandomUtils; | ||
| 11 | +import org.apache.commons.lang3.StringUtils; | ||
| 12 | +import cn.hutool.core.util.RandomUtil; | ||
| 13 | + | ||
| 14 | +import java.awt.*; | ||
| 15 | +import java.awt.geom.AffineTransform; | ||
| 16 | +import java.awt.image.BufferedImage; | ||
| 17 | +import java.util.Properties; | ||
| 18 | + | ||
| 19 | +/** | ||
| 20 | + * 图片文字验证码 | ||
| 21 | + * | ||
| 22 | + * @author Tsui | ||
| 23 | + * @since 2025/7/23 20:44 | ||
| 24 | + */ | ||
| 25 | +public class PictureWordCaptchaServiceImpl extends AbstractCaptchaService { | ||
| 26 | + | ||
| 27 | + /** | ||
| 28 | + * 验证码的基础字符 | ||
| 29 | + */ | ||
| 30 | + private static final String CHARACTERS = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789"; | ||
| 31 | + /** | ||
| 32 | + * 验证码长度 | ||
| 33 | + */ | ||
| 34 | + private static final Integer LENGTH = 4; | ||
| 35 | + | ||
| 36 | + private static final int WIDTH = 120; | ||
| 37 | + private static final int HEIGHT = 40; | ||
| 38 | + private static final int LINES = 10; | ||
| 39 | + | ||
| 40 | + @Override | ||
| 41 | + public void init(Properties config) { | ||
| 42 | + super.init(config); | ||
| 43 | + } | ||
| 44 | + | ||
| 45 | + @Override | ||
| 46 | + public void destroy(Properties config) { | ||
| 47 | + logger.info("start-clear-history-data-{}", captchaType()); | ||
| 48 | + } | ||
| 49 | + | ||
| 50 | + @Override | ||
| 51 | + public String captchaType() { | ||
| 52 | + return "pictureWord"; | ||
| 53 | + } | ||
| 54 | + | ||
| 55 | + @Override | ||
| 56 | + public ResponseModel get(CaptchaVO captchaVO) { | ||
| 57 | + String text = generateRandomText(LENGTH); | ||
| 58 | + CaptchaVO imageData = getImageData(text); | ||
| 59 | + // pointJson 不传到前端,只做后端校验,测试时放开 | ||
| 60 | +// imageData.setPointJson(text); | ||
| 61 | + return ResponseModel.successData(imageData); | ||
| 62 | + } | ||
| 63 | + | ||
| 64 | + @Override | ||
| 65 | + public ResponseModel check(CaptchaVO captchaVO) { | ||
| 66 | + ResponseModel r = super.check(captchaVO); | ||
| 67 | + if (!validatedReq(r)) { | ||
| 68 | + return r; | ||
| 69 | + } | ||
| 70 | + | ||
| 71 | + // 取出验证码 | ||
| 72 | + String codeKey = String.format(REDIS_CAPTCHA_KEY, captchaVO.getToken()); | ||
| 73 | + if (!CaptchaServiceFactory.getCache(cacheType).exists(codeKey)) { | ||
| 74 | + return ResponseModel.errorMsg(RepCodeEnum.API_CAPTCHA_INVALID); | ||
| 75 | + } | ||
| 76 | + // 正确的验证码 | ||
| 77 | + String codeValue = CaptchaServiceFactory.getCache(cacheType).get(codeKey); | ||
| 78 | + String code = getCodeByCodeValue(codeValue); | ||
| 79 | + String secretKey = getSecretKeyByCodeValue(codeValue); | ||
| 80 | + // 验证码只用一次,即刻失效 | ||
| 81 | + CaptchaServiceFactory.getCache(cacheType).delete(codeKey); | ||
| 82 | + | ||
| 83 | + // 用户输入的验证码(CaptchaVO 中 没有预留字段,暂时用 pointJson 无需加解密) | ||
| 84 | + String userCode = captchaVO.getPointJson(); | ||
| 85 | + if (!StringUtils.equalsIgnoreCase(code, userCode)) { | ||
| 86 | + afterValidateFail(captchaVO); | ||
| 87 | + return ResponseModel.errorMsg(RepCodeEnum.API_CAPTCHA_COORDINATE_ERROR); | ||
| 88 | + } | ||
| 89 | + | ||
| 90 | + // 校验成功,将信息存入缓存 | ||
| 91 | + String value; | ||
| 92 | + try { | ||
| 93 | + value = AESUtil.aesEncrypt(captchaVO.getToken().concat("---").concat(userCode), secretKey); | ||
| 94 | + } catch (Exception e) { | ||
| 95 | + logger.error("AES 加密失败", e); | ||
| 96 | + afterValidateFail(captchaVO); | ||
| 97 | + return ResponseModel.errorMsg(e.getMessage()); | ||
| 98 | + } | ||
| 99 | + String secondKey = String.format(REDIS_SECOND_CAPTCHA_KEY, value); | ||
| 100 | + CaptchaServiceFactory.getCache(cacheType).set(secondKey, captchaVO.getToken(), EXPIRESIN_THREE); | ||
| 101 | + captchaVO.setResult(true); | ||
| 102 | + captchaVO.resetClientFlag(); | ||
| 103 | + return ResponseModel.successData(captchaVO); | ||
| 104 | + } | ||
| 105 | + | ||
| 106 | + @Override | ||
| 107 | + public ResponseModel verification(CaptchaVO captchaVO) { | ||
| 108 | + ResponseModel r = super.verification(captchaVO); | ||
| 109 | + if (!validatedReq(r)) { | ||
| 110 | + return r; | ||
| 111 | + } | ||
| 112 | + try { | ||
| 113 | + String codeKey = String.format(REDIS_SECOND_CAPTCHA_KEY, captchaVO.getCaptchaVerification()); | ||
| 114 | + if (!CaptchaServiceFactory.getCache(cacheType).exists(codeKey)) { | ||
| 115 | + return ResponseModel.errorMsg(RepCodeEnum.API_CAPTCHA_INVALID); | ||
| 116 | + } | ||
| 117 | + // 二次校验取值后,即刻失效 | ||
| 118 | + CaptchaServiceFactory.getCache(cacheType).delete(codeKey); | ||
| 119 | + } catch (Exception e) { | ||
| 120 | + logger.error("验证码解析失败", e); | ||
| 121 | + return ResponseModel.errorMsg(e.getMessage()); | ||
| 122 | + } | ||
| 123 | + return ResponseModel.success(); | ||
| 124 | + } | ||
| 125 | + | ||
| 126 | + | ||
| 127 | + private CaptchaVO getImageData(String text) { | ||
| 128 | + CaptchaVO dataVO = new CaptchaVO(); | ||
| 129 | + BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB); | ||
| 130 | + Graphics2D g = image.createGraphics(); | ||
| 131 | + | ||
| 132 | + // 设置背景色 | ||
| 133 | + g.setColor(getRandomColor(200, 250)); | ||
| 134 | + g.fillRect(0, 0, WIDTH, HEIGHT); | ||
| 135 | + // 绘制干扰线 | ||
| 136 | + for (int i = 0; i < LINES; i++) { | ||
| 137 | + g.setColor(getRandomColor(100, 200)); | ||
| 138 | + int x1 = RandomUtil.randomInt(WIDTH); | ||
| 139 | + int y1 = RandomUtil.randomInt(HEIGHT); | ||
| 140 | + int x2 = RandomUtil.randomInt(WIDTH); | ||
| 141 | + int y2 = RandomUtil.randomInt(HEIGHT); | ||
| 142 | + g.drawLine(x1, y1, x2, y2); | ||
| 143 | + } | ||
| 144 | + // 设置字体 | ||
| 145 | + g.setFont(new Font("Arial", Font.BOLD, 24)); | ||
| 146 | + // 绘制验证码文本 | ||
| 147 | + for (int i = 0; i < text.length(); i++) { | ||
| 148 | + g.setColor(getRandomColor(20, 130)); | ||
| 149 | + // 文字旋转 | ||
| 150 | + AffineTransform affineTransform = new AffineTransform(); | ||
| 151 | + int x = 20 + i * 20; | ||
| 152 | + int y = 24 + RandomUtil.randomInt(8); | ||
| 153 | + // 旋转范围 -45 ~ 45 | ||
| 154 | + affineTransform.setToRotation(Math.toRadians(RandomUtil.randomInt(-45, 45)), x, y); | ||
| 155 | + g.setTransform(affineTransform); | ||
| 156 | + g.drawString(text.charAt(i) + "", x, y); | ||
| 157 | + } | ||
| 158 | + // 添加噪点 | ||
| 159 | + for (int i = 0; i < 100; i++) { | ||
| 160 | + int x = RandomUtil.randomInt(WIDTH); | ||
| 161 | + int y = RandomUtil.randomInt(HEIGHT); | ||
| 162 | + image.setRGB(x, y, getRandomColor(0, 255).getRGB()); | ||
| 163 | + } | ||
| 164 | + g.dispose(); | ||
| 165 | + | ||
| 166 | + String secretKey = null; | ||
| 167 | + if (captchaAesStatus) { | ||
| 168 | + secretKey = AESUtil.getKey(); | ||
| 169 | + } | ||
| 170 | + dataVO.setSecretKey(secretKey); | ||
| 171 | + | ||
| 172 | + dataVO.setOriginalImageBase64(ImageUtils.getImageToBase64Str(image).replaceAll("\r|\n", "")); | ||
| 173 | + dataVO.setToken(RandomUtils.getUUID()); | ||
| 174 | +// dataVO.setSecretKey(secretKey); | ||
| 175 | + // 将坐标信息存入 redis 中 | ||
| 176 | + String codeKey = String.format(REDIS_CAPTCHA_KEY, dataVO.getToken()); | ||
| 177 | + CaptchaServiceFactory.getCache(cacheType).set(codeKey, getCodeValue(text, secretKey), EXPIRESIN_SECONDS); | ||
| 178 | + return dataVO; | ||
| 179 | + } | ||
| 180 | + | ||
| 181 | + private String getCodeValue(String text, String secretKey) { | ||
| 182 | + return text + "," + secretKey; | ||
| 183 | + } | ||
| 184 | + | ||
| 185 | + private String getCodeByCodeValue(String codeValue) { | ||
| 186 | + return codeValue.split(",")[0]; | ||
| 187 | + } | ||
| 188 | + | ||
| 189 | + private String getSecretKeyByCodeValue(String codeValue) { | ||
| 190 | + return codeValue.split(",")[1]; | ||
| 191 | + } | ||
| 192 | + | ||
| 193 | + private Color getRandomColor(int min, int max) { | ||
| 194 | + int minVal = Math.min(min, max); | ||
| 195 | + int maxVal = Math.max(min, max); | ||
| 196 | + int r = RandomUtil.randomInt(minVal, maxVal); | ||
| 197 | + int g = RandomUtil.randomInt(minVal, maxVal); | ||
| 198 | + int b = RandomUtil.randomInt(minVal, maxVal); | ||
| 199 | + return new Color(r, g, b); | ||
| 200 | + } | ||
| 201 | + | ||
| 202 | + /** | ||
| 203 | + * 生成指定长度的随机字符串 | ||
| 204 | + * | ||
| 205 | + * @param length 长度 | ||
| 206 | + * @return {@link String} | ||
| 207 | + */ | ||
| 208 | + public static String generateRandomText(int length) { | ||
| 209 | + return RandomUtil.randomString(CHARACTERS, length); | ||
| 210 | + } | ||
| 211 | + | ||
| 212 | +} | ||
| 0 | \ No newline at end of file | 213 | \ No newline at end of file |
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/AliyunSmsClient.java
| @@ -136,15 +136,20 @@ public class AliyunSmsClient extends AbstractSmsClient { | @@ -136,15 +136,20 @@ public class AliyunSmsClient extends AbstractSmsClient { | ||
| 136 | .map(entry -> percentCode(entry.getKey()) + "=" + percentCode(String.valueOf(entry.getValue()))) | 136 | .map(entry -> percentCode(entry.getKey()) + "=" + percentCode(String.valueOf(entry.getValue()))) |
| 137 | .collect(Collectors.joining("&")); | 137 | .collect(Collectors.joining("&")); |
| 138 | 138 | ||
| 139 | - // 2.1 请求 Header | 139 | + // 2. 请求 Body |
| 140 | + String requestBody = ""; // 短信 API 为 RPC 接口,query parameters 在 uri 中拼接,因此 request body 如果没有特殊要求,设置为空 | ||
| 141 | + String hashedRequestPayload = DigestUtil.sha256Hex(requestBody); | ||
| 142 | + | ||
| 143 | + // 3.1 请求 Header | ||
| 140 | TreeMap<String, String> headers = new TreeMap<>(); | 144 | TreeMap<String, String> headers = new TreeMap<>(); |
| 141 | headers.put("host", HOST); | 145 | headers.put("host", HOST); |
| 142 | headers.put("x-acs-version", VERSION); | 146 | headers.put("x-acs-version", VERSION); |
| 143 | headers.put("x-acs-action", apiName); | 147 | headers.put("x-acs-action", apiName); |
| 144 | headers.put("x-acs-date", FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss'Z'", TimeZone.getTimeZone("GMT")).format(new Date())); | 148 | headers.put("x-acs-date", FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss'Z'", TimeZone.getTimeZone("GMT")).format(new Date())); |
| 145 | headers.put("x-acs-signature-nonce", IdUtil.randomUUID()); | 149 | headers.put("x-acs-signature-nonce", IdUtil.randomUUID()); |
| 150 | + headers.put("x-acs-content-sha256", hashedRequestPayload); | ||
| 146 | 151 | ||
| 147 | - // 2.2 构建签名 Header | 152 | + // 3.2 构建签名 Header |
| 148 | StringBuilder canonicalHeaders = new StringBuilder(); // 构造请求头,多个规范化消息头,按照消息头名称(小写)的字符代码顺序以升序排列后拼接在一起 | 153 | StringBuilder canonicalHeaders = new StringBuilder(); // 构造请求头,多个规范化消息头,按照消息头名称(小写)的字符代码顺序以升序排列后拼接在一起 |
| 149 | StringBuilder signedHeadersBuilder = new StringBuilder(); // 已签名消息头列表,多个请求头名称(小写)按首字母升序排列并以英文分号(;)分隔 | 154 | StringBuilder signedHeadersBuilder = new StringBuilder(); // 已签名消息头列表,多个请求头名称(小写)按首字母升序排列并以英文分号(;)分隔 |
| 150 | headers.entrySet().stream().filter(entry -> entry.getKey().toLowerCase().startsWith("x-acs-") | 155 | headers.entrySet().stream().filter(entry -> entry.getKey().toLowerCase().startsWith("x-acs-") |
| @@ -157,13 +162,13 @@ public class AliyunSmsClient extends AbstractSmsClient { | @@ -157,13 +162,13 @@ public class AliyunSmsClient extends AbstractSmsClient { | ||
| 157 | }); | 162 | }); |
| 158 | String signedHeaders = signedHeadersBuilder.substring(0, signedHeadersBuilder.length() - 1); | 163 | String signedHeaders = signedHeadersBuilder.substring(0, signedHeadersBuilder.length() - 1); |
| 159 | 164 | ||
| 160 | - // 3. 请求 Body | ||
| 161 | - String requestBody = ""; // 短信 API 为 RPC 接口,query parameters 在 uri 中拼接,因此 request body 如果没有特殊要求,设置为空。 | ||
| 162 | - String hashedRequestBody = DigestUtil.sha256Hex(requestBody); | ||
| 163 | - | ||
| 164 | // 4. 构建 Authorization 签名 | 165 | // 4. 构建 Authorization 签名 |
| 165 | - String canonicalRequest = "POST" + "\n" + "/" + "\n" + queryString + "\n" | ||
| 166 | - + canonicalHeaders + "\n" + signedHeaders + "\n" + hashedRequestBody; | 166 | + String canonicalRequest = "POST" + "\n" + |
| 167 | + "/" + "\n" + | ||
| 168 | + queryString + "\n" + | ||
| 169 | + canonicalHeaders + "\n" + | ||
| 170 | + signedHeaders + "\n" + | ||
| 171 | + hashedRequestPayload; | ||
| 167 | String hashedCanonicalRequest = DigestUtil.sha256Hex(canonicalRequest); | 172 | String hashedCanonicalRequest = DigestUtil.sha256Hex(canonicalRequest); |
| 168 | String stringToSign = "ACS3-HMAC-SHA256" + "\n" + hashedCanonicalRequest; | 173 | String stringToSign = "ACS3-HMAC-SHA256" + "\n" + hashedCanonicalRequest; |
| 169 | String signature = SecureUtil.hmacSha256(properties.getApiSecret()).digestHex(stringToSign); // 计算签名 | 174 | String signature = SecureUtil.hmacSha256(properties.getApiSecret()).digestHex(stringToSign); // 计算签名 |
| @@ -184,7 +189,7 @@ public class AliyunSmsClient extends AbstractSmsClient { | @@ -184,7 +189,7 @@ public class AliyunSmsClient extends AbstractSmsClient { | ||
| 184 | @SneakyThrows | 189 | @SneakyThrows |
| 185 | private static String percentCode(String str) { | 190 | private static String percentCode(String str) { |
| 186 | Assert.notNull(str, "str 不能为空"); | 191 | Assert.notNull(str, "str 不能为空"); |
| 187 | - return HttpUtils.encodeUtf8(str) | 192 | + return URLEncoder.encode(str, StandardCharsets.UTF_8.name()) |
| 188 | .replace("+", "%20") // 加号 "+" 被替换为 "%20" | 193 | .replace("+", "%20") // 加号 "+" 被替换为 "%20" |
| 189 | .replace("*", "%2A") // 星号 "*" 被替换为 "%2A" | 194 | .replace("*", "%2A") // 星号 "*" 被替换为 "%2A" |
| 190 | .replace("%7E", "~"); // 波浪号 "%7E" 被替换为 "~" | 195 | .replace("%7E", "~"); // 波浪号 "%7E" 被替换为 "~" |
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/mq/message/mail/MailSendMessage.java
| @@ -5,6 +5,9 @@ import lombok.Data; | @@ -5,6 +5,9 @@ import lombok.Data; | ||
| 5 | import jakarta.validation.constraints.NotEmpty; | 5 | import jakarta.validation.constraints.NotEmpty; |
| 6 | import jakarta.validation.constraints.NotNull; | 6 | import jakarta.validation.constraints.NotNull; |
| 7 | 7 | ||
| 8 | +import java.util.Collection; | ||
| 9 | +import java.util.List; | ||
| 10 | + | ||
| 8 | /** | 11 | /** |
| 9 | * 邮箱发送消息 | 12 | * 邮箱发送消息 |
| 10 | * | 13 | * |
| @@ -21,8 +24,16 @@ public class MailSendMessage { | @@ -21,8 +24,16 @@ public class MailSendMessage { | ||
| 21 | /** | 24 | /** |
| 22 | * 接收邮件地址 | 25 | * 接收邮件地址 |
| 23 | */ | 26 | */ |
| 24 | - @NotNull(message = "接收邮件地址不能为空") | ||
| 25 | - private String mail; | 27 | + @NotEmpty(message = "接收邮件地址不能为空") |
| 28 | + private Collection<String> toMails; | ||
| 29 | + /** | ||
| 30 | + * 抄送邮件地址 | ||
| 31 | + */ | ||
| 32 | + private Collection<String> ccMails; | ||
| 33 | + /** | ||
| 34 | + * 密送邮件地址 | ||
| 35 | + */ | ||
| 36 | + private Collection<String> bccMails; | ||
| 26 | /** | 37 | /** |
| 27 | * 邮件账号编号 | 38 | * 邮件账号编号 |
| 28 | */ | 39 | */ |
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/mq/producer/mail/MailProducer.java
| @@ -7,6 +7,11 @@ import org.springframework.stereotype.Component; | @@ -7,6 +7,11 @@ import org.springframework.stereotype.Component; | ||
| 7 | 7 | ||
| 8 | import jakarta.annotation.Resource; | 8 | import jakarta.annotation.Resource; |
| 9 | 9 | ||
| 10 | +import java.util.Collection; | ||
| 11 | +import java.util.List; | ||
| 12 | + | ||
| 13 | +import static java.util.Collections.singletonList; | ||
| 14 | + | ||
| 10 | /** | 15 | /** |
| 11 | * Mail 邮件相关消息的 Producer | 16 | * Mail 邮件相关消息的 Producer |
| 12 | * | 17 | * |
| @@ -24,17 +29,22 @@ public class MailProducer { | @@ -24,17 +29,22 @@ public class MailProducer { | ||
| 24 | * 发送 {@link MailSendMessage} 消息 | 29 | * 发送 {@link MailSendMessage} 消息 |
| 25 | * | 30 | * |
| 26 | * @param sendLogId 发送日志编码 | 31 | * @param sendLogId 发送日志编码 |
| 27 | - * @param mail 接收邮件地址 | 32 | + * @param toMails 接收邮件地址 |
| 33 | + * @param ccMails 抄送邮件地址 | ||
| 34 | + * @param bccMails 密送邮件地址 | ||
| 28 | * @param accountId 邮件账号编号 | 35 | * @param accountId 邮件账号编号 |
| 29 | - * @param nickname 邮件发件人 | ||
| 30 | - * @param title 邮件标题 | ||
| 31 | - * @param content 邮件内容 | 36 | + * @param nickname 邮件发件人 |
| 37 | + * @param title 邮件标题 | ||
| 38 | + * @param content 邮件内容 | ||
| 32 | */ | 39 | */ |
| 33 | - public void sendMailSendMessage(Long sendLogId, String mail, Long accountId, | ||
| 34 | - String nickname, String title, String content) { | 40 | + public void sendMailSendMessage(Long sendLogId, |
| 41 | + Collection<String> toMails, Collection<String> ccMails, Collection<String> bccMails, | ||
| 42 | + Long accountId, String nickname, String title, String content) { | ||
| 35 | MailSendMessage message = new MailSendMessage() | 43 | MailSendMessage message = new MailSendMessage() |
| 36 | - .setLogId(sendLogId).setMail(mail).setAccountId(accountId) | ||
| 37 | - .setNickname(nickname).setTitle(title).setContent(content); | 44 | + .setLogId(sendLogId) |
| 45 | + .setToMails(toMails).setCcMails(ccMails).setBccMails(bccMails) | ||
| 46 | + .setAccountId(accountId).setNickname(nickname) | ||
| 47 | + .setTitle(title).setContent(content); | ||
| 38 | applicationContext.publishEvent(message); | 48 | applicationContext.publishEvent(message); |
| 39 | } | 49 | } |
| 40 | 50 |
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/dept/DeptService.java
| @@ -37,6 +37,13 @@ public interface DeptService { | @@ -37,6 +37,13 @@ public interface DeptService { | ||
| 37 | void deleteDept(Long id); | 37 | void deleteDept(Long id); |
| 38 | 38 | ||
| 39 | /** | 39 | /** |
| 40 | + * 批量删除部门 | ||
| 41 | + * | ||
| 42 | + * @param ids 部门编号数组 | ||
| 43 | + */ | ||
| 44 | + void deleteDeptList(List<Long> ids); | ||
| 45 | + | ||
| 46 | + /** | ||
| 40 | * 获得部门信息 | 47 | * 获得部门信息 |
| 41 | * | 48 | * |
| 42 | * @param id 部门编号 | 49 | * @param id 部门编号 |
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/dept/DeptServiceImpl.java
| @@ -88,6 +88,21 @@ public class DeptServiceImpl implements DeptService { | @@ -88,6 +88,21 @@ public class DeptServiceImpl implements DeptService { | ||
| 88 | deptMapper.deleteById(id); | 88 | deptMapper.deleteById(id); |
| 89 | } | 89 | } |
| 90 | 90 | ||
| 91 | + @Override | ||
| 92 | + @CacheEvict(cacheNames = RedisKeyConstants.DEPT_CHILDREN_ID_LIST, | ||
| 93 | + allEntries = true) // allEntries 清空所有缓存,因为操作一个部门,涉及到多个缓存 | ||
| 94 | + public void deleteDeptList(List<Long> ids) { | ||
| 95 | + // 校验是否有子部门 | ||
| 96 | + for (Long id : ids) { | ||
| 97 | + if (deptMapper.selectCountByParentId(id) > 0) { | ||
| 98 | + throw exception(DEPT_EXITS_CHILDREN); | ||
| 99 | + } | ||
| 100 | + } | ||
| 101 | + | ||
| 102 | + // 批量删除部门 | ||
| 103 | + deptMapper.deleteByIds(ids); | ||
| 104 | + } | ||
| 105 | + | ||
| 91 | @VisibleForTesting | 106 | @VisibleForTesting |
| 92 | void validateDeptExists(Long id) { | 107 | void validateDeptExists(Long id) { |
| 93 | if (id == null) { | 108 | if (id == null) { |
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailLogService.java
| @@ -6,6 +6,8 @@ import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO; | @@ -6,6 +6,8 @@ import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO; | ||
| 6 | import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailLogDO; | 6 | import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailLogDO; |
| 7 | import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO; | 7 | import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO; |
| 8 | 8 | ||
| 9 | +import java.util.Collection; | ||
| 10 | +import java.util.List; | ||
| 9 | import java.util.Map; | 11 | import java.util.Map; |
| 10 | 12 | ||
| 11 | /** | 13 | /** |
| @@ -35,18 +37,21 @@ public interface MailLogService { | @@ -35,18 +37,21 @@ public interface MailLogService { | ||
| 35 | /** | 37 | /** |
| 36 | * 创建邮件日志 | 38 | * 创建邮件日志 |
| 37 | * | 39 | * |
| 38 | - * @param userId 用户编码 | ||
| 39 | - * @param userType 用户类型 | ||
| 40 | - * @param toMail 收件人邮件 | ||
| 41 | - * @param account 邮件账号信息 | ||
| 42 | - * @param template 模版信息 | 40 | + * @param userId 用户编码 |
| 41 | + * @param userType 用户类型 | ||
| 42 | + * @param toMails 收件人邮件 | ||
| 43 | + * @param ccMails 收件人邮件 | ||
| 44 | + * @param bccMails 收件人邮件 | ||
| 45 | + * @param account 邮件账号信息 | ||
| 46 | + * @param template 模版信息 | ||
| 43 | * @param templateContent 模版内容 | 47 | * @param templateContent 模版内容 |
| 44 | - * @param templateParams 模版参数 | ||
| 45 | - * @param isSend 是否发送成功 | 48 | + * @param templateParams 模版参数 |
| 49 | + * @param isSend 是否发送成功 | ||
| 46 | * @return 日志编号 | 50 | * @return 日志编号 |
| 47 | */ | 51 | */ |
| 48 | - Long createMailLog(Long userId, Integer userType, String toMail, | ||
| 49 | - MailAccountDO account, MailTemplateDO template , | 52 | + Long createMailLog(Long userId, Integer userType, |
| 53 | + Collection<String> toMails, Collection<String> ccMails, Collection<String> bccMails, | ||
| 54 | + MailAccountDO account, MailTemplateDO template, | ||
| 50 | String templateContent, Map<String, Object> templateParams, Boolean isSend); | 55 | String templateContent, Map<String, Object> templateParams, Boolean isSend); |
| 51 | 56 | ||
| 52 | /** | 57 | /** |
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailLogServiceImpl.java
| 1 | package cn.iocoder.yudao.module.system.service.mail; | 1 | package cn.iocoder.yudao.module.system.service.mail; |
| 2 | 2 | ||
| 3 | +import cn.hutool.core.collection.ListUtil; | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | import cn.iocoder.yudao.module.system.controller.admin.mail.vo.log.MailLogPageReqVO; | 5 | import cn.iocoder.yudao.module.system.controller.admin.mail.vo.log.MailLogPageReqVO; |
| 5 | import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO; | 6 | import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO; |
| @@ -12,8 +13,7 @@ import org.springframework.validation.annotation.Validated; | @@ -12,8 +13,7 @@ import org.springframework.validation.annotation.Validated; | ||
| 12 | 13 | ||
| 13 | import jakarta.annotation.Resource; | 14 | import jakarta.annotation.Resource; |
| 14 | import java.time.LocalDateTime; | 15 | import java.time.LocalDateTime; |
| 15 | -import java.util.Map; | ||
| 16 | -import java.util.Objects; | 16 | +import java.util.*; |
| 17 | 17 | ||
| 18 | import static cn.hutool.core.exceptions.ExceptionUtil.getRootCauseMessage; | 18 | import static cn.hutool.core.exceptions.ExceptionUtil.getRootCauseMessage; |
| 19 | 19 | ||
| @@ -41,7 +41,8 @@ public class MailLogServiceImpl implements MailLogService { | @@ -41,7 +41,8 @@ public class MailLogServiceImpl implements MailLogService { | ||
| 41 | } | 41 | } |
| 42 | 42 | ||
| 43 | @Override | 43 | @Override |
| 44 | - public Long createMailLog(Long userId, Integer userType, String toMail, | 44 | + public Long createMailLog(Long userId, Integer userType, |
| 45 | + Collection<String> toMails, Collection<String> ccMails, Collection<String> bccMails, | ||
| 45 | MailAccountDO account, MailTemplateDO template, | 46 | MailAccountDO account, MailTemplateDO template, |
| 46 | String templateContent, Map<String, Object> templateParams, Boolean isSend) { | 47 | String templateContent, Map<String, Object> templateParams, Boolean isSend) { |
| 47 | MailLogDO.MailLogDOBuilder logDOBuilder = MailLogDO.builder(); | 48 | MailLogDO.MailLogDOBuilder logDOBuilder = MailLogDO.builder(); |
| @@ -49,7 +50,8 @@ public class MailLogServiceImpl implements MailLogService { | @@ -49,7 +50,8 @@ public class MailLogServiceImpl implements MailLogService { | ||
| 49 | logDOBuilder.sendStatus(Objects.equals(isSend, true) ? MailSendStatusEnum.INIT.getStatus() | 50 | logDOBuilder.sendStatus(Objects.equals(isSend, true) ? MailSendStatusEnum.INIT.getStatus() |
| 50 | : MailSendStatusEnum.IGNORE.getStatus()) | 51 | : MailSendStatusEnum.IGNORE.getStatus()) |
| 51 | // 用户信息 | 52 | // 用户信息 |
| 52 | - .userId(userId).userType(userType).toMail(toMail) | 53 | + .userId(userId).userType(userType) |
| 54 | + .toMails(ListUtil.toList(toMails)).ccMails(ListUtil.toList(ccMails)).bccMails(ListUtil.toList(bccMails)) | ||
| 53 | .accountId(account.getId()).fromMail(account.getMail()) | 55 | .accountId(account.getId()).fromMail(account.getMail()) |
| 54 | // 模板相关字段 | 56 | // 模板相关字段 |
| 55 | .templateId(template.getId()).templateCode(template.getCode()).templateNickname(template.getNickname()) | 57 | .templateId(template.getId()).templateCode(template.getCode()).templateNickname(template.getNickname()) |
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailSendService.java
| 1 | package cn.iocoder.yudao.module.system.service.mail; | 1 | package cn.iocoder.yudao.module.system.service.mail; |
| 2 | 2 | ||
| 3 | +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; | ||
| 3 | import cn.iocoder.yudao.module.system.mq.message.mail.MailSendMessage; | 4 | import cn.iocoder.yudao.module.system.mq.message.mail.MailSendMessage; |
| 4 | 5 | ||
| 6 | +import java.util.Collection; | ||
| 5 | import java.util.Map; | 7 | import java.util.Map; |
| 6 | 8 | ||
| 7 | /** | 9 | /** |
| @@ -15,38 +17,53 @@ public interface MailSendService { | @@ -15,38 +17,53 @@ public interface MailSendService { | ||
| 15 | /** | 17 | /** |
| 16 | * 发送单条邮件给管理后台的用户 | 18 | * 发送单条邮件给管理后台的用户 |
| 17 | * | 19 | * |
| 18 | - * @param mail 邮箱 | ||
| 19 | * @param userId 用户编码 | 20 | * @param userId 用户编码 |
| 21 | + * @param toMails 收件邮箱 | ||
| 22 | + * @param ccMails 抄送邮箱 | ||
| 23 | + * @param bccMails 密送邮箱 | ||
| 20 | * @param templateCode 邮件模版编码 | 24 | * @param templateCode 邮件模版编码 |
| 21 | * @param templateParams 邮件模版参数 | 25 | * @param templateParams 邮件模版参数 |
| 22 | * @return 发送日志编号 | 26 | * @return 发送日志编号 |
| 23 | */ | 27 | */ |
| 24 | - Long sendSingleMailToAdmin(String mail, Long userId, | ||
| 25 | - String templateCode, Map<String, Object> templateParams); | 28 | + default Long sendSingleMailToAdmin(Long userId, |
| 29 | + Collection<String> toMails, Collection<String> ccMails, Collection<String> bccMails, | ||
| 30 | + String templateCode, Map<String, Object> templateParams) { | ||
| 31 | + return sendSingleMail(toMails, ccMails, bccMails, userId, UserTypeEnum.ADMIN.getValue(), | ||
| 32 | + templateCode, templateParams); | ||
| 33 | + } | ||
| 26 | 34 | ||
| 27 | /** | 35 | /** |
| 28 | * 发送单条邮件给用户 APP 的用户 | 36 | * 发送单条邮件给用户 APP 的用户 |
| 29 | * | 37 | * |
| 30 | - * @param mail 邮箱 | ||
| 31 | * @param userId 用户编码 | 38 | * @param userId 用户编码 |
| 39 | + * @param toMails 收件邮箱 | ||
| 40 | + * @param ccMails 抄送邮箱 | ||
| 41 | + * @param bccMails 密送邮箱 | ||
| 32 | * @param templateCode 邮件模版编码 | 42 | * @param templateCode 邮件模版编码 |
| 33 | * @param templateParams 邮件模版参数 | 43 | * @param templateParams 邮件模版参数 |
| 34 | * @return 发送日志编号 | 44 | * @return 发送日志编号 |
| 35 | */ | 45 | */ |
| 36 | - Long sendSingleMailToMember(String mail, Long userId, | ||
| 37 | - String templateCode, Map<String, Object> templateParams); | 46 | + default Long sendSingleMailToMember(Long userId, |
| 47 | + Collection<String> toMails, Collection<String> ccMails, Collection<String> bccMails, | ||
| 48 | + String templateCode, Map<String, Object> templateParams) { | ||
| 49 | + return sendSingleMail(toMails, ccMails, bccMails, userId, UserTypeEnum.MEMBER.getValue(), | ||
| 50 | + templateCode, templateParams); | ||
| 51 | + } | ||
| 38 | 52 | ||
| 39 | /** | 53 | /** |
| 40 | - * 发送单条邮件给用户 | 54 | + * 发送单条邮件 |
| 41 | * | 55 | * |
| 42 | - * @param mail 邮箱 | ||
| 43 | - * @param userId 用户编码 | 56 | + * @param toMails 收件邮箱 |
| 57 | + * @param ccMails 抄送邮箱 | ||
| 58 | + * @param bccMails 密送邮箱 | ||
| 59 | + * @param userId 用户编号 | ||
| 44 | * @param userType 用户类型 | 60 | * @param userType 用户类型 |
| 45 | * @param templateCode 邮件模版编码 | 61 | * @param templateCode 邮件模版编码 |
| 46 | * @param templateParams 邮件模版参数 | 62 | * @param templateParams 邮件模版参数 |
| 47 | * @return 发送日志编号 | 63 | * @return 发送日志编号 |
| 48 | */ | 64 | */ |
| 49 | - Long sendSingleMail(String mail, Long userId, Integer userType, | 65 | + Long sendSingleMail(Collection<String> toMails, Collection<String> ccMails, Collection<String> bccMails, |
| 66 | + Long userId, Integer userType, | ||
| 50 | String templateCode, Map<String, Object> templateParams); | 67 | String templateCode, Map<String, Object> templateParams); |
| 51 | 68 | ||
| 52 | /** | 69 | /** |
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailSendServiceImpl.java
| 1 | package cn.iocoder.yudao.module.system.service.mail; | 1 | package cn.iocoder.yudao.module.system.service.mail; |
| 2 | 2 | ||
| 3 | +import cn.hutool.core.collection.CollUtil; | ||
| 4 | +import cn.hutool.core.lang.Validator; | ||
| 3 | import cn.hutool.core.util.StrUtil; | 5 | import cn.hutool.core.util.StrUtil; |
| 4 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | 6 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| 5 | import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; | 7 | import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; |
| @@ -13,10 +15,13 @@ import cn.iocoder.yudao.module.system.service.user.AdminUserService; | @@ -13,10 +15,13 @@ import cn.iocoder.yudao.module.system.service.user.AdminUserService; | ||
| 13 | import com.google.common.annotations.VisibleForTesting; | 15 | import com.google.common.annotations.VisibleForTesting; |
| 14 | import jakarta.annotation.Resource; | 16 | import jakarta.annotation.Resource; |
| 15 | import lombok.extern.slf4j.Slf4j; | 17 | import lombok.extern.slf4j.Slf4j; |
| 16 | -import org.dromara.hutool.extra.mail.*; | 18 | +import org.dromara.hutool.extra.mail.MailAccount; |
| 19 | +import org.dromara.hutool.extra.mail.MailUtil; | ||
| 17 | import org.springframework.stereotype.Service; | 20 | import org.springframework.stereotype.Service; |
| 18 | import org.springframework.validation.annotation.Validated; | 21 | import org.springframework.validation.annotation.Validated; |
| 19 | 22 | ||
| 23 | +import java.util.Collection; | ||
| 24 | +import java.util.LinkedHashSet; | ||
| 20 | import java.util.Map; | 25 | import java.util.Map; |
| 21 | 26 | ||
| 22 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 27 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| @@ -49,56 +54,67 @@ public class MailSendServiceImpl implements MailSendService { | @@ -49,56 +54,67 @@ public class MailSendServiceImpl implements MailSendService { | ||
| 49 | private MailProducer mailProducer; | 54 | private MailProducer mailProducer; |
| 50 | 55 | ||
| 51 | @Override | 56 | @Override |
| 52 | - public Long sendSingleMailToAdmin(String mail, Long userId, | ||
| 53 | - String templateCode, Map<String, Object> templateParams) { | ||
| 54 | - // 如果 mail 为空,则加载用户编号对应的邮箱 | ||
| 55 | - if (StrUtil.isEmpty(mail)) { | ||
| 56 | - AdminUserDO user = adminUserService.getUser(userId); | ||
| 57 | - if (user != null) { | ||
| 58 | - mail = user.getEmail(); | ||
| 59 | - } | ||
| 60 | - } | ||
| 61 | - // 执行发送 | ||
| 62 | - return sendSingleMail(mail, userId, UserTypeEnum.ADMIN.getValue(), templateCode, templateParams); | ||
| 63 | - } | ||
| 64 | - | ||
| 65 | - @Override | ||
| 66 | - public Long sendSingleMailToMember(String mail, Long userId, | ||
| 67 | - String templateCode, Map<String, Object> templateParams) { | ||
| 68 | - // 如果 mail 为空,则加载用户编号对应的邮箱 | ||
| 69 | - if (StrUtil.isEmpty(mail)) { | ||
| 70 | - mail = memberService.getMemberUserEmail(userId); | ||
| 71 | - } | ||
| 72 | - // 执行发送 | ||
| 73 | - return sendSingleMail(mail, userId, UserTypeEnum.MEMBER.getValue(), templateCode, templateParams); | ||
| 74 | - } | ||
| 75 | - | ||
| 76 | - @Override | ||
| 77 | - public Long sendSingleMail(String mail, Long userId, Integer userType, | 57 | + public Long sendSingleMail(Collection<String> toMails, Collection<String> ccMails, Collection<String> bccMails, |
| 58 | + Long userId, Integer userType, | ||
| 78 | String templateCode, Map<String, Object> templateParams) { | 59 | String templateCode, Map<String, Object> templateParams) { |
| 79 | - // 校验邮箱模版是否合法 | 60 | + // 1.1 校验邮箱模版是否合法 |
| 80 | MailTemplateDO template = validateMailTemplate(templateCode); | 61 | MailTemplateDO template = validateMailTemplate(templateCode); |
| 81 | - // 校验邮箱账号是否合法 | 62 | + // 1.2 校验邮箱账号是否合法 |
| 82 | MailAccountDO account = validateMailAccount(template.getAccountId()); | 63 | MailAccountDO account = validateMailAccount(template.getAccountId()); |
| 83 | - | ||
| 84 | - // 校验邮箱是否存在 | ||
| 85 | - mail = validateMail(mail); | 64 | + // 1.3 校验邮件参数是否缺失 |
| 86 | validateTemplateParams(template, templateParams); | 65 | validateTemplateParams(template, templateParams); |
| 87 | 66 | ||
| 67 | + // 2. 组装邮箱 | ||
| 68 | + String userMail = getUserMail(userId, userType); | ||
| 69 | + Collection<String> toMailSet = new LinkedHashSet<>(); | ||
| 70 | + Collection<String> ccMailSet = new LinkedHashSet<>(); | ||
| 71 | + Collection<String> bccMailSet = new LinkedHashSet<>(); | ||
| 72 | + if (Validator.isEmail(userMail)) { | ||
| 73 | + toMailSet.add(userMail); | ||
| 74 | + } | ||
| 75 | + if (CollUtil.isNotEmpty(toMails)) { | ||
| 76 | + toMails.stream().filter(Validator::isEmail).forEach(toMailSet::add); | ||
| 77 | + } | ||
| 78 | + if (CollUtil.isNotEmpty(ccMails)) { | ||
| 79 | + ccMails.stream().filter(Validator::isEmail).forEach(ccMailSet::add); | ||
| 80 | + } | ||
| 81 | + if (CollUtil.isNotEmpty(bccMails)) { | ||
| 82 | + bccMails.stream().filter(Validator::isEmail).forEach(bccMailSet::add); | ||
| 83 | + } | ||
| 84 | + if (CollUtil.isEmpty(toMailSet)) { | ||
| 85 | + throw exception(MAIL_SEND_MAIL_NOT_EXISTS); | ||
| 86 | + } | ||
| 87 | + | ||
| 88 | // 创建发送日志。如果模板被禁用,则不发送短信,只记录日志 | 88 | // 创建发送日志。如果模板被禁用,则不发送短信,只记录日志 |
| 89 | Boolean isSend = CommonStatusEnum.ENABLE.getStatus().equals(template.getStatus()); | 89 | Boolean isSend = CommonStatusEnum.ENABLE.getStatus().equals(template.getStatus()); |
| 90 | String title = mailTemplateService.formatMailTemplateContent(template.getTitle(), templateParams); | 90 | String title = mailTemplateService.formatMailTemplateContent(template.getTitle(), templateParams); |
| 91 | String content = mailTemplateService.formatMailTemplateContent(template.getContent(), templateParams); | 91 | String content = mailTemplateService.formatMailTemplateContent(template.getContent(), templateParams); |
| 92 | - Long sendLogId = mailLogService.createMailLog(userId, userType, mail, | 92 | + Long sendLogId = mailLogService.createMailLog(userId, userType, toMailSet, ccMailSet, bccMailSet, |
| 93 | account, template, content, templateParams, isSend); | 93 | account, template, content, templateParams, isSend); |
| 94 | // 发送 MQ 消息,异步执行发送短信 | 94 | // 发送 MQ 消息,异步执行发送短信 |
| 95 | if (isSend) { | 95 | if (isSend) { |
| 96 | - mailProducer.sendMailSendMessage(sendLogId, mail, account.getId(), | ||
| 97 | - template.getNickname(), title, content); | 96 | + mailProducer.sendMailSendMessage(sendLogId, toMailSet, ccMailSet, bccMailSet, |
| 97 | + account.getId(), template.getNickname(), title, content); | ||
| 98 | } | 98 | } |
| 99 | return sendLogId; | 99 | return sendLogId; |
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | + private String getUserMail(Long userId, Integer userType) { | ||
| 103 | + if (userId == null || userType == null) { | ||
| 104 | + return null; | ||
| 105 | + } | ||
| 106 | + if (UserTypeEnum.ADMIN.getValue().equals(userType)) { | ||
| 107 | + AdminUserDO user = adminUserService.getUser(userId); | ||
| 108 | + if (user != null) { | ||
| 109 | + return user.getEmail(); | ||
| 110 | + } | ||
| 111 | + } | ||
| 112 | + if (UserTypeEnum.MEMBER.getValue().equals(userType)) { | ||
| 113 | + return memberService.getMemberUserEmail(userId); | ||
| 114 | + } | ||
| 115 | + return null; | ||
| 116 | + } | ||
| 117 | + | ||
| 102 | @Override | 118 | @Override |
| 103 | public void doSendMail(MailSendMessage message) { | 119 | public void doSendMail(MailSendMessage message) { |
| 104 | // 1. 创建发送账号 | 120 | // 1. 创建发送账号 |
| @@ -106,7 +122,7 @@ public class MailSendServiceImpl implements MailSendService { | @@ -106,7 +122,7 @@ public class MailSendServiceImpl implements MailSendService { | ||
| 106 | MailAccount mailAccount = buildMailAccount(account, message.getNickname()); | 122 | MailAccount mailAccount = buildMailAccount(account, message.getNickname()); |
| 107 | // 2. 发送邮件 | 123 | // 2. 发送邮件 |
| 108 | try { | 124 | try { |
| 109 | - String messageId = MailUtil.send(mailAccount, message.getMail(), | 125 | + String messageId = MailUtil.send(mailAccount, message.getToMails(), message.getCcMails(), message.getBccMails(), |
| 110 | message.getTitle(), message.getContent(), true); | 126 | message.getTitle(), message.getContent(), true); |
| 111 | // 3. 更新结果(成功) | 127 | // 3. 更新结果(成功) |
| 112 | mailLogService.updateMailSendResult(message.getLogId(), messageId, null); | 128 | mailLogService.updateMailSendResult(message.getLogId(), messageId, null); |
| @@ -146,16 +162,8 @@ public class MailSendServiceImpl implements MailSendService { | @@ -146,16 +162,8 @@ public class MailSendServiceImpl implements MailSendService { | ||
| 146 | return account; | 162 | return account; |
| 147 | } | 163 | } |
| 148 | 164 | ||
| 149 | - @VisibleForTesting | ||
| 150 | - String validateMail(String mail) { | ||
| 151 | - if (StrUtil.isEmpty(mail)) { | ||
| 152 | - throw exception(MAIL_SEND_MAIL_NOT_EXISTS); | ||
| 153 | - } | ||
| 154 | - return mail; | ||
| 155 | - } | ||
| 156 | - | ||
| 157 | /** | 165 | /** |
| 158 | - * 校验邮件参数是否确实 | 166 | + * 校验邮件参数是否缺失 |
| 159 | * | 167 | * |
| 160 | * @param template 邮箱模板 | 168 | * @param template 邮箱模板 |
| 161 | * @param templateParams 参数列表 | 169 | * @param templateParams 参数列表 |
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/permission/MenuServiceImpl.java
| @@ -255,9 +255,6 @@ public class MenuServiceImpl implements MenuService { | @@ -255,9 +255,6 @@ public class MenuServiceImpl implements MenuService { | ||
| 255 | return; | 255 | return; |
| 256 | } | 256 | } |
| 257 | // 如果 id 为空,说明不用比较是否为相同 id 的菜单 | 257 | // 如果 id 为空,说明不用比较是否为相同 id 的菜单 |
| 258 | - if (id == null) { | ||
| 259 | - throw exception(MENU_NAME_DUPLICATE); | ||
| 260 | - } | ||
| 261 | if (!menu.getId().equals(id)) { | 258 | if (!menu.getId().equals(id)) { |
| 262 | throw exception(MENU_NAME_DUPLICATE); | 259 | throw exception(MENU_NAME_DUPLICATE); |
| 263 | } | 260 | } |
yudao-module-system/src/main/resources/META-INF/services/com.anji.captcha.service.CaptchaService
0 → 100644
yudao-module-system/src/test/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImplTest.java
| @@ -26,8 +26,8 @@ import jakarta.validation.Validation; | @@ -26,8 +26,8 @@ import jakarta.validation.Validation; | ||
| 26 | import jakarta.validation.Validator; | 26 | import jakarta.validation.Validator; |
| 27 | import org.junit.jupiter.api.BeforeEach; | 27 | import org.junit.jupiter.api.BeforeEach; |
| 28 | import org.junit.jupiter.api.Test; | 28 | import org.junit.jupiter.api.Test; |
| 29 | -import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 30 | import org.springframework.context.annotation.Import; | 29 | import org.springframework.context.annotation.Import; |
| 30 | +import org.springframework.test.context.bean.override.mockito.MockitoBean; | ||
| 31 | 31 | ||
| 32 | import static cn.hutool.core.util.RandomUtil.randomEle; | 32 | import static cn.hutool.core.util.RandomUtil.randomEle; |
| 33 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; | 33 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; |
| @@ -45,21 +45,21 @@ public class AdminAuthServiceImplTest extends BaseDbUnitTest { | @@ -45,21 +45,21 @@ public class AdminAuthServiceImplTest extends BaseDbUnitTest { | ||
| 45 | @Resource | 45 | @Resource |
| 46 | private AdminAuthServiceImpl authService; | 46 | private AdminAuthServiceImpl authService; |
| 47 | 47 | ||
| 48 | - @MockBean | 48 | + @MockitoBean |
| 49 | private AdminUserService userService; | 49 | private AdminUserService userService; |
| 50 | - @MockBean | 50 | + @MockitoBean |
| 51 | private CaptchaService captchaService; | 51 | private CaptchaService captchaService; |
| 52 | - @MockBean | 52 | + @MockitoBean |
| 53 | private LoginLogService loginLogService; | 53 | private LoginLogService loginLogService; |
| 54 | - @MockBean | 54 | + @MockitoBean |
| 55 | private SocialUserService socialUserService; | 55 | private SocialUserService socialUserService; |
| 56 | - @MockBean | 56 | + @MockitoBean |
| 57 | private SmsCodeApi smsCodeApi; | 57 | private SmsCodeApi smsCodeApi; |
| 58 | - @MockBean | 58 | + @MockitoBean |
| 59 | private OAuth2TokenService oauth2TokenService; | 59 | private OAuth2TokenService oauth2TokenService; |
| 60 | - @MockBean | 60 | + @MockitoBean |
| 61 | private MemberService memberService; | 61 | private MemberService memberService; |
| 62 | - @MockBean | 62 | + @MockitoBean |
| 63 | private Validator validator; | 63 | private Validator validator; |
| 64 | 64 | ||
| 65 | @BeforeEach | 65 | @BeforeEach |
yudao-module-system/src/test/java/cn/iocoder/yudao/module/system/service/dept/DeptServiceImplTest.java
| @@ -105,12 +105,40 @@ public class DeptServiceImplTest extends BaseDbUnitTest { | @@ -105,12 +105,40 @@ public class DeptServiceImplTest extends BaseDbUnitTest { | ||
| 105 | } | 105 | } |
| 106 | 106 | ||
| 107 | @Test | 107 | @Test |
| 108 | - public void testValidateDeptExists_notFound() { | 108 | + public void testDeleteDeptList_success() { |
| 109 | + // mock 数据 | ||
| 110 | + DeptDO deptDO1 = randomPojo(DeptDO.class); | ||
| 111 | + deptMapper.insert(deptDO1); | ||
| 112 | + DeptDO deptDO2 = randomPojo(DeptDO.class); | ||
| 113 | + deptMapper.insert(deptDO2); | ||
| 109 | // 准备参数 | 114 | // 准备参数 |
| 110 | - Long id = randomLongId(); | 115 | + List<Long> ids = Arrays.asList(deptDO1.getId(), deptDO2.getId()); |
| 116 | + | ||
| 117 | + // 调用 | ||
| 118 | + deptService.deleteDeptList(ids); | ||
| 119 | + // 校验数据不存在了 | ||
| 120 | + assertNull(deptMapper.selectById(deptDO1.getId())); | ||
| 121 | + assertNull(deptMapper.selectById(deptDO2.getId())); | ||
| 122 | + } | ||
| 123 | + | ||
| 124 | + @Test | ||
| 125 | + public void testDeleteDeptList_exitsChildren() { | ||
| 126 | + // mock 数据 | ||
| 127 | + DeptDO parentDept = randomPojo(DeptDO.class); | ||
| 128 | + deptMapper.insert(parentDept); | ||
| 129 | + DeptDO childrenDeptDO = randomPojo(DeptDO.class, o -> { | ||
| 130 | + o.setParentId(parentDept.getId()); | ||
| 131 | + o.setStatus(randomCommonStatus()); | ||
| 132 | + }); | ||
| 133 | + deptMapper.insert(childrenDeptDO); | ||
| 134 | + DeptDO anotherDept = randomPojo(DeptDO.class); | ||
| 135 | + deptMapper.insert(anotherDept); | ||
| 136 | + | ||
| 137 | + // 准备参数(包含有子部门的 parentDept) | ||
| 138 | + List<Long> ids = Arrays.asList(parentDept.getId(), anotherDept.getId()); | ||
| 111 | 139 | ||
| 112 | // 调用, 并断言异常 | 140 | // 调用, 并断言异常 |
| 113 | - assertServiceException(() -> deptService.validateDeptExists(id), DEPT_NOT_FOUND); | 141 | + assertServiceException(() -> deptService.deleteDeptList(ids), DEPT_EXITS_CHILDREN); |
| 114 | } | 142 | } |
| 115 | 143 | ||
| 116 | @Test | 144 | @Test |
yudao-module-system/src/test/java/cn/iocoder/yudao/module/system/service/dict/DictDataServiceImplTest.java
| @@ -9,11 +9,11 @@ import cn.iocoder.yudao.module.system.controller.admin.dict.vo.data.DictDataSave | @@ -9,11 +9,11 @@ import cn.iocoder.yudao.module.system.controller.admin.dict.vo.data.DictDataSave | ||
| 9 | import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictDataDO; | 9 | import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictDataDO; |
| 10 | import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictTypeDO; | 10 | import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictTypeDO; |
| 11 | import cn.iocoder.yudao.module.system.dal.mysql.dict.DictDataMapper; | 11 | import cn.iocoder.yudao.module.system.dal.mysql.dict.DictDataMapper; |
| 12 | +import jakarta.annotation.Resource; | ||
| 12 | import org.junit.jupiter.api.Test; | 13 | import org.junit.jupiter.api.Test; |
| 13 | -import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 14 | import org.springframework.context.annotation.Import; | 14 | import org.springframework.context.annotation.Import; |
| 15 | +import org.springframework.test.context.bean.override.mockito.MockitoBean; | ||
| 15 | 16 | ||
| 16 | -import jakarta.annotation.Resource; | ||
| 17 | import java.util.List; | 17 | import java.util.List; |
| 18 | import java.util.function.Consumer; | 18 | import java.util.function.Consumer; |
| 19 | 19 | ||
| @@ -35,7 +35,7 @@ public class DictDataServiceImplTest extends BaseDbUnitTest { | @@ -35,7 +35,7 @@ public class DictDataServiceImplTest extends BaseDbUnitTest { | ||
| 35 | 35 | ||
| 36 | @Resource | 36 | @Resource |
| 37 | private DictDataMapper dictDataMapper; | 37 | private DictDataMapper dictDataMapper; |
| 38 | - @MockBean | 38 | + @MockitoBean |
| 39 | private DictTypeService dictTypeService; | 39 | private DictTypeService dictTypeService; |
| 40 | 40 | ||
| 41 | @Test | 41 | @Test |
yudao-module-system/src/test/java/cn/iocoder/yudao/module/system/service/dict/DictTypeServiceImplTest.java
| @@ -8,11 +8,11 @@ import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.DictTypePage | @@ -8,11 +8,11 @@ import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.DictTypePage | ||
| 8 | import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.DictTypeSaveReqVO; | 8 | import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.DictTypeSaveReqVO; |
| 9 | import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictTypeDO; | 9 | import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictTypeDO; |
| 10 | import cn.iocoder.yudao.module.system.dal.mysql.dict.DictTypeMapper; | 10 | import cn.iocoder.yudao.module.system.dal.mysql.dict.DictTypeMapper; |
| 11 | +import jakarta.annotation.Resource; | ||
| 11 | import org.junit.jupiter.api.Test; | 12 | import org.junit.jupiter.api.Test; |
| 12 | -import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 13 | import org.springframework.context.annotation.Import; | 13 | import org.springframework.context.annotation.Import; |
| 14 | +import org.springframework.test.context.bean.override.mockito.MockitoBean; | ||
| 14 | 15 | ||
| 15 | -import jakarta.annotation.Resource; | ||
| 16 | import java.util.List; | 16 | import java.util.List; |
| 17 | import java.util.function.Consumer; | 17 | import java.util.function.Consumer; |
| 18 | 18 | ||
| @@ -36,7 +36,7 @@ public class DictTypeServiceImplTest extends BaseDbUnitTest { | @@ -36,7 +36,7 @@ public class DictTypeServiceImplTest extends BaseDbUnitTest { | ||
| 36 | 36 | ||
| 37 | @Resource | 37 | @Resource |
| 38 | private DictTypeMapper dictTypeMapper; | 38 | private DictTypeMapper dictTypeMapper; |
| 39 | - @MockBean | 39 | + @MockitoBean |
| 40 | private DictDataService dictDataService; | 40 | private DictDataService dictDataService; |
| 41 | 41 | ||
| 42 | @Test | 42 | @Test |
yudao-module-system/src/test/java/cn/iocoder/yudao/module/system/service/mail/MailAccountServiceImplTest.java
| @@ -6,11 +6,11 @@ import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.MailAccou | @@ -6,11 +6,11 @@ import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.MailAccou | ||
| 6 | import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.MailAccountSaveReqVO; | 6 | import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.MailAccountSaveReqVO; |
| 7 | import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO; | 7 | import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO; |
| 8 | import cn.iocoder.yudao.module.system.dal.mysql.mail.MailAccountMapper; | 8 | import cn.iocoder.yudao.module.system.dal.mysql.mail.MailAccountMapper; |
| 9 | +import jakarta.annotation.Resource; | ||
| 9 | import org.junit.jupiter.api.Test; | 10 | import org.junit.jupiter.api.Test; |
| 10 | -import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 11 | import org.springframework.context.annotation.Import; | 11 | import org.springframework.context.annotation.Import; |
| 12 | +import org.springframework.test.context.bean.override.mockito.MockitoBean; | ||
| 12 | 13 | ||
| 13 | -import jakarta.annotation.Resource; | ||
| 14 | import java.util.List; | 14 | import java.util.List; |
| 15 | 15 | ||
| 16 | import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; | 16 | import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; |
| @@ -36,7 +36,7 @@ public class MailAccountServiceImplTest extends BaseDbUnitTest { | @@ -36,7 +36,7 @@ public class MailAccountServiceImplTest extends BaseDbUnitTest { | ||
| 36 | @Resource | 36 | @Resource |
| 37 | private MailAccountMapper mailAccountMapper; | 37 | private MailAccountMapper mailAccountMapper; |
| 38 | 38 | ||
| 39 | - @MockBean | 39 | + @MockitoBean |
| 40 | private MailTemplateService mailTemplateService; | 40 | private MailTemplateService mailTemplateService; |
| 41 | 41 | ||
| 42 | @Test | 42 | @Test |
yudao-module-system/src/test/java/cn/iocoder/yudao/module/system/service/mail/MailLogServiceImplTest.java
| @@ -10,10 +10,12 @@ import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailLogDO; | @@ -10,10 +10,12 @@ import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailLogDO; | ||
| 10 | import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO; | 10 | import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO; |
| 11 | import cn.iocoder.yudao.module.system.dal.mysql.mail.MailLogMapper; | 11 | import cn.iocoder.yudao.module.system.dal.mysql.mail.MailLogMapper; |
| 12 | import cn.iocoder.yudao.module.system.enums.mail.MailSendStatusEnum; | 12 | import cn.iocoder.yudao.module.system.enums.mail.MailSendStatusEnum; |
| 13 | +import org.assertj.core.util.Lists; | ||
| 13 | import org.junit.jupiter.api.Test; | 14 | import org.junit.jupiter.api.Test; |
| 14 | import org.springframework.context.annotation.Import; | 15 | import org.springframework.context.annotation.Import; |
| 15 | 16 | ||
| 16 | import jakarta.annotation.Resource; | 17 | import jakarta.annotation.Resource; |
| 18 | +import java.util.Collection; | ||
| 17 | import java.util.Map; | 19 | import java.util.Map; |
| 18 | 20 | ||
| 19 | import static cn.hutool.core.util.RandomUtil.randomEle; | 21 | import static cn.hutool.core.util.RandomUtil.randomEle; |
| @@ -43,7 +45,9 @@ public class MailLogServiceImplTest extends BaseDbUnitTest { | @@ -43,7 +45,9 @@ public class MailLogServiceImplTest extends BaseDbUnitTest { | ||
| 43 | // 准备参数 | 45 | // 准备参数 |
| 44 | Long userId = randomLongId(); | 46 | Long userId = randomLongId(); |
| 45 | Integer userType = randomEle(UserTypeEnum.values()).getValue(); | 47 | Integer userType = randomEle(UserTypeEnum.values()).getValue(); |
| 46 | - String toMail = randomEmail(); | 48 | + Collection<String> toMails = Lists.newArrayList(randomEmail(), randomEmail()); |
| 49 | + Collection<String> ccMails = Lists.newArrayList(randomEmail()); | ||
| 50 | + Collection<String> bccMails = Lists.newArrayList(randomEmail()); | ||
| 47 | MailAccountDO account = randomPojo(MailAccountDO.class); | 51 | MailAccountDO account = randomPojo(MailAccountDO.class); |
| 48 | MailTemplateDO template = randomPojo(MailTemplateDO.class); | 52 | MailTemplateDO template = randomPojo(MailTemplateDO.class); |
| 49 | String templateContent = randomString(); | 53 | String templateContent = randomString(); |
| @@ -52,14 +56,20 @@ public class MailLogServiceImplTest extends BaseDbUnitTest { | @@ -52,14 +56,20 @@ public class MailLogServiceImplTest extends BaseDbUnitTest { | ||
| 52 | // mock 方法 | 56 | // mock 方法 |
| 53 | 57 | ||
| 54 | // 调用 | 58 | // 调用 |
| 55 | - Long logId = mailLogService.createMailLog(userId, userType, toMail, account, template, templateContent, templateParams, isSend); | 59 | + Long logId = mailLogService.createMailLog(userId, userType, toMails, ccMails, bccMails, |
| 60 | + account, template, templateContent, templateParams, isSend); | ||
| 56 | // 断言 | 61 | // 断言 |
| 57 | MailLogDO log = mailLogMapper.selectById(logId); | 62 | MailLogDO log = mailLogMapper.selectById(logId); |
| 58 | assertNotNull(log); | 63 | assertNotNull(log); |
| 59 | assertEquals(MailSendStatusEnum.INIT.getStatus(), log.getSendStatus()); | 64 | assertEquals(MailSendStatusEnum.INIT.getStatus(), log.getSendStatus()); |
| 60 | assertEquals(userId, log.getUserId()); | 65 | assertEquals(userId, log.getUserId()); |
| 61 | assertEquals(userType, log.getUserType()); | 66 | assertEquals(userType, log.getUserType()); |
| 62 | - assertEquals(toMail, log.getToMail()); | 67 | + assertEquals(toMails.size(), log.getToMails().size()); |
| 68 | + assertTrue(log.getToMails().containsAll(toMails)); | ||
| 69 | + assertEquals(ccMails.size(), log.getCcMails().size()); | ||
| 70 | + assertTrue(log.getCcMails().containsAll(ccMails)); | ||
| 71 | + assertEquals(bccMails.size(), log.getBccMails().size()); | ||
| 72 | + assertTrue(log.getBccMails().containsAll(bccMails)); | ||
| 63 | assertEquals(account.getId(), log.getAccountId()); | 73 | assertEquals(account.getId(), log.getAccountId()); |
| 64 | assertEquals(account.getMail(), log.getFromMail()); | 74 | assertEquals(account.getMail(), log.getFromMail()); |
| 65 | assertEquals(template.getId(), log.getTemplateId()); | 75 | assertEquals(template.getId(), log.getTemplateId()); |
| @@ -136,7 +146,9 @@ public class MailLogServiceImplTest extends BaseDbUnitTest { | @@ -136,7 +146,9 @@ public class MailLogServiceImplTest extends BaseDbUnitTest { | ||
| 136 | MailLogDO dbMailLog = randomPojo(MailLogDO.class, o -> { // 等会查询到 | 146 | MailLogDO dbMailLog = randomPojo(MailLogDO.class, o -> { // 等会查询到 |
| 137 | o.setUserId(1L); | 147 | o.setUserId(1L); |
| 138 | o.setUserType(UserTypeEnum.ADMIN.getValue()); | 148 | o.setUserType(UserTypeEnum.ADMIN.getValue()); |
| 139 | - o.setToMail("768@qq.com"); | 149 | + o.setToMails(Lists.newArrayList("768@qq.com")); |
| 150 | + o.setCcMails(Lists.newArrayList()); | ||
| 151 | + o.setBccMails(Lists.newArrayList()); | ||
| 140 | o.setAccountId(10L); | 152 | o.setAccountId(10L); |
| 141 | o.setTemplateId(100L); | 153 | o.setTemplateId(100L); |
| 142 | o.setSendStatus(MailSendStatusEnum.INIT.getStatus()); | 154 | o.setSendStatus(MailSendStatusEnum.INIT.getStatus()); |
| @@ -148,8 +160,8 @@ public class MailLogServiceImplTest extends BaseDbUnitTest { | @@ -148,8 +160,8 @@ public class MailLogServiceImplTest extends BaseDbUnitTest { | ||
| 148 | mailLogMapper.insert(cloneIgnoreId(dbMailLog, o -> o.setUserId(2L))); | 160 | mailLogMapper.insert(cloneIgnoreId(dbMailLog, o -> o.setUserId(2L))); |
| 149 | // 测试 userType 不匹配 | 161 | // 测试 userType 不匹配 |
| 150 | mailLogMapper.insert(cloneIgnoreId(dbMailLog, o -> o.setUserType(UserTypeEnum.MEMBER.getValue()))); | 162 | mailLogMapper.insert(cloneIgnoreId(dbMailLog, o -> o.setUserType(UserTypeEnum.MEMBER.getValue()))); |
| 151 | - // 测试 toMail 不匹配 | ||
| 152 | - mailLogMapper.insert(cloneIgnoreId(dbMailLog, o -> o.setToMail("788@.qq.com"))); | 163 | + // 测试 toMails 不匹配(特殊:find_in_set 无法单测) |
| 164 | +// mailLogMapper.insert(cloneIgnoreId(dbMailLog, o -> o.setToMails(Lists.newArrayList("788@qq.com")))); | ||
| 153 | // 测试 accountId 不匹配 | 165 | // 测试 accountId 不匹配 |
| 154 | mailLogMapper.insert(cloneIgnoreId(dbMailLog, o -> o.setAccountId(11L))); | 166 | mailLogMapper.insert(cloneIgnoreId(dbMailLog, o -> o.setAccountId(11L))); |
| 155 | // 测试 templateId 不匹配 | 167 | // 测试 templateId 不匹配 |
| @@ -162,7 +174,7 @@ public class MailLogServiceImplTest extends BaseDbUnitTest { | @@ -162,7 +174,7 @@ public class MailLogServiceImplTest extends BaseDbUnitTest { | ||
| 162 | MailLogPageReqVO reqVO = new MailLogPageReqVO(); | 174 | MailLogPageReqVO reqVO = new MailLogPageReqVO(); |
| 163 | reqVO.setUserId(1L); | 175 | reqVO.setUserId(1L); |
| 164 | reqVO.setUserType(UserTypeEnum.ADMIN.getValue()); | 176 | reqVO.setUserType(UserTypeEnum.ADMIN.getValue()); |
| 165 | - reqVO.setToMail("768"); | 177 | +// reqVO.setToMail("768@qq.com"); |
| 166 | reqVO.setAccountId(10L); | 178 | reqVO.setAccountId(10L); |
| 167 | reqVO.setTemplateId(100L); | 179 | reqVO.setTemplateId(100L); |
| 168 | reqVO.setSendStatus(MailSendStatusEnum.INIT.getStatus()); | 180 | reqVO.setSendStatus(MailSendStatusEnum.INIT.getStatus()); |
yudao-module-system/src/test/java/cn/iocoder/yudao/module/system/service/mail/MailSendServiceImplTest.java
| @@ -20,6 +20,7 @@ import org.mockito.InjectMocks; | @@ -20,6 +20,7 @@ import org.mockito.InjectMocks; | ||
| 20 | import org.mockito.Mock; | 20 | import org.mockito.Mock; |
| 21 | import org.mockito.MockedStatic; | 21 | import org.mockito.MockedStatic; |
| 22 | 22 | ||
| 23 | +import java.util.Collection; | ||
| 23 | import java.util.HashMap; | 24 | import java.util.HashMap; |
| 24 | import java.util.Map; | 25 | import java.util.Map; |
| 25 | 26 | ||
| @@ -65,14 +66,18 @@ public class MailSendServiceImplTest extends BaseMockitoUnitTest { | @@ -65,14 +66,18 @@ public class MailSendServiceImplTest extends BaseMockitoUnitTest { | ||
| 65 | } | 66 | } |
| 66 | 67 | ||
| 67 | @Test | 68 | @Test |
| 68 | - public void testSendSingleMailToAdmin() { | 69 | + public void testSendSingleMail_success() { |
| 69 | // 准备参数 | 70 | // 准备参数 |
| 70 | Long userId = randomLongId(); | 71 | Long userId = randomLongId(); |
| 71 | String templateCode = RandomUtils.randomString(); | 72 | String templateCode = RandomUtils.randomString(); |
| 72 | Map<String, Object> templateParams = MapUtil.<String, Object>builder().put("code", "1234") | 73 | Map<String, Object> templateParams = MapUtil.<String, Object>builder().put("code", "1234") |
| 73 | .put("op", "login").build(); | 74 | .put("op", "login").build(); |
| 75 | + Collection<String> toMails = Lists.newArrayList("admin@test.com"); | ||
| 76 | + Collection<String> ccMails = Lists.newArrayList("cc@test.com"); | ||
| 77 | + Collection<String> bccMails = Lists.newArrayList("bcc@test.com"); | ||
| 78 | + | ||
| 74 | // mock adminUserService 的方法 | 79 | // mock adminUserService 的方法 |
| 75 | - AdminUserDO user = randomPojo(AdminUserDO.class, o -> o.setMobile("15601691300")); | 80 | + AdminUserDO user = randomPojo(AdminUserDO.class, o -> o.setEmail("admin@example.com")); |
| 76 | when(adminUserService.getUser(eq(userId))).thenReturn(user); | 81 | when(adminUserService.getUser(eq(userId))).thenReturn(user); |
| 77 | 82 | ||
| 78 | // mock MailTemplateService 的方法 | 83 | // mock MailTemplateService 的方法 |
| @@ -93,61 +98,27 @@ public class MailSendServiceImplTest extends BaseMockitoUnitTest { | @@ -93,61 +98,27 @@ public class MailSendServiceImplTest extends BaseMockitoUnitTest { | ||
| 93 | when(mailAccountService.getMailAccountFromCache(eq(template.getAccountId()))).thenReturn(account); | 98 | when(mailAccountService.getMailAccountFromCache(eq(template.getAccountId()))).thenReturn(account); |
| 94 | // mock MailLogService 的方法 | 99 | // mock MailLogService 的方法 |
| 95 | Long mailLogId = randomLongId(); | 100 | Long mailLogId = randomLongId(); |
| 96 | - when(mailLogService.createMailLog(eq(userId), eq(UserTypeEnum.ADMIN.getValue()), eq(user.getEmail()), | 101 | + when(mailLogService.createMailLog(eq(userId), eq(UserTypeEnum.ADMIN.getValue()), |
| 102 | + argThat(toMailSet -> toMailSet.contains(user.getEmail()) && toMailSet.contains("admin@test.com")), | ||
| 103 | + argThat(ccMailSet -> ccMailSet.contains("cc@test.com")), | ||
| 104 | + argThat(bccMailSet -> bccMailSet.contains("bcc@test.com")), | ||
| 97 | eq(account), eq(template), eq(content), eq(templateParams), eq(true))).thenReturn(mailLogId); | 105 | eq(account), eq(template), eq(content), eq(templateParams), eq(true))).thenReturn(mailLogId); |
| 98 | 106 | ||
| 99 | // 调用 | 107 | // 调用 |
| 100 | - Long resultMailLogId = mailSendService.sendSingleMailToAdmin(null, userId, templateCode, templateParams); | 108 | + Long resultMailLogId = mailSendService.sendSingleMail(toMails, ccMails, bccMails, userId, |
| 109 | + UserTypeEnum.ADMIN.getValue(), templateCode, templateParams); | ||
| 101 | // 断言 | 110 | // 断言 |
| 102 | assertEquals(mailLogId, resultMailLogId); | 111 | assertEquals(mailLogId, resultMailLogId); |
| 103 | // 断言调用 | 112 | // 断言调用 |
| 104 | - verify(mailProducer).sendMailSendMessage(eq(mailLogId), eq(user.getEmail()), | ||
| 105 | - eq(account.getId()), eq(template.getNickname()), eq(title), eq(content)); | ||
| 106 | - } | ||
| 107 | - | ||
| 108 | - @Test | ||
| 109 | - public void testSendSingleMailToMember() { | ||
| 110 | - // 准备参数 | ||
| 111 | - Long userId = randomLongId(); | ||
| 112 | - String templateCode = RandomUtils.randomString(); | ||
| 113 | - Map<String, Object> templateParams = MapUtil.<String, Object>builder().put("code", "1234") | ||
| 114 | - .put("op", "login").build(); | ||
| 115 | - // mock memberService 的方法 | ||
| 116 | - String mail = randomEmail(); | ||
| 117 | - when(memberService.getMemberUserEmail(eq(userId))).thenReturn(mail); | ||
| 118 | - | ||
| 119 | - // mock MailTemplateService 的方法 | ||
| 120 | - MailTemplateDO template = randomPojo(MailTemplateDO.class, o -> { | ||
| 121 | - o.setStatus(CommonStatusEnum.ENABLE.getStatus()); | ||
| 122 | - o.setContent("验证码为{code}, 操作为{op}"); | ||
| 123 | - o.setParams(Lists.newArrayList("code", "op")); | ||
| 124 | - }); | ||
| 125 | - when(mailTemplateService.getMailTemplateByCodeFromCache(eq(templateCode))).thenReturn(template); | ||
| 126 | - String title = RandomUtils.randomString(); | ||
| 127 | - when(mailTemplateService.formatMailTemplateContent(eq(template.getTitle()), eq(templateParams))) | ||
| 128 | - .thenReturn(title); | ||
| 129 | - String content = RandomUtils.randomString(); | ||
| 130 | - when(mailTemplateService.formatMailTemplateContent(eq(template.getContent()), eq(templateParams))) | ||
| 131 | - .thenReturn(content); | ||
| 132 | - // mock MailAccountService 的方法 | ||
| 133 | - MailAccountDO account = randomPojo(MailAccountDO.class); | ||
| 134 | - when(mailAccountService.getMailAccountFromCache(eq(template.getAccountId()))).thenReturn(account); | ||
| 135 | - // mock MailLogService 的方法 | ||
| 136 | - Long mailLogId = randomLongId(); | ||
| 137 | - when(mailLogService.createMailLog(eq(userId), eq(UserTypeEnum.MEMBER.getValue()), eq(mail), | ||
| 138 | - eq(account), eq(template), eq(content), eq(templateParams), eq(true))).thenReturn(mailLogId); | ||
| 139 | - | ||
| 140 | - // 调用 | ||
| 141 | - Long resultMailLogId = mailSendService.sendSingleMailToMember(null, userId, templateCode, templateParams); | ||
| 142 | - // 断言 | ||
| 143 | - assertEquals(mailLogId, resultMailLogId); | ||
| 144 | - // 断言调用 | ||
| 145 | - verify(mailProducer).sendMailSendMessage(eq(mailLogId), eq(mail), | 113 | + verify(mailProducer).sendMailSendMessage(eq(mailLogId), |
| 114 | + argThat(toMailSet -> toMailSet.contains(user.getEmail()) && toMailSet.contains("admin@test.com")), | ||
| 115 | + argThat(ccMailSet -> ccMailSet.contains("cc@test.com")), | ||
| 116 | + argThat(bccMailSet -> bccMailSet.contains("bcc@test.com")), | ||
| 146 | eq(account.getId()), eq(template.getNickname()), eq(title), eq(content)); | 117 | eq(account.getId()), eq(template.getNickname()), eq(title), eq(content)); |
| 147 | } | 118 | } |
| 148 | 119 | ||
| 149 | /** | 120 | /** |
| 150 | - * 发送成功,当短信模板开启时 | 121 | + * 发送成功,当邮件模板开启时 |
| 151 | */ | 122 | */ |
| 152 | @Test | 123 | @Test |
| 153 | public void testSendSingleMail_successWhenMailTemplateEnable() { | 124 | public void testSendSingleMail_successWhenMailTemplateEnable() { |
| @@ -158,6 +129,8 @@ public class MailSendServiceImplTest extends BaseMockitoUnitTest { | @@ -158,6 +129,8 @@ public class MailSendServiceImplTest extends BaseMockitoUnitTest { | ||
| 158 | String templateCode = RandomUtils.randomString(); | 129 | String templateCode = RandomUtils.randomString(); |
| 159 | Map<String, Object> templateParams = MapUtil.<String, Object>builder().put("code", "1234") | 130 | Map<String, Object> templateParams = MapUtil.<String, Object>builder().put("code", "1234") |
| 160 | .put("op", "login").build(); | 131 | .put("op", "login").build(); |
| 132 | + Collection<String> toMails = Lists.newArrayList(mail); | ||
| 133 | + | ||
| 161 | // mock MailTemplateService 的方法 | 134 | // mock MailTemplateService 的方法 |
| 162 | MailTemplateDO template = randomPojo(MailTemplateDO.class, o -> { | 135 | MailTemplateDO template = randomPojo(MailTemplateDO.class, o -> { |
| 163 | o.setStatus(CommonStatusEnum.ENABLE.getStatus()); | 136 | o.setStatus(CommonStatusEnum.ENABLE.getStatus()); |
| @@ -176,23 +149,29 @@ public class MailSendServiceImplTest extends BaseMockitoUnitTest { | @@ -176,23 +149,29 @@ public class MailSendServiceImplTest extends BaseMockitoUnitTest { | ||
| 176 | when(mailAccountService.getMailAccountFromCache(eq(template.getAccountId()))).thenReturn(account); | 149 | when(mailAccountService.getMailAccountFromCache(eq(template.getAccountId()))).thenReturn(account); |
| 177 | // mock MailLogService 的方法 | 150 | // mock MailLogService 的方法 |
| 178 | Long mailLogId = randomLongId(); | 151 | Long mailLogId = randomLongId(); |
| 179 | - when(mailLogService.createMailLog(eq(userId), eq(userType), eq(mail), | 152 | + when(mailLogService.createMailLog(eq(userId), eq(userType), |
| 153 | + argThat(toMailSet -> toMailSet.contains(mail)), | ||
| 154 | + argThat(Collection::isEmpty), | ||
| 155 | + argThat(Collection::isEmpty), | ||
| 180 | eq(account), eq(template), eq(content), eq(templateParams), eq(true))).thenReturn(mailLogId); | 156 | eq(account), eq(template), eq(content), eq(templateParams), eq(true))).thenReturn(mailLogId); |
| 181 | 157 | ||
| 182 | // 调用 | 158 | // 调用 |
| 183 | - Long resultMailLogId = mailSendService.sendSingleMail(mail, userId, userType, templateCode, templateParams); | 159 | + Long resultMailLogId = mailSendService.sendSingleMail(toMails, null, null, userId, userType, templateCode, templateParams); |
| 184 | // 断言 | 160 | // 断言 |
| 185 | assertEquals(mailLogId, resultMailLogId); | 161 | assertEquals(mailLogId, resultMailLogId); |
| 186 | // 断言调用 | 162 | // 断言调用 |
| 187 | - verify(mailProducer).sendMailSendMessage(eq(mailLogId), eq(mail), | 163 | + verify(mailProducer).sendMailSendMessage(eq(mailLogId), |
| 164 | + argThat(toMailSet -> toMailSet.contains(mail)), | ||
| 165 | + argThat(Collection::isEmpty), | ||
| 166 | + argThat(Collection::isEmpty), | ||
| 188 | eq(account.getId()), eq(template.getNickname()), eq(title), eq(content)); | 167 | eq(account.getId()), eq(template.getNickname()), eq(title), eq(content)); |
| 189 | } | 168 | } |
| 190 | 169 | ||
| 191 | /** | 170 | /** |
| 192 | - * 发送成功,当短信模板关闭时 | 171 | + * 发送成功,当邮件模板关闭时 |
| 193 | */ | 172 | */ |
| 194 | @Test | 173 | @Test |
| 195 | - public void testSendSingleMail_successWhenSmsTemplateDisable() { | 174 | + public void testSendSingleMail_successWhenMailTemplateDisable() { |
| 196 | // 准备参数 | 175 | // 准备参数 |
| 197 | String mail = randomEmail(); | 176 | String mail = randomEmail(); |
| 198 | Long userId = randomLongId(); | 177 | Long userId = randomLongId(); |
| @@ -200,6 +179,8 @@ public class MailSendServiceImplTest extends BaseMockitoUnitTest { | @@ -200,6 +179,8 @@ public class MailSendServiceImplTest extends BaseMockitoUnitTest { | ||
| 200 | String templateCode = RandomUtils.randomString(); | 179 | String templateCode = RandomUtils.randomString(); |
| 201 | Map<String, Object> templateParams = MapUtil.<String, Object>builder().put("code", "1234") | 180 | Map<String, Object> templateParams = MapUtil.<String, Object>builder().put("code", "1234") |
| 202 | .put("op", "login").build(); | 181 | .put("op", "login").build(); |
| 182 | + Collection<String> toMails = Lists.newArrayList(mail); | ||
| 183 | + | ||
| 203 | // mock MailTemplateService 的方法 | 184 | // mock MailTemplateService 的方法 |
| 204 | MailTemplateDO template = randomPojo(MailTemplateDO.class, o -> { | 185 | MailTemplateDO template = randomPojo(MailTemplateDO.class, o -> { |
| 205 | o.setStatus(CommonStatusEnum.DISABLE.getStatus()); | 186 | o.setStatus(CommonStatusEnum.DISABLE.getStatus()); |
| @@ -218,15 +199,18 @@ public class MailSendServiceImplTest extends BaseMockitoUnitTest { | @@ -218,15 +199,18 @@ public class MailSendServiceImplTest extends BaseMockitoUnitTest { | ||
| 218 | when(mailAccountService.getMailAccountFromCache(eq(template.getAccountId()))).thenReturn(account); | 199 | when(mailAccountService.getMailAccountFromCache(eq(template.getAccountId()))).thenReturn(account); |
| 219 | // mock MailLogService 的方法 | 200 | // mock MailLogService 的方法 |
| 220 | Long mailLogId = randomLongId(); | 201 | Long mailLogId = randomLongId(); |
| 221 | - when(mailLogService.createMailLog(eq(userId), eq(userType), eq(mail), | 202 | + when(mailLogService.createMailLog(eq(userId), eq(userType), |
| 203 | + argThat(toMailSet -> toMailSet.contains(mail)), | ||
| 204 | + argThat(Collection::isEmpty), | ||
| 205 | + argThat(Collection::isEmpty), | ||
| 222 | eq(account), eq(template), eq(content), eq(templateParams), eq(false))).thenReturn(mailLogId); | 206 | eq(account), eq(template), eq(content), eq(templateParams), eq(false))).thenReturn(mailLogId); |
| 223 | 207 | ||
| 224 | // 调用 | 208 | // 调用 |
| 225 | - Long resultMailLogId = mailSendService.sendSingleMail(mail, userId, userType, templateCode, templateParams); | 209 | + Long resultMailLogId = mailSendService.sendSingleMail(toMails, null, null, userId, userType, templateCode, templateParams); |
| 226 | // 断言 | 210 | // 断言 |
| 227 | assertEquals(mailLogId, resultMailLogId); | 211 | assertEquals(mailLogId, resultMailLogId); |
| 228 | // 断言调用 | 212 | // 断言调用 |
| 229 | - verify(mailProducer, times(0)).sendMailSendMessage(anyLong(), anyString(), | 213 | + verify(mailProducer, times(0)).sendMailSendMessage(anyLong(), any(), any(), any(), |
| 230 | anyLong(), anyString(), anyString(), anyString()); | 214 | anyLong(), anyString(), anyString(), anyString()); |
| 231 | } | 215 | } |
| 232 | 216 | ||
| @@ -255,12 +239,29 @@ public class MailSendServiceImplTest extends BaseMockitoUnitTest { | @@ -255,12 +239,29 @@ public class MailSendServiceImplTest extends BaseMockitoUnitTest { | ||
| 255 | } | 239 | } |
| 256 | 240 | ||
| 257 | @Test | 241 | @Test |
| 258 | - public void testValidateMail_notExists() { | 242 | + public void testSendSingleMail_noValidEmail() { |
| 259 | // 准备参数 | 243 | // 准备参数 |
| 260 | - // mock 方法 | 244 | + Long userId = randomLongId(); |
| 245 | + String templateCode = RandomUtils.randomString(); | ||
| 246 | + Map<String, Object> templateParams = MapUtil.<String, Object>builder().put("code", "1234") | ||
| 247 | + .put("op", "login").build(); | ||
| 248 | + Collection<String> toMails = Lists.newArrayList("invalid-email"); // 非法邮箱 | ||
| 249 | + | ||
| 250 | + // mock MailTemplateService 的方法 | ||
| 251 | + MailTemplateDO template = randomPojo(MailTemplateDO.class, o -> { | ||
| 252 | + o.setStatus(CommonStatusEnum.ENABLE.getStatus()); | ||
| 253 | + o.setContent("验证码为{code}, 操作为{op}"); | ||
| 254 | + o.setParams(Lists.newArrayList("code", "op")); | ||
| 255 | + }); | ||
| 256 | + when(mailTemplateService.getMailTemplateByCodeFromCache(eq(templateCode))).thenReturn(template); | ||
| 257 | + | ||
| 258 | + // mock MailAccountService 的方法 | ||
| 259 | + MailAccountDO account = randomPojo(MailAccountDO.class); | ||
| 260 | + when(mailAccountService.getMailAccountFromCache(eq(template.getAccountId()))).thenReturn(account); | ||
| 261 | 261 | ||
| 262 | // 调用,并断言异常 | 262 | // 调用,并断言异常 |
| 263 | - assertServiceException(() -> mailSendService.validateMail(null), | 263 | + assertServiceException(() -> mailSendService.sendSingleMail(toMails, null, null, userId, |
| 264 | + UserTypeEnum.ADMIN.getValue(), templateCode, templateParams), | ||
| 264 | MAIL_SEND_MAIL_NOT_EXISTS); | 265 | MAIL_SEND_MAIL_NOT_EXISTS); |
| 265 | } | 266 | } |
| 266 | 267 | ||
| @@ -286,7 +287,8 @@ public class MailSendServiceImplTest extends BaseMockitoUnitTest { | @@ -286,7 +287,8 @@ public class MailSendServiceImplTest extends BaseMockitoUnitTest { | ||
| 286 | assertEquals(account.getPort(), mailAccount.getPort()); | 287 | assertEquals(account.getPort(), mailAccount.getPort()); |
| 287 | assertEquals(account.getSslEnable(), mailAccount.isSslEnable()); | 288 | assertEquals(account.getSslEnable(), mailAccount.isSslEnable()); |
| 288 | return true; | 289 | return true; |
| 289 | - }), eq(message.getMail()), eq(message.getTitle()), eq(message.getContent()), eq(true))) | 290 | + }), eq(message.getToMails()), eq(message.getCcMails()), eq(message.getBccMails()), |
| 291 | + eq(message.getTitle()), eq(message.getContent()), eq(true))) | ||
| 290 | .thenReturn(messageId); | 292 | .thenReturn(messageId); |
| 291 | 293 | ||
| 292 | // 调用 | 294 | // 调用 |
| @@ -317,7 +319,8 @@ public class MailSendServiceImplTest extends BaseMockitoUnitTest { | @@ -317,7 +319,8 @@ public class MailSendServiceImplTest extends BaseMockitoUnitTest { | ||
| 317 | assertEquals(account.getPort(), mailAccount.getPort()); | 319 | assertEquals(account.getPort(), mailAccount.getPort()); |
| 318 | assertEquals(account.getSslEnable(), mailAccount.isSslEnable()); | 320 | assertEquals(account.getSslEnable(), mailAccount.isSslEnable()); |
| 319 | return true; | 321 | return true; |
| 320 | - }), eq(message.getMail()), eq(message.getTitle()), eq(message.getContent()), eq(true))).thenThrow(e); | 322 | + }), eq(message.getToMails()), eq(message.getCcMails()), eq(message.getBccMails()), |
| 323 | + eq(message.getTitle()), eq(message.getContent()), eq(true))).thenThrow(e); | ||
| 321 | 324 | ||
| 322 | // 调用 | 325 | // 调用 |
| 323 | mailSendService.doSendMail(message); | 326 | mailSendService.doSendMail(message); |
yudao-module-system/src/test/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2ApproveServiceImplTest.java
| @@ -8,21 +8,23 @@ import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; | @@ -8,21 +8,23 @@ import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; | ||
| 8 | import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2ApproveDO; | 8 | import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2ApproveDO; |
| 9 | import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2ClientDO; | 9 | import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2ClientDO; |
| 10 | import cn.iocoder.yudao.module.system.dal.mysql.oauth2.OAuth2ApproveMapper; | 10 | import cn.iocoder.yudao.module.system.dal.mysql.oauth2.OAuth2ApproveMapper; |
| 11 | +import jakarta.annotation.Resource; | ||
| 11 | import org.assertj.core.util.Lists; | 12 | import org.assertj.core.util.Lists; |
| 12 | import org.junit.jupiter.api.Test; | 13 | import org.junit.jupiter.api.Test; |
| 13 | -import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 14 | import org.springframework.context.annotation.Import; | 14 | import org.springframework.context.annotation.Import; |
| 15 | +import org.springframework.test.context.bean.override.mockito.MockitoBean; | ||
| 15 | 16 | ||
| 16 | -import jakarta.annotation.Resource; | ||
| 17 | import java.time.LocalDateTime; | 17 | import java.time.LocalDateTime; |
| 18 | import java.time.ZoneId; | 18 | import java.time.ZoneId; |
| 19 | import java.time.temporal.ChronoUnit; | 19 | import java.time.temporal.ChronoUnit; |
| 20 | -import java.util.*; | 20 | +import java.util.LinkedHashMap; |
| 21 | +import java.util.List; | ||
| 22 | +import java.util.Map; | ||
| 21 | 23 | ||
| 22 | import static cn.hutool.core.util.RandomUtil.*; | 24 | import static cn.hutool.core.util.RandomUtil.*; |
| 23 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; | 25 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; |
| 24 | -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString; | ||
| 25 | import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; | 26 | import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; |
| 27 | +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString; | ||
| 26 | import static org.junit.jupiter.api.Assertions.*; | 28 | import static org.junit.jupiter.api.Assertions.*; |
| 27 | import static org.mockito.ArgumentMatchers.eq; | 29 | import static org.mockito.ArgumentMatchers.eq; |
| 28 | import static org.mockito.Mockito.when; | 30 | import static org.mockito.Mockito.when; |
| @@ -41,7 +43,7 @@ public class OAuth2ApproveServiceImplTest extends BaseDbUnitTest { | @@ -41,7 +43,7 @@ public class OAuth2ApproveServiceImplTest extends BaseDbUnitTest { | ||
| 41 | @Resource | 43 | @Resource |
| 42 | private OAuth2ApproveMapper oauth2ApproveMapper; | 44 | private OAuth2ApproveMapper oauth2ApproveMapper; |
| 43 | 45 | ||
| 44 | - @MockBean | 46 | + @MockitoBean |
| 45 | private OAuth2ClientService oauth2ClientService; | 47 | private OAuth2ClientService oauth2ClientService; |
| 46 | 48 | ||
| 47 | @Test | 49 | @Test |
yudao-module-system/src/test/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2TokenServiceImplTest.java
| @@ -19,8 +19,8 @@ import cn.iocoder.yudao.module.system.service.user.AdminUserService; | @@ -19,8 +19,8 @@ import cn.iocoder.yudao.module.system.service.user.AdminUserService; | ||
| 19 | import jakarta.annotation.Resource; | 19 | import jakarta.annotation.Resource; |
| 20 | import org.assertj.core.util.Lists; | 20 | import org.assertj.core.util.Lists; |
| 21 | import org.junit.jupiter.api.Test; | 21 | import org.junit.jupiter.api.Test; |
| 22 | -import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 23 | import org.springframework.context.annotation.Import; | 22 | import org.springframework.context.annotation.Import; |
| 23 | +import org.springframework.test.context.bean.override.mockito.MockitoBean; | ||
| 24 | 24 | ||
| 25 | import java.time.LocalDateTime; | 25 | import java.time.LocalDateTime; |
| 26 | import java.util.List; | 26 | import java.util.List; |
| @@ -52,9 +52,9 @@ public class OAuth2TokenServiceImplTest extends BaseDbAndRedisUnitTest { | @@ -52,9 +52,9 @@ public class OAuth2TokenServiceImplTest extends BaseDbAndRedisUnitTest { | ||
| 52 | @Resource | 52 | @Resource |
| 53 | private OAuth2AccessTokenRedisDAO oauth2AccessTokenRedisDAO; | 53 | private OAuth2AccessTokenRedisDAO oauth2AccessTokenRedisDAO; |
| 54 | 54 | ||
| 55 | - @MockBean | 55 | + @MockitoBean |
| 56 | private OAuth2ClientService oauth2ClientService; | 56 | private OAuth2ClientService oauth2ClientService; |
| 57 | - @MockBean | 57 | + @MockitoBean |
| 58 | private AdminUserService adminUserService; | 58 | private AdminUserService adminUserService; |
| 59 | 59 | ||
| 60 | @Test | 60 | @Test |
yudao-module-system/src/test/java/cn/iocoder/yudao/module/system/service/permission/MenuServiceImplTest.java
| @@ -8,11 +8,11 @@ import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO; | @@ -8,11 +8,11 @@ import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO; | ||
| 8 | import cn.iocoder.yudao.module.system.dal.mysql.permission.MenuMapper; | 8 | import cn.iocoder.yudao.module.system.dal.mysql.permission.MenuMapper; |
| 9 | import cn.iocoder.yudao.module.system.enums.permission.MenuTypeEnum; | 9 | import cn.iocoder.yudao.module.system.enums.permission.MenuTypeEnum; |
| 10 | import cn.iocoder.yudao.module.system.service.tenant.TenantService; | 10 | import cn.iocoder.yudao.module.system.service.tenant.TenantService; |
| 11 | +import jakarta.annotation.Resource; | ||
| 11 | import org.junit.jupiter.api.Test; | 12 | import org.junit.jupiter.api.Test; |
| 12 | -import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 13 | import org.springframework.context.annotation.Import; | 13 | import org.springframework.context.annotation.Import; |
| 14 | +import org.springframework.test.context.bean.override.mockito.MockitoBean; | ||
| 14 | 15 | ||
| 15 | -import jakarta.annotation.Resource; | ||
| 16 | import java.util.Collection; | 16 | import java.util.Collection; |
| 17 | import java.util.Collections; | 17 | import java.util.Collections; |
| 18 | import java.util.List; | 18 | import java.util.List; |
| @@ -40,9 +40,9 @@ public class MenuServiceImplTest extends BaseDbUnitTest { | @@ -40,9 +40,9 @@ public class MenuServiceImplTest extends BaseDbUnitTest { | ||
| 40 | @Resource | 40 | @Resource |
| 41 | private MenuMapper menuMapper; | 41 | private MenuMapper menuMapper; |
| 42 | 42 | ||
| 43 | - @MockBean | 43 | + @MockitoBean |
| 44 | private PermissionService permissionService; | 44 | private PermissionService permissionService; |
| 45 | - @MockBean | 45 | + @MockitoBean |
| 46 | private TenantService tenantService; | 46 | private TenantService tenantService; |
| 47 | 47 | ||
| 48 | @Test | 48 | @Test |
yudao-module-system/src/test/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceTest.java
| @@ -2,9 +2,9 @@ package cn.iocoder.yudao.module.system.service.permission; | @@ -2,9 +2,9 @@ package cn.iocoder.yudao.module.system.service.permission; | ||
| 2 | 2 | ||
| 3 | import cn.hutool.core.collection.CollUtil; | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | import cn.hutool.extra.spring.SpringUtil; | 4 | import cn.hutool.extra.spring.SpringUtil; |
| 5 | +import cn.iocoder.yudao.framework.common.biz.system.permission.dto.DeptDataPermissionRespDTO; | ||
| 5 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | 6 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| 6 | import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; | 7 | import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; |
| 7 | -import cn.iocoder.yudao.framework.common.biz.system.permission.dto.DeptDataPermissionRespDTO; | ||
| 8 | import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; | 8 | import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; |
| 9 | import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO; | 9 | import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO; |
| 10 | import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO; | 10 | import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO; |
| @@ -16,12 +16,12 @@ import cn.iocoder.yudao.module.system.dal.mysql.permission.UserRoleMapper; | @@ -16,12 +16,12 @@ import cn.iocoder.yudao.module.system.dal.mysql.permission.UserRoleMapper; | ||
| 16 | import cn.iocoder.yudao.module.system.enums.permission.DataScopeEnum; | 16 | import cn.iocoder.yudao.module.system.enums.permission.DataScopeEnum; |
| 17 | import cn.iocoder.yudao.module.system.service.dept.DeptService; | 17 | import cn.iocoder.yudao.module.system.service.dept.DeptService; |
| 18 | import cn.iocoder.yudao.module.system.service.user.AdminUserService; | 18 | import cn.iocoder.yudao.module.system.service.user.AdminUserService; |
| 19 | +import jakarta.annotation.Resource; | ||
| 19 | import org.junit.jupiter.api.Test; | 20 | import org.junit.jupiter.api.Test; |
| 20 | import org.mockito.MockedStatic; | 21 | import org.mockito.MockedStatic; |
| 21 | -import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 22 | import org.springframework.context.annotation.Import; | 22 | import org.springframework.context.annotation.Import; |
| 23 | +import org.springframework.test.context.bean.override.mockito.MockitoBean; | ||
| 23 | 24 | ||
| 24 | -import jakarta.annotation.Resource; | ||
| 25 | import java.util.Collection; | 25 | import java.util.Collection; |
| 26 | import java.util.List; | 26 | import java.util.List; |
| 27 | import java.util.Set; | 27 | import java.util.Set; |
| @@ -48,13 +48,13 @@ public class PermissionServiceTest extends BaseDbUnitTest { | @@ -48,13 +48,13 @@ public class PermissionServiceTest extends BaseDbUnitTest { | ||
| 48 | @Resource | 48 | @Resource |
| 49 | private UserRoleMapper userRoleMapper; | 49 | private UserRoleMapper userRoleMapper; |
| 50 | 50 | ||
| 51 | - @MockBean | 51 | + @MockitoBean |
| 52 | private RoleService roleService; | 52 | private RoleService roleService; |
| 53 | - @MockBean | 53 | + @MockitoBean |
| 54 | private MenuService menuService; | 54 | private MenuService menuService; |
| 55 | - @MockBean | 55 | + @MockitoBean |
| 56 | private DeptService deptService; | 56 | private DeptService deptService; |
| 57 | - @MockBean | 57 | + @MockitoBean |
| 58 | private AdminUserService userService; | 58 | private AdminUserService userService; |
| 59 | 59 | ||
| 60 | @Test | 60 | @Test |
yudao-module-system/src/test/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceImplTest.java
| @@ -10,12 +10,12 @@ import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO; | @@ -10,12 +10,12 @@ import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO; | ||
| 10 | import cn.iocoder.yudao.module.system.dal.mysql.permission.RoleMapper; | 10 | import cn.iocoder.yudao.module.system.dal.mysql.permission.RoleMapper; |
| 11 | import cn.iocoder.yudao.module.system.enums.permission.DataScopeEnum; | 11 | import cn.iocoder.yudao.module.system.enums.permission.DataScopeEnum; |
| 12 | import cn.iocoder.yudao.module.system.enums.permission.RoleTypeEnum; | 12 | import cn.iocoder.yudao.module.system.enums.permission.RoleTypeEnum; |
| 13 | +import jakarta.annotation.Resource; | ||
| 13 | import org.junit.jupiter.api.Test; | 14 | import org.junit.jupiter.api.Test; |
| 14 | import org.mockito.MockedStatic; | 15 | import org.mockito.MockedStatic; |
| 15 | -import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 16 | import org.springframework.context.annotation.Import; | 16 | import org.springframework.context.annotation.Import; |
| 17 | +import org.springframework.test.context.bean.override.mockito.MockitoBean; | ||
| 17 | 18 | ||
| 18 | -import jakarta.annotation.Resource; | ||
| 19 | import java.util.Collection; | 19 | import java.util.Collection; |
| 20 | import java.util.List; | 20 | import java.util.List; |
| 21 | import java.util.Set; | 21 | import java.util.Set; |
| @@ -44,7 +44,7 @@ public class RoleServiceImplTest extends BaseDbUnitTest { | @@ -44,7 +44,7 @@ public class RoleServiceImplTest extends BaseDbUnitTest { | ||
| 44 | @Resource | 44 | @Resource |
| 45 | private RoleMapper roleMapper; | 45 | private RoleMapper roleMapper; |
| 46 | 46 | ||
| 47 | - @MockBean | 47 | + @MockitoBean |
| 48 | private PermissionService permissionService; | 48 | private PermissionService permissionService; |
| 49 | 49 | ||
| 50 | @Test | 50 | @Test |
yudao-module-system/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelServiceTest.java
| @@ -3,19 +3,19 @@ package cn.iocoder.yudao.module.system.service.sms; | @@ -3,19 +3,19 @@ package cn.iocoder.yudao.module.system.service.sms; | ||
| 3 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | 3 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 5 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | 5 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| 6 | -import cn.iocoder.yudao.module.system.framework.sms.core.client.SmsClient; | ||
| 7 | -import cn.iocoder.yudao.module.system.framework.sms.core.client.SmsClientFactory; | ||
| 8 | -import cn.iocoder.yudao.module.system.framework.sms.core.property.SmsChannelProperties; | ||
| 9 | import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; | 6 | import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; |
| 10 | import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelPageReqVO; | 7 | import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelPageReqVO; |
| 11 | import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelSaveReqVO; | 8 | import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelSaveReqVO; |
| 12 | import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO; | 9 | import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO; |
| 13 | import cn.iocoder.yudao.module.system.dal.mysql.sms.SmsChannelMapper; | 10 | import cn.iocoder.yudao.module.system.dal.mysql.sms.SmsChannelMapper; |
| 11 | +import cn.iocoder.yudao.module.system.framework.sms.core.client.SmsClient; | ||
| 12 | +import cn.iocoder.yudao.module.system.framework.sms.core.client.SmsClientFactory; | ||
| 13 | +import cn.iocoder.yudao.module.system.framework.sms.core.property.SmsChannelProperties; | ||
| 14 | +import jakarta.annotation.Resource; | ||
| 14 | import org.junit.jupiter.api.Test; | 15 | import org.junit.jupiter.api.Test; |
| 15 | -import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 16 | import org.springframework.context.annotation.Import; | 16 | import org.springframework.context.annotation.Import; |
| 17 | +import org.springframework.test.context.bean.override.mockito.MockitoBean; | ||
| 17 | 18 | ||
| 18 | -import jakarta.annotation.Resource; | ||
| 19 | import java.util.List; | 19 | import java.util.List; |
| 20 | 20 | ||
| 21 | import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime; | 21 | import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime; |
| @@ -28,7 +28,8 @@ import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SMS_CHANNE | @@ -28,7 +28,8 @@ import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SMS_CHANNE | ||
| 28 | import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SMS_CHANNEL_NOT_EXISTS; | 28 | import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SMS_CHANNEL_NOT_EXISTS; |
| 29 | import static org.junit.jupiter.api.Assertions.*; | 29 | import static org.junit.jupiter.api.Assertions.*; |
| 30 | import static org.mockito.ArgumentMatchers.eq; | 30 | import static org.mockito.ArgumentMatchers.eq; |
| 31 | -import static org.mockito.Mockito.*; | 31 | +import static org.mockito.Mockito.mock; |
| 32 | +import static org.mockito.Mockito.when; | ||
| 32 | 33 | ||
| 33 | @Import(SmsChannelServiceImpl.class) | 34 | @Import(SmsChannelServiceImpl.class) |
| 34 | public class SmsChannelServiceTest extends BaseDbUnitTest { | 35 | public class SmsChannelServiceTest extends BaseDbUnitTest { |
| @@ -39,9 +40,9 @@ public class SmsChannelServiceTest extends BaseDbUnitTest { | @@ -39,9 +40,9 @@ public class SmsChannelServiceTest extends BaseDbUnitTest { | ||
| 39 | @Resource | 40 | @Resource |
| 40 | private SmsChannelMapper smsChannelMapper; | 41 | private SmsChannelMapper smsChannelMapper; |
| 41 | 42 | ||
| 42 | - @MockBean | 43 | + @MockitoBean |
| 43 | private SmsClientFactory smsClientFactory; | 44 | private SmsClientFactory smsClientFactory; |
| 44 | - @MockBean | 45 | + @MockitoBean |
| 45 | private SmsTemplateService smsTemplateService; | 46 | private SmsTemplateService smsTemplateService; |
| 46 | 47 | ||
| 47 | @Test | 48 | @Test |
yudao-module-system/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsCodeServiceImplTest.java
| @@ -12,8 +12,8 @@ import cn.iocoder.yudao.module.system.framework.sms.config.SmsCodeProperties; | @@ -12,8 +12,8 @@ import cn.iocoder.yudao.module.system.framework.sms.config.SmsCodeProperties; | ||
| 12 | import jakarta.annotation.Resource; | 12 | import jakarta.annotation.Resource; |
| 13 | import org.junit.jupiter.api.BeforeEach; | 13 | import org.junit.jupiter.api.BeforeEach; |
| 14 | import org.junit.jupiter.api.Test; | 14 | import org.junit.jupiter.api.Test; |
| 15 | -import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 16 | import org.springframework.context.annotation.Import; | 15 | import org.springframework.context.annotation.Import; |
| 16 | +import org.springframework.test.context.bean.override.mockito.MockitoBean; | ||
| 17 | 17 | ||
| 18 | import java.time.Duration; | 18 | import java.time.Duration; |
| 19 | import java.time.LocalDateTime; | 19 | import java.time.LocalDateTime; |
| @@ -38,9 +38,9 @@ public class SmsCodeServiceImplTest extends BaseDbUnitTest { | @@ -38,9 +38,9 @@ public class SmsCodeServiceImplTest extends BaseDbUnitTest { | ||
| 38 | @Resource | 38 | @Resource |
| 39 | private SmsCodeMapper smsCodeMapper; | 39 | private SmsCodeMapper smsCodeMapper; |
| 40 | 40 | ||
| 41 | - @MockBean | 41 | + @MockitoBean |
| 42 | private SmsCodeProperties smsCodeProperties; | 42 | private SmsCodeProperties smsCodeProperties; |
| 43 | - @MockBean | 43 | + @MockitoBean |
| 44 | private SmsSendService smsSendService; | 44 | private SmsSendService smsSendService; |
| 45 | 45 | ||
| 46 | @BeforeEach | 46 | @BeforeEach |
yudao-module-system/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsTemplateServiceImplTest.java
| @@ -5,9 +5,6 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | @@ -5,9 +5,6 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | ||
| 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 6 | import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; | 6 | import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; |
| 7 | import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; | 7 | import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; |
| 8 | -import cn.iocoder.yudao.module.system.framework.sms.core.client.SmsClient; | ||
| 9 | -import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsTemplateRespDTO; | ||
| 10 | -import cn.iocoder.yudao.module.system.framework.sms.core.enums.SmsTemplateAuditStatusEnum; | ||
| 11 | import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; | 8 | import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; |
| 12 | import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplatePageReqVO; | 9 | import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplatePageReqVO; |
| 13 | import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateSaveReqVO; | 10 | import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateSaveReqVO; |
| @@ -15,12 +12,15 @@ import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO; | @@ -15,12 +12,15 @@ import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO; | ||
| 15 | import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO; | 12 | import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO; |
| 16 | import cn.iocoder.yudao.module.system.dal.mysql.sms.SmsTemplateMapper; | 13 | import cn.iocoder.yudao.module.system.dal.mysql.sms.SmsTemplateMapper; |
| 17 | import cn.iocoder.yudao.module.system.enums.sms.SmsTemplateTypeEnum; | 14 | import cn.iocoder.yudao.module.system.enums.sms.SmsTemplateTypeEnum; |
| 15 | +import cn.iocoder.yudao.module.system.framework.sms.core.client.SmsClient; | ||
| 16 | +import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsTemplateRespDTO; | ||
| 17 | +import cn.iocoder.yudao.module.system.framework.sms.core.enums.SmsTemplateAuditStatusEnum; | ||
| 18 | import com.google.common.collect.Lists; | 18 | import com.google.common.collect.Lists; |
| 19 | +import jakarta.annotation.Resource; | ||
| 19 | import org.junit.jupiter.api.Test; | 20 | import org.junit.jupiter.api.Test; |
| 20 | -import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 21 | import org.springframework.context.annotation.Import; | 21 | import org.springframework.context.annotation.Import; |
| 22 | +import org.springframework.test.context.bean.override.mockito.MockitoBean; | ||
| 22 | 23 | ||
| 23 | -import jakarta.annotation.Resource; | ||
| 24 | import java.util.List; | 24 | import java.util.List; |
| 25 | import java.util.Map; | 25 | import java.util.Map; |
| 26 | import java.util.function.Consumer; | 26 | import java.util.function.Consumer; |
| @@ -45,9 +45,9 @@ public class SmsTemplateServiceImplTest extends BaseDbUnitTest { | @@ -45,9 +45,9 @@ public class SmsTemplateServiceImplTest extends BaseDbUnitTest { | ||
| 45 | @Resource | 45 | @Resource |
| 46 | private SmsTemplateMapper smsTemplateMapper; | 46 | private SmsTemplateMapper smsTemplateMapper; |
| 47 | 47 | ||
| 48 | - @MockBean | 48 | + @MockitoBean |
| 49 | private SmsChannelService smsChannelService; | 49 | private SmsChannelService smsChannelService; |
| 50 | - @MockBean | 50 | + @MockitoBean |
| 51 | private SmsClient smsClient; | 51 | private SmsClient smsClient; |
| 52 | 52 | ||
| 53 | @Test | 53 | @Test |
yudao-module-system/src/test/java/cn/iocoder/yudao/module/system/service/social/SocialClientServiceImplTest.java
| @@ -28,9 +28,9 @@ import me.zhyd.oauth.request.AuthRequest; | @@ -28,9 +28,9 @@ import me.zhyd.oauth.request.AuthRequest; | ||
| 28 | import me.zhyd.oauth.utils.AuthStateUtils; | 28 | import me.zhyd.oauth.utils.AuthStateUtils; |
| 29 | import org.junit.jupiter.api.Test; | 29 | import org.junit.jupiter.api.Test; |
| 30 | import org.mockito.MockedStatic; | 30 | import org.mockito.MockedStatic; |
| 31 | -import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 32 | import org.springframework.context.annotation.Import; | 31 | import org.springframework.context.annotation.Import; |
| 33 | import org.springframework.data.redis.core.StringRedisTemplate; | 32 | import org.springframework.data.redis.core.StringRedisTemplate; |
| 33 | +import org.springframework.test.context.bean.override.mockito.MockitoBean; | ||
| 34 | 34 | ||
| 35 | import static cn.hutool.core.util.RandomUtil.randomEle; | 35 | import static cn.hutool.core.util.RandomUtil.randomEle; |
| 36 | import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; | 36 | import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; |
| @@ -55,18 +55,18 @@ public class SocialClientServiceImplTest extends BaseDbUnitTest { | @@ -55,18 +55,18 @@ public class SocialClientServiceImplTest extends BaseDbUnitTest { | ||
| 55 | @Resource | 55 | @Resource |
| 56 | private SocialClientMapper socialClientMapper; | 56 | private SocialClientMapper socialClientMapper; |
| 57 | 57 | ||
| 58 | - @MockBean | 58 | + @MockitoBean |
| 59 | private AuthRequestFactory authRequestFactory; | 59 | private AuthRequestFactory authRequestFactory; |
| 60 | 60 | ||
| 61 | - @MockBean | 61 | + @MockitoBean |
| 62 | private WxMpService wxMpService; | 62 | private WxMpService wxMpService; |
| 63 | - @MockBean | 63 | + @MockitoBean |
| 64 | private WxMpProperties wxMpProperties; | 64 | private WxMpProperties wxMpProperties; |
| 65 | - @MockBean | 65 | + @MockitoBean |
| 66 | private StringRedisTemplate stringRedisTemplate; | 66 | private StringRedisTemplate stringRedisTemplate; |
| 67 | - @MockBean | 67 | + @MockitoBean |
| 68 | private WxMaService wxMaService; | 68 | private WxMaService wxMaService; |
| 69 | - @MockBean | 69 | + @MockitoBean |
| 70 | private WxMaProperties wxMaProperties; | 70 | private WxMaProperties wxMaProperties; |
| 71 | 71 | ||
| 72 | @Test | 72 | @Test |
yudao-module-system/src/test/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImplTest.java
| @@ -14,8 +14,8 @@ import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; | @@ -14,8 +14,8 @@ import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; | ||
| 14 | import jakarta.annotation.Resource; | 14 | import jakarta.annotation.Resource; |
| 15 | import me.zhyd.oauth.model.AuthUser; | 15 | import me.zhyd.oauth.model.AuthUser; |
| 16 | import org.junit.jupiter.api.Test; | 16 | import org.junit.jupiter.api.Test; |
| 17 | -import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 18 | import org.springframework.context.annotation.Import; | 17 | import org.springframework.context.annotation.Import; |
| 18 | +import org.springframework.test.context.bean.override.mockito.MockitoBean; | ||
| 19 | 19 | ||
| 20 | import java.util.List; | 20 | import java.util.List; |
| 21 | 21 | ||
| @@ -50,7 +50,7 @@ public class SocialUserServiceImplTest extends BaseDbUnitTest { | @@ -50,7 +50,7 @@ public class SocialUserServiceImplTest extends BaseDbUnitTest { | ||
| 50 | @Resource | 50 | @Resource |
| 51 | private SocialUserBindMapper socialUserBindMapper; | 51 | private SocialUserBindMapper socialUserBindMapper; |
| 52 | 52 | ||
| 53 | - @MockBean | 53 | + @MockitoBean |
| 54 | private SocialClientService socialClientService; | 54 | private SocialClientService socialClientService; |
| 55 | 55 | ||
| 56 | @Test | 56 | @Test |
yudao-module-system/src/test/java/cn/iocoder/yudao/module/system/service/tenant/TenantPackageServiceImplTest.java
| @@ -8,11 +8,11 @@ import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.Tenant | @@ -8,11 +8,11 @@ import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.Tenant | ||
| 8 | import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO; | 8 | import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO; |
| 9 | import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantPackageDO; | 9 | import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantPackageDO; |
| 10 | import cn.iocoder.yudao.module.system.dal.mysql.tenant.TenantPackageMapper; | 10 | import cn.iocoder.yudao.module.system.dal.mysql.tenant.TenantPackageMapper; |
| 11 | +import jakarta.annotation.Resource; | ||
| 11 | import org.junit.jupiter.api.Test; | 12 | import org.junit.jupiter.api.Test; |
| 12 | -import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 13 | import org.springframework.context.annotation.Import; | 13 | import org.springframework.context.annotation.Import; |
| 14 | +import org.springframework.test.context.bean.override.mockito.MockitoBean; | ||
| 14 | 15 | ||
| 15 | -import jakarta.annotation.Resource; | ||
| 16 | import java.util.List; | 16 | import java.util.List; |
| 17 | 17 | ||
| 18 | import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime; | 18 | import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime; |
| @@ -42,7 +42,7 @@ public class TenantPackageServiceImplTest extends BaseDbUnitTest { | @@ -42,7 +42,7 @@ public class TenantPackageServiceImplTest extends BaseDbUnitTest { | ||
| 42 | @Resource | 42 | @Resource |
| 43 | private TenantPackageMapper tenantPackageMapper; | 43 | private TenantPackageMapper tenantPackageMapper; |
| 44 | 44 | ||
| 45 | - @MockBean | 45 | + @MockitoBean |
| 46 | private TenantService tenantService; | 46 | private TenantService tenantService; |
| 47 | 47 | ||
| 48 | @Test | 48 | @Test |
yudao-module-system/src/test/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImplTest.java
| @@ -20,12 +20,12 @@ import cn.iocoder.yudao.module.system.service.permission.RoleService; | @@ -20,12 +20,12 @@ import cn.iocoder.yudao.module.system.service.permission.RoleService; | ||
| 20 | import cn.iocoder.yudao.module.system.service.tenant.handler.TenantInfoHandler; | 20 | import cn.iocoder.yudao.module.system.service.tenant.handler.TenantInfoHandler; |
| 21 | import cn.iocoder.yudao.module.system.service.tenant.handler.TenantMenuHandler; | 21 | import cn.iocoder.yudao.module.system.service.tenant.handler.TenantMenuHandler; |
| 22 | import cn.iocoder.yudao.module.system.service.user.AdminUserService; | 22 | import cn.iocoder.yudao.module.system.service.user.AdminUserService; |
| 23 | +import jakarta.annotation.Resource; | ||
| 23 | import org.junit.jupiter.api.BeforeEach; | 24 | import org.junit.jupiter.api.BeforeEach; |
| 24 | import org.junit.jupiter.api.Test; | 25 | import org.junit.jupiter.api.Test; |
| 25 | -import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 26 | import org.springframework.context.annotation.Import; | 26 | import org.springframework.context.annotation.Import; |
| 27 | +import org.springframework.test.context.bean.override.mockito.MockitoBean; | ||
| 27 | 28 | ||
| 28 | -import jakarta.annotation.Resource; | ||
| 29 | import java.time.LocalDateTime; | 29 | import java.time.LocalDateTime; |
| 30 | import java.util.Arrays; | 30 | import java.util.Arrays; |
| 31 | import java.util.Collections; | 31 | import java.util.Collections; |
| @@ -60,17 +60,17 @@ public class TenantServiceImplTest extends BaseDbUnitTest { | @@ -60,17 +60,17 @@ public class TenantServiceImplTest extends BaseDbUnitTest { | ||
| 60 | @Resource | 60 | @Resource |
| 61 | private TenantMapper tenantMapper; | 61 | private TenantMapper tenantMapper; |
| 62 | 62 | ||
| 63 | - @MockBean | 63 | + @MockitoBean |
| 64 | private TenantProperties tenantProperties; | 64 | private TenantProperties tenantProperties; |
| 65 | - @MockBean | 65 | + @MockitoBean |
| 66 | private TenantPackageService tenantPackageService; | 66 | private TenantPackageService tenantPackageService; |
| 67 | - @MockBean | 67 | + @MockitoBean |
| 68 | private AdminUserService userService; | 68 | private AdminUserService userService; |
| 69 | - @MockBean | 69 | + @MockitoBean |
| 70 | private RoleService roleService; | 70 | private RoleService roleService; |
| 71 | - @MockBean | 71 | + @MockitoBean |
| 72 | private MenuService menuService; | 72 | private MenuService menuService; |
| 73 | - @MockBean | 73 | + @MockitoBean |
| 74 | private PermissionService permissionService; | 74 | private PermissionService permissionService; |
| 75 | 75 | ||
| 76 | @BeforeEach | 76 | @BeforeEach |
yudao-module-system/src/test/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImplTest.java
| @@ -31,9 +31,9 @@ import jakarta.annotation.Resource; | @@ -31,9 +31,9 @@ import jakarta.annotation.Resource; | ||
| 31 | import org.junit.jupiter.api.BeforeEach; | 31 | import org.junit.jupiter.api.BeforeEach; |
| 32 | import org.junit.jupiter.api.Test; | 32 | import org.junit.jupiter.api.Test; |
| 33 | import org.mockito.stubbing.Answer; | 33 | import org.mockito.stubbing.Answer; |
| 34 | -import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 35 | import org.springframework.context.annotation.Import; | 34 | import org.springframework.context.annotation.Import; |
| 36 | import org.springframework.security.crypto.password.PasswordEncoder; | 35 | import org.springframework.security.crypto.password.PasswordEncoder; |
| 36 | +import org.springframework.test.context.bean.override.mockito.MockitoBean; | ||
| 37 | 37 | ||
| 38 | import java.util.Collection; | 38 | import java.util.Collection; |
| 39 | import java.util.List; | 39 | import java.util.List; |
| @@ -68,19 +68,19 @@ public class AdminUserServiceImplTest extends BaseDbUnitTest { | @@ -68,19 +68,19 @@ public class AdminUserServiceImplTest extends BaseDbUnitTest { | ||
| 68 | @Resource | 68 | @Resource |
| 69 | private UserPostMapper userPostMapper; | 69 | private UserPostMapper userPostMapper; |
| 70 | 70 | ||
| 71 | - @MockBean | 71 | + @MockitoBean |
| 72 | private DeptService deptService; | 72 | private DeptService deptService; |
| 73 | - @MockBean | 73 | + @MockitoBean |
| 74 | private PostService postService; | 74 | private PostService postService; |
| 75 | - @MockBean | 75 | + @MockitoBean |
| 76 | private PermissionService permissionService; | 76 | private PermissionService permissionService; |
| 77 | - @MockBean | 77 | + @MockitoBean |
| 78 | private PasswordEncoder passwordEncoder; | 78 | private PasswordEncoder passwordEncoder; |
| 79 | - @MockBean | 79 | + @MockitoBean |
| 80 | private TenantService tenantService; | 80 | private TenantService tenantService; |
| 81 | - @MockBean | 81 | + @MockitoBean |
| 82 | private FileApi fileApi; | 82 | private FileApi fileApi; |
| 83 | - @MockBean | 83 | + @MockitoBean |
| 84 | private ConfigApi configApi; | 84 | private ConfigApi configApi; |
| 85 | 85 | ||
| 86 | @BeforeEach | 86 | @BeforeEach |
yudao-module-system/src/test/resources/sql/create_tables.sql
| @@ -553,7 +553,9 @@ CREATE TABLE IF NOT EXISTS "system_mail_log" ( | @@ -553,7 +553,9 @@ CREATE TABLE IF NOT EXISTS "system_mail_log" ( | ||
| 553 | "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, | 553 | "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, |
| 554 | "user_id" bigint, | 554 | "user_id" bigint, |
| 555 | "user_type" varchar, | 555 | "user_type" varchar, |
| 556 | - "to_mail" varchar NOT NULL, | 556 | + "to_mails" varchar NOT NULL, |
| 557 | + "cc_mails" varchar, | ||
| 558 | + "bcc_mails" varchar, | ||
| 557 | "account_id" bigint NOT NULL, | 559 | "account_id" bigint NOT NULL, |
| 558 | "from_mail" varchar NOT NULL, | 560 | "from_mail" varchar NOT NULL, |
| 559 | "template_id" bigint NOT NULL, | 561 | "template_id" bigint NOT NULL, |
yudao-server/src/main/resources/application.yaml
| @@ -107,7 +107,7 @@ aj: | @@ -107,7 +107,7 @@ aj: | ||
| 107 | cache-type: redis # 缓存 local/redis... | 107 | cache-type: redis # 缓存 local/redis... |
| 108 | cache-number: 1000 # local 缓存的阈值,达到这个值,清除缓存 | 108 | cache-number: 1000 # local 缓存的阈值,达到这个值,清除缓存 |
| 109 | timing-clear: 180 # local定时清除过期缓存(单位秒),设置为0代表不执行 | 109 | timing-clear: 180 # local定时清除过期缓存(单位秒),设置为0代表不执行 |
| 110 | - type: blockPuzzle # 验证码类型 default两种都实例化。 blockPuzzle 滑块拼图 clickWord 文字点选 | 110 | + type: blockPuzzle # 验证码类型 default 三种都实例化。blockPuzzle 滑块拼图、clickWord 文字点选、pictureWord 文本输入 |
| 111 | water-mark: 芋道源码 # 右下角水印文字(我的水印),可使用 https://tool.chinaz.com/tools/unicode.aspx 中文转 Unicode,Linux 可能需要转 unicode | 111 | water-mark: 芋道源码 # 右下角水印文字(我的水印),可使用 https://tool.chinaz.com/tools/unicode.aspx 中文转 Unicode,Linux 可能需要转 unicode |
| 112 | interference-options: 0 # 滑动干扰项(0/1/2) | 112 | interference-options: 0 # 滑动干扰项(0/1/2) |
| 113 | req-frequency-limit-enable: false # 接口请求次数一分钟限制是否开启 true|false | 113 | req-frequency-limit-enable: false # 接口请求次数一分钟限制是否开启 true|false |
| @@ -245,6 +245,13 @@ yudao: | @@ -245,6 +245,13 @@ yudao: | ||
| 245 | security: | 245 | security: |
| 246 | permit-all_urls: | 246 | permit-all_urls: |
| 247 | - /admin-api/mp/open/** # 微信公众号开放平台,微信回调接口,不需要登录 | 247 | - /admin-api/mp/open/** # 微信公众号开放平台,微信回调接口,不需要登录 |
| 248 | + api-encrypt: | ||
| 249 | + enable: true # 是否开启 API 加密 | ||
| 250 | + algorithm: AES # 加密算法,支持 AES、RSA 等 | ||
| 251 | + request-key: 52549111389893486934626385991395 # 【AES 案例】请求加密的秘钥,,必须 16、24、32 位 | ||
| 252 | + response-key: 96103715984234343991809655248883 # 【AES 案例】响应加密的秘钥,AES 案例,必须 16、24、32 位 | ||
| 253 | +# request-key: MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKWzasimcZ1icsWDPVdTXcZs1DkOWjI+m9bTQU8aOqflnomkr6QO1WWeSHBHzuJGsTlV/ZY2pFfq/NstKC94hBjx7yioYJvzb2bKN/Uy4j5nM3iCF//u0RiFkkY8j0Bt/EWoFTOb6RHf8cHIAjbYYtP3pYzbpCIwryfe0g//KIuzAgMBAAECgYADDjZrYcpZjR2xr7RbXmGtzYbyUGXwZEAqa3XaWBD51J2iSyOkAlQEDjGmxGQ3vvb4qDHHadWI+3/TKNeDXJUO+xTVJrnismK5BsHyC6dfxlIK/5BAuknryTca/3UoA1yomS9ZlF3Q0wcecaDoEnSmZEaTrp9T3itPAz4KnGjv5QJBAN5mNcfu6iJ5ktNvEdzqcxkKwbXb9Nq1SLnmTvt+d5TPX7eQ9fCwtOfVu5iBLhhZzb5PJ7pSN3Zt6rl5/jPOGv0CQQC+vETX9oe1wbxZSv6/RBGy0Xow6GndbJwvd89PcAJ2h+OJXWtg/rRHB3t9EQm7iis0XbZTapj19E4U6l8EibhvAkEA1CvYpRwmHKu1SqdM+GBnW/2qHlBwwXJvpoK02TOm674HR/4w0+YRQJfkd7LOAgcyxJuJgDTNmtt0MmzS+iNoFQJAMVSUIZ77XoDq69U/qcw7H5qaFcgmiUQr6QL9tTftCyb+LGri+MUnby96OtCLSdvkbLjIDS8GvKYhA7vSM2RDNQJBAKGyVVnFFIrbK3yuwW71yvxQEGoGxlgvZSezZ4vGgqTxrr9HvAtvWLwR6rpe6ybR/x8uUtoW7NRBWgpiIFwjvY4= # 【RSA 案例】请求解密的私钥 | ||
| 254 | +# response-key: MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDh/CHyBcS/zEfVyINVA7+c9Xxl0CPdxPMK1OIjxaLy/7BLfbkoEpI8onQtjuzfpuxCraDem9bu3BMF0pMH95HytI3Vi0kGjaV+WLIalwgc2w37oA2sbsmKzQOP7SDLO5s2QJNAD7kVwd+Q5rqaLu2MO0xVv+0IUJhn83hClC0L5wIDAQAB # 【RSA 案例】响应加密的公钥 | ||
| 248 | websocket: | 255 | websocket: |
| 249 | enable: true # websocket的开关 | 256 | enable: true # websocket的开关 |
| 250 | path: /infra/ws # 路径 | 257 | path: /infra/ws # 路径 |