!464 发布 5.1.2 版本 2023 最后一版

Merge pull request !464 from 疯狂的狮子Li/dev
This commit is contained in:
疯狂的狮子Li 2023-12-22 05:23:30 +00:00 committed by Gitee
commit 203233fbaf
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
99 changed files with 885 additions and 628 deletions

View File

@ -2,7 +2,7 @@
<configuration default="false" name="ruoyi-monitor-admin" type="docker-deploy" factoryName="dockerfile" server-name="Docker"> <configuration default="false" name="ruoyi-monitor-admin" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
<deployment type="dockerfile"> <deployment type="dockerfile">
<settings> <settings>
<option name="imageTag" value="ruoyi/ruoyi-monitor-admin:5.1.1" /> <option name="imageTag" value="ruoyi/ruoyi-monitor-admin:5.1.2" />
<option name="buildOnly" value="true" /> <option name="buildOnly" value="true" />
<option name="sourceFilePath" value="ruoyi-extend/ruoyi-monitor-admin/Dockerfile" /> <option name="sourceFilePath" value="ruoyi-extend/ruoyi-monitor-admin/Dockerfile" />
</settings> </settings>

View File

@ -2,7 +2,7 @@
<configuration default="false" name="ruoyi-powerjob-server" type="docker-deploy" factoryName="dockerfile" server-name="Docker"> <configuration default="false" name="ruoyi-powerjob-server" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
<deployment type="dockerfile"> <deployment type="dockerfile">
<settings> <settings>
<option name="imageTag" value="ruoyi/ruoyi-powerjob-server:5.1.1" /> <option name="imageTag" value="ruoyi/ruoyi-powerjob-server:5.1.2" />
<option name="buildOnly" value="true" /> <option name="buildOnly" value="true" />
<option name="sourceFilePath" value="ruoyi-extend/ruoyi-powerjob-server/Dockerfile" /> <option name="sourceFilePath" value="ruoyi-extend/ruoyi-powerjob-server/Dockerfile" />
</settings> </settings>

View File

@ -2,7 +2,7 @@
<configuration default="false" name="ruoyi-server" type="docker-deploy" factoryName="dockerfile" server-name="Docker"> <configuration default="false" name="ruoyi-server" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
<deployment type="dockerfile"> <deployment type="dockerfile">
<settings> <settings>
<option name="imageTag" value="ruoyi/ruoyi-server:5.1.1" /> <option name="imageTag" value="ruoyi/ruoyi-server:5.1.2" />
<option name="buildOnly" value="true" /> <option name="buildOnly" value="true" />
<option name="sourceFilePath" value="ruoyi-admin/Dockerfile" /> <option name="sourceFilePath" value="ruoyi-admin/Dockerfile" />
</settings> </settings>

View File

