Compare commits

...

42 Commits

Author SHA1 Message Date
李佳航
f73fa14bfd Merge pull request #55 from dromara/dev
Dev
2024-09-02 13:11:36 +08:00
lijiahang
fd88c725d3 :replace: 修改 demo 地址. 2024-09-02 13:06:17 +08:00
lijiahang
3a16f9d9ab 优化查询逻辑. 2024-09-02 12:37:11 +08:00
lijiahang
de9b89d805 🔖 升级版本. 2024-09-02 11:51:30 +08:00
lijiahangmax
a05c387ba1 修改配置. 2024-08-29 23:34:28 +08:00
lijiahangmax
3cb6e5a2d4 修改配置. 2024-08-29 23:33:46 +08:00
lijiahang
104a9a0aa3 🔨 数据清理时添加条数限制. 2024-08-29 18:26:26 +08:00
lijiahangmax
d7b747eac4 优化主机删除逻辑. 2024-08-29 00:33:13 +08:00
lijiahangmax
d2949c11f3 Merge remote-tracking branch 'origin/dev' into dev 2024-08-29 00:23:33 +08:00
lijiahangmax
cd05f71173 🐛 修复开始 webgl 终端显示错误. 2024-08-29 00:23:11 +08:00
lijiahang
e0dca73369 📝 修改文档. 2024-08-28 17:14:18 +08:00
lijiahang
b8599a6693 🐛 修复加载缓存时报错. 2024-08-28 10:46:06 +08:00
lijiahang
a0adb415fa 🔨 数据清理时添加条数限制. 2024-08-26 17:10:40 +08:00
lijiahang
6c60756e54 禁用 demo api. 2024-08-26 13:57:18 +08:00
lijiahangmax
ee9f51ce7d 🐛 修复 quartz 配置不生效. 2024-08-25 00:50:16 +08:00
lijiahangmax
924b46b41a 优化异常信息获取逻辑. 2024-08-24 19:59:45 +08:00
lijiahangmax
1fca5a1912 优化数据分组逻辑. 2024-08-23 01:44:05 +08:00
李佳航
120eb1ee69 Merge pull request #54 from dromara/dev
Dev
2024-08-22 12:27:58 +08:00
lijiahang
252c538571 🔖 升级版本. 2024-08-22 11:45:24 +08:00
lijiahang
1eec373b7e demo 禁用定时任务. 2024-08-21 13:23:31 +08:00
lijiahang
aa9b96a9c1 修改表格显示字段. 2024-08-21 12:56:07 +08:00
lijiahang
059fb30aa4 优化权限逻辑. 2024-08-20 10:20:35 +08:00
lijiahang
2afaf7ad34 Merge remote-tracking branch 'origin/dev' into dev 2024-08-19 09:53:15 +08:00
lijiahang
076a0956c5 修改心跳检测时间. 2024-08-19 09:49:41 +08:00
lijiahangmax
4a91ec47bf 添加主题. 2024-08-13 20:56:00 +08:00
lijiahangmax
1066b43b3d 全屏模式. 2024-08-12 00:07:54 +08:00
lijiahangmax
3f78125c43 Merge remote-tracking branch 'origin/dev' into dev 2024-08-11 23:07:14 +08:00
lijiahangmax
144a44673b 🐛 修复更新菜单后查询条件错误. 2024-08-11 23:06:59 +08:00
李佳航
777f7b3758 Merge pull request #52 from dromara/dev
Dev
2024-08-08 10:52:09 +08:00
lijiahang
947fa0fea3 🐳 添加 push 脚本. 2024-08-08 10:17:31 +08:00
lijiahang
7109e89fb4 🔖 升级版本. 2024-08-08 10:14:39 +08:00
lijiahang
70e7b1d544 修改终端标签颜色显示. 2024-08-07 10:18:39 +08:00
lijiahangmax
613f86155c 💄 修改终端样式. 2024-08-06 00:01:27 +08:00
lijiahang
8d0b58e48f ⬆️ 升级 orion kit 版本. 2024-08-05 13:49:52 +08:00
lijiahang
8cea9dc977 优化终端代码. 2024-08-05 09:11:54 +08:00
lijiahangmax
471acfdf00 优化自动聚焦逻辑. 2024-08-04 17:01:44 +08:00
lijiahangmax
8ed42131d0 优化命令片段处理逻辑. 2024-08-02 01:52:29 +08:00
lijiahangmax
18c605354a 🔨 修改终端逻辑. 2024-07-31 00:42:02 +08:00
李佳航
8c04411458 Merge pull request #48 from MemoryShadow/dev
perf: Use the.env file instead to modify docker-compose.yml
2024-07-30 17:53:31 +08:00
lijiahang
9a8d1d05cd 💄 修改终端样式. 2024-07-30 14:40:15 +08:00
MemoryShadow
1cbaf9c424 docs: Clarify behavior semantics and accelerate deployment efficiency 2024-07-29 07:02:32 +00:00
MemoryShadow
537c2fc108 perf: Use the.env file instead to modify docker-compose.yml 2024-07-29 07:02:21 +00:00
265 changed files with 3299 additions and 1904 deletions

15
.env.example Normal file
View File

@@ -0,0 +1,15 @@
SERVICE_PORT=1081
VOLUME_BASE=/data/orion-visor-space/docker-volumes
MYSQL_HOST=mysql
MYSQL_PORT=3306
MYSQL_DATABASE=orion_visor
MYSQL_USER=orion
MYSQL_PASSWORD=Data@123456
MYSQL_ROOT_PASSWORD=Data@123456
REDIS_HOST=redis
REDIS_PASSWORD=Data@123456
SECRET_KEY=uQeacXV8b3isvKLK
DEMO_MODE=false

1
.gitignore vendored
View File

@@ -33,3 +33,4 @@ build/
### VS Code ###
.vscode/
.env

View File

