diff --git a/yudao-dependencies/pom.xml b/yudao-dependencies/pom.xml index f611ddac4..a24f43fea 100644 --- a/yudao-dependencies/pom.xml +++ b/yudao-dependencies/pom.xml @@ -29,6 +29,7 @@ 3.5.3.1 3.5.3.1 3.6.1 + 1.4.5 3.18.0 8.1.2.141 @@ -248,7 +249,7 @@ yudao-spring-boot-starter-mybatis ${revision} - + org.springdoc springdoc-openapi-webflux-ui ${springdoc.version} @@ -274,6 +275,11 @@ dynamic-datasource-spring-boot-starter ${dynamic-datasource.version} + + com.github.yulichang + mybatis-plus-join-boot-starter + ${mybatis-plus-join-boot-starter.version} + cn.iocoder.cloud diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java index 62e0e4441..a55af427c 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java @@ -4,6 +4,7 @@ import cn.hutool.core.date.LocalDateTimeUtil; import java.time.Duration; import java.time.LocalDateTime; +import java.time.LocalTime; /** * 时间工具类,用于 {@link java.time.LocalDateTime} @@ -50,7 +51,7 @@ public class LocalDateTimeUtils { * 判断当前时间是否在该时间范围内 * * @param startTime 开始时间 - * @param endTime 结束时间 + * @param endTime 结束时间 * @return 是否 */ public static boolean isBetween(LocalDateTime startTime, LocalDateTime endTime) { @@ -60,4 +61,24 @@ public class LocalDateTimeUtils { return LocalDateTimeUtil.isIn(LocalDateTime.now(), startTime, endTime); } + /** + * 检查时间重叠 不包含日期 + * + * @param startTime1 需要校验的开始时间 + * @param endTime1 需要校验的结束时间 + * @param startTime2 校验所需的开始时间 + * @param endTime2 校验所需的结束时间 + * @return 是否重叠 + */ + // TODO @puhui999:LocalDateTimeUtil.isOverlap() 是不是可以满足呀? + public static boolean checkTimeOverlap(LocalTime startTime1, LocalTime endTime1, LocalTime startTime2, LocalTime endTime2) { + // 判断时间是否重叠 + // 开始时间在已配置时段的结束时间之前 且 结束时间在已配置时段的开始时间之后 [] + return startTime1.isBefore(endTime2) && endTime1.isAfter(startTime2) + // 开始时间在已配置时段的开始时间之前 且 结束时间在已配置时段的开始时间之后 (] 或 () + || startTime1.isBefore(startTime2) && endTime1.isAfter(startTime2) + // 开始时间在已配置时段的结束时间之前 且 结束时间在已配值时段的结束时间之后 [) 或 () + || startTime1.isBefore(endTime2) && endTime1.isAfter(endTime2); + } + } diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/spring/SpringExpressionUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/spring/SpringExpressionUtils.java index 659053da7..5e82d5e3b 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/spring/SpringExpressionUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/spring/SpringExpressionUtils.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.framework.common.util.spring; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.ArrayUtil; +import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.core.DefaultParameterNameDiscoverer; @@ -24,7 +25,13 @@ import java.util.Map; */ public class SpringExpressionUtils { + /** + * spel表达式解析器 + */ private static final ExpressionParser EXPRESSION_PARSER = new SpelExpressionParser(); + /** + * 参数名发现器 + */ private static final ParameterNameDiscoverer PARAMETER_NAME_DISCOVERER = new DefaultParameterNameDiscoverer(); private SpringExpressionUtils() { @@ -33,7 +40,7 @@ public class SpringExpressionUtils { /** * 从切面中,单个解析 EL 表达式的结果 * - * @param joinPoint 切面点 + * @param joinPoint 切面点 * @param expressionString EL 表达式数组 * @return 执行界面 */ @@ -45,7 +52,7 @@ public class SpringExpressionUtils { /** * 从切面中,批量解析 EL 表达式的结果 * - * @param joinPoint 切面点 + * @param joinPoint 切面点 * @param expressionStrings EL 表达式数组 * @return 结果,key 为表达式,value 为对应值 */ @@ -79,4 +86,48 @@ public class SpringExpressionUtils { }); return result; } + + /** + * JoinPoint 切面 批量解析 EL 表达式,转换 jspl参数 + * + * @param joinPoint 切面点 + * @param info 返回值 + * @param expressionStrings EL 表达式数组 + * @return Map 结果 + * @author 陈賝 + * @since 2023/6/18 11:20 + */ + // TODO @chenchen: 这个方法,和 parseExpressions 比较接近,是不是可以合并下; + public static Map parseExpression(JoinPoint joinPoint, Object info, List expressionStrings) { + // 如果为空,则不进行解析 + if (CollUtil.isEmpty(expressionStrings)) { + return MapUtil.newHashMap(); + } + + // 第一步,构建解析的上下文 EvaluationContext + // 通过 joinPoint 获取被注解方法 + MethodSignature signature = (MethodSignature) joinPoint.getSignature(); + Method method = signature.getMethod(); + // 使用 spring 的 ParameterNameDiscoverer 获取方法形参名数组 + String[] parameterNames = PARAMETER_NAME_DISCOVERER.getParameterNames(method); + // Spring 的表达式上下文对象 + EvaluationContext context = new StandardEvaluationContext(); + if (ArrayUtil.isNotEmpty(parameterNames)) { + //获取方法参数值 + Object[] args = joinPoint.getArgs(); + for (int i = 0; i < args.length; i++) { + // 替换 SP EL 里的变量值为实际值, 比如 #user --> user对象 + context.setVariable(parameterNames[i], args[i]); + } + context.setVariable("info", info); + } + // 第二步,逐个参数解析 + Map result = MapUtil.newHashMap(expressionStrings.size(), true); + expressionStrings.forEach(key -> { + Object value = EXPRESSION_PARSER.parseExpression(key).getValue(context); + result.put(key, value); + }); + return result; + } + } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/context/TenantContextHolder.java b/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/context/TenantContextHolder.java index 3b15398d6..93a17b376 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/context/TenantContextHolder.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/context/TenantContextHolder.java @@ -38,7 +38,7 @@ public class TenantContextHolder { Long tenantId = getTenantId(); if (tenantId == null) { throw new NullPointerException("TenantContextHolder 不存在租户编号!可参考文档:" - + DocumentEnum.TENANT.getUrl()); + + DocumentEnum.TENANT.getUrl()); } return tenantId; } diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml b/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml index 4bb35b106..e40171584 100644 --- a/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml @@ -63,6 +63,10 @@ dynamic-datasource-spring-boot-starter + + com.github.yulichang + mybatis-plus-join-boot-starter + diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoWebSecurityConfigurerAdapter.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoWebSecurityConfigurerAdapter.java index e17a023a6..24ba15ac0 100644 --- a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoWebSecurityConfigurerAdapter.java +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoWebSecurityConfigurerAdapter.java @@ -60,7 +60,7 @@ public class YudaoWebSecurityConfigurerAdapter { /** * 自定义的权限映射 Bean 们 * - * @see #configure(HttpSecurity) + * @see #filterChain(HttpSecurity) */ @Resource private List authorizeRequestsCustomizers; @@ -95,7 +95,7 @@ public class YudaoWebSecurityConfigurerAdapter { * authenticated | 用户登录后可访问 */ @Bean - protected SecurityFilterChain configure(HttpSecurity httpSecurity) throws Exception { + protected SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception { // 登出 httpSecurity // 开启跨域 @@ -116,16 +116,16 @@ public class YudaoWebSecurityConfigurerAdapter { httpSecurity // ①:全局共享规则 .authorizeRequests() - // 静态资源,可匿名访问 + // 1.1 静态资源,可匿名访问 .antMatchers(HttpMethod.GET, "/*.html", "/**/*.html", "/**/*.css", "/**/*.js").permitAll() - // 设置 @PermitAll 无需认证 + // 1.2 设置 @PermitAll 无需认证 .antMatchers(HttpMethod.GET, permitAllUrls.get(HttpMethod.GET).toArray(new String[0])).permitAll() .antMatchers(HttpMethod.POST, permitAllUrls.get(HttpMethod.POST).toArray(new String[0])).permitAll() .antMatchers(HttpMethod.PUT, permitAllUrls.get(HttpMethod.PUT).toArray(new String[0])).permitAll() .antMatchers(HttpMethod.DELETE, permitAllUrls.get(HttpMethod.DELETE).toArray(new String[0])).permitAll() - // 基于 yudao.security.permit-all-urls 无需认证 + // 1.3 基于 yudao.security.permit-all-urls 无需认证 .antMatchers(securityProperties.getPermitAllUrls().toArray(new String[0])).permitAll() - // 设置 App API 无需认证 + // 1.4 设置 App API 无需认证 .antMatchers(buildAppApi("/**")).permitAll() // ②:每个项目的自定义规则 .and().authorizeRequests(registry -> // 下面,循环设置自定义规则 @@ -135,7 +135,7 @@ public class YudaoWebSecurityConfigurerAdapter { .anyRequest().authenticated() ; - // 添加 JWT Filter + // 添加 Token Filter httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); return httpSecurity.build(); } diff --git a/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/ut/BaseDbAndRedisUnitTest.java b/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/ut/BaseDbAndRedisUnitTest.java index 1ee8dfef2..f5de235f6 100644 --- a/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/ut/BaseDbAndRedisUnitTest.java +++ b/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/ut/BaseDbAndRedisUnitTest.java @@ -8,7 +8,6 @@ import cn.iocoder.yudao.framework.test.config.SqlInitializationTestConfiguration import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure; import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration; import org.redisson.spring.starter.RedissonAutoConfiguration; -import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; @@ -41,7 +40,7 @@ public class BaseDbAndRedisUnitTest { // Redis 配置类 RedisTestConfiguration.class, // Redis 测试配置类,用于启动 RedisServer - RedisAutoConfiguration.class, // Spring Redis 自动配置类 +// RedisAutoConfiguration.class, // Spring Redis 自动配置类 YudaoRedisAutoConfiguration.class, // 自己的 Redis 配置类 RedissonAutoConfiguration.class, // Redisson 自动高配置类 }) diff --git a/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/ut/BaseDbUnitTest.java b/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/ut/BaseDbUnitTest.java index 6a9a3ffcb..316c4d52f 100644 --- a/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/ut/BaseDbUnitTest.java +++ b/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/ut/BaseDbUnitTest.java @@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.mybatis.config.YudaoMybatisAutoConfiguration; import cn.iocoder.yudao.framework.test.config.SqlInitializationTestConfiguration; import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure; import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration; +import com.github.yulichang.autoconfigure.MybatisPlusJoinAutoConfiguration; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; @@ -34,6 +35,7 @@ public class BaseDbUnitTest { // MyBatis 配置类 YudaoMybatisAutoConfiguration.class, // 自己的 MyBatis 配置类 MybatisPlusAutoConfiguration.class, // MyBatis 的自动配置类 + MybatisPlusJoinAutoConfiguration.class, // MyBatis 的Join配置类 }) public static class Application { } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/config/YudaoApiLogAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/config/YudaoApiLogAutoConfiguration.java index b6ccdfce7..6ced68756 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/config/YudaoApiLogAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/config/YudaoApiLogAutoConfiguration.java @@ -12,15 +12,13 @@ import cn.iocoder.yudao.module.infra.api.logger.ApiAccessLogApi; import cn.iocoder.yudao.module.infra.api.logger.ApiErrorLogApi; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.AutoConfiguration; -import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import javax.servlet.Filter; -@AutoConfiguration -@AutoConfigureAfter(YudaoWebAutoConfiguration.class) +@AutoConfiguration(after = YudaoWebAutoConfiguration.class) public class YudaoApiLogAutoConfiguration { @Bean diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/filter/ApiAccessLogFilter.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/filter/ApiAccessLogFilter.java index bd8085882..9eea0788d 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/filter/ApiAccessLogFilter.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/filter/ApiAccessLogFilter.java @@ -3,7 +3,6 @@ package cn.iocoder.yudao.framework.apilog.core.filter; import cn.hutool.core.date.LocalDateTimeUtil; import cn.hutool.core.exceptions.ExceptionUtil; import cn.hutool.core.map.MapUtil; -import cn.hutool.extra.servlet.ServletUtil; import cn.iocoder.yudao.framework.apilog.core.service.ApiAccessLog; import cn.iocoder.yudao.framework.apilog.core.service.ApiAccessLogFrameworkService; import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; @@ -50,8 +49,8 @@ public class ApiAccessLogFilter extends ApiRequestFilter { // 获得开始时间 LocalDateTime beginTime = LocalDateTime.now(); // 提前获得参数,避免 XssFilter 过滤处理 - Map queryString = ServletUtil.getParamMap(request); - String requestBody = ServletUtils.isJsonRequest(request) ? ServletUtil.getBody(request) : null; + Map queryString = ServletUtils.getParamMap(request); + String requestBody = ServletUtils.isJsonRequest(request) ? ServletUtils.getBody(request) : null; try { // 继续过滤器 @@ -101,7 +100,7 @@ public class ApiAccessLogFilter extends ApiRequestFilter { accessLog.setRequestParams(toJsonString(requestParams)); accessLog.setRequestMethod(request.getMethod()); accessLog.setUserAgent(ServletUtils.getUserAgent(request)); - accessLog.setUserIp(ServletUtil.getClientIP(request)); + accessLog.setUserIp(ServletUtils.getClientIP(request)); // 持续时间 accessLog.setBeginTime(beginTime); accessLog.setEndTime(LocalDateTime.now()); diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/package-info.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/package-info.java index 8c69219d0..2dc531692 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/package-info.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/package-info.java @@ -1 +1,4 @@ +/** + * Web 框架,全局异常、API 日志等 + */ package cn.iocoder.yudao.framework; diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java index 6069f8767..e47619df3 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java @@ -2,28 +2,22 @@ package cn.iocoder.yudao.framework.web.config; import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLogFrameworkService; import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum; -import cn.iocoder.yudao.framework.web.core.clean.JsoupXssCleaner; -import cn.iocoder.yudao.framework.web.core.clean.XssCleaner; import cn.iocoder.yudao.framework.web.core.filter.CacheRequestBodyFilter; import cn.iocoder.yudao.framework.web.core.filter.DemoFilter; -import cn.iocoder.yudao.framework.web.core.filter.XssFilter; import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler; import cn.iocoder.yudao.framework.web.core.handler.GlobalResponseBodyHandler; -import cn.iocoder.yudao.framework.web.core.json.XssStringJsonDeserializer; import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; -import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.AutoConfiguration; -import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; +import org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.util.AntPathMatcher; -import org.springframework.util.PathMatcher; import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.client.RestTemplate; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.CorsFilter; @@ -34,7 +28,7 @@ import javax.annotation.Resource; import javax.servlet.Filter; @AutoConfiguration -@EnableConfigurationProperties({WebProperties.class, XssProperties.class}) +@EnableConfigurationProperties(WebProperties.class) public class YudaoWebAutoConfiguration implements WebMvcConfigurer { @Resource @@ -107,15 +101,6 @@ public class YudaoWebAutoConfiguration implements WebMvcConfigurer { return createFilterBean(new CacheRequestBodyFilter(), WebFilterOrderEnum.REQUEST_BODY_CACHE_FILTER); } - /** - * 创建 XssFilter Bean,解决 Xss 安全问题 - */ - @Bean - @ConditionalOnBean(XssCleaner.class) - public FilterRegistrationBean xssFilter(XssProperties properties, PathMatcher pathMatcher, XssCleaner xssCleaner) { - return createFilterBean(new XssFilter(properties, pathMatcher, xssCleaner), WebFilterOrderEnum.XSS_FILTER); - } - /** * 创建 DemoFilter Bean,演示模式 */ @@ -125,37 +110,19 @@ public class YudaoWebAutoConfiguration implements WebMvcConfigurer { return createFilterBean(new DemoFilter(), WebFilterOrderEnum.DEMO_FILTER); } - - /** - * Xss 清理者 - * - * @return XssCleaner - */ - @ConditionalOnMissingBean(XssCleaner.class) - @Bean - public XssCleaner xssCleaner() { - return new JsoupXssCleaner(); - } - - /** - * 注册 Jackson 的序列化器,用于处理 json 类型参数的 xss 过滤 - * - * @return Jackson2ObjectMapperBuilderCustomizer - */ - @Bean - @ConditionalOnMissingBean(name = "xssJacksonCustomizer") - @ConditionalOnBean(ObjectMapper.class) - @ConditionalOnProperty(value = "yudao.xss.enable", havingValue = "true") - public Jackson2ObjectMapperBuilderCustomizer xssJacksonCustomizer(XssCleaner xssCleaner) { - // 在反序列化时进行 xss 过滤,可以替换使用 XssStringJsonSerializer,在序列化时进行处理 - return builder -> builder.deserializerByType(String.class, new XssStringJsonDeserializer(xssCleaner)); - } - - - private static FilterRegistrationBean createFilterBean(T filter, Integer order) { + public static FilterRegistrationBean createFilterBean(T filter, Integer order) { FilterRegistrationBean bean = new FilterRegistrationBean<>(filter); bean.setOrder(order); return bean; } + /** + * 创建 RestTemplate 实例 + * + * @param restTemplateBuilder {@link RestTemplateAutoConfiguration#restTemplateBuilder} + */ + @Bean + public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder) { + return restTemplateBuilder.build(); + } } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/XssProperties.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/config/XssProperties.java similarity index 92% rename from yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/XssProperties.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/config/XssProperties.java index e4d123089..c914b0465 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/XssProperties.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/config/XssProperties.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.web.config; +package cn.iocoder.yudao.framework.xss.config; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/config/YudaoXssAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/config/YudaoXssAutoConfiguration.java new file mode 100644 index 000000000..d5d892c07 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/config/YudaoXssAutoConfiguration.java @@ -0,0 +1,60 @@ +package cn.iocoder.yudao.framework.xss.config; + +import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum; +import cn.iocoder.yudao.framework.xss.core.clean.JsoupXssCleaner; +import cn.iocoder.yudao.framework.xss.core.clean.XssCleaner; +import cn.iocoder.yudao.framework.xss.core.filter.XssFilter; +import cn.iocoder.yudao.framework.xss.core.json.XssStringJsonDeserializer; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.util.PathMatcher; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +import static cn.iocoder.yudao.framework.web.config.YudaoWebAutoConfiguration.createFilterBean; + +@AutoConfiguration +@EnableConfigurationProperties(XssProperties.class) +public class YudaoXssAutoConfiguration implements WebMvcConfigurer { + + /** + * Xss 清理者 + * + * @return XssCleaner + */ + @Bean + @ConditionalOnMissingBean(XssCleaner.class) + public XssCleaner xssCleaner() { + return new JsoupXssCleaner(); + } + + /** + * 注册 Jackson 的序列化器,用于处理 json 类型参数的 xss 过滤 + * + * @return Jackson2ObjectMapperBuilderCustomizer + */ + @Bean + @ConditionalOnMissingBean(name = "xssJacksonCustomizer") + @ConditionalOnBean(ObjectMapper.class) + @ConditionalOnProperty(value = "yudao.xss.enable", havingValue = "true") + public Jackson2ObjectMapperBuilderCustomizer xssJacksonCustomizer(XssCleaner xssCleaner) { + // 在反序列化时进行 xss 过滤,可以替换使用 XssStringJsonSerializer,在序列化时进行处理 + return builder -> builder.deserializerByType(String.class, new XssStringJsonDeserializer(xssCleaner)); + } + + /** + * 创建 XssFilter Bean,解决 Xss 安全问题 + */ + @Bean + @ConditionalOnBean(XssCleaner.class) + public FilterRegistrationBean xssFilter(XssProperties properties, PathMatcher pathMatcher, XssCleaner xssCleaner) { + return createFilterBean(new XssFilter(properties, pathMatcher, xssCleaner), WebFilterOrderEnum.XSS_FILTER); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/clean/JsoupXssCleaner.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/clean/JsoupXssCleaner.java similarity index 84% rename from yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/clean/JsoupXssCleaner.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/clean/JsoupXssCleaner.java index 559267c3f..4cbc907b9 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/clean/JsoupXssCleaner.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/clean/JsoupXssCleaner.java @@ -1,11 +1,11 @@ -package cn.iocoder.yudao.framework.web.core.clean; +package cn.iocoder.yudao.framework.xss.core.clean; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.safety.Safelist; /** - * jsonp 过滤字符串 + * 基于 JSONP 实现 XSS 过滤字符串 */ public class JsoupXssCleaner implements XssCleaner { @@ -24,21 +24,6 @@ public class JsoupXssCleaner implements XssCleaner { this.baseUri = ""; } - public JsoupXssCleaner(Safelist safelist) { - this.safelist = safelist; - this.baseUri = ""; - } - - public JsoupXssCleaner(String baseUri) { - this.safelist = buildSafelist(); - this.baseUri = baseUri; - } - - public JsoupXssCleaner(Safelist safelist, String baseUri) { - this.safelist = safelist; - this.baseUri = baseUri; - } - /** * 构建一个 Xss 清理的 Safelist 规则。 * 基于 Safelist#relaxed() 的基础上: @@ -67,7 +52,6 @@ public class JsoupXssCleaner implements XssCleaner { // 虽然可以重写 WhiteList#isSafeAttribute 来处理,但是有隐患,所以暂时不支持相对路径 // WHITELIST.removeProtocols("a", "href", "ftp", "http", "https", "mailto"); // WHITELIST.removeProtocols("img", "src", "http", "https"); - return relaxedSafelist; } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/clean/XssCleaner.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/clean/XssCleaner.java similarity index 83% rename from yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/clean/XssCleaner.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/clean/XssCleaner.java index 433f7e775..529bc64a2 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/clean/XssCleaner.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/clean/XssCleaner.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.web.core.clean; +package cn.iocoder.yudao.framework.xss.core.clean; /** * 对 html 文本中的有 Xss 风险的数据进行清理 @@ -12,4 +12,5 @@ public interface XssCleaner { * @return 清理后的 html */ String clean(String html); + } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/XssFilter.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/filter/XssFilter.java similarity index 80% rename from yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/XssFilter.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/filter/XssFilter.java index 2da18768d..5f2ce6e3d 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/XssFilter.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/filter/XssFilter.java @@ -1,7 +1,7 @@ -package cn.iocoder.yudao.framework.web.core.filter; +package cn.iocoder.yudao.framework.xss.core.filter; -import cn.iocoder.yudao.framework.web.config.XssProperties; -import cn.iocoder.yudao.framework.web.core.clean.XssCleaner; +import cn.iocoder.yudao.framework.xss.config.XssProperties; +import cn.iocoder.yudao.framework.xss.core.clean.XssCleaner; import lombok.AllArgsConstructor; import org.springframework.util.PathMatcher; import org.springframework.web.filter.OncePerRequestFilter; @@ -14,8 +14,6 @@ import java.io.IOException; /** * Xss 过滤器 - *

- * 对 Xss 不了解的胖友,可以看看 http://www.iocoder.cn/Fight/The-new-girl-asked-me-why-AJAX-requests-are-not-secure-I-did-not-answer/ * * @author 芋道源码 */ diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/XssRequestWrapper.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/filter/XssRequestWrapper.java similarity index 95% rename from yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/XssRequestWrapper.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/filter/XssRequestWrapper.java index 9118229e3..1466a97cc 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/XssRequestWrapper.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/filter/XssRequestWrapper.java @@ -1,6 +1,6 @@ -package cn.iocoder.yudao.framework.web.core.filter; +package cn.iocoder.yudao.framework.xss.core.filter; -import cn.iocoder.yudao.framework.web.core.clean.XssCleaner; +import cn.iocoder.yudao.framework.xss.core.clean.XssCleaner; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; @@ -13,6 +13,7 @@ import java.util.Map; * @author 芋道源码 */ public class XssRequestWrapper extends HttpServletRequestWrapper { + private final XssCleaner xssCleaner; public XssRequestWrapper(HttpServletRequest request, XssCleaner xssCleaner) { diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/json/XssStringJsonDeserializer.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/json/XssStringJsonDeserializer.java similarity index 94% rename from yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/json/XssStringJsonDeserializer.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/json/XssStringJsonDeserializer.java index 7e1f631c7..2b1725d96 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/json/XssStringJsonDeserializer.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/json/XssStringJsonDeserializer.java @@ -1,6 +1,6 @@ -package cn.iocoder.yudao.framework.web.core.json; +package cn.iocoder.yudao.framework.xss.core.json; -import cn.iocoder.yudao.framework.web.core.clean.XssCleaner; +import cn.iocoder.yudao.framework.xss.core.clean.XssCleaner; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.databind.DeserializationContext; diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/package-info.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/package-info.java new file mode 100644 index 000000000..c6e46f070 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/package-info.java @@ -0,0 +1,6 @@ +/** + * 针对 XSS 的基础封装 + * + * XSS 说明:https://tech.meituan.com/2018/09/27/fe-security.html + */ +package cn.iocoder.yudao.framework.xss; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.java index 74b2ceb34..57d601f6d 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.java @@ -4,16 +4,15 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*; import cn.iocoder.yudao.module.bpm.service.task.BpmTaskService; -import io.swagger.v3.oas.annotations.tags.Tag; -import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import javax.validation.Valid; - import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java index 32f2b942d..aa140fdd9 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java @@ -56,8 +56,8 @@ public interface BpmTaskConvert { } default List convertList2(List tasks, - Map bpmTaskExtDOMap, Map historicProcessInstanceMap, - Map userMap) { + Map bpmTaskExtDOMap, Map historicProcessInstanceMap, + Map userMap) { return CollectionUtils.convertList(tasks, task -> { BpmTaskDonePageItemRespVO respVO = convert2(task); BpmTaskExtDO taskExtDO = bpmTaskExtDOMap.get(task.getId()); @@ -74,10 +74,10 @@ public interface BpmTaskConvert { BpmTaskDonePageItemRespVO convert2(HistoricTaskInstance bean); @Mappings({@Mapping(source = "processInstance.id", target = "id"), - @Mapping(source = "processInstance.name", target = "name"), - @Mapping(source = "processInstance.startUserId", target = "startUserId"), - @Mapping(source = "processInstance.processDefinitionId", target = "processDefinitionId"), - @Mapping(source = "startUser.nickname", target = "startUserNickname")}) + @Mapping(source = "processInstance.name", target = "name"), + @Mapping(source = "processInstance.startUserId", target = "startUserId"), + @Mapping(source = "processInstance.processDefinitionId", target = "processDefinitionId"), + @Mapping(source = "startUser.nickname", target = "startUserNickname")}) BpmTaskTodoPageItemRespVO.ProcessInstance convert(ProcessInstance processInstance, AdminUserRespDTO startUser); default List convertList3(List tasks, @@ -114,28 +114,28 @@ public interface BpmTaskConvert { void copyTo(BpmTaskExtDO from, @MappingTarget BpmTaskDonePageItemRespVO to); @Mappings({@Mapping(source = "processInstance.id", target = "id"), - @Mapping(source = "processInstance.name", target = "name"), - @Mapping(source = "processInstance.startUserId", target = "startUserId"), - @Mapping(source = "processInstance.processDefinitionId", target = "processDefinitionId"), - @Mapping(source = "startUser.nickname", target = "startUserNickname")}) + @Mapping(source = "processInstance.name", target = "name"), + @Mapping(source = "processInstance.startUserId", target = "startUserId"), + @Mapping(source = "processInstance.processDefinitionId", target = "processDefinitionId"), + @Mapping(source = "startUser.nickname", target = "startUserNickname")}) BpmTaskTodoPageItemRespVO.ProcessInstance convert(HistoricProcessInstance processInstance, - AdminUserRespDTO startUser); + AdminUserRespDTO startUser); default BpmTaskExtDO convert2TaskExt(Task task) { BpmTaskExtDO taskExtDO = new BpmTaskExtDO().setTaskId(task.getId()) - .setAssigneeUserId(NumberUtils.parseLong(task.getAssignee())).setName(task.getName()) - .setProcessDefinitionId(task.getProcessDefinitionId()).setProcessInstanceId(task.getProcessInstanceId()); + .setAssigneeUserId(NumberUtils.parseLong(task.getAssignee())).setName(task.getName()) + .setProcessDefinitionId(task.getProcessDefinitionId()).setProcessInstanceId(task.getProcessInstanceId()); taskExtDO.setCreateTime(LocalDateTimeUtil.of(task.getCreateTime())); return taskExtDO; } default BpmMessageSendWhenTaskCreatedReqDTO convert(ProcessInstance processInstance, AdminUserRespDTO startUser, - Task task) { + Task task) { BpmMessageSendWhenTaskCreatedReqDTO reqDTO = new BpmMessageSendWhenTaskCreatedReqDTO(); reqDTO.setProcessInstanceId(processInstance.getProcessInstanceId()) - .setProcessInstanceName(processInstance.getName()).setStartUserId(startUser.getId()) - .setStartUserNickname(startUser.getNickname()).setTaskId(task.getId()).setTaskName(task.getName()) - .setAssigneeUserId(NumberUtils.parseLong(task.getAssignee())); + .setProcessInstanceName(processInstance.getName()).setStartUserId(startUser.getId()) + .setStartUserNickname(startUser.getNickname()).setTaskId(task.getId()).setTaskName(task.getName()) + .setAssigneeUserId(NumberUtils.parseLong(task.getAssignee())); return reqDTO; } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java index 3b569d625..b8cdf7209 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java @@ -135,7 +135,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService // 获得流程定义 ProcessDefinition processDefinition = processDefinitionService - .getProcessDefinition(processInstance.getProcessDefinitionId()); + .getProcessDefinition(processInstance.getProcessDefinitionId()); Assert.notNull(processDefinition, "流程定义({}) 不存在", processInstance.getProcessDefinitionId()); BpmProcessDefinitionExtDO processDefinitionExt = processDefinitionService.getProcessDefinitionExt( processInstance.getProcessDefinitionId()); diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileConfigController.http b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileConfigController.http index 61dede43f..499f64df7 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileConfigController.http +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileConfigController.http @@ -1,5 +1,5 @@ ### 请求 /infra/file-config/create 接口 => 成功 -POST {{infaBaseUrl}}/infra/file-config/create +POST {{baseUrl}}/infra/file-config/create Content-Type: application/json tenant-id: {{adminTenentId}} Authorization: Bearer {{token}} @@ -19,7 +19,7 @@ Authorization: Bearer {{token}} } ### 请求 /infra/file-config/update 接口 => 成功 -PUT {{infaBaseUrl}}/infra/file-config/update +PUT {{baseUrl}}/infra/file-config/update Content-Type: application/json tenant-id: {{adminTenentId}} Authorization: Bearer {{token}} @@ -39,7 +39,7 @@ Authorization: Bearer {{token}} } ### 请求 /infra/file-config/test 接口 => 成功 -GET {{infaBaseUrl}}/infra/file-config/test?id=2 +GET {{baseUrl}}/infra/file-config/test?id=2 Content-Type: application/json tenant-id: {{adminTenentId}} Authorization: Bearer {{token}} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogExportReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogExportReqVO.java index c618d2f5c..792f2d7c0 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogExportReqVO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogExportReqVO.java @@ -1,6 +1,5 @@ package cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apierrorlog; -import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import org.springframework.format.annotation.DateTimeFormat; @@ -9,7 +8,7 @@ import java.time.LocalDateTime; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -@Schema(description = "管理后台 - API 错误日志 Excel 导出 Request VO,参数和 ApiErrorLogPageReqVO 是一致的") +@Schema(description = "管理后台 - API 错误日志 Excel 导出 Request VO,参数和 ApiErrorLogPageReqVO 是一致的") @Data public class ApiErrorLogExportReqVO { @@ -32,4 +31,4 @@ public class ApiErrorLogExportReqVO { @Schema(description = "处理状态", example = "0") private Integer processStatus; -} \ No newline at end of file +} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/redis/RedisController.http b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/redis/RedisController.http index e59cd4eb1..0310dea58 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/redis/RedisController.http +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/redis/RedisController.http @@ -1,9 +1,9 @@ ### 请求 /infra/redis/get-monitor-info 接口 => 成功 -GET {{infaBaseUrl}}/infra/redis/get-monitor-info +GET {{baseUrl}}/infra/redis/get-monitor-info Authorization: Bearer {{token}} tenant-id: {{adminTenentId}} ### 请求 /infra/redis/get-key-list 接口 => 成功 -GET {{infaBaseUrl}}/infra/redis/get-key-list +GET {{baseUrl}}/infra/redis/get-key-list Authorization: Bearer {{token}} tenant-id: {{adminTenentId}} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/TestDemoController.http b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/TestDemoController.http index 499f64df7..ed65d0b86 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/TestDemoController.http +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/TestDemoController.http @@ -1,45 +1,19 @@ -### 请求 /infra/file-config/create 接口 => 成功 -POST {{baseUrl}}/infra/file-config/create -Content-Type: application/json -tenant-id: {{adminTenentId}} +### 请求 /infra/test-demo/get 接口 => 成功 +GET {{baseUrl}}/infra/test-demo/get?id=106 Authorization: Bearer {{token}} +tenant-id: {{adminTenentId}} + +### 请求 /infra/test-demo/update 接口 => 成功 +PUT {{baseUrl}}/infra/test-demo/update +Authorization: Bearer {{token}} +tenant-id: {{adminTenentId}} +Content-Type: application/json + { - "name": "S3 - 七牛云", - "remark": "", - "storage": 20, - "config": { - "accessKey": "b7yvuhBSAGjmtPhMFcn9iMOxUOY_I06cA_p0ZUx8", - "accessSecret": "kXM1l5ia1RvSX3QaOEcwI3RLz3Y2rmNszWonKZtP", - "bucket": "ruoyi-vue-pro", - "endpoint": "s3-cn-south-1.qiniucs.com", - "domain": "http://test.yudao.iocoder.cn", - "region": "oss-cn-beijing" - } + "id": 106, + "name": "测试", + "status": "0", + "type": 1, + "category": 1 } - -### 请求 /infra/file-config/update 接口 => 成功 -PUT {{baseUrl}}/infra/file-config/update -Content-Type: application/json -tenant-id: {{adminTenentId}} -Authorization: Bearer {{token}} - -{ - "id": 2, - "name": "S3 - 七牛云", - "remark": "", - "config": { - "accessKey": "b7yvuhBSAGjmtPhMFcn9iMOxUOY_I06cA_p0ZUx8", - "accessSecret": "kXM1l5ia1RvSX3QaOEcwI3RLz3Y2rmNszWonKZtP", - "bucket": "ruoyi-vue-pro", - "endpoint": "s3-cn-south-1.qiniucs.com", - "domain": "http://test.yudao.iocoder.cn", - "region": "oss-cn-beijing" - } -} - -### 请求 /infra/file-config/test 接口 => 成功 -GET {{baseUrl}}/infra/file-config/test?id=2 -Content-Type: application/json -tenant-id: {{adminTenentId}} -Authorization: Bearer {{token}} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.http b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.http index 4a869ff3f..c2715634e 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.http +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.http @@ -1,8 +1,7 @@ ### 请求 /login 接口 => 成功 -POST {{systemBaseUrl}}/system/auth/login +POST {{baseUrl}}/system/auth/login Content-Type: application/json tenant-id: {{adminTenentId}} -tag: {{tag}} { "username": "admin", @@ -12,7 +11,7 @@ tag: {{tag}} } ### 请求 /login 接口 => 成功(无验证码) -POST {{systemBaseUrl}}/system/auth/login +POST {{baseUrl}}/system/auth/login Content-Type: application/json tenant-id: {{adminTenentId}} @@ -22,12 +21,12 @@ tenant-id: {{adminTenentId}} } ### 请求 /get-permission-info 接口 => 成功 -GET {{systemBaseUrl}}/system/auth/get-permission-info +GET {{baseUrl}}/system/auth/get-permission-info Authorization: Bearer {{token}} tenant-id: {{adminTenentId}} ### 请求 /list-menus 接口 => 成功 -GET {{systemBaseUrl}}/system/auth/list-menus -#Authorization: Bearer {{token}} -Authorization: Bearer c347026e805e4d99b0d116eae66eda8c +GET {{baseUrl}}/system/list-menus +Authorization: Bearer {{token}} +#Authorization: Bearer a6aa7714a2e44c95aaa8a2c5adc2a67a tenant-id: {{adminTenentId}} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthLoginReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthLoginReqVO.java index 0c200647b..7b2629c93 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthLoginReqVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthLoginReqVO.java @@ -14,7 +14,7 @@ import javax.validation.constraints.AssertTrue; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.Pattern; -@Schema(description = "管理后台 - 账号密码登录 Request VO,如果登录并绑定社交用户,需要传递 social 开头的参数") +@Schema(description = "管理后台 - 账号密码登录 Request VO,如果登录并绑定社交用户,需要传递 social 开头的参数") @Data @NoArgsConstructor @AllArgsConstructor @@ -34,7 +34,7 @@ public class AuthLoginReqVO { // ========== 图片验证码相关 ========== - @Schema(description = "验证码,验证码开启时,需要传递", requiredMode = Schema.RequiredMode.REQUIRED, + @Schema(description = "验证码,验证码开启时,需要传递", requiredMode = Schema.RequiredMode.REQUIRED, example = "PfcH6mgr8tpXuMWFjvW6YVaqrswIuwmWI5dsVZSg7sGpWtDCUbHuDEXl3cFB1+VvCC/rAkSwK8Fad52FSuncVg==") @NotEmpty(message = "验证码不能为空", groups = CodeEnableGroup.class) private String captchaVerification; @@ -54,8 +54,7 @@ public class AuthLoginReqVO { /** * 开启验证码的 Group */ - public interface CodeEnableGroup { - } + public interface CodeEnableGroup {} @AssertTrue(message = "授权码不能为空") public boolean isSocialCodeValid() { diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthPermissionInfoRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthPermissionInfoRespVO.java index 94367ad3f..d22765cbe 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthPermissionInfoRespVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthPermissionInfoRespVO.java @@ -1,6 +1,5 @@ package cn.iocoder.yudao.module.system.controller.admin.auth.vo; -import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Builder; @@ -38,7 +37,7 @@ public class AuthPermissionInfoRespVO { @Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道源码") private String nickname; - @Schema(description = "用户头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "http://www.iocoder.cn/xx.jpg") + @Schema(description = "用户头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.jpg") private String avatar; } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/ip/AreaController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/ip/AreaController.java index 055dd5640..b3bc0c03c 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/ip/AreaController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/ip/AreaController.java @@ -6,17 +6,17 @@ import cn.iocoder.yudao.framework.ip.core.Area; import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils; import cn.iocoder.yudao.framework.ip.core.utils.IPUtils; import cn.iocoder.yudao.module.system.controller.admin.ip.vo.AreaNodeRespVO; +import cn.iocoder.yudao.module.system.controller.admin.ip.vo.AreaNodeSimpleRespVO; import cn.iocoder.yudao.module.system.convert.ip.AreaConvert; -import io.swagger.v3.oas.annotations.tags.Tag; -import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; +import java.util.ArrayList; import java.util.List; +import java.util.Set; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; @@ -34,6 +34,28 @@ public class AreaController { return success(AreaConvert.INSTANCE.convertList(area.getChildren())); } + @GetMapping("/get-children") + @Operation(summary = "获得地区的下级区域") + @Parameter(name = "id", description = "区域编号", required = true, example = "150000") + public CommonResult> getChildren(@RequestParam("id") Integer id) { + Area area = AreaUtils.getArea(id); + Assert.notNull(area, String.format("获取不到 id : %d 的区域", id)); + return success(AreaConvert.INSTANCE.convertList2(area.getChildren())); + } + + // 4)方法改成 getAreaChildrenList 获得子节点们;5)url 可以已改成 children-list + //@芋艿 是不是叫 getAreaListByIds 更合适。 因为不一定是子节点。 用于前端树选择获取缓存数据。 见 + @GetMapping("/get-by-ids") + @Operation(summary = "通过区域 ids 获得地区列表") + @Parameter(name = "ids", description = "区域编号 ids", required = true, example = "1,150000") + public CommonResult> getAreaListByIds(@RequestParam("ids") Set ids) { + List areaList = new ArrayList<>(ids.size()); + for (Integer areaId : ids) { + areaList.add(AreaUtils.getArea(areaId)); + } + return success(AreaConvert.INSTANCE.convertList2(areaList)); + } + @GetMapping("/get-by-ip") @Operation(summary = "获得 IP 对应的地区名") @Parameter(name = "ip", description = "IP", required = true) diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/ip/vo/AreaNodeRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/ip/vo/AreaNodeRespVO.java index ec3bf8181..1360ec66d 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/ip/vo/AreaNodeRespVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/ip/vo/AreaNodeRespVO.java @@ -1,6 +1,5 @@ package cn.iocoder.yudao.module.system.controller.admin.ip.vo; -import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/ip/vo/AreaNodeSimpleRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/ip/vo/AreaNodeSimpleRespVO.java new file mode 100644 index 000000000..a37430248 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/ip/vo/AreaNodeSimpleRespVO.java @@ -0,0 +1,19 @@ +package cn.iocoder.yudao.module.system.controller.admin.ip.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "管理后台 - 简洁的地区节点 Response VO") +@Data +public class AreaNodeSimpleRespVO { + + @Schema(description = "编号", required = true, example = "110000") + private Integer id; + + @Schema(description = "名字", required = true, example = "北京") + private String name; + + @Schema(description = "是否叶子节点", required = false, example = "false") + private Boolean leaf; + +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/vo/template/NotifyTemplateBaseVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/vo/template/NotifyTemplateBaseVO.java index 8bc791b7e..72b995ad1 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/vo/template/NotifyTemplateBaseVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/vo/template/NotifyTemplateBaseVO.java @@ -9,9 +9,9 @@ import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; /** -* 站内信模版 Base VO,提供给添加、修改、详细的子 VO 使用 -* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 -*/ + * 站内信模版 Base VO,提供给添加、修改、详细的子 VO 使用 + * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 + */ @Data public class NotifyTemplateBaseVO { diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/user/OAuth2UserInfoRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/user/OAuth2UserInfoRespVO.java index 05fee95bc..69a905d2c 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/user/OAuth2UserInfoRespVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/user/OAuth2UserInfoRespVO.java @@ -1,6 +1,5 @@ package cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.user; -import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Data; @@ -17,7 +16,7 @@ public class OAuth2UserInfoRespVO { @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private Long id; - @Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") + @Schema(description = "用户账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") private String username; @Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道") diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/RoleController.http b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/RoleController.http index de109ea28..c68b86b75 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/RoleController.http +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/RoleController.http @@ -31,7 +31,7 @@ tenant-id: {{adminTenentId}} roleId=14 ### /role/get 成功 -GET {{systemBaseUrl}}/system/role/get?id=100 +GET {{baseUrl}}/system/role/get?id=100 Content-Type: application/x-www-form-urlencoded Authorization: Bearer {{token}} tenant-id: {{adminTenentId}} @@ -40,6 +40,3 @@ tenant-id: {{adminTenentId}} GET {{baseUrl}}/system/role/page?pageNo=1&pageSize=10 Authorization: Bearer {{token}} tenant-id: {{adminTenentId}} - -### - diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/permission/PermissionAssignUserRoleReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/permission/PermissionAssignUserRoleReqVO.java index e28651795..9ca43f943 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/permission/PermissionAssignUserRoleReqVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/permission/PermissionAssignUserRoleReqVO.java @@ -1,6 +1,5 @@ package cn.iocoder.yudao.module.system.controller.admin.permission.vo.permission; -import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -12,8 +11,8 @@ import java.util.Set; @Data public class PermissionAssignUserRoleReqVO { - @Schema(description = "角色编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "角色编号不能为空") + @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "用户编号不能为空") private Long userId; @Schema(description = "角色编号列表", example = "1,3,5") diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/SmsTemplateController.http b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/SmsTemplateController.http index 8661a80d9..e8213e5cd 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/SmsTemplateController.http +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/SmsTemplateController.http @@ -1,5 +1,5 @@ ### 请求 /system/sms-template/send-sms 接口 => 成功 -POST {{systemBaseUrl}}/system/sms-template/send-sms +POST {{baseUrl}}/system/sms-template/send-sms Authorization: Bearer {{token}} Content-Type: application/json tenant-id: {{adminTenentId}} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/log/SmsLogPageReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/log/SmsLogPageReqVO.java index d61597b66..fbf9dcfae 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/log/SmsLogPageReqVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/log/SmsLogPageReqVO.java @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.system.controller.admin.sms.vo.log; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; @@ -31,14 +30,14 @@ public class SmsLogPageReqVO extends PageParam { private Integer sendStatus; @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - @Schema(description = "开始发送时间") + @Schema(description = "发送时间") private LocalDateTime[] sendTime; - @Schema(description = "接收状态,参见 SmsSendStatusEnum 枚举类", example = "0") + @Schema(description = "接收状态,参见 SmsReceiveStatusEnum 枚举类", example = "0") private Integer receiveStatus; @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - @Schema(description = "开始接收时间") + @Schema(description = "接收时间") private LocalDateTime[] receiveTime; } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserExportReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserExportReqVO.java index a2433c6df..f74771121 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserExportReqVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserExportReqVO.java @@ -1,6 +1,5 @@ package cn.iocoder.yudao.module.system.controller.admin.user.vo.user; -import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Data; @@ -26,11 +25,11 @@ public class UserExportReqVO { @Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1") private Integer status; - @Schema(description = "创建时间", example = "[2022-07-01 00:00:00, 2022-07-01 23:59:59]") + @Schema(description = "创建时间", example = "[2022-07-01 00:00:00,2022-07-01 23:59:59]") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) private LocalDateTime[] createTime; @Schema(description = "部门编号,同时筛选子部门", example = "1024") private Long deptId; -} \ No newline at end of file +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserPageItemRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserPageItemRespVO.java index e3fb9b6d2..3c01ca9bb 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserPageItemRespVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserPageItemRespVO.java @@ -1,6 +1,5 @@ package cn.iocoder.yudao.module.system.controller.admin.user.vo.user; -import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Data; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserSimpleRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserSimpleRespVO.java index f2fef15c3..f021d7213 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserSimpleRespVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserSimpleRespVO.java @@ -1,12 +1,11 @@ package cn.iocoder.yudao.module.system.controller.admin.user.vo.user; -import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; -@Schema(description = "用户精简信息 Response VO") +@Schema(description = "管理后台 - 用户精简信息 Response VO") @Data @NoArgsConstructor @AllArgsConstructor diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserUpdateStatusReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserUpdateStatusReqVO.java index 2cea65c23..e5a113e18 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserUpdateStatusReqVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserUpdateStatusReqVO.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.system.controller.admin.user.vo.user; -import io.swagger.v3.oas.annotations.media.Schema; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.validation.InEnum; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -16,7 +17,7 @@ public class UserUpdateStatusReqVO { @Schema(description = "状态,见 CommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @NotNull(message = "状态不能为空") -// @InEnum(value = CommonStatusEnum.class, message = "修改状态必须是 {value}") + @InEnum(value = CommonStatusEnum.class, message = "修改状态必须是 {value}") private Integer status; } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/app/ip/AppAreaController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/app/ip/AppAreaController.java new file mode 100644 index 000000000..98260a34d --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/app/ip/AppAreaController.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.system.controller.app.ip; + +import cn.hutool.core.lang.Assert; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.ip.core.Area; +import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils; +import cn.iocoder.yudao.module.system.controller.app.ip.vo.AppAreaNodeRespVO; +import cn.iocoder.yudao.module.system.convert.ip.AreaConvert; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "用户 App - 地区") +@RestController +@RequestMapping("/system/area") +@Validated +public class AppAreaController { + + @GetMapping("/tree") + @Operation(summary = "获得地区树") + public CommonResult> getAreaTree() { + Area area = AreaUtils.getArea(Area.ID_CHINA); + Assert.notNull(area, "获取不到中国"); + return success(AreaConvert.INSTANCE.convertList3(area.getChildren())); + } + +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/app/ip/vo/AppAreaNodeRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/app/ip/vo/AppAreaNodeRespVO.java new file mode 100644 index 000000000..f6ca4a82b --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/app/ip/vo/AppAreaNodeRespVO.java @@ -0,0 +1,23 @@ +package cn.iocoder.yudao.module.system.controller.app.ip.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.List; + +@Schema(description = "用户 App - 地区节点 Response VO") +@Data +public class AppAreaNodeRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "110000") + private Integer id; + + @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "北京") + private String name; + + /** + * 子节点 + */ + private List children; + +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/auth/AuthConvert.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/auth/AuthConvert.java index d54a2f026..a9a48fdfc 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/auth/AuthConvert.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/auth/AuthConvert.java @@ -27,10 +27,10 @@ public interface AuthConvert { default AuthPermissionInfoRespVO convert(AdminUserDO user, List roleList, List menuList) { return AuthPermissionInfoRespVO.builder() - .user(AuthPermissionInfoRespVO.UserVO.builder().id(user.getId()).nickname(user.getNickname()).avatar(user.getAvatar()).build()) - .roles(convertSet(roleList, RoleDO::getCode)) - .permissions(convertSet(menuList, MenuDO::getPermission)) - .build(); + .user(AuthPermissionInfoRespVO.UserVO.builder().id(user.getId()).nickname(user.getNickname()).avatar(user.getAvatar()).build()) + .roles(convertSet(roleList, RoleDO::getCode)) + .permissions(convertSet(menuList, MenuDO::getPermission)) + .build(); } AuthMenuRespVO convertTreeNode(MenuDO menu); diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/ip/AreaConvert.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/ip/AreaConvert.java index 0cedf8785..4ffa374e7 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/ip/AreaConvert.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/ip/AreaConvert.java @@ -1,11 +1,16 @@ package cn.iocoder.yudao.module.system.convert.ip; import cn.iocoder.yudao.framework.ip.core.Area; +import cn.iocoder.yudao.framework.ip.core.enums.AreaTypeEnum; import cn.iocoder.yudao.module.system.controller.admin.ip.vo.AreaNodeRespVO; +import cn.iocoder.yudao.module.system.controller.admin.ip.vo.AreaNodeSimpleRespVO; +import cn.iocoder.yudao.module.system.controller.app.ip.vo.AppAreaNodeRespVO; import org.mapstruct.Mapper; +import org.mapstruct.Mapping; import org.mapstruct.factory.Mappers; import java.util.List; +import java.util.Objects; @Mapper public interface AreaConvert { @@ -14,4 +19,15 @@ public interface AreaConvert { List convertList(List list); + List convertList2(List list); + + @Mapping(source = "type", target = "leaf") + AreaNodeSimpleRespVO convert(Area area); + + default Boolean convertAreaType(Integer type) { + return Objects.equals(AreaTypeEnum.DISTRICT.getType(), type); + } + + List convertList3(List list); + } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dept/DeptServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dept/DeptServiceImpl.java index 441c7bf60..8dc52fdf8 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dept/DeptServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dept/DeptServiceImpl.java @@ -140,9 +140,9 @@ public class DeptServiceImpl implements DeptService { } List result = new ArrayList<>(); // 递归,简单粗暴 - getDeptsByParentIdFromCache(result, parentId, - recursive ? Integer.MAX_VALUE : 1, // 如果递归获取,则无限;否则,只递归 1 次 - parentDeptCache); + getDeptsByParentIdFromCache(result, parentId, + recursive ? Integer.MAX_VALUE : 1, // 如果递归获取,则无限;否则,只递归 1 次 + parentDeptCache); return result; } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/MenuServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/MenuServiceImpl.java index b0481abef..06e1355b0 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/MenuServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/MenuServiceImpl.java @@ -185,7 +185,7 @@ public class MenuServiceImpl implements MenuService { } // 创建新数组,避免缓存被修改 return menuCache.values().stream().filter(menu -> menuTypes.contains(menu.getType()) - && menusStatuses.contains(menu.getStatus())) + && menusStatuses.contains(menu.getStatus())) .collect(Collectors.toList()); } @@ -238,7 +238,7 @@ public class MenuServiceImpl implements MenuService { } // 父菜单必须是目录或者菜单类型 if (!MenuTypeEnum.DIR.getType().equals(menu.getType()) - && !MenuTypeEnum.MENU.getType().equals(menu.getType())) { + && !MenuTypeEnum.MENU.getType().equals(menu.getType())) { throw exception(MENU_PARENT_NOT_DIR_OR_MENU); } } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceImpl.java index a3f2c70a3..30ac2daa0 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceImpl.java @@ -171,8 +171,8 @@ public class RoleServiceImpl implements RoleService { @Override public List getRoleListByStatus(@Nullable Collection statuses) { if (CollUtil.isEmpty(statuses)) { - return roleMapper.selectList(); - } + return roleMapper.selectList(); + } return roleMapper.selectListByStatus(statuses); } diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImplTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImplTest.java index 9861b912c..b0331cff2 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImplTest.java @@ -349,8 +349,9 @@ public class AdminAuthServiceImplTest extends BaseDbUnitTest { // 调用 authService.logout(token, LoginLogTypeEnum.LOGOUT_SELF.getType()); // 校验调用参数 - verify(loginLogService).createLoginLog(argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGOUT_SELF.getType()) - && o.getResult().equals(LoginResultEnum.SUCCESS.getResult())) + verify(loginLogService).createLoginLog( + argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGOUT_SELF.getType()) + && o.getResult().equals(LoginResultEnum.SUCCESS.getResult())) ); // 调用,并校验 diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/mail/MailSendServiceImplTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/mail/MailSendServiceImplTest.java index 8eeb6299e..4efeb1a82 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/mail/MailSendServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/mail/MailSendServiceImplTest.java @@ -33,7 +33,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.*; -class MailSendServiceImplTest extends BaseMockitoUnitTest { +public class MailSendServiceImplTest extends BaseMockitoUnitTest { @InjectMocks private MailSendServiceImpl mailSendService; @@ -278,16 +278,17 @@ class MailSendServiceImplTest extends BaseMockitoUnitTest { // mock 方法(发送邮件) String messageId = randomString(); - mailUtilMock.when(() -> MailUtil.send(argThat(mailAccount -> { - assertEquals("芋艿 <7685@qq.com>", mailAccount.getFrom()); - assertTrue(mailAccount.isAuth()); - assertEquals(account.getUsername(), mailAccount.getUser()); - assertEquals(account.getPassword(), mailAccount.getPass()); - assertEquals(account.getHost(), mailAccount.getHost()); - assertEquals(account.getPort(), mailAccount.getPort()); - assertEquals(account.getSslEnable(), mailAccount.isSslEnable()); - return true; - }), eq(message.getMail()), eq(message.getTitle()), eq(message.getContent()), eq(true))) + mailUtilMock.when(() -> MailUtil.send( + argThat(mailAccount -> { + assertEquals("芋艿 <7685@qq.com>", mailAccount.getFrom()); + assertTrue(mailAccount.isAuth()); + assertEquals(account.getUsername(), mailAccount.getUser()); + assertEquals(account.getPassword(), mailAccount.getPass()); + assertEquals(account.getHost(), mailAccount.getHost()); + assertEquals(account.getPort(), mailAccount.getPort()); + assertEquals(account.getSslEnable(), mailAccount.isSslEnable()); + return true; + }), eq(message.getMail()), eq(message.getTitle()), eq(message.getContent()), eq(true))) .thenReturn(messageId); // 调用 diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImplTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImplTest.java index 9d6d578fe..38357b280 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImplTest.java @@ -454,7 +454,7 @@ public class TenantServiceImplTest extends BaseDbUnitTest { TenantContextHolder.setTenantId(dbTenant.getId()); // mock 菜单 when(menuService.getMenuList()).thenReturn(Arrays.asList(randomPojo(MenuDO.class, o -> o.setId(100L)), - randomPojo(MenuDO.class, o -> o.setId(101L)))); + randomPojo(MenuDO.class, o -> o.setId(101L)))); // 调用 tenantService.handleTenantMenu(handler);