@ -9,7 +9,7 @@
[![License](https://img.shields.io/badge/License-MIT-blue.svg)](https://gitee.com/dromara/RuoYi-Vue-Plus/blob/master/LICENSE) [![License](https://img.shields.io/badge/License-MIT-blue.svg)](https://gitee.com/dromara/RuoYi-Vue-Plus/blob/master/LICENSE)
[![使用IntelliJ IDEA开发维护](https://img.shields.io/badge/IntelliJ%20IDEA-提供支持-blue.svg)](https://www.jetbrains.com/?from=RuoYi-Vue-Plus) [![使用IntelliJ IDEA开发维护](https://img.shields.io/badge/IntelliJ%20IDEA-提供支持-blue.svg)](https://www.jetbrains.com/?from=RuoYi-Vue-Plus)
<br> <br>
[![RuoYi-Vue-Plus](https://img.shields.io/badge/RuoYi_Vue_Plus-5.1.1-success.svg)](https://gitee.com/dromara/RuoYi-Vue-Plus) [![RuoYi-Vue-Plus](https://img.shields.io/badge/RuoYi_Vue_Plus-5.1.2-success.svg)](https://gitee.com/dromara/RuoYi-Vue-Plus)
[![Spring Boot](https://img.shields.io/badge/Spring%20Boot-3.1-blue.svg)]() [![Spring Boot](https://img.shields.io/badge/Spring%20Boot-3.1-blue.svg)]()
[![JDK-17](https://img.shields.io/badge/JDK-17-green.svg)]() [![JDK-17](https://img.shields.io/badge/JDK-17-green.svg)]()
[![JDK-21](https://img.shields.io/badge/JDK-21-green.svg)]() [![JDK-21](https://img.shields.io/badge/JDK-21-green.svg)]()
@ -36,7 +36,7 @@
| 权限认证 | 采用 Sa-Token、Jwt 静态使用功能齐全 低耦合 高扩展 | Spring Security 配置繁琐扩展性极差 | | 权限认证 | 采用 Sa-Token、Jwt 静态使用功能齐全 低耦合 高扩展 | Spring Security 配置繁琐扩展性极差 |
| 权限注解 | 采用 Sa-Token 支持注解 登录校验、角色校验、权限校验、二级认证校验、HttpBasic校验、忽略校验<br/>角色与权限校验支持多种条件 如 `AND` `OR``权限 OR 角色` 等复杂表达式 | 只支持是否存在匹配 | | 权限注解 | 采用 Sa-Token 支持注解 登录校验、角色校验、权限校验、二级认证校验、HttpBasic校验、忽略校验<br/>角色与权限校验支持多种条件 如 `AND` `OR``权限 OR 角色` 等复杂表达式 | 只支持是否存在匹配 |
| 三方鉴权 | 采用 JustAuth 第三方登录组件 支持微信、钉钉等数十种三方认证 | 无 | | 三方鉴权 | 采用 JustAuth 第三方登录组件 支持微信、钉钉等数十种三方认证 | 无 |
| 关系数据库支持 | 原生支持 MySQL、Oracle、PostgreSQL、SQLServer<br/>可同时使用异构切换 | 支持 Mysql、Oracle 不支持同时使用、不支持异构切换 | | 关系数据库支持 | 原生支持 MySQL、Oracle、PostgreSQL、SQLServer<br/>可同时使用异构切换(支持其他 mybatis-plus 支持的所有数据库 只需要增加jdbc依赖即可使用 达梦金仓等均有成功案例) | 支持 Mysql、Oracle 不支持同时使用、不支持异构切换 |
| 缓存数据库 | 支持 Redis 5-7 支持大部分新功能特性 如 分布式限流、分布式队列 | Redis 简单 get set 支持 | | 缓存数据库 | 支持 Redis 5-7 支持大部分新功能特性 如 分布式限流、分布式队列 | Redis 简单 get set 支持 |
| Redis客户端 | 采用 Redisson Redis官方推荐 基于Netty的客户端工具<br/>支持Redis 90%以上的命令 底层优化规避很多不正确的用法 例如: keys被转换为scan<br/>支持单机、哨兵、单主集群、多主集群等模式 | Lettuce + RedisTemplate 支持模式少 工具使用繁琐<br/>连接池采用 common-pool Bug多经常性出问题 | | Redis客户端 | 采用 Redisson Redis官方推荐 基于Netty的客户端工具<br/>支持Redis 90%以上的命令 底层优化规避很多不正确的用法 例如: keys被转换为scan<br/>支持单机、哨兵、单主集群、多主集群等模式 | Lettuce + RedisTemplate 支持模式少 工具使用繁琐<br/>连接池采用 common-pool Bug多经常性出问题 |
| 缓存注解 | 采用 Spring-Cache 注解 对其扩展了实现支持了更多功能<br/>例如 过期时间 最大空闲时间 组最大长度等 只需一个注解即可完成数据自动缓存 | 需手动编写Redis代码逻辑 | | 缓存注解 | 采用 Spring-Cache 注解 对其扩展了实现支持了更多功能<br/>例如 过期时间 最大空闲时间 组最大长度等 只需一个注解即可完成数据自动缓存 | 需手动编写Redis代码逻辑 |

20
pom.xml
View File

@ -13,38 +13,38 @@
<description>RuoYi-Vue-Plus多租户管理系统</description> <description>RuoYi-Vue-Plus多租户管理系统</description>
<properties> <properties>
<revision>5.1.1</revision> <revision>5.1.2</revision>
<spring-boot.version>3.1.5</spring-boot.version> <spring-boot.version>3.1.7</spring-boot.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>17</java.version> <java.version>17</java.version>
<spring-boot.mybatis>3.0.2</spring-boot.mybatis> <spring-boot.mybatis>3.0.3</spring-boot.mybatis>
<springdoc.version>2.2.0</springdoc.version> <springdoc.version>2.2.0</springdoc.version>
<therapi-javadoc.version>0.15.0</therapi-javadoc.version> <therapi-javadoc.version>0.15.0</therapi-javadoc.version>
<poi.version>5.2.3</poi.version> <poi.version>5.2.3</poi.version>
<easyexcel.version>3.3.2</easyexcel.version> <easyexcel.version>3.3.3</easyexcel.version>
<velocity.version>2.3</velocity.version> <velocity.version>2.3</velocity.version>
<satoken.version>1.37.0</satoken.version> <satoken.version>1.37.0</satoken.version>
<mybatis-plus.version>3.5.4</mybatis-plus.version> <mybatis-plus.version>3.5.4</mybatis-plus.version>
<p6spy.version>3.9.1</p6spy.version> <p6spy.version>3.9.1</p6spy.version>
<hutool.version>5.8.22</hutool.version> <hutool.version>5.8.22</hutool.version>
<okhttp.version>4.10.0</okhttp.version> <okhttp.version>4.10.0</okhttp.version>
<spring-boot-admin.version>3.1.7</spring-boot-admin.version> <spring-boot-admin.version>3.1.8</spring-boot-admin.version>
<redisson.version>3.24.1</redisson.version> <redisson.version>3.24.3</redisson.version>
<lock4j.version>2.2.5</lock4j.version> <lock4j.version>2.2.5</lock4j.version>
<dynamic-ds.version>4.2.0</dynamic-ds.version> <dynamic-ds.version>4.2.0</dynamic-ds.version>
<alibaba-ttl.version>2.14.2</alibaba-ttl.version> <alibaba-ttl.version>2.14.4</alibaba-ttl.version>
<powerjob.version>4.3.3</powerjob.version> <powerjob.version>4.3.6</powerjob.version>
<mapstruct-plus.version>1.3.5</mapstruct-plus.version> <mapstruct-plus.version>1.3.5</mapstruct-plus.version>
<mapstruct-plus.lombok.version>0.2.0</mapstruct-plus.lombok.version> <mapstruct-plus.lombok.version>0.2.0</mapstruct-plus.lombok.version>
<lombok.version>1.18.30</lombok.version> <lombok.version>1.18.30</lombok.version>
<bouncycastle.version>1.76</bouncycastle.version> <bouncycastle.version>1.76</bouncycastle.version>
<justauth.version>1.16.5</justauth.version> <justauth.version>1.16.6</justauth.version>
<!-- 离线IP地址定位库 --> <!-- 离线IP地址定位库 -->
<ip2region.version>2.7.0</ip2region.version> <ip2region.version>2.7.0</ip2region.version>
<!-- OSS 配置 --> <!-- OSS 配置 -->
<aws-java-sdk-s3.version>1.12.540</aws-java-sdk-s3.version> <aws-java-sdk-s3.version>1.12.600</aws-java-sdk-s3.version>
<!-- SMS 配置 --> <!-- SMS 配置 -->
<sms4j.version>2.2.0</sms4j.version> <sms4j.version>2.2.0</sms4j.version>
<!-- 限制框架中的fastjson版本 --> <!-- 限制框架中的fastjson版本 -->

View File

@ -9,16 +9,16 @@ RUN mkdir -p /ruoyi/server/logs \
WORKDIR /ruoyi/server WORKDIR /ruoyi/server
ENV SERVER_PORT=8080 LANG=C.UTF-8 LC_ALL=C.UTF-8 ENV SERVER_PORT=8080 LANG=C.UTF-8 LC_ALL=C.UTF-8 JAVA_OPTS=""
EXPOSE ${SERVER_PORT} EXPOSE ${SERVER_PORT}
ADD ./target/ruoyi-admin.jar ./app.jar ADD ./target/ruoyi-admin.jar ./app.jar
ENTRYPOINT ["java", \ ENTRYPOINT java -Djava.security.egd=file:/dev/./urandom -Dserver.port=${SERVER_PORT} \
"-Djava.security.egd=file:/dev/./urandom", \ # 应用名称 如果想区分集群节点监控 改成不同的名称即可
"-Dserver.port=${SERVER_PORT}", \ #-Dskywalking.agent.service_name=ruoyi-server \
# 应用名称 如果想区分集群节点监控 改成不同的名称即可 #-javaagent:/ruoyi/skywalking/agent/skywalking-agent.jar \
# "-Dskywalking.agent.service_name=ruoyi-server", \ -jar app.jar \
# "-javaagent:/ruoyi/skywalking/agent/skywalking-agent.jar", \ -XX:+HeapDumpOnOutOfMemoryError -Xlog:gc*,:time,tags,level -XX:+UseZGC ${JAVA_OPTS}
"-jar", "app.jar"]

View File

@ -48,6 +48,10 @@
<artifactId>ruoyi-common-social</artifactId> <artifactId>ruoyi-common-social</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-ratelimiter</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.dromara</groupId> <groupId>org.dromara</groupId>

View File

@ -16,6 +16,7 @@ import org.dromara.common.core.domain.model.LoginBody;
import org.dromara.common.core.domain.model.RegisterBody; import org.dromara.common.core.domain.model.RegisterBody;
import org.dromara.common.core.domain.model.SocialLoginBody; import org.dromara.common.core.domain.model.SocialLoginBody;
import org.dromara.common.core.utils.*; import org.dromara.common.core.utils.*;
import org.dromara.common.encrypt.annotation.ApiEncrypt;
import org.dromara.common.json.utils.JsonUtils; import org.dromara.common.json.utils.JsonUtils;
import org.dromara.common.satoken.utils.LoginHelper; import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.common.social.config.properties.SocialLoginConfigProperties; import org.dromara.common.social.config.properties.SocialLoginConfigProperties;
@ -51,7 +52,6 @@ import java.util.concurrent.TimeUnit;
*/ */
@Slf4j @Slf4j
@SaIgnore @SaIgnore
@Validated
@RequiredArgsConstructor @RequiredArgsConstructor
@RestController @RestController
@RequestMapping("/auth") @RequestMapping("/auth")
@ -73,8 +73,9 @@ public class AuthController {
* @param body 登录信息 * @param body 登录信息
* @return 结果 * @return 结果
*/ */
@ApiEncrypt
@PostMapping("/login") @PostMapping("/login")
public R<LoginVo> login(@Validated @RequestBody String body) { public R<LoginVo> login(@RequestBody String body) {
LoginBody loginBody = JsonUtils.parseObject(body, LoginBody.class); LoginBody loginBody = JsonUtils.parseObject(body, LoginBody.class);
ValidatorUtils.validate(loginBody); ValidatorUtils.validate(loginBody);
// 授权类型和客户端id // 授权类型和客户端id
@ -163,6 +164,7 @@ public class AuthController {
/** /**
* 用户注册 * 用户注册
*/ */
@ApiEncrypt
@PostMapping("/register") @PostMapping("/register")
public R<Void> register(@Validated @RequestBody RegisterBody user) { public R<Void> register(@Validated @RequestBody RegisterBody user) {
if (!configService.selectRegisterEnabled(user.getTenantId())) { if (!configService.selectRegisterEnabled(user.getTenantId())) {

View File

@ -13,6 +13,8 @@ import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.core.utils.reflect.ReflectUtils; import org.dromara.common.core.utils.reflect.ReflectUtils;
import org.dromara.common.mail.config.properties.MailProperties; import org.dromara.common.mail.config.properties.MailProperties;
import org.dromara.common.mail.utils.MailUtils; import org.dromara.common.mail.utils.MailUtils;
import org.dromara.common.ratelimiter.annotation.RateLimiter;
import org.dromara.common.ratelimiter.enums.LimitType;
import org.dromara.common.redis.utils.RedisUtils; import org.dromara.common.redis.utils.RedisUtils;
import org.dromara.common.web.config.properties.CaptchaProperties; import org.dromara.common.web.config.properties.CaptchaProperties;
import org.dromara.common.web.enums.CaptchaType; import org.dromara.common.web.enums.CaptchaType;
@ -54,6 +56,7 @@ public class CaptchaController {
* *
* @param phonenumber 用户手机号 * @param phonenumber 用户手机号
*/ */
@RateLimiter(key = "#phonenumber", time = 60, count = 1)
@GetMapping("/resource/sms/code") @GetMapping("/resource/sms/code")
public R<Void> smsCode(@NotBlank(message = "{user.phonenumber.not.blank}") String phonenumber) { public R<Void> smsCode(@NotBlank(message = "{user.phonenumber.not.blank}") String phonenumber) {
String key = GlobalConstants.CAPTCHA_CODE_KEY + phonenumber; String key = GlobalConstants.CAPTCHA_CODE_KEY + phonenumber;
@ -77,6 +80,7 @@ public class CaptchaController {
* *
* @param email 邮箱 * @param email 邮箱
*/ */
@RateLimiter(key = "#email", time = 60, count = 1)
@GetMapping("/resource/email/code") @GetMapping("/resource/email/code")
public R<Void> emailCode(@NotBlank(message = "{user.email.not.blank}") String email) { public R<Void> emailCode(@NotBlank(message = "{user.email.not.blank}") String email) {
if (!mailProperties.getEnabled()) { if (!mailProperties.getEnabled()) {
@ -97,6 +101,7 @@ public class CaptchaController {
/** /**
* 生成验证码 * 生成验证码
*/ */
@RateLimiter(time = 60, count = 10, limitType = LimitType.IP)
@GetMapping("/auth/code") @GetMapping("/auth/code")
public R<CaptchaVo> getCode() { public R<CaptchaVo> getCode() {
CaptchaVo captchaVo = new CaptchaVo(); CaptchaVo captchaVo = new CaptchaVo();

View File

@ -1,20 +1,24 @@
package org.dromara.common.satoken.listener; package org.dromara.web.listener;
import cn.dev33.satoken.config.SaTokenConfig; import cn.dev33.satoken.config.SaTokenConfig;
import cn.dev33.satoken.listener.SaTokenListener; import cn.dev33.satoken.listener.SaTokenListener;
import cn.dev33.satoken.stp.SaLoginModel; import cn.dev33.satoken.stp.SaLoginModel;
import cn.hutool.http.useragent.UserAgent; import cn.hutool.http.useragent.UserAgent;
import cn.hutool.http.useragent.UserAgentUtil; import cn.hutool.http.useragent.UserAgentUtil;
import org.dromara.common.core.constant.CacheConstants;
import org.dromara.common.core.domain.dto.UserOnlineDTO;
import org.dromara.common.core.domain.model.LoginUser;
import org.dromara.common.core.enums.UserType;
import org.dromara.common.redis.utils.RedisUtils;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.common.core.utils.ip.AddressUtils;
import org.dromara.common.core.utils.ServletUtils;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.constant.CacheConstants;
import org.dromara.common.core.constant.Constants;
import org.dromara.common.core.domain.dto.UserOnlineDTO;
import org.dromara.common.core.domain.model.LoginUser;
import org.dromara.common.core.utils.MessageUtils;
import org.dromara.common.core.utils.ServletUtils;
import org.dromara.common.core.utils.SpringUtils;
import org.dromara.common.core.utils.ip.AddressUtils;
import org.dromara.common.log.event.LogininforEvent;
import org.dromara.common.redis.utils.RedisUtils;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.web.service.SysLoginService;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.time.Duration; import java.time.Duration;
@ -30,37 +34,43 @@ import java.time.Duration;
public class UserActionListener implements SaTokenListener { public class UserActionListener implements SaTokenListener {
private final SaTokenConfig tokenConfig; private final SaTokenConfig tokenConfig;
private final SysLoginService loginService;
/** /**
* 每次登录时触发 * 每次登录时触发
*/ */
@Override @Override
public void doLogin(String loginType, Object loginId, String tokenValue, SaLoginModel loginModel) { public void doLogin(String loginType, Object loginId, String tokenValue, SaLoginModel loginModel) {
UserType userType = UserType.getUserType(loginId.toString()); UserAgent userAgent = UserAgentUtil.parse(ServletUtils.getRequest().getHeader("User-Agent"));
if (userType == UserType.SYS_USER) { String ip = ServletUtils.getClientIP();
UserAgent userAgent = UserAgentUtil.parse(ServletUtils.getRequest().getHeader("User-Agent")); LoginUser user = LoginHelper.getLoginUser();
String ip = ServletUtils.getClientIP(); UserOnlineDTO dto = new UserOnlineDTO();
LoginUser user = LoginHelper.getLoginUser(); dto.setIpaddr(ip);
UserOnlineDTO dto = new UserOnlineDTO(); dto.setLoginLocation(AddressUtils.getRealAddressByIP(ip));
dto.setIpaddr(ip); dto.setBrowser(userAgent.getBrowser().getName());
dto.setLoginLocation(AddressUtils.getRealAddressByIP(ip)); dto.setOs(userAgent.getOs().getName());
dto.setBrowser(userAgent.getBrowser().getName()); dto.setLoginTime(System.currentTimeMillis());
dto.setOs(userAgent.getOs().getName()); dto.setTokenId(tokenValue);
dto.setLoginTime(System.currentTimeMillis()); dto.setUserName(user.getUsername());
dto.setTokenId(tokenValue); dto.setClientKey(user.getClientKey());
dto.setUserName(user.getUsername()); dto.setDeviceType(user.getDeviceType());
dto.setClientKey(user.getClientKey()); dto.setDeptName(user.getDeptName());
dto.setDeviceType(user.getDeviceType()); if(tokenConfig.getTimeout() == -1) {
dto.setDeptName(user.getDeptName()); RedisUtils.setCacheObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue, dto);
if(tokenConfig.getTimeout() == -1) { } else {
RedisUtils.setCacheObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue, dto); RedisUtils.setCacheObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue, dto, Duration.ofSeconds(tokenConfig.getTimeout()));
} else {
RedisUtils.setCacheObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue, dto, Duration.ofSeconds(tokenConfig.getTimeout()));
}
log.info("user doLogin, userId:{}, token:{}", loginId, tokenValue);
} else if (userType == UserType.APP_USER) {
// app端 自行根据业务编写
} }
// 记录登录日志
LogininforEvent logininforEvent = new LogininforEvent();
logininforEvent.setTenantId(user.getTenantId());
logininforEvent.setUsername(user.getUsername());
logininforEvent.setStatus(Constants.LOGIN_SUCCESS);
logininforEvent.setMessage(MessageUtils.message("user.login.success"));
logininforEvent.setRequest(ServletUtils.getRequest());
SpringUtils.context().publishEvent(logininforEvent);
// 更新登录信息
loginService.recordLoginInfo(user.getUserId(), ip);
log.info("user doLogin, userId:{}, token:{}", loginId, tokenValue);
} }
/** /**

View File

@ -3,6 +3,7 @@ package org.dromara.web.service;
import cn.dev33.satoken.exception.NotLoginException; import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.stp.StpUtil; import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -17,6 +18,7 @@ import org.dromara.common.core.enums.TenantStatus;
import org.dromara.common.core.exception.user.UserException; import org.dromara.common.core.exception.user.UserException;
import org.dromara.common.core.utils.*; import org.dromara.common.core.utils.*;
import org.dromara.common.log.event.LogininforEvent; import org.dromara.common.log.event.LogininforEvent;
import org.dromara.common.mybatis.helper.DataPermissionHelper;
import org.dromara.common.redis.utils.RedisUtils; import org.dromara.common.redis.utils.RedisUtils;
import org.dromara.common.satoken.utils.LoginHelper; import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.common.tenant.exception.TenantException; import org.dromara.common.tenant.exception.TenantException;
@ -77,13 +79,13 @@ public class SysLoginService {
bo.setUserName(authUserData.getUsername()); bo.setUserName(authUserData.getUsername());
bo.setNickName(authUserData.getNickname()); bo.setNickName(authUserData.getNickname());
// 查询是否已经绑定用户 // 查询是否已经绑定用户
SysSocialVo vo = sysSocialService.selectByAuthId(authId); List<SysSocialVo> list = sysSocialService.selectByAuthId(authId);
if (ObjectUtil.isEmpty(vo)) { if (CollUtil.isEmpty(list)) {
// 没有绑定用户, 新增用户信息 // 没有绑定用户, 新增用户信息
sysSocialService.insertByBo(bo); sysSocialService.insertByBo(bo);
} else { } else {
// 更新用户信息 // 更新用户信息
bo.setId(vo.getId()); bo.setId(list.get(0).getId());
sysSocialService.updateByBo(bo); sysSocialService.updateByBo(bo);
} }
} }
@ -95,6 +97,9 @@ public class SysLoginService {
public void logout() { public void logout() {
try { try {
LoginUser loginUser = LoginHelper.getLoginUser(); LoginUser loginUser = LoginHelper.getLoginUser();
if (ObjectUtil.isNull(loginUser)) {
return;
}
if (TenantHelper.isEnable() && LoginHelper.isSuperAdmin()) { if (TenantHelper.isEnable() && LoginHelper.isSuperAdmin()) {
// 超级管理员 登出清除动态租户 // 超级管理员 登出清除动态租户
TenantHelper.clearDynamic(); TenantHelper.clearDynamic();
@ -152,13 +157,13 @@ public class SysLoginService {
* *
* @param userId 用户ID * @param userId 用户ID
*/ */
public void recordLoginInfo(Long userId) { public void recordLoginInfo(Long userId, String ip) {
SysUser sysUser = new SysUser(); SysUser sysUser = new SysUser();
sysUser.setUserId(userId); sysUser.setUserId(userId);
sysUser.setLoginIp(ServletUtils.getClientIP()); sysUser.setLoginIp(ip);
sysUser.setLoginDate(DateUtils.getNowDate()); sysUser.setLoginDate(DateUtils.getNowDate());
sysUser.setUpdateBy(userId); sysUser.setUpdateBy(userId);
userMapper.updateById(sysUser); DataPermissionHelper.ignore(() -> userMapper.updateById(sysUser));
} }
/** /**

View File

@ -3,6 +3,7 @@ package org.dromara.web.service;
import cn.dev33.satoken.secure.BCrypt; import cn.dev33.satoken.secure.BCrypt;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.constant.Constants; import org.dromara.common.core.constant.Constants;
import org.dromara.common.core.constant.GlobalConstants; import org.dromara.common.core.constant.GlobalConstants;
import org.dromara.common.core.domain.model.RegisterBody; import org.dromara.common.core.domain.model.RegisterBody;
@ -22,7 +23,6 @@ import org.dromara.system.domain.SysUser;
import org.dromara.system.domain.bo.SysUserBo; import org.dromara.system.domain.bo.SysUserBo;
import org.dromara.system.mapper.SysUserMapper; import org.dromara.system.mapper.SysUserMapper;
import org.dromara.system.service.ISysUserService; import org.dromara.system.service.ISysUserService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
/** /**
@ -59,10 +59,11 @@ public class SysRegisterService {
sysUser.setPassword(BCrypt.hashpw(password)); sysUser.setPassword(BCrypt.hashpw(password));
sysUser.setUserType(userType); sysUser.setUserType(userType);
boolean exist = userMapper.exists(new LambdaQueryWrapper<SysUser>() boolean exist = TenantHelper.dynamic(tenantId, () -> {
.eq(TenantHelper.isEnable(), SysUser::getTenantId, tenantId) return userMapper.exists(new LambdaQueryWrapper<SysUser>()
.eq(SysUser::getUserName, sysUser.getUserName()) .eq(SysUser::getUserName, sysUser.getUserName())
.ne(ObjectUtil.isNotNull(sysUser.getUserId()), SysUser::getUserId, sysUser.getUserId())); .ne(ObjectUtil.isNotNull(sysUser.getUserId()), SysUser::getUserId, sysUser.getUserId()));
});
if (exist) { if (exist) {
throw new UserException("user.register.save.error", username); throw new UserException("user.register.save.error", username);
} }

View File

@ -69,9 +69,6 @@ public class EmailAuthStrategy implements IAuthStrategy {
// 生成token // 生成token
LoginHelper.login(loginUser, model); LoginHelper.login(loginUser, model);
loginService.recordLogininfor(loginUser.getTenantId(), user.getUserName(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
loginService.recordLoginInfo(user.getUserId());
LoginVo loginVo = new LoginVo(); LoginVo loginVo = new LoginVo();
loginVo.setAccessToken(StpUtil.getTokenValue()); loginVo.setAccessToken(StpUtil.getTokenValue());
loginVo.setExpireIn(StpUtil.getTokenTimeout()); loginVo.setExpireIn(StpUtil.getTokenTimeout());
@ -92,21 +89,19 @@ public class EmailAuthStrategy implements IAuthStrategy {
} }
private SysUserVo loadUserByEmail(String tenantId, String email) { private SysUserVo loadUserByEmail(String tenantId, String email) {
SysUser user = userMapper.selectOne(new LambdaQueryWrapper<SysUser>() return TenantHelper.dynamic(tenantId, () -> {
.select(SysUser::getEmail, SysUser::getStatus) SysUser user = userMapper.selectOne(new LambdaQueryWrapper<SysUser>()
.eq(TenantHelper.isEnable(), SysUser::getTenantId, tenantId) .select(SysUser::getEmail, SysUser::getStatus)
.eq(SysUser::getEmail, email)); .eq(SysUser::getEmail, email));
if (ObjectUtil.isNull(user)) { if (ObjectUtil.isNull(user)) {
log.info("登录用户:{} 不存在.", email); log.info("登录用户:{} 不存在.", email);
throw new UserException("user.not.exists", email); throw new UserException("user.not.exists", email);
} else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) { } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
log.info("登录用户:{} 已被停用.", email); log.info("登录用户:{} 已被停用.", email);
throw new UserException("user.blocked", email); throw new UserException("user.blocked", email);
} }
if (TenantHelper.isEnable()) { return userMapper.selectUserByEmail(email);
return userMapper.selectTenantUserByEmail(email, tenantId); });
}
return userMapper.selectUserByEmail(email);
} }
} }

View File

@ -79,9 +79,6 @@ public class PasswordAuthStrategy implements IAuthStrategy {
// 生成token // 生成token
LoginHelper.login(loginUser, model); LoginHelper.login(loginUser, model);
loginService.recordLogininfor(loginUser.getTenantId(), username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
loginService.recordLoginInfo(user.getUserId());
LoginVo loginVo = new LoginVo(); LoginVo loginVo = new LoginVo();
loginVo.setAccessToken(StpUtil.getTokenValue()); loginVo.setAccessToken(StpUtil.getTokenValue());
loginVo.setExpireIn(StpUtil.getTokenTimeout()); loginVo.setExpireIn(StpUtil.getTokenTimeout());
@ -111,21 +108,19 @@ public class PasswordAuthStrategy implements IAuthStrategy {
} }
private SysUserVo loadUserByUsername(String tenantId, String username) { private SysUserVo loadUserByUsername(String tenantId, String username) {
SysUser user = userMapper.selectOne(new LambdaQueryWrapper<SysUser>() return TenantHelper.dynamic(tenantId, () -> {
.select(SysUser::getUserName, SysUser::getStatus) SysUser user = userMapper.selectOne(new LambdaQueryWrapper<SysUser>()
.eq(TenantHelper.isEnable(), SysUser::getTenantId, tenantId) .select(SysUser::getUserName, SysUser::getStatus)
.eq(SysUser::getUserName, username)); .eq(SysUser::getUserName, username));
if (ObjectUtil.isNull(user)) { if (ObjectUtil.isNull(user)) {
log.info("登录用户:{} 不存在.", username); log.info("登录用户:{} 不存在.", username);
throw new UserException("user.not.exists", username); throw new UserException("user.not.exists", username);
} else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) { } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
log.info("登录用户:{} 已被停用.", username); log.info("登录用户:{} 已被停用.", username);
throw new UserException("user.blocked", username); throw new UserException("user.blocked", username);
} }
if (TenantHelper.isEnable()) { return userMapper.selectUserByUserName(username);
return userMapper.selectTenantUserByUserName(username, tenantId); });
}
return userMapper.selectUserByUserName(username);
} }
} }

View File

@ -69,9 +69,6 @@ public class SmsAuthStrategy implements IAuthStrategy {
// 生成token // 生成token
LoginHelper.login(loginUser, model); LoginHelper.login(loginUser, model);
loginService.recordLogininfor(loginUser.getTenantId(), user.getUserName(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
loginService.recordLoginInfo(user.getUserId());
LoginVo loginVo = new LoginVo(); LoginVo loginVo = new LoginVo();
loginVo.setAccessToken(StpUtil.getTokenValue()); loginVo.setAccessToken(StpUtil.getTokenValue());
loginVo.setExpireIn(StpUtil.getTokenTimeout()); loginVo.setExpireIn(StpUtil.getTokenTimeout());
@ -92,21 +89,19 @@ public class SmsAuthStrategy implements IAuthStrategy {
} }
private SysUserVo loadUserByPhonenumber(String tenantId, String phonenumber) { private SysUserVo loadUserByPhonenumber(String tenantId, String phonenumber) {
SysUser user = userMapper.selectOne(new LambdaQueryWrapper<SysUser>() return TenantHelper.dynamic(tenantId, () -> {
.select(SysUser::getPhonenumber, SysUser::getStatus) SysUser user = userMapper.selectOne(new LambdaQueryWrapper<SysUser>()
.eq(TenantHelper.isEnable(), SysUser::getTenantId, tenantId) .select(SysUser::getPhonenumber, SysUser::getStatus)
.eq(SysUser::getPhonenumber, phonenumber)); .eq(SysUser::getPhonenumber, phonenumber));
if (ObjectUtil.isNull(user)) { if (ObjectUtil.isNull(user)) {
log.info("登录用户:{} 不存在.", phonenumber); log.info("登录用户:{} 不存在.", phonenumber);
throw new UserException("user.not.exists", phonenumber); throw new UserException("user.not.exists", phonenumber);
} else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) { } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
log.info("登录用户:{} 已被停用.", phonenumber); log.info("登录用户:{} 已被停用.", phonenumber);
throw new UserException("user.blocked", phonenumber); throw new UserException("user.blocked", phonenumber);
} }
if (TenantHelper.isEnable()) { return userMapper.selectUserByPhonenumber(phonenumber);
return userMapper.selectTenantUserByPhonenumber(phonenumber, tenantId); });
}
return userMapper.selectUserByPhonenumber(phonenumber);
} }
} }

View File

@ -2,9 +2,9 @@ package org.dromara.web.service.impl;
import cn.dev33.satoken.stp.SaLoginModel; import cn.dev33.satoken.stp.SaLoginModel;
import cn.dev33.satoken.stp.StpUtil; import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil; import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil; import cn.hutool.http.HttpUtil;
import cn.hutool.http.Method; import cn.hutool.http.Method;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@ -12,13 +12,11 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import me.zhyd.oauth.model.AuthResponse; import me.zhyd.oauth.model.AuthResponse;
import me.zhyd.oauth.model.AuthUser; import me.zhyd.oauth.model.AuthUser;
import org.dromara.common.core.constant.Constants;
import org.dromara.common.core.domain.model.LoginUser; import org.dromara.common.core.domain.model.LoginUser;
import org.dromara.common.core.domain.model.SocialLoginBody; import org.dromara.common.core.domain.model.SocialLoginBody;
import org.dromara.common.core.enums.UserStatus; import org.dromara.common.core.enums.UserStatus;
import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.exception.user.UserException; import org.dromara.common.core.exception.user.UserException;
import org.dromara.common.core.utils.MessageUtils;
import org.dromara.common.core.utils.ValidatorUtils; import org.dromara.common.core.utils.ValidatorUtils;
import org.dromara.common.json.utils.JsonUtils; import org.dromara.common.json.utils.JsonUtils;
import org.dromara.common.satoken.utils.LoginHelper; import org.dromara.common.satoken.utils.LoginHelper;
@ -36,6 +34,9 @@ import org.dromara.web.service.IAuthStrategy;
import org.dromara.web.service.SysLoginService; import org.dromara.web.service.SysLoginService;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
/** /**
* 第三方授权策略 * 第三方授权策略
* *
@ -78,19 +79,17 @@ public class SocialAuthStrategy implements IAuthStrategy {
.executeAsync(); .executeAsync();
} }
SysSocialVo social = sysSocialService.selectByAuthId(authUserData.getSource() + authUserData.getUuid()); List<SysSocialVo> list = sysSocialService.selectByAuthId(authUserData.getSource() + authUserData.getUuid());
if (!ObjectUtil.isNotNull(social)) { if (CollUtil.isEmpty(list)) {
throw new ServiceException("你还没有绑定第三方账号,绑定后才可以登录!"); throw new ServiceException("你还没有绑定第三方账号,绑定后才可以登录!");
} }
// 验证授权表里面的租户id是否包含当前租户id Optional<SysSocialVo> opt = list.stream().filter(x -> x.getTenantId().equals(loginBody.getTenantId())).findAny();
String tenantId = social.getTenantId(); if (opt.isEmpty()) {
if (ObjectUtil.isNotNull(social) && StrUtil.isNotBlank(tenantId)
&& !tenantId.contains(loginBody.getTenantId())) {
throw new ServiceException("对不起,你没有权限登录当前租户!"); throw new ServiceException("对不起,你没有权限登录当前租户!");
} }
SysSocialVo social = opt.get();
// 查找用户 // 查找用户
SysUserVo user = loadUser(tenantId, social.getUserId()); SysUserVo user = loadUser(social.getTenantId(), social.getUserId());
// 此处可根据登录用户的数据不同 自行创建 loginUser 属性不够用继承扩展就行了 // 此处可根据登录用户的数据不同 自行创建 loginUser 属性不够用继承扩展就行了
LoginUser loginUser = loginService.buildLoginUser(user); LoginUser loginUser = loginService.buildLoginUser(user);
@ -106,9 +105,6 @@ public class SocialAuthStrategy implements IAuthStrategy {
// 生成token // 生成token
LoginHelper.login(loginUser, model); LoginHelper.login(loginUser, model);
loginService.recordLogininfor(loginUser.getTenantId(), user.getUserName(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
loginService.recordLoginInfo(user.getUserId());
LoginVo loginVo = new LoginVo(); LoginVo loginVo = new LoginVo();
loginVo.setAccessToken(StpUtil.getTokenValue()); loginVo.setAccessToken(StpUtil.getTokenValue());
loginVo.setExpireIn(StpUtil.getTokenTimeout()); loginVo.setExpireIn(StpUtil.getTokenTimeout());
@ -117,21 +113,19 @@ public class SocialAuthStrategy implements IAuthStrategy {
} }
private SysUserVo loadUser(String tenantId, Long userId) { private SysUserVo loadUser(String tenantId, Long userId) {
SysUser user = userMapper.selectOne(new LambdaQueryWrapper<SysUser>() return TenantHelper.dynamic(tenantId, () -> {
SysUser user = userMapper.selectOne(new LambdaQueryWrapper<SysUser>()
.select(SysUser::getUserName, SysUser::getStatus) .select(SysUser::getUserName, SysUser::getStatus)
.eq(TenantHelper.isEnable(), SysUser::getTenantId, tenantId)
.eq(SysUser::getUserId, userId)); .eq(SysUser::getUserId, userId));
if (ObjectUtil.isNull(user)) { if (ObjectUtil.isNull(user)) {
log.info("登录用户:{} 不存在.", ""); log.info("登录用户:{} 不存在.", "");
throw new UserException("user.not.exists", ""); throw new UserException("user.not.exists", "");
} else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) { } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
log.info("登录用户:{} 已被停用.", ""); log.info("登录用户:{} 已被停用.", "");
throw new UserException("user.blocked", ""); throw new UserException("user.blocked", "");
} }
if (TenantHelper.isEnable()) { return userMapper.selectUserByUserName(user.getUserName());
return userMapper.selectTenantUserByUserName(user.getUserName(), tenantId); });
}
return userMapper.selectUserByUserName(user.getUserName());
} }
} }

View File

@ -5,11 +5,9 @@ import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.constant.Constants;
import org.dromara.common.core.domain.model.XcxLoginBody; import org.dromara.common.core.domain.model.XcxLoginBody;
import org.dromara.common.core.domain.model.XcxLoginUser; import org.dromara.common.core.domain.model.XcxLoginUser;
import org.dromara.common.core.enums.UserStatus; import org.dromara.common.core.enums.UserStatus;
import org.dromara.common.core.utils.MessageUtils;
import org.dromara.common.core.utils.ValidatorUtils; import org.dromara.common.core.utils.ValidatorUtils;
import org.dromara.common.json.utils.JsonUtils; import org.dromara.common.json.utils.JsonUtils;
import org.dromara.common.satoken.utils.LoginHelper; import org.dromara.common.satoken.utils.LoginHelper;
@ -68,9 +66,6 @@ public class XcxAuthStrategy implements IAuthStrategy {
// 生成token // 生成token
LoginHelper.login(loginUser, model); LoginHelper.login(loginUser, model);
loginService.recordLogininfor(loginUser.getTenantId(), user.getUserName(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
loginService.recordLoginInfo(user.getUserId());
LoginVo loginVo = new LoginVo(); LoginVo loginVo = new LoginVo();
loginVo.setAccessToken(StpUtil.getTokenValue()); loginVo.setAccessToken(StpUtil.getTokenValue());
loginVo.setExpireIn(StpUtil.getTokenTimeout()); loginVo.setExpireIn(StpUtil.getTokenTimeout());

View File

@ -15,7 +15,7 @@ powerjob:
enabled: false enabled: false
# 需要先在 powerjob 登录页执行应用注册后才能使用 # 需要先在 powerjob 登录页执行应用注册后才能使用
app-name: ruoyi-worker app-name: ruoyi-worker
enable-test-mode: false allow-lazy-connect-server: false
max-appended-wf-context-length: 4096 max-appended-wf-context-length: 4096
max-result-length: 4096 max-result-length: 4096
# 28080 端口 随着主应用端口飘逸 避免集群冲突 # 28080 端口 随着主应用端口飘逸 避免集群冲突
@ -60,8 +60,6 @@ spring:
# url: jdbc:oracle:thin:@//localhost:1521/XE # url: jdbc:oracle:thin:@//localhost:1521/XE
# username: ROOT # username: ROOT
# password: root # password: root
# hikari:
# connectionTestQuery: SELECT 1 FROM DUAL
# postgres: # postgres:
# type: ${spring.datasource.type} # type: ${spring.datasource.type}
# driverClassName: org.postgresql.Driver # driverClassName: org.postgresql.Driver
@ -87,8 +85,6 @@ spring:
idleTimeout: 600000 idleTimeout: 600000
# 此属性控制池中连接的最长生命周期值0表示无限生命周期默认30分钟 # 此属性控制池中连接的最长生命周期值0表示无限生命周期默认30分钟
maxLifetime: 1800000 maxLifetime: 1800000
# 连接测试query配置检测连接是否有效
connectionTestQuery: SELECT 1
# 多久检查一次连接的活性 # 多久检查一次连接的活性
keepaliveTime: 30000 keepaliveTime: 30000

View File

@ -18,7 +18,7 @@ powerjob:
enabled: false enabled: false
# 需要先在 powerjob 登录页执行应用注册后才能使用 # 需要先在 powerjob 登录页执行应用注册后才能使用
app-name: ruoyi-worker app-name: ruoyi-worker
enable-test-mode: false allow-lazy-connect-server: false
max-appended-wf-context-length: 4096 max-appended-wf-context-length: 4096
max-result-length: 4096 max-result-length: 4096
# 28080 端口 随着主应用端口飘逸 避免集群冲突 # 28080 端口 随着主应用端口飘逸 避免集群冲突
@ -63,8 +63,6 @@ spring:
# url: jdbc:oracle:thin:@//localhost:1521/XE # url: jdbc:oracle:thin:@//localhost:1521/XE
# username: ROOT # username: ROOT
# password: root # password: root
# hikari:
# connectionTestQuery: SELECT 1 FROM DUAL
# postgres: # postgres:
# type: ${spring.datasource.type} # type: ${spring.datasource.type}
# driverClassName: org.postgresql.Driver # driverClassName: org.postgresql.Driver
@ -90,8 +88,6 @@ spring:
idleTimeout: 600000 idleTimeout: 600000
# 此属性控制池中连接的最长生命周期值0表示无限生命周期默认30分钟 # 此属性控制池中连接的最长生命周期值0表示无限生命周期默认30分钟
maxLifetime: 1800000 maxLifetime: 1800000
# 连接测试query配置检测连接是否有效
connectionTestQuery: SELECT 1
# 多久检查一次连接的活性 # 多久检查一次连接的活性
keepaliveTime: 30000 keepaliveTime: 30000

View File

@ -133,6 +133,7 @@ tenant:
- sys_user_post - sys_user_post
- sys_user_role - sys_user_role
- sys_client - sys_client
- sys_oss_config
# MyBatisPlus配置 # MyBatisPlus配置
# https://baomidou.com/config/ # https://baomidou.com/config/
@ -171,8 +172,11 @@ api-decrypt:
enabled: true enabled: true
# AES 加密头标识 # AES 加密头标识
headerFlag: encrypt-key headerFlag: encrypt-key
# 公私钥 非对称算法的公私钥 如SM2RSA 使用者请自行更换 # 响应加密公钥 非对称算法的公私钥 如SM2RSA 使用者请自行更换
publicKey: MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdHnzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ== # 对应前端解密私钥 MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAmc3CuPiGL/LcIIm7zryCEIbl1SPzBkr75E2VMtxegyZ1lYRD+7TZGAPkvIsBcaMs6Nsy0L78n2qh+lIZMpLH8wIDAQABAkEAk82Mhz0tlv6IVCyIcw/s3f0E+WLmtPFyR9/WtV3Y5aaejUkU60JpX4m5xNR2VaqOLTZAYjW8Wy0aXr3zYIhhQQIhAMfqR9oFdYw1J9SsNc+CrhugAvKTi0+BF6VoL6psWhvbAiEAxPPNTmrkmrXwdm/pQQu3UOQmc2vCZ5tiKpW10CgJi8kCIFGkL6utxw93Ncj4exE/gPLvKcT+1Emnoox+O9kRXss5AiAMtYLJDaLEzPrAWcZeeSgSIzbL+ecokmFKSDDcRske6QIgSMkHedwND1olF8vlKsJUGK3BcdtM8w4Xq7BpSBwsloE=
publicKey: MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJnNwrj4hi/y3CCJu868ghCG5dUj8wZK++RNlTLcXoMmdZWEQ/u02RgD5LyLAXGjLOjbMtC+/J9qofpSGTKSx/MCAwEAAQ==
# 请求解密私钥 非对称算法的公私钥 如SM2RSA 使用者请自行更换
# 对应前端加密公钥 MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdHnzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ==
privateKey: MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAqhHyZfSsYourNxaY7Nt+PrgrxkiA50efORdI5U5lsW79MmFnusUA355oaSXcLhu5xxB38SMSyP2KvuKNPuH3owIDAQABAkAfoiLyL+Z4lf4Myxk6xUDgLaWGximj20CUf+5BKKnlrK+Ed8gAkM0HqoTt2UZwA5E2MzS4EI2gjfQhz5X28uqxAiEA3wNFxfrCZlSZHb0gn2zDpWowcSxQAgiCstxGUoOqlW8CIQDDOerGKH5OmCJ4Z21v+F25WaHYPxCFMvwxpcw99EcvDQIgIdhDTIqD2jfYjPTY8Jj3EDGPbH2HHuffvflECt3Ek60CIQCFRlCkHpi7hthhYhovyloRYsM+IS9h/0BzlEAuO0ktMQIgSPT3aFAgJYwKpqRYKlLDVcflZFCKY7u3UP8iWi1Qw0Y= privateKey: MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAqhHyZfSsYourNxaY7Nt+PrgrxkiA50efORdI5U5lsW79MmFnusUA355oaSXcLhu5xxB38SMSyP2KvuKNPuH3owIDAQABAkAfoiLyL+Z4lf4Myxk6xUDgLaWGximj20CUf+5BKKnlrK+Ed8gAkM0HqoTt2UZwA5E2MzS4EI2gjfQhz5X28uqxAiEA3wNFxfrCZlSZHb0gn2zDpWowcSxQAgiCstxGUoOqlW8CIQDDOerGKH5OmCJ4Z21v+F25WaHYPxCFMvwxpcw99EcvDQIgIdhDTIqD2jfYjPTY8Jj3EDGPbH2HHuffvflECt3Ek60CIQCFRlCkHpi7hthhYhovyloRYsM+IS9h/0BzlEAuO0ktMQIgSPT3aFAgJYwKpqRYKlLDVcflZFCKY7u3UP8iWi1Qw0Y=
springdoc: springdoc:

View File

@ -50,7 +50,10 @@ sms.code.retry.limit.exceed=短信验证码输入错误{0}次,帐户锁定{1}
email.code.not.blank=邮箱验证码不能为空 email.code.not.blank=邮箱验证码不能为空
email.code.retry.limit.count=邮箱验证码输入错误{0}次 email.code.retry.limit.count=邮箱验证码输入错误{0}次
email.code.retry.limit.exceed=邮箱验证码输入错误{0}次,帐户锁定{1}分钟 email.code.retry.limit.exceed=邮箱验证码输入错误{0}次,帐户锁定{1}分钟
xcx.code.not.blank=小程序code不能为空 xcx.code.not.blank=小程序[code]不能为空
social.source.not.blank=第三方登录平台[source]不能为空
social.code.not.blank=第三方登录平台[code]不能为空
social.state.not.blank=第三方登录平台[state]不能为空
##租户 ##租户
tenant.number.not.blank=租户编号不能为空 tenant.number.not.blank=租户编号不能为空
tenant.not.exists=对不起, 您的租户不存在,请联系管理员 tenant.not.exists=对不起, 您的租户不存在,请联系管理员

View File

@ -50,7 +50,10 @@ sms.code.retry.limit.exceed=Sms code input error {0} times, account locked for {
email.code.not.blank=Email code cannot be blank email.code.not.blank=Email code cannot be blank
email.code.retry.limit.count=Email code input error {0} times email.code.retry.limit.count=Email code input error {0} times
email.code.retry.limit.exceed=Email code input error {0} times, account locked for {1} minutes email.code.retry.limit.exceed=Email code input error {0} times, account locked for {1} minutes
xcx.code.not.blank=Mini program code cannot be blank xcx.code.not.blank=Mini program [code] cannot be blank
social.source.not.blank=Social login platform [source] cannot be blank
social.code.not.blank=Social login platform [code] cannot be blank
social.state.not.blank=Social login platform [state] cannot be blank
##租户 ##租户
tenant.number.not.blank=Tenant number cannot be blank tenant.number.not.blank=Tenant number cannot be blank
tenant.not.exists=Sorry, your tenant does not exist. Please contact the administrator tenant.not.exists=Sorry, your tenant does not exist. Please contact the administrator

View File

@ -50,7 +50,10 @@ sms.code.retry.limit.exceed=短信验证码输入错误{0}次,帐户锁定{1}
email.code.not.blank=邮箱验证码不能为空 email.code.not.blank=邮箱验证码不能为空
email.code.retry.limit.count=邮箱验证码输入错误{0}次 email.code.retry.limit.count=邮箱验证码输入错误{0}次
email.code.retry.limit.exceed=邮箱验证码输入错误{0}次,帐户锁定{1}分钟 email.code.retry.limit.exceed=邮箱验证码输入错误{0}次,帐户锁定{1}分钟
xcx.code.not.blank=小程序code不能为空 xcx.code.not.blank=小程序[code]不能为空
social.source.not.blank=第三方登录平台[source]不能为空
social.code.not.blank=第三方登录平台[code]不能为空
social.state.not.blank=第三方登录平台[state]不能为空
##租户 ##租户
tenant.number.not.blank=租户编号不能为空 tenant.number.not.blank=租户编号不能为空
tenant.not.exists=对不起, 您的租户不存在,请联系管理员 tenant.not.exists=对不起, 您的租户不存在,请联系管理员

View File

@ -14,7 +14,7 @@
</description> </description>
<properties> <properties>
<revision>5.1.1</revision> <revision>5.1.2</revision>
</properties> </properties>
<dependencyManagement> <dependencyManagement>

View File

@ -66,12 +66,6 @@
<artifactId>hutool-extra</artifactId> <artifactId>hutool-extra</artifactId>
</dependency> </dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-json</artifactId>
<scope>provided</scope>
</dependency>
<dependency> <dependency>
<groupId>org.projectlombok</groupId> <groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId> <artifactId>lombok</artifactId>

View File

@ -40,6 +40,11 @@ public interface CacheNames {
*/ */
String SYS_USER_NAME = "sys_user_name#30d"; String SYS_USER_NAME = "sys_user_name#30d";
/**
* 用户名称
*/
String SYS_NICKNAME = "sys_nickname#30d";
/** /**
* 部门 * 部门
*/ */
@ -53,7 +58,7 @@ public interface CacheNames {
/** /**
* OSS配置 * OSS配置
*/ */
String SYS_OSS_CONFIG = "sys_oss_config"; String SYS_OSS_CONFIG = GlobalConstants.GLOBAL_REDIS_KEY + "sys_oss_config";
/** /**
* 在线用户 * 在线用户

View File

@ -1,17 +0,0 @@
package org.dromara.common.core.exception;
import java.io.Serial;
/**
* 演示模式异常
*
* @author ruoyi
*/
public class DemoModeException extends RuntimeException {
@Serial
private static final long serialVersionUID = 1L;
public DemoModeException() {
}
}

View File

@ -1,56 +0,0 @@
package org.dromara.common.core.exception;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import java.io.Serial;
/**
* 全局异常
*
* @author ruoyi
*/
@Data
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@AllArgsConstructor
public class GlobalException extends RuntimeException {
@Serial
private static final long serialVersionUID = 1L;
/**
* 错误提示
*/
private String message;
/**
* 错误明细内部调试错误
*/
private String detailMessage;
public GlobalException(String message) {
this.message = message;
}
public String getDetailMessage() {
return detailMessage;
}
public GlobalException setDetailMessage(String detailMessage) {
this.detailMessage = detailMessage;
return this;
}
@Override
public String getMessage() {
return message;
}
public GlobalException setMessage(String message) {
this.message = message;
return this;
}
}

View File

@ -1,26 +0,0 @@
package org.dromara.common.core.exception;
import java.io.Serial;
/**
* 工具类异常
*
* @author ruoyi
*/
public class UtilException extends RuntimeException {
@Serial
private static final long serialVersionUID = 8247610319171014183L;
public UtilException(Throwable e) {
super(e.getMessage(), e);
}
public UtilException(String message) {
super(message);
}
public UtilException(String message, Throwable throwable) {
super(message, throwable);
}
}

View File

@ -1,18 +0,0 @@
package org.dromara.common.core.exception.user;
import java.io.Serial;
/**
* 用户密码不正确或不符合规范异常类
*
* @author ruoyi
*/
public class UserPasswordNotMatchException extends UserException {
@Serial
private static final long serialVersionUID = 1L;
public UserPasswordNotMatchException() {
super("user.password.not.match");
}
}

View File

@ -1,19 +0,0 @@
package org.dromara.common.core.exception.user;
import java.io.Serial;
/**
* 用户错误最大次数异常类
*
* @author ruoyi
*/
public class UserPasswordRetryLimitExceedException extends UserException {
@Serial
private static final long serialVersionUID = 1L;
public UserPasswordRetryLimitExceedException(int retryLimitCount, int lockTime) {
super("user.password.retry.limit.exceed", retryLimitCount, lockTime);
}
}

View File

@ -15,4 +15,12 @@ public interface UserService {
*/ */
String selectUserNameById(Long userId); String selectUserNameById(Long userId);
/**
* 通过用户ID查询用户账户
*
* @param userId 用户ID
* @return 用户账户
*/
String selectNicknameById(Long userId);
} }

View File

@ -1,9 +1,8 @@
package org.dromara.common.core.utils.sql; package org.dromara.common.core.utils.sql;
import org.dromara.common.core.exception.UtilException;
import org.dromara.common.core.utils.StringUtils;
import lombok.AccessLevel; import lombok.AccessLevel;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import org.dromara.common.core.utils.StringUtils;
/** /**
* sql操作工具类 * sql操作工具类
@ -28,7 +27,7 @@ public class SqlUtil {
*/ */
public static String escapeOrderBySql(String value) { public static String escapeOrderBySql(String value) {
if (StringUtils.isNotEmpty(value) && !isValidOrderBySql(value)) { if (StringUtils.isNotEmpty(value) && !isValidOrderBySql(value)) {
throw new UtilException("参数不符合规范,不能进行查询"); throw new IllegalArgumentException("参数不符合规范,不能进行查询");
} }
return value; return value;
} }
@ -50,7 +49,7 @@ public class SqlUtil {
String[] sqlKeywords = StringUtils.split(SQL_REGEX, "\\|"); String[] sqlKeywords = StringUtils.split(SQL_REGEX, "\\|");
for (String sqlKeyword : sqlKeywords) { for (String sqlKeyword : sqlKeywords) {
if (StringUtils.indexOfIgnoreCase(value, sqlKeyword) > -1) { if (StringUtils.indexOfIgnoreCase(value, sqlKeyword) > -1) {
throw new UtilException("参数存在SQL注入风险"); throw new IllegalArgumentException("参数存在SQL注入风险");
} }
} }
} }

View File

@ -37,6 +37,11 @@
<artifactId>hutool-crypto</artifactId> <artifactId>hutool-crypto</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -0,0 +1,20 @@
package org.dromara.common.encrypt.annotation;
import java.lang.annotation.*;
/**
* 强制加密注解
*
* @author Michelle.Chung
*/
@Documented
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiEncrypt {
/**
* 响应加密忽略默认不加密 true 时加密
*/
boolean response() default false;
}

View File

@ -3,10 +3,19 @@ package org.dromara.common.encrypt.filter;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import jakarta.servlet.*; import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.dromara.common.core.constant.HttpStatus;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.SpringUtils;
import org.dromara.common.core.utils.StringUtils; import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.encrypt.annotation.ApiEncrypt;
import org.dromara.common.encrypt.properties.ApiDecryptProperties; import org.dromara.common.encrypt.properties.ApiDecryptProperties;
import org.springframework.http.HttpMethod; import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.HandlerExecutionChain;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import java.io.IOException; import java.io.IOException;
@ -25,8 +34,14 @@ public class CryptoFilter implements Filter {
@Override @Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
ServletRequest requestWrapper = null;
HttpServletRequest servletRequest = (HttpServletRequest) request; HttpServletRequest servletRequest = (HttpServletRequest) request;
HttpServletResponse servletResponse = (HttpServletResponse) response;
boolean encryptFlag = false;
ServletRequest requestWrapper = null;
ServletResponse responseWrapper = null;
EncryptResponseBodyWrapper responseBodyWrapper = null;
// 是否为 json 请求 // 是否为 json 请求
if (StringUtils.startsWithIgnoreCase(request.getContentType(), MediaType.APPLICATION_JSON_VALUE)) { if (StringUtils.startsWithIgnoreCase(request.getContentType(), MediaType.APPLICATION_JSON_VALUE)) {
// 是否为 put 或者 post 请求 // 是否为 put 或者 post 请求
@ -34,16 +49,67 @@ public class CryptoFilter implements Filter {
// 是否存在加密标头 // 是否存在加密标头
String headerValue = servletRequest.getHeader(properties.getHeaderFlag()); String headerValue = servletRequest.getHeader(properties.getHeaderFlag());
if (StringUtils.isNotBlank(headerValue)) { if (StringUtils.isNotBlank(headerValue)) {
requestWrapper = new DecryptRequestBodyWrapper(servletRequest, properties.getPublicKey(), properties.getPrivateKey(), properties.getHeaderFlag()); // 请求解密
requestWrapper = new DecryptRequestBodyWrapper(servletRequest, properties.getPrivateKey(), properties.getHeaderFlag());
// 获取加密注解
ApiEncrypt apiEncrypt = this.getApiEncryptAnnotation(servletRequest);
if (ObjectUtil.isNotNull(apiEncrypt)) {
// 响应加密标志
encryptFlag = apiEncrypt.response();
} else {
// 是否有注解有就报错没有放行
HandlerExceptionResolver exceptionResolver = SpringUtils.getBean(HandlerExceptionResolver.class);
exceptionResolver.resolveException(
servletRequest, servletResponse, null,
new ServiceException("没有访问权限,请联系管理员授权", HttpStatus.FORBIDDEN));
}
}
// 判断是否响应加密
if (encryptFlag) {
responseBodyWrapper = new EncryptResponseBodyWrapper(servletResponse);
responseWrapper = responseBodyWrapper;
} }
} }
} }
chain.doFilter(ObjectUtil.defaultIfNull(requestWrapper, request), response); chain.doFilter(
ObjectUtil.defaultIfNull(requestWrapper, request),
ObjectUtil.defaultIfNull(responseWrapper, response));
if (encryptFlag) {
servletResponse.reset();
// 对原始内容加密
String encryptContent = responseBodyWrapper.getEncryptContent(
servletResponse, properties.getPublicKey(), properties.getHeaderFlag());
// 对加密后的内容写出
servletResponse.getWriter().write(encryptContent);
}
}
/**
* 获取 ApiEncrypt 注解
*/
private ApiEncrypt getApiEncryptAnnotation(HttpServletRequest servletRequest) {
RequestMappingHandlerMapping handlerMapping = SpringUtils.getBean("requestMappingHandlerMapping", RequestMappingHandlerMapping.class);
// 获取注解
try {
HandlerExecutionChain mappingHandler = handlerMapping.getHandler(servletRequest);
if (ObjectUtil.isNotNull(mappingHandler)) {
Object handler = mappingHandler.getHandler();
if (ObjectUtil.isNotNull(handler)) {
// 从handler获取注解
if (handler instanceof HandlerMethod handlerMethod) {
return handlerMethod.getMethodAnnotation(ApiEncrypt.class);
}
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
return null;
} }
@Override @Override
public void destroy() { public void destroy() {
} }
} }

View File

@ -24,7 +24,7 @@ public class DecryptRequestBodyWrapper extends HttpServletRequestWrapper {
private final byte[] body; private final byte[] body;
public DecryptRequestBodyWrapper(HttpServletRequest request, String publicKey, String privateKey, String headerFlag) throws IOException { public DecryptRequestBodyWrapper(HttpServletRequest request, String privateKey, String headerFlag) throws IOException {
super(request); super(request);
// 获取 AES 密码 采用 RSA 加密 // 获取 AES 密码 采用 RSA 加密
String headerRsa = request.getHeader(headerFlag); String headerRsa = request.getHeader(headerFlag);

View File

@ -0,0 +1,120 @@
package org.dromara.common.encrypt.filter;
import cn.hutool.core.util.RandomUtil;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.WriteListener;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpServletResponseWrapper;
import org.dromara.common.encrypt.utils.EncryptUtils;
import java.io.*;
import java.nio.charset.StandardCharsets;
/**
* 加密响应参数包装类
*
* @author Michelle.Chung
*/
public class EncryptResponseBodyWrapper extends HttpServletResponseWrapper {
private final ByteArrayOutputStream byteArrayOutputStream;
private final ServletOutputStream servletOutputStream;
private final PrintWriter printWriter;
public EncryptResponseBodyWrapper(HttpServletResponse response) throws IOException {
super(response);
this.byteArrayOutputStream = new ByteArrayOutputStream();
this.servletOutputStream = this.getOutputStream();
this.printWriter = new PrintWriter(new OutputStreamWriter(byteArrayOutputStream));
}
@Override
public PrintWriter getWriter() {
return printWriter;
}
@Override
public void flushBuffer() throws IOException {
if (servletOutputStream != null) {
servletOutputStream.flush();
}
if (printWriter != null) {
printWriter.flush();
}
}
@Override
public void reset() {
byteArrayOutputStream.reset();
}
public byte[] getResponseData() throws IOException {
flushBuffer();
return byteArrayOutputStream.toByteArray();
}
public String getContent() throws IOException {
flushBuffer();
return byteArrayOutputStream.toString();
}
/**
* 获取加密内容
*
* @param servletResponse response
* @param publicKey RSA公钥 (用于加密 AES 秘钥)
* @param headerFlag 请求头标志
* @return 加密内容
* @throws IOException
*/
public String getEncryptContent(HttpServletResponse servletResponse, String publicKey, String headerFlag) throws IOException {
// 生成秘钥
String aesPassword = RandomUtil.randomString(32);
// 秘钥使用 Base64 编码
String encryptAes = EncryptUtils.encryptByBase64(aesPassword);
// Rsa 公钥加密 Base64 编码
String encryptPassword = EncryptUtils.encryptByRsa(encryptAes, publicKey);
// 设置响应头
servletResponse.setHeader(headerFlag, encryptPassword);
servletResponse.setHeader("Access-Control-Allow-Origin", "*");
servletResponse.setHeader("Access-Control-Allow-Methods", "*");
servletResponse.setCharacterEncoding(StandardCharsets.UTF_8.toString());
// 获取原始内容
String originalBody = this.getContent();
// 对内容进行加密
return EncryptUtils.encryptByAes(originalBody, aesPassword);
}
@Override
public ServletOutputStream getOutputStream() throws IOException {
return new ServletOutputStream() {
@Override
public boolean isReady() {
return false;
}
@Override
public void setWriteListener(WriteListener writeListener) {
}
@Override
public void write(int b) throws IOException {
byteArrayOutputStream.write(b);
}
@Override
public void write(byte[] b) throws IOException {
byteArrayOutputStream.write(b);
}
@Override
public void write(byte[] b, int off, int len) throws IOException {
byteArrayOutputStream.write(b, off, len);
}
};
}
}

View File

@ -21,14 +21,14 @@ public class ApiDecryptProperties {
*/ */
private String headerFlag; private String headerFlag;
/** /**
* 公钥 * 响应加密公钥
*/ */
private String publicKey; private String publicKey;
/** /**
* 私钥 * 请求解密私钥
*/ */
private String privateKey; private String privateKey;
} }

View File

@ -98,9 +98,30 @@ public class CellMergeStrategy extends AbstractMergeStrategy {
cellList.add(new CellRangeAddress(repeatCell.getCurrent() + rowIndex, i + rowIndex - 1, colNum, colNum)); cellList.add(new CellRangeAddress(repeatCell.getCurrent() + rowIndex, i + rowIndex - 1, colNum, colNum));
} }
map.put(field, new RepeatCell(val, i)); map.put(field, new RepeatCell(val, i));
} else if (i == list.size() - 1) { } else if (j == 0) {
if (i > repeatCell.getCurrent()) { if (i == list.size() - 1) {
cellList.add(new CellRangeAddress(repeatCell.getCurrent() + rowIndex, i + rowIndex, colNum, colNum)); if (i > repeatCell.getCurrent()) {
cellList.add(new CellRangeAddress(repeatCell.getCurrent() + rowIndex, i + rowIndex, colNum, colNum));
}
}
} else {
// 判断前面的是否合并了
RepeatCell firstCell = map.get(mergeFields.get(0));
if (repeatCell.getCurrent() != firstCell.getCurrent()) {
if (i == list.size() - 1) {
if (i > repeatCell.getCurrent()) {
cellList.add(new CellRangeAddress(repeatCell.getCurrent() + rowIndex, i + rowIndex, colNum, colNum));
}
} else if (repeatCell.getCurrent() < firstCell.getCurrent()) {
if (i - repeatCell.getCurrent() > 1) {
cellList.add(new CellRangeAddress(repeatCell.getCurrent() + rowIndex, i + rowIndex - 1, colNum, colNum));
}
map.put(field, new RepeatCell(val, i));
}
} else if (i == list.size() - 1) {
if (i > repeatCell.getCurrent()) {
cellList.add(new CellRangeAddress(repeatCell.getCurrent() + rowIndex, i + rowIndex, colNum, colNum));
}
} }
} }
} }

View File

@ -269,6 +269,26 @@ public class ExcelUtil {
} }
} }
/**
* 多sheet模板导出 模板格式为 {key.属性}
*
* @param filename 文件名
* @param templatePath 模板路径 resource 目录下的路径包括模板文件名
* 例如: excel/temp.xlsx
* 重点: 模板文件必须放置到启动类对应的 resource 目录下
* @param data 模板需要的数据
* @param response 响应体
*/
public static void exportTemplateMultiSheet(List<Map<String, Object>> data, String filename, String templatePath, HttpServletResponse response) {
try {
resetResponse(filename, response);
ServletOutputStream os = response.getOutputStream();
exportTemplateMultiSheet(data, templatePath, os);
} catch (IOException e) {
throw new RuntimeException("导出Excel异常");
}
}
/** /**
* 多表多数据模板导出 模板格式为 {key.属性} * 多表多数据模板导出 模板格式为 {key.属性}
* *
@ -303,6 +323,42 @@ public class ExcelUtil {
excelWriter.finish(); excelWriter.finish();
} }
/**
* 多sheet模板导出 模板格式为 {key.属性}
*
* @param templatePath 模板路径 resource 目录下的路径包括模板文件名
* 例如: excel/temp.xlsx
* 重点: 模板文件必须放置到启动类对应的 resource 目录下
* @param data 模板需要的数据
* @param os 输出流
*/
public static void exportTemplateMultiSheet(List<Map<String, Object>> data, String templatePath, OutputStream os) {
ClassPathResource templateResource = new ClassPathResource(templatePath);
ExcelWriter excelWriter = EasyExcel.write(os)
.withTemplate(templateResource.getStream())
.autoCloseStream(false)
// 大数值自动转换 防止失真
.registerConverter(new ExcelBigNumberConvert())
.build();
if (CollUtil.isEmpty(data)) {
throw new IllegalArgumentException("数据为空");
}
for (int i = 0; i < data.size(); i++) {
WriteSheet writeSheet = EasyExcel.writerSheet(i).build();
for (Map.Entry<String, Object> map : data.get(i).entrySet()) {
// 设置列表后续还有数据
FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
if (map.getValue() instanceof Collection) {
// 多表导出必须使用 FillWrapper
excelWriter.fill(new FillWrapper(map.getKey(), (Collection<?>) map.getValue()), fillConfig, writeSheet);
} else {
excelWriter.fill(map.getValue(), writeSheet);
}
}
}
excelWriter.finish();
}
/** /**
* 重置响应体 * 重置响应体
*/ */

View File

@ -32,9 +32,20 @@
<artifactId>dynamic-datasource-spring-boot3-starter</artifactId> <artifactId>dynamic-datasource-spring-boot3-starter</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<dependency> <dependency>
<groupId>com.baomidou</groupId> <groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId> <artifactId>mybatis-plus-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
</exclusion>
</exclusions>
</dependency> </dependency>
<!-- sql性能分析插件 --> <!-- sql性能分析插件 -->

View File

@ -35,7 +35,7 @@ public class MybatisExceptionHandler {
public R<Void> handleCannotFindDataSourceException(MyBatisSystemException e, HttpServletRequest request) { public R<Void> handleCannotFindDataSourceException(MyBatisSystemException e, HttpServletRequest request) {
String requestURI = request.getRequestURI(); String requestURI = request.getRequestURI();
String message = e.getMessage(); String message = e.getMessage();
if (message.contains("CannotFindDataSourceException")) { if ("CannotFindDataSourceException".contains(message)) {
log.error("请求地址'{}', 未找到数据源", requestURI); log.error("请求地址'{}', 未找到数据源", requestURI);
return R.fail("未找到数据源,请联系管理员确认"); return R.fail("未找到数据源,请联系管理员确认");
} }

View File

@ -149,7 +149,12 @@ public class PlusDataPermissionHandler {
int index = sb.lastIndexOf("."); int index = sb.lastIndexOf(".");
String clazzName = sb.substring(0, index); String clazzName = sb.substring(0, index);
String methodName = sb.substring(index + 1, sb.length()); String methodName = sb.substring(index + 1, sb.length());
Class<?> clazz = ClassUtil.loadClass(clazzName); Class<?> clazz;
try {
clazz = ClassUtil.loadClass(clazzName);
} catch (Exception e) {
return null;
}
List<Method> methods = Arrays.stream(ClassUtil.getDeclaredMethods(clazz)) List<Method> methods = Arrays.stream(ClassUtil.getDeclaredMethods(clazz))
.filter(method -> method.getName().equals(methodName)).toList(); .filter(method -> method.getName().equals(methodName)).toList();
DataPermission dataPermission; DataPermission dataPermission;

View File

@ -1,5 +1,7 @@
package org.dromara.common.oss.constant; package org.dromara.common.oss.constant;
import org.dromara.common.core.constant.GlobalConstants;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@ -13,7 +15,7 @@ public interface OssConstant {
/** /**
* 默认配置KEY * 默认配置KEY
*/ */
String DEFAULT_CONFIG_KEY = "sys_oss:default_config"; String DEFAULT_CONFIG_KEY = GlobalConstants.GLOBAL_REDIS_KEY + "sys_oss:default_config";
/** /**
* 预览列表资源开关Key * 预览列表资源开关Key

View File

@ -39,7 +39,7 @@ public class OssFactory {
/** /**
* 根据类型获取实例 * 根据类型获取实例
*/ */
public static OssClient instance(String configKey) { public static synchronized OssClient instance(String configKey) {
String json = CacheUtils.get(CacheNames.SYS_OSS_CONFIG, configKey); String json = CacheUtils.get(CacheNames.SYS_OSS_CONFIG, configKey);
if (json == null) { if (json == null) {
throw new OssException("系统异常, '" + configKey + "'配置信息不存在!"); throw new OssException("系统异常, '" + configKey + "'配置信息不存在!");

View File

@ -49,6 +49,8 @@ public class RedisConfig {
CompositeCodec codec = new CompositeCodec(StringCodec.INSTANCE, jsonCodec, jsonCodec); CompositeCodec codec = new CompositeCodec(StringCodec.INSTANCE, jsonCodec, jsonCodec);
config.setThreads(redissonProperties.getThreads()) config.setThreads(redissonProperties.getThreads())
.setNettyThreads(redissonProperties.getNettyThreads()) .setNettyThreads(redissonProperties.getNettyThreads())
// 缓存 Lua 脚本 减少网络传输(redisson 大部分的功能都是基于 Lua 脚本实现)
.setUseScriptCache(true)
.setCodec(codec); .setCodec(codec);
RedissonProperties.SingleServerConfig singleServerConfig = redissonProperties.getSingleServerConfig(); RedissonProperties.SingleServerConfig singleServerConfig = redissonProperties.getSingleServerConfig();
if (ObjectUtil.isNotNull(singleServerConfig)) { if (ObjectUtil.isNotNull(singleServerConfig)) {

View File

@ -224,8 +224,12 @@ public class QueueUtils {
/** /**
* 订阅阻塞队列(可订阅所有实现类 例如: 延迟 优先 有界 ) * 订阅阻塞队列(可订阅所有实现类 例如: 延迟 优先 有界 )
*/ */
public static <T> void subscribeBlockingQueue(String queueName, Consumer<T> consumer) { public static <T> void subscribeBlockingQueue(String queueName, Consumer<T> consumer, boolean isDelayed) {
RBlockingQueue<T> queue = CLIENT.getBlockingQueue(queueName); RBlockingQueue<T> queue = CLIENT.getBlockingQueue(queueName);
if (isDelayed) {
// 订阅延迟队列
CLIENT.getDelayedQueue(queue);
}
queue.subscribeOnElements(consumer); queue.subscribeOnElements(consumer);
} }

View File

@ -141,6 +141,18 @@ public class RedisUtils {
return bucket.setIfAbsent(value, duration); return bucket.setIfAbsent(value, duration);
} }
/**
* 如果存在则设置 并返回 true 如果存在则返回 false
*
* @param key 缓存的键值
* @param value 缓存的值
* @return set成功或失败
*/
public static <T> boolean setObjectIfExists(final String key, final T value, final Duration duration) {
RBucket<T> bucket = CLIENT.getBucket(key);
return bucket.setIfExists(value, duration);
}
/** /**
* 注册对象监听器 * 注册对象监听器
* <p> * <p>
@ -242,6 +254,18 @@ public class RedisUtils {
return rList.addAll(dataList); return rList.addAll(dataList);
} }
/**
* 追加缓存List数据
*
* @param key 缓存的键值
* @param data 待缓存的数据
* @return 缓存的对象
*/
public static <T> boolean addCacheList(final String key, final T data) {
RList<T> rList = CLIENT.getList(key);
return rList.add(data);
}
/** /**
* 注册List监听器 * 注册List监听器
* <p> * <p>
@ -266,6 +290,19 @@ public class RedisUtils {
return rList.readAll(); return rList.readAll();
} }
/**
* 获得缓存的list对象(范围)
*
* @param key 缓存的键值
* @param form 起始下标
* @param to 截止下标
* @return 缓存键值对应的数据
*/
public static <T> List<T> getCacheListRange(final String key, int form, int to) {
RList<T> rList = CLIENT.getList(key);
return rList.range(form, to);
}
/** /**
* 缓存Set * 缓存Set
* *
@ -278,6 +315,18 @@ public class RedisUtils {
return rSet.addAll(dataSet); return rSet.addAll(dataSet);
} }
/**
* 追加缓存Set数据
*
* @param key 缓存的键值
* @param data 待缓存的数据
* @return 缓存的对象
*/
public static <T> boolean addCacheSet(final String key, final T data) {
RSet<T> rSet = CLIENT.getSet(key);
return rSet.add(data);
}
/** /**
* 注册Set监听器 * 注册Set监听器
* <p> * <p>

View File

@ -10,7 +10,6 @@ import org.dromara.common.satoken.core.service.SaPermissionImpl;
import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.PropertySource; import org.springframework.context.annotation.PropertySource;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/** /**
* sa-token 配置 * sa-token 配置
@ -19,7 +18,7 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
*/ */
@AutoConfiguration @AutoConfiguration
@PropertySource(value = "classpath:common-satoken.yml", factory = YmlPropertySourceFactory.class) @PropertySource(value = "classpath:common-satoken.yml", factory = YmlPropertySourceFactory.class)
public class SaTokenConfig implements WebMvcConfigurer { public class SaTokenConfig {
@Bean @Bean
public StpLogic getStpLogicJwt() { public StpLogic getStpLogicJwt() {

View File

@ -45,12 +45,9 @@ public class PlusSaTokenDao implements SaTokenDao {
*/ */
@Override @Override
public void update(String key, String value) { public void update(String key, String value) {
long expire = getTimeout(key); if (RedisUtils.hasKey(key)) {
// -2 = 无此键 RedisUtils.setCacheObject(key, value, true);
if (expire == NOT_VALUE_EXPIRE) {
return;
} }
this.set(key, value, expire);
} }
/** /**
@ -75,17 +72,6 @@ public class PlusSaTokenDao implements SaTokenDao {
*/ */
@Override @Override
public void updateTimeout(String key, long timeout) { public void updateTimeout(String key, long timeout) {
// 判断是否想要设置为永久
if (timeout == NEVER_EXPIRE) {
long expire = getTimeout(key);
if (expire == NEVER_EXPIRE) {
// 如果其已经被设置为永久则不作任何处理
} else {
// 如果尚未被设置为永久那么再次set一次
this.set(key, this.get(key), timeout);
}
return;
}
RedisUtils.expire(key, Duration.ofSeconds(timeout)); RedisUtils.expire(key, Duration.ofSeconds(timeout));
} }
@ -119,12 +105,9 @@ public class PlusSaTokenDao implements SaTokenDao {
*/ */
@Override @Override
public void updateObject(String key, Object object) { public void updateObject(String key, Object object) {
long expire = getObjectTimeout(key); if (RedisUtils.hasKey(key)) {
// -2 = 无此键 RedisUtils.setCacheObject(key, object, true);
if (expire == NOT_VALUE_EXPIRE) {
return;
} }
this.setObject(key, object, expire);
} }
/** /**
@ -149,17 +132,6 @@ public class PlusSaTokenDao implements SaTokenDao {
*/ */
@Override @Override
public void updateObjectTimeout(String key, long timeout) { public void updateObjectTimeout(String key, long timeout) {
// 判断是否想要设置为永久
if (timeout == NEVER_EXPIRE) {
long expire = getObjectTimeout(key);
if (expire == NEVER_EXPIRE) {
// 如果其已经被设置为永久则不作任何处理
} else {
// 如果尚未被设置为永久那么再次set一次
this.setObject(key, this.getObject(key), timeout);
}
return;
}
RedisUtils.expire(key, Duration.ofSeconds(timeout)); RedisUtils.expire(key, Duration.ofSeconds(timeout));
} }

View File

@ -15,6 +15,7 @@ import org.dromara.common.core.domain.model.LoginUser;
import org.dromara.common.core.enums.UserType; import org.dromara.common.core.enums.UserType;
import java.util.Set; import java.util.Set;
import java.util.function.Supplier;
/** /**
* 登录鉴权助手 * 登录鉴权助手
@ -36,6 +37,7 @@ public class LoginHelper {
public static final String USER_KEY = "userId"; public static final String USER_KEY = "userId";
public static final String DEPT_KEY = "deptId"; public static final String DEPT_KEY = "deptId";
public static final String CLIENT_KEY = "clientid"; public static final String CLIENT_KEY = "clientid";
public static final String TENANT_ADMIN_KEY = "isTenantAdmin";
/** /**
* 登录系统 基于 设备类型 * 登录系统 基于 设备类型
@ -55,32 +57,27 @@ public class LoginHelper {
model.setExtra(TENANT_KEY, loginUser.getTenantId()) model.setExtra(TENANT_KEY, loginUser.getTenantId())
.setExtra(USER_KEY, loginUser.getUserId()) .setExtra(USER_KEY, loginUser.getUserId())
.setExtra(DEPT_KEY, loginUser.getDeptId())); .setExtra(DEPT_KEY, loginUser.getDeptId()));
StpUtil.getSession().set(LOGIN_USER_KEY, loginUser); StpUtil.getTokenSession().set(LOGIN_USER_KEY, loginUser);
} }
/** /**
* 获取用户(多级缓存) * 获取用户(多级缓存)
*/ */
public static LoginUser getLoginUser() { public static LoginUser getLoginUser() {
LoginUser loginUser = (LoginUser) SaHolder.getStorage().get(LOGIN_USER_KEY); return (LoginUser) getStorageIfAbsentSet(LOGIN_USER_KEY, () -> {
if (loginUser != null) { SaSession session = StpUtil.getTokenSession();
return loginUser; if (ObjectUtil.isNull(session)) {
} return null;
SaSession session = StpUtil.getSession(); }
if (ObjectUtil.isNull(session)) { return session.get(LOGIN_USER_KEY);
return null; });
}
loginUser = (LoginUser) session.get(LOGIN_USER_KEY);
SaHolder.getStorage().set(LOGIN_USER_KEY, loginUser);
return loginUser;
} }
/** /**
* 获取用户基于token * 获取用户基于token
*/ */
public static LoginUser getLoginUser(String token) { public static LoginUser getLoginUser(String token) {
Object loginId = StpUtil.getLoginIdByToken(token); SaSession session = StpUtil.getTokenSessionByToken(token);
SaSession session = StpUtil.getSessionByLoginId(loginId);
if (ObjectUtil.isNull(session)) { if (ObjectUtil.isNull(session)) {
return null; return null;
} }
@ -109,17 +106,7 @@ public class LoginHelper {
} }
private static Object getExtra(String key) { private static Object getExtra(String key) {
Object obj; return getStorageIfAbsentSet(key, () -> StpUtil.getExtra(key));
try {
obj = SaHolder.getStorage().get(key);
if (ObjectUtil.isNull(obj)) {
obj = StpUtil.getExtra(key);
SaHolder.getStorage().set(key, obj);
}
} catch (Exception e) {
return null;
}
return obj;
} }
/** /**
@ -162,7 +149,26 @@ public class LoginHelper {
} }
public static boolean isTenantAdmin() { public static boolean isTenantAdmin() {
return isTenantAdmin(getLoginUser().getRolePermission()); Object value = getStorageIfAbsentSet(TENANT_ADMIN_KEY, () -> {
return isTenantAdmin(getLoginUser().getRolePermission());
});
return Convert.toBool(value);
} }
public static boolean isLogin() {
return getLoginUser() != null;
}
public static Object getStorageIfAbsentSet(String key, Supplier<Object> handle) {
try {
Object obj = SaHolder.getStorage().get(key);
if (ObjectUtil.isNull(obj)) {
obj = handle.get();
SaHolder.getStorage().set(key, obj);
}
return obj;
} catch (Exception e) {
return null;
}
}
} }

View File

@ -10,7 +10,6 @@ import jakarta.validation.ConstraintViolation;
import jakarta.validation.ConstraintViolationException; import jakarta.validation.ConstraintViolationException;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.R; import org.dromara.common.core.domain.R;
import org.dromara.common.core.exception.DemoModeException;
import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.exception.base.BaseException; import org.dromara.common.core.exception.base.BaseException;
import org.dromara.common.core.utils.StreamUtils; import org.dromara.common.core.utils.StreamUtils;
@ -162,11 +161,4 @@ public class GlobalExceptionHandler {
return R.fail(message); return R.fail(message);
} }
/**
* 演示模式异常
*/
@ExceptionHandler(DemoModeException.class)
public R<Void> handleDemoModeException(DemoModeException e) {
return R.fail("演示模式,不允许操作");
}
} }

View File

@ -3,13 +3,12 @@ package org.dromara.common.sms.config;
import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfiguration;
/** /**
* 短信配置类 * 短信配置类(暂时没用 预留扩展)
* *
* @author Lion Li * @author Lion Li
* @version 4.2.0 * @version 4.2.0
*/ */
@AutoConfiguration @AutoConfiguration
//@EnableConfigurationProperties(SmsProperties.class) public class SmsAutoConfiguration {
public class SmsConfig {
} }

View File

@ -1,19 +0,0 @@
//package org.dromara.common.sms.config.properties;
//
//import lombok.Data;
//import org.springframework.boot.context.properties.ConfigurationProperties;
//
///**
// * SMS短信 配置属性
// *
// * @author Lion Li
// * @version 4.2.0
// */
//@Data
//@ConfigurationProperties(prefix = "sms")
//public class SmsProperties {
//
// private Boolean enabled;
//
//
//}

View File

@ -1 +1 @@
org.dromara.common.sms.config.SmsConfig org.dromara.common.sms.config.SmsAutoConfiguration

View File

@ -35,33 +35,34 @@ public class SocialUtils {
if (ObjectUtil.isNull(obj)) { if (ObjectUtil.isNull(obj)) {
throw new AuthException("不支持的第三方登录类型"); throw new AuthException("不支持的第三方登录类型");
} }
String clientId = obj.getClientId(); AuthConfig.AuthConfigBuilder builder = AuthConfig.builder()
String clientSecret = obj.getClientSecret(); .clientId(obj.getClientId())
String redirectUri = obj.getRedirectUri(); .clientSecret(obj.getClientSecret())
.redirectUri(obj.getRedirectUri());
return switch (source.toLowerCase()) { return switch (source.toLowerCase()) {
case "dingtalk" -> new AuthDingTalkRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret).redirectUri(redirectUri).build(), STATE_CACHE); case "dingtalk" -> new AuthDingTalkRequest(builder.build(), STATE_CACHE);
case "baidu" -> new AuthBaiduRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret).redirectUri(redirectUri).build(), STATE_CACHE); case "baidu" -> new AuthBaiduRequest(builder.build(), STATE_CACHE);
case "github" -> new AuthGithubRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret).redirectUri(redirectUri).build(), STATE_CACHE); case "github" -> new AuthGithubRequest(builder.build(), STATE_CACHE);
case "gitee" -> new AuthGiteeRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret).redirectUri(redirectUri).build(), STATE_CACHE); case "gitee" -> new AuthGiteeRequest(builder.build(), STATE_CACHE);
case "weibo" -> new AuthWeiboRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret).redirectUri(redirectUri).build(), STATE_CACHE); case "weibo" -> new AuthWeiboRequest(builder.build(), STATE_CACHE);
case "coding" -> new AuthCodingRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret).redirectUri(redirectUri).build(), STATE_CACHE); case "coding" -> new AuthCodingRequest(builder.build(), STATE_CACHE);
case "oschina" -> new AuthOschinaRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret).redirectUri(redirectUri).build(), STATE_CACHE); case "oschina" -> new AuthOschinaRequest(builder.build(), STATE_CACHE);
// 支付宝在创建回调地址时不允许使用localhost或者127.0.0.1所以这儿的回调地址使用的局域网内的ip // 支付宝在创建回调地址时不允许使用localhost或者127.0.0.1所以这儿的回调地址使用的局域网内的ip
case "alipay_wallet" -> new AuthAlipayRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret).redirectUri(redirectUri).build(), socialProperties.getType().get("alipay_wallet").getAlipayPublicKey(), STATE_CACHE); case "alipay_wallet" -> new AuthAlipayRequest(builder.build(), socialProperties.getType().get("alipay_wallet").getAlipayPublicKey(), STATE_CACHE);
case "qq" -> new AuthQqRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret).redirectUri(redirectUri).build(), STATE_CACHE); case "qq" -> new AuthQqRequest(builder.build(), STATE_CACHE);
case "wechat_open" -> new AuthWeChatOpenRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret).redirectUri(redirectUri).build(), STATE_CACHE); case "wechat_open" -> new AuthWeChatOpenRequest(builder.build(), STATE_CACHE);
case "taobao" -> new AuthTaobaoRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret).redirectUri(redirectUri).build(), STATE_CACHE); case "taobao" -> new AuthTaobaoRequest(builder.build(), STATE_CACHE);
case "douyin" -> new AuthDouyinRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret).redirectUri(redirectUri).build(), STATE_CACHE); case "douyin" -> new AuthDouyinRequest(builder.build(), STATE_CACHE);
case "linkedin" -> new AuthLinkedinRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret).redirectUri(redirectUri).build(), STATE_CACHE); case "linkedin" -> new AuthLinkedinRequest(builder.build(), STATE_CACHE);
case "microsoft" -> new AuthMicrosoftRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret).redirectUri(redirectUri).build(), STATE_CACHE); case "microsoft" -> new AuthMicrosoftRequest(builder.build(), STATE_CACHE);
case "renren" -> new AuthRenrenRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret).redirectUri(redirectUri).build(), STATE_CACHE); case "renren" -> new AuthRenrenRequest(builder.build(), STATE_CACHE);
case "stack_overflow" -> new AuthStackOverflowRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret).redirectUri(redirectUri).stackOverflowKey("").build(), STATE_CACHE); case "stack_overflow" -> new AuthStackOverflowRequest(builder.stackOverflowKey("").build(), STATE_CACHE);
case "huawei" -> new AuthHuaweiRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret).redirectUri(redirectUri).build(), STATE_CACHE); case "huawei" -> new AuthHuaweiRequest(builder.build(), STATE_CACHE);
case "wechat_enterprise" -> new AuthWeChatEnterpriseQrcodeRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret).redirectUri(redirectUri).agentId("").build(), STATE_CACHE); case "wechat_enterprise" -> new AuthWeChatEnterpriseQrcodeRequest(builder.agentId("").build(), STATE_CACHE);
case "gitlab" -> new AuthGitlabRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret).redirectUri(redirectUri).build(), STATE_CACHE); case "gitlab" -> new AuthGitlabRequest(builder.build(), STATE_CACHE);
case "wechat_mp" -> new AuthWeChatMpRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret).redirectUri(redirectUri).build(), STATE_CACHE); case "wechat_mp" -> new AuthWeChatMpRequest(builder.build(), STATE_CACHE);
case "aliyun" -> new AuthAliyunRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret).redirectUri(redirectUri).build(), STATE_CACHE); case "aliyun" -> new AuthAliyunRequest(builder.build(), STATE_CACHE);
case "maxkey" -> new AuthMaxKeyRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret).redirectUri(redirectUri).build(), STATE_CACHE); case "maxkey" -> new AuthMaxKeyRequest(builder.build(), STATE_CACHE);
default -> throw new AuthException("未获取到有效的Auth配置"); default -> throw new AuthException("未获取到有效的Auth配置");
}; };
} }