@@ -19,12 +19,12 @@
<a target="_blank"
style="text-decoration: none !important;"
href="https://gitee.com/dromara/orion-visor/stargazers">
<img src="https://gitee.com/dromara/orion-visor/badge/star.svg?theme=dark" alt="star" />
<img src="https://gitee.com/dromara/orion-visor/badge/star.svg?theme=gvp" alt="star" />
</a>
<a target="_blank"
style="text-decoration: none !important;"
href="https://gitee.com/dromara/orion-visor/members">
<img src="https://gitee.com/dromara/orion-visor/badge/fork.svg?theme=dark" alt="fork" />
<img src="https://gitee.com/dromara/orion-visor/badge/fork.svg?theme=gvp" alt="fork" />
</a>
<a target="_blank"
style="text-decoration: none !important;"
@@ -51,7 +51,7 @@
## 演示环境
* 🔗 演示地址: http://101.43.254.243:1081/
* 🔗 演示地址: https://dv.orionsec.cn/
* 🔏 演示账号: admin/admin
* ⭐ 体验后可以点一下 `star` 这对我很重要! [github](https://github.com/dromara/orion-visor) [gitee](https://gitee.com/dromara/orion-visor) [gitcode](https://gitcode.com/dromara/orion-visor/overview)
* 🌈 如果本项目对你有帮助请帮忙推广一下 让更多的人知道此项目!
@@ -63,7 +63,7 @@
```bash
# clone
git clone https://github.com/dromara/orion-visor
git clone --depth=1 https://github.com/dromara/orion-visor
cd orion-visor
# 启动
docker compose up -d
@@ -72,11 +72,11 @@ docker compose up -d
## 项目文档
* [文档地址](https://lijiahangmax.github.io/open-orion/orion-visor/)
* [安装文档](https://lijiahangmax.github.io/open-orion/orion-visor/quickstart/docker.html)
* [更新日志](https://lijiahangmax.github.io/open-orion/orion-visor/update/change-log.html)
* [操作手册](https://lijiahangmax.github.io/open-orion/orion-visor/operator/asset.html)
* [常见问题](https://lijiahangmax.github.io/open-orion/orion-visor/support/faq.html)
* [文档地址](https://visor.orionsec.cn/)
* [安装文档](https://visor.orionsec.cn/quickstart/docker.html)
* [更新日志](https://visor.orionsec.cn/update/change-log.html)
* [操作手册](https://visor.orionsec.cn/operator/asset.html)
* [常见问题](https://visor.orionsec.cn/support/faq.html)
## 技术栈

View File

@@ -1,7 +1,7 @@
version: '3.3'
services:
service:
image: registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-service:2.1.2
image: registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-service:2.1.5
privileged: true
ports:
- 1081:80
@@ -32,7 +32,7 @@ services:
- mysql
- redis
mysql:
image: registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-mysql:2.1.2
image: registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-mysql:2.1.5
privileged: true
ports:
- 3307:3306
@@ -52,7 +52,7 @@ services:
retries: 10
start_period: 3s
redis:
image: registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-redis:2.1.2
image: registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-redis:2.1.5
privileged: true
ports:
- 6380:6379

View File

@@ -1,27 +1,27 @@
version: '3.3'
services:
service:
image: registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-service:2.1.2
image: registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-service:2.1.5
privileged: true
ports:
- 1081:80
- ${SERVICE_PORT:-1081}:80
environment:
- MYSQL_HOST=mysql
- MYSQL_PORT=3306
- MYSQL_DATABASE=orion_visor
- MYSQL_USER=root
- MYSQL_PASSWORD=Data@123456
- REDIS_HOST=redis
- REDIS_PASSWORD=Data@123456
- SECRET_KEY=uQeacXV8b3isvKLK
- DEMO_MODE=false
- MYSQL_HOST=${MYSQL_HOST:-mysql}
- MYSQL_PORT=${MYSQL_PORT:-3306}
- MYSQL_DATABASE=${MYSQL_DATABASE:-orion_visor}
- MYSQL_USER=${MYSQL_USER:-root}
- MYSQL_PASSWORD=${MYSQL_PASSWORD:-Data@123456}
- REDIS_HOST=${REDIS_HOST:-redis}
- REDIS_PASSWORD=${REDIS_PASSWORD:-Data@123456}
- SECRET_KEY=${SECRET_KEY:-uQeacXV8b3isvKLK}
- DEMO_MODE=${DEMO_MODE:-false}
volumes:
- /data/orion-visor-space/docker-volumes/service/root-orion:/root/orion
- ${VOLUME_BASE:-/data/orion-visor-space/docker-volumes}/service/root-orion:/root/orion
healthcheck:
test: [ "CMD", "curl", "http://127.0.0.1:9200/orion-visor/api/server/bootstrap/health" ]
interval: 3s
interval: 15s
timeout: 300s
retries: 200
retries: 15
start_period: 3s
depends_on:
mysql:
@@ -32,43 +32,43 @@ services:
- mysql
- redis
mysql:
image: registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-mysql:2.1.2
image: registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-mysql:2.1.5
privileged: true
ports:
- 3307:3306
environment:
- MYSQL_DATABASE=orion_visor
- MYSQL_USER=orion
- MYSQL_PASSWORD=Data@123456
- MYSQL_ROOT_PASSWORD=Data@123456
- MYSQL_DATABASE=${MYSQL_DATABASE:-orion_visor}
- MYSQL_USER=${MYSQL_USER:-orion}
- MYSQL_PASSWORD=${MYSQL_PASSWORD:-Data@123456}
- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:-Data@123456}
volumes:
- /data/orion-visor-space/docker-volumes/mysql/var-lib-mysql:/var/lib/mysql
- /data/orion-visor-space/docker-volumes/mysql/var-lib-mysql-files:/var/lib/mysql-files
- /data/orion-visor-space/docker-volumes/mysql/etc-mysql:/etc/mysql
- ${VOLUME_BASE:-/data/orion-visor-space/docker-volumes}/mysql/var-lib-mysql:/var/lib/mysql
- ${VOLUME_BASE:-/data/orion-visor-space/docker-volumes}/mysql/var-lib-mysql-files:/var/lib/mysql-files
- ${VOLUME_BASE:-/data/orion-visor-space/docker-volumes}/mysql/etc-mysql:/etc/mysql
healthcheck:
test: [ "CMD", "bash", "-c", "cat < /dev/null > /dev/tcp/127.0.0.1/3306" ]
interval: 3s
interval: 15s
timeout: 60s
retries: 10
retries: 15
start_period: 3s
redis:
image: registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-redis:2.1.2
image: registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-redis:2.1.5
privileged: true
ports:
- 6380:6379
environment:
- REDIS_PASSWORD=Data@123456
- REDIS_PASSWORD=${REDIS_PASSWORD:-Data@123456}
volumes:
- /data/orion-visor-space/docker-volumes/redis/data:/data
- ${VOLUME_BASE:-/data/orion-visor-space/docker-volumes}/redis/data:/data
command: sh -c "redis-server /usr/local/redis.conf --requirepass $${REDIS_PASSWORD}"
healthcheck:
test: [ "CMD", "redis-cli", "--raw", "incr", "ping" ]
interval: 3s
interval: 15s
timeout: 60s
retries: 10
retries: 15
start_period: 3s
adminer:
image: registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-adminer:2.1.2
image: registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-adminer:2.1.5
ports:
- 8081:8080
depends_on:

View File

@@ -2,6 +2,6 @@
docker compose down
# demo 启动
if [ "$1" == "demo" ]; then
sed -i 's/DEMO_MODE=false/DEMO_MODE=true/g' docker-compose.yml
sed -i 's/\${DEMO_MODE:-false}/true/g' docker-compose.yml
fi
docker compose up -d --remove-orphans

View File

@@ -1,5 +1,4 @@
#/bin/bash
version=2.1.2
version=2.1.5
docker build -t orion-visor-adminer:${version} .
docker tag orion-visor-adminer:${version} registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-adminer:${version}
docker push registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-adminer:${version}

View File

@@ -17,7 +17,7 @@ items:
code: 200
- name: userPermission
request:
api: /orion-visor/api/infra/permission/user
api: /orion-visor/api/infra/user-permission/user
header:
Authorization: Bearer {{.login.data.token}}
expect:
@@ -26,7 +26,7 @@ items:
msg: "success"
- name: menu
request:
api: /orion-visor/api/infra/permission/menu
api: /orion-visor/api/infra/user-permission/menu
header:
Authorization: Bearer {{.login.data.token}}
expect:

View File

@@ -1,7 +1,6 @@
#/bin/bash
version=2.1.2
version=2.1.5
cp -r ../../sql ./sql
docker build -t orion-visor-mysql:${version} .
rm -rf ./sql
docker tag orion-visor-mysql:${version} registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-mysql:${version}
docker push registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-mysql:${version}

6
docker/push.sh Normal file
View File

@@ -0,0 +1,6 @@
#/bin/bash
version=2.1.5
docker push registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-adminer:${version}
docker push registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-mysql:${version}
docker push registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-redis:${version}
docker push registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-service:${version}

View File

@@ -1,5 +1,4 @@
#/bin/bash
version=2.1.2
version=2.1.5
docker build -t orion-visor-redis:${version} .
docker tag orion-visor-redis:${version} registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-redis:${version}
docker push registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-redis:${version}

View File

@@ -1,9 +1,8 @@
#/bin/bash
version=2.1.2
version=2.1.5
mv ../../orion-visor-launch/target/orion-visor-launch.jar ./orion-visor-launch.jar
mv ../../orion-visor-ui/dist ./dist
docker build -t orion-visor-service:${version} .
rm -rf ./orion-visor-launch.jar
rm -rf ./dist
docker tag orion-visor-service:${version} registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-service:${version}
docker push registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-service:${version}

View File

@@ -29,7 +29,7 @@ server {
location /orion-visor/api {
proxy_pass http://localhost:9200/orion-visor/api;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}

View File

@@ -19,12 +19,12 @@
<a target="_blank"
style="text-decoration: none !important;"
href="https://gitee.com/lijiahangmax/orion-visor/stargazers">
<img src="https://gitee.com/lijiahangmax/orion-visor/badge/star.svg?theme=dark" alt="star" />
<img src="https://gitee.com/lijiahangmax/orion-visor/badge/star.svg?theme=gvp" alt="star" />
</a>
<a target="_blank"
style="text-decoration: none !important;"
href="https://gitee.com/lijiahangmax/orion-visor/members">
<img src="https://gitee.com/lijiahangmax/orion-visor/badge/fork.svg?theme=dark" alt="fork" />
<img src="https://gitee.com/lijiahangmax/orion-visor/badge/fork.svg?theme=gvp" alt="fork" />
</a>
<a target="_blank"
style="text-decoration: none !important;"

View File

@@ -21,22 +21,35 @@ Dashboard 修改)
```shell
# github
git clone https://github.com/lijiahangmax/orion-visor
git clone --depth=1 https://github.com/lijiahangmax/orion-visor
# gitee
git clone https://gitee.com/lijiahangmax/orion-visor
git clone --depth=1 https://gitee.com/lijiahangmax/orion-visor
```
### 构建镜像
### 拉取镜像
```
# 进入仓库目录
cd orion-visor
# 修改 docker-compose.yml (建议修改)
# MYSQL_USER mysql 用户名
# MYSQL_PASSWORD mysql 用户密码
# MYSQL_ROOT_PASSWORD mysql root 密码
# REDIS_PASSWORD redis 密码
# SECRET_KEY 加密密钥
# 创建名为 .env 的 .env.example 副本
cp .env.example .env
# 将其中的值删除以保持默认或将其修改为你喜欢的值
# SERVICE_PORT 你希望服务监听的端口
# VOLUME_BASE 你希望数据持久化保存的目录, 如果不提前创建将以 docker 进程宿主身份创建(通常是 root)
# MYSQL_HOST mysql 服务所在的主机, 如果你没有现有的 MySQL 请保持值为 mysql, 如果你有自部署的请在 docker-compose.yml 中移除 services.mysql 以节约性能
# MYSQL_PORT mysql 监听的端口
# MYSQL_DATABASE mysql 数据库
# MYSQL_USER mysql 用户名
# MYSQL_PASSWORD mysql 用户密码
# MYSQL_ROOT_PASSWORD mysql root 密码
# REDIS_HOST redis 服务所在的主机, 如果你没有现有的 Redis 请保持值为 redis, 如果你有自部署的请在 docker-compose.yml 中移除 services.redis 以节约性能
# REDIS_PASSWORD redis 密码
# SECRET_KEY 加密密钥
# 拉取远程镜像
docker compose pull
```
### 启动
@@ -45,7 +58,7 @@ cd orion-visor
docker compose up -d
```
### 修改加密方式
### 修改 MySQL 账户的加密方式
```
访问 adminer: http://localhost:8081

View File

@@ -14,11 +14,11 @@
<url>https://github.com/dromara/orion-visor</url>
<properties>
<revision>2.1.2</revision>
<revision>2.1.5</revision>
<spring.boot.version>2.7.17</spring.boot.version>
<spring.boot.admin.version>2.7.15</spring.boot.admin.version>
<flatten.maven.plugin.version>1.5.0</flatten.maven.plugin.version>
<orion.kit.version>1.0.7</orion.kit.version>
<orion.kit.version>1.0.8</orion.kit.version>
<aspectj.version>1.9.7</aspectj.version>
<lombok.version>1.18.26</lombok.version>
<springdoc.version>1.6.15</springdoc.version>

View File

@@ -1,17 +0,0 @@
package com.orion.visor.framework.common.annotation;
import java.lang.annotation.*;
/**
* 保留
*
* @author Jiahang Li
* @version 1.0.0
* @since 2024/6/6 15:26
*/
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Keep {
}

View File

@@ -14,7 +14,7 @@ public interface AppConst extends OrionConst {
/**
* 同 ${orion.version} 迭代时候需要手动更改
*/
String VERSION = "2.1.2";
String VERSION = "2.1.5";
/**
* 同 ${spring.application.name}

View File

@@ -29,4 +29,6 @@ public interface Const extends com.orion.lang.constant.Const, FieldConst, CnCons
String SYSTEM_USERNAME = "system";
int BATCH_COUNT = 500;
}

View File

@@ -1,5 +1,8 @@
package com.orion.visor.framework.common.constant;
import com.orion.lang.exception.ApplicationException;
import com.orion.lang.exception.argument.InvalidArgumentException;
/**
* 错误信息
*
@@ -97,6 +100,14 @@ public interface ErrorMessage {
String TASK_ABSENT = "任务不存在";
String CONNECT_ERROR = "连接失败";
String AUTH_ERROR = "认证失败";
String SCRIPT_UPLOAD_ERROR = "脚本上传失败";
String EXEC_ERROR = "执行失败";
String ILLEGAL_STATUS = "当前状态不支持此操作";
String CHECK_AUTHORIZED_HOST = "请选择已授权的主机";
@@ -109,4 +120,43 @@ public interface ErrorMessage {
String CLIENT_ABORT = "手动中断";
String UNABLE_DOWNLOAD_FOLDER = "无法下载文件夹";
/**
* 是否为业务异常
*
* @param ex ex
* @return biz exception
*/
static boolean isBizException(Exception ex) {
if (ex == null) {
return false;
}
return ex instanceof InvalidArgumentException
|| ex instanceof IllegalArgumentException
|| ex instanceof ApplicationException;
}
/**
* 获取错误信息
*
* @param ex ex
* @param defaultMsg defaultMsg
* @return message
*/
static String getErrorMessage(Exception ex, String defaultMsg) {
if (ex == null) {
return null;
}
String message = ex.getMessage();
if (message == null) {
return defaultMsg;
}
// 业务异常
if (isBizException(ex)) {
return message;
}
return defaultMsg;
}
}

View File

@@ -0,0 +1,26 @@
package com.orion.visor.framework.common.entity;
/**
* 数据清理请求 定义
*
* @author Jiahang Li
* @version 1.0.0
* @since 2024/8/29 11:26
*/
public interface DataClearRequest {
/**
* 获取清理数量限制
*
* @return 清理限制
*/
Integer getLimit();
/**
* 设置清理数量限制
*
* @param limit limit
*/
void setLimit(Integer limit);
}

View File

@@ -1,10 +1,12 @@
package com.orion.visor.framework.common.entity;
import com.orion.lang.define.wrapper.IPageRequest;
import com.orion.visor.framework.common.validator.group.Page;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.hibernate.validator.constraints.Range;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
/**
* 公共页码请求
@@ -15,14 +17,18 @@ import org.hibernate.validator.constraints.Range;
*/
@Data
@Schema(description = "公共页码请求")
public class PageRequest implements IPageRequest {
public class PageRequest {
@Range(min = 1, max = 10000, groups = Page.class)
@NotNull(groups = Page.class)
@Min(value = 1, groups = Page.class)
@Max(value = 10000, groups = Page.class)
@Schema(description = "页码")
private int page;
private Integer page;
@Range(min = 1, max = 100, groups = Page.class)
@NotNull(groups = Page.class)
@Min(value = 1, groups = Page.class)
@Max(value = 200, groups = Page.class)
@Schema(description = "大小")
private int limit;
private Integer limit;
}

View File

@@ -1,6 +1,8 @@
package com.orion.visor.framework.common.meta;
import com.alibaba.ttl.TransmittableThreadLocal;
import com.orion.lang.id.UUIds;
import org.slf4j.MDC;
/**
* traceId 持有者
@@ -23,16 +25,74 @@ public class TraceIdHolder {
*/
private static final ThreadLocal<String> HOLDER = new TransmittableThreadLocal<>();
/**
* 获取 traceId
*
* @return traceId
*/
public static String get() {
return HOLDER.get();
}
public static void set(String traceId) {
HOLDER.set(traceId);
/**
* 设置 traceId
*/
public static void set() {
set(createTraceId());
}
/**
* 设置 traceId
*
* @param traceId traceId
*/
public static void set(String traceId) {
// 设置应用上下文
HOLDER.set(traceId);
// 设置日志上下文
setMdc(traceId);
}
/**
* 删除 traceId
*/
public static void remove() {
// 移除应用上下文
HOLDER.remove();
// 移除日志上下文
removeMdc();
}
/**
* 从应用上下文 设置到日志上下文
*/
public static void setMdc() {
setMdc(HOLDER.get());
}
/**
* 设置到日志上下文
*
* @param traceId traceId
*/
public static void setMdc(String traceId) {
MDC.put(TRACE_ID_MDC, traceId);
}
/**
* 移除日志上下文
*/
public static void removeMdc() {
MDC.remove(TRACE_ID_MDC);
}
/**
* 创建 traceId
*
* @return traceId
*/
public static String createTraceId() {
return UUIds.random32();
}
}

View File

@@ -32,11 +32,11 @@ public class IpUtils {
* @return addr
*/
public static String getRemoteAddr(HttpServletRequest request) {
// 获取实际地址
String realIp = request.getHeader(StandardHttpHeader.X_REAL_IP);
if (!Strings.isBlank(realIp)) {
return realIp;
}
// 获取实际地址 X_REAL_IP 在多代理情况下会有问题
// String realIp = request.getHeader(StandardHttpHeader.X_REAL_IP);
// if (!Strings.isBlank(realIp)) {
// return realIp;
// }
// 获取请求地址
return Servlets.getRemoteAddr(request);
}

View File

@@ -0,0 +1,38 @@
package com.orion.visor.framework.common.utils;
import com.orion.visor.framework.common.constant.Const;
/**
* sql 工具类
*
* @author Jiahang Li
* @version 1.0.0
* @since 2024/8/26 16:03
*/
public class SqlUtils {
private SqlUtils() {
}
/**
* limit n
*
* @param limit limit
* @return limit
*/
public static String limit(Number limit) {
return Const.LIMIT + Const.SPACE + limit;
}
/**
* limit offset limit
*
* @param offset offset
* @param limit limit
* @return limit
*/
public static String limit(Number offset, Number limit) {
return Const.LIMIT + Const.SPACE + offset + Const.COMMA + limit;
}
}

View File

@@ -9,6 +9,7 @@ import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.Validator;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
@@ -31,6 +32,10 @@ public class Valid extends com.orion.lang.utils.Valid {
return notBlank(s, ErrorMessage.PARAM_MISSING);
}
public static <T extends Map<?, ?>> T notEmpty(T map) {
return notEmpty(map, ErrorMessage.PARAM_MISSING);
}
public static <T extends Collection<?>> T notEmpty(T object) {
return notEmpty(object, ErrorMessage.PARAM_MISSING);
}

View File

@@ -1,7 +1,5 @@
package com.orion.visor.framework.common.validator.group;
import javax.validation.groups.Default;
/**
* 批量验证分组
*
@@ -9,5 +7,5 @@ import javax.validation.groups.Default;
* @version 1.0.0
* @since 2023/9/1 19:13
*/
public interface Batch extends Default {
public interface Batch {
}

View File

@@ -0,0 +1,11 @@
package com.orion.visor.framework.common.validator.group;
/**
* 清理验证分组
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023/9/1 19:13
*/
public interface Clear {
}

View File

@@ -0,0 +1,11 @@
package com.orion.visor.framework.common.validator.group;
/**
* 导出验证分组
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023/9/1 19:13
*/
public interface Export {
}

View File

@@ -1,7 +1,5 @@
package com.orion.visor.framework.common.validator.group;
import javax.validation.groups.Default;
/**
* 分页验证分组
*
@@ -9,5 +7,5 @@ import javax.validation.groups.Default;
* @version 1.0.0
* @since 2023/9/1 19:13
*/
public interface Id extends Default {
public interface Id {
}

View File

@@ -0,0 +1,11 @@
package com.orion.visor.framework.common.validator.group;
/**
* 导出验证分组
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023/9/1 19:13
*/
public interface Import {
}

View File

@@ -1,7 +1,5 @@
package com.orion.visor.framework.common.validator.group;
import javax.validation.groups.Default;
/**
* 分页验证分组
*
@@ -9,5 +7,5 @@ import javax.validation.groups.Default;
* @version 1.0.0
* @since 2023/9/1 19:13
*/
public interface Page extends Default {
public interface Page {
}

View File

@@ -7,9 +7,6 @@ import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.scheduling.quartz.SpringBeanJobFactory;
import javax.sql.DataSource;
/**
* quartz 配置
@@ -22,27 +19,6 @@ import javax.sql.DataSource;
@AutoConfigureOrder(AutoConfigureOrderConst.FRAMEWORK_JOB_QUARTZ)
public class OrionQuartzAutoConfiguration {
/**
* @return 任务工厂
*/
@Bean
public SpringBeanJobFactory jobFactory() {
return new SpringBeanJobFactory();
}
/**
* @param dataSource dataSource
* @param jobFactory jobFactory
* @return 调度器工厂
*/
@Bean
public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource, SpringBeanJobFactory jobFactory) {
SchedulerFactoryBean factory = new SchedulerFactoryBean();
factory.setDataSource(dataSource);
factory.setJobFactory(jobFactory);
return factory;
}
/**
* @param schedulerFactoryBean 调度器工厂
* @return 调度器

View File

@@ -6,6 +6,9 @@ import java.lang.annotation.*;
/**
* 不执行统一日志打印
* <p>
* 如果设置在方法上,则忽略该方法的日志打印
* 如果设置到参数上,则忽略该参数的日志打印
*
* @author Jiahang Li
* @version 1.0.0

View File

@@ -3,6 +3,7 @@ package com.orion.visor.framework.mybatis.core.generator.core;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.generator.config.po.TableField;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.orion.lang.utils.Exceptions;
import com.orion.lang.utils.Strings;
import com.orion.visor.framework.common.constant.Const;
import com.orion.visor.framework.common.constant.FieldConst;
@@ -47,7 +48,7 @@ public class DictParser {
.stream()
.filter(s -> variable.equals(s.getName()) || variable.equals(s.getPropertyName()))
.findFirst()
.orElseThrow(() -> new RuntimeException("未查询到字典映射字段 " + variable));
.orElseThrow(() -> Exceptions.runtime("未查询到字典映射字段 " + variable));
// 设置字段名称
if (meta.getField() == null) {
meta.setField(Strings.firstUpper(tableField.getPropertyName()));

View File

@@ -3,6 +3,7 @@ package com.orion.visor.framework.mybatis.core.mapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import com.orion.visor.framework.common.constant.Const;
import com.orion.visor.framework.mybatis.core.query.Conditions;
import com.orion.visor.framework.mybatis.core.query.DataQuery;
@@ -61,7 +62,7 @@ public interface IMapper<T> extends BaseMapper<T> {
* @return 是否成功
*/
default boolean insertBatch(Collection<T> entities) {
return Db.saveBatch(entities);
return this.insertBatch(entities, Const.BATCH_COUNT);
}
/**
@@ -82,7 +83,7 @@ public interface IMapper<T> extends BaseMapper<T> {
* @return 是否成功
*/
default boolean updateBatch(Collection<T> entities) {
return Db.updateBatchById(entities);
return this.updateBatch(entities, Const.BATCH_COUNT);
}
/**
@@ -113,7 +114,7 @@ public interface IMapper<T> extends BaseMapper<T> {
* @return 是否成功
*/
default boolean insertOrUpdateBatch(Collection<T> entities) {
return Db.saveOrUpdateBatch(entities);
return this.insertOrUpdateBatch(entities, Const.BATCH_COUNT);
}
/**

View File

@@ -16,6 +16,7 @@ import com.orion.lang.utils.collect.Lists;
import com.orion.lang.utils.reflect.Classes;
import com.orion.spring.SpringHolder;
import com.orion.visor.framework.common.constant.Const;
import com.orion.visor.framework.common.utils.SqlUtils;
import com.orion.visor.framework.mybatis.core.domain.BaseDO;
import java.io.Serializable;
@@ -36,7 +37,7 @@ public class DataQuery<T> {
private final BaseMapper<T> dao;
private IPageRequest page;
private PageRequest page;
private Wrapper<T> wrapper;
@@ -73,8 +74,9 @@ public class DataQuery<T> {
return new DataQuery<>(dao, wrapper);
}
public DataQuery<T> page(IPageRequest page) {
this.page = Valid.notNull(page, "page is null");
public DataQuery<T> page(com.orion.visor.framework.common.entity.PageRequest page) {
com.orion.visor.framework.common.entity.PageRequest pr = Valid.notNull(page, "page is null");
this.page = new PageRequest(pr.getPage(), pr.getLimit());
return this;
}
@@ -111,11 +113,11 @@ public class DataQuery<T> {
}
public DataQuery<T> limit(int limit) {
return this.last(Const.LIMIT + Const.SPACE + limit);
return this.last(SqlUtils.limit(limit));
}
public DataQuery<T> limit(int offset, int limit) {
return this.last(Const.LIMIT + Const.SPACE + offset + Const.COMMA + limit);
return this.last(SqlUtils.limit(offset, limit));
}
public DataQuery<T> only() {
@@ -199,6 +201,18 @@ public class DataQuery<T> {
return dao.selectCount(wrapper);
}
public Long countMax(Number max) {
Long count = dao.selectCount(wrapper);
if (max == null) {
return count;
}
long maxValue = max.longValue();
if (maxValue <= 0L) {
return count;
}
return Math.min(count, maxValue);
}
public boolean absent() {
return dao.selectCount(wrapper) == 0;
}

View File

@@ -60,6 +60,18 @@ Authorization: {{token}}
}
${httpComment} ${apiComment.queryCount}
POST {{baseUrl}}/${package.ModuleName}/${typeHyphen}/count
Content-Type: application/json
Authorization: {{token}}
{
#foreach($field in ${table.fields})
"${field.propertyName}": ""#if($foreach.hasNext),#end
#end
}
${httpComment} ${apiComment.deleteById}
DELETE {{baseUrl}}/${package.ModuleName}/${typeHyphen}/delete?id=1
Authorization: {{token}}

View File

@@ -113,6 +113,13 @@ public class ${table.controllerName} {
return ${typeLower}Service.get${type}Page(request);
}
@PostMapping("/count")
@Operation(summary = "${apiComment.queryCount}")
@PreAuthorize("@ss.hasPermission('${package.ModuleName}:${typeHyphen}:query')")
public Long get${type}Count(@Validated @RequestBody ${type}QueryRequest request) {
return ${typeLower}Service.get${type}Count(request);
}
#if($meta.enableDemoApi)
@DemoDisableApi
#end

View File

@@ -122,7 +122,8 @@ public class ${table.serviceImplName} implements ${table.serviceName} {
@Override
public List<${type}VO> get${type}List(${type}QueryRequest request) {
// 条件
LambdaQueryWrapper<${type}DO> wrapper = this.buildQueryWrapper(request);
LambdaQueryWrapper<${type}DO> wrapper = this.buildQueryWrapper(request)
.orderByDesc(${type}DO::getId);
// 查询
return ${typeLower}DAO.of(wrapper).list(${type}Convert.MAPPER::to);
}
@@ -148,24 +149,28 @@ public class ${table.serviceImplName} implements ${table.serviceName} {
.sorted(Comparator.comparing(${type}VO::getId).reversed())
.collect(Collectors.toList());
}
#end
@Override
public DataGrid<${type}VO> get${type}Page(${type}QueryRequest request) {
// 条件
LambdaQueryWrapper<${type}DO> wrapper = this.buildQueryWrapper(request)
.orderByDesc(${type}DO::getId);
// 查询
return ${typeLower}DAO.of()
.page(request)
.wrapper(wrapper)
.dataGrid(${type}Convert.MAPPER::to);
}
@Override
public Long get${type}Count(${type}QueryRequest request) {
// 条件
LambdaQueryWrapper<${type}DO> wrapper = this.buildQueryWrapper(request);
// 查询
return ${typeLower}DAO.selectCount(wrapper);
}
@Override
public DataGrid<${type}VO> get${type}Page(${type}QueryRequest request) {
// 条件
LambdaQueryWrapper<${type}DO> wrapper = this.buildQueryWrapper(request);
// 查询
return ${typeLower}DAO.of(wrapper)
.page(request)
.dataGrid(${type}Convert.MAPPER::to);
return ${typeLower}DAO.of()
.wrapper(wrapper)
.countMax(request.getLimit());
}
@Override
@@ -235,13 +240,8 @@ public class ${table.serviceImplName} implements ${table.serviceName} {
Valid.isFalse(present, ErrorMessage.DATA_PRESENT);
}
/**
* 构建查询 wrapper
*
* @param request request
* @return wrapper
*/
private LambdaQueryWrapper<${type}DO> buildQueryWrapper(${type}QueryRequest request) {
@Override
public LambdaQueryWrapper<${type}DO> buildQueryWrapper(${type}QueryRequest request) {
String searchValue = request.getSearchValue();
return ${typeLower}DAO.wrapper()
#foreach($field in ${table.fields})
@@ -251,8 +251,7 @@ public class ${table.serviceImplName} implements ${table.serviceName} {
#foreach($field in ${table.fields})
.eq(${type}DO::get${field.capitalName}, searchValue)#if($foreach.hasNext).or()#end
#end
)
.orderByDesc(${type}DO::getId);
);
}
}

View File

@@ -1,5 +1,6 @@
package ${package.Service};
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.orion.lang.define.wrapper.DataGrid;
#foreach($pkg in ${customModuleFilePackages})
import ${pkg}.*;
@@ -116,4 +117,12 @@ public interface ${table.serviceName} {
*/
Integer delete${type}(${type}QueryRequest request);
/**
* 构建查询 wrapper
*
* @param request request
* @return wrapper
*/
private LambdaQueryWrapper<${type}DO> buildQueryWrapper(${type}QueryRequest request);
}

View File

@@ -115,6 +115,13 @@ export function get${vue.featureEntity}Page(request: ${vue.featureEntity}QueryRe
return axios.post<DataGrid<${vue.featureEntity}QueryResponse>>('/${package.ModuleName}/${typeHyphen}/query', request);
}
/**
* $apiComment.queryCount
*/
export function get${vue.featureEntity}Count(request: ${vue.featureEntity}QueryRequest) {
return axios.post<number>('/${package.ModuleName}/${typeHyphen}/count', request);
}
/**
* $apiComment.deleteById
*/

View File

@@ -1,7 +1,7 @@
<template>
<card-list v-model:searchValue="formModel.searchValue"
search-input-placeholder="输入搜索值"
create-card-position="head"
:create-card-position="false"
:loading="loading"
:field-config="fieldConfig"
:list="list"
@@ -68,7 +68,7 @@
<template #extra="{ record }">
<a-space>
<!-- 更多操作 -->
<a-dropdown trigger="hover">
<a-dropdown trigger="hover" :popup-max-height="false">
<icon-more class="card-extra-icon" />
<template #content>
<!-- 修改 -->

View File

@@ -98,6 +98,13 @@ public class SecurityUtils {
return loginUser != null ? loginUser.getTimestamp() : null;
}
/**
* 清空用户上下文
*/
public static void clearAuthentication() {
SecurityContextHolder.getContext().setAuthentication(null);
}
/**
* 设置当前用户
*
@@ -107,7 +114,9 @@ public class SecurityUtils {
public static void setLoginUser(LoginUser loginUser, HttpServletRequest request) {
// 创建 authentication
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(loginUser, null, Collections.emptyList());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
if (request != null) {
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
}
// 设置上下文
SecurityContextHolder.getContext().setAuthentication(authentication);
}

View File

@@ -1,8 +1,6 @@
package com.orion.visor.framework.web.core.filter;
import com.orion.lang.id.UUIds;
import com.orion.visor.framework.common.meta.TraceIdHolder;
import org.slf4j.MDC;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
@@ -23,21 +21,17 @@ public class TraceIdFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
try {
// 获 traceId
String traceId = UUIds.random32();
// 设置应用上下文
// 获 traceId
String traceId = TraceIdHolder.createTraceId();
// 设置 traceId 上下文
TraceIdHolder.set(traceId);
// 设置日志上下文
MDC.put(TraceIdHolder.TRACE_ID_MDC, traceId);
// 设置响应头
response.setHeader(TraceIdHolder.TRACE_ID_HEADER, traceId);
// 执行请求
filterChain.doFilter(request, response);
} finally {
// 清理应用上下文
// 清空 traceId 上下文
TraceIdHolder.remove();
// 清理日志上下文
MDC.clear();
}
}

View File

@@ -33,5 +33,5 @@ management:
mybatis-plus:
configuration:
# 日志打印
# sql 日志打印
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

View File

@@ -82,13 +82,13 @@ spring:
instanceName: quartzScheduler
jobStore:
# 持久化配置
class: org.quartz.impl.jdbcjobstore.JobStoreTX
class: org.springframework.scheduling.quartz.LocalDataSourceJobStore
driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
useProperties: false
tablePrefix: QRTZ_
misfireThreshold: 60000
clusterCheckinInterval: 5000
isClustered: true
isClustered: false
# 连接池
threadPool:
class: org.quartz.simpl.SimpleThreadPool
@@ -167,6 +167,8 @@ app:
allow-refresh: true
# 凭证续签最大次数
max-refresh-count: 3
# 登录失败发送站内信阈值
login-failed-send-threshold: 3
# 登录失败锁定次数
login-failed-lock-count: 5
# 登录失败锁定时间 (分)

View File

@@ -5,6 +5,7 @@ import com.orion.visor.module.asset.handler.host.terminal.TerminalMessageDispatc
import com.orion.visor.module.asset.handler.host.transfer.TransferMessageDispatcher;
import com.orion.visor.module.asset.interceptor.ExecLogTailInterceptor;
import com.orion.visor.module.asset.interceptor.TerminalAccessInterceptor;
import com.orion.visor.module.asset.interceptor.TerminalTransferInterceptor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
@@ -28,6 +29,9 @@ public class AssetWebSocketConfiguration implements WebSocketConfigurer {
@Resource
private TerminalAccessInterceptor terminalAccessInterceptor;
@Resource
private TerminalTransferInterceptor terminalTransferInterceptor;
@Resource
private ExecLogTailInterceptor execLogTailInterceptor;
@@ -42,13 +46,13 @@ public class AssetWebSocketConfiguration implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
// 终端
// 终端会话
registry.addHandler(terminalMessageDispatcher, prefix + "/host/terminal/{accessToken}")
.addInterceptors(terminalAccessInterceptor)
.setAllowedOrigins("*");
// 文件传输
registry.addHandler(transferMessageDispatcher, prefix + "/host/transfer/{accessToken}")
.addInterceptors(terminalAccessInterceptor)
registry.addHandler(transferMessageDispatcher, prefix + "/host/transfer/{transferToken}")
.addInterceptors(terminalTransferInterceptor)
.setAllowedOrigins("*");
// 执行日志
registry.addHandler(execLogTailHandler, prefix + "/exec/log/{token}")

View File

@@ -3,6 +3,7 @@ package com.orion.visor.module.asset.controller;
import com.orion.visor.framework.biz.operator.log.core.annotation.OperatorLog;
import com.orion.visor.framework.log.core.annotation.IgnoreLog;
import com.orion.visor.framework.log.core.enums.IgnoreLogMode;
import com.orion.visor.framework.web.core.annotation.DemoDisableApi;
import com.orion.visor.framework.web.core.annotation.RestWrapper;
import com.orion.visor.module.asset.define.operator.HostGroupOperatorType;
import com.orion.visor.module.asset.define.operator.HostIdentityOperatorType;
@@ -43,6 +44,7 @@ public class AssetDataGrantServiceController {
@Resource
private AssetAuthorizedDataService assetAuthorizedDataService;
@DemoDisableApi
@OperatorLog(HostGroupOperatorType.GRANT)
@PutMapping("/grant-host-group")
@Operation(summary = "主机分组授权")
@@ -60,6 +62,7 @@ public class AssetDataGrantServiceController {
return assetAuthorizedDataService.getAuthorizedDataRelId(DataPermissionTypeEnum.HOST_GROUP, request);
}
@DemoDisableApi
@OperatorLog(HostKeyOperatorType.GRANT)
@PutMapping("/grant-host-key")
@Operation(summary = "主机密钥授权")
@@ -77,6 +80,7 @@ public class AssetDataGrantServiceController {
return assetAuthorizedDataService.getAuthorizedDataRelId(DataPermissionTypeEnum.HOST_KEY, request);
}
@DemoDisableApi
@OperatorLog(HostIdentityOperatorType.GRANT)
@PutMapping("/grant-host-identity")
@Operation(summary = "主机身份授权")

View File

@@ -10,6 +10,7 @@ import com.orion.visor.framework.security.core.utils.SecurityUtils;
import com.orion.visor.framework.web.core.annotation.RestWrapper;
import com.orion.visor.module.asset.define.operator.ExecCommandLogOperatorType;
import com.orion.visor.module.asset.entity.request.exec.ExecInterruptRequest;
import com.orion.visor.module.asset.entity.request.exec.ExecLogClearRequest;
import com.orion.visor.module.asset.entity.request.exec.ExecLogQueryRequest;
import com.orion.visor.module.asset.entity.request.exec.ExecLogTailRequest;
import com.orion.visor.module.asset.entity.vo.ExecHostLogVO;
@@ -97,6 +98,14 @@ public class ExecCommandLogController {
return execLogService.getExecHistory(request);
}
@PostMapping("/count")
@Operation(summary = "查询批量执行日志数量")
@PreAuthorize("@ss.hasPermission('asset:exec-command-log:query')")
public Long getExecCommandLogCount(@Validated @RequestBody ExecLogQueryRequest request) {
request.setSource(SOURCE);
return execLogService.queryExecLogCount(request);
}
@OperatorLog(ExecCommandLogOperatorType.DELETE)
@DeleteMapping("/delete")
@Operation(summary = "删除批量执行日志")
@@ -124,19 +133,11 @@ public class ExecCommandLogController {
return execHostLogService.deleteExecHostLogById(id);
}
@PostMapping("/query-count")
@Operation(summary = "查询批量执行日志数量")
@PreAuthorize("@ss.hasPermission('asset:exec-command-log:management:clear')")
public Long getExecCommandLogCount(@RequestBody ExecLogQueryRequest request) {
request.setSource(SOURCE);
return execLogService.queryExecLogCount(request);
}
@OperatorLog(ExecCommandLogOperatorType.CLEAR)
@PostMapping("/clear")
@Operation(summary = "清空批量执行日志")
@PreAuthorize("@ss.hasPermission('asset:exec-command-log:management:clear')")
public Integer clearExecCommandLog(@RequestBody ExecLogQueryRequest request) {
public Integer clearExecCommandLog(@Validated @RequestBody ExecLogClearRequest request) {
request.setSource(SOURCE);
return execLogService.clearExecLog(request);
}
@@ -178,4 +179,3 @@ public class ExecCommandLogController {
}
}

View File

@@ -5,6 +5,7 @@ import com.orion.visor.framework.biz.operator.log.core.annotation.OperatorLog;
import com.orion.visor.framework.common.validator.group.Page;
import com.orion.visor.framework.log.core.annotation.IgnoreLog;
import com.orion.visor.framework.log.core.enums.IgnoreLogMode;
import com.orion.visor.framework.web.core.annotation.DemoDisableApi;
import com.orion.visor.framework.web.core.annotation.RestWrapper;
import com.orion.visor.module.asset.define.operator.ExecJobOperatorType;
import com.orion.visor.module.asset.entity.request.exec.*;
@@ -39,6 +40,7 @@ public class ExecJobController {
@Resource
private ExecJobService execJobService;
@DemoDisableApi
@OperatorLog(ExecJobOperatorType.CREATE)
@PostMapping("/create")
@Operation(summary = "创建计划任务")
@@ -47,6 +49,7 @@ public class ExecJobController {
return execJobService.createExecJob(request);
}
@DemoDisableApi
@OperatorLog(ExecJobOperatorType.UPDATE)
@PutMapping("/update")
@Operation(summary = "更新计划任务")
@@ -55,6 +58,7 @@ public class ExecJobController {
return execJobService.updateExecJobById(request);
}
@DemoDisableApi
@OperatorLog(ExecJobOperatorType.UPDATE_STATUS)
@PutMapping("/update-status")
@Operation(summary = "更新计划任务状态")
@@ -88,6 +92,7 @@ public class ExecJobController {
return execJobService.getExecJobPage(request);
}
@DemoDisableApi
@OperatorLog(ExecJobOperatorType.DELETE)
@DeleteMapping("/delete")
@Operation(summary = "删除计划任务")
@@ -97,6 +102,7 @@ public class ExecJobController {
return execJobService.deleteExecJobById(id);
}
@DemoDisableApi
@OperatorLog(ExecJobOperatorType.DELETE)
@DeleteMapping("/batch-delete")
@Operation(summary = "批量删除计划任务")

View File

@@ -9,6 +9,7 @@ import com.orion.visor.framework.log.core.enums.IgnoreLogMode;
import com.orion.visor.framework.web.core.annotation.RestWrapper;
import com.orion.visor.module.asset.define.operator.ExecJobLogOperatorType;
import com.orion.visor.module.asset.entity.request.exec.ExecInterruptRequest;
import com.orion.visor.module.asset.entity.request.exec.ExecLogClearRequest;
import com.orion.visor.module.asset.entity.request.exec.ExecLogQueryRequest;
import com.orion.visor.module.asset.entity.request.exec.ExecLogTailRequest;
import com.orion.visor.module.asset.entity.vo.ExecHostLogVO;
@@ -86,6 +87,14 @@ public class ExecJobLogController {
return execLogService.getExecLogStatus(idList, SOURCE);
}
@PostMapping("/count")
@Operation(summary = "查询计划任务日志数量")
@PreAuthorize("@ss.hasPermission('asset:exec-job-log:query')")
public Long getExecJobLogCount(@Validated @RequestBody ExecLogQueryRequest request) {
request.setSource(SOURCE);
return execLogService.queryExecLogCount(request);
}
@OperatorLog(ExecJobLogOperatorType.DELETE)
@DeleteMapping("/delete")
@Operation(summary = "删除计划任务日志")
@@ -113,19 +122,11 @@ public class ExecJobLogController {
return execHostLogService.deleteExecHostLogById(id);
}
@PostMapping("/query-count")
@Operation(summary = "查询计划任务日志数量")
@PreAuthorize("@ss.hasPermission('asset:exec-job-log:management:clear')")
public Long getExecJobLogCount(@RequestBody ExecLogQueryRequest request) {
request.setSource(SOURCE);
return execLogService.queryExecLogCount(request);
}
@OperatorLog(ExecJobLogOperatorType.CLEAR)
@PostMapping("/clear")
@Operation(summary = "清空计划任务日志")
@PreAuthorize("@ss.hasPermission('asset:exec-job-log:management:clear')")
public Integer clearExecJobLog(@RequestBody ExecLogQueryRequest request) {
public Integer clearExecJobLog(@Validated @RequestBody ExecLogClearRequest request) {
request.setSource(SOURCE);
return execLogService.clearExecLog(request);
}
@@ -167,4 +168,3 @@ public class ExecJobLogController {
}
}

View File

@@ -5,6 +5,7 @@ import com.orion.visor.framework.biz.operator.log.core.annotation.OperatorLog;
import com.orion.visor.framework.common.validator.group.Page;
import com.orion.visor.framework.log.core.annotation.IgnoreLog;
import com.orion.visor.framework.log.core.enums.IgnoreLogMode;
import com.orion.visor.framework.web.core.annotation.DemoDisableApi;
import com.orion.visor.framework.web.core.annotation.RestWrapper;
import com.orion.visor.module.asset.define.operator.ExecTemplateOperatorType;
import com.orion.visor.module.asset.entity.request.exec.ExecTemplateCreateRequest;
@@ -41,6 +42,7 @@ public class ExecTemplateController {
@Resource
private ExecTemplateService execTemplateService;
@DemoDisableApi
@OperatorLog(ExecTemplateOperatorType.CREATE)
@PostMapping("/create")
@Operation(summary = "创建执行模板")
@@ -49,6 +51,7 @@ public class ExecTemplateController {
return execTemplateService.createExecTemplate(request);
}
@DemoDisableApi
@OperatorLog(ExecTemplateOperatorType.UPDATE)
@PutMapping("/update")
@Operation(summary = "更新执行模板")
@@ -83,6 +86,7 @@ public class ExecTemplateController {
return execTemplateService.getExecTemplatePage(request);
}
@DemoDisableApi
@OperatorLog(ExecTemplateOperatorType.DELETE)
@DeleteMapping("/delete")
@Operation(summary = "删除执行模板")
@@ -92,6 +96,7 @@ public class ExecTemplateController {
return execTemplateService.deleteExecTemplateById(id);
}
@DemoDisableApi
@OperatorLog(ExecTemplateOperatorType.DELETE)
@DeleteMapping("/batch-delete")
@Operation(summary = "批量删除执行模板")

View File

@@ -9,6 +9,7 @@ import com.orion.visor.framework.log.core.enums.IgnoreLogMode;
import com.orion.visor.framework.web.core.annotation.DemoDisableApi;
import com.orion.visor.framework.web.core.annotation.RestWrapper;
import com.orion.visor.module.asset.define.operator.HostConnectLogOperatorType;
import com.orion.visor.module.asset.entity.request.host.HostConnectLogClearRequest;
import com.orion.visor.module.asset.entity.request.host.HostConnectLogQueryRequest;
import com.orion.visor.module.asset.entity.vo.HostConnectLogVO;
import com.orion.visor.module.asset.service.HostConnectLogService;
@@ -49,6 +50,13 @@ public class HostConnectLogController {
return hostConnectLogService.getHostConnectLogPage(request);
}
@PostMapping("/count")
@Operation(summary = "查询主机连接日志数量")
@PreAuthorize("@ss.hasPermission('asset:host-connect-log:management:query')")
public Long getHostConnectLogCount(@Validated @RequestBody HostConnectLogQueryRequest request) {
return hostConnectLogService.getHostConnectLogCount(request);
}
@IgnoreLog(IgnoreLogMode.RET)
@PostMapping("/session")
@Operation(summary = "查询全部主机连接会话")
@@ -73,18 +81,11 @@ public class HostConnectLogController {
return hostConnectLogService.deleteHostConnectLog(idList);
}
@PostMapping("/query-count")
@Operation(summary = "查询主机连接日志数量")
@PreAuthorize("@ss.hasPermission('asset:host-connect-log:management:clear')")
public Long getHostConnectLogCount(@RequestBody HostConnectLogQueryRequest request) {
return hostConnectLogService.getHostConnectLogCount(request);
}
@OperatorLog(HostConnectLogOperatorType.CLEAR)
@PostMapping("/clear")
@Operation(summary = "清空主机连接日志")
@PreAuthorize("@ss.hasPermission('asset:host-connect-log:management:clear')")
public Integer clearHostConnectLog(@RequestBody HostConnectLogQueryRequest request) {
public Integer clearHostConnectLog(@Validated @RequestBody HostConnectLogClearRequest request) {
return hostConnectLogService.clearHostConnectLog(request);
}

View File

@@ -98,7 +98,7 @@ public class HostController {
@IgnoreLog(IgnoreLogMode.RET)
@GetMapping("/list")
@Operation(summary = "查询主机")
@Parameter(name = "type", description = "type", required = false)
@Parameter(name = "type", description = "type")
@PreAuthorize("@ss.hasPermission('asset:host:query')")
public List<HostVO> getHostList(@RequestParam(value = "type", required = false) String type) {
return hostService.getHostList(type);
@@ -112,6 +112,14 @@ public class HostController {
return hostService.getHostPage(request);
}
@DemoDisableApi
@PostMapping("/count")
@Operation(summary = "查询主机数量")
@PreAuthorize("@ss.hasPermission('asset:host:query')")
public Long getHostExportCount(@Validated @RequestBody HostQueryRequest request) {
return hostService.getHostCount(request);
}
@DemoDisableApi
@OperatorLog(HostOperatorType.DELETE)
@DeleteMapping("/delete")

View File

@@ -49,5 +49,12 @@ public class HostTerminalController {
return hostTerminalService.getTerminalAccessToken();
}
@GetMapping("/transfer")
@Operation(summary = "获取主机终端 transferToken")
@PreAuthorize("@ss.hasPermission('asset:host-terminal:access')")
public String getTerminalTransferToken() {
return hostTerminalService.getTerminalTransferToken();
}
}

View File

@@ -7,6 +7,7 @@ import com.orion.visor.framework.log.core.annotation.IgnoreLog;
import com.orion.visor.framework.log.core.enums.IgnoreLogMode;
import com.orion.visor.framework.web.core.annotation.RestWrapper;
import com.orion.visor.module.asset.define.operator.UploadTaskOperatorType;
import com.orion.visor.module.asset.entity.request.upload.UploadTaskClearRequest;
import com.orion.visor.module.asset.entity.request.upload.UploadTaskCreateRequest;
import com.orion.visor.module.asset.entity.request.upload.UploadTaskQueryRequest;
import com.orion.visor.module.asset.entity.request.upload.UploadTaskRequest;
@@ -94,6 +95,13 @@ public class UploadTaskController {
return uploadTaskService.getUploadTaskStatus(idList, queryFiles);
}
@PostMapping("/count")
@Operation(summary = "查询上传任务数量")
@PreAuthorize("@ss.hasPermission('asset:upload-task:query')")
public Long getUploadTaskCount(@RequestBody UploadTaskQueryRequest request) {
return uploadTaskService.getUploadTaskCount(request);
}
@OperatorLog(UploadTaskOperatorType.DELETE)
@DeleteMapping("/delete")
@Operation(summary = "删除上传任务")
@@ -112,18 +120,11 @@ public class UploadTaskController {
return uploadTaskService.deleteUploadTaskByIdList(idList);
}
@PostMapping("/query-count")
@Operation(summary = "查询上传任务数量")
@PreAuthorize("@ss.hasPermission('asset:upload-task:management:clear')")
public Long getUploadTaskCount(@RequestBody UploadTaskQueryRequest request) {
return uploadTaskService.getUploadTaskCount(request);
}
@OperatorLog(UploadTaskOperatorType.CLEAR)
@PostMapping("/clear")
@Operation(summary = "清空上传任务")
@PreAuthorize("@ss.hasPermission('asset:upload-task:management:clear')")
public Integer clearUploadTask(@RequestBody UploadTaskQueryRequest request) {
public Integer clearUploadTask(@Validated @RequestBody UploadTaskClearRequest request) {
return uploadTaskService.clearUploadTask(request);
}

View File

@@ -4,6 +4,7 @@ import com.orion.lang.define.cache.key.CacheKeyBuilder;
import com.orion.lang.define.cache.key.CacheKeyDefine;
import com.orion.lang.define.cache.key.struct.RedisCacheStruct;
import com.orion.visor.module.asset.entity.dto.HostTerminalAccessDTO;
import com.orion.visor.module.asset.entity.dto.HostTerminalTransferDTO;
import java.util.concurrent.TimeUnit;
@@ -24,4 +25,12 @@ public interface HostTerminalCacheKeyDefine {
.timeout(3, TimeUnit.MINUTES)
.build();
CacheKeyDefine HOST_TERMINAL_TRANSFER = new CacheKeyBuilder()
.key("host:terminal:transfer:{}")
.desc("主机终端传输token ${token}")
.type(HostTerminalTransferDTO.class)
.struct(RedisCacheStruct.STRING)
.timeout(3, TimeUnit.MINUTES)
.build();
}

View File

@@ -31,7 +31,7 @@ public class HostOperatorType extends InitializingOperatorTypes {
return new OperatorType[]{
new OperatorType(L, CREATE, "创建主机 <sb>${name}</sb>"),
new OperatorType(L, UPDATE, "修改主机 <sb>${name}</sb>"),
new OperatorType(H, DELETE, "删除主机 <sb>${name}</sb>"),
new OperatorType(H, DELETE, "删除主机 <sb>${count}</sb>"),
new OperatorType(M, UPDATE_STATUS, "修改主机状态 <sb>${name}</sb> - <sb>${status}</sb>"),
new OperatorType(M, UPDATE_CONFIG, "修改主机配置 <sb>${name}</sb>"),
};

View File

@@ -42,10 +42,6 @@ public class CommandSnippetDO extends BaseDO {
@TableField("name")
private String name;
@Schema(description = "触发前缀")
@TableField("prefix")
private String prefix;
@Schema(description = "代码片段")
@TableField("command")
private String command;

View File

@@ -34,9 +34,6 @@ public class CommandSnippetCacheDTO implements LongCacheIdModel, Serializable {
@Schema(description = "名称")
private String name;
@Schema(description = "触发前缀")
private String prefix;
@Schema(description = "代码片段")
private String command;

View File

@@ -0,0 +1,31 @@
package com.orion.visor.module.asset.entity.dto;
import com.orion.visor.framework.desensitize.core.annotation.DesensitizeObject;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 主机终端传输参数
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023/12/26 15:47
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@DesensitizeObject
@Schema(name = "HostTerminalTransferDTO", description = "主机终端传输参数")
public class HostTerminalTransferDTO {
@Schema(description = "userId")
private Long userId;
@Schema(description = "username")
private String username;
}

View File

@@ -0,0 +1,30 @@
package com.orion.visor.module.asset.entity.request.exec;
import com.orion.visor.framework.common.entity.DataClearRequest;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
/**
* 批量执行日志 清理请求对象
*
* @author Jiahang Li
* @version 1.0.1
* @since 2024-3-11 11:31
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Schema(name = "ExecLogClearRequest", description = "批量执行日志 清理请求对象")
public class ExecLogClearRequest extends ExecLogQueryRequest implements DataClearRequest {
@NotNull
@Min(value = 1)
@Max(value = 1000)
@Schema(description = "清理数量限制")
private Integer limit;
}

View File

@@ -0,0 +1,30 @@
package com.orion.visor.module.asset.entity.request.host;
import com.orion.visor.framework.common.entity.DataClearRequest;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
/**
* 主机连接日志 清理请求对象
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023-12-26 22:09
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Schema(name = "HostConnectLogClearRequest", description = "主机连接日志 清理请求对象")
public class HostConnectLogClearRequest extends HostConnectLogQueryRequest implements DataClearRequest {
@NotNull
@Min(value = 1)
@Max(value = 2000)
@Schema(description = "清理数量限制")
private Integer limit;
}

View File

@@ -2,9 +2,11 @@ package com.orion.visor.module.asset.entity.request.host;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.orion.visor.framework.common.entity.PageRequest;
import com.orion.visor.framework.common.validator.group.Id;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.util.Date;
import java.util.List;
@@ -24,6 +26,7 @@ import java.util.List;
@Schema(name = "HostConnectLogQueryRequest", description = "主机连接日志 查询请求对象")
public class HostConnectLogQueryRequest extends PageRequest {
@NotNull(groups = Id.class)
@Schema(description = "id")
private Long id;

View File

@@ -5,8 +5,9 @@ import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.validator.constraints.Range;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
import java.io.Serializable;
@@ -45,7 +46,8 @@ public class HostCreateRequest implements Serializable {
@Schema(description = "主机地址")
private String address;
@Range(min = 1, max = 65535)
@Min(value = 1)
@Max(value = 65535)
@Schema(description = "主机端口")
private Integer port;

View File

@@ -5,11 +5,8 @@ import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.validator.constraints.Range;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import javax.validation.constraints.*;
import java.io.Serializable;
import java.util.List;
@@ -46,7 +43,9 @@ public class HostUpdateRequest implements Serializable {
@Schema(description = "主机地址")
private String address;
@Range(min = 1, max = 65535)
@NotNull
@Min(value = 1)
@Max(value = 65535)
@Schema(description = "主机端口")
private Integer port;

View File

@@ -0,0 +1,30 @@
package com.orion.visor.module.asset.entity.request.upload;
import com.orion.visor.framework.common.entity.DataClearRequest;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
/**
* 上传任务 清理请求对象
*
* @author Jiahang Li
* @version 1.0.7
* @since 2024-5-7 22:15
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Schema(name = "UploadTaskClearRequest", description = "上传任务 清理请求对象")
public class UploadTaskClearRequest extends UploadTaskQueryRequest implements DataClearRequest {
@NotNull
@Min(value = 1)
@Max(value = 2000)
@Schema(description = "清理数量限制")
private Integer limit;
}

View File

@@ -33,9 +33,6 @@ public class CommandSnippetVO implements Serializable {
@Schema(description = "名称")
private String name;
@Schema(description = "触发前缀")
private String prefix;
@Schema(description = "代码片段")
private String command;

View File

@@ -10,17 +10,17 @@ package com.orion.visor.module.asset.enums;
public enum HostExtraSshAuthTypeEnum {
/**
* 默认证方式
* 默认证方式
*/
DEFAULT,
/**
* 自定义密钥
* 自定义密钥
*/
CUSTOM_KEY,
/**
* 自定义身份
* 自定义身份
*/
CUSTOM_IDENTITY,
@@ -28,14 +28,14 @@ public enum HostExtraSshAuthTypeEnum {
public static HostExtraSshAuthTypeEnum of(String type) {
if (type == null) {
return null;
return DEFAULT;
}
for (HostExtraSshAuthTypeEnum value : values()) {
if (value.name().equals(type)) {
return value;
}
}
return null;
return DEFAULT;
}
}

View File

@@ -1,7 +1,7 @@
package com.orion.visor.module.asset.enums;
/**
* 主机证类型 - ssh
* 主机证类型 - ssh
*
* @author Jiahang Li
* @version 1.0.0
@@ -10,17 +10,17 @@ package com.orion.visor.module.asset.enums;
public enum HostSshAuthTypeEnum {
/**
* 密码
* 密码
*/
PASSWORD,
/**
* 密钥
* 密钥
*/
KEY,
/**
* 身份
* 身份
*/
IDENTITY,
@@ -28,14 +28,14 @@ public enum HostSshAuthTypeEnum {
public static HostSshAuthTypeEnum of(String type) {
if (type == null) {
return null;
return PASSWORD;
}
for (HostSshAuthTypeEnum value : values()) {
if (value.name().equals(type)) {
return value;
}
}
return null;
return PASSWORD;
}
}

View File

@@ -30,14 +30,14 @@ public enum HostSshOsTypeEnum {
public static HostSshOsTypeEnum of(String type) {
if (type == null) {
return null;
return LINUX;
}
for (HostSshOsTypeEnum value : values()) {
if (value.name().equals(type)) {
return value;
}
}
return null;
return LINUX;
}
}

View File

@@ -6,11 +6,8 @@ import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.validator.constraints.Range;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import javax.validation.constraints.*;
/**
* 主机 SSH 配置
@@ -64,7 +61,8 @@ public class HostSshConfigModel implements GenericsDataModel, UpdatePasswordActi
* 连接超时时间
*/
@NotNull
@Range(min = 0, max = 100000)
@Min(value = 1)
@Max(value = 100000)
private Integer connectTimeout;
/**

View File

@@ -55,10 +55,6 @@ public class HostSshConfigStrategy extends AbstractGenericsDataStrategy<HostSshC
@Override
protected void preValid(HostSshConfigModel model) {
// 验证认证类型
Valid.valid(HostSshAuthTypeEnum::of, model.getAuthType());
// 验证系统版本
Valid.valid(HostSshOsTypeEnum::of, model.getOsType());
// 验证编码格式
this.validCharset(model.getCharset());
this.validCharset(model.getFileNameCharset());

View File

@@ -4,7 +4,6 @@ import com.alibaba.fastjson.JSON;
import com.orion.lang.exception.AuthenticationException;
import com.orion.lang.exception.ConnectionRuntimeException;
import com.orion.lang.exception.SftpException;
import com.orion.lang.exception.argument.InvalidArgumentException;
import com.orion.lang.support.timeout.TimeoutChecker;
import com.orion.lang.support.timeout.TimeoutEndpoint;
import com.orion.lang.utils.Booleans;
@@ -16,6 +15,7 @@ import com.orion.net.host.SessionStore;
import com.orion.net.host.sftp.SftpExecutor;
import com.orion.net.host.ssh.command.CommandExecutor;
import com.orion.spring.SpringHolder;
import com.orion.visor.framework.common.constant.ErrorMessage;
import com.orion.visor.framework.common.file.FileClient;
import com.orion.visor.module.asset.dao.ExecHostLogDAO;
import com.orion.visor.module.asset.entity.domain.ExecHostLogDO;
@@ -289,17 +289,25 @@ public abstract class BaseExecCommandHandler implements IExecCommandHandler {
* @return errorMessage
*/
protected String getErrorMessage(Exception ex) {
if (ex == null) {
return null;
}
String message;
if (ex instanceof InvalidArgumentException || ex instanceof IllegalArgumentException) {
if (ErrorMessage.isBizException(ex)) {
// 业务异常
message = ex.getMessage();
} else if (ex instanceof ConnectionRuntimeException) {
message = "连接失败";
// 连接异常
message = ErrorMessage.CONNECT_ERROR;
} else if (ex instanceof AuthenticationException) {
message = "认证失败";
// 认证异常
message = ErrorMessage.AUTH_ERROR;
} else if (ex instanceof SftpException) {
message = "脚本上传失败";
// 上传异常
message = ErrorMessage.SCRIPT_UPLOAD_ERROR;
} else {
message = "执行失败";
// 其他异常
message = ErrorMessage.EXEC_ERROR;
}
return Strings.retain(message, 250);
}

View File

@@ -1,6 +1,6 @@
package com.orion.visor.module.asset.handler.host.exec.log;
import com.orion.visor.framework.common.annotation.Keep;
import com.orion.lang.annotation.Keep;
import com.orion.visor.framework.common.constant.ExtraFieldConst;
import com.orion.visor.framework.common.file.FileClient;
import com.orion.visor.framework.websocket.core.utils.WebSockets;

View File

@@ -5,7 +5,9 @@ import com.orion.lang.exception.argument.InvalidArgumentException;
import com.orion.lang.utils.Exceptions;
import com.orion.lang.utils.Strings;
import com.orion.net.host.SessionHolder;
import com.orion.net.host.SessionLogger;
import com.orion.net.host.SessionStore;
import com.orion.visor.framework.common.constant.AppConst;
import com.orion.visor.framework.common.constant.Const;
import com.orion.visor.framework.common.utils.CryptoUtils;
import com.orion.visor.module.asset.entity.dto.HostTerminalConnectDTO;
@@ -40,7 +42,10 @@ public class SessionStores {
CURRENT_ADDRESS.set(address);
// 创建会话
SessionHolder sessionHolder = SessionHolder.create();
sessionHolder.setLogger(SessionLogger.INFO);
SessionStore session = createSessionStore(conn, sessionHolder);
// 设置版本
session.getSession().setClientVersion("SSH-2.0-ORION_VISOR_V" + AppConst.VERSION);
// 连接
session.connect();
log.info("SessionStores-open-success hostId: {}, address: {}, username: {}", hostId, address, username);
@@ -48,7 +53,7 @@ public class SessionStores {
} catch (Exception e) {
String message = e.getMessage();
log.error("SessionStores-open-error hostId: {}, address: {}, username: {}, message: {}", hostId, address, username, message, e);
throw Exceptions.runtime(getErrorMessage(e), e);
throw Exceptions.app(getErrorMessage(e), e);
} finally {
CURRENT_ADDRESS.remove();
}
@@ -84,7 +89,10 @@ public class SessionStores {
SessionStore session = sessionHolder.getSession(conn.getHostAddress(), conn.getHostPort(), conn.getUsername());
// 使用密码认证
if (!useKey) {
session.password(CryptoUtils.decryptAsString(conn.getPassword()));
String password = conn.getPassword();
if (!Strings.isEmpty(password)) {
session.password(CryptoUtils.decryptAsString(password));
}
}
// 超时时间
session.timeout(conn.getTimeout());

View File

@@ -131,9 +131,9 @@ public enum InputTypeEnum {
* SFTP 修改文件权限
*/
SFTP_CHMOD("cm",
SftpChangeModHandler.class,
SftpChangeModeHandler.class,
new String[]{"type", "sessionId", "path", "mod"},
SftpChangeModRequest.class,
SftpChangeModeRequest.class,
true),
/**

View File

@@ -97,13 +97,8 @@ public abstract class AbstractTerminalHandler<T extends TerminalBasePayload> imp
* @return msg
*/
protected String getErrorMessage(Exception ex) {
if (ex == null) {
return null;
}
if (ex instanceof InvalidArgumentException || ex instanceof IllegalArgumentException) {
return ex.getMessage();
}
return ErrorMessage.OPERATE_ERROR;
// 获取错误信息
return ErrorMessage.getErrorMessage(ex, ErrorMessage.OPERATE_ERROR);
}
}

View File

@@ -5,7 +5,7 @@ import com.orion.visor.framework.biz.operator.log.core.utils.OperatorLogs;
import com.orion.visor.framework.common.enums.BooleanBit;
import com.orion.visor.module.asset.define.operator.HostTerminalOperatorType;
import com.orion.visor.module.asset.handler.host.terminal.enums.OutputTypeEnum;
import com.orion.visor.module.asset.handler.host.terminal.model.request.SftpChangeModRequest;
import com.orion.visor.module.asset.handler.host.terminal.model.request.SftpChangeModeRequest;
import com.orion.visor.module.asset.handler.host.terminal.model.response.SftpBaseResponse;
import com.orion.visor.module.asset.handler.host.terminal.session.ISftpSession;
import lombok.extern.slf4j.Slf4j;
@@ -23,24 +23,24 @@ import java.util.Map;
*/
@Slf4j
@Component
public class SftpChangeModHandler extends AbstractTerminalHandler<SftpChangeModRequest> {
public class SftpChangeModeHandler extends AbstractTerminalHandler<SftpChangeModeRequest> {
@Override
public void handle(WebSocketSession channel, SftpChangeModRequest payload) {
public void handle(WebSocketSession channel, SftpChangeModeRequest payload) {
long startTime = System.currentTimeMillis();
// 获取会话
String sessionId = payload.getSessionId();
ISftpSession session = hostTerminalManager.getSession(channel.getId(), sessionId);
String path = payload.getPath();
Integer mod = payload.getMod();
log.info("SftpChangeModHandler-handle start sessionId: {}, path: {}, mod: {}", sessionId, path, mod);
log.info("SftpChangeModeHandler-handle start sessionId: {}, path: {}, mod: {}", sessionId, path, mod);
Exception ex = null;
// 修改权限
try {
session.chmod(path, mod);
log.info("SftpChangeModHandler-handle success sessionId: {}, path: {}, mod: {}", sessionId, path, mod);
log.info("SftpChangeModeHandler-handle success sessionId: {}, path: {}, mod: {}", sessionId, path, mod);
} catch (Exception e) {
log.error("SftpChangeModHandler-handle error sessionId: {}", sessionId, e);
log.error("SftpChangeModeHandler-handle error sessionId: {}", sessionId, e);
ex = e;
}
// 返回

View File

@@ -65,13 +65,15 @@ public class TerminalConnectHandler extends AbstractTerminalHandler<TerminalConn
// 移除会话连接信息
channel.getAttributes().remove(sessionId);
Exception ex = null;
ITerminalSession session = null;
try {
// 连接主机
ITerminalSession session = this.connect(sessionId, connect, channel, payload);
session = this.connect(sessionId, connect, channel, payload);
// 添加会话到 manager
hostTerminalManager.addSession(session);
} catch (Exception e) {
ex = e;
Streams.close(session);
// 修改连接状态为失败
Map<String, Object> extra = Maps.newMap(4);
extra.put(ExtraFieldConst.ERROR_MESSAGE, this.getConnectErrorMessage(e));

View File

@@ -20,7 +20,7 @@ import lombok.experimental.SuperBuilder;
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class SftpChangeModRequest extends SftpBaseRequest {
public class SftpChangeModeRequest extends SftpBaseRequest {
/**
* 10进制的8进制 权限

View File

@@ -12,7 +12,6 @@ import com.orion.visor.framework.common.constant.Const;
import com.orion.visor.framework.common.utils.Valid;
import com.orion.visor.module.asset.handler.host.terminal.model.TerminalConfig;
import com.orion.visor.module.asset.handler.host.terminal.model.response.SftpFileVO;
import com.orion.visor.module.asset.utils.SftpUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.socket.WebSocketSession;
@@ -84,9 +83,7 @@ public class SftpSession extends TerminalSession implements ISftpSession {
public void move(String source, String target) {
source = Valid.checkNormalize(source);
// 移动
SftpUtils.move(executor, source, target);
// FIXME kit
// executor.move(source, target);
executor.move(source, target);
}
@Override

View File

@@ -37,8 +37,11 @@ public class DownloadSession extends TransferSession implements StreamingRespons
protected InputStream inputStream;
private Long fileSize;
public DownloadSession(HostTerminalConnectDTO connectInfo, SessionStore sessionStore, WebSocketSession channel) {
super(connectInfo, sessionStore, channel);
this.fileSize = 0L;
}
@Override
@@ -53,7 +56,9 @@ public class DownloadSession extends TransferSession implements StreamingRespons
// 检查文件是否存在
SftpFile file = executor.getFile(path);
Valid.notNull(file, ErrorMessage.FILE_ABSENT);
if (file.getSize() == 0L) {
// 验证非文件夹
Valid.isTrue(!file.isDirectory(), ErrorMessage.UNABLE_DOWNLOAD_FOLDER);
if ((this.fileSize = file.getSize()) == 0L) {
// 文件为空
log.info("DownloadSession.startDownload file empty channelId: {}, path: {}", channelId, path);
TransferUtils.sendMessage(channel, TransferReceiver.FINISH, null);
@@ -101,14 +106,14 @@ public class DownloadSession extends TransferSession implements StreamingRespons
// 首次触发
if (i == 0) {
outputStream.flush();
this.sendProgress(size, null);
this.sendProgress(size, fileSize);
}
i++;
}
// 最后一次也要 flush
if (i != 0) {
outputStream.flush();
this.sendProgress(size, null);
this.sendProgress(size, fileSize);
}
log.info("DownloadSession.download finish channelId: {}, path: {}", channelId, path);
} catch (Exception e) {

View File

@@ -1,7 +1,6 @@
package com.orion.visor.module.asset.handler.host.transfer.utils;
import com.alibaba.fastjson.JSON;
import com.orion.lang.exception.argument.InvalidArgumentException;
import com.orion.lang.utils.Strings;
import com.orion.visor.framework.common.constant.ErrorMessage;
import com.orion.visor.framework.websocket.core.utils.WebSockets;
@@ -62,13 +61,15 @@ public class TransferUtils {
public static String getErrorMessage(Exception ex) {
if (ex == null) {
return null;
} else if (ex instanceof InvalidArgumentException || ex instanceof IllegalArgumentException) {
} else if (ErrorMessage.isBizException(ex)) {
// 业务异常
String message = ex.getMessage();
if (Strings.isBlank(message)) {
return ErrorMessage.OPERATE_ERROR;
}
return message;
} else if (ex instanceof ClientAbortException) {
// 客户端主动断开
return ErrorMessage.CLIENT_ABORT;
}
return ErrorMessage.OPERATE_ERROR;

View File

@@ -17,7 +17,7 @@ import javax.annotation.Resource;
import java.util.Map;
/**
* 终端拦截器
* 终端访问拦截器
*
* @author Jiahang Li
* @version 1.0.0
@@ -34,11 +34,11 @@ public class TerminalAccessInterceptor implements HandshakeInterceptor {
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
// 获取 accessToken
String accessToken = Urls.getUrlSource(request.getURI().getPath());
log.info("TerminalInterceptor-beforeHandshake start accessToken: {}", accessToken);
log.info("TerminalAccessInterceptor-beforeHandshake start accessToken: {}", accessToken);
// 获取连接数据
HostTerminalAccessDTO access = hostTerminalService.getAccessInfoByToken(accessToken);
if (access == null) {
log.error("TerminalInterceptor-beforeHandshake absent accessToken: {}", accessToken);
log.error("TerminalAccessInterceptor-beforeHandshake absent accessToken: {}", accessToken);
return false;
}
// 设置参数

View File

@@ -0,0 +1,56 @@
package com.orion.visor.module.asset.interceptor;
import com.orion.lang.utils.Urls;
import com.orion.visor.framework.common.constant.ExtraFieldConst;
import com.orion.visor.framework.common.meta.TraceIdHolder;
import com.orion.visor.framework.common.utils.Requests;
import com.orion.visor.module.asset.entity.dto.HostTerminalTransferDTO;
import com.orion.visor.module.asset.service.HostTerminalService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.HandshakeInterceptor;
import javax.annotation.Resource;
import java.util.Map;
/**
* 终端传输拦截器
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023/12/27 23:53
*/
@Slf4j
@Component
public class TerminalTransferInterceptor implements HandshakeInterceptor {
@Resource
private HostTerminalService hostTerminalService;
@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
// 获取 transferToken
String transferToken = Urls.getUrlSource(request.getURI().getPath());
log.info("TerminalTransferInterceptor-beforeHandshake start transferToken: {}", transferToken);
// 获取连接数据
HostTerminalTransferDTO transfer = hostTerminalService.getTransferInfoByToken(transferToken);
if (transfer == null) {
log.error("TerminalTransferInterceptor-beforeHandshake absent transferToken: {}", transferToken);
return false;
}
// 设置参数
attributes.put(ExtraFieldConst.USER_ID, transfer.getUserId());
attributes.put(ExtraFieldConst.USERNAME, transfer.getUsername());
attributes.put(ExtraFieldConst.TRACE_ID, TraceIdHolder.get());
attributes.put(ExtraFieldConst.IDENTITY, Requests.getIdentity());
return true;
}
@Override
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {
}
}

View File

@@ -1,7 +1,10 @@
package com.orion.visor.module.asset.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.orion.lang.define.wrapper.DataGrid;
import com.orion.visor.module.asset.entity.domain.ExecLogDO;
import com.orion.visor.module.asset.entity.dto.ExecLogTailDTO;
import com.orion.visor.module.asset.entity.request.exec.ExecLogClearRequest;
import com.orion.visor.module.asset.entity.request.exec.ExecLogQueryRequest;
import com.orion.visor.module.asset.entity.request.exec.ExecLogTailRequest;
import com.orion.visor.module.asset.entity.vo.ExecLogStatusVO;
@@ -93,7 +96,7 @@ public interface ExecLogService {
* @param request request
* @return effect
*/
Integer clearExecLog(ExecLogQueryRequest request);
Integer clearExecLog(ExecLogClearRequest request);
/**
* 中断命令执行
@@ -143,4 +146,12 @@ public interface ExecLogService {
*/
void asyncDeleteLogFiles(List<Long> idList);
/**
* 构建查询 wrapper
*
* @param request request
* @return wrapper
*/
LambdaQueryWrapper<ExecLogDO> buildQueryWrapper(ExecLogQueryRequest request);
}

View File

@@ -1,7 +1,9 @@
package com.orion.visor.module.asset.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.orion.lang.define.wrapper.DataGrid;
import com.orion.visor.module.asset.entity.domain.HostConnectLogDO;
import com.orion.visor.module.asset.entity.request.host.HostConnectLogClearRequest;
import com.orion.visor.module.asset.entity.request.host.HostConnectLogCreateRequest;
import com.orion.visor.module.asset.entity.request.host.HostConnectLogQueryRequest;
import com.orion.visor.module.asset.entity.vo.HostConnectLogVO;
@@ -95,7 +97,7 @@ public interface HostConnectLogService {
* @param request request
* @return effect
*/
Integer clearHostConnectLog(HostConnectLogQueryRequest request);
Integer clearHostConnectLog(HostConnectLogClearRequest request);
/**
* 强制断开主机连接
@@ -105,4 +107,12 @@ public interface HostConnectLogService {
*/
Integer forceOffline(HostConnectLogQueryRequest request);
/**
* 构建查询 wrapper
*
* @param request request
* @return wrapper
*/
LambdaQueryWrapper<HostConnectLogDO> buildQueryWrapper(HostConnectLogQueryRequest request);
}

View File

@@ -1,6 +1,8 @@
package com.orion.visor.module.asset.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.orion.lang.define.wrapper.DataGrid;
import com.orion.visor.module.asset.entity.domain.HostDO;
import com.orion.visor.module.asset.entity.request.host.*;
import com.orion.visor.module.asset.entity.vo.HostConfigVO;
import com.orion.visor.module.asset.entity.vo.HostVO;
@@ -80,6 +82,14 @@ public interface HostService {
*/
DataGrid<HostVO> getHostPage(HostQueryRequest request);
/**
* 查询主机数量
*
* @param request request
* @return count
*/
Long getHostCount(HostQueryRequest request);
/**
* 通过 id 删除主机
*
@@ -110,4 +120,17 @@ public interface HostService {
*/
Long getCurrentUpdateConfigHostId();
/**
* 清除缓存
*/
void clearCache();
/**
* 构建查询 wrapper
*
* @param request request
* @return wrapper
*/
LambdaQueryWrapper<HostDO> buildQueryWrapper(HostQueryRequest request);
}

View File

@@ -3,6 +3,7 @@ package com.orion.visor.module.asset.service;
import com.orion.visor.module.asset.entity.domain.HostDO;
import com.orion.visor.module.asset.entity.dto.HostTerminalAccessDTO;
import com.orion.visor.module.asset.entity.dto.HostTerminalConnectDTO;
import com.orion.visor.module.asset.entity.dto.HostTerminalTransferDTO;
import com.orion.visor.module.asset.entity.vo.HostTerminalThemeVO;
import java.util.List;
@@ -30,6 +31,13 @@ public interface HostTerminalService {
*/
String getTerminalAccessToken();
/**
* 获取主机终端传输 transferToken
*
* @return transferToken
*/
String getTerminalTransferToken();
/**
* 通过 accessToken 获取主机终端访问信息
*
@@ -38,6 +46,14 @@ public interface HostTerminalService {
*/
HostTerminalAccessDTO getAccessInfoByToken(String token);
/**
* 通过 transferToken 获取主机终端传输信息
*
* @param token token
* @return config
*/
HostTerminalTransferDTO getTransferInfoByToken(String token);
/**
* 获取连接信息
*

View File

@@ -1,6 +1,9 @@
package com.orion.visor.module.asset.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.orion.lang.define.wrapper.DataGrid;
import com.orion.visor.module.asset.entity.domain.UploadTaskDO;
import com.orion.visor.module.asset.entity.request.upload.UploadTaskClearRequest;
import com.orion.visor.module.asset.entity.request.upload.UploadTaskCreateRequest;
import com.orion.visor.module.asset.entity.request.upload.UploadTaskQueryRequest;
import com.orion.visor.module.asset.entity.request.upload.UploadTaskRequest;
@@ -66,7 +69,7 @@ public interface UploadTaskService {
* @param request request
* @return count
*/
Integer clearUploadTask(UploadTaskQueryRequest request);
Integer clearUploadTask(UploadTaskClearRequest request);
/**
* 删除上传任务
@@ -112,4 +115,12 @@ public interface UploadTaskService {
*/
void clearUploadSwapFiles(List<Long> idList);
/**
* 构建查询 wrapper
*
* @param request request
* @return wrapper
*/
LambdaQueryWrapper<UploadTaskDO> buildQueryWrapper(UploadTaskQueryRequest request);
}

View File

@@ -1,6 +1,7 @@
package com.orion.visor.module.asset.service.impl;
import com.alibaba.fastjson.JSON;
import com.orion.lang.annotation.Keep;
import com.orion.lang.function.Functions;
import com.orion.lang.id.UUIds;
import com.orion.lang.utils.Strings;
@@ -11,7 +12,6 @@ import com.orion.lang.utils.json.matcher.ReplacementFormatter;
import com.orion.lang.utils.json.matcher.ReplacementFormatters;
import com.orion.lang.utils.time.Dates;
import com.orion.visor.framework.biz.operator.log.core.utils.OperatorLogs;
import com.orion.visor.framework.common.annotation.Keep;
import com.orion.visor.framework.common.constant.Const;
import com.orion.visor.framework.common.constant.ErrorMessage;
import com.orion.visor.framework.common.constant.FileConst;

View File

@@ -2,8 +2,8 @@ package com.orion.visor.module.asset.service.impl;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.orion.lang.annotation.Keep;
import com.orion.lang.define.wrapper.DataGrid;
import com.orion.lang.exception.argument.InvalidArgumentException;
import com.orion.lang.id.UUIds;
import com.orion.lang.utils.Arrays1;
import com.orion.lang.utils.Objects1;
@@ -13,12 +13,12 @@ import com.orion.lang.utils.io.Files1;
import com.orion.lang.utils.io.Streams;
import com.orion.spring.SpringHolder;
import com.orion.visor.framework.biz.operator.log.core.utils.OperatorLogs;
import com.orion.visor.framework.common.annotation.Keep;
import com.orion.visor.framework.common.constant.Const;
import com.orion.visor.framework.common.constant.ErrorMessage;
import com.orion.visor.framework.common.constant.FileConst;
import com.orion.visor.framework.common.enums.EndpointDefine;
import com.orion.visor.framework.common.file.FileClient;
import com.orion.visor.framework.common.utils.SqlUtils;
import com.orion.visor.framework.common.utils.Valid;
import com.orion.visor.framework.redis.core.utils.RedisStrings;
import com.orion.visor.framework.security.core.utils.SecurityUtils;
@@ -31,6 +31,7 @@ import com.orion.visor.module.asset.entity.domain.ExecHostLogDO;
import com.orion.visor.module.asset.entity.domain.ExecLogDO;
import com.orion.visor.module.asset.entity.dto.ExecHostLogTailDTO;
import com.orion.visor.module.asset.entity.dto.ExecLogTailDTO;
import com.orion.visor.module.asset.entity.request.exec.ExecLogClearRequest;
import com.orion.visor.module.asset.entity.request.exec.ExecLogQueryRequest;
import com.orion.visor.module.asset.entity.request.exec.ExecLogTailRequest;
import com.orion.visor.module.asset.entity.vo.ExecHostLogVO;
@@ -92,7 +93,8 @@ public class ExecLogServiceImpl implements ExecLogService {
@Override
public DataGrid<ExecLogVO> getExecLogPage(ExecLogQueryRequest request) {
// 条件
LambdaQueryWrapper<ExecLogDO> wrapper = this.buildQueryWrapper(request);
LambdaQueryWrapper<ExecLogDO> wrapper = this.buildQueryWrapper(request)
.orderByDesc(ExecLogDO::getId);
// 查询
return execLogDAO.of(wrapper)
.page(request)
@@ -219,16 +221,23 @@ public class ExecLogServiceImpl implements ExecLogService {
@Override
public Long queryExecLogCount(ExecLogQueryRequest request) {
return execLogDAO.selectCount(this.buildQueryWrapper(request));
// 条件
LambdaQueryWrapper<ExecLogDO> wrapper = this.buildQueryWrapper(request);
// 查询
return execLogDAO.of()
.wrapper(wrapper)
.countMax(request.getLimit());
}
@Override
@Transactional(rollbackFor = Exception.class)
public Integer clearExecLog(ExecLogQueryRequest request) {
public Integer clearExecLog(ExecLogClearRequest request) {
log.info("ExecLogService.clearExecLog start {}", JSON.toJSONString(request));
// 查询
LambdaQueryWrapper<ExecLogDO> wrapper = this.buildQueryWrapper(request)
.select(ExecLogDO::getId);
.select(ExecLogDO::getId)
.orderByAsc(ExecLogDO::getId)
.last(SqlUtils.limit(request.getLimit()));
List<Long> idList = execLogDAO.selectList(wrapper)
.stream()
.map(ExecLogDO::getId)
@@ -421,10 +430,8 @@ public class ExecLogServiceImpl implements ExecLogService {
} catch (Exception e) {
log.error("ExecLogService.downloadLogFile error id: {}", id, e);
Streams.close(in);
String errorMessage = ErrorMessage.FILE_READ_ERROR_CLEAR;
if (e instanceof InvalidArgumentException || e instanceof IllegalArgumentException) {
errorMessage = e.getMessage();
}
// 获取错误信息
String errorMessage = ErrorMessage.getErrorMessage(e, ErrorMessage.FILE_READ_ERROR_CLEAR);
// 响应错误信息
try {
Servlets.transfer(response, Strings.bytes(errorMessage), FileConst.ERROR_LOG);
@@ -450,13 +457,8 @@ public class ExecLogServiceImpl implements ExecLogService {
.forEach(Files1::delete);
}
/**
* 构建查询 wrapper
*
* @param request request
* @return wrapper
*/
private LambdaQueryWrapper<ExecLogDO> buildQueryWrapper(ExecLogQueryRequest request) {
@Override
public LambdaQueryWrapper<ExecLogDO> buildQueryWrapper(ExecLogQueryRequest request) {
return execLogDAO.wrapper()
.eq(ExecLogDO::getId, request.getId())
.eq(ExecLogDO::getUserId, request.getUserId())
@@ -469,8 +471,7 @@ public class ExecLogServiceImpl implements ExecLogService {
.in(ExecLogDO::getStatus, request.getStatusList())
.ge(ExecLogDO::getStartTime, Arrays1.getIfPresent(request.getStartTimeRange(), 0))
.le(ExecLogDO::getStartTime, Arrays1.getIfPresent(request.getStartTimeRange(), 1))
.le(ExecLogDO::getCreateTime, request.getCreateTimeLe())
.orderByDesc(ExecLogDO::getId);
.le(ExecLogDO::getCreateTime, request.getCreateTimeLe());
}
/**

View File

@@ -8,12 +8,14 @@ import com.orion.lang.utils.collect.Lists;
import com.orion.visor.framework.biz.operator.log.core.utils.OperatorLogs;
import com.orion.visor.framework.common.constant.Const;
import com.orion.visor.framework.common.constant.ErrorMessage;
import com.orion.visor.framework.common.utils.SqlUtils;
import com.orion.visor.framework.common.utils.Valid;
import com.orion.visor.framework.security.core.utils.SecurityUtils;
import com.orion.visor.module.asset.convert.HostConnectLogConvert;
import com.orion.visor.module.asset.dao.HostConnectLogDAO;
import com.orion.visor.module.asset.entity.domain.HostConnectLogDO;
import com.orion.visor.module.asset.entity.dto.HostConnectLogExtraDTO;
import com.orion.visor.module.asset.entity.request.host.HostConnectLogClearRequest;
import com.orion.visor.module.asset.entity.request.host.HostConnectLogCreateRequest;
import com.orion.visor.module.asset.entity.request.host.HostConnectLogQueryRequest;
import com.orion.visor.module.asset.entity.vo.HostConnectLogVO;
@@ -26,6 +28,7 @@ import com.orion.visor.module.asset.service.HostConnectLogService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.*;
@@ -70,7 +73,8 @@ public class HostConnectLogServiceImpl implements HostConnectLogService {
@Override
public DataGrid<HostConnectLogVO> getHostConnectLogPage(HostConnectLogQueryRequest request) {
// 条件
LambdaQueryWrapper<HostConnectLogDO> wrapper = this.buildQueryWrapper(request);
LambdaQueryWrapper<HostConnectLogDO> wrapper = this.buildQueryWrapper(request)
.orderByDesc(HostConnectLogDO::getId);
// 查询
return hostConnectLogDAO.of(wrapper)
.page(request)
@@ -101,7 +105,8 @@ public class HostConnectLogServiceImpl implements HostConnectLogService {
// 条件
request.setIdList(idList);
request.setStatus(HostConnectStatusEnum.CONNECTING.name());
LambdaQueryWrapper<HostConnectLogDO> wrapper = this.buildQueryWrapper(request);
LambdaQueryWrapper<HostConnectLogDO> wrapper = this.buildQueryWrapper(request)
.orderByDesc(HostConnectLogDO::getId);
// 查询
return hostConnectLogDAO.of(wrapper)
.list(s -> {
@@ -167,13 +172,14 @@ public class HostConnectLogServiceImpl implements HostConnectLogService {
}
@Override
@Transactional(rollbackFor = Exception.class)
public Integer deleteHostConnectLog(List<Long> idList) {
log.info("HostConnectLogService.deleteHostConnectLog start {}", JSON.toJSONString(idList));
if (Lists.isEmpty(idList)) {
OperatorLogs.add(OperatorLogs.COUNT, Const.N_0);
return Const.N_0;
}
// 删除
// 删除日志表
int effect = hostConnectLogDAO.deleteBatchIds(idList);
log.info("HostConnectLogService.deleteHostConnectLog finish {}", effect);
// 设置日志参数
@@ -183,15 +189,23 @@ public class HostConnectLogServiceImpl implements HostConnectLogService {
@Override
public Long getHostConnectLogCount(HostConnectLogQueryRequest request) {
return hostConnectLogDAO.selectCount(this.buildQueryWrapper(request));
// 条件
LambdaQueryWrapper<HostConnectLogDO> wrapper = this.buildQueryWrapper(request);
// 查询
return hostConnectLogDAO.of()
.wrapper(wrapper)
.countMax(request.getLimit());
}
@Override
public Integer clearHostConnectLog(HostConnectLogQueryRequest request) {
@Transactional(rollbackFor = Exception.class)
public Integer clearHostConnectLog(HostConnectLogClearRequest request) {
log.info("HostConnectLogService.clearHostConnectLog start {}", JSON.toJSONString(request));
// 查询
LambdaQueryWrapper<HostConnectLogDO> wrapper = this.buildQueryWrapper(request)
.select(HostConnectLogDO::getId);
.select(HostConnectLogDO::getId)
.orderByAsc(HostConnectLogDO::getId)
.last(SqlUtils.limit(request.getLimit()));
List<HostConnectLogDO> list = hostConnectLogDAO.selectList(wrapper);
if (list.isEmpty()) {
log.info("HostConnectLogService.clearHostConnectLog empty");
@@ -226,13 +240,8 @@ public class HostConnectLogServiceImpl implements HostConnectLogService {
return this.updateStatus(record, HostConnectStatusEnum.FORCE_OFFLINE, null);
}
/**
* 构建查询 wrapper
*
* @param request request
* @return wrapper
*/
private LambdaQueryWrapper<HostConnectLogDO> buildQueryWrapper(HostConnectLogQueryRequest request) {
@Override
public LambdaQueryWrapper<HostConnectLogDO> buildQueryWrapper(HostConnectLogQueryRequest request) {
return hostConnectLogDAO.wrapper()
.eq(HostConnectLogDO::getId, request.getId())
.in(HostConnectLogDO::getId, request.getIdList())
@@ -245,8 +254,7 @@ public class HostConnectLogServiceImpl implements HostConnectLogService {
.in(HostConnectLogDO::getStatus, request.getStatusList())
.ge(HostConnectLogDO::getStartTime, Arrays1.getIfPresent(request.getStartTimeRange(), 0))
.le(HostConnectLogDO::getStartTime, Arrays1.getIfPresent(request.getStartTimeRange(), 1))
.le(HostConnectLogDO::getCreateTime, request.getCreateTimeLe())
.orderByDesc(HostConnectLogDO::getId);
.le(HostConnectLogDO::getCreateTime, request.getCreateTimeLe());
}
}

View File

@@ -259,9 +259,10 @@ public class HostServiceImpl implements HostService {
if (wrapper == null) {
return DataGrid.of(Lists.empty());
}
// 数量条件
LambdaQueryWrapper<HostDO> countWrapper = wrapper.clone();
wrapper.select(HostDAO.BASE_COLUMN);
// 基础条件
LambdaQueryWrapper<HostDO> countWrapper = wrapper.clone()
.select(HostDAO.BASE_COLUMN)
.orderByAsc(HostDO::getId);
// 查询
DataGrid<HostVO> hosts = hostDAO.of(wrapper)
.page(request)
@@ -271,6 +272,16 @@ public class HostServiceImpl implements HostService {
return hosts;
}
@Override
public Long getHostCount(HostQueryRequest request) {
// 条件
LambdaQueryWrapper<HostDO> wrapper = this.buildQueryWrapper(request);
// 查询
return hostDAO.of()
.wrapper(wrapper)
.countMax(request.getLimit());
}
@Override
public Integer deleteHostById(Long id) {
return this.deleteHostByIdList(Lists.singleton(id));
@@ -279,17 +290,10 @@ public class HostServiceImpl implements HostService {
@Override
public Integer deleteHostByIdList(List<Long> idList) {
log.info("HostService-deleteHostByIdList idList: {}", idList);
// 查询
List<HostDO> hosts = hostDAO.selectBaseByIdList(idList);
Valid.notEmpty(hosts, ErrorMessage.HOST_ABSENT);
// 添加日志参数
String name = hosts.stream()
.map(HostDO::getName)
.collect(Collectors.joining(Const.COMMA));
OperatorLogs.add(OperatorLogs.NAME, name);
OperatorLogs.add(OperatorLogs.COUNT, hosts.size());
// 删除
int effect = hostDAO.deleteBatchIds(hosts);
int effect = hostDAO.deleteBatchIds(idList);
// 添加日志参数
OperatorLogs.add(OperatorLogs.COUNT, idList.size());
log.info("HostService-deleteHostByIdList effect: {}", effect);
// 删除缓存
this.clearCache();
@@ -322,10 +326,8 @@ public class HostServiceImpl implements HostService {
return CURRENT_UPDATE_CONFIG_ID.get();
}
/**
* 清除缓存
*/
private void clearCache() {
@Override
public void clearCache() {
RedisMaps.scanKeysDelete(HostCacheKeyDefine.HOST_INFO.format("*"));
}
@@ -361,13 +363,8 @@ public class HostServiceImpl implements HostService {
Valid.isFalse(present, ErrorMessage.CODE_PRESENT);
}
/**
* 构建查询 wrapper
*
* @param request request
* @return wrapper
*/
private LambdaQueryWrapper<HostDO> buildQueryWrapper(HostQueryRequest request) {
@Override
public LambdaQueryWrapper<HostDO> buildQueryWrapper(HostQueryRequest request) {
String searchValue = request.getSearchValue();
LambdaQueryWrapper<HostDO> wrapper = hostDAO.wrapper();
// tag 条件

View File

@@ -17,6 +17,7 @@ import com.orion.visor.module.asset.entity.domain.HostIdentityDO;
import com.orion.visor.module.asset.entity.domain.HostKeyDO;
import com.orion.visor.module.asset.entity.dto.HostTerminalAccessDTO;
import com.orion.visor.module.asset.entity.dto.HostTerminalConnectDTO;
import com.orion.visor.module.asset.entity.dto.HostTerminalTransferDTO;
import com.orion.visor.module.asset.entity.vo.HostTerminalThemeVO;
import com.orion.visor.module.asset.enums.*;
import com.orion.visor.module.asset.handler.host.config.model.HostSshConfigModel;
@@ -74,6 +75,10 @@ public class HostTerminalServiceImpl implements HostTerminalService {
@Override
public List<HostTerminalThemeVO> getTerminalThemes() {
// if (true) {
// String arr = "";
// return JSON.parseArray(arr, HostTerminalThemeVO.class);
// }
List<JSONObject> themes = dictValueApi.getDictValue(THEME_DICT_KEY);
return themes.stream()
.map(s -> HostTerminalThemeVO.builder()
@@ -99,6 +104,21 @@ public class HostTerminalServiceImpl implements HostTerminalService {
return accessToken;
}
@Override
public String getTerminalTransferToken() {
LoginUser user = Valid.notNull(SecurityUtils.getLoginUser());
log.info("HostConnectService.getTerminalTransferToken userId: {}", user.getId());
String transferToken = UUIds.random19();
HostTerminalTransferDTO transfer = HostTerminalTransferDTO.builder()
.userId(user.getId())
.username(user.getUsername())
.build();
// 设置 transfer 缓存
String key = HostTerminalCacheKeyDefine.HOST_TERMINAL_TRANSFER.format(transferToken);
RedisStrings.setJson(key, HostTerminalCacheKeyDefine.HOST_TERMINAL_TRANSFER, transfer);
return transferToken;
}
@Override
public HostTerminalAccessDTO getAccessInfoByToken(String token) {
// 获取缓存
@@ -111,6 +131,18 @@ public class HostTerminalServiceImpl implements HostTerminalService {
return access;
}
@Override
public HostTerminalTransferDTO getTransferInfoByToken(String token) {
// 获取缓存
String key = HostTerminalCacheKeyDefine.HOST_TERMINAL_TRANSFER.format(token);
HostTerminalTransferDTO transfer = RedisStrings.getJson(key, HostTerminalCacheKeyDefine.HOST_TERMINAL_TRANSFER);
// 删除缓存
if (transfer != null) {
RedisStrings.delete(key);
}
return transfer;
}
@Override
public HostTerminalConnectDTO getTerminalConnectInfo(Long hostId) {
log.info("HostConnectService.getTerminalConnectInfo-withHost hostId: {}", hostId);

View File

@@ -2,6 +2,7 @@ package com.orion.visor.module.asset.service.impl;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.orion.lang.annotation.Keep;
import com.orion.lang.define.wrapper.DataGrid;
import com.orion.lang.utils.Arrays1;
import com.orion.lang.utils.Booleans;
@@ -12,12 +13,12 @@ import com.orion.lang.utils.collect.Maps;
import com.orion.lang.utils.io.Files1;
import com.orion.lang.utils.time.Dates;
import com.orion.visor.framework.biz.operator.log.core.utils.OperatorLogs;
import com.orion.visor.framework.common.annotation.Keep;
import com.orion.visor.framework.common.constant.Const;
import com.orion.visor.framework.common.constant.ErrorMessage;
import com.orion.visor.framework.common.enums.EndpointDefine;
import com.orion.visor.framework.common.file.FileClient;
import com.orion.visor.framework.common.security.LoginUser;
import com.orion.visor.framework.common.utils.SqlUtils;
import com.orion.visor.framework.common.utils.Valid;
import com.orion.visor.framework.mybatis.core.query.Conditions;
import com.orion.visor.framework.security.core.utils.SecurityUtils;
@@ -30,10 +31,7 @@ import com.orion.visor.module.asset.dao.UploadTaskFileDAO;
import com.orion.visor.module.asset.entity.domain.UploadTaskDO;
import com.orion.visor.module.asset.entity.domain.UploadTaskFileDO;
import com.orion.visor.module.asset.entity.dto.UploadTaskExtraDTO;
import com.orion.visor.module.asset.entity.request.upload.UploadTaskCreateRequest;
import com.orion.visor.module.asset.entity.request.upload.UploadTaskFileRequest;
import com.orion.visor.module.asset.entity.request.upload.UploadTaskQueryRequest;
import com.orion.visor.module.asset.entity.request.upload.UploadTaskRequest;
import com.orion.visor.module.asset.entity.request.upload.*;
import com.orion.visor.module.asset.entity.vo.*;
import com.orion.visor.module.asset.enums.HostTypeEnum;
import com.orion.visor.module.asset.enums.UploadTaskFileStatusEnum;
@@ -171,7 +169,8 @@ public class UploadTaskServiceImpl implements UploadTaskService {
@Override
public DataGrid<UploadTaskVO> getUploadTaskPage(UploadTaskQueryRequest request) {
// 条件
LambdaQueryWrapper<UploadTaskDO> wrapper = this.buildQueryWrapper(request);
LambdaQueryWrapper<UploadTaskDO> wrapper = this.buildQueryWrapper(request)
.orderByDesc(UploadTaskDO::getId);
// 查询
return uploadTaskDAO.of(wrapper)
.page(request)
@@ -218,15 +217,22 @@ public class UploadTaskServiceImpl implements UploadTaskService {
@Override
public Long getUploadTaskCount(UploadTaskQueryRequest request) {
return uploadTaskDAO.selectCount(this.buildQueryWrapper(request));
// 条件
LambdaQueryWrapper<UploadTaskDO> wrapper = this.buildQueryWrapper(request);
// 查询
return uploadTaskDAO.of()
.wrapper(wrapper)
.countMax(request.getLimit());
}
@Transactional(rollbackFor = Exception.class)
@Override
public Integer clearUploadTask(UploadTaskQueryRequest request) {
@Transactional(rollbackFor = Exception.class)
public Integer clearUploadTask(UploadTaskClearRequest request) {
// 查询id
LambdaQueryWrapper<UploadTaskDO> wrapper = this.buildQueryWrapper(request)
.select(UploadTaskDO::getId);
.select(UploadTaskDO::getId)
.orderByAsc(UploadTaskDO::getId)
.last(SqlUtils.limit(request.getLimit()));
List<Long> idList = uploadTaskDAO.of(wrapper)
.list(UploadTaskDO::getId);
// 删除
@@ -305,13 +311,8 @@ public class UploadTaskServiceImpl implements UploadTaskService {
paths.forEach(Files1::delete);
}
/**
* 构建查询 wrapper
*
* @param request request
* @return wrapper
*/
private LambdaQueryWrapper<UploadTaskDO> buildQueryWrapper(UploadTaskQueryRequest request) {
@Override
public LambdaQueryWrapper<UploadTaskDO> buildQueryWrapper(UploadTaskQueryRequest request) {
return uploadTaskDAO.wrapper()
.eq(UploadTaskDO::getId, request.getId())
.eq(UploadTaskDO::getUserId, request.getUserId())
@@ -319,8 +320,7 @@ public class UploadTaskServiceImpl implements UploadTaskService {
.like(UploadTaskDO::getRemotePath, request.getRemotePath())
.eq(UploadTaskDO::getStatus, request.getStatus())
.ge(UploadTaskDO::getCreateTime, Arrays1.getIfPresent(request.getCreateTimeRange(), 0))
.le(UploadTaskDO::getCreateTime, Arrays1.getIfPresent(request.getCreateTimeRange(), 1))
.orderByDesc(UploadTaskDO::getId);
.le(UploadTaskDO::getCreateTime, Arrays1.getIfPresent(request.getCreateTimeRange(), 1));
}
/**

View File

@@ -3,7 +3,7 @@ package com.orion.visor.module.asset.task;
import com.orion.lang.utils.time.Dates;
import com.orion.visor.framework.common.utils.LockerUtils;
import com.orion.visor.module.asset.define.config.AppExecLogAutoClearConfig;
import com.orion.visor.module.asset.entity.request.exec.ExecLogQueryRequest;
import com.orion.visor.module.asset.entity.request.exec.ExecLogClearRequest;
import com.orion.visor.module.asset.enums.ExecStatusEnum;
import com.orion.visor.module.asset.service.ExecLogService;
import lombok.extern.slf4j.Slf4j;
@@ -57,7 +57,7 @@ public class ExecLogFileAutoClearTask {
.subDay(appExecLogAutoClearConfig.getKeepPeriod())
.date();
// 清理
ExecLogQueryRequest request = new ExecLogQueryRequest();
ExecLogClearRequest request = new ExecLogClearRequest();
request.setCreateTimeLe(createLessEq);
request.setStatusList(ExecStatusEnum.FINISH_STATUS_LIST);
execLogService.clearExecLog(request);

View File

@@ -3,7 +3,7 @@ package com.orion.visor.module.asset.task;
import com.orion.lang.utils.time.Dates;
import com.orion.visor.framework.common.utils.LockerUtils;
import com.orion.visor.module.asset.define.config.AppHostConnectLogAutoClearConfig;
import com.orion.visor.module.asset.entity.request.host.HostConnectLogQueryRequest;
import com.orion.visor.module.asset.entity.request.host.HostConnectLogClearRequest;
import com.orion.visor.module.asset.enums.HostConnectStatusEnum;
import com.orion.visor.module.asset.service.HostConnectLogService;
import lombok.extern.slf4j.Slf4j;
@@ -57,7 +57,7 @@ public class HostConnectLogAutoClearTask {
.subDay(appHostConnectLogAutoClearConfig.getKeepPeriod())
.date();
// 清理
HostConnectLogQueryRequest request = new HostConnectLogQueryRequest();
HostConnectLogClearRequest request = new HostConnectLogClearRequest();
request.setCreateTimeLe(createLessEq);
request.setStatusList(HostConnectStatusEnum.FINISH_STATUS_LIST);
hostConnectLogService.clearHostConnectLog(request);

Some files were not shown because too many files have changed in this diff Show More