frist commit
This commit is contained in:
commit
227f68f30f
18
.editorconfig
Normal file
18
.editorconfig
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# http://editorconfig.org
|
||||||
|
root = true
|
||||||
|
|
||||||
|
# 空格替代Tab缩进在各种编辑工具下效果一致
|
||||||
|
[*]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
||||||
|
|
||||||
|
[*.{json,yml,yaml}]
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
insert_final_newline = false
|
||||||
|
trim_trailing_whitespace = false
|
47
.gitignore
vendored
Normal file
47
.gitignore
vendored
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
######################################################################
|
||||||
|
# Build Tools
|
||||||
|
|
||||||
|
.gradle
|
||||||
|
/build/
|
||||||
|
!gradle/wrapper/gradle-wrapper.jar
|
||||||
|
|
||||||
|
target/
|
||||||
|
!.mvn/wrapper/maven-wrapper.jar
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
# IDE
|
||||||
|
|
||||||
|
### STS ###
|
||||||
|
.apt_generated
|
||||||
|
.classpath
|
||||||
|
.factorypath
|
||||||
|
.project
|
||||||
|
.settings
|
||||||
|
.springBeans
|
||||||
|
|
||||||
|
### IntelliJ IDEA ###
|
||||||
|
.idea
|
||||||
|
*.iws
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
|
||||||
|
### JRebel ###
|
||||||
|
rebel.xml
|
||||||
|
### NetBeans ###
|
||||||
|
nbproject/private/
|
||||||
|
build/*
|
||||||
|
nbbuild/
|
||||||
|
nbdist/
|
||||||
|
.nb-gradle/
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
# Others
|
||||||
|
*.log
|
||||||
|
*.xml.versionsBackup
|
||||||
|
*.swp
|
||||||
|
|
||||||
|
!*/build/*.java
|
||||||
|
!*/build/*.html
|
||||||
|
!*/build/*.xml
|
||||||
|
|
||||||
|
.flattened-pom.xml
|
12
.run/asinkj-auth.run.xml
Normal file
12
.run/asinkj-auth.run.xml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="asinkj-auth" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
|
||||||
|
<deployment type="dockerfile">
|
||||||
|
<settings>
|
||||||
|
<option name="imageTag" value="asinkj/asinkj-auth:2.2.2" />
|
||||||
|
<option name="buildOnly" value="true" />
|
||||||
|
<option name="sourceFilePath" value="asinkj-auth/Dockerfile" />
|
||||||
|
</settings>
|
||||||
|
</deployment>
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
12
.run/asinkj-gateway.run.xml
Normal file
12
.run/asinkj-gateway.run.xml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="asinkj-gateway" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
|
||||||
|
<deployment type="dockerfile">
|
||||||
|
<settings>
|
||||||
|
<option name="imageTag" value="asinkj/asinkj-gateway:2.2.2" />
|
||||||
|
<option name="buildOnly" value="true" />
|
||||||
|
<option name="sourceFilePath" value="asinkj-gateway/Dockerfile" />
|
||||||
|
</settings>
|
||||||
|
</deployment>
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
12
.run/asinkj-gen.run.xml
Normal file
12
.run/asinkj-gen.run.xml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="asinkj-gen" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
|
||||||
|
<deployment type="dockerfile">
|
||||||
|
<settings>
|
||||||
|
<option name="imageTag" value="asinkj/asinkj-gen:2.2.2" />
|
||||||
|
<option name="buildOnly" value="true" />
|
||||||
|
<option name="sourceFilePath" value="asinkj-modules/asinkj-gen/Dockerfile" />
|
||||||
|
</settings>
|
||||||
|
</deployment>
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
12
.run/asinkj-job.run.xml
Normal file
12
.run/asinkj-job.run.xml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="asinkj-job" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
|
||||||
|
<deployment type="dockerfile">
|
||||||
|
<settings>
|
||||||
|
<option name="imageTag" value="asinkj/asinkj-job:2.2.2" />
|
||||||
|
<option name="buildOnly" value="true" />
|
||||||
|
<option name="sourceFilePath" value="asinkj-modules/asinkj-job/Dockerfile" />
|
||||||
|
</settings>
|
||||||
|
</deployment>
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
12
.run/asinkj-monitor.run.xml
Normal file
12
.run/asinkj-monitor.run.xml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="asinkj-monitor" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
|
||||||
|
<deployment type="dockerfile">
|
||||||
|
<settings>
|
||||||
|
<option name="imageTag" value="asinkj/asinkj-monitor:2.2.2" />
|
||||||
|
<option name="buildOnly" value="true" />
|
||||||
|
<option name="sourceFilePath" value="asinkj-visual/asinkj-monitor/Dockerfile" />
|
||||||
|
</settings>
|
||||||
|
</deployment>
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
27
.run/asinkj-nacos.run.xml
Normal file
27
.run/asinkj-nacos.run.xml
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="asinkj-nacos" type="docker-deploy" factoryName="dockerfile" server-name="阿里云">
|
||||||
|
<deployment type="dockerfile">
|
||||||
|
<settings>
|
||||||
|
<option name="imageTag" value="asinkj/asinkj-nacos:2.2.2" />
|
||||||
|
<option name="containerName" value="asinkj-nacos" />
|
||||||
|
<option name="portBindings">
|
||||||
|
<list>
|
||||||
|
<DockerPortBindingImpl>
|
||||||
|
<option name="containerPort" value="8848" />
|
||||||
|
<option name="hostPort" value="8848" />
|
||||||
|
</DockerPortBindingImpl>
|
||||||
|
<DockerPortBindingImpl>
|
||||||
|
<option name="containerPort" value="9848" />
|
||||||
|
<option name="hostPort" value="9848" />
|
||||||
|
</DockerPortBindingImpl>
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
<option name="commandLineOptions" value="--network 1panel-network" />
|
||||||
|
<option name="sourceFilePath" value="asinkj-visual/asinkj-nacos/Dockerfile" />
|
||||||
|
</settings>
|
||||||
|
</deployment>
|
||||||
|
<method v="2">
|
||||||
|
<option name="Maven.BeforeRunTask" enabled="true" file="F:\Asinkj-Cloud-Plus\asinkj-visual\asinkj-nacos/pom.xml" goal="package" />
|
||||||
|
</method>
|
||||||
|
</configuration>
|
||||||
|
</component>
|
12
.run/asinkj-resource.run.xml
Normal file
12
.run/asinkj-resource.run.xml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="asinkj-resource" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
|
||||||
|
<deployment type="dockerfile">
|
||||||
|
<settings>
|
||||||
|
<option name="imageTag" value="asinkj/asinkj-resource:2.2.2" />
|
||||||
|
<option name="buildOnly" value="true" />
|
||||||
|
<option name="sourceFilePath" value="asinkj-modules/asinkj-resource/Dockerfile" />
|
||||||
|
</settings>
|
||||||
|
</deployment>
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
12
.run/asinkj-seata-server.run.xml
Normal file
12
.run/asinkj-seata-server.run.xml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="asinkj-seata-server" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
|
||||||
|
<deployment type="dockerfile">
|
||||||
|
<settings>
|
||||||
|
<option name="imageTag" value="asinkj/asinkj-seata-server:2.2.2" />
|
||||||
|
<option name="buildOnly" value="true" />
|
||||||
|
<option name="sourceFilePath" value="asinkj-visual/asinkj-seata-server/Dockerfile" />
|
||||||
|
</settings>
|
||||||
|
</deployment>
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
12
.run/asinkj-sentinel-dashboard.run.xml
Normal file
12
.run/asinkj-sentinel-dashboard.run.xml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="asinkj-sentinel-dashboard" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
|
||||||
|
<deployment type="dockerfile">
|
||||||
|
<settings>
|
||||||
|
<option name="imageTag" value="asinkj/asinkj-sentinel-dashboard:2.2.2" />
|
||||||
|
<option name="buildOnly" value="true" />
|
||||||
|
<option name="sourceFilePath" value="asinkj-visual/asinkj-sentinel-dashboard/Dockerfile" />
|
||||||
|
</settings>
|
||||||
|
</deployment>
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
12
.run/asinkj-snailjob-server.run.xml
Normal file
12
.run/asinkj-snailjob-server.run.xml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="asinkj-snailjob-server" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
|
||||||
|
<deployment type="dockerfile">
|
||||||
|
<settings>
|
||||||
|
<option name="imageTag" value="asinkj/asinkj-snailjob-server:2.2.2" />
|
||||||
|
<option name="buildOnly" value="true" />
|
||||||
|
<option name="sourceFilePath" value="asinkj-visual/asinkj-snailjob-server/Dockerfile" />
|
||||||
|
</settings>
|
||||||
|
</deployment>
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
12
.run/asinkj-system.run.xml
Normal file
12
.run/asinkj-system.run.xml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="asinkj-system" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
|
||||||
|
<deployment type="dockerfile">
|
||||||
|
<settings>
|
||||||
|
<option name="imageTag" value="asinkj/asinkj-system:2.2.2" />
|
||||||
|
<option name="buildOnly" value="true" />
|
||||||
|
<option name="sourceFilePath" value="asinkj-modules/asinkj-system/Dockerfile" />
|
||||||
|
</settings>
|
||||||
|
</deployment>
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
12
.run/asinkj-workflow.run.xml
Normal file
12
.run/asinkj-workflow.run.xml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="asinkj-workflow" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
|
||||||
|
<deployment type="dockerfile">
|
||||||
|
<settings>
|
||||||
|
<option name="imageTag" value="asinkj/asinkj-workflow:2.2.2" />
|
||||||
|
<option name="buildOnly" value="true" />
|
||||||
|
<option name="sourceFilePath" value="asinkj-modules/asinkj-workflow/Dockerfile" />
|
||||||
|
</settings>
|
||||||
|
</deployment>
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2022 AsinKj-Cloud-Plus
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
46
asinkj-api/asinkj-api-bom/pom.xml
Normal file
46
asinkj-api/asinkj-api-bom/pom.xml
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-api-bom</artifactId>
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
<version>${revision}</version>
|
||||||
|
|
||||||
|
<description>
|
||||||
|
asinkj-api-bom api依赖项
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<revision>2.2.2</revision>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencyManagement>
|
||||||
|
<dependencies>
|
||||||
|
<!-- 系统接口 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-api-system</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 资源服务接口 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-api-resource</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- workflow接口 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-api-workflow</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
</dependencyManagement>
|
||||||
|
</project>
|
28
asinkj-api/asinkj-api-resource/pom.xml
Normal file
28
asinkj-api/asinkj-api-resource/pom.xml
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-api</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>asinkj-api-resource</artifactId>
|
||||||
|
|
||||||
|
<description>
|
||||||
|
asinkj-api-resource 资源服务接口模块
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<!-- AsinKj Common Core-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common-core</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
@ -0,0 +1,38 @@
|
|||||||
|
package org.asinkj.resource.api;
|
||||||
|
|
||||||
|
import org.asinkj.common.core.exception.ServiceException;
|
||||||
|
import org.asinkj.resource.api.domain.RemoteFile;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件服务
|
||||||
|
*
|
||||||
|
* @author Shuo Hu
|
||||||
|
*/
|
||||||
|
public interface RemoteFileService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传文件
|
||||||
|
*
|
||||||
|
* @param file 文件信息
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
RemoteFile upload(String name, String originalFilename, String contentType, byte[] file) throws ServiceException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过ossId查询对应的url
|
||||||
|
*
|
||||||
|
* @param ossIds ossId串逗号分隔
|
||||||
|
* @return url串逗号分隔
|
||||||
|
*/
|
||||||
|
String selectUrlByIds(String ossIds);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过ossId查询列表
|
||||||
|
*
|
||||||
|
* @param ossIds ossId串逗号分隔
|
||||||
|
* @return 列表
|
||||||
|
*/
|
||||||
|
List<RemoteFile> selectByIds(String ossIds);
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
package org.asinkj.resource.api;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.asinkj.common.core.utils.StringUtils;
|
||||||
|
import org.asinkj.resource.api.domain.RemoteFile;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件服务(降级处理)
|
||||||
|
*
|
||||||
|
* @author Shuo Hu
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class RemoteFileServiceMock implements RemoteFileService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传文件
|
||||||
|
*
|
||||||
|
* @param file 文件信息
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public RemoteFile upload(String name, String originalFilename, String contentType, byte[] file) {
|
||||||
|
log.warn("服务调用异常 -> 降级处理");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过ossId查询对应的url
|
||||||
|
*
|
||||||
|
* @param ossIds ossId串逗号分隔
|
||||||
|
* @return url串逗号分隔
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String selectUrlByIds(String ossIds) {
|
||||||
|
log.warn("服务调用异常 -> 降级处理");
|
||||||
|
return StringUtils.EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过ossId查询列表
|
||||||
|
*
|
||||||
|
* @param ossIds ossId串逗号分隔
|
||||||
|
* @return 列表
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<RemoteFile> selectByIds(String ossIds) {
|
||||||
|
log.warn("服务调用异常 -> 降级处理");
|
||||||
|
return List.of();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package org.asinkj.resource.api;
|
||||||
|
|
||||||
|
import org.asinkj.common.core.exception.ServiceException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 邮件服务
|
||||||
|
*
|
||||||
|
* @author Shuo Hu
|
||||||
|
*/
|
||||||
|
public interface RemoteMailService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送邮件
|
||||||
|
*
|
||||||
|
* @param to 接收人
|
||||||
|
* @param subject 标题
|
||||||
|
* @param text 内容
|
||||||
|
*/
|
||||||
|
void send(String to, String subject, String text) throws ServiceException;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
package org.asinkj.resource.api;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息服务
|
||||||
|
*
|
||||||
|
* @author Shuo Hu
|
||||||
|
*/
|
||||||
|
public interface RemoteMessageService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送消息
|
||||||
|
*
|
||||||
|
* @param sessionKey session主键 一般为用户id
|
||||||
|
* @param message 消息文本
|
||||||
|
*/
|
||||||
|
void publishMessage(Long sessionKey, String message);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发布订阅的消息(群发)
|
||||||
|
*
|
||||||
|
* @param message 消息内容
|
||||||
|
*/
|
||||||
|
void publishAll(String message);
|
||||||
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
package org.asinkj.resource.api;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息服务
|
||||||
|
*
|
||||||
|
* @author Shuo Hu
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class RemoteMessageServiceStub implements RemoteMessageService {
|
||||||
|
|
||||||
|
private final RemoteMessageService remoteMessageService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送消息
|
||||||
|
*
|
||||||
|
* @param sessionKey session主键 一般为用户id
|
||||||
|
* @param message 消息文本
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void publishMessage(Long sessionKey, String message) {
|
||||||
|
try {
|
||||||
|
remoteMessageService.publishMessage(sessionKey, message);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("推送功能未开启或服务未找到");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发布订阅的消息(群发)
|
||||||
|
*
|
||||||
|
* @param message 消息内容
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void publishAll(String message) {
|
||||||
|
try {
|
||||||
|
remoteMessageService.publishAll(message);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("推送功能未开启或服务未找到");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,145 @@
|
|||||||
|
package org.asinkj.resource.api;
|
||||||
|
|
||||||
|
import org.asinkj.resource.api.domain.RemoteSms;
|
||||||
|
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 短信服务
|
||||||
|
*
|
||||||
|
* @author Feng
|
||||||
|
*/
|
||||||
|
public interface RemoteSmsService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 同步方法:发送固定消息模板短信
|
||||||
|
*
|
||||||
|
* @param phone 目标手机号
|
||||||
|
* @param message 短信内容
|
||||||
|
* @return 封装了短信发送结果的 RemoteSms 对象
|
||||||
|
*/
|
||||||
|
RemoteSms sendMessage(String phone, String message);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 同步方法:发送固定消息模板多模板参数短信
|
||||||
|
*
|
||||||
|
* @param phone 目标手机号
|
||||||
|
* @param messages 短信模板参数,使用 LinkedHashMap 以保持参数顺序
|
||||||
|
* @return 封装了短信发送结果的 RemoteSms 对象
|
||||||
|
*/
|
||||||
|
RemoteSms sendMessage(String phone, LinkedHashMap<String, String> messages);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 同步方法:使用自定义模板发送短信
|
||||||
|
*
|
||||||
|
* @param phone 目标手机号
|
||||||
|
* @param templateId 短信模板ID
|
||||||
|
* @param messages 短信模板参数,使用 LinkedHashMap 以保持参数顺序
|
||||||
|
* @return 封装了短信发送结果的 RemoteSms 对象
|
||||||
|
*/
|
||||||
|
RemoteSms sendMessage(String phone, String templateId, LinkedHashMap<String, String> messages);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 同步方法:群发固定模板短信
|
||||||
|
*
|
||||||
|
* @param phones 目标手机号列表(1~1000)
|
||||||
|
* @param message 短信内容
|
||||||
|
* @return 封装了短信发送结果的 RemoteSms 对象
|
||||||
|
*/
|
||||||
|
RemoteSms messageTexting(List<String> phones, String message);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 同步方法:使用自定义模板群发短信
|
||||||
|
*
|
||||||
|
* @param phones 目标手机号列表(1~1000)(1~1000)
|
||||||
|
* @param templateId 短信模板ID
|
||||||
|
* @param messages 短信模板参数,使用 LinkedHashMap 以保持参数顺序
|
||||||
|
* @return 封装了短信发送结果的 RemoteSms 对象
|
||||||
|
*/
|
||||||
|
RemoteSms messageTexting(List<String> phones, String templateId, LinkedHashMap<String, String> messages);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 异步方法:发送固定消息模板短信
|
||||||
|
*
|
||||||
|
* @param phone 目标手机号
|
||||||
|
* @param message 短信内容
|
||||||
|
*/
|
||||||
|
void sendMessageAsync(String phone, String message);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 异步方法:使用自定义模板发送短信
|
||||||
|
*
|
||||||
|
* @param phone 目标手机号
|
||||||
|
* @param templateId 短信模板ID
|
||||||
|
* @param messages 短信模板参数,使用 LinkedHashMap 以保持参数顺序
|
||||||
|
*/
|
||||||
|
void sendMessageAsync(String phone, String templateId, LinkedHashMap<String, String> messages);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 延迟发送:发送固定消息模板短信
|
||||||
|
*
|
||||||
|
* @param phone 目标手机号
|
||||||
|
* @param message 短信内容
|
||||||
|
* @param delayedTime 延迟发送时间(毫秒)
|
||||||
|
*/
|
||||||
|
void delayMessage(String phone, String message, Long delayedTime);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 延迟发送:使用自定义模板发送定时短信
|
||||||
|
*
|
||||||
|
* @param phone 目标手机号
|
||||||
|
* @param templateId 短信模板ID
|
||||||
|
* @param messages 短信模板参数,使用 LinkedHashMap 以保持参数顺序
|
||||||
|
* @param delayedTime 延迟发送时间(毫秒)
|
||||||
|
*/
|
||||||
|
void delayMessage(String phone, String templateId, LinkedHashMap<String, String> messages, Long delayedTime);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 延迟群发:群发延迟短信
|
||||||
|
*
|
||||||
|
* @param phones 目标手机号列表(1~1000)
|
||||||
|
* @param message 短信内容
|
||||||
|
* @param delayedTime 延迟发送时间(毫秒)
|
||||||
|
*/
|
||||||
|
void delayMessageTexting(List<String> phones, String message, Long delayedTime);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 延迟群发:使用自定义模板发送群体延迟短信
|
||||||
|
*
|
||||||
|
* @param phones 目标手机号列表(1~1000)
|
||||||
|
* @param templateId 短信模板ID
|
||||||
|
* @param messages 短信模板参数,使用 LinkedHashMap 以保持参数顺序
|
||||||
|
* @param delayedTime 延迟发送时间(毫秒)
|
||||||
|
*/
|
||||||
|
void delayMessageTexting(List<String> phones, String templateId, LinkedHashMap<String, String> messages, Long delayedTime);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加入黑名单
|
||||||
|
*
|
||||||
|
* @param phone 手机号
|
||||||
|
*/
|
||||||
|
void addBlacklist(String phone);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加入黑名单
|
||||||
|
*
|
||||||
|
* @param phones 手机号列表
|
||||||
|
*/
|
||||||
|
void addBlacklist(List<String> phones);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 移除黑名单
|
||||||
|
*
|
||||||
|
* @param phone 手机号
|
||||||
|
*/
|
||||||
|
void removeBlacklist(String phone);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 移除黑名单
|
||||||
|
*
|
||||||
|
* @param phones 手机号
|
||||||
|
*/
|
||||||
|
void removeBlacklist(List<String> phones);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
package org.asinkj.resource.api.domain;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件信息
|
||||||
|
*
|
||||||
|
* @author asinkj
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class RemoteFile implements Serializable {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* oss主键
|
||||||
|
*/
|
||||||
|
private Long ossId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件名称
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件地址
|
||||||
|
*/
|
||||||
|
private String url;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 原名
|
||||||
|
*/
|
||||||
|
private String originalName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件后缀名
|
||||||
|
*/
|
||||||
|
private String fileSuffix;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
package org.asinkj.resource.api.domain;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件信息
|
||||||
|
*
|
||||||
|
* @author asinkj
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class RemoteSms implements Serializable {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否成功
|
||||||
|
*/
|
||||||
|
private Boolean success;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置标识名 如未配置取对应渠道名例如 Alibaba
|
||||||
|
*/
|
||||||
|
private String configId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 厂商原返回体
|
||||||
|
* <p>
|
||||||
|
* 可自行转换为 SDK 对应的 SendSmsResponse
|
||||||
|
*/
|
||||||
|
private String response;
|
||||||
|
|
||||||
|
}
|
33
asinkj-api/asinkj-api-system/pom.xml
Normal file
33
asinkj-api/asinkj-api-system/pom.xml
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-api</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>asinkj-api-system</artifactId>
|
||||||
|
|
||||||
|
<description>
|
||||||
|
asinkj-api-system系统接口模块
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<!-- AsinKj Common Core-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common-core</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common-excel</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
@ -0,0 +1,20 @@
|
|||||||
|
package org.asinkj.system.api;
|
||||||
|
|
||||||
|
import org.asinkj.system.api.domain.vo.RemoteClientVo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户端服务
|
||||||
|
*
|
||||||
|
* @author Michelle.Chung
|
||||||
|
*/
|
||||||
|
public interface RemoteClientService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据客户端id获取客户端详情
|
||||||
|
*
|
||||||
|
* @param clientId 客户端id
|
||||||
|
* @return 客户端对象
|
||||||
|
*/
|
||||||
|
RemoteClientVo queryByClientId(String clientId);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package org.asinkj.system.api;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置服务
|
||||||
|
*
|
||||||
|
* @author Michelle.Chung
|
||||||
|
*/
|
||||||
|
public interface RemoteConfigService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取注册开关
|
||||||
|
* @param tenantId 租户id
|
||||||
|
* @return true开启,false关闭
|
||||||
|
*/
|
||||||
|
boolean selectRegisterEnabled(String tenantId);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
package org.asinkj.system.api;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据权限服务
|
||||||
|
*
|
||||||
|
* @author Shuo Hu
|
||||||
|
*/
|
||||||
|
public interface RemoteDataScopeService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取角色自定义权限语句
|
||||||
|
*
|
||||||
|
* @param roleId 角色ID
|
||||||
|
* @return 返回角色的自定义权限语句,如果没有找到则返回 null
|
||||||
|
*/
|
||||||
|
String getRoleCustom(Long roleId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取部门和下级权限语句
|
||||||
|
*
|
||||||
|
* @param deptId 部门ID
|
||||||
|
* @return 返回部门及其下级的权限语句,如果没有找到则返回 null
|
||||||
|
*/
|
||||||
|
String getDeptAndChild(Long deptId);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package org.asinkj.system.api;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 部门服务
|
||||||
|
*
|
||||||
|
* @author Shuo Hu
|
||||||
|
*/
|
||||||
|
public interface RemoteDeptService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过部门ID查询部门名称
|
||||||
|
*
|
||||||
|
* @param deptIds 部门ID串逗号分隔
|
||||||
|
* @return 部门名称串逗号分隔
|
||||||
|
*/
|
||||||
|
String selectDeptNameByIds(String deptIds);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
package org.asinkj.system.api;
|
||||||
|
|
||||||
|
import org.asinkj.system.api.domain.vo.RemoteDictDataVo;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字典服务
|
||||||
|
*
|
||||||
|
* @author Shuo Hu
|
||||||
|
*/
|
||||||
|
public interface RemoteDictService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据字典类型查询字典数据
|
||||||
|
*
|
||||||
|
* @param dictType 字典类型
|
||||||
|
* @return 字典数据集合信息
|
||||||
|
*/
|
||||||
|
List<RemoteDictDataVo> selectDictDataByType(String dictType);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package org.asinkj.system.api;
|
||||||
|
|
||||||
|
import org.asinkj.system.api.domain.bo.RemoteLogininforBo;
|
||||||
|
import org.asinkj.system.api.domain.bo.RemoteOperLogBo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日志服务
|
||||||
|
*
|
||||||
|
* @author Shuo Hu
|
||||||
|
*/
|
||||||
|
public interface RemoteLogService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存系统日志
|
||||||
|
*
|
||||||
|
* @param sysOperLog 日志实体
|
||||||
|
*/
|
||||||
|
void saveLog(RemoteOperLogBo sysOperLog);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存访问记录
|
||||||
|
*
|
||||||
|
* @param sysLogininfor 访问实体
|
||||||
|
*/
|
||||||
|
void saveLogininfor(RemoteLogininforBo sysLogininfor);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
package org.asinkj.system.api;
|
||||||
|
|
||||||
|
import org.asinkj.system.api.domain.bo.RemoteSocialBo;
|
||||||
|
import org.asinkj.system.api.domain.vo.RemoteSocialVo;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 社会化关系服务
|
||||||
|
*
|
||||||
|
* @author Michelle.Chung
|
||||||
|
*/
|
||||||
|
public interface RemoteSocialService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据 authId 查询用户授权信息
|
||||||
|
*
|
||||||
|
* @param authId 认证id
|
||||||
|
* @return 授权信息
|
||||||
|
*/
|
||||||
|
List<RemoteSocialVo> selectByAuthId(String authId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询列表
|
||||||
|
*
|
||||||
|
* @param bo 社会化关系业务对象
|
||||||
|
*/
|
||||||
|
List<RemoteSocialVo> queryList(RemoteSocialBo bo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存社会化关系
|
||||||
|
*
|
||||||
|
* @param bo 社会化关系业务对象
|
||||||
|
*/
|
||||||
|
void insertByBo(RemoteSocialBo bo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新社会化关系
|
||||||
|
*
|
||||||
|
* @param bo 社会化关系业务对象
|
||||||
|
*/
|
||||||
|
void updateByBo(RemoteSocialBo bo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除社会化关系
|
||||||
|
*
|
||||||
|
* @param socialId 社会化关系ID
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
Boolean deleteWithValidById(Long socialId);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
package org.asinkj.system.api;
|
||||||
|
|
||||||
|
|
||||||
|
import org.asinkj.system.api.domain.vo.RemoteTenantVo;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 租户服务
|
||||||
|
*
|
||||||
|
* @author zhujie
|
||||||
|
*/
|
||||||
|
public interface RemoteTenantService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据租户id获取租户详情
|
||||||
|
* @param tenantId 租户id
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
RemoteTenantVo queryByTenantId(String tenantId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取租户列表
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
List<RemoteTenantVo> queryList();
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,134 @@
|
|||||||
|
package org.asinkj.system.api;
|
||||||
|
|
||||||
|
import org.asinkj.common.core.exception.ServiceException;
|
||||||
|
import org.asinkj.common.core.exception.user.UserException;
|
||||||
|
import org.asinkj.system.api.domain.bo.RemoteUserBo;
|
||||||
|
import org.asinkj.system.api.domain.vo.RemoteUserVo;
|
||||||
|
import org.asinkj.system.api.model.LoginUser;
|
||||||
|
import org.asinkj.system.api.model.XcxLoginUser;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户服务
|
||||||
|
*
|
||||||
|
* @author Shuo Hu
|
||||||
|
*/
|
||||||
|
public interface RemoteUserService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过用户名查询用户信息
|
||||||
|
*
|
||||||
|
* @param username 用户名
|
||||||
|
* @param tenantId 租户id
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
LoginUser getUserInfo(String username, String tenantId) throws UserException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过用户id查询用户信息
|
||||||
|
*
|
||||||
|
* @param userId 用户id
|
||||||
|
* @param tenantId 租户id
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
LoginUser getUserInfo(Long userId, String tenantId) throws UserException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过手机号查询用户信息
|
||||||
|
*
|
||||||
|
* @param phonenumber 手机号
|
||||||
|
* @param tenantId 租户id
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
LoginUser getUserInfoByPhonenumber(String phonenumber, String tenantId) throws UserException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过邮箱查询用户信息
|
||||||
|
*
|
||||||
|
* @param email 邮箱
|
||||||
|
* @param tenantId 租户id
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
LoginUser getUserInfoByEmail(String email, String tenantId) throws UserException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过openid查询用户信息
|
||||||
|
*
|
||||||
|
* @param openid openid
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
XcxLoginUser getUserInfoByOpenid(String openid) throws UserException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注册用户信息
|
||||||
|
*
|
||||||
|
* @param remoteUserBo 用户信息
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
Boolean registerUserInfo(RemoteUserBo remoteUserBo) throws UserException, ServiceException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过userId查询用户账户
|
||||||
|
*
|
||||||
|
* @param userId 用户id
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
String selectUserNameById(Long userId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过用户ID查询用户昵称
|
||||||
|
*
|
||||||
|
* @param userId 用户id
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
String selectNicknameById(Long userId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过用户ID查询用户账户
|
||||||
|
*
|
||||||
|
* @param userIds 用户ID 多个用逗号隔开
|
||||||
|
* @return 用户名称
|
||||||
|
*/
|
||||||
|
String selectNicknameByIds(String userIds);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过用户ID查询用户手机号
|
||||||
|
*
|
||||||
|
* @param userId 用户id
|
||||||
|
* @return 用户手机号
|
||||||
|
*/
|
||||||
|
String selectPhonenumberById(Long userId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过用户ID查询用户邮箱
|
||||||
|
*
|
||||||
|
* @param userId 用户id
|
||||||
|
* @return 用户邮箱
|
||||||
|
*/
|
||||||
|
String selectEmailById(Long userId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新用户信息
|
||||||
|
*
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @param ip IP地址
|
||||||
|
*/
|
||||||
|
void recordLoginInfo(Long userId, String ip);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过用户ID查询用户列表
|
||||||
|
*
|
||||||
|
* @param userIds 用户ids
|
||||||
|
* @return 用户列表
|
||||||
|
*/
|
||||||
|
List<RemoteUserVo> selectListByIds(List<Long> userIds);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过角色ID查询用户ID
|
||||||
|
*
|
||||||
|
* @param roleIds 角色ids
|
||||||
|
* @return 用户ids
|
||||||
|
*/
|
||||||
|
List<Long> selectUserIdsByRoleIds(List<Long> roleIds);
|
||||||
|
}
|
@ -0,0 +1,71 @@
|
|||||||
|
package org.asinkj.system.api.domain;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前在线会话
|
||||||
|
*
|
||||||
|
* @author Shuo Hu
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class SysUserOnline implements Serializable {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会话编号
|
||||||
|
*/
|
||||||
|
private String tokenId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 部门名称
|
||||||
|
*/
|
||||||
|
private String deptName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户名称
|
||||||
|
*/
|
||||||
|
private String userName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户端
|
||||||
|
*/
|
||||||
|
private String clientKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备类型
|
||||||
|
*/
|
||||||
|
private String deviceType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录IP地址
|
||||||
|
*/
|
||||||
|
private String ipaddr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录地址
|
||||||
|
*/
|
||||||
|
private String loginLocation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 浏览器类型
|
||||||
|
*/
|
||||||
|
private String browser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 操作系统
|
||||||
|
*/
|
||||||
|
private String os;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录时间
|
||||||
|
*/
|
||||||
|
private Long loginTime;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,89 @@
|
|||||||
|
package org.asinkj.system.api.domain.bo;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统访问记录表 sys_logininfor
|
||||||
|
*
|
||||||
|
* @author Shuo Hu
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class RemoteLogininforBo implements Serializable {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 访问ID
|
||||||
|
*/
|
||||||
|
private Long infoId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 租户编号
|
||||||
|
*/
|
||||||
|
private String tenantId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户账号
|
||||||
|
*/
|
||||||
|
private String userName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户端
|
||||||
|
*/
|
||||||
|
private String clientKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备类型
|
||||||
|
*/
|
||||||
|
private String deviceType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录IP地址
|
||||||
|
*/
|
||||||
|
private String ipaddr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录地点
|
||||||
|
*/
|
||||||
|
private String loginLocation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 浏览器类型
|
||||||
|
*/
|
||||||
|
private String browser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 操作系统
|
||||||
|
*/
|
||||||
|
private String os;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录状态(0成功 1失败)
|
||||||
|
*/
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提示消息
|
||||||
|
*/
|
||||||
|
private String msg;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 访问时间
|
||||||
|
*/
|
||||||
|
private Date loginTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求参数
|
||||||
|
*/
|
||||||
|
private Map<String, Object> params = new HashMap<>();
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,119 @@
|
|||||||
|
package org.asinkj.system.api.domain.bo;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 操作日志记录表 oper_log
|
||||||
|
*
|
||||||
|
* @author Shuo Hu
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class RemoteOperLogBo implements Serializable {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日志主键
|
||||||
|
*/
|
||||||
|
private Long operId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 租户编号
|
||||||
|
*/
|
||||||
|
private String tenantId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模块标题
|
||||||
|
*/
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 业务类型(0其它 1新增 2修改 3删除)
|
||||||
|
*/
|
||||||
|
private Integer businessType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 方法名称
|
||||||
|
*/
|
||||||
|
private String method;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求方式
|
||||||
|
*/
|
||||||
|
private String requestMethod;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 操作类别(0其它 1后台用户 2手机端用户)
|
||||||
|
*/
|
||||||
|
private Integer operatorType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 操作人员
|
||||||
|
*/
|
||||||
|
private String operName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 部门名称
|
||||||
|
*/
|
||||||
|
private String deptName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求URL
|
||||||
|
*/
|
||||||
|
private String operUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主机地址
|
||||||
|
*/
|
||||||
|
private String operIp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 操作地点
|
||||||
|
*/
|
||||||
|
private String operLocation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求参数
|
||||||
|
*/
|
||||||
|
private String operParam;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回参数
|
||||||
|
*/
|
||||||
|
private String jsonResult;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 操作状态(0正常 1异常)
|
||||||
|
*/
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 错误消息
|
||||||
|
*/
|
||||||
|
private String errorMsg;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 操作时间
|
||||||
|
*/
|
||||||
|
private Date operTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消耗时间
|
||||||
|
*/
|
||||||
|
private Long costTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求参数
|
||||||
|
*/
|
||||||
|
private Map<String, Object> params = new HashMap<>();
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,129 @@
|
|||||||
|
package org.asinkj.system.api.domain.bo;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 社会化关系业务对象 sys_social
|
||||||
|
*
|
||||||
|
* @author Michelle.Chung
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class RemoteSocialBo implements Serializable {
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
/**
|
||||||
|
* 主键
|
||||||
|
*/
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 的唯一ID
|
||||||
|
*/
|
||||||
|
private String authId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户来源
|
||||||
|
*/
|
||||||
|
private String source;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户的授权令牌
|
||||||
|
*/
|
||||||
|
private String accessToken;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户的授权令牌的有效期,部分平台可能没有
|
||||||
|
*/
|
||||||
|
private int expireIn;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 刷新令牌,部分平台可能没有
|
||||||
|
*/
|
||||||
|
private String refreshToken;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 平台唯一id
|
||||||
|
*/
|
||||||
|
private String openId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户的 ID
|
||||||
|
*/
|
||||||
|
private Long userId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 平台的授权信息,部分平台可能没有
|
||||||
|
*/
|
||||||
|
private String accessCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户的 unionid
|
||||||
|
*/
|
||||||
|
private String unionId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 授予的权限,部分平台可能没有
|
||||||
|
*/
|
||||||
|
private String scope;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 授权的第三方账号
|
||||||
|
*/
|
||||||
|
private String userName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 授权的第三方昵称
|
||||||
|
*/
|
||||||
|
private String nickName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 授权的第三方邮箱
|
||||||
|
*/
|
||||||
|
private String email;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 授权的第三方头像地址
|
||||||
|
*/
|
||||||
|
private String avatar;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 个别平台的授权信息,部分平台可能没有
|
||||||
|
*/
|
||||||
|
private String tokenType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* id token,部分平台可能没有
|
||||||
|
*/
|
||||||
|
private String idToken;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 小米平台用户的附带属性,部分平台可能没有
|
||||||
|
*/
|
||||||
|
private String macAlgorithm;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 小米平台用户的附带属性,部分平台可能没有
|
||||||
|
*/
|
||||||
|
private String macKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户的授权code,部分平台可能没有
|
||||||
|
*/
|
||||||
|
private String code;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Twitter平台用户的附带属性,部分平台可能没有
|
||||||
|
*/
|
||||||
|
private String oauthToken;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Twitter平台用户的附带属性,部分平台可能没有
|
||||||
|
*/
|
||||||
|
private String oauthTokenSecret;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,124 @@
|
|||||||
|
package org.asinkj.system.api.domain.bo;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import org.asinkj.common.core.constant.UserConstants;
|
||||||
|
import org.asinkj.common.core.xss.Xss;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.Email;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import jakarta.validation.constraints.Size;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户信息业务对象 sys_user
|
||||||
|
*
|
||||||
|
* @author Michelle.Chung
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class RemoteUserBo implements Serializable {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户ID
|
||||||
|
*/
|
||||||
|
private Long userId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 租户ID
|
||||||
|
*/
|
||||||
|
private String tenantId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 部门ID
|
||||||
|
*/
|
||||||
|
private Long deptId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户账号
|
||||||
|
*/
|
||||||
|
@Xss(message = "用户账号不能包含脚本字符")
|
||||||
|
@NotBlank(message = "用户账号不能为空")
|
||||||
|
@Size(min = 0, max = 30, message = "用户账号长度不能超过{max}个字符")
|
||||||
|
private String userName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户昵称
|
||||||
|
*/
|
||||||
|
@Xss(message = "用户昵称不能包含脚本字符")
|
||||||
|
@Size(min = 0, max = 30, message = "用户昵称长度不能超过{max}个字符")
|
||||||
|
private String nickName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户类型(sys_user系统用户)
|
||||||
|
*/
|
||||||
|
private String userType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户邮箱
|
||||||
|
*/
|
||||||
|
@Email(message = "邮箱格式不正确")
|
||||||
|
@Size(min = 0, max = 50, message = "邮箱长度不能超过{max}个字符")
|
||||||
|
private String email;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 手机号码
|
||||||
|
*/
|
||||||
|
private String phonenumber;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户性别(0男 1女 2未知)
|
||||||
|
*/
|
||||||
|
private String sex;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 头像地址
|
||||||
|
*/
|
||||||
|
private Long avatar;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 密码
|
||||||
|
*/
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 帐号状态(0正常 1停用)
|
||||||
|
*/
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最后登录IP
|
||||||
|
*/
|
||||||
|
private String loginIp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最后登录时间
|
||||||
|
*/
|
||||||
|
private Date loginDate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 备注
|
||||||
|
*/
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据权限 当前角色ID
|
||||||
|
*/
|
||||||
|
private Long roleId;
|
||||||
|
|
||||||
|
public RemoteUserBo(Long userId) {
|
||||||
|
this.userId = userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSuperAdmin() {
|
||||||
|
return UserConstants.SUPER_ADMIN_ID.equals(this.userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,70 @@
|
|||||||
|
package org.asinkj.system.api.domain.vo;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 授权管理视图对象 sys_client
|
||||||
|
*
|
||||||
|
* @author Michelle.Chung
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class RemoteClientVo implements Serializable {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* id
|
||||||
|
*/
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户端id
|
||||||
|
*/
|
||||||
|
private String clientId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户端key
|
||||||
|
*/
|
||||||
|
private String clientKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户端秘钥
|
||||||
|
*/
|
||||||
|
private String clientSecret;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 授权类型
|
||||||
|
*/
|
||||||
|
private List<String> grantTypeList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 授权类型
|
||||||
|
*/
|
||||||
|
private String grantType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备类型
|
||||||
|
*/
|
||||||
|
private String deviceType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* token活跃超时时间
|
||||||
|
*/
|
||||||
|
private Long activeTimeout;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* token固定超时时间
|
||||||
|
*/
|
||||||
|
private Long timeout;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态(0正常 1停用)
|
||||||
|
*/
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,76 @@
|
|||||||
|
package org.asinkj.system.api.domain.vo;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字典数据视图对象 sys_dict_data
|
||||||
|
*
|
||||||
|
* @author Michelle.Chung
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class RemoteDictDataVo implements Serializable {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字典编码
|
||||||
|
*/
|
||||||
|
private Long dictCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字典排序
|
||||||
|
*/
|
||||||
|
private Integer dictSort;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字典标签
|
||||||
|
*/
|
||||||
|
private String dictLabel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字典键值
|
||||||
|
*/
|
||||||
|
private String dictValue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字典类型
|
||||||
|
*/
|
||||||
|
private String dictType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 样式属性(其他样式扩展)
|
||||||
|
*/
|
||||||
|
private String cssClass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表格回显样式
|
||||||
|
*/
|
||||||
|
private String listClass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否默认(Y是 N否)
|
||||||
|
*/
|
||||||
|
private String isDefault;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态(0正常 1停用)
|
||||||
|
*/
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 备注
|
||||||
|
*/
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建时间
|
||||||
|
*/
|
||||||
|
private Date createTime;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,135 @@
|
|||||||
|
package org.asinkj.system.api.domain.vo;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 社会化关系视图对象 sys_social
|
||||||
|
*
|
||||||
|
* @author thiszhc
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class RemoteSocialVo implements Serializable {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主键
|
||||||
|
*/
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户ID
|
||||||
|
*/
|
||||||
|
private Long userId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 租户ID
|
||||||
|
*/
|
||||||
|
private String tenantId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 认证唯一ID
|
||||||
|
*/
|
||||||
|
private String authId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户来源
|
||||||
|
*/
|
||||||
|
private String source;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户的授权令牌
|
||||||
|
*/
|
||||||
|
private String accessToken;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户的授权令牌的有效期,部分平台可能没有
|
||||||
|
*/
|
||||||
|
private int expireIn;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 刷新令牌,部分平台可能没有
|
||||||
|
*/
|
||||||
|
private String refreshToken;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户的 open id
|
||||||
|
*/
|
||||||
|
private String openId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 授权的第三方账号
|
||||||
|
*/
|
||||||
|
private String userName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 授权的第三方昵称
|
||||||
|
*/
|
||||||
|
private String nickName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 授权的第三方邮箱
|
||||||
|
*/
|
||||||
|
private String email;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 授权的第三方头像地址
|
||||||
|
*/
|
||||||
|
private String avatar;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 平台的授权信息,部分平台可能没有
|
||||||
|
*/
|
||||||
|
private String accessCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户的 unionid
|
||||||
|
*/
|
||||||
|
private String unionId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 授予的权限,部分平台可能没有
|
||||||
|
*/
|
||||||
|
private String scope;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 个别平台的授权信息,部分平台可能没有
|
||||||
|
*/
|
||||||
|
private String tokenType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* id token,部分平台可能没有
|
||||||
|
*/
|
||||||
|
private String idToken;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 小米平台用户的附带属性,部分平台可能没有
|
||||||
|
*/
|
||||||
|
private String macAlgorithm;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 小米平台用户的附带属性,部分平台可能没有
|
||||||
|
*/
|
||||||
|
private String macKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户的授权code,部分平台可能没有
|
||||||
|
*/
|
||||||
|
private String code;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Twitter平台用户的附带属性,部分平台可能没有
|
||||||
|
*/
|
||||||
|
private String oauthToken;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Twitter平台用户的附带属性,部分平台可能没有
|
||||||
|
*/
|
||||||
|
private String oauthTokenSecret;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,91 @@
|
|||||||
|
package org.asinkj.system.api.domain.vo;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 租户视图对象
|
||||||
|
*
|
||||||
|
* @author zhujie
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class RemoteTenantVo implements Serializable {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* id
|
||||||
|
*/
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 租户编号
|
||||||
|
*/
|
||||||
|
private String tenantId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 联系人
|
||||||
|
*/
|
||||||
|
private String contactUserName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 联系电话
|
||||||
|
*/
|
||||||
|
private String contactPhone;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 企业名称
|
||||||
|
*/
|
||||||
|
private String companyName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 统一社会信用代码
|
||||||
|
*/
|
||||||
|
private String licenseNumber;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 地址
|
||||||
|
*/
|
||||||
|
private String address;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 域名
|
||||||
|
*/
|
||||||
|
private String domain;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 企业简介
|
||||||
|
*/
|
||||||
|
private String intro;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 备注
|
||||||
|
*/
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 租户套餐编号
|
||||||
|
*/
|
||||||
|
private Long packageId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 过期时间
|
||||||
|
*/
|
||||||
|
private Date expireTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户数量(-1不限制)
|
||||||
|
*/
|
||||||
|
private Long accountCount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 租户状态(0正常 1停用)
|
||||||
|
*/
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,73 @@
|
|||||||
|
package org.asinkj.system.api.domain.vo;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户
|
||||||
|
*
|
||||||
|
* @author Michelle.Chung
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class RemoteUserVo implements Serializable {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户ID
|
||||||
|
*/
|
||||||
|
private Long userId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 部门ID
|
||||||
|
*/
|
||||||
|
private Long deptId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户账号
|
||||||
|
*/
|
||||||
|
private String userName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户昵称
|
||||||
|
*/
|
||||||
|
private String nickName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户类型(sys_user系统用户)
|
||||||
|
*/
|
||||||
|
private String userType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户邮箱
|
||||||
|
*/
|
||||||
|
private String email;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 手机号码
|
||||||
|
*/
|
||||||
|
private String phonenumber;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户性别(0男 1女 2未知)
|
||||||
|
*/
|
||||||
|
private String sex;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 帐号状态(0正常 1停用)
|
||||||
|
*/
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建时间
|
||||||
|
*/
|
||||||
|
private Date createTime;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,146 @@
|
|||||||
|
package org.asinkj.system.api.model;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户信息
|
||||||
|
*
|
||||||
|
* @author asinkj
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class LoginUser implements Serializable {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 租户ID
|
||||||
|
*/
|
||||||
|
private String tenantId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户ID
|
||||||
|
*/
|
||||||
|
private Long userId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 部门ID
|
||||||
|
*/
|
||||||
|
private Long deptId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 部门类别编码
|
||||||
|
*/
|
||||||
|
private String deptCategory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 部门名
|
||||||
|
*/
|
||||||
|
private String deptName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户唯一标识
|
||||||
|
*/
|
||||||
|
private String token;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户类型
|
||||||
|
*/
|
||||||
|
private String userType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录时间
|
||||||
|
*/
|
||||||
|
private Long loginTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 过期时间
|
||||||
|
*/
|
||||||
|
private Long expireTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录IP地址
|
||||||
|
*/
|
||||||
|
private String ipaddr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录地点
|
||||||
|
*/
|
||||||
|
private String loginLocation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 浏览器类型
|
||||||
|
*/
|
||||||
|
private String browser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 操作系统
|
||||||
|
*/
|
||||||
|
private String os;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 菜单权限
|
||||||
|
*/
|
||||||
|
private Set<String> menuPermission;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 角色权限
|
||||||
|
*/
|
||||||
|
private Set<String> rolePermission;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户名
|
||||||
|
*/
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户昵称
|
||||||
|
*/
|
||||||
|
private String nickname;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 密码
|
||||||
|
*/
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 角色对象
|
||||||
|
*/
|
||||||
|
private List<RoleDTO> roles;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据权限 当前角色ID
|
||||||
|
*/
|
||||||
|
private Long roleId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户端
|
||||||
|
*/
|
||||||
|
private String clientKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备类型
|
||||||
|
*/
|
||||||
|
private String deviceType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取登录id
|
||||||
|
*/
|
||||||
|
public String getLoginId() {
|
||||||
|
if (userType == null) {
|
||||||
|
throw new IllegalArgumentException("用户类型不能为空");
|
||||||
|
}
|
||||||
|
if (userId == null) {
|
||||||
|
throw new IllegalArgumentException("用户ID不能为空");
|
||||||
|
}
|
||||||
|
return userType + ":" + userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
package org.asinkj.system.api.model;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 角色
|
||||||
|
*
|
||||||
|
* @author Shuo Hu
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class RoleDTO implements Serializable {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 角色ID
|
||||||
|
*/
|
||||||
|
private Long roleId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 角色名称
|
||||||
|
*/
|
||||||
|
private String roleName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 角色权限
|
||||||
|
*/
|
||||||
|
private String roleKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据范围(1:所有数据权限;2:自定义数据权限;3:本部门数据权限;4:本部门及以下数据权限;5:仅本人数据权限)
|
||||||
|
*/
|
||||||
|
private String dataScope;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package org.asinkj.system.api.model;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 小程序登录用户身份权限
|
||||||
|
*
|
||||||
|
* @author Shuo Hu
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class XcxLoginUser extends LoginUser {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* openid
|
||||||
|
*/
|
||||||
|
private String openid;
|
||||||
|
|
||||||
|
}
|
32
asinkj-api/asinkj-api-workflow/pom.xml
Normal file
32
asinkj-api/asinkj-api-workflow/pom.xml
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-api</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>asinkj-api-workflow</artifactId>
|
||||||
|
|
||||||
|
<description>
|
||||||
|
asinkj-api-workflow 工作流接口模块
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<!-- AsinKj Common Core-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common-core</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common-bus</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
@ -0,0 +1,78 @@
|
|||||||
|
package org.asinkj.workflow.api.domain;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通用 工作流服务
|
||||||
|
*
|
||||||
|
* @Author ZETA
|
||||||
|
* @Date 2024/6/3
|
||||||
|
*/
|
||||||
|
public interface RemoteWorkflowService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 运行中的实例 删除程实例,删除历史记录,删除业务与流程关联信息
|
||||||
|
*
|
||||||
|
* @param businessKeys 业务id
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
boolean deleteRunAndHisInstance(List<String> businessKeys);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前流程状态
|
||||||
|
*
|
||||||
|
* @param taskId 任务id
|
||||||
|
*/
|
||||||
|
String getBusinessStatusByTaskId(String taskId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前流程状态
|
||||||
|
*
|
||||||
|
* @param businessKey 业务id
|
||||||
|
*/
|
||||||
|
String getBusinessStatus(String businessKey);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置流程变量(全局变量)
|
||||||
|
*
|
||||||
|
* @param taskId 任务id
|
||||||
|
* @param variableName 变量名称
|
||||||
|
* @param value 变量值
|
||||||
|
*/
|
||||||
|
void setVariable(String taskId, String variableName, Object value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置流程变量(全局变量)
|
||||||
|
*
|
||||||
|
* @param taskId 任务id
|
||||||
|
* @param variables 流程变量
|
||||||
|
*/
|
||||||
|
void setVariables(String taskId, Map<String, Object> variables);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置流程变量(本地变量,非全局变量)
|
||||||
|
*
|
||||||
|
* @param taskId 任务id
|
||||||
|
* @param variableName 变量名称
|
||||||
|
* @param value 变量值
|
||||||
|
*/
|
||||||
|
void setVariableLocal(String taskId, String variableName, Object value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置流程变量(本地变量,非全局变量)
|
||||||
|
*
|
||||||
|
* @param taskId 任务id
|
||||||
|
* @param variables 流程变量
|
||||||
|
*/
|
||||||
|
void setVariablesLocal(String taskId, Map<String, Object> variables);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按照业务id查询流程实例id
|
||||||
|
*
|
||||||
|
* @param businessKey 业务id
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
String getInstanceIdByBusinessKey(String businessKey);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
package org.asinkj.workflow.api.domain.event;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import org.asinkj.common.core.utils.SpringUtils;
|
||||||
|
import org.springframework.cloud.bus.event.RemoteApplicationEvent;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 总体流程监听
|
||||||
|
*
|
||||||
|
* @author may
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class ProcessEvent extends RemoteApplicationEvent {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 流程定义key
|
||||||
|
*/
|
||||||
|
private String key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 业务id
|
||||||
|
*/
|
||||||
|
private String businessKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态
|
||||||
|
*/
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当为true时为申请人节点办理
|
||||||
|
*/
|
||||||
|
private boolean submit;
|
||||||
|
|
||||||
|
public ProcessEvent() {
|
||||||
|
super(new Object(), SpringUtils.getApplicationName(), DEFAULT_DESTINATION_FACTORY.getDestination(null));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
package org.asinkj.workflow.api.domain.event;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import org.asinkj.common.core.utils.SpringUtils;
|
||||||
|
import org.springframework.cloud.bus.event.RemoteApplicationEvent;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 流程办理监听
|
||||||
|
*
|
||||||
|
* @author may
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class ProcessTaskEvent extends RemoteApplicationEvent {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 流程定义key
|
||||||
|
*/
|
||||||
|
private String key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 审批节点key
|
||||||
|
*/
|
||||||
|
private String taskDefinitionKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 任务id
|
||||||
|
*/
|
||||||
|
private String taskId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 业务id
|
||||||
|
*/
|
||||||
|
private String businessKey;
|
||||||
|
|
||||||
|
public ProcessTaskEvent() {
|
||||||
|
super(new Object(), SpringUtils.getApplicationName(), DEFAULT_DESTINATION_FACTORY.getDestination(null));
|
||||||
|
}
|
||||||
|
}
|
25
asinkj-api/pom.xml
Normal file
25
asinkj-api/pom.xml
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-cloud-plus</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<modules>
|
||||||
|
<module>asinkj-api-bom</module>
|
||||||
|
<module>asinkj-api-system</module>
|
||||||
|
<module>asinkj-api-resource</module>
|
||||||
|
<module>asinkj-api-workflow</module>
|
||||||
|
</modules>
|
||||||
|
|
||||||
|
<artifactId>asinkj-api</artifactId>
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
|
||||||
|
<description>
|
||||||
|
asinkj-api系统接口
|
||||||
|
</description>
|
||||||
|
|
||||||
|
</project>
|
25
asinkj-auth/Dockerfile
Normal file
25
asinkj-auth/Dockerfile
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# 贝尔实验室 Spring 官方推荐镜像 JDK下载地址 https://bell-sw.com/pages/downloads/
|
||||||
|
FROM bellsoft/liberica-openjdk-debian:17.0.11-cds
|
||||||
|
#FROM bellsoft/liberica-openjdk-debian:21.0.3-cds
|
||||||
|
#FROM findepi/graalvm:java17-native
|
||||||
|
|
||||||
|
LABEL maintainer="Shuo Hu "
|
||||||
|
|
||||||
|
RUN mkdir -p /asinkj/auth/logs \
|
||||||
|
/asinkj/auth/temp \
|
||||||
|
/asinkj/skywalking/agent
|
||||||
|
|
||||||
|
WORKDIR /asinkj/auth
|
||||||
|
|
||||||
|
ENV SERVER_PORT=9210 LANG=C.UTF-8 LC_ALL=C.UTF-8 JAVA_OPTS=""
|
||||||
|
|
||||||
|
EXPOSE ${SERVER_PORT}
|
||||||
|
|
||||||
|
ADD ./target/asinkj-auth.jar ./app.jar
|
||||||
|
|
||||||
|
ENTRYPOINT java -Djava.security.egd=file:/dev/./urandom -Dserver.port=${SERVER_PORT} \
|
||||||
|
#-Dskywalking.agent.service_name=asinkj-auth \
|
||||||
|
#-javaagent:/asinkj/skywalking/agent/skywalking-agent.jar \
|
||||||
|
-XX:+HeapDumpOnOutOfMemoryError -XX:+UseZGC ${JAVA_OPTS} \
|
||||||
|
-jar app.jar
|
||||||
|
|
133
asinkj-auth/pom.xml
Normal file
133
asinkj-auth/pom.xml
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-cloud-plus</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>asinkj-auth</artifactId>
|
||||||
|
|
||||||
|
<description>
|
||||||
|
asinkj-auth 认证授权中心
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common-nacos</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.hutool</groupId>
|
||||||
|
<artifactId>hutool-captcha</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common-sentinel</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- AsinKj Common Security-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common-security</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common-social</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- AsinKj Common Log -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common-log</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common-doc</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common-ratelimiter</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common-encrypt</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common-dubbo</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common-seata</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common-tenant</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-api-resource</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 自定义负载均衡(多团队开发使用) -->
|
||||||
|
<!-- <dependency>-->
|
||||||
|
<!-- <groupId>org.asinkj</groupId>-->
|
||||||
|
<!-- <artifactId>asinkj-common-loadbalancer</artifactId>-->
|
||||||
|
<!-- </dependency>-->
|
||||||
|
|
||||||
|
<!-- ELK 日志收集 -->
|
||||||
|
<!-- <dependency>-->
|
||||||
|
<!-- <groupId>org.asinkj</groupId>-->
|
||||||
|
<!-- <artifactId>asinkj-common-logstash</artifactId>-->
|
||||||
|
<!-- </dependency>-->
|
||||||
|
|
||||||
|
<!-- skywalking 日志收集 -->
|
||||||
|
<!-- <dependency>-->
|
||||||
|
<!-- <groupId>org.asinkj</groupId>-->
|
||||||
|
<!-- <artifactId>asinkj-common-skylog</artifactId>-->
|
||||||
|
<!-- </dependency>-->
|
||||||
|
|
||||||
|
<!-- prometheus 监控 -->
|
||||||
|
<!-- <dependency>-->
|
||||||
|
<!-- <groupId>org.asinkj</groupId>-->
|
||||||
|
<!-- <artifactId>asinkj-common-prometheus</artifactId>-->
|
||||||
|
<!-- </dependency>-->
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<finalName>${project.artifactId}</finalName>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
<version>${spring-boot.version}</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>repackage</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
@ -0,0 +1,23 @@
|
|||||||
|
package org.asinkj.auth;
|
||||||
|
|
||||||
|
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||||
|
import org.springframework.boot.context.metrics.buffering.BufferingApplicationStartup;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 认证授权中心
|
||||||
|
*
|
||||||
|
* @author asinkj
|
||||||
|
*/
|
||||||
|
@EnableDubbo
|
||||||
|
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
|
||||||
|
public class AsinKjAuthApplication {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication application = new SpringApplication(AsinKjAuthApplication.class);
|
||||||
|
application.setApplicationStartup(new BufferingApplicationStartup(2048));
|
||||||
|
application.run(args);
|
||||||
|
System.out.println("(♥◠‿◠)ノ゙ 认证授权中心启动成功 ლ(´ڡ`ლ)゙ ");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,88 @@
|
|||||||
|
package org.asinkj.auth.captcha;
|
||||||
|
|
||||||
|
import cn.hutool.captcha.generator.CodeGenerator;
|
||||||
|
import cn.hutool.core.math.Calculator;
|
||||||
|
import cn.hutool.core.util.CharUtil;
|
||||||
|
import cn.hutool.core.util.RandomUtil;
|
||||||
|
import org.asinkj.common.core.utils.StringUtils;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 无符号计算生成器
|
||||||
|
*
|
||||||
|
* @author Shuo Hu
|
||||||
|
*/
|
||||||
|
public class UnsignedMathGenerator implements CodeGenerator {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = -5514819971774091076L;
|
||||||
|
|
||||||
|
private static final String OPERATORS = "+-*";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 参与计算数字最大长度
|
||||||
|
*/
|
||||||
|
private final int numberLength;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
*/
|
||||||
|
public UnsignedMathGenerator() {
|
||||||
|
this(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
*
|
||||||
|
* @param numberLength 参与计算最大数字位数
|
||||||
|
*/
|
||||||
|
public UnsignedMathGenerator(int numberLength) {
|
||||||
|
this.numberLength = numberLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String generate() {
|
||||||
|
final int limit = getLimit();
|
||||||
|
int a = RandomUtil.randomInt(limit);
|
||||||
|
int b = RandomUtil.randomInt(limit);
|
||||||
|
String max = Integer.toString(Math.max(a,b));
|
||||||
|
String min = Integer.toString(Math.min(a,b));
|
||||||
|
max = StringUtils.rightPad(max, this.numberLength, CharUtil.SPACE);
|
||||||
|
min = StringUtils.rightPad(min, this.numberLength, CharUtil.SPACE);
|
||||||
|
|
||||||
|
return max + RandomUtil.randomChar(OPERATORS) + min + '=';
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean verify(String code, String userInputCode) {
|
||||||
|
int result;
|
||||||
|
try {
|
||||||
|
result = Integer.parseInt(userInputCode);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
// 用户输入非数字
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
final int calculateResult = (int) Calculator.conversion(code);
|
||||||
|
return result == calculateResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取验证码长度
|
||||||
|
*
|
||||||
|
* @return 验证码长度
|
||||||
|
*/
|
||||||
|
public int getLength() {
|
||||||
|
return this.numberLength * 2 + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据长度获取参与计算数字最大值
|
||||||
|
*
|
||||||
|
* @return 最大值
|
||||||
|
*/
|
||||||
|
private int getLimit() {
|
||||||
|
return Integer.parseInt("1" + StringUtils.repeat('0', this.numberLength));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
package org.asinkj.auth.config;
|
||||||
|
|
||||||
|
import cn.hutool.captcha.CaptchaUtil;
|
||||||
|
import cn.hutool.captcha.CircleCaptcha;
|
||||||
|
import cn.hutool.captcha.LineCaptcha;
|
||||||
|
import cn.hutool.captcha.ShearCaptcha;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.annotation.Lazy;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证码配置
|
||||||
|
*
|
||||||
|
* @author Shuo Hu
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class CaptchaConfig {
|
||||||
|
|
||||||
|
private static final int WIDTH = 160;
|
||||||
|
private static final int HEIGHT = 60;
|
||||||
|
private static final Color BACKGROUND = Color.LIGHT_GRAY;
|
||||||
|
private static final Font FONT = new Font("Arial", Font.BOLD, 48);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 圆圈干扰验证码
|
||||||
|
*/
|
||||||
|
@Lazy
|
||||||
|
@Bean
|
||||||
|
public CircleCaptcha circleCaptcha() {
|
||||||
|
CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(WIDTH, HEIGHT);
|
||||||
|
captcha.setBackground(BACKGROUND);
|
||||||
|
captcha.setFont(FONT);
|
||||||
|
return captcha;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 线段干扰的验证码
|
||||||
|
*/
|
||||||
|
@Lazy
|
||||||
|
@Bean
|
||||||
|
public LineCaptcha lineCaptcha() {
|
||||||
|
LineCaptcha captcha = CaptchaUtil.createLineCaptcha(WIDTH, HEIGHT);
|
||||||
|
captcha.setBackground(BACKGROUND);
|
||||||
|
captcha.setFont(FONT);
|
||||||
|
return captcha;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 扭曲干扰验证码
|
||||||
|
*/
|
||||||
|
@Lazy
|
||||||
|
@Bean
|
||||||
|
public ShearCaptcha shearCaptcha() {
|
||||||
|
ShearCaptcha captcha = CaptchaUtil.createShearCaptcha(WIDTH, HEIGHT);
|
||||||
|
captcha.setBackground(BACKGROUND);
|
||||||
|
captcha.setFont(FONT);
|
||||||
|
return captcha;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,78 @@
|
|||||||
|
package org.asinkj.auth.controller;
|
||||||
|
|
||||||
|
import cn.hutool.captcha.AbstractCaptcha;
|
||||||
|
import cn.hutool.captcha.generator.CodeGenerator;
|
||||||
|
import cn.hutool.core.util.IdUtil;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.asinkj.auth.domain.vo.CaptchaVo;
|
||||||
|
import org.asinkj.auth.enums.CaptchaType;
|
||||||
|
import org.asinkj.auth.properties.CaptchaProperties;
|
||||||
|
import org.asinkj.common.core.constant.Constants;
|
||||||
|
import org.asinkj.common.core.constant.GlobalConstants;
|
||||||
|
import org.asinkj.common.core.domain.R;
|
||||||
|
import org.asinkj.common.core.utils.SpringUtils;
|
||||||
|
import org.asinkj.common.core.utils.StringUtils;
|
||||||
|
import org.asinkj.common.core.utils.reflect.ReflectUtils;
|
||||||
|
import org.asinkj.common.ratelimiter.annotation.RateLimiter;
|
||||||
|
import org.asinkj.common.ratelimiter.enums.LimitType;
|
||||||
|
import org.asinkj.common.redis.utils.RedisUtils;
|
||||||
|
import org.springframework.expression.Expression;
|
||||||
|
import org.springframework.expression.ExpressionParser;
|
||||||
|
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证码操作处理
|
||||||
|
*
|
||||||
|
* @author Shuo Hu
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Validated
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@RestController
|
||||||
|
public class CaptchaController {
|
||||||
|
|
||||||
|
private final CaptchaProperties captchaProperties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成验证码
|
||||||
|
*/
|
||||||
|
@RateLimiter(time = 60, count = 10, limitType = LimitType.IP)
|
||||||
|
@GetMapping("/code")
|
||||||
|
public R<CaptchaVo> getCode() {
|
||||||
|
CaptchaVo captchaVo = new CaptchaVo();
|
||||||
|
boolean captchaEnabled = captchaProperties.getEnabled();
|
||||||
|
if (!captchaEnabled) {
|
||||||
|
captchaVo.setCaptchaEnabled(false);
|
||||||
|
return R.ok(captchaVo);
|
||||||
|
}
|
||||||
|
// 保存验证码信息
|
||||||
|
String uuid = IdUtil.simpleUUID();
|
||||||
|
String verifyKey = GlobalConstants.CAPTCHA_CODE_KEY + uuid;
|
||||||
|
// 生成验证码
|
||||||
|
CaptchaType captchaType = captchaProperties.getType();
|
||||||
|
boolean isMath = CaptchaType.MATH == captchaType;
|
||||||
|
Integer length = isMath ? captchaProperties.getNumberLength() : captchaProperties.getCharLength();
|
||||||
|
CodeGenerator codeGenerator = ReflectUtils.newInstance(captchaType.getClazz(), length);
|
||||||
|
AbstractCaptcha captcha = SpringUtils.getBean(captchaProperties.getCategory().getClazz());
|
||||||
|
captcha.setGenerator(codeGenerator);
|
||||||
|
captcha.createCode();
|
||||||
|
// 如果是数学验证码,使用SpEL表达式处理验证码结果
|
||||||
|
String code = captcha.getCode();
|
||||||
|
if (isMath) {
|
||||||
|
ExpressionParser parser = new SpelExpressionParser();
|
||||||
|
Expression exp = parser.parseExpression(StringUtils.remove(code, "="));
|
||||||
|
code = exp.getValue(String.class);
|
||||||
|
}
|
||||||
|
RedisUtils.setCacheObject(verifyKey, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION));
|
||||||
|
captchaVo.setUuid(uuid);
|
||||||
|
captchaVo.setImg(captcha.getImageBase64());
|
||||||
|
return R.ok(captchaVo);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,231 @@
|
|||||||
|
package org.asinkj.auth.controller;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.exception.NotLoginException;
|
||||||
|
import cn.hutool.core.codec.Base64;
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import me.zhyd.oauth.model.AuthResponse;
|
||||||
|
import me.zhyd.oauth.model.AuthUser;
|
||||||
|
import me.zhyd.oauth.request.AuthRequest;
|
||||||
|
import me.zhyd.oauth.utils.AuthStateUtils;
|
||||||
|
import org.apache.dubbo.config.annotation.DubboReference;
|
||||||
|
import org.asinkj.auth.domain.vo.LoginTenantVo;
|
||||||
|
import org.asinkj.auth.domain.vo.LoginVo;
|
||||||
|
import org.asinkj.auth.domain.vo.TenantListVo;
|
||||||
|
import org.asinkj.auth.form.RegisterBody;
|
||||||
|
import org.asinkj.auth.form.SocialLoginBody;
|
||||||
|
import org.asinkj.auth.service.IAuthStrategy;
|
||||||
|
import org.asinkj.auth.service.SysLoginService;
|
||||||
|
import org.asinkj.common.core.constant.UserConstants;
|
||||||
|
import org.asinkj.common.core.domain.R;
|
||||||
|
import org.asinkj.common.core.domain.model.LoginBody;
|
||||||
|
import org.asinkj.common.core.utils.*;
|
||||||
|
import org.asinkj.common.encrypt.annotation.ApiEncrypt;
|
||||||
|
import org.asinkj.common.json.utils.JsonUtils;
|
||||||
|
import org.asinkj.common.satoken.utils.LoginHelper;
|
||||||
|
import org.asinkj.common.social.config.properties.SocialLoginConfigProperties;
|
||||||
|
import org.asinkj.common.social.config.properties.SocialProperties;
|
||||||
|
import org.asinkj.common.social.utils.SocialUtils;
|
||||||
|
import org.asinkj.common.tenant.helper.TenantHelper;
|
||||||
|
import org.asinkj.resource.api.RemoteMessageService;
|
||||||
|
import org.asinkj.system.api.RemoteClientService;
|
||||||
|
import org.asinkj.system.api.RemoteConfigService;
|
||||||
|
import org.asinkj.system.api.RemoteSocialService;
|
||||||
|
import org.asinkj.system.api.RemoteTenantService;
|
||||||
|
import org.asinkj.system.api.domain.vo.RemoteClientVo;
|
||||||
|
import org.asinkj.system.api.domain.vo.RemoteTenantVo;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* token 控制
|
||||||
|
*
|
||||||
|
* @author Shuo Hu
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@RestController
|
||||||
|
public class TokenController {
|
||||||
|
|
||||||
|
private final SocialProperties socialProperties;
|
||||||
|
private final SysLoginService sysLoginService;
|
||||||
|
private final ScheduledExecutorService scheduledExecutorService;
|
||||||
|
|
||||||
|
@DubboReference
|
||||||
|
private final RemoteConfigService remoteConfigService;
|
||||||
|
@DubboReference
|
||||||
|
private final RemoteTenantService remoteTenantService;
|
||||||
|
@DubboReference
|
||||||
|
private final RemoteClientService remoteClientService;
|
||||||
|
@DubboReference
|
||||||
|
private final RemoteSocialService remoteSocialService;
|
||||||
|
@DubboReference(stub = "true")
|
||||||
|
private final RemoteMessageService remoteMessageService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录方法
|
||||||
|
*
|
||||||
|
* @param body 登录信息
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
@ApiEncrypt
|
||||||
|
@PostMapping("/login")
|
||||||
|
public R<LoginVo> login(@RequestBody String body) {
|
||||||
|
LoginBody loginBody = JsonUtils.parseObject(body, LoginBody.class);
|
||||||
|
ValidatorUtils.validate(loginBody);
|
||||||
|
// 授权类型和客户端id
|
||||||
|
String clientId = loginBody.getClientId();
|
||||||
|
String grantType = loginBody.getGrantType();
|
||||||
|
RemoteClientVo clientVo = remoteClientService.queryByClientId(clientId);
|
||||||
|
|
||||||
|
// 查询不到 client 或 client 内不包含 grantType
|
||||||
|
if (ObjectUtil.isNull(clientVo) || !StringUtils.contains(clientVo.getGrantType(), grantType)) {
|
||||||
|
log.info("客户端id: {} 认证类型:{} 异常!.", clientId, grantType);
|
||||||
|
return R.fail(MessageUtils.message("auth.grant.type.error"));
|
||||||
|
} else if (!UserConstants.NORMAL.equals(clientVo.getStatus())) {
|
||||||
|
return R.fail(MessageUtils.message("auth.grant.type.blocked"));
|
||||||
|
}
|
||||||
|
// 校验租户
|
||||||
|
sysLoginService.checkTenant(loginBody.getTenantId());
|
||||||
|
// 登录
|
||||||
|
LoginVo loginVo = IAuthStrategy.login(body, clientVo, grantType);
|
||||||
|
|
||||||
|
Long userId = LoginHelper.getUserId();
|
||||||
|
scheduledExecutorService.schedule(() -> {
|
||||||
|
remoteMessageService.publishMessage(userId, "欢迎登录瑷胜科技管理系统");
|
||||||
|
}, 3, TimeUnit.SECONDS);
|
||||||
|
return R.ok(loginVo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 第三方登录请求
|
||||||
|
*
|
||||||
|
* @param source 登录来源
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
@GetMapping("/binding/{source}")
|
||||||
|
public R<String> authBinding(@PathVariable("source") String source,
|
||||||
|
@RequestParam String tenantId, @RequestParam String domain) {
|
||||||
|
SocialLoginConfigProperties obj = socialProperties.getType().get(source);
|
||||||
|
if (ObjectUtil.isNull(obj)) {
|
||||||
|
return R.fail(source + "平台账号暂不支持");
|
||||||
|
}
|
||||||
|
AuthRequest authRequest = SocialUtils.getAuthRequest(source, socialProperties);
|
||||||
|
Map<String, String> map = new HashMap<>();
|
||||||
|
map.put("tenantId", tenantId);
|
||||||
|
map.put("domain", domain);
|
||||||
|
map.put("state", AuthStateUtils.createState());
|
||||||
|
String authorizeUrl = authRequest.authorize(Base64.encode(JsonUtils.toJsonString(map), StandardCharsets.UTF_8));
|
||||||
|
return R.ok("操作成功", authorizeUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 第三方登录回调业务处理 绑定授权
|
||||||
|
*
|
||||||
|
* @param loginBody 请求体
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
@PostMapping("/social/callback")
|
||||||
|
public R<Void> socialCallback(@RequestBody SocialLoginBody loginBody) {
|
||||||
|
// 获取第三方登录信息
|
||||||
|
AuthResponse<AuthUser> response = SocialUtils.loginAuth(
|
||||||
|
loginBody.getSource(), loginBody.getSocialCode(),
|
||||||
|
loginBody.getSocialState(), socialProperties);
|
||||||
|
AuthUser authUserData = response.getData();
|
||||||
|
// 判断授权响应是否成功
|
||||||
|
if (!response.ok()) {
|
||||||
|
return R.fail(response.getMsg());
|
||||||
|
}
|
||||||
|
sysLoginService.socialRegister(authUserData);
|
||||||
|
return R.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 取消授权
|
||||||
|
*
|
||||||
|
* @param socialId socialId
|
||||||
|
*/
|
||||||
|
@DeleteMapping(value = "/unlock/{socialId}")
|
||||||
|
public R<Void> unlockSocial(@PathVariable Long socialId) {
|
||||||
|
Boolean rows = remoteSocialService.deleteWithValidById(socialId);
|
||||||
|
return rows ? R.ok() : R.fail("取消授权失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登出方法
|
||||||
|
*/
|
||||||
|
@PostMapping("logout")
|
||||||
|
public R<Void> logout() {
|
||||||
|
sysLoginService.logout();
|
||||||
|
return R.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户注册
|
||||||
|
*/
|
||||||
|
@ApiEncrypt
|
||||||
|
@PostMapping("register")
|
||||||
|
public R<Void> register(@RequestBody RegisterBody registerBody) {
|
||||||
|
if (!remoteConfigService.selectRegisterEnabled(registerBody.getTenantId())) {
|
||||||
|
return R.fail("当前系统没有开启注册功能!");
|
||||||
|
}
|
||||||
|
// 用户注册
|
||||||
|
sysLoginService.register(registerBody);
|
||||||
|
return R.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录页面租户下拉框
|
||||||
|
*
|
||||||
|
* @return 租户列表
|
||||||
|
*/
|
||||||
|
@GetMapping("/tenant/list")
|
||||||
|
public R<LoginTenantVo> tenantList(HttpServletRequest request) throws Exception {
|
||||||
|
// 返回对象
|
||||||
|
LoginTenantVo result = new LoginTenantVo();
|
||||||
|
boolean enable = TenantHelper.isEnable();
|
||||||
|
result.setTenantEnabled(enable);
|
||||||
|
// 如果未开启租户这直接返回
|
||||||
|
if (!enable) {
|
||||||
|
return R.ok(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<RemoteTenantVo> tenantList = remoteTenantService.queryList();
|
||||||
|
List<TenantListVo> voList = MapstructUtils.convert(tenantList, TenantListVo.class);
|
||||||
|
try {
|
||||||
|
// 如果只超管返回所有租户
|
||||||
|
if (LoginHelper.isSuperAdmin()) {
|
||||||
|
result.setVoList(voList);
|
||||||
|
return R.ok(result);
|
||||||
|
}
|
||||||
|
} catch (NotLoginException ignored) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取域名
|
||||||
|
String host;
|
||||||
|
String referer = request.getHeader("referer");
|
||||||
|
if (StringUtils.isNotBlank(referer)) {
|
||||||
|
// 这里从referer中取值是为了本地使用hosts添加虚拟域名,方便本地环境调试
|
||||||
|
host = referer.split("//")[1].split("/")[0];
|
||||||
|
} else {
|
||||||
|
host = new URL(request.getRequestURL().toString()).getHost();
|
||||||
|
}
|
||||||
|
// 根据域名进行筛选
|
||||||
|
List<TenantListVo> list = StreamUtils.filter(voList, vo ->
|
||||||
|
StringUtils.equals(vo.getDomain(), host));
|
||||||
|
result.setVoList(CollUtil.isNotEmpty(list) ? list : voList);
|
||||||
|
return R.ok(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
package org.asinkj.auth.domain.convert;
|
||||||
|
|
||||||
|
import io.github.linpeilie.BaseMapper;
|
||||||
|
import org.asinkj.auth.domain.vo.TenantListVo;
|
||||||
|
import org.asinkj.system.api.domain.vo.RemoteTenantVo;
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.MappingConstants;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 租户vo转换器
|
||||||
|
* @author zhujie
|
||||||
|
*/
|
||||||
|
@Mapper(componentModel = MappingConstants.ComponentModel.SPRING)
|
||||||
|
public interface TenantVoConvert extends BaseMapper<RemoteTenantVo, TenantListVo> {
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package org.asinkj.auth.domain.vo;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证码信息
|
||||||
|
*
|
||||||
|
* @author Michelle.Chung
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class CaptchaVo {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否开启验证码
|
||||||
|
*/
|
||||||
|
private Boolean captchaEnabled = true;
|
||||||
|
|
||||||
|
private String uuid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证码图片
|
||||||
|
*/
|
||||||
|
private String img;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package org.asinkj.auth.domain.vo;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录租户对象
|
||||||
|
*
|
||||||
|
* @author Michelle.Chung
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class LoginTenantVo {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 租户开关
|
||||||
|
*/
|
||||||
|
private Boolean tenantEnabled;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 租户对象列表
|
||||||
|
*/
|
||||||
|
private List<TenantListVo> voList;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
package org.asinkj.auth.domain.vo;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录验证信息
|
||||||
|
*
|
||||||
|
* @author Michelle.Chung
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class LoginVo {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 授权令牌
|
||||||
|
*/
|
||||||
|
@JsonProperty("access_token")
|
||||||
|
private String accessToken;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 刷新令牌
|
||||||
|
*/
|
||||||
|
@JsonProperty("refresh_token")
|
||||||
|
private String refreshToken;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 授权令牌 access_token 的有效期
|
||||||
|
*/
|
||||||
|
@JsonProperty("expire_in")
|
||||||
|
private Long expireIn;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 刷新令牌 refresh_token 的有效期
|
||||||
|
*/
|
||||||
|
@JsonProperty("refresh_expire_in")
|
||||||
|
private Long refreshExpireIn;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用id
|
||||||
|
*/
|
||||||
|
@JsonProperty("client_id")
|
||||||
|
private String clientId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 令牌权限
|
||||||
|
*/
|
||||||
|
private String scope;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户 openid
|
||||||
|
*/
|
||||||
|
private String openid;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
package org.asinkj.auth.domain.vo;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 租户列表
|
||||||
|
*
|
||||||
|
* @author zhujie
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class TenantListVo {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 租户编号
|
||||||
|
*/
|
||||||
|
private String tenantId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 企业名称
|
||||||
|
*/
|
||||||
|
private String companyName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 域名
|
||||||
|
*/
|
||||||
|
private String domain;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
package org.asinkj.auth.enums;
|
||||||
|
|
||||||
|
import cn.hutool.captcha.AbstractCaptcha;
|
||||||
|
import cn.hutool.captcha.CircleCaptcha;
|
||||||
|
import cn.hutool.captcha.LineCaptcha;
|
||||||
|
import cn.hutool.captcha.ShearCaptcha;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证码类别
|
||||||
|
*
|
||||||
|
* @author Shuo Hu
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public enum CaptchaCategory {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 线段干扰
|
||||||
|
*/
|
||||||
|
LINE(LineCaptcha.class),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 圆圈干扰
|
||||||
|
*/
|
||||||
|
CIRCLE(CircleCaptcha.class),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 扭曲干扰
|
||||||
|
*/
|
||||||
|
SHEAR(ShearCaptcha.class);
|
||||||
|
|
||||||
|
private final Class<? extends AbstractCaptcha> clazz;
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
package org.asinkj.auth.enums;
|
||||||
|
|
||||||
|
import cn.hutool.captcha.generator.CodeGenerator;
|
||||||
|
import cn.hutool.captcha.generator.RandomGenerator;
|
||||||
|
import org.asinkj.auth.captcha.UnsignedMathGenerator;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证码类型
|
||||||
|
*
|
||||||
|
* @author Shuo Hu
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public enum CaptchaType {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数字
|
||||||
|
*/
|
||||||
|
MATH(UnsignedMathGenerator.class),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字符
|
||||||
|
*/
|
||||||
|
CHAR(RandomGenerator.class);
|
||||||
|
|
||||||
|
private final Class<? extends CodeGenerator> clazz;
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package org.asinkj.auth.form;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.Email;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import org.asinkj.common.core.domain.model.LoginBody;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 邮件登录对象
|
||||||
|
*
|
||||||
|
* @author Shuo Hu
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class EmailLoginBody extends LoginBody {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 邮箱
|
||||||
|
*/
|
||||||
|
@NotBlank(message = "{user.email.not.blank}")
|
||||||
|
@Email(message = "{user.email.not.valid}")
|
||||||
|
private String email;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 邮箱code
|
||||||
|
*/
|
||||||
|
@NotBlank(message = "{email.code.not.blank}")
|
||||||
|
private String emailCode;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
package org.asinkj.auth.form;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import org.asinkj.common.core.domain.model.LoginBody;
|
||||||
|
import org.hibernate.validator.constraints.Length;
|
||||||
|
|
||||||
|
import static org.asinkj.common.core.constant.UserConstants.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 密码登录对象
|
||||||
|
*
|
||||||
|
* @author Shuo Hu
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class PasswordLoginBody extends LoginBody {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户名
|
||||||
|
*/
|
||||||
|
@NotBlank(message = "{user.username.not.blank}")
|
||||||
|
@Length(min = USERNAME_MIN_LENGTH, max = USERNAME_MAX_LENGTH, message = "{user.username.length.valid}")
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户密码
|
||||||
|
*/
|
||||||
|
@NotBlank(message = "{user.password.not.blank}")
|
||||||
|
@Length(min = PASSWORD_MIN_LENGTH, max = PASSWORD_MAX_LENGTH, message = "{user.password.length.valid}")
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
package org.asinkj.auth.form;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import org.asinkj.common.core.domain.model.LoginBody;
|
||||||
|
import org.hibernate.validator.constraints.Length;
|
||||||
|
|
||||||
|
import static org.asinkj.common.core.constant.UserConstants.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户注册对象
|
||||||
|
*
|
||||||
|
* @author Shuo Hu
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class RegisterBody extends LoginBody {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户名
|
||||||
|
*/
|
||||||
|
@NotBlank(message = "{user.username.not.blank}")
|
||||||
|
@Length(min = USERNAME_MIN_LENGTH, max = USERNAME_MAX_LENGTH, message = "{user.username.length.valid}")
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户密码
|
||||||
|
*/
|
||||||
|
@NotBlank(message = "{user.password.not.blank}")
|
||||||
|
@Length(min = PASSWORD_MIN_LENGTH, max = PASSWORD_MAX_LENGTH, message = "{user.password.length.valid}")
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户类型
|
||||||
|
*/
|
||||||
|
private String userType;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
package org.asinkj.auth.form;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import org.asinkj.common.core.domain.model.LoginBody;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 短信登录对象
|
||||||
|
*
|
||||||
|
* @author Shuo Hu
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class SmsLoginBody extends LoginBody {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 手机号
|
||||||
|
*/
|
||||||
|
@NotBlank(message = "{user.phonenumber.not.blank}")
|
||||||
|
private String phonenumber;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 短信code
|
||||||
|
*/
|
||||||
|
@NotBlank(message = "{sms.code.not.blank}")
|
||||||
|
private String smsCode;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
package org.asinkj.auth.form;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import org.asinkj.common.core.domain.model.LoginBody;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 三方登录对象
|
||||||
|
*
|
||||||
|
* @author Shuo Hu
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class SocialLoginBody extends LoginBody {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 第三方登录平台
|
||||||
|
*/
|
||||||
|
@NotBlank(message = "{social.source.not.blank}")
|
||||||
|
private String source;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 第三方登录code
|
||||||
|
*/
|
||||||
|
@NotBlank(message = "{social.code.not.blank}")
|
||||||
|
private String socialCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 第三方登录socialState
|
||||||
|
*/
|
||||||
|
@NotBlank(message = "{social.state.not.blank}")
|
||||||
|
private String socialState;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
package org.asinkj.auth.form;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import org.asinkj.common.core.domain.model.LoginBody;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 三方登录对象
|
||||||
|
*
|
||||||
|
* @author Shuo Hu
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class XcxLoginBody extends LoginBody {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 小程序id(多个小程序时使用)
|
||||||
|
*/
|
||||||
|
private String appid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 小程序code
|
||||||
|
*/
|
||||||
|
@NotBlank(message = "{xcx.code.not.blank}")
|
||||||
|
private String xcxCode;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,170 @@
|
|||||||
|
package org.asinkj.auth.listener;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.config.SaTokenConfig;
|
||||||
|
import cn.dev33.satoken.listener.SaTokenListener;
|
||||||
|
import cn.dev33.satoken.stp.SaLoginModel;
|
||||||
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
|
import cn.hutool.core.convert.Convert;
|
||||||
|
import cn.hutool.http.useragent.UserAgent;
|
||||||
|
import cn.hutool.http.useragent.UserAgentUtil;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.dubbo.config.annotation.DubboReference;
|
||||||
|
import org.asinkj.common.core.constant.CacheConstants;
|
||||||
|
import org.asinkj.common.core.constant.Constants;
|
||||||
|
import org.asinkj.common.core.utils.MessageUtils;
|
||||||
|
import org.asinkj.common.core.utils.ServletUtils;
|
||||||
|
import org.asinkj.common.core.utils.SpringUtils;
|
||||||
|
import org.asinkj.common.core.utils.ip.AddressUtils;
|
||||||
|
import org.asinkj.common.log.event.LogininforEvent;
|
||||||
|
import org.asinkj.common.redis.utils.RedisUtils;
|
||||||
|
import org.asinkj.common.satoken.utils.LoginHelper;
|
||||||
|
import org.asinkj.common.tenant.helper.TenantHelper;
|
||||||
|
import org.asinkj.resource.api.RemoteMessageService;
|
||||||
|
import org.asinkj.system.api.RemoteUserService;
|
||||||
|
import org.asinkj.system.api.domain.SysUserOnline;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户行为 侦听器的实现
|
||||||
|
*
|
||||||
|
* @author Shuo Hu
|
||||||
|
*/
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@Component
|
||||||
|
@Slf4j
|
||||||
|
public class UserActionListener implements SaTokenListener {
|
||||||
|
|
||||||
|
private final SaTokenConfig tokenConfig;
|
||||||
|
@DubboReference
|
||||||
|
private RemoteUserService remoteUserService;
|
||||||
|
@DubboReference
|
||||||
|
private RemoteMessageService remoteMessageService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 每次登录时触发
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void doLogin(String loginType, Object loginId, String tokenValue, SaLoginModel loginModel) {
|
||||||
|
UserAgent userAgent = UserAgentUtil.parse(ServletUtils.getRequest().getHeader("User-Agent"));
|
||||||
|
String ip = ServletUtils.getClientIP();
|
||||||
|
SysUserOnline userOnline = new SysUserOnline();
|
||||||
|
userOnline.setIpaddr(ip);
|
||||||
|
userOnline.setLoginLocation(AddressUtils.getRealAddressByIP(ip));
|
||||||
|
userOnline.setBrowser(userAgent.getBrowser().getName());
|
||||||
|
userOnline.setOs(userAgent.getOs().getName());
|
||||||
|
userOnline.setLoginTime(System.currentTimeMillis());
|
||||||
|
userOnline.setTokenId(tokenValue);
|
||||||
|
String username = (String) loginModel.getExtra(LoginHelper.USER_NAME_KEY);
|
||||||
|
String tenantId = (String) loginModel.getExtra(LoginHelper.TENANT_KEY);
|
||||||
|
userOnline.setUserName(username);
|
||||||
|
userOnline.setClientKey((String) loginModel.getExtra(LoginHelper.CLIENT_KEY));
|
||||||
|
userOnline.setDeviceType(loginModel.getDevice());
|
||||||
|
userOnline.setDeptName((String) loginModel.getExtra(LoginHelper.DEPT_NAME_KEY));
|
||||||
|
TenantHelper.dynamic(tenantId, () -> {
|
||||||
|
if (tokenConfig.getTimeout() == -1) {
|
||||||
|
RedisUtils.setCacheObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue, userOnline);
|
||||||
|
} else {
|
||||||
|
RedisUtils.setCacheObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue, userOnline, Duration.ofSeconds(tokenConfig.getTimeout()));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// 记录登录日志
|
||||||
|
LogininforEvent logininforEvent = new LogininforEvent();
|
||||||
|
logininforEvent.setTenantId(tenantId);
|
||||||
|
logininforEvent.setUsername(username);
|
||||||
|
logininforEvent.setStatus(Constants.LOGIN_SUCCESS);
|
||||||
|
logininforEvent.setMessage(MessageUtils.message("user.login.success"));
|
||||||
|
SpringUtils.context().publishEvent(logininforEvent);
|
||||||
|
// 更新登录信息
|
||||||
|
remoteUserService.recordLoginInfo((Long) loginModel.getExtra(LoginHelper.USER_KEY), ip);
|
||||||
|
log.info("user doLogin, useId:{}, token:{}", loginId, tokenValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 每次注销时触发
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void doLogout(String loginType, Object loginId, String tokenValue) {
|
||||||
|
String tenantId = Convert.toStr(StpUtil.getExtra(tokenValue, LoginHelper.TENANT_KEY));
|
||||||
|
TenantHelper.dynamic(tenantId, () -> {
|
||||||
|
RedisUtils.deleteObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue);
|
||||||
|
});
|
||||||
|
log.info("user doLogout, useId:{}, token:{}", loginId, tokenValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 每次被踢下线时触发
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void doKickout(String loginType, Object loginId, String tokenValue) {
|
||||||
|
String tenantId = Convert.toStr(StpUtil.getExtra(tokenValue, LoginHelper.TENANT_KEY));
|
||||||
|
TenantHelper.dynamic(tenantId, () -> {
|
||||||
|
RedisUtils.deleteObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue);
|
||||||
|
});
|
||||||
|
log.info("user doLogoutByLoginId, useId:{}, token:{}", loginId, tokenValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 每次被顶下线时触发
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void doReplaced(String loginType, Object loginId, String tokenValue) {
|
||||||
|
String tenantId = Convert.toStr(StpUtil.getExtra(tokenValue, LoginHelper.TENANT_KEY));
|
||||||
|
TenantHelper.dynamic(tenantId, () -> {
|
||||||
|
RedisUtils.deleteObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue);
|
||||||
|
});
|
||||||
|
log.info("user doReplaced, useId:{}, token:{}", loginId, tokenValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 每次被封禁时触发
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void doDisable(String loginType, Object loginId, String service, int level, long disableTime) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 每次被解封时触发
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void doUntieDisable(String loginType, Object loginId, String service) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 每次打开二级认证时触发
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void doOpenSafe(String loginType, String tokenValue, String service, long safeTime) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 每次创建Session时触发
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void doCloseSafe(String loginType, String tokenValue, String service) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 每次创建Session时触发
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void doCreateSession(String id) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 每次注销Session时触发
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void doLogoutSession(String id) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 每次Token续期时触发
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void doRenewTimeout(String tokenValue, Object loginId, long timeout) {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
package org.asinkj.auth.properties;
|
||||||
|
|
||||||
|
import org.asinkj.auth.enums.CaptchaCategory;
|
||||||
|
import org.asinkj.auth.enums.CaptchaType;
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.cloud.context.config.annotation.RefreshScope;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证码配置
|
||||||
|
*
|
||||||
|
* @author asinkj
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Configuration
|
||||||
|
@RefreshScope
|
||||||
|
@ConfigurationProperties(prefix = "security.captcha")
|
||||||
|
public class CaptchaProperties {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证码类型
|
||||||
|
*/
|
||||||
|
private CaptchaType type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证码类别
|
||||||
|
*/
|
||||||
|
private CaptchaCategory category;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数字验证码位数
|
||||||
|
*/
|
||||||
|
private Integer numberLength;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字符验证码长度
|
||||||
|
*/
|
||||||
|
private Integer charLength;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证码开关
|
||||||
|
*/
|
||||||
|
private Boolean enabled;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
package org.asinkj.auth.properties;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.cloud.context.config.annotation.RefreshScope;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户密码配置
|
||||||
|
*
|
||||||
|
* @author Shuo Hu
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Configuration
|
||||||
|
@RefreshScope
|
||||||
|
@ConfigurationProperties(prefix = "user.password")
|
||||||
|
public class UserPasswordProperties {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 密码最大错误次数
|
||||||
|
*/
|
||||||
|
private Integer maxRetryCount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 密码锁定时间(默认10分钟)
|
||||||
|
*/
|
||||||
|
private Integer lockTime;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
package org.asinkj.auth.service;
|
||||||
|
|
||||||
|
import org.asinkj.auth.domain.vo.LoginVo;
|
||||||
|
import org.asinkj.common.core.exception.ServiceException;
|
||||||
|
import org.asinkj.common.core.utils.SpringUtils;
|
||||||
|
import org.asinkj.system.api.domain.vo.RemoteClientVo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 授权策略
|
||||||
|
*
|
||||||
|
* @author Michelle.Chung
|
||||||
|
*/
|
||||||
|
public interface IAuthStrategy {
|
||||||
|
|
||||||
|
String BASE_NAME = "AuthStrategy";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录
|
||||||
|
*
|
||||||
|
* @param body 登录对象
|
||||||
|
* @param client 授权管理视图对象
|
||||||
|
* @param grantType 授权类型
|
||||||
|
* @return 登录验证信息
|
||||||
|
*/
|
||||||
|
static LoginVo login(String body, RemoteClientVo client, String grantType) {
|
||||||
|
// 授权类型和客户端id
|
||||||
|
String beanName = grantType + BASE_NAME;
|
||||||
|
if (!SpringUtils.containsBean(beanName)) {
|
||||||
|
throw new ServiceException("授权类型不正确!");
|
||||||
|
}
|
||||||
|
IAuthStrategy instance = SpringUtils.getBean(beanName);
|
||||||
|
return instance.login(body, client);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录
|
||||||
|
*
|
||||||
|
* @param body 登录对象
|
||||||
|
* @param client 授权管理视图对象
|
||||||
|
* @return 登录验证信息
|
||||||
|
*/
|
||||||
|
LoginVo login(String body, RemoteClientVo client);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,269 @@
|
|||||||
|
package org.asinkj.auth.service;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.exception.NotLoginException;
|
||||||
|
import cn.dev33.satoken.secure.BCrypt;
|
||||||
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
|
import com.baomidou.lock.annotation.Lock4j;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import me.zhyd.oauth.model.AuthUser;
|
||||||
|
import org.apache.dubbo.config.annotation.DubboReference;
|
||||||
|
import org.asinkj.auth.form.RegisterBody;
|
||||||
|
import org.asinkj.auth.properties.CaptchaProperties;
|
||||||
|
import org.asinkj.auth.properties.UserPasswordProperties;
|
||||||
|
import org.asinkj.common.core.constant.CacheConstants;
|
||||||
|
import org.asinkj.common.core.constant.Constants;
|
||||||
|
import org.asinkj.common.core.constant.GlobalConstants;
|
||||||
|
import org.asinkj.common.core.constant.TenantConstants;
|
||||||
|
import org.asinkj.common.core.enums.LoginType;
|
||||||
|
import org.asinkj.common.core.enums.TenantStatus;
|
||||||
|
import org.asinkj.common.core.enums.UserType;
|
||||||
|
import org.asinkj.common.core.exception.ServiceException;
|
||||||
|
import org.asinkj.common.core.exception.user.CaptchaException;
|
||||||
|
import org.asinkj.common.core.exception.user.CaptchaExpireException;
|
||||||
|
import org.asinkj.common.core.exception.user.UserException;
|
||||||
|
import org.asinkj.common.core.utils.MessageUtils;
|
||||||
|
import org.asinkj.common.core.utils.SpringUtils;
|
||||||
|
import org.asinkj.common.core.utils.StringUtils;
|
||||||
|
import org.asinkj.common.log.event.LogininforEvent;
|
||||||
|
import org.asinkj.common.redis.utils.RedisUtils;
|
||||||
|
import org.asinkj.common.satoken.utils.LoginHelper;
|
||||||
|
import org.asinkj.common.tenant.exception.TenantException;
|
||||||
|
import org.asinkj.common.tenant.helper.TenantHelper;
|
||||||
|
import org.asinkj.system.api.RemoteSocialService;
|
||||||
|
import org.asinkj.system.api.RemoteTenantService;
|
||||||
|
import org.asinkj.system.api.RemoteUserService;
|
||||||
|
import org.asinkj.system.api.domain.bo.RemoteSocialBo;
|
||||||
|
import org.asinkj.system.api.domain.bo.RemoteUserBo;
|
||||||
|
import org.asinkj.system.api.domain.vo.RemoteSocialVo;
|
||||||
|
import org.asinkj.system.api.domain.vo.RemoteTenantVo;
|
||||||
|
import org.asinkj.system.api.model.LoginUser;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录校验方法
|
||||||
|
*
|
||||||
|
* @author asinkj
|
||||||
|
*/
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@Service
|
||||||
|
@Slf4j
|
||||||
|
public class SysLoginService {
|
||||||
|
|
||||||
|
@DubboReference
|
||||||
|
private RemoteUserService remoteUserService;
|
||||||
|
@DubboReference
|
||||||
|
private RemoteTenantService remoteTenantService;
|
||||||
|
@DubboReference
|
||||||
|
private RemoteSocialService remoteSocialService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UserPasswordProperties userPasswordProperties;
|
||||||
|
@Autowired
|
||||||
|
private final CaptchaProperties captchaProperties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 绑定第三方用户
|
||||||
|
*
|
||||||
|
* @param authUserData 授权响应实体
|
||||||
|
*/
|
||||||
|
@Lock4j
|
||||||
|
public void socialRegister(AuthUser authUserData) {
|
||||||
|
String authId = authUserData.getSource() + authUserData.getUuid();
|
||||||
|
// 第三方用户信息
|
||||||
|
RemoteSocialBo bo = BeanUtil.toBean(authUserData, RemoteSocialBo.class);
|
||||||
|
BeanUtil.copyProperties(authUserData.getToken(), bo);
|
||||||
|
Long userId = LoginHelper.getUserId();
|
||||||
|
bo.setUserId(userId);
|
||||||
|
bo.setAuthId(authId);
|
||||||
|
bo.setOpenId(authUserData.getUuid());
|
||||||
|
bo.setUserName(authUserData.getUsername());
|
||||||
|
bo.setNickName(authUserData.getNickname());
|
||||||
|
List<RemoteSocialVo> checkList = remoteSocialService.selectByAuthId(authId);
|
||||||
|
if (CollUtil.isNotEmpty(checkList)) {
|
||||||
|
throw new ServiceException("此三方账号已经被绑定!");
|
||||||
|
}
|
||||||
|
// 查询是否已经绑定用户
|
||||||
|
RemoteSocialBo params = new RemoteSocialBo();
|
||||||
|
params.setUserId(userId);
|
||||||
|
params.setSource(bo.getSource());
|
||||||
|
List<RemoteSocialVo> list = remoteSocialService.queryList(params);
|
||||||
|
if (CollUtil.isEmpty(list)) {
|
||||||
|
// 没有绑定用户, 新增用户信息
|
||||||
|
remoteSocialService.insertByBo(bo);
|
||||||
|
} else {
|
||||||
|
// 更新用户信息
|
||||||
|
bo.setId(list.get(0).getId());
|
||||||
|
remoteSocialService.updateByBo(bo);
|
||||||
|
// 如果要绑定的平台账号已经被绑定过了 是否抛异常自行决断
|
||||||
|
// throw new ServiceException("此平台账号已经被绑定!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 退出登录
|
||||||
|
*/
|
||||||
|
public void logout() {
|
||||||
|
try {
|
||||||
|
LoginUser loginUser = LoginHelper.getLoginUser();
|
||||||
|
if (ObjectUtil.isNull(loginUser)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (TenantHelper.isEnable() && LoginHelper.isSuperAdmin()) {
|
||||||
|
// 超级管理员 登出清除动态租户
|
||||||
|
TenantHelper.clearDynamic();
|
||||||
|
}
|
||||||
|
recordLogininfor(loginUser.getTenantId(), loginUser.getUsername(), Constants.LOGOUT, MessageUtils.message("user.logout.success"));
|
||||||
|
} catch (NotLoginException ignored) {
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
StpUtil.logout();
|
||||||
|
} catch (NotLoginException ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注册
|
||||||
|
*/
|
||||||
|
public void register(RegisterBody registerBody) {
|
||||||
|
String tenantId = registerBody.getTenantId();
|
||||||
|
String username = registerBody.getUsername();
|
||||||
|
String password = registerBody.getPassword();
|
||||||
|
// 校验用户类型是否存在
|
||||||
|
String userType = UserType.getUserType(registerBody.getUserType()).getUserType();
|
||||||
|
|
||||||
|
boolean captchaEnabled = captchaProperties.getEnabled();
|
||||||
|
// 验证码开关
|
||||||
|
if (captchaEnabled) {
|
||||||
|
validateCaptcha(tenantId, username, registerBody.getCode(), registerBody.getUuid());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 注册用户信息
|
||||||
|
RemoteUserBo remoteUserBo = new RemoteUserBo();
|
||||||
|
remoteUserBo.setTenantId(tenantId);
|
||||||
|
remoteUserBo.setUserName(username);
|
||||||
|
remoteUserBo.setNickName(username);
|
||||||
|
remoteUserBo.setPassword(BCrypt.hashpw(password));
|
||||||
|
remoteUserBo.setUserType(userType);
|
||||||
|
|
||||||
|
boolean regFlag = remoteUserService.registerUserInfo(remoteUserBo);
|
||||||
|
if (!regFlag) {
|
||||||
|
throw new UserException("user.register.error");
|
||||||
|
}
|
||||||
|
recordLogininfor(tenantId, username, Constants.REGISTER, MessageUtils.message("user.register.success"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验验证码
|
||||||
|
*
|
||||||
|
* @param username 用户名
|
||||||
|
* @param code 验证码
|
||||||
|
* @param uuid 唯一标识
|
||||||
|
*/
|
||||||
|
public void validateCaptcha(String tenantId, String username, String code, String uuid) {
|
||||||
|
String verifyKey = GlobalConstants.CAPTCHA_CODE_KEY + StringUtils.blankToDefault(uuid, "");
|
||||||
|
String captcha = RedisUtils.getCacheObject(verifyKey);
|
||||||
|
RedisUtils.deleteObject(verifyKey);
|
||||||
|
if (captcha == null) {
|
||||||
|
recordLogininfor(tenantId, username, Constants.REGISTER, MessageUtils.message("user.jcaptcha.expire"));
|
||||||
|
throw new CaptchaExpireException();
|
||||||
|
}
|
||||||
|
if (!code.equalsIgnoreCase(captcha)) {
|
||||||
|
recordLogininfor(tenantId, username, Constants.REGISTER, MessageUtils.message("user.jcaptcha.error"));
|
||||||
|
throw new CaptchaException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 记录登录信息
|
||||||
|
*
|
||||||
|
* @param username 用户名
|
||||||
|
* @param status 状态
|
||||||
|
* @param message 消息内容
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public void recordLogininfor(String tenantId, String username, String status, String message) {
|
||||||
|
// 封装对象
|
||||||
|
LogininforEvent logininforEvent = new LogininforEvent();
|
||||||
|
logininforEvent.setTenantId(tenantId);
|
||||||
|
logininforEvent.setUsername(username);
|
||||||
|
logininforEvent.setStatus(status);
|
||||||
|
logininforEvent.setMessage(message);
|
||||||
|
SpringUtils.context().publishEvent(logininforEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录校验
|
||||||
|
*/
|
||||||
|
public void checkLogin(LoginType loginType, String tenantId, String username, Supplier<Boolean> supplier) {
|
||||||
|
String errorKey = CacheConstants.PWD_ERR_CNT_KEY + username;
|
||||||
|
String loginFail = Constants.LOGIN_FAIL;
|
||||||
|
Integer maxRetryCount = userPasswordProperties.getMaxRetryCount();
|
||||||
|
Integer lockTime = userPasswordProperties.getLockTime();
|
||||||
|
|
||||||
|
// 获取用户登录错误次数,默认为0 (可自定义限制策略 例如: key + username + ip)
|
||||||
|
int errorNumber = ObjectUtil.defaultIfNull(RedisUtils.getCacheObject(errorKey), 0);
|
||||||
|
// 锁定时间内登录 则踢出
|
||||||
|
if (errorNumber >= maxRetryCount) {
|
||||||
|
recordLogininfor(tenantId, username, loginFail, MessageUtils.message(loginType.getRetryLimitExceed(), maxRetryCount, lockTime));
|
||||||
|
throw new UserException(loginType.getRetryLimitExceed(), maxRetryCount, lockTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (supplier.get()) {
|
||||||
|
// 错误次数递增
|
||||||
|
errorNumber++;
|
||||||
|
RedisUtils.setCacheObject(errorKey, errorNumber, Duration.ofMinutes(lockTime));
|
||||||
|
// 达到规定错误次数 则锁定登录
|
||||||
|
if (errorNumber >= maxRetryCount) {
|
||||||
|
recordLogininfor(tenantId, username, loginFail, MessageUtils.message(loginType.getRetryLimitExceed(), maxRetryCount, lockTime));
|
||||||
|
throw new UserException(loginType.getRetryLimitExceed(), maxRetryCount, lockTime);
|
||||||
|
} else {
|
||||||
|
// 未达到规定错误次数
|
||||||
|
recordLogininfor(tenantId, username, loginFail, MessageUtils.message(loginType.getRetryLimitCount(), errorNumber));
|
||||||
|
throw new UserException(loginType.getRetryLimitCount(), errorNumber);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 登录成功 清空错误次数
|
||||||
|
RedisUtils.deleteObject(errorKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验租户
|
||||||
|
*
|
||||||
|
* @param tenantId 租户ID
|
||||||
|
*/
|
||||||
|
public void checkTenant(String tenantId) {
|
||||||
|
if (!TenantHelper.isEnable()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (TenantConstants.DEFAULT_TENANT_ID.equals(tenantId)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (StringUtils.isBlank(tenantId)) {
|
||||||
|
throw new TenantException("tenant.number.not.blank");
|
||||||
|
}
|
||||||
|
RemoteTenantVo tenant = remoteTenantService.queryByTenantId(tenantId);
|
||||||
|
if (ObjectUtil.isNull(tenant)) {
|
||||||
|
log.info("登录租户:{} 不存在.", tenantId);
|
||||||
|
throw new TenantException("tenant.not.exists");
|
||||||
|
} else if (TenantStatus.DISABLE.getCode().equals(tenant.getStatus())) {
|
||||||
|
log.info("登录租户:{} 已被停用.", tenantId);
|
||||||
|
throw new TenantException("tenant.blocked");
|
||||||
|
} else if (ObjectUtil.isNotNull(tenant.getExpireTime())
|
||||||
|
&& new Date().after(tenant.getExpireTime())) {
|
||||||
|
log.info("登录租户:{} 已超过有效期.", tenantId);
|
||||||
|
throw new TenantException("tenant.expired");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,86 @@
|
|||||||
|
package org.asinkj.auth.service.impl;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.stp.SaLoginModel;
|
||||||
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.dubbo.config.annotation.DubboReference;
|
||||||
|
import org.asinkj.auth.domain.vo.LoginVo;
|
||||||
|
import org.asinkj.auth.form.EmailLoginBody;
|
||||||
|
import org.asinkj.auth.service.IAuthStrategy;
|
||||||
|
import org.asinkj.auth.service.SysLoginService;
|
||||||
|
import org.asinkj.common.core.constant.Constants;
|
||||||
|
import org.asinkj.common.core.constant.GlobalConstants;
|
||||||
|
import org.asinkj.common.core.enums.LoginType;
|
||||||
|
import org.asinkj.common.core.exception.user.CaptchaExpireException;
|
||||||
|
import org.asinkj.common.core.utils.MessageUtils;
|
||||||
|
import org.asinkj.common.core.utils.StringUtils;
|
||||||
|
import org.asinkj.common.core.utils.ValidatorUtils;
|
||||||
|
import org.asinkj.common.json.utils.JsonUtils;
|
||||||
|
import org.asinkj.common.redis.utils.RedisUtils;
|
||||||
|
import org.asinkj.common.satoken.utils.LoginHelper;
|
||||||
|
import org.asinkj.common.tenant.helper.TenantHelper;
|
||||||
|
import org.asinkj.system.api.RemoteUserService;
|
||||||
|
import org.asinkj.system.api.domain.vo.RemoteClientVo;
|
||||||
|
import org.asinkj.system.api.model.LoginUser;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 邮件认证策略
|
||||||
|
*
|
||||||
|
* @author Michelle.Chung
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service("email" + IAuthStrategy.BASE_NAME)
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class EmailAuthStrategy implements IAuthStrategy {
|
||||||
|
|
||||||
|
private final SysLoginService loginService;
|
||||||
|
|
||||||
|
@DubboReference
|
||||||
|
private RemoteUserService remoteUserService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LoginVo login(String body, RemoteClientVo client) {
|
||||||
|
EmailLoginBody loginBody = JsonUtils.parseObject(body, EmailLoginBody.class);
|
||||||
|
ValidatorUtils.validate(loginBody);
|
||||||
|
String tenantId = loginBody.getTenantId();
|
||||||
|
String email = loginBody.getEmail();
|
||||||
|
String emailCode = loginBody.getEmailCode();
|
||||||
|
LoginUser loginUser = TenantHelper.dynamic(tenantId, () -> {
|
||||||
|
LoginUser user = remoteUserService.getUserInfoByEmail(email, tenantId);
|
||||||
|
loginService.checkLogin(LoginType.EMAIL, tenantId, user.getUsername(), () -> !validateEmailCode(tenantId, email, emailCode));
|
||||||
|
return user;
|
||||||
|
});
|
||||||
|
loginUser.setClientKey(client.getClientKey());
|
||||||
|
loginUser.setDeviceType(client.getDeviceType());
|
||||||
|
SaLoginModel model = new SaLoginModel();
|
||||||
|
model.setDevice(client.getDeviceType());
|
||||||
|
// 自定义分配 不同用户体系 不同 token 授权时间 不设置默认走全局 yml 配置
|
||||||
|
// 例如: 后台用户30分钟过期 app用户1天过期
|
||||||
|
model.setTimeout(client.getTimeout());
|
||||||
|
model.setActiveTimeout(client.getActiveTimeout());
|
||||||
|
model.setExtra(LoginHelper.CLIENT_KEY, client.getClientId());
|
||||||
|
// 生成token
|
||||||
|
LoginHelper.login(loginUser, model);
|
||||||
|
|
||||||
|
LoginVo loginVo = new LoginVo();
|
||||||
|
loginVo.setAccessToken(StpUtil.getTokenValue());
|
||||||
|
loginVo.setExpireIn(StpUtil.getTokenTimeout());
|
||||||
|
loginVo.setClientId(client.getClientId());
|
||||||
|
return loginVo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验邮箱验证码
|
||||||
|
*/
|
||||||
|
private boolean validateEmailCode(String tenantId, String email, String emailCode) {
|
||||||
|
String code = RedisUtils.getCacheObject(GlobalConstants.CAPTCHA_CODE_KEY + email);
|
||||||
|
if (StringUtils.isBlank(code)) {
|
||||||
|
loginService.recordLogininfor(tenantId, email, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"));
|
||||||
|
throw new CaptchaExpireException();
|
||||||
|
}
|
||||||
|
return code.equals(emailCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,107 @@
|
|||||||
|
package org.asinkj.auth.service.impl;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.secure.BCrypt;
|
||||||
|
import cn.dev33.satoken.stp.SaLoginModel;
|
||||||
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.dubbo.config.annotation.DubboReference;
|
||||||
|
import org.asinkj.auth.domain.vo.LoginVo;
|
||||||
|
import org.asinkj.auth.form.PasswordLoginBody;
|
||||||
|
import org.asinkj.auth.properties.CaptchaProperties;
|
||||||
|
import org.asinkj.auth.service.IAuthStrategy;
|
||||||
|
import org.asinkj.auth.service.SysLoginService;
|
||||||
|
import org.asinkj.common.core.constant.Constants;
|
||||||
|
import org.asinkj.common.core.constant.GlobalConstants;
|
||||||
|
import org.asinkj.common.core.enums.LoginType;
|
||||||
|
import org.asinkj.common.core.exception.user.CaptchaException;
|
||||||
|
import org.asinkj.common.core.exception.user.CaptchaExpireException;
|
||||||
|
import org.asinkj.common.core.utils.MessageUtils;
|
||||||
|
import org.asinkj.common.core.utils.StringUtils;
|
||||||
|
import org.asinkj.common.core.utils.ValidatorUtils;
|
||||||
|
import org.asinkj.common.json.utils.JsonUtils;
|
||||||
|
import org.asinkj.common.redis.utils.RedisUtils;
|
||||||
|
import org.asinkj.common.satoken.utils.LoginHelper;
|
||||||
|
import org.asinkj.common.tenant.helper.TenantHelper;
|
||||||
|
import org.asinkj.system.api.RemoteUserService;
|
||||||
|
import org.asinkj.system.api.domain.vo.RemoteClientVo;
|
||||||
|
import org.asinkj.system.api.model.LoginUser;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 密码认证策略
|
||||||
|
*
|
||||||
|
* @author Michelle.Chung
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service("password" + IAuthStrategy.BASE_NAME)
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class PasswordAuthStrategy implements IAuthStrategy {
|
||||||
|
|
||||||
|
private final CaptchaProperties captchaProperties;
|
||||||
|
|
||||||
|
private final SysLoginService loginService;
|
||||||
|
|
||||||
|
@DubboReference
|
||||||
|
private RemoteUserService remoteUserService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LoginVo login(String body, RemoteClientVo client) {
|
||||||
|
PasswordLoginBody loginBody = JsonUtils.parseObject(body, PasswordLoginBody.class);
|
||||||
|
ValidatorUtils.validate(loginBody);
|
||||||
|
String tenantId = loginBody.getTenantId();
|
||||||
|
String username = loginBody.getUsername();
|
||||||
|
String password = loginBody.getPassword();
|
||||||
|
String code = loginBody.getCode();
|
||||||
|
String uuid = loginBody.getUuid();
|
||||||
|
|
||||||
|
// 验证码开关
|
||||||
|
if (captchaProperties.getEnabled()) {
|
||||||
|
validateCaptcha(tenantId, username, code, uuid);
|
||||||
|
}
|
||||||
|
LoginUser loginUser = TenantHelper.dynamic(tenantId, () -> {
|
||||||
|
LoginUser user = remoteUserService.getUserInfo(username, tenantId);
|
||||||
|
loginService.checkLogin(LoginType.PASSWORD, tenantId, username, () -> !BCrypt.checkpw(password, user.getPassword()));
|
||||||
|
return user;
|
||||||
|
});
|
||||||
|
loginUser.setClientKey(client.getClientKey());
|
||||||
|
loginUser.setDeviceType(client.getDeviceType());
|
||||||
|
SaLoginModel model = new SaLoginModel();
|
||||||
|
model.setDevice(client.getDeviceType());
|
||||||
|
// 自定义分配 不同用户体系 不同 token 授权时间 不设置默认走全局 yml 配置
|
||||||
|
// 例如: 后台用户30分钟过期 app用户1天过期
|
||||||
|
model.setTimeout(client.getTimeout());
|
||||||
|
model.setActiveTimeout(client.getActiveTimeout());
|
||||||
|
model.setExtra(LoginHelper.CLIENT_KEY, client.getClientId());
|
||||||
|
// 生成token
|
||||||
|
LoginHelper.login(loginUser, model);
|
||||||
|
|
||||||
|
LoginVo loginVo = new LoginVo();
|
||||||
|
loginVo.setAccessToken(StpUtil.getTokenValue());
|
||||||
|
loginVo.setExpireIn(StpUtil.getTokenTimeout());
|
||||||
|
loginVo.setClientId(client.getClientId());
|
||||||
|
return loginVo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验验证码
|
||||||
|
*
|
||||||
|
* @param username 用户名
|
||||||
|
* @param code 验证码
|
||||||
|
* @param uuid 唯一标识
|
||||||
|
*/
|
||||||
|
private void validateCaptcha(String tenantId, String username, String code, String uuid) {
|
||||||
|
String verifyKey = GlobalConstants.CAPTCHA_CODE_KEY + StringUtils.blankToDefault(uuid, "");
|
||||||
|
String captcha = RedisUtils.getCacheObject(verifyKey);
|
||||||
|
RedisUtils.deleteObject(verifyKey);
|
||||||
|
if (captcha == null) {
|
||||||
|
loginService.recordLogininfor(tenantId, username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"));
|
||||||
|
throw new CaptchaExpireException();
|
||||||
|
}
|
||||||
|
if (!code.equalsIgnoreCase(captcha)) {
|
||||||
|
loginService.recordLogininfor(tenantId, username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error"));
|
||||||
|
throw new CaptchaException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,86 @@
|
|||||||
|
package org.asinkj.auth.service.impl;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.stp.SaLoginModel;
|
||||||
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.dubbo.config.annotation.DubboReference;
|
||||||
|
import org.asinkj.auth.domain.vo.LoginVo;
|
||||||
|
import org.asinkj.auth.form.SmsLoginBody;
|
||||||
|
import org.asinkj.auth.service.IAuthStrategy;
|
||||||
|
import org.asinkj.auth.service.SysLoginService;
|
||||||
|
import org.asinkj.common.core.constant.Constants;
|
||||||
|
import org.asinkj.common.core.constant.GlobalConstants;
|
||||||
|
import org.asinkj.common.core.enums.LoginType;
|
||||||
|
import org.asinkj.common.core.exception.user.CaptchaExpireException;
|
||||||
|
import org.asinkj.common.core.utils.MessageUtils;
|
||||||
|
import org.asinkj.common.core.utils.StringUtils;
|
||||||
|
import org.asinkj.common.core.utils.ValidatorUtils;
|
||||||
|
import org.asinkj.common.json.utils.JsonUtils;
|
||||||
|
import org.asinkj.common.redis.utils.RedisUtils;
|
||||||
|
import org.asinkj.common.satoken.utils.LoginHelper;
|
||||||
|
import org.asinkj.common.tenant.helper.TenantHelper;
|
||||||
|
import org.asinkj.system.api.RemoteUserService;
|
||||||
|
import org.asinkj.system.api.domain.vo.RemoteClientVo;
|
||||||
|
import org.asinkj.system.api.model.LoginUser;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 短信认证策略
|
||||||
|
*
|
||||||
|
* @author Michelle.Chung
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service("sms" + IAuthStrategy.BASE_NAME)
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class SmsAuthStrategy implements IAuthStrategy {
|
||||||
|
|
||||||
|
private final SysLoginService loginService;
|
||||||
|
|
||||||
|
@DubboReference
|
||||||
|
private RemoteUserService remoteUserService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LoginVo login(String body, RemoteClientVo client) {
|
||||||
|
SmsLoginBody loginBody = JsonUtils.parseObject(body, SmsLoginBody.class);
|
||||||
|
ValidatorUtils.validate(loginBody);
|
||||||
|
String tenantId = loginBody.getTenantId();
|
||||||
|
String phonenumber = loginBody.getPhonenumber();
|
||||||
|
String smsCode = loginBody.getSmsCode();
|
||||||
|
LoginUser loginUser = TenantHelper.dynamic(tenantId, () -> {
|
||||||
|
LoginUser user = remoteUserService.getUserInfoByPhonenumber(phonenumber, tenantId);
|
||||||
|
loginService.checkLogin(LoginType.SMS, tenantId, user.getUsername(), () -> !validateSmsCode(tenantId, phonenumber, smsCode));
|
||||||
|
return user;
|
||||||
|
});
|
||||||
|
loginUser.setClientKey(client.getClientKey());
|
||||||
|
loginUser.setDeviceType(client.getDeviceType());
|
||||||
|
SaLoginModel model = new SaLoginModel();
|
||||||
|
model.setDevice(client.getDeviceType());
|
||||||
|
// 自定义分配 不同用户体系 不同 token 授权时间 不设置默认走全局 yml 配置
|
||||||
|
// 例如: 后台用户30分钟过期 app用户1天过期
|
||||||
|
model.setTimeout(client.getTimeout());
|
||||||
|
model.setActiveTimeout(client.getActiveTimeout());
|
||||||
|
model.setExtra(LoginHelper.CLIENT_KEY, client.getClientId());
|
||||||
|
// 生成token
|
||||||
|
LoginHelper.login(loginUser, model);
|
||||||
|
|
||||||
|
LoginVo loginVo = new LoginVo();
|
||||||
|
loginVo.setAccessToken(StpUtil.getTokenValue());
|
||||||
|
loginVo.setExpireIn(StpUtil.getTokenTimeout());
|
||||||
|
loginVo.setClientId(client.getClientId());
|
||||||
|
return loginVo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验短信验证码
|
||||||
|
*/
|
||||||
|
private boolean validateSmsCode(String tenantId, String phonenumber, String smsCode) {
|
||||||
|
String code = RedisUtils.getCacheObject(GlobalConstants.CAPTCHA_CODE_KEY + phonenumber);
|
||||||
|
if (StringUtils.isBlank(code)) {
|
||||||
|
loginService.recordLogininfor(tenantId, phonenumber, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"));
|
||||||
|
throw new CaptchaExpireException();
|
||||||
|
}
|
||||||
|
return code.equals(smsCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,114 @@
|
|||||||
|
package org.asinkj.auth.service.impl;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.stp.SaLoginModel;
|
||||||
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import cn.hutool.core.map.MapUtil;
|
||||||
|
import cn.hutool.http.HttpUtil;
|
||||||
|
import cn.hutool.http.Method;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import me.zhyd.oauth.model.AuthResponse;
|
||||||
|
import me.zhyd.oauth.model.AuthUser;
|
||||||
|
import org.apache.dubbo.config.annotation.DubboReference;
|
||||||
|
import org.asinkj.auth.domain.vo.LoginVo;
|
||||||
|
import org.asinkj.auth.form.SocialLoginBody;
|
||||||
|
import org.asinkj.auth.service.IAuthStrategy;
|
||||||
|
import org.asinkj.common.core.exception.ServiceException;
|
||||||
|
import org.asinkj.common.core.utils.StreamUtils;
|
||||||
|
import org.asinkj.common.core.utils.ValidatorUtils;
|
||||||
|
import org.asinkj.common.json.utils.JsonUtils;
|
||||||
|
import org.asinkj.common.satoken.utils.LoginHelper;
|
||||||
|
import org.asinkj.common.social.config.properties.SocialProperties;
|
||||||
|
import org.asinkj.common.social.utils.SocialUtils;
|
||||||
|
import org.asinkj.common.tenant.helper.TenantHelper;
|
||||||
|
import org.asinkj.system.api.RemoteSocialService;
|
||||||
|
import org.asinkj.system.api.RemoteUserService;
|
||||||
|
import org.asinkj.system.api.domain.vo.RemoteClientVo;
|
||||||
|
import org.asinkj.system.api.domain.vo.RemoteSocialVo;
|
||||||
|
import org.asinkj.system.api.model.LoginUser;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 第三方授权策略
|
||||||
|
*
|
||||||
|
* @author thiszhc is 三三
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service("social" + IAuthStrategy.BASE_NAME)
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class SocialAuthStrategy implements IAuthStrategy {
|
||||||
|
|
||||||
|
private final SocialProperties socialProperties;
|
||||||
|
|
||||||
|
@DubboReference
|
||||||
|
private RemoteSocialService remoteSocialService;
|
||||||
|
@DubboReference
|
||||||
|
private RemoteUserService remoteUserService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录-第三方授权登录
|
||||||
|
*
|
||||||
|
* @param body 登录信息
|
||||||
|
* @param client 客户端信息
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public LoginVo login(String body, RemoteClientVo client) {
|
||||||
|
SocialLoginBody loginBody = JsonUtils.parseObject(body, SocialLoginBody.class);
|
||||||
|
ValidatorUtils.validate(loginBody);
|
||||||
|
AuthResponse<AuthUser> response = SocialUtils.loginAuth(
|
||||||
|
loginBody.getSource(), loginBody.getSocialCode(),
|
||||||
|
loginBody.getSocialState(), socialProperties);
|
||||||
|
if (!response.ok()) {
|
||||||
|
throw new ServiceException(response.getMsg());
|
||||||
|
}
|
||||||
|
AuthUser authUserData = response.getData();
|
||||||
|
if ("GITEE".equals(authUserData.getSource())) {
|
||||||
|
// 如用户使用 gitee 登录顺手 star 给作者一点支持 拒绝白嫖
|
||||||
|
HttpUtil.createRequest(Method.PUT, "https://gitee.com/api/v5/user/starred/asinkj/AsinKj-Vue-Plus")
|
||||||
|
.formStr(MapUtil.of("access_token", authUserData.getToken().getAccessToken()))
|
||||||
|
.executeAsync();
|
||||||
|
HttpUtil.createRequest(Method.PUT, "https://gitee.com/api/v5/user/starred/asinkj/AsinKj-Cloud-Plus")
|
||||||
|
.formStr(MapUtil.of("access_token", authUserData.getToken().getAccessToken()))
|
||||||
|
.executeAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<RemoteSocialVo> list = remoteSocialService.selectByAuthId(authUserData.getSource() + authUserData.getUuid());
|
||||||
|
if (CollUtil.isEmpty(list)) {
|
||||||
|
throw new ServiceException("你还没有绑定第三方账号,绑定后才可以登录!");
|
||||||
|
}
|
||||||
|
RemoteSocialVo socialVo;
|
||||||
|
if (TenantHelper.isEnable()) {
|
||||||
|
Optional<RemoteSocialVo> opt = StreamUtils.findAny(list, x -> x.getTenantId().equals(loginBody.getTenantId()));
|
||||||
|
if (opt.isEmpty()) {
|
||||||
|
throw new ServiceException("对不起,你没有权限登录当前租户!");
|
||||||
|
}
|
||||||
|
socialVo = opt.get();
|
||||||
|
} else {
|
||||||
|
socialVo = list.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
LoginUser loginUser = remoteUserService.getUserInfo(socialVo.getUserId(), socialVo.getTenantId());
|
||||||
|
loginUser.setClientKey(client.getClientKey());
|
||||||
|
loginUser.setDeviceType(client.getDeviceType());
|
||||||
|
SaLoginModel model = new SaLoginModel();
|
||||||
|
model.setDevice(client.getDeviceType());
|
||||||
|
// 自定义分配 不同用户体系 不同 token 授权时间 不设置默认走全局 yml 配置
|
||||||
|
// 例如: 后台用户30分钟过期 app用户1天过期
|
||||||
|
model.setTimeout(client.getTimeout());
|
||||||
|
model.setActiveTimeout(client.getActiveTimeout());
|
||||||
|
model.setExtra(LoginHelper.CLIENT_KEY, client.getClientId());
|
||||||
|
// 生成token
|
||||||
|
LoginHelper.login(loginUser, model);
|
||||||
|
|
||||||
|
LoginVo loginVo = new LoginVo();
|
||||||
|
loginVo.setAccessToken(StpUtil.getTokenValue());
|
||||||
|
loginVo.setExpireIn(StpUtil.getTokenTimeout());
|
||||||
|
loginVo.setClientId(client.getClientId());
|
||||||
|
return loginVo;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
package org.asinkj.auth.service.impl;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.stp.SaLoginModel;
|
||||||
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.dubbo.config.annotation.DubboReference;
|
||||||
|
import org.asinkj.auth.domain.vo.LoginVo;
|
||||||
|
import org.asinkj.auth.form.XcxLoginBody;
|
||||||
|
import org.asinkj.auth.service.IAuthStrategy;
|
||||||
|
import org.asinkj.auth.service.SysLoginService;
|
||||||
|
import org.asinkj.common.core.utils.ValidatorUtils;
|
||||||
|
import org.asinkj.common.json.utils.JsonUtils;
|
||||||
|
import org.asinkj.common.satoken.utils.LoginHelper;
|
||||||
|
import org.asinkj.system.api.RemoteUserService;
|
||||||
|
import org.asinkj.system.api.domain.vo.RemoteClientVo;
|
||||||
|
import org.asinkj.system.api.model.XcxLoginUser;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 邮件认证策略
|
||||||
|
*
|
||||||
|
* @author Michelle.Chung
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service("xcx" + IAuthStrategy.BASE_NAME)
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class XcxAuthStrategy implements IAuthStrategy {
|
||||||
|
|
||||||
|
private final SysLoginService loginService;
|
||||||
|
|
||||||
|
@DubboReference
|
||||||
|
private RemoteUserService remoteUserService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LoginVo login(String body, RemoteClientVo client) {
|
||||||
|
XcxLoginBody loginBody = JsonUtils.parseObject(body, XcxLoginBody.class);
|
||||||
|
ValidatorUtils.validate(loginBody);
|
||||||
|
// xcxCode 为 小程序调用 wx.login 授权后获取
|
||||||
|
String xcxCode = loginBody.getXcxCode();
|
||||||
|
// 多个小程序识别使用
|
||||||
|
String appid = loginBody.getAppid();
|
||||||
|
|
||||||
|
// todo 以下自行实现
|
||||||
|
// 校验 appid + appsrcret + xcxCode 调用登录凭证校验接口 获取 session_key 与 openid
|
||||||
|
String openid = "";
|
||||||
|
XcxLoginUser loginUser = remoteUserService.getUserInfoByOpenid(openid);
|
||||||
|
loginUser.setClientKey(client.getClientKey());
|
||||||
|
loginUser.setDeviceType(client.getDeviceType());
|
||||||
|
|
||||||
|
SaLoginModel model = new SaLoginModel();
|
||||||
|
model.setDevice(client.getDeviceType());
|
||||||
|
// 自定义分配 不同用户体系 不同 token 授权时间 不设置默认走全局 yml 配置
|
||||||
|
// 例如: 后台用户30分钟过期 app用户1天过期
|
||||||
|
model.setTimeout(client.getTimeout());
|
||||||
|
model.setActiveTimeout(client.getActiveTimeout());
|
||||||
|
model.setExtra(LoginHelper.CLIENT_KEY, client.getClientId());
|
||||||
|
// 生成token
|
||||||
|
LoginHelper.login(loginUser, model);
|
||||||
|
|
||||||
|
LoginVo loginVo = new LoginVo();
|
||||||
|
loginVo.setAccessToken(StpUtil.getTokenValue());
|
||||||
|
loginVo.setExpireIn(StpUtil.getTokenTimeout());
|
||||||
|
loginVo.setClientId(client.getClientId());
|
||||||
|
loginVo.setOpenid(openid);
|
||||||
|
return loginVo;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
33
asinkj-auth/src/main/resources/application.yml
Normal file
33
asinkj-auth/src/main/resources/application.yml
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
# Tomcat
|
||||||
|
server:
|
||||||
|
port: 9210
|
||||||
|
|
||||||
|
# Spring
|
||||||
|
spring:
|
||||||
|
application:
|
||||||
|
# 应用名称
|
||||||
|
name: asinkj-auth
|
||||||
|
profiles:
|
||||||
|
# 环境配置
|
||||||
|
active: @profiles.active@
|
||||||
|
|
||||||
|
--- # nacos 配置
|
||||||
|
spring:
|
||||||
|
cloud:
|
||||||
|
nacos:
|
||||||
|
# nacos 服务地址
|
||||||
|
server-addr: @nacos.server@
|
||||||
|
username: @nacos.username@
|
||||||
|
password: @nacos.password@
|
||||||
|
discovery:
|
||||||
|
# 注册组
|
||||||
|
group: @nacos.discovery.group@
|
||||||
|
namespace: ${spring.profiles.active}
|
||||||
|
config:
|
||||||
|
# 配置组
|
||||||
|
group: @nacos.config.group@
|
||||||
|
namespace: ${spring.profiles.active}
|
||||||
|
config:
|
||||||
|
import:
|
||||||
|
- optional:nacos:application-common.yml
|
||||||
|
- optional:nacos:${spring.application.name}.yml
|
8
asinkj-auth/src/main/resources/banner.txt
Normal file
8
asinkj-auth/src/main/resources/banner.txt
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
Spring Boot Version: ${spring-boot.version}
|
||||||
|
Spring Application Name: ${spring.application.name}
|
||||||
|
_ _ _ _ _
|
||||||
|
/_\ ___(_)_ __ /\ /(_) __ _ _ _| |_| |__
|
||||||
|
//_\\/ __| | '_ \ / //_/ |_____ / _` | | | | __| '_ \
|
||||||
|
/ _ \__ \ | | | / __ \| |_____| (_| | |_| | |_| | | |
|
||||||
|
\_/ \_/___/_|_| |_\/ \// | \__,_|\__,_|\__|_| |_|
|
||||||
|
|__/
|
28
asinkj-auth/src/main/resources/logback-plus.xml
Normal file
28
asinkj-auth/src/main/resources/logback-plus.xml
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<configuration scan="true" scanPeriod="60 seconds" debug="false">
|
||||||
|
<!-- 日志存放路径 -->
|
||||||
|
<property name="log.path" value="logs/${project.artifactId}"/>
|
||||||
|
<!-- 日志输出格式 -->
|
||||||
|
<property name="console.log.pattern"
|
||||||
|
value="%red(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{36}%n) - %msg%n"/>
|
||||||
|
|
||||||
|
<!-- 控制台输出 -->
|
||||||
|
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
<encoder>
|
||||||
|
<pattern>${console.log.pattern}</pattern>
|
||||||
|
<charset>utf-8</charset>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<include resource="logback-common.xml" />
|
||||||
|
|
||||||
|
<include resource="logback-logstash.xml" />
|
||||||
|
|
||||||
|
<!-- 开启 skywalking 日志收集 -->
|
||||||
|
<include resource="logback-skylog.xml" />
|
||||||
|
|
||||||
|
<!--系统操作日志-->
|
||||||
|
<root level="info">
|
||||||
|
<appender-ref ref="console"/>
|
||||||
|
</root>
|
||||||
|
</configuration>
|
182
asinkj-common/asinkj-common-alibaba-bom/pom.xml
Normal file
182
asinkj-common/asinkj-common-alibaba-bom/pom.xml
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common-alibaba-bom</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
|
||||||
|
<description>
|
||||||
|
asinkj-common-alibaba-bom alibaba依赖项
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<revision>2.2.2</revision>
|
||||||
|
<spring-cloud-alibaba.version>2023.0.1.2</spring-cloud-alibaba.version>
|
||||||
|
<sentinel.version>1.8.8</sentinel.version>
|
||||||
|
<seata.version>1.7.1</seata.version>
|
||||||
|
<nacos.client.version>2.3.3</nacos.client.version>
|
||||||
|
<dubbo.version>3.2.14</dubbo.version>
|
||||||
|
<spring.context.support.version>1.0.11</spring.context.support.version>
|
||||||
|
</properties>
|
||||||
|
<dependencyManagement>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
|
||||||
|
<version>${spring-cloud-alibaba.version}</version>
|
||||||
|
<type>pom</type>
|
||||||
|
<scope>import</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba.nacos</groupId>
|
||||||
|
<artifactId>nacos-client</artifactId>
|
||||||
|
<version>${nacos.client.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba.csp</groupId>
|
||||||
|
<artifactId>sentinel-core</artifactId>
|
||||||
|
<version>${sentinel.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba.csp</groupId>
|
||||||
|
<artifactId>sentinel-parameter-flow-control</artifactId>
|
||||||
|
<version>${sentinel.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba.csp</groupId>
|
||||||
|
<artifactId>sentinel-datasource-extension</artifactId>
|
||||||
|
<version>${sentinel.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba.csp</groupId>
|
||||||
|
<artifactId>sentinel-datasource-apollo</artifactId>
|
||||||
|
<version>${sentinel.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba.csp</groupId>
|
||||||
|
<artifactId>sentinel-datasource-zookeeper</artifactId>
|
||||||
|
<version>${sentinel.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba.csp</groupId>
|
||||||
|
<artifactId>sentinel-datasource-nacos</artifactId>
|
||||||
|
<version>${sentinel.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba.csp</groupId>
|
||||||
|
<artifactId>sentinel-datasource-redis</artifactId>
|
||||||
|
<version>${sentinel.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba.csp</groupId>
|
||||||
|
<artifactId>sentinel-datasource-consul</artifactId>
|
||||||
|
<version>${sentinel.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba.csp</groupId>
|
||||||
|
<artifactId>sentinel-web-servlet</artifactId>
|
||||||
|
<version>${sentinel.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba.csp</groupId>
|
||||||
|
<artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
|
||||||
|
<version>${sentinel.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba.csp</groupId>
|
||||||
|
<artifactId>sentinel-transport-simple-http</artifactId>
|
||||||
|
<version>${sentinel.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba.csp</groupId>
|
||||||
|
<artifactId>sentinel-annotation-aspectj</artifactId>
|
||||||
|
<version>${sentinel.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba.csp</groupId>
|
||||||
|
<artifactId>sentinel-reactor-adapter</artifactId>
|
||||||
|
<version>${sentinel.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba.csp</groupId>
|
||||||
|
<artifactId>sentinel-cluster-server-default</artifactId>
|
||||||
|
<version>${sentinel.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba.csp</groupId>
|
||||||
|
<artifactId>sentinel-cluster-client-default</artifactId>
|
||||||
|
<version>${sentinel.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba.csp</groupId>
|
||||||
|
<artifactId>sentinel-spring-webflux-adapter</artifactId>
|
||||||
|
<version>${sentinel.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba.csp</groupId>
|
||||||
|
<artifactId>sentinel-api-gateway-adapter-common</artifactId>
|
||||||
|
<version>${sentinel.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba.csp</groupId>
|
||||||
|
<artifactId>sentinel-spring-webmvc-v6x-adapter</artifactId>
|
||||||
|
<version>${sentinel.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba.csp</groupId>
|
||||||
|
<artifactId>sentinel-dubbo-adapter</artifactId>
|
||||||
|
<version>${sentinel.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba.csp</groupId>
|
||||||
|
<artifactId>sentinel-apache-dubbo-adapter</artifactId>
|
||||||
|
<version>${sentinel.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba.csp</groupId>
|
||||||
|
<artifactId>sentinel-apache-dubbo3-adapter</artifactId>
|
||||||
|
<version>${sentinel.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.seata</groupId>
|
||||||
|
<artifactId>seata-spring-boot-starter</artifactId>
|
||||||
|
<version>${seata.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Apache Dubbo 配置 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.dubbo</groupId>
|
||||||
|
<artifactId>dubbo-spring-boot-starter</artifactId>
|
||||||
|
<version>${dubbo.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.dubbo</groupId>
|
||||||
|
<artifactId>dubbo-spring-boot-actuator</artifactId>
|
||||||
|
<version>${dubbo.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.dubbo</groupId>
|
||||||
|
<artifactId>dubbo</artifactId>
|
||||||
|
<version>${dubbo.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.dubbo</groupId>
|
||||||
|
<artifactId>dubbo-metadata-report-redis</artifactId>
|
||||||
|
<version>${dubbo.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba.spring</groupId>
|
||||||
|
<artifactId>spring-context-support</artifactId>
|
||||||
|
<version>${spring.context.support.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</dependencyManagement>
|
||||||
|
</project>
|
262
asinkj-common/asinkj-common-bom/pom.xml
Normal file
262
asinkj-common/asinkj-common-bom/pom.xml
Normal file
@ -0,0 +1,262 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common-bom</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
|
||||||
|
<description>
|
||||||
|
asinkj-common-bom common依赖项
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<revision>2.2.2</revision>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencyManagement>
|
||||||
|
<dependencies>
|
||||||
|
<!-- 核心模块 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common-core</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 接口模块 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common-doc</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 安全模块 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common-security</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 权限认证服务 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common-satoken</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 日志记录 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common-log</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 字典 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common-dict</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- excel -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common-excel</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 缓存服务 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common-redis</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- web服务 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common-web</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 数据库服务 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common-mybatis</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 定时任务 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common-job</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- RPC服务 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common-dubbo</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 分布式事务 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common-seata</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 自定义负载均衡 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common-loadbalancer</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- oss服务 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common-oss</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 限流功能 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common-ratelimiter</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 幂等功能 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common-idempotent</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 邮件模块 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common-mail</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 短信模块 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common-sms</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- logstash日志推送模块 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common-logstash</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- ES搜索引擎服务 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common-elasticsearch</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 限流模块 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common-sentinel</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- skywalking日志收集模块 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common-skylog</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- prometheus监控 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common-prometheus</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 通用翻译功能 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common-translation</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 脱敏模块 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common-sensitive</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 序列化模块 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common-json</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 数据加解密模块 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common-encrypt</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 租户模块 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common-tenant</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- websocket模块 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common-websocket</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 授权认证 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common-social</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 配置中心 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common-nacos</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 消息总线模块 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common-bus</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- sse -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common-sse</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
</dependencyManagement>
|
||||||
|
</project>
|
35
asinkj-common/asinkj-common-bus/pom.xml
Normal file
35
asinkj-common/asinkj-common-bus/pom.xml
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>asinkj-common-bus</artifactId>
|
||||||
|
|
||||||
|
<description>
|
||||||
|
asinkj-common-bus 消息总线模块
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<!-- rabbitmq -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<!-- kafka -->
|
||||||
|
<!-- <dependency>-->
|
||||||
|
<!-- <groupId>org.springframework.cloud</groupId>-->
|
||||||
|
<!-- <artifactId>spring-cloud-starter-bus-kafka</artifactId>-->
|
||||||
|
<!-- </dependency>-->
|
||||||
|
<!-- rocketmq -->
|
||||||
|
<!-- <dependency>-->
|
||||||
|
<!-- <groupId>com.alibaba.cloud</groupId>-->
|
||||||
|
<!-- <artifactId>spring-cloud-starter-bus-rocketmq</artifactId>-->
|
||||||
|
<!-- </dependency>-->
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
@ -0,0 +1,15 @@
|
|||||||
|
package org.asinkj.common.bus.config;
|
||||||
|
|
||||||
|
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||||
|
import org.springframework.cloud.bus.jackson.RemoteApplicationEventScan;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* bus 配置
|
||||||
|
*
|
||||||
|
* @author Shuo Hu
|
||||||
|
*/
|
||||||
|
@AutoConfiguration
|
||||||
|
@RemoteApplicationEventScan(basePackages = "${spring.cloud.bus.base-packages}")
|
||||||
|
public class BusCustomConfiguration {
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
org.asinkj.common.bus.config.BusCustomConfiguration
|
104
asinkj-common/asinkj-common-core/pom.xml
Normal file
104
asinkj-common/asinkj-common-core/pom.xml
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<groupId>org.asinkj</groupId>
|
||||||
|
<artifactId>asinkj-common</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>asinkj-common-core</artifactId>
|
||||||
|
|
||||||
|
<description>
|
||||||
|
asinkj-common-core 核心模块
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<!-- Spring框架基本的核心工具 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework</groupId>
|
||||||
|
<artifactId>spring-context-support</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- SpringWeb模块 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework</groupId>
|
||||||
|
<artifactId>spring-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Hibernate Validator -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-validation</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-aop</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!--常用工具类 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-lang3</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- servlet包 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>jakarta.servlet</groupId>
|
||||||
|
<artifactId>jakarta.servlet-api</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.swagger.core.v3</groupId>
|
||||||
|
<artifactId>swagger-annotations</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.hutool</groupId>
|
||||||
|
<artifactId>hutool-core</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.hutool</groupId>
|
||||||
|
<artifactId>hutool-http</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.hutool</groupId>
|
||||||
|
<artifactId>hutool-extra</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 自动生成YML配置关联JSON文件 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-properties-migrator</artifactId>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.github.linpeilie</groupId>
|
||||||
|
<artifactId>mapstruct-plus-spring-boot-starter</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 离线IP地址定位库 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.lionsoul</groupId>
|
||||||
|
<artifactId>ip2region</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
@ -0,0 +1,17 @@
|
|||||||
|
package org.asinkj.common.core.config;
|
||||||
|
|
||||||
|
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||||
|
import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
||||||
|
import org.springframework.scheduling.annotation.EnableAsync;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 程序注解配置
|
||||||
|
*
|
||||||
|
* @author Shuo Hu
|
||||||
|
*/
|
||||||
|
@AutoConfiguration
|
||||||
|
@EnableAspectJAutoProxy
|
||||||
|
@EnableAsync(proxyTargetClass = true)
|
||||||
|
public class ApplicationConfig {
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
package org.asinkj.common.core.config;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.ArrayUtil;
|
||||||
|
import org.asinkj.common.core.exception.ServiceException;
|
||||||
|
import org.asinkj.common.core.utils.SpringUtils;
|
||||||
|
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
|
||||||
|
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||||
|
import org.springframework.core.task.VirtualThreadTaskExecutor;
|
||||||
|
import org.springframework.scheduling.annotation.AsyncConfigurer;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 异步配置
|
||||||
|
* <p>
|
||||||
|
* 如果未使用虚拟线程则生效
|
||||||
|
*
|
||||||
|
* @author Shuo Hu
|
||||||
|
*/
|
||||||
|
@AutoConfiguration
|
||||||
|
public class AsyncConfig implements AsyncConfigurer {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义 @Async 注解使用系统线程池
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Executor getAsyncExecutor() {
|
||||||
|
if(SpringUtils.isVirtual()) {
|
||||||
|
return new VirtualThreadTaskExecutor("async-");
|
||||||
|
}
|
||||||
|
return SpringUtils.getBean("scheduledExecutorService");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 异步执行异常处理
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
|
||||||
|
return (throwable, method, objects) -> {
|
||||||
|
throwable.printStackTrace();
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("Exception message - ").append(throwable.getMessage())
|
||||||
|
.append(", Method name - ").append(method.getName());
|
||||||
|
if (ArrayUtil.isNotEmpty(objects)) {
|
||||||
|
sb.append(", Parameter value - ").append(Arrays.toString(objects));
|
||||||
|
}
|
||||||
|
throw new ServiceException(sb.toString());
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
package org.asinkj.common.core.config;
|
||||||
|
|
||||||
|
import jakarta.annotation.PreDestroy;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
|
||||||
|
import org.asinkj.common.core.utils.Threads;
|
||||||
|
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 线程池配置
|
||||||
|
*
|
||||||
|
* @author Shuo Hu
|
||||||
|
**/
|
||||||
|
@Slf4j
|
||||||
|
@AutoConfiguration
|
||||||
|
public class ThreadPoolConfig {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 核心线程数 = cpu 核心数 + 1
|
||||||
|
*/
|
||||||
|
private final int core = Runtime.getRuntime().availableProcessors() + 1;
|
||||||
|
|
||||||
|
private ScheduledExecutorService scheduledExecutorService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行周期性或定时任务
|
||||||
|
*/
|
||||||
|
@Bean(name = "scheduledExecutorService")
|
||||||
|
protected ScheduledExecutorService scheduledExecutorService() {
|
||||||
|
ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(core,
|
||||||
|
new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build(),
|
||||||
|
new ThreadPoolExecutor.CallerRunsPolicy()) {
|
||||||
|
@Override
|
||||||
|
protected void afterExecute(Runnable r, Throwable t) {
|
||||||
|
super.afterExecute(r, t);
|
||||||
|
Threads.printException(r, t);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.scheduledExecutorService = scheduledThreadPoolExecutor;
|
||||||
|
return scheduledThreadPoolExecutor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 销毁事件
|
||||||
|
*/
|
||||||
|
@PreDestroy
|
||||||
|
public void destroy() {
|
||||||
|
try {
|
||||||
|
log.info("====关闭后台任务任务线程池====");
|
||||||
|
Threads.shutdownAndAwaitTermination(scheduledExecutorService);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
package org.asinkj.common.core.config;
|
||||||
|
|
||||||
|
import jakarta.validation.Validator;
|
||||||
|
import org.hibernate.validator.HibernateValidator;
|
||||||
|
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||||
|
import org.springframework.context.MessageSource;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
|
||||||
|
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验框架配置类
|
||||||
|
*
|
||||||
|
* @author Shuo Hu
|
||||||
|
*/
|
||||||
|
@AutoConfiguration
|
||||||
|
public class ValidatorConfig {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置校验框架 快速返回模式
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public Validator validator(MessageSource messageSource) {
|
||||||
|
try (LocalValidatorFactoryBean factoryBean = new LocalValidatorFactoryBean()) {
|
||||||
|
// 国际化
|
||||||
|
factoryBean.setValidationMessageSource(messageSource);
|
||||||
|
// 设置使用 HibernateValidator 校验器
|
||||||
|
factoryBean.setProviderClass(HibernateValidator.class);
|
||||||
|
Properties properties = new Properties();
|
||||||
|
// 设置 快速异常返回
|
||||||
|
properties.setProperty("hibernate.validator.fail_fast", "true");
|
||||||
|
factoryBean.setValidationProperties(properties);
|
||||||
|
// 加载配置
|
||||||
|
factoryBean.afterPropertiesSet();
|
||||||
|
return factoryBean.getValidator();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package org.asinkj.common.core.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缓存的key 常量
|
||||||
|
*
|
||||||
|
* @author Shuo Hu
|
||||||
|
*/
|
||||||
|
public interface CacheConstants {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在线用户 redis key
|
||||||
|
*/
|
||||||
|
String ONLINE_TOKEN_KEY = "online_tokens:";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 参数管理 cache key
|
||||||
|
*/
|
||||||
|
String SYS_CONFIG_KEY = "sys_config:";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字典管理 cache key
|
||||||
|
*/
|
||||||
|
String SYS_DICT_KEY = "sys_dict:";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录账户密码错误次数 redis key
|
||||||
|
*/
|
||||||
|
String PWD_ERR_CNT_KEY = "pwd_err_cnt:";
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,73 @@
|
|||||||
|
package org.asinkj.common.core.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缓存组名称常量
|
||||||
|
* <p>
|
||||||
|
* key 格式为 cacheNames#ttl#maxIdleTime#maxSize
|
||||||
|
* <p>
|
||||||
|
* ttl 过期时间 如果设置为0则不过期 默认为0
|
||||||
|
* maxIdleTime 最大空闲时间 根据LRU算法清理空闲数据 如果设置为0则不检测 默认为0
|
||||||
|
* maxSize 组最大长度 根据LRU算法清理溢出数据 如果设置为0则无限长 默认为0
|
||||||
|
* <p>
|
||||||
|
* 例子: test#60s、test#0#60s、test#0#1m#1000、test#1h#0#500
|
||||||
|
*
|
||||||
|
* @author Shuo Hu
|
||||||
|
*/
|
||||||
|
public interface CacheNames {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 演示案例
|
||||||
|
*/
|
||||||
|
String DEMO_CACHE = "demo:cache#60s#10m#20";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统配置
|
||||||
|
*/
|
||||||
|
String SYS_CONFIG = "sys_config";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据字典
|
||||||
|
*/
|
||||||
|
String SYS_DICT = "sys_dict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 租户
|
||||||
|
*/
|
||||||
|
String SYS_TENANT = GlobalConstants.GLOBAL_REDIS_KEY + "sys_tenant#30d";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户端
|
||||||
|
*/
|
||||||
|
String SYS_CLIENT = GlobalConstants.GLOBAL_REDIS_KEY + "sys_client#30d";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户账户
|
||||||
|
*/
|
||||||
|
String SYS_USER_NAME = "sys_user_name#30d";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户名称
|
||||||
|
*/
|
||||||
|
String SYS_NICKNAME = "sys_nickname#30d";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 部门
|
||||||
|
*/
|
||||||
|
String SYS_DEPT = "sys_dept#30d";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OSS内容
|
||||||
|
*/
|
||||||
|
String SYS_OSS = "sys_oss#30d";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OSS配置
|
||||||
|
*/
|
||||||
|
String SYS_OSS_CONFIG = GlobalConstants.GLOBAL_REDIS_KEY + "sys_oss_config";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在线用户
|
||||||
|
*/
|
||||||
|
String ONLINE_TOKEN = "online_tokens";
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,81 @@
|
|||||||
|
package org.asinkj.common.core.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通用常量信息
|
||||||
|
*
|
||||||
|
* @author asinkj
|
||||||
|
*/
|
||||||
|
public interface Constants {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UTF-8 字符集
|
||||||
|
*/
|
||||||
|
String UTF8 = "UTF-8";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GBK 字符集
|
||||||
|
*/
|
||||||
|
String GBK = "GBK";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* www主域
|
||||||
|
*/
|
||||||
|
String WWW = "www.";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* http请求
|
||||||
|
*/
|
||||||
|
String HTTP = "http://";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* https请求
|
||||||
|
*/
|
||||||
|
String HTTPS = "https://";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通用成功标识
|
||||||
|
*/
|
||||||
|
String SUCCESS = "0";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通用失败标识
|
||||||
|
*/
|
||||||
|
String FAIL = "1";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录成功
|
||||||
|
*/
|
||||||
|
String LOGIN_SUCCESS = "Success";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注销
|
||||||
|
*/
|
||||||
|
String LOGOUT = "Logout";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注册
|
||||||
|
*/
|
||||||
|
String REGISTER = "Register";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录失败
|
||||||
|
*/
|
||||||
|
String LOGIN_FAIL = "Error";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证码有效期(分钟)
|
||||||
|
*/
|
||||||
|
Integer CAPTCHA_EXPIRATION = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 令牌
|
||||||
|
*/
|
||||||
|
String TOKEN = "token";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 顶级部门id
|
||||||
|
*/
|
||||||
|
Long TOP_PARENT_ID = 0L;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,35 @@
|
|||||||
|
package org.asinkj.common.core.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 全局的key常量 (业务无关的key)
|
||||||
|
*
|
||||||
|
* @author Shuo Hu
|
||||||
|
*/
|
||||||
|
public interface GlobalConstants {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 全局 redis key (业务无关的key)
|
||||||
|
*/
|
||||||
|
String GLOBAL_REDIS_KEY = "global:";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证码 redis key
|
||||||
|
*/
|
||||||
|
String CAPTCHA_CODE_KEY = GLOBAL_REDIS_KEY + "captcha_codes:";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 防重提交 redis key
|
||||||
|
*/
|
||||||
|
String REPEAT_SUBMIT_KEY = GLOBAL_REDIS_KEY + "repeat_submit:";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 限流 redis key
|
||||||
|
*/
|
||||||
|
String RATE_LIMIT_KEY = GLOBAL_REDIS_KEY + "rate_limit:";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 三方认证 redis key
|
||||||
|
*/
|
||||||
|
String SOCIAL_AUTH_CODE_KEY = GLOBAL_REDIS_KEY + "social_auth_codes:";
|
||||||
|
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user