View File

@ -1,7 +1,7 @@
package org.dromara.common.tenant.helper; package org.dromara.common.tenant.helper;
import cn.dev33.satoken.context.SaHolder; import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.spring.SpringMVCUtil; import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.convert.Convert; import cn.hutool.core.convert.Convert;
import com.alibaba.ttl.TransmittableThreadLocal; import com.alibaba.ttl.TransmittableThreadLocal;
import com.baomidou.mybatisplus.core.plugins.IgnoreStrategy; import com.baomidou.mybatisplus.core.plugins.IgnoreStrategy;
@ -82,10 +82,13 @@ public class TenantHelper {
/** /**
* 设置动态租户(一直有效 需要手动清理) * 设置动态租户(一直有效 需要手动清理)
* <p> * <p>
* 如果为非web环境 那么只在当前线程内生效 * 如果为未登录状态下 那么只在当前线程内生效
*/ */
public static void setDynamic(String tenantId) { public static void setDynamic(String tenantId) {
if (!SpringMVCUtil.isWeb()) { if (!isEnable()) {
return;
}
if (!isLogin()) {
TEMP_DYNAMIC_TENANT.set(tenantId); TEMP_DYNAMIC_TENANT.set(tenantId);
return; return;
} }
@ -97,10 +100,13 @@ public class TenantHelper {
/** /**
* 获取动态租户(一直有效 需要手动清理) * 获取动态租户(一直有效 需要手动清理)
* <p> * <p>
* 如果为非web环境 那么只在当前线程内生效 * 如果为未登录状态下 那么只在当前线程内生效
*/ */
public static String getDynamic() { public static String getDynamic() {
if (!SpringMVCUtil.isWeb()) { if (!isEnable()) {
return null;
}
if (!isLogin()) {
return TEMP_DYNAMIC_TENANT.get(); return TEMP_DYNAMIC_TENANT.get();
} }
String cacheKey = DYNAMIC_TENANT_KEY + ":" + LoginHelper.getUserId(); String cacheKey = DYNAMIC_TENANT_KEY + ":" + LoginHelper.getUserId();
@ -117,7 +123,10 @@ public class TenantHelper {
* 清除动态租户 * 清除动态租户
*/ */
public static void clearDynamic() { public static void clearDynamic() {
if (!SpringMVCUtil.isWeb()) { if (!isEnable()) {
return;
}
if (!isLogin()) {
TEMP_DYNAMIC_TENANT.remove(); TEMP_DYNAMIC_TENANT.remove();
return; return;
} }
@ -126,10 +135,41 @@ public class TenantHelper {
SaHolder.getStorage().delete(cacheKey); SaHolder.getStorage().delete(cacheKey);
} }
/**
* 在动态租户中执行
*
* @param handle 处理执行方法
*/
public static void dynamic(String tenantId, Runnable handle) {
setDynamic(tenantId);
try {
handle.run();
} finally {
clearDynamic();
}
}
/**
* 在动态租户中执行
*
* @param handle 处理执行方法
*/
public static <T> T dynamic(String tenantId, Supplier<T> handle) {
setDynamic(tenantId);
try {
return handle.get();
} finally {
clearDynamic();
}
}
/** /**
* 获取当前租户id(动态租户优先) * 获取当前租户id(动态租户优先)
*/ */
public static String getTenantId() { public static String getTenantId() {
if (!isEnable()) {
return null;
}
String tenantId = TenantHelper.getDynamic(); String tenantId = TenantHelper.getDynamic();
if (StringUtils.isBlank(tenantId)) { if (StringUtils.isBlank(tenantId)) {
tenantId = LoginHelper.getTenantId(); tenantId = LoginHelper.getTenantId();
@ -137,4 +177,13 @@ public class TenantHelper {
return tenantId; return tenantId;
} }
private static boolean isLogin() {
try {
StpUtil.checkLogin();
return true;
} catch (Exception e) {
return false;
}
}
} }

View File

@ -12,6 +12,11 @@ public interface TransConstant {
*/ */
String USER_ID_TO_NAME = "user_id_to_name"; String USER_ID_TO_NAME = "user_id_to_name";
/**
* 用户id转用户名称
*/
String USER_ID_TO_NICKNAME = "user_id_to_nickname";
/** /**
* 部门id转名称 * 部门id转名称
*/ */

View File

@ -0,0 +1,27 @@
package org.dromara.common.translation.core.impl;
import lombok.AllArgsConstructor;
import org.dromara.common.core.service.UserService;
import org.dromara.common.translation.annotation.TranslationType;
import org.dromara.common.translation.constant.TransConstant;
import org.dromara.common.translation.core.TranslationInterface;
/**
* 用户名称翻译实现
*
* @author may
*/
@AllArgsConstructor
@TranslationType(type = TransConstant.USER_ID_TO_NICKNAME)
public class NicknameTranslationImpl implements TranslationInterface<String> {
private final UserService userService;
@Override
public String translation(Object key, String other) {
if (key instanceof Long id) {
return userService.selectNicknameById(id);
}
return null;
}
}

View File

@ -3,3 +3,4 @@ org.dromara.common.translation.core.impl.DeptNameTranslationImpl
org.dromara.common.translation.core.impl.DictTypeTranslationImpl org.dromara.common.translation.core.impl.DictTypeTranslationImpl
org.dromara.common.translation.core.impl.OssUrlTranslationImpl org.dromara.common.translation.core.impl.OssUrlTranslationImpl
org.dromara.common.translation.core.impl.UserNameTranslationImpl org.dromara.common.translation.core.impl.UserNameTranslationImpl
org.dromara.common.translation.core.impl.NicknameTranslationImpl

View File

@ -98,7 +98,7 @@ public class WebSocketUtils {
private static void sendMessage(WebSocketSession session, WebSocketMessage<?> message) { private static void sendMessage(WebSocketSession session, WebSocketMessage<?> message) {
if (session == null || !session.isOpen()) { if (session == null || !session.isOpen()) {
log.error("[send] session会话已经关闭"); log.warn("[send] session会话已经关闭");
} else { } else {
try { try {
session.sendMessage(message); session.sendMessage(message);

View File

@ -7,10 +7,11 @@ RUN mkdir -p /ruoyi/monitor/logs
WORKDIR /ruoyi/monitor WORKDIR /ruoyi/monitor
ENV LANG=C.UTF-8 LC_ALL=C.UTF-8 ENV LANG=C.UTF-8 LC_ALL=C.UTF-8 JAVA_OPTS=""
EXPOSE 9090 EXPOSE 9090
ADD ./target/ruoyi-monitor-admin.jar ./app.jar ADD ./target/ruoyi-monitor-admin.jar ./app.jar
ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "app.jar"] ENTRYPOINT java -Djava.security.egd=file:/dev/./urandom -jar app.jar \
-XX:+HeapDumpOnOutOfMemoryError -Xlog:gc*,:time,tags,level -XX:+UseZGC ${JAVA_OPTS}

View File

@ -7,10 +7,11 @@ RUN mkdir -p /ruoyi/powerjob/logs
WORKDIR /ruoyi/powerjob WORKDIR /ruoyi/powerjob
ENV LANG=C.UTF-8 LC_ALL=C.UTF-8 ENV LANG=C.UTF-8 LC_ALL=C.UTF-8 JAVA_OPTS="-Xms512m -Xmx1024m"
EXPOSE 7700 EXPOSE 7700
ADD ./target/ruoyi-powerjob-server.jar ./app.jar ADD ./target/ruoyi-powerjob-server.jar ./app.jar
ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "app.jar"] ENTRYPOINT java -Djava.security.egd=file:/dev/./urandom -jar app.jar \
-XX:+HeapDumpOnOutOfMemoryError -Xlog:gc*,:time,tags,level -XX:+UseZGC ${JAVA_OPTS}

View File

@ -10,7 +10,7 @@
<artifactId>ruoyi-powerjob-server</artifactId> <artifactId>ruoyi-powerjob-server</artifactId>
<properties> <properties>
<spring-boot.version>2.7.17</spring-boot.version> <spring-boot.version>2.7.18</spring-boot.version>
<spring-boot-admin.version>2.7.11</spring-boot-admin.version> <spring-boot-admin.version>2.7.11</spring-boot-admin.version>
</properties> </properties>
<dependencyManagement> <dependencyManagement>

View File

@ -94,6 +94,41 @@ public class TestExcelController {
exportExcelService.exportWithOptions(response); exportExcelService.exportWithOptions(response);
} }
/**
* 多个sheet导出
*/
@GetMapping("/exportTemplateMultiSheet")
public void exportTemplateMultiSheet(HttpServletResponse response) {
List<TestObj1> list1 = new ArrayList<>();
list1.add(new TestObj1("list1测试1", "list1测试2", "list1测试3"));
list1.add(new TestObj1("list1测试4", "list1测试5", "list1测试6"));
List<TestObj1> list2 = new ArrayList<>();
list2.add(new TestObj1("list2测试1", "list2测试2", "list2测试3"));
list2.add(new TestObj1("list2测试4", "list2测试5", "list2测试6"));
List<TestObj1> list3 = new ArrayList<>();
list3.add(new TestObj1("list3测试1", "list3测试2", "list3测试3"));
list3.add(new TestObj1("list3测试4", "list3测试5", "list3测试6"));
List<TestObj1> list4 = new ArrayList<>();
list4.add(new TestObj1("list4测试1", "list4测试2", "list4测试3"));
list4.add(new TestObj1("list4测试4", "list4测试5", "list4测试6"));
List<Map<String, Object>> list = new ArrayList<>();
Map<String, Object> sheetMap1 = new HashMap<>();
sheetMap1.put("data1", list1);
Map<String, Object> sheetMap2 = new HashMap<>();
sheetMap2.put("data2", list2);
Map<String, Object> sheetMap3 = new HashMap<>();
sheetMap3.put("data3", list3);
Map<String, Object> sheetMap4 = new HashMap<>();
sheetMap4.put("data4", list4);
list.add(sheetMap1);
list.add(sheetMap2);
list.add(sheetMap3);
list.add(sheetMap4);
ExcelUtil.exportTemplateMultiSheet(list, "多sheet列表", "excel/多sheet列表.xlsx", response);
}
/** /**
* 导入表格 * 导入表格
*/ */

View File

@ -1,5 +1,6 @@
package org.dromara.demo.controller.queue; package org.dromara.demo.controller.queue;
import cn.dev33.satoken.annotation.SaIgnore;
import org.dromara.common.core.domain.R; import org.dromara.common.core.domain.R;
import org.dromara.common.redis.utils.QueueUtils; import org.dromara.common.redis.utils.QueueUtils;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
@ -22,6 +23,7 @@ import java.util.concurrent.TimeUnit;
* @author Lion Li * @author Lion Li
* @version 3.6.0 * @version 3.6.0
*/ */
@SaIgnore
@Slf4j @Slf4j
@RequiredArgsConstructor @RequiredArgsConstructor
@RestController @RestController
@ -40,7 +42,7 @@ public class DelayedQueueController {
QueueUtils.subscribeBlockingQueue(queueName, (String orderNum) -> { QueueUtils.subscribeBlockingQueue(queueName, (String orderNum) -> {
// 观察接收时间 // 观察接收时间
log.info("通道: {}, 收到数据: {}", queueName, orderNum); log.info("通道: {}, 收到数据: {}", queueName, orderNum);
}); }, true);
return R.ok("操作成功"); return R.ok("操作成功");
} }

View File

@ -40,7 +40,7 @@ public class SysOssConfigController extends BaseController {
/** /**
* 查询对象存储配置列表 * 查询对象存储配置列表
*/ */
@SaCheckPermission("system:oss:list") @SaCheckPermission("system:ossConfig:list")
@GetMapping("/list") @GetMapping("/list")
public TableDataInfo<SysOssConfigVo> list(@Validated(QueryGroup.class) SysOssConfigBo bo, PageQuery pageQuery) { public TableDataInfo<SysOssConfigVo> list(@Validated(QueryGroup.class) SysOssConfigBo bo, PageQuery pageQuery) {
return ossConfigService.queryPageList(bo, pageQuery); return ossConfigService.queryPageList(bo, pageQuery);
@ -51,7 +51,7 @@ public class SysOssConfigController extends BaseController {
* *
* @param ossConfigId OSS配置ID * @param ossConfigId OSS配置ID
*/ */
@SaCheckPermission("system:oss:query") @SaCheckPermission("system:ossConfig:list")
@GetMapping("/{ossConfigId}") @GetMapping("/{ossConfigId}")
public R<SysOssConfigVo> getInfo(@NotNull(message = "主键不能为空") public R<SysOssConfigVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long ossConfigId) { @PathVariable Long ossConfigId) {
@ -61,7 +61,7 @@ public class SysOssConfigController extends BaseController {
/** /**
* 新增对象存储配置 * 新增对象存储配置
*/ */
@SaCheckPermission("system:oss:add") @SaCheckPermission("system:ossConfig:add")
@Log(title = "对象存储配置", businessType = BusinessType.INSERT) @Log(title = "对象存储配置", businessType = BusinessType.INSERT)
@RepeatSubmit() @RepeatSubmit()
@PostMapping() @PostMapping()
@ -72,7 +72,7 @@ public class SysOssConfigController extends BaseController {
/** /**
* 修改对象存储配置 * 修改对象存储配置
*/ */
@SaCheckPermission("system:oss:edit") @SaCheckPermission("system:ossConfig:edit")
@Log(title = "对象存储配置", businessType = BusinessType.UPDATE) @Log(title = "对象存储配置", businessType = BusinessType.UPDATE)
@RepeatSubmit() @RepeatSubmit()
@PutMapping() @PutMapping()
@ -85,7 +85,7 @@ public class SysOssConfigController extends BaseController {
* *
* @param ossConfigIds OSS配置ID串 * @param ossConfigIds OSS配置ID串
*/ */
@SaCheckPermission("system:oss:remove") @SaCheckPermission("system:ossConfig:remove")
@Log(title = "对象存储配置", businessType = BusinessType.DELETE) @Log(title = "对象存储配置", businessType = BusinessType.DELETE)
@DeleteMapping("/{ossConfigIds}") @DeleteMapping("/{ossConfigIds}")
public R<Void> remove(@NotEmpty(message = "主键不能为空") public R<Void> remove(@NotEmpty(message = "主键不能为空")
@ -96,7 +96,7 @@ public class SysOssConfigController extends BaseController {
/** /**
* 状态修改 * 状态修改
*/ */
@SaCheckPermission("system:oss:edit") @SaCheckPermission("system:ossConfig:edit")
@Log(title = "对象存储状态修改", businessType = BusinessType.UPDATE) @Log(title = "对象存储状态修改", businessType = BusinessType.UPDATE)
@PutMapping("/changeStatus") @PutMapping("/changeStatus")
public R<Void> changeStatus(@RequestBody SysOssConfigBo bo) { public R<Void> changeStatus(@RequestBody SysOssConfigBo bo) {

View File

@ -6,6 +6,7 @@ import cn.hutool.core.io.FileUtil;
import org.dromara.common.core.domain.R; import org.dromara.common.core.domain.R;
import org.dromara.common.core.utils.StringUtils; import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.core.utils.file.MimeTypeUtils; import org.dromara.common.core.utils.file.MimeTypeUtils;
import org.dromara.common.encrypt.annotation.ApiEncrypt;
import org.dromara.common.log.annotation.Log; import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType; import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.satoken.utils.LoginHelper; import org.dromara.common.satoken.utils.LoginHelper;
@ -61,11 +62,12 @@ public class SysProfileController extends BaseController {
@PutMapping @PutMapping
public R<Void> updateProfile(@RequestBody SysUserProfileBo profile) { public R<Void> updateProfile(@RequestBody SysUserProfileBo profile) {
SysUserBo user = BeanUtil.toBean(profile, SysUserBo.class); SysUserBo user = BeanUtil.toBean(profile, SysUserBo.class);
String username = LoginHelper.getUsername();
if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) { if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) {
return R.fail("修改用户'" + user.getUserName() + "'失败,手机号码已存在"); return R.fail("修改用户'" + username + "'失败,手机号码已存在");
} }
if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) { if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) {
return R.fail("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在"); return R.fail("修改用户'" + username + "'失败,邮箱账号已存在");
} }
user.setUserId(LoginHelper.getUserId()); user.setUserId(LoginHelper.getUserId());
if (userService.updateUserProfile(user) > 0) { if (userService.updateUserProfile(user) > 0) {
@ -79,6 +81,7 @@ public class SysProfileController extends BaseController {
* *
* @param bo 新旧密码 * @param bo 新旧密码
*/ */
@ApiEncrypt
@Log(title = "个人信息", businessType = BusinessType.UPDATE) @Log(title = "个人信息", businessType = BusinessType.UPDATE)
@PutMapping("/updatePwd") @PutMapping("/updatePwd")
public R<Void> updatePwd(@Validated @RequestBody SysUserPasswordBo bo) { public R<Void> updatePwd(@Validated @RequestBody SysUserPasswordBo bo) {

View File

@ -1,6 +1,5 @@
package org.dromara.system.controller.system; package org.dromara.system.controller.system;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R; import org.dromara.common.core.domain.R;
import org.dromara.common.satoken.utils.LoginHelper; import org.dromara.common.satoken.utils.LoginHelper;
@ -9,7 +8,6 @@ import org.dromara.system.domain.vo.SysSocialVo;
import org.dromara.system.service.ISysSocialService; import org.dromara.system.service.ISysSocialService;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
@ -37,16 +35,4 @@ public class SysSocialController extends BaseController {
return R.ok(socialUserService.queryListByUserId(LoginHelper.getUserId())); return R.ok(socialUserService.queryListByUserId(LoginHelper.getUserId()));
} }
/**
* 获取社会化关系详细信息
*
* @param id 主键
*/
@GetMapping("/{id}")
public R<SysSocialVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable String id) {
return R.ok(socialUserService.queryById(id));
}
} }

View File

@ -4,7 +4,6 @@ import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.annotation.SaCheckRole; import cn.dev33.satoken.annotation.SaCheckRole;
import com.baomidou.lock.annotation.Lock4j; import com.baomidou.lock.annotation.Lock4j;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
@ -13,6 +12,7 @@ import org.dromara.common.core.constant.TenantConstants;
import org.dromara.common.core.domain.R; import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup; import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup; import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.encrypt.annotation.ApiEncrypt;
import org.dromara.common.excel.utils.ExcelUtil; import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.common.idempotent.annotation.RepeatSubmit; import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log; import org.dromara.common.log.annotation.Log;
@ -25,14 +25,7 @@ import org.dromara.system.domain.bo.SysTenantBo;
import org.dromara.system.domain.vo.SysTenantVo; import org.dromara.system.domain.vo.SysTenantVo;
import org.dromara.system.service.ISysTenantService; import org.dromara.system.service.ISysTenantService;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List; import java.util.List;
@ -87,6 +80,7 @@ public class SysTenantController extends BaseController {
/** /**
* 新增租户 * 新增租户
*/ */
@ApiEncrypt
@SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY) @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY)
@SaCheckPermission("system:tenant:add") @SaCheckPermission("system:tenant:add")
@Log(title = "租户", businessType = BusinessType.INSERT) @Log(title = "租户", businessType = BusinessType.INSERT)

View File

@ -14,6 +14,7 @@ import org.dromara.common.core.domain.model.LoginUser;
import org.dromara.common.core.utils.MapstructUtils; import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StreamUtils; import org.dromara.common.core.utils.StreamUtils;
import org.dromara.common.core.utils.StringUtils; import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.encrypt.annotation.ApiEncrypt;
import org.dromara.common.excel.core.ExcelResult; import org.dromara.common.excel.core.ExcelResult;
import org.dromara.common.excel.utils.ExcelUtil; import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.common.log.annotation.Log; import org.dromara.common.log.annotation.Log;
@ -209,6 +210,7 @@ public class SysUserController extends BaseController {
/** /**
* 重置密码 * 重置密码
*/ */
@ApiEncrypt
@SaCheckPermission("system:user:resetPwd") @SaCheckPermission("system:user:resetPwd")
@Log(title = "用户管理", businessType = BusinessType.UPDATE) @Log(title = "用户管理", businessType = BusinessType.UPDATE)
@PutMapping("/resetPwd") @PutMapping("/resetPwd")

View File

@ -2,9 +2,9 @@ package org.dromara.system.domain;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import org.dromara.common.tenant.core.TenantEntity;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import org.dromara.common.mybatis.core.domain.BaseEntity;
/** /**
* 对象存储配置对象 sys_oss_config * 对象存储配置对象 sys_oss_config
@ -14,7 +14,7 @@ import lombok.EqualsAndHashCode;
@Data @Data
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@TableName("sys_oss_config") @TableName("sys_oss_config")
public class SysOssConfig extends TenantEntity { public class SysOssConfig extends BaseEntity {
/** /**
* 主建 * 主建

View File

@ -1,13 +1,12 @@
package org.dromara.system.domain.vo; package org.dromara.system.domain.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.github.linpeilie.annotations.AutoMapper; import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data; import lombok.Data;
import org.dromara.system.domain.SysSocial; import org.dromara.system.domain.SysSocial;
import java.io.Serial; import java.io.Serial;
import java.io.Serializable; import java.io.Serializable;
import java.util.Date;
/** /**
@ -16,7 +15,6 @@ import java.io.Serializable;
* @author thiszhc * @author thiszhc
*/ */
@Data @Data
@ExcelIgnoreUnannotated
@AutoMapper(target = SysSocial.class) @AutoMapper(target = SysSocial.class)
public class SysSocialVo implements Serializable { public class SysSocialVo implements Serializable {
@ -26,13 +24,11 @@ public class SysSocialVo implements Serializable {
/** /**
* 主键 * 主键
*/ */
@ExcelProperty(value = "主键")
private Long id; private Long id;
/** /**
* 用户ID * 用户ID
*/ */
@ExcelProperty(value = "用户ID")
private Long userId; private Long userId;
/** /**
@ -43,123 +39,106 @@ public class SysSocialVo implements Serializable {
/** /**
* 的唯一ID * 的唯一ID
*/ */
@ExcelProperty(value = "授权UUID")
private String authId; private String authId;
/** /**
* 用户来源 * 用户来源
*/ */
@ExcelProperty(value = "用户来源")
private String source; private String source;
/** /**
* 用户的授权令牌 * 用户的授权令牌
*/ */
@ExcelProperty(value = "用户的授权令牌")
private String accessToken; private String accessToken;
/** /**
* 用户的授权令牌的有效期部分平台可能没有 * 用户的授权令牌的有效期部分平台可能没有
*/ */
@ExcelProperty(value = "用户的授权令牌的有效期,部分平台可能没有")
private int expireIn; private int expireIn;
/** /**
* 刷新令牌部分平台可能没有 * 刷新令牌部分平台可能没有
*/ */
@ExcelProperty(value = "刷新令牌,部分平台可能没有")
private String refreshToken; private String refreshToken;
/** /**
* 用户的 open id * 用户的 open id
*/ */
@ExcelProperty(value = "平台的唯一id")
private String openId; private String openId;
/** /**
* 授权的第三方账号 * 授权的第三方账号
*/ */
@ExcelProperty(value = "授权的第三方账号")
private String userName; private String userName;
/** /**
* 授权的第三方昵称 * 授权的第三方昵称
*/ */
@ExcelProperty(value = "授权的第三方昵称")
private String nickName; private String nickName;
/** /**
* 授权的第三方邮箱 * 授权的第三方邮箱
*/ */
@ExcelProperty(value = "授权的第三方邮箱")
private String email; private String email;
/** /**
* 授权的第三方头像地址 * 授权的第三方头像地址
*/ */
@ExcelProperty(value = "授权的第三方头像地址")
private String avatar; private String avatar;
/** /**
* 平台的授权信息部分平台可能没有 * 平台的授权信息部分平台可能没有
*/ */
@ExcelProperty(value = "平台的授权信息,部分平台可能没有")
private String accessCode; private String accessCode;
/** /**
* 用户的 unionid * 用户的 unionid
*/ */
@ExcelProperty(value = "用户的 unionid")
private String unionId; private String unionId;
/** /**
* 授予的权限部分平台可能没有 * 授予的权限部分平台可能没有
*/ */
@ExcelProperty(value = "授予的权限,部分平台可能没有")
private String scope; private String scope;
/** /**
* 个别平台的授权信息部分平台可能没有 * 个别平台的授权信息部分平台可能没有
*/ */
@ExcelProperty(value = "个别平台的授权信息,部分平台可能没有")
private String tokenType; private String tokenType;
/** /**
* id token部分平台可能没有 * id token部分平台可能没有
*/ */
@ExcelProperty(value = "id token部分平台可能没有")
private String idToken; private String idToken;
/** /**
* 小米平台用户的附带属性部分平台可能没有 * 小米平台用户的附带属性部分平台可能没有
*/ */
@ExcelProperty(value = "小米平台用户的附带属性,部分平台可能没有")
private String macAlgorithm; private String macAlgorithm;
/** /**
* 小米平台用户的附带属性部分平台可能没有 * 小米平台用户的附带属性部分平台可能没有
*/ */
@ExcelProperty(value = "小米平台用户的附带属性,部分平台可能没有")
private String macKey; private String macKey;
/** /**
* 用户的授权code部分平台可能没有 * 用户的授权code部分平台可能没有
*/ */
@ExcelProperty(value = "用户的授权code部分平台可能没有")
private String code; private String code;
/** /**
* Twitter平台用户的附带属性部分平台可能没有 * Twitter平台用户的附带属性部分平台可能没有
*/ */
@ExcelProperty(value = "Twitter平台用户的附带属性部分平台可能没有")
private String oauthToken; private String oauthToken;
/** /**
* Twitter平台用户的附带属性部分平台可能没有 * Twitter平台用户的附带属性部分平台可能没有
*/ */
@ExcelProperty(value = "Twitter平台用户的附带属性部分平台可能没有")
private String oauthTokenSecret; private String oauthTokenSecret;
/**
* 创建时间
*/
private Date createTime;
} }

View File

@ -1,15 +1,14 @@
package org.dromara.system.mapper; package org.dromara.system.mapper;
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.toolkit.Constants; import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
import org.dromara.common.mybatis.annotation.DataColumn; import org.dromara.common.mybatis.annotation.DataColumn;
import org.dromara.common.mybatis.annotation.DataPermission; import org.dromara.common.mybatis.annotation.DataPermission;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import org.dromara.system.domain.SysUser; import org.dromara.system.domain.SysUser;
import org.dromara.system.domain.vo.SysUserVo; import org.dromara.system.domain.vo.SysUserVo;
import org.apache.ibatis.annotations.Param;
import java.util.List; import java.util.List;
@ -86,37 +85,6 @@ public interface SysUserMapper extends BaseMapperPlus<SysUser, SysUserVo> {
*/ */
SysUserVo selectUserByEmail(String email); SysUserVo selectUserByEmail(String email);
/**
* 通过用户名查询用户(不走租户插件)
*
* @param userName 用户名
* @param tenantId 租户id
* @return 用户对象信息
*/
@InterceptorIgnore(tenantLine = "true")
SysUserVo selectTenantUserByUserName(@Param("userName") String userName, @Param("tenantId") String tenantId);
/**
* 通过手机号查询用户(不走租户插件)
*
* @param phonenumber 手机号
* @param tenantId 租户id
* @return 用户对象信息
*/
@InterceptorIgnore(tenantLine = "true")
SysUserVo selectTenantUserByPhonenumber(@Param("phonenumber") String phonenumber, @Param("tenantId") String tenantId);
/**
* 通过邮箱查询用户(不走租户插件)
*
* @param email 邮箱
* @param tenantId 租户id
* @return 用户对象信息
*/
@InterceptorIgnore(tenantLine = "true")
SysUserVo selectTenantUserByEmail(@Param("email") String email, @Param("tenantId") String tenantId);
/** /**
* 通过用户ID查询用户 * 通过用户ID查询用户
* *

View File

@ -49,7 +49,7 @@ public interface ISysSocialService {
* @param authId 认证ID * @param authId 认证ID
* @return SysSocial * @return SysSocial
*/ */
SysSocialVo selectByAuthId(String authId); List<SysSocialVo> selectByAuthId(String authId);
} }

View File

@ -85,9 +85,10 @@ public class SysConfigServiceImpl implements ISysConfigService, ConfigService {
*/ */
@Override @Override
public boolean selectRegisterEnabled(String tenantId) { public boolean selectRegisterEnabled(String tenantId) {
SysConfig retConfig = baseMapper.selectOne(new LambdaQueryWrapper<SysConfig>() SysConfig retConfig = TenantHelper.dynamic(tenantId, () -> {
.eq(SysConfig::getConfigKey, "sys.account.registerUser") return baseMapper.selectOne(new LambdaQueryWrapper<SysConfig>()
.eq(TenantHelper.isEnable(),SysConfig::getTenantId, tenantId)); .eq(SysConfig::getConfigKey, "sys.account.registerUser"));
});
if (ObjectUtil.isNull(retConfig)) { if (ObjectUtil.isNull(retConfig)) {
return false; return false;
} }

View File

@ -125,7 +125,7 @@ public class SysDictTypeServiceImpl implements ISysDictTypeService, DictService
*/ */
@Override @Override
public SysDictTypeVo selectDictTypeByType(String dictType) { public SysDictTypeVo selectDictTypeByType(String dictType) {
return baseMapper.selectVoById(new LambdaQueryWrapper<SysDictType>().eq(SysDictType::getDictType, dictType)); return baseMapper.selectVoOne(new LambdaQueryWrapper<SysDictType>().eq(SysDictType::getDictType, dictType));
} }
/** /**

View File

@ -11,7 +11,6 @@ import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.constant.CacheNames; import org.dromara.common.core.constant.CacheNames;
import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.MapstructUtils; import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StreamUtils;
import org.dromara.common.core.utils.StringUtils; import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.json.utils.JsonUtils; import org.dromara.common.json.utils.JsonUtils;
import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.PageQuery;
@ -19,8 +18,6 @@ import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.oss.constant.OssConstant; import org.dromara.common.oss.constant.OssConstant;
import org.dromara.common.redis.utils.CacheUtils; import org.dromara.common.redis.utils.CacheUtils;
import org.dromara.common.redis.utils.RedisUtils; import org.dromara.common.redis.utils.RedisUtils;
import org.dromara.common.tenant.core.TenantEntity;
import org.dromara.common.tenant.helper.TenantHelper;
import org.dromara.system.domain.SysOssConfig; import org.dromara.system.domain.SysOssConfig;
import org.dromara.system.domain.bo.SysOssConfigBo; import org.dromara.system.domain.bo.SysOssConfigBo;
import org.dromara.system.domain.vo.SysOssConfigVo; import org.dromara.system.domain.vo.SysOssConfigVo;
@ -31,7 +28,6 @@ import org.springframework.transaction.annotation.Transactional;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* 对象存储配置Service业务层处理 * 对象存储配置Service业务层处理
@ -52,25 +48,14 @@ public class SysOssConfigServiceImpl implements ISysOssConfigService {
*/ */
@Override @Override
public void init() { public void init() {
List<SysOssConfig> list = TenantHelper.ignore(() -> List<SysOssConfig> list = baseMapper.selectList();
baseMapper.selectList( // 加载OSS初始化配置
new LambdaQueryWrapper<SysOssConfig>().orderByAsc(TenantEntity::getTenantId)) for (SysOssConfig config : list) {
); String configKey = config.getConfigKey();
Map<String, List<SysOssConfig>> map = StreamUtils.groupByKey(list, SysOssConfig::getTenantId); if ("0".equals(config.getStatus())) {
try { RedisUtils.setCacheObject(OssConstant.DEFAULT_CONFIG_KEY, configKey);
for (String tenantId : map.keySet()) {
TenantHelper.setDynamic(tenantId);
// 加载OSS初始化配置
for (SysOssConfig config : map.get(tenantId)) {
String configKey = config.getConfigKey();
if ("0".equals(config.getStatus())) {
RedisUtils.setCacheObject(OssConstant.DEFAULT_CONFIG_KEY, configKey);
}
CacheUtils.put(CacheNames.SYS_OSS_CONFIG, config.getConfigKey(), JsonUtils.toJsonString(config));
}
} }
} finally { CacheUtils.put(CacheNames.SYS_OSS_CONFIG, config.getConfigKey(), JsonUtils.toJsonString(config));
TenantHelper.clearDynamic();
} }
} }

View File

@ -23,7 +23,7 @@ public class SysSensitiveServiceImpl implements SensitiveService {
*/ */
@Override @Override
public boolean isSensitive(String roleKey, String perms) { public boolean isSensitive(String roleKey, String perms) {
if (!StpUtil.isLogin()) { if (!LoginHelper.isLogin()) {
return true; return true;
} }
boolean roleExist = StringUtils.isNotBlank(roleKey); boolean roleExist = StringUtils.isNotBlank(roleKey);

View File

@ -99,8 +99,8 @@ public class SysSocialServiceImpl implements ISysSocialService {
* @return 授权信息 * @return 授权信息
*/ */
@Override @Override
public SysSocialVo selectByAuthId(String authId) { public List<SysSocialVo> selectByAuthId(String authId) {
return baseMapper.selectVoOne(new LambdaQueryWrapper<SysSocial>().eq(SysSocial::getAuthId, authId)); return baseMapper.selectVoList(new LambdaQueryWrapper<SysSocial>().eq(SysSocial::getAuthId, authId));
} }
} }

View File

@ -536,4 +536,12 @@ public class SysUserServiceImpl implements ISysUserService, UserService {
.select(SysUser::getUserName).eq(SysUser::getUserId, userId)); .select(SysUser::getUserName).eq(SysUser::getUserId, userId));
return ObjectUtil.isNull(sysUser) ? null : sysUser.getUserName(); return ObjectUtil.isNull(sysUser) ? null : sysUser.getUserName();
} }
@Override
@Cacheable(cacheNames = CacheNames.SYS_NICKNAME, key = "#userId")
public String selectNicknameById(Long userId) {
SysUser sysUser = baseMapper.selectOne(new LambdaQueryWrapper<SysUser>()
.select(SysUser::getNickName).eq(SysUser::getUserId, userId));
return ObjectUtil.isNull(sysUser) ? null : sysUser.getNickName();
}
} }

View File

@ -118,21 +118,6 @@
where u.del_flag = '0' and u.email = #{email} where u.del_flag = '0' and u.email = #{email}
</select> </select>
<select id="selectTenantUserByUserName" parameterType="String" resultMap="SysUserResult">
<include refid="selectUserVo"/>
where u.del_flag = '0' and u.user_name = #{userName} and u.tenant_id = #{tenantId}
</select>
<select id="selectTenantUserByPhonenumber" parameterType="String" resultMap="SysUserResult">
<include refid="selectUserVo"/>
where u.del_flag = '0' and u.phonenumber = #{phonenumber} and u.tenant_id = #{tenantId}
</select>
<select id="selectTenantUserByEmail" parameterType="String" resultMap="SysUserResult">
<include refid="selectUserVo"/>
where u.del_flag = '0' and u.email = #{email} and u.tenant_id = #{tenantId}
</select>
<select id="selectUserById" parameterType="Long" resultMap="SysUserResult"> <select id="selectUserById" parameterType="Long" resultMap="SysUserResult">
<include refid="selectUserVo"/> <include refid="selectUserVo"/>
where u.del_flag = '0' and u.user_id = #{userId} where u.del_flag = '0' and u.user_id = #{userId}

View File

@ -5,7 +5,7 @@ rem jar平级目录
set AppName=ruoyi-admin.jar set AppName=ruoyi-admin.jar
rem JVM参数 rem JVM参数
set JVM_OPTS="-Dname=%AppName% -Duser.timezone=Asia/Shanghai -Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:NewRatio=1 -XX:SurvivorRatio=30 -XX:+UseParallelGC -XX:+UseParallelOldGC" set JVM_OPTS="-Dname=%AppName% -Duser.timezone=Asia/Shanghai -Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -Xlog:gc*,:time,tags,level -XX:+UseZGC"
ECHO. ECHO.

View File

@ -3,7 +3,7 @@
AppName=ruoyi-admin.jar AppName=ruoyi-admin.jar
# JVM参数 # JVM参数
JVM_OPTS="-Dname=$AppName -Duser.timezone=Asia/Shanghai -Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:NewRatio=1 -XX:SurvivorRatio=30 -XX:+UseParallelGC -XX:+UseParallelOldGC" JVM_OPTS="-Dname=$AppName -Duser.timezone=Asia/Shanghai -Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -Xlog:gc*,:time,tags,level -XX:+UseZGC"
APP_HOME=`pwd` APP_HOME=`pwd`
LOG_PATH=$APP_HOME/logs/$AppName.log LOG_PATH=$APP_HOME/logs/$AppName.log

View File

@ -100,7 +100,7 @@ services:
network_mode: "host" network_mode: "host"
ruoyi-server1: ruoyi-server1:
image: ruoyi/ruoyi-server:5.1.1 image: ruoyi/ruoyi-server:5.1.2
container_name: ruoyi-server1 container_name: ruoyi-server1
environment: environment:
# 时区上海 # 时区上海
@ -115,7 +115,7 @@ services:
network_mode: "host" network_mode: "host"
ruoyi-server2: ruoyi-server2:
image: ruoyi/ruoyi-server:5.1.1 image: ruoyi/ruoyi-server:5.1.2
container_name: ruoyi-server2 container_name: ruoyi-server2
environment: environment:
# 时区上海 # 时区上海
@ -130,7 +130,7 @@ services:
network_mode: "host" network_mode: "host"
ruoyi-monitor-admin: ruoyi-monitor-admin:
image: ruoyi/ruoyi-monitor-admin:5.1.1 image: ruoyi/ruoyi-monitor-admin:5.1.2
container_name: ruoyi-monitor-admin container_name: ruoyi-monitor-admin
environment: environment:
# 时区上海 # 时区上海
@ -142,7 +142,7 @@ services:
network_mode: "host" network_mode: "host"
ruoyi-powerjob-server: ruoyi-powerjob-server:
image: ruoyi/ruoyi-powerjob-server:5.1.1 image: ruoyi/ruoyi-powerjob-server:5.1.2
container_name: ruoyi-powerjob-server container_name: ruoyi-powerjob-server
environment: environment:
# 时区上海 # 时区上海

View File

@ -108,7 +108,7 @@ http {
} }
# 解决 powerjob 代理之后静态文件无法访问的问题 请勿修改乱动 # 解决 powerjob 代理之后静态文件无法访问的问题 请勿修改乱动
location .*\.(js|css|jpg|png|svg|woff|ttf|ico)?$ { location ~ ^/(js|css|jpg|png|svg|woff|ttf|ico|img)/ {
proxy_pass http://powerjob-server; proxy_pass http://powerjob-server;
} }

View File

@ -522,8 +522,10 @@ insert into sys_menu values('1600', '文件查询', '118', '1', '#', '', '', 1,
insert into sys_menu values('1601', '文件上传', '118', '2', '#', '', '', 1, 0, 'F', '0', '0', 'system:oss:upload', '#', 103, 1, sysdate, null, null, ''); insert into sys_menu values('1601', '文件上传', '118', '2', '#', '', '', 1, 0, 'F', '0', '0', 'system:oss:upload', '#', 103, 1, sysdate, null, null, '');
insert into sys_menu values('1602', '文件下载', '118', '3', '#', '', '', 1, 0, 'F', '0', '0', 'system:oss:download', '#', 103, 1, sysdate, null, null, ''); insert into sys_menu values('1602', '文件下载', '118', '3', '#', '', '', 1, 0, 'F', '0', '0', 'system:oss:download', '#', 103, 1, sysdate, null, null, '');
insert into sys_menu values('1603', '文件删除', '118', '4', '#', '', '', 1, 0, 'F', '0', '0', 'system:oss:remove', '#', 103, 1, sysdate, null, null, ''); insert into sys_menu values('1603', '文件删除', '118', '4', '#', '', '', 1, 0, 'F', '0', '0', 'system:oss:remove', '#', 103, 1, sysdate, null, null, '');
insert into sys_menu values('1604', '配置添加', '118', '5', '#', '', '', 1, 0, 'F', '0', '0', 'system:oss:add', '#', 103, 1, sysdate, null, null, ''); insert into sys_menu values('1620', '配置列表', '118', '5', '#', '', '', 1, 0, 'F', '0', '0', 'system:ossConfig:list', '#', 103, 1, sysdate, null, null, '');
insert into sys_menu values('1605', '配置编辑', '118', '6', '#', '', '', 1, 0, 'F', '0', '0', 'system:oss:edit', '#', 103, 1, sysdate, null, null, ''); insert into sys_menu values('1621', '配置添加', '118', '6', '#', '', '', 1, 0, 'F', '0', '0', 'system:ossConfig:add', '#', 103, 1, sysdate, null, null, '');
insert into sys_menu values('1622', '配置编辑', '118', '6', '#', '', '', 1, 0, 'F', '0', '0', 'system:ossConfig:edit', '#', 103, 1, sysdate, null, null, '');
insert into sys_menu values('1623', '配置删除', '118', '6', '#', '', '', 1, 0, 'F', '0', '0', 'system:ossConfig:remove', '#', 103, 1, sysdate, null, null, '');
-- 租户管理相关按钮 -- 租户管理相关按钮
insert into sys_menu values('1606', '租户查询', '121', '1', '#', '', '', 1, 0, 'F', '0', '0', 'system:tenant:query', '#', 103, 1, sysdate, null, null, ''); insert into sys_menu values('1606', '租户查询', '121', '1', '#', '', '', 1, 0, 'F', '0', '0', 'system:tenant:query', '#', 103, 1, sysdate, null, null, '');
insert into sys_menu values('1607', '租户新增', '121', '2', '#', '', '', 1, 0, 'F', '0', '0', 'system:tenant:add', '#', 103, 1, sysdate, null, null, ''); insert into sys_menu values('1607', '租户新增', '121', '2', '#', '', '', 1, 0, 'F', '0', '0', 'system:tenant:add', '#', 103, 1, sysdate, null, null, '');

View File

@ -159,10 +159,10 @@ DISABLE ROW MOVEMENT
-- ---------------------------- -- ----------------------------
-- Records of "PJ_JOB_INFO" -- Records of "PJ_JOB_INFO"
-- ---------------------------- -- ----------------------------
INSERT INTO "PJ_JOB_INFO" VALUES ('1', '{\"alertThreshold\":0,\"silenceWindowLen\":0,\"statisticWindowLen\":0}', '1', '5', NULL, '2', '1', NULL, NULL, NULL, '1', '0', NULL, '单机处理器执行测试', NULL, '{}', '{\"type\":1}', '0', '0', '0.0000000000000000', '0.0000000000000000', '0.0000000000000000', NULL, NULL, 'org.dromara.job.processors.StandaloneProcessorDemo', '1', '2', NULL, '1', '30000', '3'); INSERT INTO "PJ_JOB_INFO" VALUES ('1', '{"alertThreshold":0,"silenceWindowLen":0,"statisticWindowLen":0}', '1', '5', NULL, '2', '1', NULL, NULL, NULL, '1', '0', NULL, '单机处理器执行测试', NULL, '{}', '{"type":1}', '0', '0', '0.0000000000000000', '0.0000000000000000', '0.0000000000000000', NULL, NULL, 'org.dromara.job.processors.StandaloneProcessorDemo', '1', '2', NULL, '1', '30000', '3');
INSERT INTO "PJ_JOB_INFO" VALUES ('2', '{\"alertThreshold\":0,\"silenceWindowLen\":0,\"statisticWindowLen\":0}', '1', '5', NULL, '1', '2', NULL, NULL, NULL, '0', '0', NULL, '广播处理器测试', NULL, '{}', '{\"type\":1}', '0', '0', '0.0000000000000000', '0.0000000000000000', '0.0000000000000000', NULL, NULL, 'org.dromara.job.processors.BroadcastProcessorDemo', '1', '2', NULL, '1', '30000', '3'); INSERT INTO "PJ_JOB_INFO" VALUES ('2', '{"alertThreshold":0,"silenceWindowLen":0,"statisticWindowLen":0}', '1', '5', NULL, '1', '2', NULL, NULL, NULL, '0', '0', NULL, '广播处理器测试', NULL, '{}', '{"type":1}', '0', '0', '0.0000000000000000', '0.0000000000000000', '0.0000000000000000', NULL, NULL, 'org.dromara.job.processors.BroadcastProcessorDemo', '1', '2', NULL, '1', '30000', '3');
INSERT INTO "PJ_JOB_INFO" VALUES ('3', '{\"alertThreshold\":0,\"silenceWindowLen\":0,\"statisticWindowLen\":0}', '1', '5', NULL, '1', '4', NULL, NULL, NULL, '0', '0', NULL, 'Map处理器测试', NULL, '{}', '{\"type\":1}', '0', '0', '0.0000000000000000', '0.0000000000000000', '0.0000000000000000', NULL, NULL, 'org.dromara.job.processors.MapProcessorDemo', '1', '2', NULL, '1', '1000', '3'); INSERT INTO "PJ_JOB_INFO" VALUES ('3', '{"alertThreshold":0,"silenceWindowLen":0,"statisticWindowLen":0}', '1', '5', NULL, '1', '4', NULL, NULL, NULL, '0', '0', NULL, 'Map处理器测试', NULL, '{}', '{"type":1}', '0', '0', '0.0000000000000000', '0.0000000000000000', '0.0000000000000000', NULL, NULL, 'org.dromara.job.processors.MapProcessorDemo', '1', '2', NULL, '1', '1000', '3');
INSERT INTO "PJ_JOB_INFO" VALUES ('4', '{\"alertThreshold\":0,\"silenceWindowLen\":0,\"statisticWindowLen\":0}', '1', '5', NULL, '1', '3', NULL, NULL, NULL, '0', '0', NULL, 'MapReduce处理器测试', NULL, '{}', '{\"type\":1}', '0', '0', '0.0000000000000000', '0.0000000000000000', '0.0000000000000000', NULL, NULL, 'org.dromara.job.processors.MapReduceProcessorDemo', '1', '2', NULL, '1', '1000', '3'); INSERT INTO "PJ_JOB_INFO" VALUES ('4', '{"alertThreshold":0,"silenceWindowLen":0,"statisticWindowLen":0}', '1', '5', NULL, '1', '3', NULL, NULL, NULL, '0', '0', NULL, 'MapReduce处理器测试', NULL, '{}', '{"type":1}', '0', '0', '0.0000000000000000', '0.0000000000000000', '0.0000000000000000', NULL, NULL, 'org.dromara.job.processors.MapReduceProcessorDemo', '1', '2', NULL, '1', '1000', '3');
-- ---------------------------- -- ----------------------------
-- Table structure for PJ_OMS_LOCK -- Table structure for PJ_OMS_LOCK

View File

@ -532,8 +532,10 @@ insert into sys_menu values('1600', '文件查询', '118', '1', '#', '', '', '1'
insert into sys_menu values('1601', '文件上传', '118', '2', '#', '', '', '1', '0', 'F', '0', '0', 'system:oss:upload', '#', 103, 1, now(), null, null, ''); insert into sys_menu values('1601', '文件上传', '118', '2', '#', '', '', '1', '0', 'F', '0', '0', 'system:oss:upload', '#', 103, 1, now(), null, null, '');
insert into sys_menu values('1602', '文件下载', '118', '3', '#', '', '', '1', '0', 'F', '0', '0', 'system:oss:download', '#', 103, 1, now(), null, null, ''); insert into sys_menu values('1602', '文件下载', '118', '3', '#', '', '', '1', '0', 'F', '0', '0', 'system:oss:download', '#', 103, 1, now(), null, null, '');
insert into sys_menu values('1603', '文件删除', '118', '4', '#', '', '', '1', '0', 'F', '0', '0', 'system:oss:remove', '#', 103, 1, now(), null, null, ''); insert into sys_menu values('1603', '文件删除', '118', '4', '#', '', '', '1', '0', 'F', '0', '0', 'system:oss:remove', '#', 103, 1, now(), null, null, '');
insert into sys_menu values('1604', '配置添加', '118', '5', '#', '', '', '1', '0', 'F', '0', '0', 'system:oss:add', '#', 103, 1, now(), null, null, ''); insert into sys_menu values('1620', '配置列表', '118', '5', '#', '', '', '1', '0', 'F', '0', '0', 'system:ossConfig:list', '#', 103, 1, now(), null, null, '');
insert into sys_menu values('1605', '配置编辑', '118', '6', '#', '', '', '1', '0', 'F', '0', '0', 'system:oss:edit', '#', 103, 1, now(), null, null, ''); insert into sys_menu values('1621', '配置添加', '118', '6', '#', '', '', '1', '0', 'F', '0', '0', 'system:ossConfig:add', '#', 103, 1, now(), null, null, '');
insert into sys_menu values('1622', '配置编辑', '118', '6', '#', '', '', '1', '0', 'F', '0', '0', 'system:ossConfig:edit', '#', 103, 1, now(), null, null, '');
insert into sys_menu values('1623', '配置删除', '118', '6', '#', '', '', '1', '0', 'F', '0', '0', 'system:ossConfig:remove', '#', 103, 1, now(), null, null, '');
-- 租户管理相关按钮 -- 租户管理相关按钮
insert into sys_menu values('1606', '租户查询', '121', '1', '#', '', '', '1', '0', 'F', '0', '0', 'system:tenant:query', '#', 103, 1, now(), null, null, ''); insert into sys_menu values('1606', '租户查询', '121', '1', '#', '', '', '1', '0', 'F', '0', '0', 'system:tenant:query', '#', 103, 1, now(), null, null, '');
insert into sys_menu values('1607', '租户新增', '121', '2', '#', '', '', '1', '0', 'F', '0', '0', 'system:tenant:add', '#', 103, 1, now(), null, null, ''); insert into sys_menu values('1607', '租户新增', '121', '2', '#', '', '', '1', '0', 'F', '0', '0', 'system:tenant:add', '#', 103, 1, now(), null, null, '');

View File

@ -116,10 +116,10 @@ CREATE TABLE pj_job_info (
CREATE INDEX idx01_job_info ON pj_job_info USING btree (app_id, status, time_expression_type, next_trigger_time); CREATE INDEX idx01_job_info ON pj_job_info USING btree (app_id, status, time_expression_type, next_trigger_time);
INSERT INTO pj_job_info VALUES(1, '{\"alertThreshold\":0,\"silenceWindowLen\":0,\"statisticWindowLen\":0}', 1, 5, '', 2, 1, NULL, '2023-06-02 15:01:27.717', '2023-07-04 17:22:12.374', 1, 0, '', '单机处理器执行测试', NULL, '{}', '{\"type\":1}', 0, 0, 0.0, 0.0, 0.0, NULL, NULL, 'org.dromara.job.processors.StandaloneProcessorDemo', 1, 2, NULL, 1, '30000', 3); INSERT INTO pj_job_info VALUES(1, '{"alertThreshold":0,"silenceWindowLen":0,"statisticWindowLen":0}', 1, 5, '', 2, 1, NULL, '2023-06-02 15:01:27.717', '2023-07-04 17:22:12.374', 1, 0, '', '单机处理器执行测试', NULL, '{}', '{"type":1}', 0, 0, 0.0, 0.0, 0.0, NULL, NULL, 'org.dromara.job.processors.StandaloneProcessorDemo', 1, 2, NULL, 1, '30000', 3);
INSERT INTO pj_job_info VALUES(2, '{\"alertThreshold\":0,\"silenceWindowLen\":0,\"statisticWindowLen\":0}', 1, 5, '', 1, 2, NULL, '2023-06-02 15:04:45.342', '2023-07-04 17:22:12.816', 0, 0, NULL, '广播处理器测试', NULL, '{}', '{\"type\":1}', 0, 0, 0.0, 0.0, 0.0, NULL, NULL, 'org.dromara.job.processors.BroadcastProcessorDemo', 1, 2, NULL, 1, '30000', 3); INSERT INTO pj_job_info VALUES(2, '{"alertThreshold":0,"silenceWindowLen":0,"statisticWindowLen":0}', 1, 5, '', 1, 2, NULL, '2023-06-02 15:04:45.342', '2023-07-04 17:22:12.816', 0, 0, NULL, '广播处理器测试', NULL, '{}', '{"type":1}', 0, 0, 0.0, 0.0, 0.0, NULL, NULL, 'org.dromara.job.processors.BroadcastProcessorDemo', 1, 2, NULL, 1, '30000', 3);
INSERT INTO pj_job_info VALUES(3, '{\"alertThreshold\":0,\"silenceWindowLen\":0,\"statisticWindowLen\":0}', 1, 5, '', 1, 4, NULL, '2023-06-02 15:13:23.519', '2023-06-02 16:03:22.421', 0, 0, NULL, 'Map处理器测试', NULL, '{}', '{\"type\":1}', 0, 0, 0.0, 0.0, 0.0, NULL, NULL, 'org.dromara.job.processors.MapProcessorDemo', 1, 2, NULL, 1, '1000', 3); INSERT INTO pj_job_info VALUES(3, '{"alertThreshold":0,"silenceWindowLen":0,"statisticWindowLen":0}', 1, 5, '', 1, 4, NULL, '2023-06-02 15:13:23.519', '2023-06-02 16:03:22.421', 0, 0, NULL, 'Map处理器测试', NULL, '{}', '{"type":1}', 0, 0, 0.0, 0.0, 0.0, NULL, NULL, 'org.dromara.job.processors.MapProcessorDemo', 1, 2, NULL, 1, '1000', 3);
INSERT INTO pj_job_info VALUES(4, '{\"alertThreshold\":0,\"silenceWindowLen\":0,\"statisticWindowLen\":0}', 1, 5, '', 1, 3, NULL, '2023-06-02 15:45:25.896', '2023-06-02 16:03:23.125', 0, 0, NULL, 'MapReduce处理器测试', NULL, '{}', '{\"type\":1}', 0, 0, 0.0, 0.0, 0.0, NULL, NULL, 'org.dromara.job.processors.MapReduceProcessorDemo', 1, 2, NULL, 1, '1000', 3); INSERT INTO pj_job_info VALUES(4, '{"alertThreshold":0,"silenceWindowLen":0,"statisticWindowLen":0}', 1, 5, '', 1, 3, NULL, '2023-06-02 15:45:25.896', '2023-06-02 16:03:23.125', 0, 0, NULL, 'MapReduce处理器测试', NULL, '{}', '{"type":1}', 0, 0, 0.0, 0.0, 0.0, NULL, NULL, 'org.dromara.job.processors.MapReduceProcessorDemo', 1, 2, NULL, 1, '1000', 3);
-- pj_oms_lock definition -- pj_oms_lock definition

View File

@ -285,7 +285,7 @@ insert into sys_menu values('113', '缓存监控', '2', '5', 'cache',
insert into sys_menu values('114', '表单构建', '3', '1', 'build', 'tool/build/index', '', 1, 0, 'C', '0', '0', 'tool:build:list', 'build', 103, 1, sysdate(), null, null, '表单构建菜单'); insert into sys_menu values('114', '表单构建', '3', '1', 'build', 'tool/build/index', '', 1, 0, 'C', '0', '0', 'tool:build:list', 'build', 103, 1, sysdate(), null, null, '表单构建菜单');
insert into sys_menu values('115', '代码生成', '3', '2', 'gen', 'tool/gen/index', '', 1, 0, 'C', '0', '0', 'tool:gen:list', 'code', 103, 1, sysdate(), null, null, '代码生成菜单'); insert into sys_menu values('115', '代码生成', '3', '2', 'gen', 'tool/gen/index', '', 1, 0, 'C', '0', '0', 'tool:gen:list', 'code', 103, 1, sysdate(), null, null, '代码生成菜单');
insert into sys_menu values('121', '租户管理', '6', '1', 'tenant', 'system/tenant/index', '', 1, 0, 'C', '0', '0', 'system:tenant:list', 'list', 103, 1, sysdate(), null, null, '租户管理菜单'); insert into sys_menu values('121', '租户管理', '6', '1', 'tenant', 'system/tenant/index', '', 1, 0, 'C', '0', '0', 'system:tenant:list', 'list', 103, 1, sysdate(), null, null, '租户管理菜单');
insert into sys_menu values('122', '租户套餐管理', '6', '2', 'tenantPackage', 'system/tenantPackage/index', '', 1, 0, 'C', '0', '0', 'system:tenantPackage:list', 'form', 103, 1, sysdate(), null, null, '租户套餐管理菜单'); insert into sys_menu values('122', '租户套餐管理', '6', '2', 'tenantPackage', 'system/tenantPackage/index', '', 1, 0, 'C', '0', '0', 'system:tenantPackage:list', 'form', 103, 1, sysdate(), null, null, '租户套餐管理菜单');
insert into sys_menu values('123', '客户端管理', '1', '11', 'client', 'system/client/index', '', 1, 0, 'C', '0', '0', 'system:client:list', 'international', 103, 1, sysdate(), null, null, '客户端管理菜单'); insert into sys_menu values('123', '客户端管理', '1', '11', 'client', 'system/client/index', '', 1, 0, 'C', '0', '0', 'system:client:list', 'international', 103, 1, sysdate(), null, null, '客户端管理菜单');
-- springboot-admin监控 -- springboot-admin监控
@ -370,8 +370,11 @@ insert into sys_menu values('1600', '文件查询', '118', '1', '#', '', '', 1,
insert into sys_menu values('1601', '文件上传', '118', '2', '#', '', '', 1, 0, 'F', '0', '0', 'system:oss:upload', '#', 103, 1, sysdate(), null, null, ''); insert into sys_menu values('1601', '文件上传', '118', '2', '#', '', '', 1, 0, 'F', '0', '0', 'system:oss:upload', '#', 103, 1, sysdate(), null, null, '');
insert into sys_menu values('1602', '文件下载', '118', '3', '#', '', '', 1, 0, 'F', '0', '0', 'system:oss:download', '#', 103, 1, sysdate(), null, null, ''); insert into sys_menu values('1602', '文件下载', '118', '3', '#', '', '', 1, 0, 'F', '0', '0', 'system:oss:download', '#', 103, 1, sysdate(), null, null, '');
insert into sys_menu values('1603', '文件删除', '118', '4', '#', '', '', 1, 0, 'F', '0', '0', 'system:oss:remove', '#', 103, 1, sysdate(), null, null, ''); insert into sys_menu values('1603', '文件删除', '118', '4', '#', '', '', 1, 0, 'F', '0', '0', 'system:oss:remove', '#', 103, 1, sysdate(), null, null, '');
insert into sys_menu values('1604', '配置添加', '118', '5', '#', '', '', 1, 0, 'F', '0', '0', 'system:oss:add', '#', 103, 1, sysdate(), null, null, ''); insert into sys_menu values('1620', '配置列表', '118', '5', '#', '', '', 1, 0, 'F', '0', '0', 'system:ossConfig:list', '#', 103, 1, sysdate(), null, null, '');
insert into sys_menu values('1605', '配置编辑', '118', '6', '#', '', '', 1, 0, 'F', '0', '0', 'system:oss:edit', '#', 103, 1, sysdate(), null, null, ''); insert into sys_menu values('1621', '配置添加', '118', '6', '#', '', '', 1, 0, 'F', '0', '0', 'system:ossConfig:add', '#', 103, 1, sysdate(), null, null, '');
insert into sys_menu values('1622', '配置编辑', '118', '6', '#', '', '', 1, 0, 'F', '0', '0', 'system:ossConfig:edit', '#', 103, 1, sysdate(), null, null, '');
insert into sys_menu values('1623', '配置删除', '118', '6', '#', '', '', 1, 0, 'F', '0', '0', 'system:ossConfig:remove', '#', 103, 1, sysdate(), null, null, '');
-- 租户管理相关按钮 -- 租户管理相关按钮
insert into sys_menu values ('1606', '租户查询', '121', '1', '#', '', '', 1, 0, 'F', '0', '0', 'system:tenant:query', '#', 103, 1, sysdate(), null, null, ''); insert into sys_menu values ('1606', '租户查询', '121', '1', '#', '', '', 1, 0, 'F', '0', '0', 'system:tenant:query', '#', 103, 1, sysdate(), null, null, '');
insert into sys_menu values ('1607', '租户新增', '121', '2', '#', '', '', 1, 0, 'F', '0', '0', 'system:tenant:add', '#', 103, 1, sysdate(), null, null, ''); insert into sys_menu values ('1607', '租户新增', '121', '2', '#', '', '', 1, 0, 'F', '0', '0', 'system:tenant:add', '#', 103, 1, sysdate(), null, null, '');

View File

@ -130,16 +130,16 @@ GO
SET IDENTITY_INSERT [pj_job_info] ON SET IDENTITY_INSERT [pj_job_info] ON
GO GO
INSERT INTO [pj_job_info] ([id], [alarm_config], [app_id], [concurrency], [designated_workers], [dispatch_strategy], [execute_type], [extra], [gmt_create], [gmt_modified], [instance_retry_num], [instance_time_limit], [job_description], [job_name], [job_params], [lifecycle], [log_config], [max_instance_num], [max_worker_count], [min_cpu_cores], [min_disk_space], [min_memory_space], [next_trigger_time], [notify_user_ids], [processor_info], [processor_type], [status], [tag], [task_retry_num], [time_expression], [time_expression_type]) VALUES (N'1', N'{\"alertThreshold\":0,\"silenceWindowLen\":0,\"statisticWindowLen\":0}', N'1', N'5', N'', N'2', N'1', NULL, N'2023-06-02 15:01:27.7170000', N'2023-07-04 17:22:12.3740000', N'1', N'0', N'', N'?????????', NULL, N'{}', N'{\"type\":1}', N'0', N'0', N'0.000000000000000', N'0.000000000000000', N'0.000000000000000', NULL, NULL, N'org.dromara.job.processors.StandaloneProcessorDemo', N'1', N'2', NULL, N'1', N'30000', N'3') INSERT INTO [pj_job_info] ([id], [alarm_config], [app_id], [concurrency], [designated_workers], [dispatch_strategy], [execute_type], [extra], [gmt_create], [gmt_modified], [instance_retry_num], [instance_time_limit], [job_description], [job_name], [job_params], [lifecycle], [log_config], [max_instance_num], [max_worker_count], [min_cpu_cores], [min_disk_space], [min_memory_space], [next_trigger_time], [notify_user_ids], [processor_info], [processor_type], [status], [tag], [task_retry_num], [time_expression], [time_expression_type]) VALUES (N'1', N'{"alertThreshold":0,"silenceWindowLen":0,"statisticWindowLen":0}', N'1', N'5', N'', N'2', N'1', NULL, N'2023-06-02 15:01:27.7170000', N'2023-07-04 17:22:12.3740000', N'1', N'0', N'', N'?????????', NULL, N'{}', N'{"type":1}', N'0', N'0', N'0.000000000000000', N'0.000000000000000', N'0.000000000000000', NULL, NULL, N'org.dromara.job.processors.StandaloneProcessorDemo', N'1', N'2', NULL, N'1', N'30000', N'3')
GO GO
INSERT INTO [pj_job_info] ([id], [alarm_config], [app_id], [concurrency], [designated_workers], [dispatch_strategy], [execute_type], [extra], [gmt_create], [gmt_modified], [instance_retry_num], [instance_time_limit], [job_description], [job_name], [job_params], [lifecycle], [log_config], [max_instance_num], [max_worker_count], [min_cpu_cores], [min_disk_space], [min_memory_space], [next_trigger_time], [notify_user_ids], [processor_info], [processor_type], [status], [tag], [task_retry_num], [time_expression], [time_expression_type]) VALUES (N'2', N'{\"alertThreshold\":0,\"silenceWindowLen\":0,\"statisticWindowLen\":0}', N'1', N'5', N'', N'1', N'2', NULL, N'2023-06-02 15:04:45.3420000', N'2023-07-04 17:22:12.8160000', N'0', N'0', NULL, N'???????', NULL, N'{}', N'{\"type\":1}', N'0', N'0', N'0.000000000000000', N'0.000000000000000', N'0.000000000000000', NULL, NULL, N'org.dromara.job.processors.BroadcastProcessorDemo', N'1', N'2', NULL, N'1', N'30000', N'3') INSERT INTO [pj_job_info] ([id], [alarm_config], [app_id], [concurrency], [designated_workers], [dispatch_strategy], [execute_type], [extra], [gmt_create], [gmt_modified], [instance_retry_num], [instance_time_limit], [job_description], [job_name], [job_params], [lifecycle], [log_config], [max_instance_num], [max_worker_count], [min_cpu_cores], [min_disk_space], [min_memory_space], [next_trigger_time], [notify_user_ids], [processor_info], [processor_type], [status], [tag], [task_retry_num], [time_expression], [time_expression_type]) VALUES (N'2', N'{"alertThreshold":0,"silenceWindowLen":0,"statisticWindowLen":0}', N'1', N'5', N'', N'1', N'2', NULL, N'2023-06-02 15:04:45.3420000', N'2023-07-04 17:22:12.8160000', N'0', N'0', NULL, N'???????', NULL, N'{}', N'{"type":1}', N'0', N'0', N'0.000000000000000', N'0.000000000000000', N'0.000000000000000', NULL, NULL, N'org.dromara.job.processors.BroadcastProcessorDemo', N'1', N'2', NULL, N'1', N'30000', N'3')
GO GO
INSERT INTO [pj_job_info] ([id], [alarm_config], [app_id], [concurrency], [designated_workers], [dispatch_strategy], [execute_type], [extra], [gmt_create], [gmt_modified], [instance_retry_num], [instance_time_limit], [job_description], [job_name], [job_params], [lifecycle], [log_config], [max_instance_num], [max_worker_count], [min_cpu_cores], [min_disk_space], [min_memory_space], [next_trigger_time], [notify_user_ids], [processor_info], [processor_type], [status], [tag], [task_retry_num], [time_expression], [time_expression_type]) VALUES (N'3', N'{\"alertThreshold\":0,\"silenceWindowLen\":0,\"statisticWindowLen\":0}', N'1', N'5', N'', N'1', N'4', NULL, N'2023-06-02 15:13:23.5190000', N'2023-06-02 16:03:22.4210000', N'0', N'0', NULL, N'Map?????', NULL, N'{}', N'{\"type\":1}', N'0', N'0', N'0.000000000000000', N'0.000000000000000', N'0.000000000000000', NULL, NULL, N'org.dromara.job.processors.MapProcessorDemo', N'1', N'2', NULL, N'1', N'1000', N'3') INSERT INTO [pj_job_info] ([id], [alarm_config], [app_id], [concurrency], [designated_workers], [dispatch_strategy], [execute_type], [extra], [gmt_create], [gmt_modified], [instance_retry_num], [instance_time_limit], [job_description], [job_name], [job_params], [lifecycle], [log_config], [max_instance_num], [max_worker_count], [min_cpu_cores], [min_disk_space], [min_memory_space], [next_trigger_time], [notify_user_ids], [processor_info], [processor_type], [status], [tag], [task_retry_num], [time_expression], [time_expression_type]) VALUES (N'3', N'{"alertThreshold":0,"silenceWindowLen":0,"statisticWindowLen":0}', N'1', N'5', N'', N'1', N'4', NULL, N'2023-06-02 15:13:23.5190000', N'2023-06-02 16:03:22.4210000', N'0', N'0', NULL, N'Map?????', NULL, N'{}', N'{"type":1}', N'0', N'0', N'0.000000000000000', N'0.000000000000000', N'0.000000000000000', NULL, NULL, N'org.dromara.job.processors.MapProcessorDemo', N'1', N'2', NULL, N'1', N'1000', N'3')
GO GO
INSERT INTO [pj_job_info] ([id], [alarm_config], [app_id], [concurrency], [designated_workers], [dispatch_strategy], [execute_type], [extra], [gmt_create], [gmt_modified], [instance_retry_num], [instance_time_limit], [job_description], [job_name], [job_params], [lifecycle], [log_config], [max_instance_num], [max_worker_count], [min_cpu_cores], [min_disk_space], [min_memory_space], [next_trigger_time], [notify_user_ids], [processor_info], [processor_type], [status], [tag], [task_retry_num], [time_expression], [time_expression_type]) VALUES (N'4', N'{\"alertThreshold\":0,\"silenceWindowLen\":0,\"statisticWindowLen\":0}', N'1', N'5', N'', N'1', N'3', NULL, N'2023-06-02 15:45:25.8960000', N'2023-06-02 16:03:23.1250000', N'0', N'0', NULL, N'MapReduce?????', NULL, N'{}', N'{\"type\":1}', N'0', N'0', N'0.000000000000000', N'0.000000000000000', N'0.000000000000000', NULL, NULL, N'org.dromara.job.processors.MapReduceProcessorDemo', N'1', N'2', NULL, N'1', N'1000', N'3') INSERT INTO [pj_job_info] ([id], [alarm_config], [app_id], [concurrency], [designated_workers], [dispatch_strategy], [execute_type], [extra], [gmt_create], [gmt_modified], [instance_retry_num], [instance_time_limit], [job_description], [job_name], [job_params], [lifecycle], [log_config], [max_instance_num], [max_worker_count], [min_cpu_cores], [min_disk_space], [min_memory_space], [next_trigger_time], [notify_user_ids], [processor_info], [processor_type], [status], [tag], [task_retry_num], [time_expression], [time_expression_type]) VALUES (N'4', N'{"alertThreshold":0,"silenceWindowLen":0,"statisticWindowLen":0}', N'1', N'5', N'', N'1', N'3', NULL, N'2023-06-02 15:45:25.8960000', N'2023-06-02 16:03:23.1250000', N'0', N'0', NULL, N'MapReduce?????', NULL, N'{}', N'{"type":1}', N'0', N'0', N'0.000000000000000', N'0.000000000000000', N'0.000000000000000', NULL, NULL, N'org.dromara.job.processors.MapReduceProcessorDemo', N'1', N'2', NULL, N'1', N'1000', N'3')
GO GO
SET IDENTITY_INSERT [pj_job_info] OFF SET IDENTITY_INSERT [pj_job_info] OFF

View File

@ -1808,9 +1808,13 @@ INSERT sys_menu VALUES (1602, N'文件下载', 118, 3, N'#', N'', N'', 1, 0, N'F
GO GO
INSERT sys_menu VALUES (1603, N'文件删除', 118, 4, N'#', N'', N'', 1, 0, N'F', N'0', N'0', N'system:oss:remove', N'#', 103, 1, getdate(), NULL, NULL, N''); INSERT sys_menu VALUES (1603, N'文件删除', 118, 4, N'#', N'', N'', 1, 0, N'F', N'0', N'0', N'system:oss:remove', N'#', 103, 1, getdate(), NULL, NULL, N'');
GO GO
INSERT sys_menu VALUES (1604, N'配置添加', 118, 5, N'#', N'', N'', 1, 0, N'F', N'0', N'0', N'system:oss:add', N'#', 103, 1, getdate(), NULL, NULL, N''); INSERT sys_menu VALUES (1620, N'配置列表', 118, 5, N'#', N'', N'', 1, 0, N'F', N'0', N'0', N'system:ossConfig:list', N'#', 103, 1, getdate(), NULL, NULL, N'');
GO GO
INSERT sys_menu VALUES (1605, N'配置编辑', 118, 6, N'#', N'', N'', 1, 0, N'F', N'0', N'0', N'system:oss:edit', N'#', 103, 1, getdate(), NULL, NULL, N''); INSERT sys_menu VALUES (1621, N'配置添加', 118, 6, N'#', N'', N'', 1, 0, N'F', N'0', N'0', N'system:ossConfig:add', N'#', 103, 1, getdate(), NULL, NULL, N'');
GO
INSERT sys_menu VALUES (1622, N'配置编辑', 118, 6, N'#', N'', N'', 1, 0, N'F', N'0', N'0', N'system:ossConfig:edit', N'#', 103, 1, getdate(), NULL, NULL, N'');
GO
INSERT sys_menu VALUES (1623, N'配置删除', 118, 6, N'#', N'', N'', 1, 0, N'F', N'0', N'0', N'system:ossConfig:remove', N'#', 103, 1, getdate(), NULL, NULL, N'');
GO GO
-- 租户管理相关按钮 -- 租户管理相关按钮
INSERT sys_menu VALUES (1606, N'租户查询', 121, 1, N'#', N'', N'', 1, 0, N'F', N'0', N'0', N'system:tenant:query', N'#', 103, 1, getdate(), NULL, NULL, N''); INSERT sys_menu VALUES (1606, N'租户查询', 121, 1, N'#', N'', N'', 1, 0, N'F', N'0', N'0', N'system:tenant:query', N'#', 103, 1, getdate(), NULL, NULL, N'');

View File

@ -0,0 +1,5 @@
delete from sys_menu where menu_id in (1604, 1605);
insert into sys_menu values('1620', '配置列表', '118', '5', '#', '', '', 1, 0, 'F', '0', '0', 'system:ossConfig:list', '#', 103, 1, sysdate, null, null, '');
insert into sys_menu values('1621', '配置添加', '118', '6', '#', '', '', 1, 0, 'F', '0', '0', 'system:ossConfig:add', '#', 103, 1, sysdate, null, null, '');
insert into sys_menu values('1622', '配置编辑', '118', '6', '#', '', '', 1, 0, 'F', '0', '0', 'system:ossConfig:edit', '#', 103, 1, sysdate, null, null, '');
insert into sys_menu values('1623', '配置删除', '118', '6', '#', '', '', 1, 0, 'F', '0', '0', 'system:ossConfig:remove', '#', 103, 1, sysdate, null, null, '');

View File

@ -0,0 +1,6 @@
delete from sys_menu where menu_id in (1604, 1605);
insert into sys_menu values('1620', '配置列表', '118', '5', '#', '', '', '1', '0', 'F', '0', '0', 'system:ossConfig:list', '#', 103, 1, now(), null, null, '');
insert into sys_menu values('1621', '配置添加', '118', '6', '#', '', '', '1', '0', 'F', '0', '0', 'system:ossConfig:add', '#', 103, 1, now(), null, null, '');
insert into sys_menu values('1622', '配置编辑', '118', '6', '#', '', '', '1', '0', 'F', '0', '0', 'system:ossConfig:edit', '#', 103, 1, now(), null, null, '');
insert into sys_menu values('1623', '配置删除', '118', '6', '#', '', '', '1', '0', 'F', '0', '0', 'system:ossConfig:remove', '#', 103, 1, now(), null, null, '');

View File

@ -0,0 +1,10 @@
DELETE FROM sys_menu WHERE menu_id IN (1604, 1605);
GO
INSERT sys_menu VALUES (1620, N'配置列表', 118, 5, N'#', N'', N'', 1, 0, N'F', N'0', N'0', N'system:ossConfig:list', N'#', 103, 1, getdate(), NULL, NULL, N'');
GO
INSERT sys_menu VALUES (1621, N'配置添加', 118, 6, N'#', N'', N'', 1, 0, N'F', N'0', N'0', N'system:ossConfig:add', N'#', 103, 1, getdate(), NULL, NULL, N'');
GO
INSERT sys_menu VALUES (1622, N'配置编辑', 118, 6, N'#', N'', N'', 1, 0, N'F', N'0', N'0', N'system:ossConfig:edit', N'#', 103, 1, getdate(), NULL, NULL, N'');
GO
INSERT sys_menu VALUES (1623, N'配置删除', 118, 6, N'#', N'', N'', 1, 0, N'F', N'0', N'0', N'system:ossConfig:remove', N'#', 103, 1, getdate(), NULL, NULL, N'');
GO

View File

@ -0,0 +1,6 @@
delete from sys_menu where menu_id in (1604, 1605);
insert into sys_menu values('1620', '配置列表', '118', '5', '#', '', '', 1, 0, 'F', '0', '0', 'system:ossConfig:list', '#', 103, 1, sysdate(), null, null, '');
insert into sys_menu values('1621', '配置添加', '118', '6', '#', '', '', 1, 0, 'F', '0', '0', 'system:ossConfig:add', '#', 103, 1, sysdate(), null, null, '');
insert into sys_menu values('1622', '配置编辑', '118', '6', '#', '', '', 1, 0, 'F', '0', '0', 'system:ossConfig:edit', '#', 103, 1, sysdate(), null, null, '');
insert into sys_menu values('1623', '配置删除', '118', '6', '#', '', '', 1, 0, 'F', '0', '0', 'system:ossConfig:remove', '#', 103, 1, sysdate(), null, null, '');