Compare commits
99 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8d46e1d44d | ||
|
|
b3c045aa46 | ||
|
|
ca4ec20e49 | ||
|
|
8db2986dfc | ||
|
|
3156ae1dff | ||
|
|
697d29c6f2 | ||
|
|
bf4b1f9702 | ||
|
|
d2703661c8 | ||
|
|
df78fc5977 | ||
|
|
5e03810295 | ||
|
|
6b44e193f5 | ||
|
|
919e8383bf | ||
|
|
0b7faa038a | ||
|
|
3c75aedcec | ||
|
|
393286d309 | ||
|
|
8501e900c7 | ||
|
|
c53042a4b5 | ||
|
|
c661d34a79 | ||
|
|
a3476596dd | ||
|
|
8a4176bc9e | ||
|
|
a0a7240191 | ||
|
|
2b52697cdc | ||
|
|
63d82b5a19 | ||
|
|
af23e56f03 | ||
|
|
cecd71c42a | ||
|
|
3ed9df8788 | ||
|
|
7a89858790 | ||
|
|
a548413358 | ||
|
|
c859225908 | ||
|
|
b097836ec8 | ||
|
|
9e0cfef4da | ||
|
|
a76a7d4150 | ||
|
|
2920504023 | ||
|
|
c32b590bb4 | ||
|
|
612d7f1166 | ||
|
|
b7c4fbcab8 | ||
|
|
a3f84e799c | ||
|
|
5ab3f168d8 | ||
|
|
402e183d2f | ||
|
|
d3e5e08f6c | ||
|
|
e214fbde5c | ||
|
|
2f7b4bd5ea | ||
|
|
8bba423ff3 | ||
|
|
0d0eadc3bf | ||
|
|
ab430d8934 | ||
|
|
edcc2cf0c8 | ||
|
|
2913ddb2e0 | ||
|
|
7d35f839df | ||
|
|
ef9c34f7d9 | ||
|
|
f1a4e049ca | ||
|
|
8ee1e6acf1 | ||
|
|
d0eddf1e15 | ||
|
|
b42645b0ce | ||
|
|
3895476ff8 | ||
|
|
d2cba947b3 | ||
|
|
964c1daa2c | ||
|
|
d496dcd9f5 | ||
|
|
9d06f0ae87 | ||
|
|
9f379546cb | ||
|
|
3123a89d13 | ||
|
|
8ebc3ee3b2 | ||
|
|
7a3580936f | ||
|
|
2e36d0f44b | ||
|
|
abada92907 | ||
|
|
0224e2f19a | ||
|
|
bf04e8eace | ||
|
|
ef146cdaef | ||
|
|
bfde435071 | ||
|
|
fc151216f1 | ||
|
|
dd0237a83a | ||
|
|
f34dc75f41 | ||
|
|
1abc47bb56 | ||
|
|
4643c37a5a | ||
|
|
aed5d10eed | ||
|
|
4b25de3811 | ||
|
|
e72a9d97cd | ||
|
|
97dddf01a7 | ||
|
|
01d53dadd7 | ||
|
|
5c119deaf4 | ||
|
|
4dc1364b11 | ||
|
|
65771f0b41 | ||
|
|
47a14dec6a | ||
|
|
6f0f6da07c | ||
|
|
eb64e80d06 | ||
|
|
ca8c5b53d2 | ||
|
|
9e9c390baf | ||
|
|
a546827432 | ||
|
|
5c03784f9c | ||
|
|
6fa2d65e18 | ||
|
|
0b4e42ee89 | ||
|
|
2175a9fb40 | ||
|
|
2e98060573 | ||
|
|
4ee4333bfe | ||
|
|
1c8c1596f9 | ||
|
|
a59f2c5bf6 | ||
|
|
f8707ebce0 | ||
|
|
28d793b84d | ||
|
|
8963ca64d2 | ||
|
|
fef11850dd |
21
.env.example
21
.env.example
@@ -1,10 +1,13 @@
|
|||||||
VOLUME_BASE=/data/orion-visor-space/docker-volumes
|
VOLUME_BASE=/data/orion-visor-space/docker-volumes
|
||||||
|
|
||||||
DEMO_MODE=false
|
|
||||||
|
|
||||||
SERVICE_PORT=1081
|
SERVICE_PORT=1081
|
||||||
SPRING_PROFILES_ACTIVE=prod
|
SPRING_PROFILES_ACTIVE=prod
|
||||||
|
|
||||||
|
DEMO_MODE=false
|
||||||
|
|
||||||
|
API_CORS=true
|
||||||
SECRET_KEY=uQeacXV8b3isvKLK
|
SECRET_KEY=uQeacXV8b3isvKLK
|
||||||
|
API_EXPOSE_TOKEN=pmqeHOyZaumHm0Wt
|
||||||
|
|
||||||
MYSQL_HOST=mysql
|
MYSQL_HOST=mysql
|
||||||
MYSQL_PORT=3306
|
MYSQL_PORT=3306
|
||||||
@@ -15,7 +18,21 @@ MYSQL_ROOT_PASSWORD=Data@123456
|
|||||||
|
|
||||||
REDIS_HOST=redis
|
REDIS_HOST=redis
|
||||||
REDIS_PASSWORD=Data@123456
|
REDIS_PASSWORD=Data@123456
|
||||||
|
REDIS_DATABASE=0
|
||||||
|
REDIS_DATA_VERSION=1
|
||||||
|
|
||||||
GUACD_HOST=guacd
|
GUACD_HOST=guacd
|
||||||
GUACD_PORT=4822
|
GUACD_PORT=4822
|
||||||
|
GUACD_SSH_PORT=22
|
||||||
|
GUACD_SSH_USERNAME=guacd
|
||||||
|
GUACD_SSH_PASSWORD=guacd
|
||||||
GUACD_DRIVE_PATH=/drive
|
GUACD_DRIVE_PATH=/drive
|
||||||
|
|
||||||
|
INFLUXDB_ENABLED=true
|
||||||
|
INFLUXDB_HOST=influxdb
|
||||||
|
INFLUXDB_PORT=8086
|
||||||
|
INFLUXDB_ORG=orion-visor
|
||||||
|
INFLUXDB_BUCKET=metrics
|
||||||
|
INFLUXDB_TOKEN=Data@123456
|
||||||
|
INFLUXDB_ADMIN_USERNAME=admin
|
||||||
|
INFLUXDB_ADMIN_PASSWORD=Data@123456
|
||||||
|
|||||||
10
.gitee/ISSUE_TEMPLATE.zh-CN.md
Normal file
10
.gitee/ISSUE_TEMPLATE.zh-CN.md
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
### *当前使用版本 (必填)
|
||||||
|
|
||||||
|
### 问题描述
|
||||||
|
|
||||||
|
### 该问题是如何引起的
|
||||||
|
|
||||||
|
### 重现步骤
|
||||||
|
|
||||||
|
### 报错信息
|
||||||
|
|
||||||
8
.gitee/PULL_REQUEST_TEMPLATE.zh-CN.md
Normal file
8
.gitee/PULL_REQUEST_TEMPLATE.zh-CN.md
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
### 修改描述
|
||||||
|
|
||||||
|
### 关联的 Issue
|
||||||
|
|
||||||
|
### 测试用例
|
||||||
|
|
||||||
|
### 修复效果的截屏
|
||||||
|
|
||||||
58
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
Normal file
58
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
name: 错误报告
|
||||||
|
description: File a bug report.
|
||||||
|
title: "[错误报告]: "
|
||||||
|
labels: [ "" ]
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
在提交前请确认:
|
||||||
|
- 使用的是[最新版本](https://github.com/dromara/orion-visor/releases)
|
||||||
|
- 参考了[安装文档](https://visor.orionsec.cn/quickstart/docker.html)
|
||||||
|
- 查阅了[常见问题](https://visor.orionsec.cn/support/faq.html)
|
||||||
|
- 搜索了[已有 issue](https://github.com/dromara/orion-visor/issues)
|
||||||
|
- type: checkboxes
|
||||||
|
id: confirm
|
||||||
|
attributes:
|
||||||
|
label: 确认
|
||||||
|
description: 在提交 issue 之前, 请确认你已经阅读并确认以下内容
|
||||||
|
options:
|
||||||
|
- label: 我使用的是最新版本 [最新版](https://github.com/dromara/orion-visor/releases)
|
||||||
|
required: true
|
||||||
|
- label: 我使用官方文档进行部署 [安装文档](https://visor.orionsec.cn/quickstart/docker.html)
|
||||||
|
required: true
|
||||||
|
- label: 我已检查了 [常见问题](https://visor.orionsec.cn/support/faq.html) 并没有找到解决方法
|
||||||
|
required: true
|
||||||
|
- label: 我已搜索 [issue](https://github.com/dromara/orion-visor/issues) 并没有找到相关问题
|
||||||
|
required: true
|
||||||
|
- type: input
|
||||||
|
id: version
|
||||||
|
attributes:
|
||||||
|
label: 当前程序版本
|
||||||
|
description: 遇到问题时程序所在的版本号
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: dropdown
|
||||||
|
id: install
|
||||||
|
attributes:
|
||||||
|
label: 安装方式
|
||||||
|
options:
|
||||||
|
- Docker
|
||||||
|
- 普通安装
|
||||||
|
- 其他
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: what-happened
|
||||||
|
attributes:
|
||||||
|
label: 问题描述
|
||||||
|
description: 请详细描述你碰到的问题
|
||||||
|
placeholder: "问题描述"
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: logs
|
||||||
|
attributes:
|
||||||
|
label: 详细日志
|
||||||
|
description: 问题出现时的程序日志
|
||||||
|
render: bash
|
||||||
5
.github/ISSUE_TEMPLATE/config.yaml
vendored
Normal file
5
.github/ISSUE_TEMPLATE/config.yaml
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
blank_issues_enabled: false
|
||||||
|
contact_links:
|
||||||
|
- name: 官网
|
||||||
|
url: https://visor.orionsec.cn/
|
||||||
|
about: document.
|
||||||
35
.github/ISSUE_TEMPLATE/feature_request.yaml
vendored
Normal file
35
.github/ISSUE_TEMPLATE/feature_request.yaml
vendored
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
name: 功能改进
|
||||||
|
description: 提出新功能建议 (请提交到需求收集帖)
|
||||||
|
title: "[功能建议]: "
|
||||||
|
labels: [ "" ]
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
所有功能建议请统一提交到需求收集帖: 🔗 [#83 需求收集](https://github.com/dromara/orion-visor/issues/83)
|
||||||
|
|
||||||
|
在提交前请确认:
|
||||||
|
- ✅ 使用的是[最新版本](https://github.com/dromara/orion-visor/releases)
|
||||||
|
- ✅ 已搜索[已有 issue](https://github.com/dromara/orion-visor/issues) 和 需求收集帖避免重复
|
||||||
|
- ✅ 定制化需求请联系作者
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 如何提交高质量建议?
|
||||||
|
1. **功能描述**: 你希望增加什么?
|
||||||
|
2. **使用场景**: 你在什么情况下需要它?
|
||||||
|
4. **参考实现**: 开源项目中的类似功能(**禁止引用商业闭源软件**)
|
||||||
|
- type: textarea
|
||||||
|
id: feature
|
||||||
|
attributes:
|
||||||
|
label: 功能改进
|
||||||
|
description: 请详细描述需要改进或者添加的功能。
|
||||||
|
placeholder: "功能改进"
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: references
|
||||||
|
attributes:
|
||||||
|
label: 参考资料
|
||||||
|
description: 可以列举一些参考资料, 但是不要引用同类但商业化软件的任何内容。
|
||||||
|
placeholder: "参考资料"
|
||||||
53
.github/settings/maven-settings.xml
vendored
Normal file
53
.github/settings/maven-settings.xml
vendored
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
|
||||||
|
|
||||||
|
<mirrors>
|
||||||
|
<mirror>
|
||||||
|
<id>public-mirror</id>
|
||||||
|
<mirrorOf>public</mirrorOf>
|
||||||
|
<name>Maven Central Repository</name>
|
||||||
|
<url>https://repo.maven.apache.org/maven2/</url>
|
||||||
|
</mirror>
|
||||||
|
</mirrors>
|
||||||
|
|
||||||
|
<profiles>
|
||||||
|
<profile>
|
||||||
|
<id>repos</id>
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>centra</id>
|
||||||
|
<url>https://repo.maven.apache.org/maven2</url>
|
||||||
|
<releases>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
</releases>
|
||||||
|
<snapshots>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</snapshots>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
|
||||||
|
<pluginRepositories>
|
||||||
|
<pluginRepository>
|
||||||
|
<id>central</id>
|
||||||
|
<name>Maven Central Plugin Repository</name>
|
||||||
|
<url>https://repo.maven.apache.org/maven2</url>
|
||||||
|
<layout>default</layout>
|
||||||
|
<releases>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
</releases>
|
||||||
|
<snapshots>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</snapshots>
|
||||||
|
</pluginRepository>
|
||||||
|
</pluginRepositories>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
|
|
||||||
|
<activeProfiles>
|
||||||
|
<activeProfile>repos</activeProfile>
|
||||||
|
</activeProfiles>
|
||||||
|
|
||||||
|
</settings>
|
||||||
139
.github/workflows/docker-publish.yaml
vendored
Normal file
139
.github/workflows/docker-publish.yaml
vendored
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
name: Docker Publish
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- 'v*'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-project:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
packages: write
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: 🌱 Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: ⚙️ Set up JDK 8
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
java-version: '8'
|
||||||
|
distribution: 'temurin'
|
||||||
|
cache: 'maven'
|
||||||
|
|
||||||
|
- name: ⚙️ Set up Node.js 18
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: '18'
|
||||||
|
|
||||||
|
- name: 🔧 Install pnpm
|
||||||
|
run: npm i -g pnpm
|
||||||
|
|
||||||
|
- name: 📦 Build Java
|
||||||
|
run: mvn -U clean install -DskipTests --settings=.github/settings/maven-settings.xml
|
||||||
|
|
||||||
|
- name: 📦️ Build UI
|
||||||
|
working-directory: ./orion-visor-ui
|
||||||
|
run: |
|
||||||
|
pnpm install
|
||||||
|
pnpm build
|
||||||
|
|
||||||
|
- name: 📦️ Download instance-agent
|
||||||
|
working-directory: ./docker/service
|
||||||
|
run: wget https://github.com/lijiahangmax/orion-visor-agent/releases/latest/download/instance-agent-release.tar.gz -O instance-agent-release.tar.gz
|
||||||
|
|
||||||
|
- name: 📁 Prepare build context
|
||||||
|
run: |
|
||||||
|
cp -r ./sql ./docker/mysql/sql
|
||||||
|
cp -r ./orion-visor-ui/dist ./docker/ui/dist
|
||||||
|
cp ./orion-visor-launch/target/orion-visor-launch.jar ./docker/service/orion-visor-launch.jar
|
||||||
|
|
||||||
|
- name: 📤 Upload build context
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: docker-context
|
||||||
|
path: docker
|
||||||
|
|
||||||
|
build-and-push:
|
||||||
|
needs: build-project
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
packages: write
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
service: [ adminer, guacd, mysql, redis, influxdb, service, ui ]
|
||||||
|
|
||||||
|
env:
|
||||||
|
GITHUB_REGISTRY: ghcr.io
|
||||||
|
ALIYUN_REGISTRY: registry.cn-hangzhou.aliyuncs.com
|
||||||
|
ALIYUN_NAMESPACE: ${{ vars.ALIYUN_NAMESPACE }}
|
||||||
|
DOCKERHUB_NAMESPACE: ${{ vars.DOCKERHUB_NAMESPACE }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: 📥 Download build context
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: docker-context
|
||||||
|
path: docker
|
||||||
|
|
||||||
|
- name: ⚙️ Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v3
|
||||||
|
|
||||||
|
- name: 🔧 Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: 🐳 Login to Docker Hub
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: 🐳 Login to GitHub Container Registry
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ${{ env.GITHUB_REGISTRY }}
|
||||||
|
username: ${{ github.repository_owner }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: 🐳 Login to Aliyun Registry
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ${{ env.ALIYUN_REGISTRY }}
|
||||||
|
username: ${{ secrets.ALIYUN_USERNAME }}
|
||||||
|
password: ${{ secrets.ALIYUN_TOKEN }}
|
||||||
|
|
||||||
|
- name: 📦 Extract Docker metadata
|
||||||
|
id: meta
|
||||||
|
uses: docker/metadata-action@v5
|
||||||
|
with:
|
||||||
|
images: |
|
||||||
|
${{ env.DOCKERHUB_NAMESPACE }}/orion-visor-${{ matrix.service }}
|
||||||
|
${{ env.GITHUB_REGISTRY }}/${{ github.repository_owner }}/orion-visor-${{ matrix.service }}
|
||||||
|
${{ env.ALIYUN_REGISTRY }}/${{ env.ALIYUN_NAMESPACE }}/orion-visor-${{ matrix.service }}
|
||||||
|
tags: |
|
||||||
|
type=semver,pattern={{version}}
|
||||||
|
type=semver,pattern={{major}}.{{minor}}
|
||||||
|
type=semver,pattern={{major}}
|
||||||
|
|
||||||
|
- name: 🛠️ Build and push Docker image for orion-visor-${{ matrix.service }}
|
||||||
|
uses: docker/build-push-action@v6
|
||||||
|
with:
|
||||||
|
context: ./docker
|
||||||
|
file: ./docker/${{ matrix.service }}/Dockerfile
|
||||||
|
push: true
|
||||||
|
cache-from: type=gha
|
||||||
|
cache-to: type=gha,mode=max
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
|
tags: |
|
||||||
|
${{ env.DOCKERHUB_NAMESPACE }}/orion-visor-${{ matrix.service }}:${{ steps.meta.outputs.version }}
|
||||||
|
${{ env.DOCKERHUB_NAMESPACE }}/orion-visor-${{ matrix.service }}:latest
|
||||||
|
${{ env.GITHUB_REGISTRY }}/${{ github.repository_owner }}/orion-visor-${{ matrix.service }}:${{ steps.meta.outputs.version }}
|
||||||
|
${{ env.GITHUB_REGISTRY }}/${{ github.repository_owner }}/orion-visor-${{ matrix.service }}:latest
|
||||||
|
${{ env.ALIYUN_REGISTRY }}/${{ env.ALIYUN_NAMESPACE }}/orion-visor-${{ matrix.service }}:${{ steps.meta.outputs.version }}
|
||||||
|
${{ env.ALIYUN_REGISTRY }}/${{ env.ALIYUN_NAMESPACE }}/orion-visor-${{ matrix.service }}:latest
|
||||||
2
.github/workflows/e2e.yaml
vendored
2
.github/workflows/e2e.yaml
vendored
@@ -18,4 +18,4 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
sudo curl -L https://github.com/docker/compose/releases/download/v2.23.0/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose
|
sudo curl -L https://github.com/docker/compose/releases/download/v2.23.0/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose
|
||||||
sudo chmod u+x /usr/local/bin/docker-compose
|
sudo chmod u+x /usr/local/bin/docker-compose
|
||||||
docker compose -f docker-compose-testing.yml up --build testing --exit-code-from testing --remove-orphans
|
docker compose -f docker-compose-testing.yaml up --build testing --exit-code-from testing --remove-orphans
|
||||||
|
|||||||
2
NOTICE
2
NOTICE
@@ -5,5 +5,5 @@
|
|||||||
1. 禁止修改或删除 LICENSE 文件。
|
1. 禁止修改或删除 LICENSE 文件。
|
||||||
2. 禁止修改或删除源码头部的版权声明。
|
2. 禁止修改或删除源码头部的版权声明。
|
||||||
3. 本项目可免费商业使用,商业使用请保留项目源码、出处、描述文件和作者声明等。
|
3. 本项目可免费商业使用,商业使用请保留项目源码、出处、描述文件和作者声明等。
|
||||||
4. 分发源码时候,请注明软件出处 https://visor.dromara.org/
|
4. 分发源码时候,请注明软件出处 https://visor.orionsec.cn/
|
||||||
5. 不可二次开发或参与同类竞品的开发。
|
5. 不可二次开发或参与同类竞品的开发。
|
||||||
|
|||||||
33
README.md
33
README.md
@@ -48,10 +48,11 @@
|
|||||||
**`orion-visor`** 提供一站式自动化运维解决方案。
|
**`orion-visor`** 提供一站式自动化运维解决方案。
|
||||||
|
|
||||||
* **资产管理**:支持对资产进行分组,实现对主机、密钥和身份的统一管理和授权。
|
* **资产管理**:支持对资产进行分组,实现对主机、密钥和身份的统一管理和授权。
|
||||||
* **在线终端**:提供在线终端 SSH/RDP 等多种协议,支持快捷命令、自定义快捷键和主题风格。
|
* **在线终端**:提供在线终端 SSH/RDP/VNC 等多种协议,支持快捷命令、自定义快捷键和主题风格。
|
||||||
* **文件管理**:支持远程主机 SFTP 大文件的批量上传、下载和在线编辑等操作。
|
* **文件管理**:支持远程主机 SFTP 大文件的批量上传、下载和在线编辑等操作。
|
||||||
* **批量操作**:支持批量执行主机命令、多主机文件分发等功能。
|
* **批量操作**:支持批量执行主机命令、多主机文件分发等功能。
|
||||||
* **计划任务**:支持配置 cron 表达式,定时执行主机命令。
|
* **计划任务**:支持配置 cron 表达式,定时执行主机命令。
|
||||||
|
* **系统监控**:支持对主机 CPU、内存、磁盘、网络等系统指标的监控和告警。
|
||||||
* **安全可靠**:动态配置权限,记录用户操作日志,提供简单的审计功能。
|
* **安全可靠**:动态配置权限,记录用户操作日志,提供简单的审计功能。
|
||||||
|
|
||||||
## 演示环境
|
## 演示环境
|
||||||
@@ -62,9 +63,6 @@
|
|||||||
这对我很重要! [github](https://github.com/dromara/orion-visor) [gitee](https://gitee.com/dromara/orion-visor) [gitcode](https://gitcode.com/dromara/orion-visor)
|
这对我很重要! [github](https://github.com/dromara/orion-visor) [gitee](https://gitee.com/dromara/orion-visor) [gitcode](https://gitcode.com/dromara/orion-visor)
|
||||||
* 🌈 如果本项目对你有帮助请帮忙推广一下 让更多的人知道此项目!
|
* 🌈 如果本项目对你有帮助请帮忙推广一下 让更多的人知道此项目!
|
||||||
* 🎭 演示环境部分功能不可用, 完整功能请本地部署!
|
* 🎭 演示环境部分功能不可用, 完整功能请本地部署!
|
||||||
* 📛 演示环境请不要随便删除数据!
|
|
||||||
* 📧 如果演示环境不可用请联系我!
|
|
||||||
* 📨 **作者随缘寻java高级/资深内推 望京/5号/10号线 有坑位的联系我哦** 微信: `ljh1553488`
|
|
||||||
|
|
||||||
## 快速开始
|
## 快速开始
|
||||||
|
|
||||||
@@ -79,18 +77,19 @@ docker compose up -d
|
|||||||
|
|
||||||
## 项目文档
|
## 项目文档
|
||||||
|
|
||||||
* [文档地址](https://visor.dromara.org/)
|
* [文档地址](https://visor.orionsec.cn/)
|
||||||
* [安装文档](https://visor.dromara.org/quickstart/docker.html)
|
* [安装文档](https://visor.orionsec.cn/quickstart/docker.html)
|
||||||
* [更新日志](https://visor.dromara.org/update/change-log.html)
|
* [更新日志](https://visor.orionsec.cn/update/change-log.html)
|
||||||
* [操作手册](https://visor.dromara.org/operator/asset.html)
|
* [操作手册](https://visor.orionsec.cn/operator/asset.html)
|
||||||
* [常见问题](https://visor.dromara.org/support/faq.html)
|
* [常见问题](https://visor.orionsec.cn/support/faq.html)
|
||||||
|
|
||||||
## 技术栈
|
## 技术栈
|
||||||
|
|
||||||
* SpringBoot 2.7.17
|
* SpringBoot 2.7+
|
||||||
* Mysql 8.0+
|
* Mysql 8.0+
|
||||||
* Redis 6.0+
|
* Redis 6.0+
|
||||||
* Vue3 3.5+
|
* InfluxDB 2.7+
|
||||||
|
* Vue 3.5+
|
||||||
* Arco Design 2.56+
|
* Arco Design 2.56+
|
||||||
|
|
||||||
## 主要功能预览
|
## 主要功能预览
|
||||||
@@ -111,6 +110,11 @@ docker compose up -d
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
#### 主机监控
|
||||||
|
|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
#### 批量执行
|
#### 批量执行
|
||||||
|
|
||||||

|

|
||||||
@@ -130,7 +134,8 @@ docker compose up -d
|
|||||||
|
|
||||||
## 关于我
|
## 关于我
|
||||||
|
|
||||||
本人专注于使用 Java 和 Vue 进行全栈开发, 并在系统自动化运维方面拥有丰富开发的经验。如果您在这些领域有需求或遇到痛点, 请随时联系我, 并备注“合作”。
|
本人专注于使用 Java 和 Vue 进行全栈开发, 并在系统自动化运维方面拥有丰富开发的经验, 并提供企业级的解决方案。如果您在这些领域有需求或遇到痛点, 请随时联系我,
|
||||||
|
并备注“合作”。
|
||||||
|
|
||||||
## 联系我
|
## 联系我
|
||||||
|
|
||||||
@@ -156,6 +161,10 @@ QQ群: 755242157
|
|||||||
|
|
||||||
本项目遵循 [Apache-2.0](https://github.com/dromara/orion-visor/blob/main/LICENSE) 开源许可证。
|
本项目遵循 [Apache-2.0](https://github.com/dromara/orion-visor/blob/main/LICENSE) 开源许可证。
|
||||||
|
|
||||||
|
## 贡献者
|
||||||
|
|
||||||
|
[](https://github.com/dromara/orion-visor, "Contributors")
|
||||||
|
|
||||||
## Gitee 最有价值的开源项目 GVP
|
## Gitee 最有价值的开源项目 GVP
|
||||||
|
|
||||||

|

|
||||||
|
|||||||
@@ -5,7 +5,7 @@ services:
|
|||||||
image: registry.cn-hangzhou.aliyuncs.com/orionsec/orion-visor-service:latest
|
image: registry.cn-hangzhou.aliyuncs.com/orionsec/orion-visor-service:latest
|
||||||
privileged: true
|
privileged: true
|
||||||
ports:
|
ports:
|
||||||
- 9200:9200
|
- "9200:9200"
|
||||||
environment:
|
environment:
|
||||||
SPRING_PROFILES_ACTIVE: prod
|
SPRING_PROFILES_ACTIVE: prod
|
||||||
MYSQL_HOST: mysql
|
MYSQL_HOST: mysql
|
||||||
@@ -37,7 +37,7 @@ services:
|
|||||||
image: registry.cn-hangzhou.aliyuncs.com/orionsec/orion-visor-mysql:latest
|
image: registry.cn-hangzhou.aliyuncs.com/orionsec/orion-visor-mysql:latest
|
||||||
privileged: true
|
privileged: true
|
||||||
ports:
|
ports:
|
||||||
- 3307:3306
|
- "3307:3306"
|
||||||
environment:
|
environment:
|
||||||
MYSQL_DATABASE: orion_visor
|
MYSQL_DATABASE: orion_visor
|
||||||
MYSQL_USER: orion
|
MYSQL_USER: orion
|
||||||
@@ -59,7 +59,7 @@ services:
|
|||||||
image: registry.cn-hangzhou.aliyuncs.com/orionsec/orion-visor-redis:latest
|
image: registry.cn-hangzhou.aliyuncs.com/orionsec/orion-visor-redis:latest
|
||||||
privileged: true
|
privileged: true
|
||||||
ports:
|
ports:
|
||||||
- 6380:6379
|
- "6380:6379"
|
||||||
environment:
|
environment:
|
||||||
REDIS_PASSWORD: Data@123456
|
REDIS_PASSWORD: Data@123456
|
||||||
volumes:
|
volumes:
|
||||||
@@ -1,6 +1,12 @@
|
|||||||
version: '3.3'
|
version: '3.3'
|
||||||
|
|
||||||
# latest = 2.4.1
|
# latest = 2.5.0
|
||||||
|
|
||||||
|
# 支持以下源
|
||||||
|
# lijiahangmax/*
|
||||||
|
# ghcr.io/dromara/*
|
||||||
|
# registry.cn-hangzhou.aliyuncs.com/orionsec/*
|
||||||
|
|
||||||
services:
|
services:
|
||||||
ui:
|
ui:
|
||||||
image: registry.cn-hangzhou.aliyuncs.com/orionsec/orion-visor-ui:latest
|
image: registry.cn-hangzhou.aliyuncs.com/orionsec/orion-visor-ui:latest
|
||||||
@@ -17,7 +23,7 @@ services:
|
|||||||
image: registry.cn-hangzhou.aliyuncs.com/orionsec/orion-visor-service:latest
|
image: registry.cn-hangzhou.aliyuncs.com/orionsec/orion-visor-service:latest
|
||||||
privileged: true
|
privileged: true
|
||||||
ports:
|
ports:
|
||||||
- 9200:9200
|
- "9200:9200"
|
||||||
environment:
|
environment:
|
||||||
SPRING_PROFILES_ACTIVE: ${SPRING_PROFILES_ACTIVE:-prod}
|
SPRING_PROFILES_ACTIVE: ${SPRING_PROFILES_ACTIVE:-prod}
|
||||||
MYSQL_HOST: ${MYSQL_HOST:-mysql}
|
MYSQL_HOST: ${MYSQL_HOST:-mysql}
|
||||||
@@ -27,10 +33,20 @@ services:
|
|||||||
MYSQL_PASSWORD: ${MYSQL_PASSWORD:-Data@123456}
|
MYSQL_PASSWORD: ${MYSQL_PASSWORD:-Data@123456}
|
||||||
REDIS_HOST: ${REDIS_HOST:-redis}
|
REDIS_HOST: ${REDIS_HOST:-redis}
|
||||||
REDIS_PASSWORD: ${REDIS_PASSWORD:-Data@123456}
|
REDIS_PASSWORD: ${REDIS_PASSWORD:-Data@123456}
|
||||||
|
REDIS_DATABASE: ${REDIS_DATABASE:-0}
|
||||||
|
REDIS_DATA_VERSION: ${REDIS_DATA_VERSION:-1}
|
||||||
|
INFLUXDB_ENABLED: ${INFLUXDB_ENABLED:-true}
|
||||||
|
INFLUXDB_HOST: ${INFLUXDB_HOST:-influxdb}
|
||||||
|
INFLUXDB_PORT: ${INFLUXDB_PORT:-8086}
|
||||||
|
INFLUXDB_ORG: ${INFLUXDB_ORG:-orion-visor}
|
||||||
|
INFLUXDB_BUCKET: ${INFLUXDB_BUCKET:-metrics}
|
||||||
|
INFLUXDB_TOKEN: ${INFLUXDB_TOKEN:-Data@123456}
|
||||||
GUACD_HOST: ${GUACD_HOST:-guacd}
|
GUACD_HOST: ${GUACD_HOST:-guacd}
|
||||||
GUACD_PORT: ${GUACD_PORT:-4822}
|
GUACD_PORT: ${GUACD_PORT:-4822}
|
||||||
GUACD_DRIVE_PATH: ${GUACD_DRIVE_PATH:-/drive}
|
GUACD_DRIVE_PATH: ${GUACD_DRIVE_PATH:-/drive}
|
||||||
SECRET_KEY: ${SECRET_KEY:-uQeacXV8b3isvKLK}
|
SECRET_KEY: ${SECRET_KEY:-pmqeHOyZaumHm0Wt}
|
||||||
|
API_EXPOSE_TOKEN: ${API_EXPOSE_TOKEN:-uQeacXV8b3isvKLK}
|
||||||
|
API_CORS: ${API_CORS:-true}
|
||||||
DEMO_MODE: ${DEMO_MODE:-false}
|
DEMO_MODE: ${DEMO_MODE:-false}
|
||||||
volumes:
|
volumes:
|
||||||
- ${VOLUME_BASE:-/data/orion-visor-space/docker-volumes}/service/root-orion:/root/orion
|
- ${VOLUME_BASE:-/data/orion-visor-space/docker-volumes}/service/root-orion:/root/orion
|
||||||
@@ -46,6 +62,8 @@ services:
|
|||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
redis:
|
redis:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
|
influxdb:
|
||||||
|
condition: service_healthy
|
||||||
networks:
|
networks:
|
||||||
- orion-visor-net
|
- orion-visor-net
|
||||||
|
|
||||||
@@ -53,7 +71,7 @@ services:
|
|||||||
image: registry.cn-hangzhou.aliyuncs.com/orionsec/orion-visor-mysql:latest
|
image: registry.cn-hangzhou.aliyuncs.com/orionsec/orion-visor-mysql:latest
|
||||||
privileged: true
|
privileged: true
|
||||||
ports:
|
ports:
|
||||||
- 3307:3306
|
- "3307:3306"
|
||||||
environment:
|
environment:
|
||||||
MYSQL_DATABASE: ${MYSQL_DATABASE:-orion_visor}
|
MYSQL_DATABASE: ${MYSQL_DATABASE:-orion_visor}
|
||||||
MYSQL_USER: ${MYSQL_USER:-orion}
|
MYSQL_USER: ${MYSQL_USER:-orion}
|
||||||
@@ -76,7 +94,7 @@ services:
|
|||||||
image: registry.cn-hangzhou.aliyuncs.com/orionsec/orion-visor-redis:latest
|
image: registry.cn-hangzhou.aliyuncs.com/orionsec/orion-visor-redis:latest
|
||||||
privileged: true
|
privileged: true
|
||||||
ports:
|
ports:
|
||||||
- 6380:6379
|
- "6380:6379"
|
||||||
environment:
|
environment:
|
||||||
REDIS_PASSWORD: ${REDIS_PASSWORD:-Data@123456}
|
REDIS_PASSWORD: ${REDIS_PASSWORD:-Data@123456}
|
||||||
volumes:
|
volumes:
|
||||||
@@ -92,10 +110,35 @@ services:
|
|||||||
networks:
|
networks:
|
||||||
- orion-visor-net
|
- orion-visor-net
|
||||||
|
|
||||||
|
influxdb:
|
||||||
|
image: registry.cn-hangzhou.aliyuncs.com/orionsec/orion-visor-influxdb:latest
|
||||||
|
privileged: true
|
||||||
|
ports:
|
||||||
|
- "8086:8086"
|
||||||
|
environment:
|
||||||
|
DOCKER_INFLUXDB_INIT_MODE: setup
|
||||||
|
DOCKER_INFLUXDB_INIT_USERNAME: ${INFLUXDB_ADMIN_USERNAME:-admin}
|
||||||
|
DOCKER_INFLUXDB_INIT_PASSWORD: ${INFLUXDB_ADMIN_PASSWORD:-Data@123456}
|
||||||
|
DOCKER_INFLUXDB_INIT_ADMIN_TOKEN: ${INFLUXDB_TOKEN:-Data@123456}
|
||||||
|
DOCKER_INFLUXDB_INIT_ORG: ${INFLUXDB_ORG:-orion-visor}
|
||||||
|
DOCKER_INFLUXDB_INIT_BUCKET: ${INFLUXDB_BUCKET:-metrics}
|
||||||
|
volumes:
|
||||||
|
- ${VOLUME_BASE:-/data/orion-visor-space/docker-volumes}/influxdb/data:/var/lib/influxdb2
|
||||||
|
- ${VOLUME_BASE:-/data/orion-visor-space/docker-volumes}/influxdb/config:/etc/influxdb2
|
||||||
|
restart: unless-stopped
|
||||||
|
healthcheck:
|
||||||
|
test: [ "CMD", "bash", "-c", "cat < /dev/null > /dev/tcp/127.0.0.1/8086" ]
|
||||||
|
interval: 15s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 10
|
||||||
|
start_period: 10s
|
||||||
|
networks:
|
||||||
|
- orion-visor-net
|
||||||
|
|
||||||
guacd:
|
guacd:
|
||||||
image: registry.cn-hangzhou.aliyuncs.com/orionsec/orion-visor-guacd:latest
|
image: registry.cn-hangzhou.aliyuncs.com/orionsec/orion-visor-guacd:latest
|
||||||
ports:
|
ports:
|
||||||
- 4822:4822
|
- "4822:4822"
|
||||||
environment:
|
environment:
|
||||||
GUACD_LOG_LEVEL: info
|
GUACD_LOG_LEVEL: info
|
||||||
GUACD_LOG_FILE: /var/log/guacd.log
|
GUACD_LOG_FILE: /var/log/guacd.log
|
||||||
@@ -117,7 +160,7 @@ services:
|
|||||||
adminer:
|
adminer:
|
||||||
image: registry.cn-hangzhou.aliyuncs.com/orionsec/orion-visor-adminer:latest
|
image: registry.cn-hangzhou.aliyuncs.com/orionsec/orion-visor-adminer:latest
|
||||||
ports:
|
ports:
|
||||||
- 8081:8080
|
- "8081:8080"
|
||||||
environment:
|
environment:
|
||||||
ADMINER_DEFAULT_SERVER: ${MYSQL_HOST:-mysql}
|
ADMINER_DEFAULT_SERVER: ${MYSQL_HOST:-mysql}
|
||||||
depends_on:
|
depends_on:
|
||||||
@@ -1,16 +1,51 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# 停止并移除现有容器
|
# 初始化标志变量
|
||||||
docker compose down --remove-orphans
|
PULL_IMAGES=false
|
||||||
|
DEMO_MODE=false
|
||||||
|
|
||||||
if [ "$1" == "demo" ]; then
|
# 解析命令行参数
|
||||||
# 设置 DEMO_MODE 环境变量为 true
|
for arg in "$@"
|
||||||
|
do
|
||||||
|
case $arg in
|
||||||
|
--pull)
|
||||||
|
PULL_IMAGES=true
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--demo)
|
||||||
|
DEMO_MODE=true
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unknown argument: $arg"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# 停止并移除现有容器
|
||||||
|
echo "Stopping all services..."
|
||||||
|
docker compose down --remove-orphans
|
||||||
|
echo "Stopped all services..."
|
||||||
|
|
||||||
|
# 拉取镜像
|
||||||
|
if [ "$PULL_IMAGES" = true ]; then
|
||||||
|
echo "Pulling latest images..."
|
||||||
|
docker compose pull
|
||||||
|
echo "Pulled latest images..."
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$DEMO_MODE" = true ]; then
|
||||||
|
# 启用 demo 模式
|
||||||
export DEMO_MODE=true
|
export DEMO_MODE=true
|
||||||
echo "Starting services for demo mode..."
|
echo "Starting services for demo mode..."
|
||||||
|
|
||||||
# 启动指定的服务
|
# 启动指定的服务
|
||||||
docker compose up -d --remove-orphans mysql redis ui service adminer
|
docker compose up -d --remove-orphans mysql redis ui service guacd adminer
|
||||||
|
echo "Started services for demo mode..."
|
||||||
else
|
else
|
||||||
|
# 启动所有服务
|
||||||
echo "Starting all services..."
|
echo "Starting all services..."
|
||||||
# 正常启动所有服务
|
|
||||||
docker compose up -d --remove-orphans
|
docker compose up -d --remove-orphans
|
||||||
|
echo "Started all services..."
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
FROM adminer:latest
|
FROM --platform=$TARGETPLATFORM adminer:latest
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
#/bin/bash
|
|
||||||
set -e
|
|
||||||
version=2.4.1
|
|
||||||
docker build -t orion-visor-adminer:${version} .
|
|
||||||
docker tag orion-visor-adminer:${version} registry.cn-hangzhou.aliyuncs.com/orionsec/orion-visor-adminer:${version}
|
|
||||||
docker tag orion-visor-adminer:${version} registry.cn-hangzhou.aliyuncs.com/orionsec/orion-visor-adminer:latest
|
|
||||||
17
docker/builder/Dockerfile.service
Normal file
17
docker/builder/Dockerfile.service
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
#FROM --platform=$BUILDPLATFORM maven:3.9-amazoncorretto-8 AS builder
|
||||||
|
FROM maven:3.9-amazoncorretto-8 AS builder
|
||||||
|
|
||||||
|
# 设置阿里云镜像加速
|
||||||
|
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
|
||||||
|
|
||||||
|
# 拷贝 settings.xml
|
||||||
|
COPY ./docker/builder/maven-settings.xml /root/.m2/settings.xml
|
||||||
|
|
||||||
|
WORKDIR /build
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# 复制 POM 文件先进行依赖下载 (利用 Docker 缓存)
|
||||||
|
RUN mvn dependency:go-offline --settings=/root/.m2/settings.xml
|
||||||
|
# 构建
|
||||||
|
RUN mvn clean package -DskipTests --settings=/root/.m2/settings.xml
|
||||||
26
docker/builder/Dockerfile.ui
Normal file
26
docker/builder/Dockerfile.ui
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#FROM --platform=$BUILDPLATFORM node:18-alpine AS builder
|
||||||
|
FROM node:18-alpine AS builder
|
||||||
|
|
||||||
|
# 设置阿里云镜像加速
|
||||||
|
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
|
||||||
|
|
||||||
|
# 安装 pnpm
|
||||||
|
RUN corepack enable && corepack prepare pnpm@latest --activate
|
||||||
|
|
||||||
|
WORKDIR /build
|
||||||
|
|
||||||
|
# 设置 pnpm 使用指定的 registry
|
||||||
|
ARG REGISTRY_URL=https://registry.npmmirror.com
|
||||||
|
RUN pnpm config set registry $REGISTRY_URL
|
||||||
|
|
||||||
|
# 复制项目文件
|
||||||
|
COPY ./orion-visor-ui/package.json ./orion-visor-ui/pnpm-lock.yaml* ./
|
||||||
|
|
||||||
|
# 安装依赖 (利用 Docker 缓存层)
|
||||||
|
RUN pnpm install --frozen-lockfile
|
||||||
|
|
||||||
|
# 复制源代码
|
||||||
|
COPY ./orion-visor-ui/ .
|
||||||
|
|
||||||
|
# 构建项目
|
||||||
|
RUN pnpm build
|
||||||
55
docker/builder/maven-settings.xml
Normal file
55
docker/builder/maven-settings.xml
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
|
||||||
|
|
||||||
|
<profiles>
|
||||||
|
<profile>
|
||||||
|
<id>repos</id>
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
<!-- 阿里云 Maven 公共仓库 -->
|
||||||
|
<repository>
|
||||||
|
<id>aliyun</id>
|
||||||
|
<name>Aliyun Repository</name>
|
||||||
|
<url>https://maven.aliyun.com/repository/public</url>
|
||||||
|
<releases>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
</releases>
|
||||||
|
<snapshots>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
</snapshots>
|
||||||
|
</repository>
|
||||||
|
|
||||||
|
<!-- Maven 中央仓库 -->
|
||||||
|
<repository>
|
||||||
|
<id>central</id>
|
||||||
|
<name>Maven Central Repository</name>
|
||||||
|
<url>https://repo.maven.apache.org/maven2</url>
|
||||||
|
<releases>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
</releases>
|
||||||
|
<snapshots>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</snapshots>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
|
||||||
|
<pluginRepositories>
|
||||||
|
<pluginRepository>
|
||||||
|
<id>aliyun-plugin</id>
|
||||||
|
<url>https://maven.aliyun.com/repository/public</url>
|
||||||
|
</pluginRepository>
|
||||||
|
<pluginRepository>
|
||||||
|
<id>central-plugin</id>
|
||||||
|
<url>https://repo.maven.apache.org/maven2</url>
|
||||||
|
</pluginRepository>
|
||||||
|
</pluginRepositories>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
|
|
||||||
|
<!-- 激活 profile -->
|
||||||
|
<activeProfiles>
|
||||||
|
<activeProfile>repos</activeProfile>
|
||||||
|
</activeProfiles>
|
||||||
|
|
||||||
|
</settings>
|
||||||
233
docker/docker-build.sh
Normal file
233
docker/docker-build.sh
Normal file
@@ -0,0 +1,233 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# DockerContext: orion-visor/docker
|
||||||
|
|
||||||
|
# 加载项目构建
|
||||||
|
source ./project-build.sh "$@"
|
||||||
|
|
||||||
|
# 版本号
|
||||||
|
version=2.5.0
|
||||||
|
# 是否推送镜像
|
||||||
|
push_image=false
|
||||||
|
# 是否构建 latest
|
||||||
|
latest_image=false
|
||||||
|
# 是否本地构建
|
||||||
|
locally_build=false
|
||||||
|
# 备份后缀
|
||||||
|
backup_suffix=".bak"
|
||||||
|
# 镜像命名空间
|
||||||
|
namespace="registry.cn-hangzhou.aliyuncs.com/orionsec"
|
||||||
|
|
||||||
|
# 解析命令行参数
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
-l|--locally)
|
||||||
|
locally_build=true
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-latest|--latest-image)
|
||||||
|
latest_image=true
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-push|--push-image)
|
||||||
|
push_image=true
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# 要处理的 Dockerfile 列表及对应的镜像名称
|
||||||
|
declare -A images=(
|
||||||
|
["./ui/Dockerfile"]="orion-visor-ui"
|
||||||
|
["./service/Dockerfile"]="orion-visor-service"
|
||||||
|
["./mysql/Dockerfile"]="orion-visor-mysql"
|
||||||
|
["./redis/Dockerfile"]="orion-visor-redis"
|
||||||
|
["./influxdb/Dockerfile"]="orion-visor-influxdb"
|
||||||
|
["./adminer/Dockerfile"]="orion-visor-adminer"
|
||||||
|
["./guacd/Dockerfile"]="orion-visor-guacd"
|
||||||
|
)
|
||||||
|
|
||||||
|
# 准备 service jar
|
||||||
|
function prepare_app_jar() {
|
||||||
|
local source_file="../orion-visor-launch/target/orion-visor-launch.jar"
|
||||||
|
local target_file="./service/orion-visor-launch.jar"
|
||||||
|
if [ ! -f "$target_file" ]; then
|
||||||
|
echo "警告: $target_file 不存在, 正在尝试从 $source_file 复制..."
|
||||||
|
if [ -f "$source_file" ]; then
|
||||||
|
cp "$source_file" "$target_file"
|
||||||
|
echo "已成功复制 $source_file 至 $target_file"
|
||||||
|
else
|
||||||
|
echo "错误: $source_file 不存在, 无法继续构建."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "$target_file 已存在, 无需复制."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# 准备 instance-agent
|
||||||
|
function prepare_instance_agent() {
|
||||||
|
local target_file="./service/instance-agent-release.tar.gz"
|
||||||
|
if [ ! -f "$target_file" ]; then
|
||||||
|
echo "警告: $target_file 不存在, 正在尝试从 Github Release 下载..."
|
||||||
|
# 尝试从 GitHub Release 下载
|
||||||
|
if curl -L --fail \
|
||||||
|
--connect-timeout 30 --max-time 30 \
|
||||||
|
https://github.com/lijiahangmax/orion-visor-agent/releases/latest/download/instance-agent-release.tar.gz \
|
||||||
|
-o "$target_file"; then
|
||||||
|
echo "已成功下载到 $target_file"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 如果下载失败, 提示用户手动下载
|
||||||
|
echo "错误: 无法从 Release 获取 instance-agent-release.tar.gz"
|
||||||
|
echo "请手动从以下地址下载, 并放置到 $target_file"
|
||||||
|
echo " 1) https://github.com/lijiahangmax/orion-visor-agent/raw/main/instance-agent-release.tar.gz"
|
||||||
|
echo " 2) https://gitee.com/lijiahangmax/orion-visor-agent/raw/main/instance-agent-release.tar.gz"
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
echo "$target_file 已存在, 无需下载."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# 准备前端 dist 目录
|
||||||
|
function prepare_dist_directory() {
|
||||||
|
local source_dir="../orion-visor-ui/dist"
|
||||||
|
local target_dir="./ui/dist"
|
||||||
|
if [ ! -d "$target_dir" ]; then
|
||||||
|
echo "警告: $target_dir 不存在, 正在尝试从 $source_dir 复制..."
|
||||||
|
if [ -d "$source_dir" ]; then
|
||||||
|
cp -r "$source_dir" "$target_dir"
|
||||||
|
echo "已成功复制 $source_dir 至 $target_dir"
|
||||||
|
else
|
||||||
|
echo "错误: $source_dir 不存在, 无法继续构建."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "$target_dir 已存在, 无需复制."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# 准备 mysql sql 目录
|
||||||
|
function prepare_sql_directory() {
|
||||||
|
local source_dir="../sql"
|
||||||
|
local target_dir="./mysql/sql"
|
||||||
|
if [ ! -d "$target_dir" ]; then
|
||||||
|
echo "警告: $target_dir 不存在, 正在尝试从 $source_dir 复制..."
|
||||||
|
if [ -d $source_dir ]; then
|
||||||
|
cp -r $source_dir "$target_dir"
|
||||||
|
echo "已成功复制 ../sql 至 $target_dir"
|
||||||
|
else
|
||||||
|
echo "错误: $source_dir 不存在!根据预期它应该存在, 请确认路径或项目结构是否正确"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "$target_dir 已存在, 无需复制."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# 修改 Dockerfile 前的备份
|
||||||
|
function modify_dockerfiles() {
|
||||||
|
if [ "$locally_build" = false ]; then
|
||||||
|
echo "跳过 Dockerfile 修改"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
echo "正在备份并修改 Dockerfile..."
|
||||||
|
for file in "${!images[@]}"; do
|
||||||
|
if [ -f "$file" ]; then
|
||||||
|
echo "备份并修改: $file"
|
||||||
|
cp "$file" "$file$backup_suffix"
|
||||||
|
sed -i 's/--platform=\TARGETPLATFORM//g' "$file"
|
||||||
|
else
|
||||||
|
echo "文件不存在 -> $file"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# 恢复原始 Dockerfile
|
||||||
|
function restore_dockerfiles() {
|
||||||
|
if [ "$locally_build" = false ]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
echo "开始恢复 Dockerfile"
|
||||||
|
for file in "${!images[@]}"; do
|
||||||
|
if [ -f "$file$backup_suffix" ]; then
|
||||||
|
echo "恢复: $file"
|
||||||
|
rm -rf "$file"
|
||||||
|
mv "$file$backup_suffix" "$file"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo "Dockerfile 已恢复为原始版本"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 构建镜像
|
||||||
|
function build_images() {
|
||||||
|
echo "构建镜像开始..."
|
||||||
|
for dockerfile in "${!images[@]}"; do
|
||||||
|
image_name="${images[$dockerfile]}"
|
||||||
|
echo "Building $image_name with version $version."
|
||||||
|
# 构建 Docker 镜像
|
||||||
|
docker build -f "$dockerfile" -t "${image_name}:${version}" -t "${namespace}/${image_name}:${version}" .
|
||||||
|
# 添加 latest 标签
|
||||||
|
if [ "$latest_image" = true ]; then
|
||||||
|
echo "Tag $image_name with latest version."
|
||||||
|
docker tag "${image_name}:${version}" "${image_name}:latest"
|
||||||
|
docker tag "${namespace}/${image_name}:${version}" "${namespace}/${image_name}:latest"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo "构建镜像结束..."
|
||||||
|
}
|
||||||
|
|
||||||
|
# 推送镜像
|
||||||
|
function push_image_to_registry() {
|
||||||
|
if [ "$push_image" = true ]; then
|
||||||
|
echo "推送镜像开始..."
|
||||||
|
for image_name in "${images[@]}"; do
|
||||||
|
# 推送版本
|
||||||
|
docker push "${namespace}/${image_name}:${version}"
|
||||||
|
# 推送 latest
|
||||||
|
if [ "latest_image" = true ]; then
|
||||||
|
docker push "${namespace}/${image_name}:latest"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo "推送镜像结束..."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# 构建项目-service
|
||||||
|
if [ "$build_service" = true ]; then
|
||||||
|
run_build_service
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 构建项目-ui
|
||||||
|
if [ "$build_ui" = true ]; then
|
||||||
|
run_build_ui
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 检查资源
|
||||||
|
echo "正在检查并准备必要的构建资源..."
|
||||||
|
prepare_app_jar
|
||||||
|
prepare_instance_agent
|
||||||
|
prepare_dist_directory
|
||||||
|
prepare_sql_directory
|
||||||
|
echo "所有前置资源已准备完毕"
|
||||||
|
|
||||||
|
# 修改镜像文件
|
||||||
|
modify_dockerfiles
|
||||||
|
|
||||||
|
# 设置异常捕获, 确保失败时恢复 Dockerfile
|
||||||
|
trap 'restore_dockerfiles; echo "构建失败, 已恢复原始 Dockerfile"; exit 1' ERR INT
|
||||||
|
|
||||||
|
# 构建镜像
|
||||||
|
build_images
|
||||||
|
|
||||||
|
# 推送镜像
|
||||||
|
push_image_to_registry
|
||||||
|
|
||||||
|
# 恢复原始 Dockerfile
|
||||||
|
restore_dockerfiles
|
||||||
|
trap - ERR INT
|
||||||
|
echo "构建完成"
|
||||||
@@ -1,10 +1,17 @@
|
|||||||
FROM guacamole/guacd:1.6.0
|
FROM --platform=$TARGETPLATFORM guacamole/guacd:1.6.0
|
||||||
|
|
||||||
USER root
|
USER root
|
||||||
|
|
||||||
# 系统时区
|
# 系统时区
|
||||||
ARG TZ=Asia/Shanghai
|
ARG TZ=Asia/Shanghai
|
||||||
# 设置时区
|
|
||||||
RUN ln -sf /usr/share/zoneinfo/${TZ} /etc/localtime && \
|
# 添加包 & 设置时区
|
||||||
echo '${TZ}' > /etc/timezone
|
RUN \
|
||||||
|
sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories && \
|
||||||
|
apk update && \
|
||||||
|
apk add --no-cache tzdata && \
|
||||||
|
ln -sf /usr/share/zoneinfo/${TZ} /etc/localtime && \
|
||||||
|
echo "${TZ}" > /etc/timezone
|
||||||
|
|
||||||
# 创建所需目录
|
# 创建所需目录
|
||||||
RUN mkdir -p /home/guacd/drive /usr/share/guacd/drive
|
RUN mkdir -p /home/guacd/drive /usr/share/guacd/drive
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
#/bin/bash
|
|
||||||
set -e
|
|
||||||
version=2.4.1
|
|
||||||
docker build -t orion-visor-guacd:${version} .
|
|
||||||
docker tag orion-visor-guacd:${version} registry.cn-hangzhou.aliyuncs.com/orionsec/orion-visor-guacd:${version}
|
|
||||||
docker tag orion-visor-guacd:${version} registry.cn-hangzhou.aliyuncs.com/orionsec/orion-visor-guacd:latest
|
|
||||||
8
docker/influxdb/Dockerfile
Normal file
8
docker/influxdb/Dockerfile
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
FROM --platform=$TARGETPLATFORM influxdb:2
|
||||||
|
|
||||||
|
# 系统时区
|
||||||
|
ARG TZ=Asia/Shanghai
|
||||||
|
|
||||||
|
# 设置时区
|
||||||
|
RUN ln -sf /usr/share/zoneinfo/${TZ} /etc/localtime && \
|
||||||
|
echo "${TZ}" > /etc/timezone
|
||||||
@@ -1,19 +1,18 @@
|
|||||||
FROM mysql:8.0.28
|
FROM --platform=$TARGETPLATFORM mysql:8.0.39
|
||||||
|
|
||||||
# 系统时区
|
# 系统时区
|
||||||
ARG TZ=Asia/Shanghai
|
ARG TZ=Asia/Shanghai
|
||||||
|
|
||||||
# 设置时区
|
# 设置时区
|
||||||
RUN ln -sf /usr/share/zoneinfo/${TZ} /etc/localtime && \
|
RUN ln -sf /usr/share/zoneinfo/${TZ} /etc/localtime && \
|
||||||
echo '${TZ}' > /etc/timezone
|
echo "${TZ}" > /etc/timezone
|
||||||
# 复制配置
|
|
||||||
COPY ./my.cnf /etc/mysql/conf.d/my.cnf
|
# 复制配置文件
|
||||||
|
COPY ./mysql/my.cnf /etc/mysql/conf.d/my.cnf
|
||||||
|
|
||||||
# 复制初始化脚本
|
# 复制初始化脚本
|
||||||
COPY ./sql/init-1-schema-databases.sql /tmp
|
COPY ./mysql/sql/init-*.sql /docker-entrypoint-initdb.d/
|
||||||
COPY ./sql/init-2-schema-tables.sql /tmp
|
|
||||||
COPY ./sql/init-3-schema-quartz.sql /tmp
|
# 心跳检测
|
||||||
COPY ./sql/init-4-data.sql /tmp
|
HEALTHCHECK --interval=10s --timeout=3s --start-period=3s --retries=3 \
|
||||||
# 设置初始化脚本
|
CMD mysqladmin ping -h localhost -u root --password=${MYSQL_ROOT_PASSWORD} || exit 1
|
||||||
RUN cat /tmp/init-1-schema-databases.sql >> /tmp/init.sql && \
|
|
||||||
cat /tmp/init-2-schema-tables.sql >> /tmp/init.sql && \
|
|
||||||
cat /tmp/init-3-schema-quartz.sql >> /tmp/init.sql && \
|
|
||||||
cat /tmp/init-4-data.sql >> /tmp/init.sql && \
|
|
||||||
cp /tmp/init.sql /docker-entrypoint-initdb.d
|
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
#/bin/bash
|
|
||||||
set -e
|
|
||||||
version=2.4.1
|
|
||||||
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/orionsec/orion-visor-mysql:${version}
|
|
||||||
docker tag orion-visor-mysql:${version} registry.cn-hangzhou.aliyuncs.com/orionsec/orion-visor-mysql:latest
|
|
||||||
125
docker/project-build.sh
Normal file
125
docker/project-build.sh
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# DockerContext: orion-visor
|
||||||
|
|
||||||
|
# 版本号
|
||||||
|
version=2.5.0
|
||||||
|
# 是否构建 service
|
||||||
|
export build_service=false
|
||||||
|
# 是否构建 ui
|
||||||
|
export build_ui=false
|
||||||
|
|
||||||
|
# 解析命令行参数
|
||||||
|
for arg in "$@"; do
|
||||||
|
case "$arg" in
|
||||||
|
-service|--build-service)
|
||||||
|
export build_service=true
|
||||||
|
;;
|
||||||
|
-ui|--build-ui)
|
||||||
|
export build_ui=true
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# 执行构建 service
|
||||||
|
function run_build_service() {
|
||||||
|
echo "开始执行 service 构建流程..."
|
||||||
|
|
||||||
|
local builder_dockerfile="./builder/Dockerfile.service"
|
||||||
|
local builder_image="orion-visor-service-builder"
|
||||||
|
local builder_container="orion-visor-service-builder-ctn"
|
||||||
|
local builder_output="/build/orion-visor-launch/target/orion-visor-launch.jar"
|
||||||
|
local target_dir="../orion-visor-launch/target"
|
||||||
|
local target_jar="$target_dir/orion-visor-launch.jar"
|
||||||
|
|
||||||
|
# 确保目标目录存在
|
||||||
|
if [ ! -d "$target_dir" ]; then
|
||||||
|
echo "创建目标目录: $target_dir"
|
||||||
|
mkdir -p "$target_dir"
|
||||||
|
else
|
||||||
|
# 如果 jar 已存在, 先删除
|
||||||
|
if [ -f "$target_jar" ]; then
|
||||||
|
echo "删除已有文件: $target_jar"
|
||||||
|
rm -f "$target_jar"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 清理旧容器
|
||||||
|
local container_id=$(docker ps -a -f "name=$builder_container" --format "{{.ID}}")
|
||||||
|
if [ -n "$container_id" ]; then
|
||||||
|
echo "删除旧容器: $builder_container"
|
||||||
|
docker rm -f "$container_id"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 构建构建镜像
|
||||||
|
echo "正在构建 service builder image..."
|
||||||
|
docker build \
|
||||||
|
-f "$builder_dockerfile" \
|
||||||
|
-t "$builder_image:$version" ../
|
||||||
|
|
||||||
|
# 创建一个临时容器用于拷贝文件
|
||||||
|
echo "创建临时容器以提取 jar 文件..."
|
||||||
|
docker create --name "$builder_container" "$builder_image:$version" > /dev/null
|
||||||
|
|
||||||
|
# 拷贝构建好的 jar 文件到目标路径
|
||||||
|
echo "正在从容器中拷贝 jar 文件..."
|
||||||
|
docker cp "$builder_container:$builder_output" "$target_jar"
|
||||||
|
|
||||||
|
# 清理临时容器
|
||||||
|
docker rm -f "$builder_container" > /dev/null
|
||||||
|
echo "后端构建完成, jar 文件已保存至: $target_jar"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 执行构建 ui
|
||||||
|
function run_build_ui() {
|
||||||
|
echo "开始执行 ui 构建流程..."
|
||||||
|
|
||||||
|
local builder_dockerfile="./builder/Dockerfile.ui"
|
||||||
|
local builder_image="orion-visor-ui-builder"
|
||||||
|
local builder_container="orion-visor-ui-builder-ctn"
|
||||||
|
local builder_output="/build/dist"
|
||||||
|
local target_dir="../orion-visor-ui/dist"
|
||||||
|
|
||||||
|
# 如果 dist 已存在, 先删除
|
||||||
|
if [ -d "$target_dir" ]; then
|
||||||
|
echo "删除已有目录: $target_dir"
|
||||||
|
rm -rf "$target_dir"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 清理旧容器
|
||||||
|
local container_id=$(docker ps -a -f "name=$builder_container" --format "{{.ID}}")
|
||||||
|
if [ -n "$container_id" ]; then
|
||||||
|
echo "删除旧容器: $builder_container"
|
||||||
|
docker rm -f "$container_id"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 构建前端镜像
|
||||||
|
echo "正在构建 ui builder image..."
|
||||||
|
docker build \
|
||||||
|
-f "$builder_dockerfile" \
|
||||||
|
-t "$builder_image:$version" ../
|
||||||
|
|
||||||
|
# 创建临时容器用于拷贝文件
|
||||||
|
echo "创建临时容器以提取 dist 文件..."
|
||||||
|
docker create --name "$builder_container" "$builder_image:$version" > /dev/null
|
||||||
|
|
||||||
|
# 拷贝 dist 目录
|
||||||
|
echo "正在从容器中拷贝 dist 文件..."
|
||||||
|
docker cp "$builder_container:$builder_output" "$target_dir"
|
||||||
|
|
||||||
|
# 清理临时容器
|
||||||
|
docker rm "$builder_container" > /dev/null
|
||||||
|
|
||||||
|
echo "前端构建完成, dist 已保存至: $target_dir"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 构建项目-service
|
||||||
|
if [ "$build_service" = true ]; then
|
||||||
|
run_build_service
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 构建项目-ui
|
||||||
|
if [ "$build_ui" = true ]; then
|
||||||
|
run_build_ui
|
||||||
|
fi
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
#/bin/bash
|
|
||||||
set -e
|
|
||||||
version=2.4.1
|
|
||||||
docker push registry.cn-hangzhou.aliyuncs.com/orionsec/orion-visor-adminer:${version}
|
|
||||||
docker push registry.cn-hangzhou.aliyuncs.com/orionsec/orion-visor-mysql:${version}
|
|
||||||
docker push registry.cn-hangzhou.aliyuncs.com/orionsec/orion-visor-redis:${version}
|
|
||||||
docker push registry.cn-hangzhou.aliyuncs.com/orionsec/orion-visor-guacd:${version}
|
|
||||||
docker push registry.cn-hangzhou.aliyuncs.com/orionsec/orion-visor-service:${version}
|
|
||||||
docker push registry.cn-hangzhou.aliyuncs.com/orionsec/orion-visor-ui:${version}
|
|
||||||
docker push registry.cn-hangzhou.aliyuncs.com/orionsec/orion-visor-adminer:latest
|
|
||||||
docker push registry.cn-hangzhou.aliyuncs.com/orionsec/orion-visor-mysql:latest
|
|
||||||
docker push registry.cn-hangzhou.aliyuncs.com/orionsec/orion-visor-redis:latest
|
|
||||||
docker push registry.cn-hangzhou.aliyuncs.com/orionsec/orion-visor-guacd:latest
|
|
||||||
docker push registry.cn-hangzhou.aliyuncs.com/orionsec/orion-visor-service:latest
|
|
||||||
docker push registry.cn-hangzhou.aliyuncs.com/orionsec/orion-visor-ui:latest
|
|
||||||
@@ -1,15 +1,22 @@
|
|||||||
FROM redis:6.0.16-alpine
|
FROM --platform=$TARGETPLATFORM redis:6.0.16-alpine
|
||||||
|
|
||||||
WORKDIR /data
|
WORKDIR /data
|
||||||
|
|
||||||
# 系统时区
|
# 系统时区
|
||||||
ARG TZ=Asia/Shanghai
|
ARG TZ=Asia/Shanghai
|
||||||
# 添加包
|
|
||||||
|
# 添加包 & 设置时区
|
||||||
RUN \
|
RUN \
|
||||||
sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories && \
|
sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories && \
|
||||||
apk update && \
|
apk update && \
|
||||||
apk add tzdata
|
apk add --no-cache tzdata && \
|
||||||
# 设置时区
|
ln -sf /usr/share/zoneinfo/${TZ} /etc/localtime && \
|
||||||
RUN ln -sf /usr/share/zoneinfo/${TZ} /etc/localtime && \
|
echo "${TZ}" > /etc/timezone && \
|
||||||
echo '${TZ}' > /etc/timezone
|
rm -rf /var/cache/apk/* && \
|
||||||
# redis 配置
|
rm -f /usr/local/redis.conf
|
||||||
COPY ./redis.conf /tmp
|
|
||||||
RUN cat /tmp/redis.conf > /usr/local/redis.conf
|
# 复制配置文件
|
||||||
|
COPY ./redis/redis.conf /usr/local/redis.conf
|
||||||
|
|
||||||
|
# 启动 Redis 并加载自定义配置
|
||||||
|
CMD ["redis-server", "/usr/local/redis.conf"]
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
#/bin/bash
|
|
||||||
set -e
|
|
||||||
version=2.4.1
|
|
||||||
docker build -t orion-visor-redis:${version} .
|
|
||||||
docker tag orion-visor-redis:${version} registry.cn-hangzhou.aliyuncs.com/orionsec/orion-visor-redis:${version}
|
|
||||||
docker tag orion-visor-redis:${version} registry.cn-hangzhou.aliyuncs.com/orionsec/orion-visor-redis:latest
|
|
||||||
@@ -1,20 +1,35 @@
|
|||||||
FROM openjdk:8-jdk-alpine
|
FROM --platform=$TARGETPLATFORM openjdk:8-jdk-alpine
|
||||||
|
|
||||||
USER root
|
USER root
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# 系统时区
|
# 系统时区
|
||||||
ARG TZ=Asia/Shanghai
|
ARG TZ=Asia/Shanghai
|
||||||
# 添加包
|
|
||||||
|
# 添加包 & 设置时区
|
||||||
RUN \
|
RUN \
|
||||||
sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories && \
|
sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories && \
|
||||||
apk update && \
|
apk update && \
|
||||||
apk add curl && \
|
apk add curl && \
|
||||||
apk add udev && \
|
apk add udev && \
|
||||||
apk add tzdata && \
|
apk add tzdata && \
|
||||||
apk add dmidecode
|
ln -sf /usr/share/zoneinfo/${TZ} /etc/localtime && \
|
||||||
# 设置时区
|
echo "${TZ}" > /etc/timezone
|
||||||
RUN ln -sf /usr/share/zoneinfo/${TZ} /etc/localtime && \
|
|
||||||
echo '${TZ}' > /etc/timezone
|
# 复制启动脚本
|
||||||
# 复制包
|
COPY ./service/entrypoint.sh /app/entrypoint.sh
|
||||||
COPY ./orion-visor-launch.jar /app/app.jar
|
RUN chmod +x /app/entrypoint.sh
|
||||||
|
|
||||||
|
# 复制 jar 包
|
||||||
|
COPY ./service/orion-visor-launch.jar /app/app.jar
|
||||||
|
# 复制探针包
|
||||||
|
ADD ./service/instance-agent-release.tar.gz /app/instance-agent-release
|
||||||
|
|
||||||
|
# 启动检测
|
||||||
|
HEALTHCHECK --interval=15s --timeout=5s --retries=5 --start-period=10s \
|
||||||
|
CMD wget -T5 -qO- http://127.0.0.1:9200/orion-visor/api/server/bootstrap/health | grep ok || exit 1
|
||||||
|
|
||||||
# 启动
|
# 启动
|
||||||
|
ENTRYPOINT ["/app/entrypoint.sh"]
|
||||||
CMD ["java", "-jar", "/app/app.jar"]
|
CMD ["java", "-jar", "/app/app.jar"]
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
#/bin/bash
|
|
||||||
set -e
|
|
||||||
version=2.4.1
|
|
||||||
mv ../../orion-visor-launch/target/orion-visor-launch.jar ./orion-visor-launch.jar
|
|
||||||
docker build -t orion-visor-service:${version} .
|
|
||||||
rm -rf ./orion-visor-launch.jar
|
|
||||||
docker tag orion-visor-service:${version} registry.cn-hangzhou.aliyuncs.com/orionsec/orion-visor-service:${version}
|
|
||||||
docker tag orion-visor-service:${version} registry.cn-hangzhou.aliyuncs.com/orionsec/orion-visor-service:latest
|
|
||||||
23
docker/service/entrypoint.sh
Normal file
23
docker/service/entrypoint.sh
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
AGENT_RELEASE_DIR="/root/orion/orion-visor/instance-agent-release"
|
||||||
|
DEFAULT_AGENT_DIR="/app/instance-agent-release"
|
||||||
|
|
||||||
|
# 确保父目录存在
|
||||||
|
mkdir -p "$(dirname "$AGENT_RELEASE_DIR")"
|
||||||
|
|
||||||
|
# 加载探针
|
||||||
|
if [ -d "$AGENT_RELEASE_DIR" ] && [ -n "$(ls -A "$AGENT_RELEASE_DIR" 2>/dev/null)" ]; then
|
||||||
|
echo "Using mounted agent release: $AGENT_RELEASE_DIR"
|
||||||
|
else
|
||||||
|
echo "Using default agent release: $DEFAULT_AGENT_DIR"
|
||||||
|
# 复制探针
|
||||||
|
cp -rf "$DEFAULT_AGENT_DIR" "$AGENT_RELEASE_DIR"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 打印探针版本信息
|
||||||
|
if [ -f "$AGENT_RELEASE_DIR/.version" ]; then
|
||||||
|
echo "Agent version: $(cat "$AGENT_RELEASE_DIR/.version")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec "$@"
|
||||||
@@ -1,18 +1,23 @@
|
|||||||
FROM nginx:alpine
|
FROM --platform=$TARGETPLATFORM nginx:alpine
|
||||||
|
|
||||||
# 系统时区
|
# 系统时区
|
||||||
ARG TZ=Asia/Shanghai
|
ARG TZ=Asia/Shanghai
|
||||||
# 添加包
|
|
||||||
|
# 添加包 & 设置时区
|
||||||
RUN \
|
RUN \
|
||||||
sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories && \
|
sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories && \
|
||||||
apk update && \
|
apk update && \
|
||||||
apk add tzdata
|
apk add --no-cache tzdata && \
|
||||||
# 设置时区
|
ln -sf /usr/share/zoneinfo/${TZ} /etc/localtime && \
|
||||||
RUN ln -sf /usr/share/zoneinfo/${TZ} /etc/localtime && \
|
echo "${TZ}" > /etc/timezone && \
|
||||||
echo '${TZ}' > /etc/timezone
|
rm -rf /var/cache/apk/* && \
|
||||||
# 删除原 nginx 配置
|
rm -rf /etc/nginx/conf.d/*
|
||||||
RUN rm -rf /etc/nginx/conf.d/*
|
|
||||||
# 复制包
|
# 复制包
|
||||||
COPY ./dist /usr/share/nginx/html
|
COPY ./ui/dist /usr/share/nginx/html
|
||||||
COPY ./nginx.conf /etc/nginx/conf.d
|
|
||||||
|
# 复制配置
|
||||||
|
COPY ./ui/nginx.conf /etc/nginx/conf.d
|
||||||
|
|
||||||
# 启动
|
# 启动
|
||||||
CMD ["nginx", "-g", "daemon off;"]
|
CMD ["nginx", "-g", "daemon off;"]
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
#/bin/bash
|
|
||||||
set -e
|
|
||||||
version=2.4.1
|
|
||||||
mv ../../orion-visor-ui/dist ./dist
|
|
||||||
docker build -t orion-visor-ui:${version} .
|
|
||||||
rm -rf ./orion-visor-launch.jar
|
|
||||||
rm -rf ./dist
|
|
||||||
docker tag orion-visor-ui:${version} registry.cn-hangzhou.aliyuncs.com/orionsec/orion-visor-ui:${version}
|
|
||||||
docker tag orion-visor-ui:${version} registry.cn-hangzhou.aliyuncs.com/orionsec/orion-visor-ui:latest
|
|
||||||
5
docs/README.md
Normal file
5
docs/README.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
## 文档已迁移至在线文档
|
||||||
|
|
||||||
|
* https://visor.dromara.org
|
||||||
|
* https://visor.dromara.org.cn
|
||||||
|
* https://visor.orionsec.cn
|
||||||
BIN
docs/assets/screenshot/monitor-detail.png
Normal file
BIN
docs/assets/screenshot/monitor-detail.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 232 KiB |
BIN
docs/assets/screenshot/monitor-list.png
Normal file
BIN
docs/assets/screenshot/monitor-list.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 153 KiB |
9
git-pull.sh
Normal file
9
git-pull.sh
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# 清空
|
||||||
|
git clean -df
|
||||||
|
# 切换到 HEAD
|
||||||
|
git reset --hard HEAD
|
||||||
|
# 拉取远程
|
||||||
|
git pull
|
||||||
|
# 查看日志
|
||||||
|
git log -n 1
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.dromara.visor.common.interfaces;
|
package org.dromara.visor.common.cipher;
|
||||||
|
|
||||||
import cn.orionsec.kit.lang.utils.codec.Base62s;
|
import cn.orionsec.kit.lang.utils.codec.Base62s;
|
||||||
import cn.orionsec.kit.lang.utils.crypto.symmetric.SymmetricCrypto;
|
import cn.orionsec.kit.lang.utils.crypto.symmetric.SymmetricCrypto;
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.dromara.visor.common.interfaces;
|
package org.dromara.visor.common.cipher;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* rsa 解密器
|
* rsa 解密器
|
||||||
@@ -36,7 +36,7 @@ public interface AppConst extends OrionConst {
|
|||||||
/**
|
/**
|
||||||
* 同 ${orion.version} 迭代时候需要手动更改
|
* 同 ${orion.version} 迭代时候需要手动更改
|
||||||
*/
|
*/
|
||||||
String VERSION = "2.4.1";
|
String VERSION = "2.5.0";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 同 ${spring.application.name}
|
* 同 ${spring.application.name}
|
||||||
|
|||||||
@@ -53,21 +53,23 @@ public interface AutoConfigureOrderConst {
|
|||||||
|
|
||||||
int FRAMEWORK_REDIS_CACHE = Integer.MIN_VALUE + 2000;
|
int FRAMEWORK_REDIS_CACHE = Integer.MIN_VALUE + 2000;
|
||||||
|
|
||||||
int FRAMEWORK_CONFIG = Integer.MIN_VALUE + 2100;
|
int FRAMEWORK_INFLUXDB = Integer.MIN_VALUE + 2100;
|
||||||
|
|
||||||
int FRAMEWORK_ENCRYPT = Integer.MIN_VALUE + 2200;
|
int FRAMEWORK_CONFIG = Integer.MIN_VALUE + 2300;
|
||||||
|
|
||||||
int FRAMEWORK_STORAGE = Integer.MIN_VALUE + 2300;
|
int FRAMEWORK_CYPHER = Integer.MIN_VALUE + 2400;
|
||||||
|
|
||||||
int FRAMEWORK_JOB = Integer.MIN_VALUE + 2400;
|
int FRAMEWORK_STORAGE = Integer.MIN_VALUE + 2500;
|
||||||
|
|
||||||
int FRAMEWORK_JOB_QUARTZ = Integer.MIN_VALUE + 2500;
|
int FRAMEWORK_JOB = Integer.MIN_VALUE + 2600;
|
||||||
|
|
||||||
int FRAMEWORK_JOB_ASYNC = Integer.MIN_VALUE + 2600;
|
int FRAMEWORK_JOB_QUARTZ = Integer.MIN_VALUE + 2700;
|
||||||
|
|
||||||
int FRAMEWORK_MONITOR = Integer.MIN_VALUE + 2700;
|
int FRAMEWORK_JOB_ASYNC = Integer.MIN_VALUE + 2800;
|
||||||
|
|
||||||
int FRAMEWORK_BIZ_OPERATOR_LOG = Integer.MIN_VALUE + 2800;
|
int FRAMEWORK_MONITOR = Integer.MIN_VALUE + 2900;
|
||||||
|
|
||||||
|
int FRAMEWORK_BIZ_OPERATOR_LOG = Integer.MIN_VALUE + 3000;
|
||||||
|
|
||||||
int FRAMEWORK_BANNER = Integer.MIN_VALUE + 10000;
|
int FRAMEWORK_BANNER = Integer.MIN_VALUE + 10000;
|
||||||
|
|
||||||
|
|||||||
@@ -31,24 +31,29 @@ package org.dromara.visor.common.constant;
|
|||||||
*/
|
*/
|
||||||
public interface BeanOrderConst {
|
public interface BeanOrderConst {
|
||||||
|
|
||||||
/**
|
|
||||||
* 公共返回值包装处理器
|
|
||||||
*/
|
|
||||||
int RESPONSE_ADVICE_WRAPPER = Integer.MIN_VALUE + 1000;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 演示模式切面
|
* 演示模式切面
|
||||||
*/
|
*/
|
||||||
int DEMO_DISABLE_API_ASPECT = Integer.MIN_VALUE + 10;
|
int DEMO_DISABLE_API_ASPECT = Integer.MIN_VALUE + 100;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 全局日志打印
|
* 全局日志打印
|
||||||
*/
|
*/
|
||||||
int LOG_PRINT_ASPECT = Integer.MIN_VALUE + 20;
|
int LOG_PRINT_ASPECT = Integer.MIN_VALUE + 200;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 暴露接口切面
|
||||||
|
*/
|
||||||
|
int EXPOSE_API_ASPECT = Integer.MIN_VALUE + 300;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 操作日志切面
|
* 操作日志切面
|
||||||
*/
|
*/
|
||||||
int OPERATOR_LOG_ASPECT = Integer.MIN_VALUE + 30;
|
int OPERATOR_LOG_ASPECT = Integer.MIN_VALUE + 400;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 公共返回值包装处理器
|
||||||
|
*/
|
||||||
|
int RESPONSE_ADVICE_WRAPPER = Integer.MIN_VALUE + 1000;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,9 +51,6 @@ public interface Const extends cn.orionsec.kit.lang.constant.Const, FieldConst,
|
|||||||
|
|
||||||
String SYSTEM_USERNAME = "system";
|
String SYSTEM_USERNAME = "system";
|
||||||
|
|
||||||
// FIXME KIT
|
|
||||||
String ADMINISTRATOR = "Administrator";
|
|
||||||
|
|
||||||
Long ALL_HOST_ID = -1L;
|
Long ALL_HOST_ID = -1L;
|
||||||
|
|
||||||
int BATCH_COUNT = 500;
|
int BATCH_COUNT = 500;
|
||||||
|
|||||||
@@ -22,17 +22,19 @@
|
|||||||
*/
|
*/
|
||||||
package org.dromara.visor.common.constant;
|
package org.dromara.visor.common.constant;
|
||||||
|
|
||||||
import cn.orionsec.kit.lang.constant.StandardHttpHeader;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* http 请求头
|
* 自定义请求头
|
||||||
*
|
*
|
||||||
* @author Jiahang Li
|
* @author Jiahang Li
|
||||||
* @version 1.0.0
|
* @version 1.0.0
|
||||||
* @since 2025/7/1 1:02
|
* @since 2025/7/1 1:02
|
||||||
*/
|
*/
|
||||||
public interface HttpHeaderConst extends StandardHttpHeader {
|
public interface CustomHeaderConst {
|
||||||
|
|
||||||
String APP_VERSION = "X-App-Version";
|
String APP_VERSION = "X-App-Version";
|
||||||
|
|
||||||
|
String AGENT_KEY_HEADER = "X-Agent-Key";
|
||||||
|
|
||||||
|
String AGENT_VERSION_HEADER = "X-Agent-Version";
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -48,6 +48,8 @@ public enum ErrorCode implements CodeInfo {
|
|||||||
|
|
||||||
UNAUTHORIZED(401, "当前认证信息已失效, 请重新登录"),
|
UNAUTHORIZED(401, "当前认证信息已失效, 请重新登录"),
|
||||||
|
|
||||||
|
EXPOSE_UNAUTHORIZED(401, "当前认证信息错误, 请检查后重试"),
|
||||||
|
|
||||||
FORBIDDEN(403, "无操作权限"),
|
FORBIDDEN(403, "无操作权限"),
|
||||||
|
|
||||||
NOT_FOUND(404, "未找到该资源"),
|
NOT_FOUND(404, "未找到该资源"),
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ public interface ErrorMessage {
|
|||||||
|
|
||||||
String HOST_TYPE_ERROR = "主机类型错误";
|
String HOST_TYPE_ERROR = "主机类型错误";
|
||||||
|
|
||||||
String HOST_NOT_ENABLED = "主机未启用";
|
String HOST_NOT_ENABLED = "{} 主机未启用";
|
||||||
|
|
||||||
String CONFIG_NOT_ENABLED = "配置未启用";
|
String CONFIG_NOT_ENABLED = "配置未启用";
|
||||||
|
|
||||||
@@ -146,6 +146,8 @@ public interface ErrorMessage {
|
|||||||
|
|
||||||
String FILE_ABSENT = "文件不存在";
|
String FILE_ABSENT = "文件不存在";
|
||||||
|
|
||||||
|
String FILE_EXTENSION_TYPE = "文件类型不正确";
|
||||||
|
|
||||||
String FILE_ABSENT_CLEAR = "文件不存在 (可能已被清理)";
|
String FILE_ABSENT_CLEAR = "文件不存在 (可能已被清理)";
|
||||||
|
|
||||||
String LOG_ABSENT = "日志不存在";
|
String LOG_ABSENT = "日志不存在";
|
||||||
@@ -158,6 +160,8 @@ public interface ErrorMessage {
|
|||||||
|
|
||||||
String FILE_UPLOAD_ERROR = "文件上传失败";
|
String FILE_UPLOAD_ERROR = "文件上传失败";
|
||||||
|
|
||||||
|
String CALC_SIGN_FAILED = "计算签名失败";
|
||||||
|
|
||||||
String SCRIPT_UPLOAD_ERROR = "脚本上传失败";
|
String SCRIPT_UPLOAD_ERROR = "脚本上传失败";
|
||||||
|
|
||||||
String EXEC_ERROR = "执行失败";
|
String EXEC_ERROR = "执行失败";
|
||||||
@@ -182,6 +186,8 @@ public interface ErrorMessage {
|
|||||||
|
|
||||||
String COMPRESS_FILE_ABSENT = "压缩文件不存在";
|
String COMPRESS_FILE_ABSENT = "压缩文件不存在";
|
||||||
|
|
||||||
|
String DECOMPRESS_FILE_ABSENT = "压缩文件不存在";
|
||||||
|
|
||||||
String UNABLE_DOWNLOAD_FOLDER = "无法下载文件夹";
|
String UNABLE_DOWNLOAD_FOLDER = "无法下载文件夹";
|
||||||
|
|
||||||
String VALID_ERROR = "验证失败";
|
String VALID_ERROR = "验证失败";
|
||||||
@@ -209,6 +215,27 @@ public interface ErrorMessage {
|
|||||||
|| ex instanceof ApplicationException;
|
|| ex instanceof ApplicationException;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取错误信息
|
||||||
|
*
|
||||||
|
* @param ex ex
|
||||||
|
* @return message
|
||||||
|
*/
|
||||||
|
static String getErrorMessage(Exception ex) {
|
||||||
|
return getErrorMessage(ex, ErrorMessage.EXEC_ERROR, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取错误信息
|
||||||
|
*
|
||||||
|
* @param ex ex
|
||||||
|
* @param len len
|
||||||
|
* @return message
|
||||||
|
*/
|
||||||
|
static String getErrorMessage(Exception ex, int len) {
|
||||||
|
return getErrorMessage(ex, ErrorMessage.EXEC_ERROR, len);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取错误信息
|
* 获取错误信息
|
||||||
*
|
*
|
||||||
@@ -217,6 +244,18 @@ public interface ErrorMessage {
|
|||||||
* @return message
|
* @return message
|
||||||
*/
|
*/
|
||||||
static String getErrorMessage(Exception ex, String defaultMsg) {
|
static String getErrorMessage(Exception ex, String defaultMsg) {
|
||||||
|
return getErrorMessage(ex, defaultMsg, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取错误信息
|
||||||
|
*
|
||||||
|
* @param ex ex
|
||||||
|
* @param defaultMsg defaultMsg
|
||||||
|
* @param len len
|
||||||
|
* @return message
|
||||||
|
*/
|
||||||
|
static String getErrorMessage(Exception ex, String defaultMsg, int len) {
|
||||||
if (ex == null) {
|
if (ex == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -226,7 +265,11 @@ public interface ErrorMessage {
|
|||||||
}
|
}
|
||||||
// 业务异常
|
// 业务异常
|
||||||
if (isBizException(ex)) {
|
if (isBizException(ex)) {
|
||||||
return message;
|
if (len > 0) {
|
||||||
|
return Strings.retain(message, len);
|
||||||
|
} else {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return defaultMsg;
|
return defaultMsg;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ public interface ExtraFieldConst extends FieldConst {
|
|||||||
|
|
||||||
String TRACE_ID = "traceId";
|
String TRACE_ID = "traceId";
|
||||||
|
|
||||||
|
String TASK_ID = "taskId";
|
||||||
|
|
||||||
String IDENTITY = "identity";
|
String IDENTITY = "identity";
|
||||||
|
|
||||||
String GROUP_NAME = "groupName";
|
String GROUP_NAME = "groupName";
|
||||||
@@ -69,4 +71,6 @@ public interface ExtraFieldConst extends FieldConst {
|
|||||||
|
|
||||||
String DARK = "dark";
|
String DARK = "dark";
|
||||||
|
|
||||||
|
String AGENT_KEY = "agentKey";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,12 +45,18 @@ public interface FieldConst {
|
|||||||
|
|
||||||
String LABEL = "label";
|
String LABEL = "label";
|
||||||
|
|
||||||
|
String FIELD = "field";
|
||||||
|
|
||||||
String TYPE = "type";
|
String TYPE = "type";
|
||||||
|
|
||||||
String COLOR = "color";
|
String COLOR = "color";
|
||||||
|
|
||||||
|
String LOADING = "loading";
|
||||||
|
|
||||||
String STATUS = "status";
|
String STATUS = "status";
|
||||||
|
|
||||||
|
String SWITCH = "switch";
|
||||||
|
|
||||||
String INFO = "info";
|
String INFO = "info";
|
||||||
|
|
||||||
String EXTRA = "extra";
|
String EXTRA = "extra";
|
||||||
@@ -71,6 +77,8 @@ public interface FieldConst {
|
|||||||
|
|
||||||
String SEQ = "seq";
|
String SEQ = "seq";
|
||||||
|
|
||||||
|
String START = "start";
|
||||||
|
|
||||||
String PATH = "path";
|
String PATH = "path";
|
||||||
|
|
||||||
String ADDRESS = "address";
|
String ADDRESS = "address";
|
||||||
@@ -119,4 +127,12 @@ public interface FieldConst {
|
|||||||
|
|
||||||
String CONFIG = "config";
|
String CONFIG = "config";
|
||||||
|
|
||||||
|
String VERSION = "version";
|
||||||
|
|
||||||
|
String SYNCED = "synced";
|
||||||
|
|
||||||
|
String SIGN = "sign";
|
||||||
|
|
||||||
|
String SIGN_SHORT = "signShort";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,4 +37,20 @@ public interface FileConst {
|
|||||||
|
|
||||||
String SCRIPT = "script";
|
String SCRIPT = "script";
|
||||||
|
|
||||||
|
String INSTANCE_AGENT_PATH = "instance-agent";
|
||||||
|
|
||||||
|
String INSTANCE_AGENT_NAME = "instance_agent";
|
||||||
|
|
||||||
|
String INSTANCE_AGENT_FILE_FORMAT = "instance_agent_{}_{}{}";
|
||||||
|
|
||||||
|
String INSTANCE_AGENT_RELEASE = "instance-agent-release";
|
||||||
|
|
||||||
|
String INSTANCE_AGENT_RELEASE_TEMP = "instance-agent-release-temp";
|
||||||
|
|
||||||
|
String INSTANCE_AGENT_RELEASE_TAR_GZ = "instance-agent-release.tar.gz";
|
||||||
|
|
||||||
|
String VERSION = ".version";
|
||||||
|
|
||||||
|
String CONFIG_YAML = "config.yaml";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023 - present Dromara, All rights reserved.
|
||||||
|
*
|
||||||
|
* https://visor.dromara.org
|
||||||
|
* https://visor.dromara.org.cn
|
||||||
|
* https://visor.orionsec.cn
|
||||||
|
*
|
||||||
|
* Members:
|
||||||
|
* Jiahang Li - ljh1553488six@139.com - author
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.dromara.visor.common.entity.chart;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 时序图系列
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2025/9/3 21:08
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Schema(name = "TimeChartSeries", description = "时序图系列")
|
||||||
|
public class TimeChartSeries {
|
||||||
|
|
||||||
|
@Schema(description = "name")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Schema(description = "颜色")
|
||||||
|
private String color;
|
||||||
|
|
||||||
|
@Schema(description = "tags")
|
||||||
|
private Map<String, Object> tags;
|
||||||
|
|
||||||
|
@Schema(description = "数据 [0]timestampMills [1]value")
|
||||||
|
private List<List<Object>> data;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.dromara.visor.common.interfaces;
|
package org.dromara.visor.common.file;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023 - present Dromara, All rights reserved.
|
||||||
|
*
|
||||||
|
* https://visor.dromara.org
|
||||||
|
* https://visor.dromara.org.cn
|
||||||
|
* https://visor.orionsec.cn
|
||||||
|
*
|
||||||
|
* Members:
|
||||||
|
* Jiahang Li - ljh1553488six@139.com - author
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.dromara.visor.common.lock;
|
||||||
|
|
||||||
|
import cn.orionsec.kit.lang.able.Executable;
|
||||||
|
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 空实现的锁
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2025/8/23 13:59
|
||||||
|
*/
|
||||||
|
public class EmptyLocker implements Locker {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean tryLockExecute(String key, Executable executable) {
|
||||||
|
executable.exec();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean tryLockExecute(String key, long timeout, Executable executable) {
|
||||||
|
executable.exec();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> T tryLockExecute(String key, Supplier<T> callable) {
|
||||||
|
return callable.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> T tryLockExecute(String key, long timeout, Supplier<T> callable) {
|
||||||
|
return callable.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void lockExecute(String key, Executable executable) {
|
||||||
|
executable.exec();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void lockExecute(String key, long timeout, Executable executable) {
|
||||||
|
executable.exec();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> T lockExecute(String key, Supplier<T> callable) {
|
||||||
|
return callable.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> T lockExecute(String key, long timeout, Supplier<T> callable) {
|
||||||
|
return callable.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,116 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023 - present Dromara, All rights reserved.
|
||||||
|
*
|
||||||
|
* https://visor.dromara.org
|
||||||
|
* https://visor.dromara.org.cn
|
||||||
|
* https://visor.orionsec.cn
|
||||||
|
*
|
||||||
|
* Members:
|
||||||
|
* Jiahang Li - ljh1553488six@139.com - author
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.dromara.visor.common.lock;
|
||||||
|
|
||||||
|
import cn.orionsec.kit.lang.able.Executable;
|
||||||
|
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分布式锁
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2024/5/16 12:24
|
||||||
|
*/
|
||||||
|
public interface Locker {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 尝试获取锁并执行
|
||||||
|
*
|
||||||
|
* @param key key
|
||||||
|
* @param executable exec
|
||||||
|
* @return 是否获取到锁
|
||||||
|
*/
|
||||||
|
boolean tryLockExecute(String key, Executable executable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 尝试获取锁并执行
|
||||||
|
*
|
||||||
|
* @param key key
|
||||||
|
* @param timeout timeout
|
||||||
|
* @param executable exec
|
||||||
|
* @return 是否获取到锁
|
||||||
|
*/
|
||||||
|
boolean tryLockExecute(String key, long timeout, Executable executable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 尝试获取锁并执行 未获取到锁则抛出异常
|
||||||
|
*
|
||||||
|
* @param key key
|
||||||
|
* @param callable callable
|
||||||
|
* @param <T> T
|
||||||
|
* @return 执行结果
|
||||||
|
*/
|
||||||
|
<T> T tryLockExecute(String key, Supplier<T> callable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 尝试获取锁并执行 未获取到锁则抛出异常
|
||||||
|
*
|
||||||
|
* @param key key
|
||||||
|
* @param timeout timeout
|
||||||
|
* @param callable callable
|
||||||
|
* @param <T> T
|
||||||
|
* @return 执行结果
|
||||||
|
*/
|
||||||
|
<T> T tryLockExecute(String key, long timeout, Supplier<T> callable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 阻塞获取锁并执行
|
||||||
|
*
|
||||||
|
* @param key key
|
||||||
|
* @param executable exec
|
||||||
|
*/
|
||||||
|
void lockExecute(String key, Executable executable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 阻塞获取锁并执行
|
||||||
|
*
|
||||||
|
* @param key key
|
||||||
|
* @param timeout timeout
|
||||||
|
* @param executable exec
|
||||||
|
*/
|
||||||
|
void lockExecute(String key, long timeout, Executable executable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 阻塞获取锁并执行
|
||||||
|
*
|
||||||
|
* @param key key
|
||||||
|
* @param callable callable
|
||||||
|
* @param <T> T
|
||||||
|
* @return 执行结果
|
||||||
|
*/
|
||||||
|
<T> T lockExecute(String key, Supplier<T> callable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 阻塞获取锁并执行
|
||||||
|
*
|
||||||
|
* @param key key
|
||||||
|
* @param timeout timeout
|
||||||
|
* @param callable callable
|
||||||
|
* @param <T> T
|
||||||
|
* @return 执行结果
|
||||||
|
*/
|
||||||
|
<T> T lockExecute(String key, long timeout, Supplier<T> callable);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -63,6 +63,9 @@ public class BaseConnectConfig implements IBaseConnectConfig {
|
|||||||
@Schema(description = "主机端口")
|
@Schema(description = "主机端口")
|
||||||
private Integer hostPort;
|
private Integer hostPort;
|
||||||
|
|
||||||
|
@Schema(description = "agentKey")
|
||||||
|
private String agentKey;
|
||||||
|
|
||||||
@Schema(description = "用户名")
|
@Schema(description = "用户名")
|
||||||
private String username;
|
private String username;
|
||||||
|
|
||||||
|
|||||||
@@ -61,6 +61,10 @@ public interface IBaseConnectConfig {
|
|||||||
|
|
||||||
void setHostPort(Integer hostPort);
|
void setHostPort(Integer hostPort);
|
||||||
|
|
||||||
|
String getAgentKey();
|
||||||
|
|
||||||
|
void setAgentKey(String agentKey);
|
||||||
|
|
||||||
String getUsername();
|
String getUsername();
|
||||||
|
|
||||||
void setUsername(String username);
|
void setUsername(String username);
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023 - present Dromara, All rights reserved.
|
||||||
|
*
|
||||||
|
* https://visor.dromara.org
|
||||||
|
* https://visor.dromara.org.cn
|
||||||
|
* https://visor.orionsec.cn
|
||||||
|
*
|
||||||
|
* Members:
|
||||||
|
* Jiahang Li - ljh1553488six@139.com - author
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.dromara.visor.common.session.config;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.SuperBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* VNC 连接参数
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2025/4/1 16:57
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@SuperBuilder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Schema(name = "VncConnectConfig", description = "VNC 连接参数")
|
||||||
|
public class VncConnectConfig extends BaseConnectConfig {
|
||||||
|
|
||||||
|
@Schema(description = "低带宽模式")
|
||||||
|
private Boolean lowBandwidthMode;
|
||||||
|
|
||||||
|
@Schema(description = "交换红蓝")
|
||||||
|
private Boolean swapRedBlue;
|
||||||
|
|
||||||
|
@Schema(description = "时区")
|
||||||
|
private String timezone;
|
||||||
|
|
||||||
|
@Schema(description = "剪切板编码")
|
||||||
|
private String clipboardEncoding;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -110,7 +110,10 @@ public class SessionStores {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 超时时间
|
// 超时时间
|
||||||
session.timeout(config.getTimeout());
|
Integer timeout = config.getTimeout();
|
||||||
|
if (timeout != null) {
|
||||||
|
session.timeout(timeout);
|
||||||
|
}
|
||||||
return session;
|
return session;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
package org.dromara.visor.common.utils;
|
package org.dromara.visor.common.utils;
|
||||||
|
|
||||||
import cn.orionsec.kit.lang.utils.Exceptions;
|
import cn.orionsec.kit.lang.utils.Exceptions;
|
||||||
import org.dromara.visor.common.interfaces.AesEncryptor;
|
import org.dromara.visor.common.cipher.AesEncryptor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* aes 数据加密工具类
|
* aes 数据加密工具类
|
||||||
|
|||||||
@@ -22,9 +22,10 @@
|
|||||||
*/
|
*/
|
||||||
package org.dromara.visor.common.utils;
|
package org.dromara.visor.common.utils;
|
||||||
|
|
||||||
|
import cn.orionsec.kit.lang.able.Executable;
|
||||||
import cn.orionsec.kit.lang.utils.Exceptions;
|
import cn.orionsec.kit.lang.utils.Exceptions;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.dromara.visor.common.interfaces.Locker;
|
import org.dromara.visor.common.lock.Locker;
|
||||||
|
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
@@ -44,26 +45,97 @@ public class LockerUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 尝试获取锁
|
* 尝试获取锁并执行
|
||||||
*
|
*
|
||||||
* @param key key
|
* @param key key
|
||||||
* @param run run
|
* @param executable exec
|
||||||
* @return 是否获取到锁
|
* @return 是否获取到锁
|
||||||
*/
|
*/
|
||||||
public static boolean tryLock(String key, Runnable run) {
|
public static boolean tryLockExecute(String key, Executable executable) {
|
||||||
return delegate.tryLock(key, run);
|
return delegate.tryLockExecute(key, executable);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 尝试获取锁
|
* 尝试获取锁并执行
|
||||||
*
|
*
|
||||||
* @param key key
|
* @param key key
|
||||||
* @param call call
|
* @param timeout timeout
|
||||||
* @param <T> T
|
* @param executable exec
|
||||||
|
* @return 是否获取到锁
|
||||||
|
*/
|
||||||
|
public static boolean tryLockExecute(String key, long timeout, Executable executable) {
|
||||||
|
return delegate.tryLockExecute(key, timeout, executable);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 尝试获取锁并执行 未获取到锁则抛出异常
|
||||||
|
*
|
||||||
|
* @param key key
|
||||||
|
* @param callable callable
|
||||||
|
* @param <T> T
|
||||||
* @return 执行结果
|
* @return 执行结果
|
||||||
*/
|
*/
|
||||||
public static <T> T tryLock(String key, Supplier<T> call) {
|
public static <T> T tryLockExecute(String key, Supplier<T> callable) {
|
||||||
return delegate.tryLock(key, call);
|
return delegate.tryLockExecute(key, callable);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 尝试获取锁并执行 未获取到锁则抛出异常
|
||||||
|
*
|
||||||
|
* @param key key
|
||||||
|
* @param timeout timeout
|
||||||
|
* @param callable callable
|
||||||
|
* @param <T> T
|
||||||
|
* @return 执行结果
|
||||||
|
*/
|
||||||
|
public static <T> T tryLockExecute(String key, long timeout, Supplier<T> callable) {
|
||||||
|
return delegate.tryLockExecute(key, timeout, callable);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 阻塞获取锁并执行
|
||||||
|
*
|
||||||
|
* @param key key
|
||||||
|
* @param executable exec
|
||||||
|
*/
|
||||||
|
public static void lockExecute(String key, Executable executable) {
|
||||||
|
delegate.lockExecute(key, executable);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 阻塞获取锁并执行
|
||||||
|
*
|
||||||
|
* @param key key
|
||||||
|
* @param timeout timeout
|
||||||
|
* @param executable exec
|
||||||
|
*/
|
||||||
|
public static void lockExecute(String key, long timeout, Executable executable) {
|
||||||
|
delegate.lockExecute(key, timeout, executable);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 阻塞获取锁并执行
|
||||||
|
*
|
||||||
|
* @param key key
|
||||||
|
* @param callable callable
|
||||||
|
* @param <T> T
|
||||||
|
* @return 执行结果
|
||||||
|
*/
|
||||||
|
public static <T> T lockExecute(String key, Supplier<T> callable) {
|
||||||
|
return delegate.lockExecute(key, callable);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 阻塞获取锁并执行
|
||||||
|
*
|
||||||
|
* @param key key
|
||||||
|
* @param timeout timeout
|
||||||
|
* @param callable callable
|
||||||
|
* @param <T> T
|
||||||
|
* @return 执行结果
|
||||||
|
*/
|
||||||
|
public static <T> T lockExecute(String key, long timeout, Supplier<T> callable) {
|
||||||
|
return delegate.lockExecute(key, timeout, callable);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setDelegate(Locker delegate) {
|
public static void setDelegate(Locker delegate) {
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
package org.dromara.visor.common.utils;
|
package org.dromara.visor.common.utils;
|
||||||
|
|
||||||
import cn.orionsec.kit.lang.utils.Exceptions;
|
import cn.orionsec.kit.lang.utils.Exceptions;
|
||||||
import org.dromara.visor.common.interfaces.RsaDecryptor;
|
import org.dromara.visor.common.cipher.RsaDecryptor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* rsa 参数解密工具类
|
* rsa 参数解密工具类
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
package org.dromara.visor.common.validator.group;
|
package org.dromara.visor.common.validator.group;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 分页验证分组
|
* id 验证分组
|
||||||
*
|
*
|
||||||
* @author Jiahang Li
|
* @author Jiahang Li
|
||||||
* @version 1.0.0
|
* @version 1.0.0
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023 - present Dromara, All rights reserved.
|
||||||
|
*
|
||||||
|
* https://visor.dromara.org
|
||||||
|
* https://visor.dromara.org.cn
|
||||||
|
* https://visor.orionsec.cn
|
||||||
|
*
|
||||||
|
* Members:
|
||||||
|
* Jiahang Li - ljh1553488six@139.com - author
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.dromara.visor.common.validator.group;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* key 验证分组
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2023/9/1 19:13
|
||||||
|
*/
|
||||||
|
public interface Key {
|
||||||
|
}
|
||||||
@@ -14,11 +14,11 @@
|
|||||||
<url>https://github.com/dromara/orion-visor</url>
|
<url>https://github.com/dromara/orion-visor</url>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<revision>2.4.1</revision>
|
<revision>2.5.0</revision>
|
||||||
<spring.boot.version>2.7.17</spring.boot.version>
|
<spring.boot.version>2.7.17</spring.boot.version>
|
||||||
<spring.boot.admin.version>2.7.15</spring.boot.admin.version>
|
<spring.boot.admin.version>2.7.15</spring.boot.admin.version>
|
||||||
<flatten.maven.plugin.version>1.5.0</flatten.maven.plugin.version>
|
<flatten.maven.plugin.version>1.5.0</flatten.maven.plugin.version>
|
||||||
<orion.kit.version>2.0.1</orion.kit.version>
|
<orion.kit.version>2.0.2</orion.kit.version>
|
||||||
<aspectj.version>1.9.7</aspectj.version>
|
<aspectj.version>1.9.7</aspectj.version>
|
||||||
<lombok.version>1.18.26</lombok.version>
|
<lombok.version>1.18.26</lombok.version>
|
||||||
<springdoc.version>1.6.15</springdoc.version>
|
<springdoc.version>1.6.15</springdoc.version>
|
||||||
@@ -31,6 +31,7 @@
|
|||||||
<druid.version>1.2.16</druid.version>
|
<druid.version>1.2.16</druid.version>
|
||||||
<redisson.version>3.18.0</redisson.version>
|
<redisson.version>3.18.0</redisson.version>
|
||||||
<transmittable.thread.local.version>2.14.2</transmittable.thread.local.version>
|
<transmittable.thread.local.version>2.14.2</transmittable.thread.local.version>
|
||||||
|
<influxdb.client.version>6.6.0</influxdb.client.version>
|
||||||
<mockito.inline.version>4.11.0</mockito.inline.version>
|
<mockito.inline.version>4.11.0</mockito.inline.version>
|
||||||
<jedis.mock.version>1.0.7</jedis.mock.version>
|
<jedis.mock.version>1.0.7</jedis.mock.version>
|
||||||
<podam.version>7.2.11.RELEASE</podam.version>
|
<podam.version>7.2.11.RELEASE</podam.version>
|
||||||
@@ -54,8 +55,12 @@
|
|||||||
<version>${orion.kit.version}</version>
|
<version>${orion.kit.version}</version>
|
||||||
<exclusions>
|
<exclusions>
|
||||||
<exclusion>
|
<exclusion>
|
||||||
<artifactId>orion-log</artifactId>
|
|
||||||
<groupId>cn.orionsec.kit</groupId>
|
<groupId>cn.orionsec.kit</groupId>
|
||||||
|
<artifactId>orion-log</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>cn.orionsec.kit</groupId>
|
||||||
|
<artifactId>orion-generator</artifactId>
|
||||||
</exclusion>
|
</exclusion>
|
||||||
</exclusions>
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
@@ -118,7 +123,7 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.dromara.visor</groupId>
|
<groupId>org.dromara.visor</groupId>
|
||||||
<artifactId>orion-visor-spring-boot-starter-encrypt</artifactId>
|
<artifactId>orion-visor-spring-boot-starter-cipher</artifactId>
|
||||||
<version>${revision}</version>
|
<version>${revision}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
@@ -146,6 +151,11 @@
|
|||||||
<artifactId>orion-visor-spring-boot-starter-test</artifactId>
|
<artifactId>orion-visor-spring-boot-starter-test</artifactId>
|
||||||
<version>${revision}</version>
|
<version>${revision}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.dromara.visor</groupId>
|
||||||
|
<artifactId>orion-visor-spring-boot-starter-influxdb</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.dromara.visor</groupId>
|
<groupId>org.dromara.visor</groupId>
|
||||||
<artifactId>orion-visor-spring-boot-starter-biz-operator-log</artifactId>
|
<artifactId>orion-visor-spring-boot-starter-biz-operator-log</artifactId>
|
||||||
@@ -272,6 +282,13 @@
|
|||||||
<version>${transmittable.thread.local.version}</version>
|
<version>${transmittable.thread.local.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- influxdb -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.influxdb</groupId>
|
||||||
|
<artifactId>influxdb-client-java</artifactId>
|
||||||
|
<version>${influxdb.client.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- test -->
|
<!-- test -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
|||||||
@@ -73,7 +73,6 @@ public class OperatorLogAspect {
|
|||||||
.maxPoolSize(1)
|
.maxPoolSize(1)
|
||||||
.useLinkedBlockingQueue()
|
.useLinkedBlockingQueue()
|
||||||
.allowCoreThreadTimeout()
|
.allowCoreThreadTimeout()
|
||||||
.useLinkedBlockingQueue()
|
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
private final OperatorLogFrameworkService operatorLogFrameworkService;
|
private final OperatorLogFrameworkService operatorLogFrameworkService;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>orion-visor-spring-boot-starter-encrypt</artifactId>
|
<artifactId>orion-visor-spring-boot-starter-cipher</artifactId>
|
||||||
<name>${project.artifactId}</name>
|
<name>${project.artifactId}</name>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
@@ -22,10 +22,10 @@
|
|||||||
*/
|
*/
|
||||||
package org.dromara.visor.framework.encrypt.configuration;
|
package org.dromara.visor.framework.encrypt.configuration;
|
||||||
|
|
||||||
|
import org.dromara.visor.common.cipher.AesEncryptor;
|
||||||
|
import org.dromara.visor.common.cipher.RsaDecryptor;
|
||||||
import org.dromara.visor.common.config.ConfigStore;
|
import org.dromara.visor.common.config.ConfigStore;
|
||||||
import org.dromara.visor.common.constant.AutoConfigureOrderConst;
|
import org.dromara.visor.common.constant.AutoConfigureOrderConst;
|
||||||
import org.dromara.visor.common.interfaces.AesEncryptor;
|
|
||||||
import org.dromara.visor.common.interfaces.RsaDecryptor;
|
|
||||||
import org.dromara.visor.common.utils.AesEncryptUtils;
|
import org.dromara.visor.common.utils.AesEncryptUtils;
|
||||||
import org.dromara.visor.common.utils.RsaParamDecryptUtils;
|
import org.dromara.visor.common.utils.RsaParamDecryptUtils;
|
||||||
import org.dromara.visor.framework.encrypt.configuration.config.AesEncryptConfig;
|
import org.dromara.visor.framework.encrypt.configuration.config.AesEncryptConfig;
|
||||||
@@ -45,7 +45,7 @@ import org.springframework.context.annotation.Bean;
|
|||||||
*/
|
*/
|
||||||
@AutoConfiguration
|
@AutoConfiguration
|
||||||
@EnableConfigurationProperties({AesEncryptConfig.class})
|
@EnableConfigurationProperties({AesEncryptConfig.class})
|
||||||
@AutoConfigureOrder(AutoConfigureOrderConst.FRAMEWORK_ENCRYPT)
|
@AutoConfigureOrder(AutoConfigureOrderConst.FRAMEWORK_CYPHER)
|
||||||
public class OrionEncryptAutoConfiguration {
|
public class OrionEncryptAutoConfiguration {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.dromara.visor.framework.encrypt.core;
|
package org.dromara.visor.framework.encrypt.core;
|
||||||
|
|
||||||
import org.dromara.visor.common.interfaces.AesEncryptor;
|
import org.dromara.visor.common.cipher.AesEncryptor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 数据加密器
|
* 数据加密器
|
||||||
@@ -26,7 +26,7 @@ import cn.orionsec.kit.lang.utils.crypto.RSA;
|
|||||||
import org.dromara.visor.common.config.ConfigRef;
|
import org.dromara.visor.common.config.ConfigRef;
|
||||||
import org.dromara.visor.common.config.ConfigStore;
|
import org.dromara.visor.common.config.ConfigStore;
|
||||||
import org.dromara.visor.common.constant.ConfigKeys;
|
import org.dromara.visor.common.constant.ConfigKeys;
|
||||||
import org.dromara.visor.common.interfaces.RsaDecryptor;
|
import org.dromara.visor.common.cipher.RsaDecryptor;
|
||||||
|
|
||||||
import java.security.interfaces.RSAPrivateKey;
|
import java.security.interfaces.RSAPrivateKey;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<groupId>org.dromara.visor</groupId>
|
||||||
|
<artifactId>orion-visor-framework</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<artifactId>orion-visor-spring-boot-starter-influxdb</artifactId>
|
||||||
|
<name>${project.artifactId}</name>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<description>项目 influxdb 配置包</description>
|
||||||
|
<url>https://github.com/dromara/orion-visor</url>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<!-- common -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.dromara.visor</groupId>
|
||||||
|
<artifactId>orion-visor-common</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- influxdb -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.influxdb</groupId>
|
||||||
|
<artifactId>influxdb-client-java</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- web -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023 - present Dromara, All rights reserved.
|
||||||
|
*
|
||||||
|
* https://visor.dromara.org
|
||||||
|
* https://visor.dromara.org.cn
|
||||||
|
* https://visor.orionsec.cn
|
||||||
|
*
|
||||||
|
* Members:
|
||||||
|
* Jiahang Li - ljh1553488six@139.com - author
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.dromara.visor.framework.influxdb.configuration;
|
||||||
|
|
||||||
|
import cn.orionsec.kit.lang.utils.Strings;
|
||||||
|
import com.influxdb.LogLevel;
|
||||||
|
import com.influxdb.client.InfluxDBClient;
|
||||||
|
import com.influxdb.client.InfluxDBClientFactory;
|
||||||
|
import com.influxdb.client.InfluxDBClientOptions;
|
||||||
|
import org.dromara.visor.common.constant.AutoConfigureOrderConst;
|
||||||
|
import org.dromara.visor.framework.influxdb.configuration.config.InfluxdbConfig;
|
||||||
|
import org.dromara.visor.framework.influxdb.core.utils.InfluxdbUtils;
|
||||||
|
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||||
|
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Lazy;
|
||||||
|
|
||||||
|
import java.net.ConnectException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* influxdb 配置类
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2025/8/10 20:35
|
||||||
|
*/
|
||||||
|
@Lazy(false)
|
||||||
|
@AutoConfiguration
|
||||||
|
@AutoConfigureOrder(AutoConfigureOrderConst.FRAMEWORK_INFLUXDB)
|
||||||
|
@ConditionalOnProperty(value = "spring.influxdb.enabled", havingValue = "true")
|
||||||
|
@EnableConfigurationProperties(InfluxdbConfig.class)
|
||||||
|
public class OrionInfluxdbAutoConfiguration {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO 重连
|
||||||
|
*
|
||||||
|
* @param config config
|
||||||
|
* @return influxdb 客户端
|
||||||
|
*/
|
||||||
|
@Bean(name = "influxDBClient")
|
||||||
|
public InfluxDBClient influxDBClient(InfluxdbConfig config) throws ConnectException {
|
||||||
|
// 参数
|
||||||
|
InfluxDBClientOptions options = InfluxDBClientOptions.builder()
|
||||||
|
.url(config.getUrl())
|
||||||
|
.authenticateToken(config.getToken().toCharArray())
|
||||||
|
.org(config.getOrg())
|
||||||
|
.bucket(config.getBucket())
|
||||||
|
.logLevel(LogLevel.NONE)
|
||||||
|
.build();
|
||||||
|
// 客户端
|
||||||
|
InfluxDBClient client = InfluxDBClientFactory.create(options);
|
||||||
|
// 尝试连接
|
||||||
|
Boolean ping = client.ping();
|
||||||
|
if (!ping) {
|
||||||
|
throw new ConnectException(Strings.format("connect to influxdb failed. url: {}, org: {}", config.getUrl(), config.getOrg()));
|
||||||
|
}
|
||||||
|
// 设置工具类
|
||||||
|
InfluxdbUtils.setInfluxClient(config.getBucket(), client);
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023 - present Dromara, All rights reserved.
|
||||||
|
*
|
||||||
|
* https://visor.dromara.org
|
||||||
|
* https://visor.dromara.org.cn
|
||||||
|
* https://visor.orionsec.cn
|
||||||
|
*
|
||||||
|
* Members:
|
||||||
|
* Jiahang Li - ljh1553488six@139.com - author
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.dromara.visor.framework.influxdb.configuration.config;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* influxdb 配置
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2025/8/10 20:36
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@ConfigurationProperties("spring.influxdb")
|
||||||
|
public class InfluxdbConfig {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* url
|
||||||
|
*/
|
||||||
|
private String url;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* org
|
||||||
|
*/
|
||||||
|
private String org;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* bucket
|
||||||
|
*/
|
||||||
|
private String bucket;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* apiToken
|
||||||
|
*/
|
||||||
|
private String token;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,349 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023 - present Dromara, All rights reserved.
|
||||||
|
*
|
||||||
|
* https://visor.dromara.org
|
||||||
|
* https://visor.dromara.org.cn
|
||||||
|
* https://visor.orionsec.cn
|
||||||
|
*
|
||||||
|
* Members:
|
||||||
|
* Jiahang Li - ljh1553488six@139.com - author
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.dromara.visor.framework.influxdb.core.query;
|
||||||
|
|
||||||
|
import cn.orionsec.kit.lang.utils.collect.Collections;
|
||||||
|
import cn.orionsec.kit.lang.utils.collect.Lists;
|
||||||
|
import org.dromara.visor.common.constant.Const;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* flux 查询构建器
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2025/9/3 16:08
|
||||||
|
*/
|
||||||
|
public class FluxQueryBuilder {
|
||||||
|
|
||||||
|
private final StringBuilder query;
|
||||||
|
|
||||||
|
private boolean hasFilter;
|
||||||
|
|
||||||
|
private boolean pretty;
|
||||||
|
|
||||||
|
private FluxQueryBuilder(String bucket) {
|
||||||
|
this.query = new StringBuilder();
|
||||||
|
this.query.append(String.format("from(bucket: \"%s\")", bucket));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建构建器
|
||||||
|
*
|
||||||
|
* @param bucket bucket
|
||||||
|
* @return builder
|
||||||
|
*/
|
||||||
|
public static FluxQueryBuilder from(String bucket) {
|
||||||
|
return new FluxQueryBuilder(bucket);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 时间范围
|
||||||
|
*
|
||||||
|
* @param start 开始时间
|
||||||
|
* @param end 结束时间
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
public FluxQueryBuilder range(long start, long end) {
|
||||||
|
query.append(String.format(" |> range(start: %s, stop: %s)", Instant.ofEpochMilli(start), Instant.ofEpochMilli(end)));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 时间范围
|
||||||
|
*
|
||||||
|
* @param range range
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
public FluxQueryBuilder range(String range) {
|
||||||
|
query.append(String.format(" |> range(start: %s)", range));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 过滤 measurement
|
||||||
|
*
|
||||||
|
* @param measurement measurement
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
public FluxQueryBuilder measurement(String measurement) {
|
||||||
|
this.appendFilter(String.format("r[\"_measurement\"] == \"%s\"", measurement));
|
||||||
|
this.closeFilter();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 过滤单个 field
|
||||||
|
*
|
||||||
|
* @param field field
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
public FluxQueryBuilder field(String field) {
|
||||||
|
this.appendFilter(String.format("r[\"_field\"] == \"%s\"", field));
|
||||||
|
this.closeFilter();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 过滤多个 field
|
||||||
|
*
|
||||||
|
* @param fields fields
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
public FluxQueryBuilder fields(Collection<String> fields) {
|
||||||
|
if (Collections.isEmpty(fields)) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
List<String> conditions = new ArrayList<>();
|
||||||
|
for (String field : fields) {
|
||||||
|
conditions.add(String.format("r[\"_field\"] == \"%s\"", field));
|
||||||
|
}
|
||||||
|
this.appendFilter(String.join(" or ", conditions));
|
||||||
|
this.closeFilter();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 过滤 tag key
|
||||||
|
*
|
||||||
|
* @param value value
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
public FluxQueryBuilder key(String value) {
|
||||||
|
return this.tag(Const.KEY, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 过滤 tag key
|
||||||
|
*
|
||||||
|
* @param values values
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
public FluxQueryBuilder key(Collection<String> values) {
|
||||||
|
return this.tag(Const.KEY, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 过滤 tag name
|
||||||
|
*
|
||||||
|
* @param value value
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
public FluxQueryBuilder name(String value) {
|
||||||
|
return this.tag(Const.NAME, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 过滤 tag name
|
||||||
|
*
|
||||||
|
* @param values values
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
public FluxQueryBuilder name(Collection<String> values) {
|
||||||
|
return this.tag(Const.NAME, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 过滤 tag
|
||||||
|
*
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
public FluxQueryBuilder tag(String key, String value) {
|
||||||
|
this.appendFilter(String.format("r[\"%s\"] == \"%s\"", key, value));
|
||||||
|
this.closeFilter();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 过滤 tag
|
||||||
|
*
|
||||||
|
* @param key key
|
||||||
|
* @param values values
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
public FluxQueryBuilder tag(String key, Collection<String> values) {
|
||||||
|
if (values == null || values.isEmpty()) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
if (values.size() == 1) {
|
||||||
|
return this.tag(key, Collections.first(values));
|
||||||
|
}
|
||||||
|
//
|
||||||
|
Collection<String> conditions = values.stream()
|
||||||
|
.map(value -> String.format("r[\"%s\"] == \"%s\"", key, value))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
this.appendFilter(String.join(" or ", conditions));
|
||||||
|
this.closeFilter();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 过滤多个 tag
|
||||||
|
* tag 使用 and
|
||||||
|
* value 使用 or
|
||||||
|
*
|
||||||
|
* @param tags tags
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
public FluxQueryBuilder tags(Map<String, ? extends Collection<String>> tags) {
|
||||||
|
for (Map.Entry<String, ? extends Collection<String>> entry : tags.entrySet()) {
|
||||||
|
String key = entry.getKey();
|
||||||
|
Collection<String> values = entry.getValue();
|
||||||
|
if (Collections.isEmpty(values)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (values.size() == 1) {
|
||||||
|
// 单值直接用等号
|
||||||
|
String singleValue = values.iterator().next();
|
||||||
|
this.appendFilter(String.format("r[\"%s\"] == \"%s\"", key, singleValue));
|
||||||
|
} else {
|
||||||
|
// 多值用 OR
|
||||||
|
Collection<String> conditions = values.stream()
|
||||||
|
.map(v -> String.format("r[\"%s\"] == \"%s\"", key, v))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
this.appendFilter("(" + String.join(" or ", conditions) + ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.closeFilter();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 聚合窗口
|
||||||
|
*/
|
||||||
|
public FluxQueryBuilder aggregateWindow(String every, String fn) {
|
||||||
|
query.append(String.format(" |> aggregateWindow(every: %s, fn: %s)", every, fn));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 聚合窗口
|
||||||
|
*/
|
||||||
|
public FluxQueryBuilder aggregateWindow(String every, String fn, boolean createEmpty) {
|
||||||
|
query.append(String.format(" |> aggregateWindow(every: %s, fn: %s, createEmpty: %b)", every, fn, createEmpty));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 排序
|
||||||
|
*
|
||||||
|
* @param columns columns
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
public FluxQueryBuilder sort(List<String> columns) {
|
||||||
|
StringBuilder cols = new StringBuilder();
|
||||||
|
for (int i = 0; i < columns.size(); i++) {
|
||||||
|
cols.append("\"").append(columns.get(i)).append("\"");
|
||||||
|
if (i < columns.size() - 1) cols.append(", ");
|
||||||
|
}
|
||||||
|
query.append(String.format(" |> sort(columns: [%s])", cols));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 降序
|
||||||
|
*
|
||||||
|
* @param column column
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
public FluxQueryBuilder sortDesc(String column) {
|
||||||
|
return this.sort(Lists.singleton("-" + column));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 升序
|
||||||
|
*
|
||||||
|
* @param column column
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
public FluxQueryBuilder sortAsc(String column) {
|
||||||
|
return this.sort(Lists.singleton(column));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 限制条数
|
||||||
|
*
|
||||||
|
* @param n limit
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
public FluxQueryBuilder limit(int n) {
|
||||||
|
query.append(String.format(" |> limit(n: %d)", n));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 基础过滤拼接
|
||||||
|
*/
|
||||||
|
private void appendFilter(String condition) {
|
||||||
|
if (!hasFilter) {
|
||||||
|
query.append(" |> filter(fn: (r) => ");
|
||||||
|
this.hasFilter = true;
|
||||||
|
} else {
|
||||||
|
query.append(" and ");
|
||||||
|
}
|
||||||
|
query.append(condition);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 结束 filter 并闭合括号
|
||||||
|
*/
|
||||||
|
private void closeFilter() {
|
||||||
|
if (hasFilter) {
|
||||||
|
query.append(")");
|
||||||
|
this.hasFilter = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置美观输出
|
||||||
|
*
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
public FluxQueryBuilder pretty() {
|
||||||
|
this.pretty = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建查询
|
||||||
|
*/
|
||||||
|
public String build() {
|
||||||
|
if (this.pretty) {
|
||||||
|
return query.toString().replaceAll("\\|>", "\n |>");
|
||||||
|
} else {
|
||||||
|
return query.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return this.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,183 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023 - present Dromara, All rights reserved.
|
||||||
|
*
|
||||||
|
* https://visor.dromara.org
|
||||||
|
* https://visor.dromara.org.cn
|
||||||
|
* https://visor.orionsec.cn
|
||||||
|
*
|
||||||
|
* Members:
|
||||||
|
* Jiahang Li - ljh1553488six@139.com - author
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.dromara.visor.framework.influxdb.core.utils;
|
||||||
|
|
||||||
|
import cn.orionsec.kit.lang.utils.Exceptions;
|
||||||
|
import cn.orionsec.kit.lang.utils.collect.Lists;
|
||||||
|
import com.influxdb.client.InfluxDBClient;
|
||||||
|
import com.influxdb.client.WriteApi;
|
||||||
|
import com.influxdb.client.write.Point;
|
||||||
|
import com.influxdb.query.FluxRecord;
|
||||||
|
import com.influxdb.query.FluxTable;
|
||||||
|
import org.dromara.visor.common.constant.Const;
|
||||||
|
import org.dromara.visor.common.entity.chart.TimeChartSeries;
|
||||||
|
import org.dromara.visor.framework.influxdb.core.query.FluxQueryBuilder;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* influxdb 工具类
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2025/8/10 20:47
|
||||||
|
*/
|
||||||
|
public class InfluxdbUtils {
|
||||||
|
|
||||||
|
private static final String FIELD_KEY = "_field";
|
||||||
|
|
||||||
|
private static final List<String> SKIP_EXTRA_KEY = Lists.of("result", "table", "_measurement", "_start", "_stop", "_time", "_value");
|
||||||
|
|
||||||
|
private static InfluxDBClient client;
|
||||||
|
|
||||||
|
private static String bucket;
|
||||||
|
|
||||||
|
private InfluxdbUtils() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 写入指标
|
||||||
|
*
|
||||||
|
* @param points points
|
||||||
|
*/
|
||||||
|
public static void writePoints(List<Point> points) {
|
||||||
|
try (WriteApi api = client.makeWriteApi()) {
|
||||||
|
// 写入指标
|
||||||
|
api.writePoints(points);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询数据点
|
||||||
|
*
|
||||||
|
* @param query query
|
||||||
|
* @return points
|
||||||
|
*/
|
||||||
|
public static List<FluxTable> queryTable(String query) {
|
||||||
|
return client.getQueryApi().query(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询数据点
|
||||||
|
*
|
||||||
|
* @param query query
|
||||||
|
* @return points
|
||||||
|
*/
|
||||||
|
public static FluxTable querySingleTable(String query) {
|
||||||
|
return Lists.first(queryTable(query));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询时序系列
|
||||||
|
*
|
||||||
|
* @param query query
|
||||||
|
* @return points
|
||||||
|
*/
|
||||||
|
public static List<TimeChartSeries> querySeries(String query) {
|
||||||
|
return toSeries(queryTable(query));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询时序系列
|
||||||
|
*
|
||||||
|
* @param query query
|
||||||
|
* @return points
|
||||||
|
*/
|
||||||
|
public static TimeChartSeries querySingleSeries(String query) {
|
||||||
|
return toSeries(querySingleTable(query));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 转为时序系列
|
||||||
|
*
|
||||||
|
* @param table table
|
||||||
|
* @return series
|
||||||
|
*/
|
||||||
|
public static TimeChartSeries toSeries(FluxTable table) {
|
||||||
|
// 数据
|
||||||
|
Map<String, Object> tags = new HashMap<>();
|
||||||
|
List<List<Object>> dataList = new ArrayList<>();
|
||||||
|
for (FluxRecord record : table.getRecords()) {
|
||||||
|
Instant time = record.getTime();
|
||||||
|
if (time == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 设置数据
|
||||||
|
List<Object> data = new ArrayList<>(2);
|
||||||
|
data.add(time.toEpochMilli());
|
||||||
|
data.add(record.getValue());
|
||||||
|
dataList.add(data);
|
||||||
|
// 设置额外值
|
||||||
|
record.getValues().forEach((k, v) -> {
|
||||||
|
if (SKIP_EXTRA_KEY.contains(k)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tags.put(k, v);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// 设置 field
|
||||||
|
tags.put(Const.FIELD, tags.get(FIELD_KEY));
|
||||||
|
tags.remove(FIELD_KEY);
|
||||||
|
// 创建 series
|
||||||
|
return TimeChartSeries.builder()
|
||||||
|
.data(dataList)
|
||||||
|
.tags(tags)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 转为时序系列
|
||||||
|
*
|
||||||
|
* @param tables tables
|
||||||
|
* @return series
|
||||||
|
*/
|
||||||
|
public static List<TimeChartSeries> toSeries(List<FluxTable> tables) {
|
||||||
|
return tables.stream()
|
||||||
|
.map(InfluxdbUtils::toSeries)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取查询构建器
|
||||||
|
*
|
||||||
|
* @return builder
|
||||||
|
*/
|
||||||
|
public static FluxQueryBuilder query() {
|
||||||
|
return FluxQueryBuilder.from(bucket);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setInfluxClient(String bucket, InfluxDBClient client) {
|
||||||
|
if (InfluxdbUtils.client != null) {
|
||||||
|
// unmodified
|
||||||
|
throw Exceptions.state();
|
||||||
|
}
|
||||||
|
InfluxdbUtils.client = client;
|
||||||
|
InfluxdbUtils.bucket = bucket;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
{
|
||||||
|
"groups": [
|
||||||
|
{
|
||||||
|
"name": "spring.influxdb",
|
||||||
|
"type": "org.dromara.visor.framework.influxdb.configuration.config.InfluxdbConfig",
|
||||||
|
"sourceType": "org.dromara.visor.framework.influxdb.configuration.config.InfluxdbConfig"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"properties": [
|
||||||
|
{
|
||||||
|
"name": "spring.influxdb.enabled",
|
||||||
|
"type": "java.lang.Boolean",
|
||||||
|
"description": "是否启用 influxdb.",
|
||||||
|
"defaultValue": "false"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "spring.influxdb.url",
|
||||||
|
"type": "java.lang.String",
|
||||||
|
"description": "influxdb 地址."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "spring.influxdb.org",
|
||||||
|
"type": "java.lang.String",
|
||||||
|
"description": "influxdb org."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "spring.influxdb.bucket",
|
||||||
|
"type": "java.lang.String",
|
||||||
|
"description": "influxdb bucket."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "spring.influxdb.token",
|
||||||
|
"type": "java.lang.String",
|
||||||
|
"description": "influxdb token."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
org.dromara.visor.framework.influxdb.configuration.OrionInfluxdbAutoConfiguration
|
||||||
@@ -23,13 +23,13 @@
|
|||||||
package org.dromara.visor.framework.job.configuration;
|
package org.dromara.visor.framework.job.configuration;
|
||||||
|
|
||||||
import org.dromara.visor.common.constant.AutoConfigureOrderConst;
|
import org.dromara.visor.common.constant.AutoConfigureOrderConst;
|
||||||
|
import org.dromara.visor.common.constant.Const;
|
||||||
import org.dromara.visor.common.thread.ThreadPoolMdcTaskExecutor;
|
import org.dromara.visor.common.thread.ThreadPoolMdcTaskExecutor;
|
||||||
import org.dromara.visor.framework.job.configuration.config.AsyncExecutorConfig;
|
import org.dromara.visor.framework.job.configuration.config.AsyncExecutorConfig;
|
||||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
|
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Primary;
|
|
||||||
import org.springframework.core.task.TaskExecutor;
|
import org.springframework.core.task.TaskExecutor;
|
||||||
import org.springframework.scheduling.annotation.EnableAsync;
|
import org.springframework.scheduling.annotation.EnableAsync;
|
||||||
|
|
||||||
@@ -49,13 +49,10 @@ import java.util.concurrent.ThreadPoolExecutor;
|
|||||||
public class OrionAsyncAutoConfiguration {
|
public class OrionAsyncAutoConfiguration {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 支持 MDC 的异步线程池
|
|
||||||
* <p>
|
|
||||||
* {@code @Async("asyncExecutor")}
|
* {@code @Async("asyncExecutor")}
|
||||||
*
|
*
|
||||||
* @return 异步线程池
|
* @return 支持 MDC 的异步线程池
|
||||||
*/
|
*/
|
||||||
@Primary
|
|
||||||
@Bean(name = "asyncExecutor")
|
@Bean(name = "asyncExecutor")
|
||||||
public TaskExecutor asyncExecutor(AsyncExecutorConfig config) {
|
public TaskExecutor asyncExecutor(AsyncExecutorConfig config) {
|
||||||
ThreadPoolMdcTaskExecutor executor = new ThreadPoolMdcTaskExecutor();
|
ThreadPoolMdcTaskExecutor executor = new ThreadPoolMdcTaskExecutor();
|
||||||
@@ -75,4 +72,25 @@ public class OrionAsyncAutoConfiguration {
|
|||||||
return executor;
|
return executor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@code @Async("metricsExecutor")}
|
||||||
|
*
|
||||||
|
* @return 指标线程池
|
||||||
|
*/
|
||||||
|
@Bean(name = "metricsExecutor")
|
||||||
|
public TaskExecutor metricsExecutor() {
|
||||||
|
ThreadPoolMdcTaskExecutor executor = new ThreadPoolMdcTaskExecutor();
|
||||||
|
executor.setCorePoolSize(4);
|
||||||
|
executor.setMaxPoolSize(8);
|
||||||
|
executor.setQueueCapacity(1000);
|
||||||
|
executor.setKeepAliveSeconds(Const.MS_S_60);
|
||||||
|
executor.setAllowCoreThreadTimeOut(true);
|
||||||
|
executor.setThreadNamePrefix("metrics-task-");
|
||||||
|
executor.setWaitForTasksToCompleteOnShutdown(true);
|
||||||
|
executor.setAwaitTerminationSeconds(60);
|
||||||
|
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
|
||||||
|
executor.initialize();
|
||||||
|
return executor;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,8 +29,8 @@ import java.lang.annotation.*;
|
|||||||
/**
|
/**
|
||||||
* 不执行统一日志打印
|
* 不执行统一日志打印
|
||||||
* <p>
|
* <p>
|
||||||
* 如果设置在方法上,则忽略该方法的日志打印
|
* 如果设置在方法上, 则忽略该方法的日志打印
|
||||||
* 如果设置到参数上,则忽略该参数的日志打印
|
* 如果设置到参数上, 则忽略该参数的日志打印
|
||||||
*
|
*
|
||||||
* @author Jiahang Li
|
* @author Jiahang Li
|
||||||
* @version 1.0.0
|
* @version 1.0.0
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.dromara.visor.framework.log.core.interceptor;
|
package org.dromara.visor.framework.log.core.interceptor;
|
||||||
|
|
||||||
|
import cn.orionsec.kit.lang.utils.Strings;
|
||||||
import cn.orionsec.kit.lang.utils.collect.Maps;
|
import cn.orionsec.kit.lang.utils.collect.Maps;
|
||||||
import cn.orionsec.kit.lang.utils.reflect.Classes;
|
import cn.orionsec.kit.lang.utils.reflect.Classes;
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
@@ -31,8 +32,8 @@ import com.alibaba.fastjson.serializer.ValueFilter;
|
|||||||
import org.aopalliance.intercept.MethodInvocation;
|
import org.aopalliance.intercept.MethodInvocation;
|
||||||
import org.dromara.visor.common.json.FieldDesensitizeFilter;
|
import org.dromara.visor.common.json.FieldDesensitizeFilter;
|
||||||
import org.dromara.visor.common.json.FieldIgnoreFilter;
|
import org.dromara.visor.common.json.FieldIgnoreFilter;
|
||||||
import org.dromara.visor.common.trace.TraceIdHolder;
|
|
||||||
import org.dromara.visor.common.security.SecurityHolder;
|
import org.dromara.visor.common.security.SecurityHolder;
|
||||||
|
import org.dromara.visor.common.trace.TraceIdHolder;
|
||||||
import org.dromara.visor.framework.log.configuration.config.LogPrinterConfig;
|
import org.dromara.visor.framework.log.configuration.config.LogPrinterConfig;
|
||||||
import org.dromara.visor.framework.log.core.annotation.IgnoreLog;
|
import org.dromara.visor.framework.log.core.annotation.IgnoreLog;
|
||||||
import org.dromara.visor.framework.log.core.enums.IgnoreLogMode;
|
import org.dromara.visor.framework.log.core.enums.IgnoreLogMode;
|
||||||
@@ -42,12 +43,13 @@ import org.springframework.web.multipart.MultipartFile;
|
|||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.servlet.ServletRequest;
|
import javax.servlet.ServletRequest;
|
||||||
import javax.servlet.ServletResponse;
|
import javax.servlet.ServletResponse;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.function.Predicate;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 日志打印拦截器 基类
|
* 日志打印拦截器 基类
|
||||||
@@ -60,11 +62,6 @@ public abstract class AbstractLogPrinterInterceptor implements LogPrinterInterce
|
|||||||
|
|
||||||
private static final ThreadLocal<IgnoreLogMode> IGNORE_LOG_MODE = new ThreadLocal<>();
|
private static final ThreadLocal<IgnoreLogMode> IGNORE_LOG_MODE = new ThreadLocal<>();
|
||||||
|
|
||||||
/**
|
|
||||||
* 请求头过滤器
|
|
||||||
*/
|
|
||||||
protected Predicate<String> headerFilter;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 字段过滤器
|
* 字段过滤器
|
||||||
*/
|
*/
|
||||||
@@ -93,8 +90,6 @@ public abstract class AbstractLogPrinterInterceptor implements LogPrinterInterce
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init() {
|
public void init() {
|
||||||
// 请求头过滤器
|
|
||||||
this.headerFilter = header -> config.getHeaders().contains(header);
|
|
||||||
// 参数过滤器
|
// 参数过滤器
|
||||||
this.serializeFilters = new SerializeFilter[]{
|
this.serializeFilters = new SerializeFilter[]{
|
||||||
// 忽略字段过滤器
|
// 忽略字段过滤器
|
||||||
@@ -136,6 +131,24 @@ public abstract class AbstractLogPrinterInterceptor implements LogPrinterInterce
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取请求头
|
||||||
|
*
|
||||||
|
* @param request request
|
||||||
|
* @return headers
|
||||||
|
*/
|
||||||
|
protected Map<String, String> getHeaderMap(HttpServletRequest request) {
|
||||||
|
Map<String, String> headers = new LinkedHashMap<>();
|
||||||
|
for (String headerName : config.getHeaders()) {
|
||||||
|
String headerValue = request.getHeader(headerName);
|
||||||
|
if (Strings.isBlank(headerValue)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
headers.put(headerName, headerValue);
|
||||||
|
}
|
||||||
|
return headers;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 打印请求信息
|
* 打印请求信息
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -84,13 +84,11 @@ public class PrettyLogPrinterInterceptor extends AbstractLogPrinterInterceptor {
|
|||||||
if (request != null) {
|
if (request != null) {
|
||||||
// remoteAddr
|
// remoteAddr
|
||||||
requestLog.append("\tremoteAddr: ").append(IpUtils.getRemoteAddr(request)).append('\n');
|
requestLog.append("\tremoteAddr: ").append(IpUtils.getRemoteAddr(request)).append('\n');
|
||||||
// header
|
// headers
|
||||||
Servlets.getHeaderMap(request).forEach((hk, hv) -> {
|
this.getHeaderMap(request).forEach((hk, hv) -> {
|
||||||
if (headerFilter.test(hk.toLowerCase())) {
|
requestLog.append('\t')
|
||||||
requestLog.append('\t')
|
.append(hk).append(": ")
|
||||||
.append(hk).append(": ")
|
.append(hv).append('\n');
|
||||||
.append(hv).append('\n');
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Method method = invocation.getMethod();
|
Method method = invocation.getMethod();
|
||||||
|
|||||||
@@ -85,14 +85,8 @@ public class RowLogPrinterInterceptor extends AbstractLogPrinterInterceptor impl
|
|||||||
if (request != null) {
|
if (request != null) {
|
||||||
// remoteAddr
|
// remoteAddr
|
||||||
fields.put(REMOTE_ADDR, IpUtils.getRemoteAddr(request));
|
fields.put(REMOTE_ADDR, IpUtils.getRemoteAddr(request));
|
||||||
// header
|
// headers
|
||||||
Map<String, Object> headers = new LinkedHashMap<>();
|
fields.put(HEADERS, this.getHeaderMap(request));
|
||||||
Servlets.getHeaderMap(request).forEach((hk, hv) -> {
|
|
||||||
if (headerFilter.test(hk.toLowerCase())) {
|
|
||||||
headers.put(hk, hv);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
fields.put(HEADERS, headers);
|
|
||||||
}
|
}
|
||||||
Method method = invocation.getMethod();
|
Method method = invocation.getMethod();
|
||||||
// 方法签名
|
// 方法签名
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ public class BaseDO implements Serializable {
|
|||||||
private String creator;
|
private String creator;
|
||||||
|
|
||||||
@Schema(description = "修改人")
|
@Schema(description = "修改人")
|
||||||
@TableField(fill = FieldFill.INSERT_UPDATE, jdbcType = JdbcType.VARCHAR)
|
@TableField(fill = FieldFill.INSERT_UPDATE, update = "IFNULL(#{et.updater}, updater)", jdbcType = JdbcType.VARCHAR)
|
||||||
private String updater;
|
private String updater;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -78,4 +78,4 @@ public class BaseDO implements Serializable {
|
|||||||
@TableField(fill = FieldFill.INSERT, jdbcType = JdbcType.TINYINT)
|
@TableField(fill = FieldFill.INSERT, jdbcType = JdbcType.TINYINT)
|
||||||
private Boolean deleted;
|
private Boolean deleted;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,12 +54,13 @@ public class CodeGenerators {
|
|||||||
// 作者
|
// 作者
|
||||||
String author = Const.ORION_AUTHOR;
|
String author = Const.ORION_AUTHOR;
|
||||||
// 模块
|
// 模块
|
||||||
String module = "infra";
|
String module = "asset";
|
||||||
// 生成的表
|
// 生成的表
|
||||||
Table[] tables = {
|
Table[] tables = {
|
||||||
// Template.create("dict_key", "字典配置项", "dict")
|
// Template.create("dict_key", "字典配置项", "dict")
|
||||||
// .enableProviderApi()
|
// .enableProviderApi()
|
||||||
// .disableUnitTest()
|
// .disableUnitTest()
|
||||||
|
// .enableDeleteUseBatch()
|
||||||
// .cache("dict:keys", "字典配置项")
|
// .cache("dict:keys", "字典配置项")
|
||||||
// .expire(8, TimeUnit.HOURS)
|
// .expire(8, TimeUnit.HOURS)
|
||||||
// .vue("system", "dict-key")
|
// .vue("system", "dict-key")
|
||||||
@@ -73,23 +74,28 @@ public class CodeGenerators {
|
|||||||
// .color("blue", "gray", "red", "green", "white")
|
// .color("blue", "gray", "red", "green", "white")
|
||||||
// .valueUseFields()
|
// .valueUseFields()
|
||||||
// .build(),
|
// .build(),
|
||||||
// Template.create("exec_template_host", "执行模板主机", "exec")
|
|
||||||
// .enableProviderApi()
|
Template.create("host_agent_log", "主机探针日志", "agent")
|
||||||
// .cache("sl", "22")
|
|
||||||
// .vue("exec", "exec-template-host")
|
|
||||||
// .build(),
|
|
||||||
Template.create("system_message", "系统消息", "message")
|
|
||||||
.disableUnitTest()
|
.disableUnitTest()
|
||||||
.enableProviderApi()
|
.vue("monitor", "monitor-host")
|
||||||
.vue("system", "message")
|
.disableRowSelection()
|
||||||
.dict("messageType", "type", "messageType")
|
.enableCardView()
|
||||||
.comment("消息类型")
|
.enableDrawerForm()
|
||||||
.fields("EXEC_FAILED", "UPLOAD_FAILED")
|
|
||||||
.labels("执行失败", "上传失败")
|
.dict("agentLogType", "type")
|
||||||
.extra("tagLabel", "执行失败", "上传失败")
|
.comment("探针日志类型")
|
||||||
.extra("tagVisible", true, true)
|
.fields("OFFLINE", "ONLINE", "INSTALL", "START", "STOP")
|
||||||
.extra("tagColor", "red", "red")
|
.labels("下线", "上线", "安装", "启动", "停止")
|
||||||
.valueUseFields()
|
.valueUseFields()
|
||||||
|
|
||||||
|
.dict("agentLogStatus", "status")
|
||||||
|
.comment("探针日志状态")
|
||||||
|
.fields("WAIT", "RUNNING", "SUCCESS", "FAILED")
|
||||||
|
.labels("等待中", "运行中", "成功", "失败")
|
||||||
|
.color("green", "green", "arcoblue", "red")
|
||||||
|
.loading(true, true, false, false)
|
||||||
|
.valueUseFields()
|
||||||
|
|
||||||
.build(),
|
.build(),
|
||||||
};
|
};
|
||||||
// jdbc 配置 - 使用配置文件
|
// jdbc 配置 - 使用配置文件
|
||||||
@@ -98,7 +104,6 @@ public class CodeGenerators {
|
|||||||
String url = resolveConfigValue(yaml.getValue("spring.datasource.druid.url"));
|
String url = resolveConfigValue(yaml.getValue("spring.datasource.druid.url"));
|
||||||
String username = resolveConfigValue(yaml.getValue("spring.datasource.druid.username"));
|
String username = resolveConfigValue(yaml.getValue("spring.datasource.druid.username"));
|
||||||
String password = resolveConfigValue(yaml.getValue("spring.datasource.druid.password"));
|
String password = resolveConfigValue(yaml.getValue("spring.datasource.druid.password"));
|
||||||
|
|
||||||
// 执行
|
// 执行
|
||||||
runGenerator(outputDir, author,
|
runGenerator(outputDir, author,
|
||||||
tables, module,
|
tables, module,
|
||||||
|
|||||||
@@ -23,10 +23,12 @@
|
|||||||
package org.dromara.visor.framework.mybatis.core.generator.core;
|
package org.dromara.visor.framework.mybatis.core.generator.core;
|
||||||
|
|
||||||
import cn.orionsec.kit.lang.able.Executable;
|
import cn.orionsec.kit.lang.able.Executable;
|
||||||
|
import cn.orionsec.kit.lang.constant.Const;
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
import com.baomidou.mybatisplus.generator.AutoGenerator;
|
import com.baomidou.mybatisplus.generator.AutoGenerator;
|
||||||
import com.baomidou.mybatisplus.generator.config.*;
|
import com.baomidou.mybatisplus.generator.config.*;
|
||||||
import com.baomidou.mybatisplus.generator.config.builder.CustomFile;
|
import com.baomidou.mybatisplus.generator.config.builder.CustomFile;
|
||||||
|
import com.baomidou.mybatisplus.generator.config.builder.Entity;
|
||||||
import com.baomidou.mybatisplus.generator.config.querys.MySqlQuery;
|
import com.baomidou.mybatisplus.generator.config.querys.MySqlQuery;
|
||||||
import com.baomidou.mybatisplus.generator.config.rules.DateType;
|
import com.baomidou.mybatisplus.generator.config.rules.DateType;
|
||||||
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
|
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
|
||||||
@@ -135,6 +137,10 @@ public class CodeGenerator implements Executable {
|
|||||||
// 整合注入配置
|
// 整合注入配置
|
||||||
.injection(injectionConfig);
|
.injection(injectionConfig);
|
||||||
|
|
||||||
|
// 提前解析父类 并且排除父类的 id 字段
|
||||||
|
Entity entity = strategyConfig.entity();
|
||||||
|
entity.getSuperEntityColumns().remove(Const.ID);
|
||||||
|
|
||||||
// 执行
|
// 执行
|
||||||
ag.execute(engine);
|
ag.execute(engine);
|
||||||
}
|
}
|
||||||
@@ -188,6 +194,8 @@ public class CodeGenerator implements Executable {
|
|||||||
case Types.BIT:
|
case Types.BIT:
|
||||||
case Types.TINYINT:
|
case Types.TINYINT:
|
||||||
return DbColumnType.INTEGER;
|
return DbColumnType.INTEGER;
|
||||||
|
case Types.DOUBLE:
|
||||||
|
return DbColumnType.DOUBLE;
|
||||||
default:
|
default:
|
||||||
return typeRegistry.getColumnType(metaInfo);
|
return typeRegistry.getColumnType(metaInfo);
|
||||||
}
|
}
|
||||||
@@ -321,9 +329,14 @@ public class CodeGenerator implements Executable {
|
|||||||
*/
|
*/
|
||||||
private InjectionConfig getInjectionConfig() {
|
private InjectionConfig getInjectionConfig() {
|
||||||
String[][] customFileDefineArr = new String[][]{
|
String[][] customFileDefineArr = new String[][]{
|
||||||
// -------------------- 后端 - module --------------------
|
// -------------------- 后端 --------------------
|
||||||
// http 文件
|
// http 文件
|
||||||
new String[]{"/templates/orion-server-module-controller.http.vm", "${type}Controller.http", "controller"},
|
new String[]{"/templates/orion-server-module-controller.http.vm", "${type}Controller.http", "controller"},
|
||||||
|
// operator log define 文件
|
||||||
|
new String[]{"/templates/orion-server-module-operator-key-define.java.vm", "${type}OperatorType.java", "define.operator"},
|
||||||
|
// convert 文件
|
||||||
|
new String[]{"/templates/orion-server-module-convert.java.vm", "${type}Convert.java", "convert"},
|
||||||
|
// -------------------- 后端 - 实体 --------------------
|
||||||
// vo 文件
|
// vo 文件
|
||||||
new String[]{"/templates/orion-server-module-entity-vo.java.vm", "${type}VO.java", "entity.vo"},
|
new String[]{"/templates/orion-server-module-entity-vo.java.vm", "${type}VO.java", "entity.vo"},
|
||||||
// create request 文件
|
// create request 文件
|
||||||
@@ -332,19 +345,19 @@ public class CodeGenerator implements Executable {
|
|||||||
new String[]{"/templates/orion-server-module-entity-request-update.java.vm", "${type}UpdateRequest.java", "entity.request.${bizPackage}"},
|
new String[]{"/templates/orion-server-module-entity-request-update.java.vm", "${type}UpdateRequest.java", "entity.request.${bizPackage}"},
|
||||||
// query request 文件
|
// query request 文件
|
||||||
new String[]{"/templates/orion-server-module-entity-request-query.java.vm", "${type}QueryRequest.java", "entity.request.${bizPackage}"},
|
new String[]{"/templates/orion-server-module-entity-request-query.java.vm", "${type}QueryRequest.java", "entity.request.${bizPackage}"},
|
||||||
// convert 文件
|
// -------------------- 后端 - 缓存 --------------------
|
||||||
new String[]{"/templates/orion-server-module-convert.java.vm", "${type}Convert.java", "convert"},
|
|
||||||
// cache dto 文件
|
// cache dto 文件
|
||||||
new String[]{"/templates/orion-server-module-cache-dto.java.vm", "${type}CacheDTO.java", "entity.dto"},
|
new String[]{"/templates/orion-server-module-cache-dto.java.vm", "${type}CacheDTO.java", "entity.dto"},
|
||||||
// cache key define 文件
|
// cache key define 文件
|
||||||
new String[]{"/templates/orion-server-module-cache-key-define.java.vm", "${type}CacheKeyDefine.java", "define.cache"},
|
new String[]{"/templates/orion-server-module-cache-key-define.java.vm", "${type}CacheKeyDefine.java", "define.cache"},
|
||||||
// operator log define 文件
|
|
||||||
new String[]{"/templates/orion-server-module-operator-key-define.java.vm", "${type}OperatorType.java", "define.operator"},
|
|
||||||
// -------------------- 后端 - provider --------------------
|
// -------------------- 后端 - provider --------------------
|
||||||
// api 文件
|
// api 文件
|
||||||
new String[]{"/templates/orion-server-provider-api.java.vm", "${type}Api.java", "api"},
|
new String[]{"/templates/orion-server-provider-api.java.vm", "${type}Api.java", "api"},
|
||||||
// api impl 文件
|
// api impl 文件
|
||||||
new String[]{"/templates/orion-server-provider-api-impl.java.vm", "${type}ApiImpl.java", "api.impl"},
|
new String[]{"/templates/orion-server-provider-api-impl.java.vm", "${type}ApiImpl.java", "api.impl"},
|
||||||
|
// convert 文件
|
||||||
|
new String[]{"/templates/orion-server-provider-convert.java.vm", "${type}ProviderConvert.java", "convert"},
|
||||||
|
// -------------------- 后端 - provider 实体 --------------------
|
||||||
// dto 文件
|
// dto 文件
|
||||||
new String[]{"/templates/orion-server-provider-entity-dto.java.vm", "${type}DTO.java", "entity.dto.${bizPackage}"},
|
new String[]{"/templates/orion-server-provider-entity-dto.java.vm", "${type}DTO.java", "entity.dto.${bizPackage}"},
|
||||||
// create dto 文件
|
// create dto 文件
|
||||||
@@ -353,8 +366,6 @@ public class CodeGenerator implements Executable {
|
|||||||
new String[]{"/templates/orion-server-provider-entity-dto-update.java.vm", "${type}UpdateDTO.java", "entity.dto.${bizPackage}"},
|
new String[]{"/templates/orion-server-provider-entity-dto-update.java.vm", "${type}UpdateDTO.java", "entity.dto.${bizPackage}"},
|
||||||
// query dto 文件
|
// query dto 文件
|
||||||
new String[]{"/templates/orion-server-provider-entity-dto-query.java.vm", "${type}QueryDTO.java", "entity.dto.${bizPackage}"},
|
new String[]{"/templates/orion-server-provider-entity-dto-query.java.vm", "${type}QueryDTO.java", "entity.dto.${bizPackage}"},
|
||||||
// convert 文件
|
|
||||||
new String[]{"/templates/orion-server-provider-convert.java.vm", "${type}ProviderConvert.java", "convert"},
|
|
||||||
// -------------------- 后端 - test --------------------
|
// -------------------- 后端 - test --------------------
|
||||||
// service unit test 文件
|
// service unit test 文件
|
||||||
new String[]{"/templates/orion-server-test-service-impl-tests.java.vm", "${type}ServiceImplTests.java", "service.impl"},
|
new String[]{"/templates/orion-server-test-service-impl-tests.java.vm", "${type}ServiceImplTests.java", "service.impl"},
|
||||||
@@ -369,22 +380,26 @@ public class CodeGenerator implements Executable {
|
|||||||
new String[]{"/templates/orion-vue-router.ts.vm", "${feature}.ts", "vue/router/routes/modules"},
|
new String[]{"/templates/orion-vue-router.ts.vm", "${feature}.ts", "vue/router/routes/modules"},
|
||||||
// views index.ts 文件
|
// views index.ts 文件
|
||||||
new String[]{"/templates/orion-vue-views-index.vue.vm", "index.vue", "vue/views/${module}/${feature}"},
|
new String[]{"/templates/orion-vue-views-index.vue.vm", "index.vue", "vue/views/${module}/${feature}"},
|
||||||
|
// const.ts 文件
|
||||||
|
new String[]{"/templates/orion-vue-views-types-const.ts.vm", "const.ts", "vue/views/${module}/${feature}/types"},
|
||||||
|
// -------------------- 前端 - form --------------------
|
||||||
// form-modal.vue 文件
|
// form-modal.vue 文件
|
||||||
new String[]{"/templates/orion-vue-views-components-form-modal.vue.vm", "${feature}-form-modal.vue", "vue/views/${module}/${feature}/components"},
|
new String[]{"/templates/orion-vue-views-components-form-modal.vue.vm", "${feature}-form-modal.vue", "vue/views/${module}/${feature}/components"},
|
||||||
// form-drawer.vue 文件
|
// form-drawer.vue 文件
|
||||||
new String[]{"/templates/orion-vue-views-components-form-drawer.vue.vm", "${feature}-form-drawer.vue", "vue/views/${module}/${feature}/components"},
|
new String[]{"/templates/orion-vue-views-components-form-drawer.vue.vm", "${feature}-form-drawer.vue", "vue/views/${module}/${feature}/components"},
|
||||||
// table.vue 文件
|
|
||||||
new String[]{"/templates/orion-vue-views-components-table.vue.vm", "${feature}-table.vue", "vue/views/${module}/${feature}/components"},
|
|
||||||
// card-list.vue 文件
|
|
||||||
new String[]{"/templates/orion-vue-views-components-card-list.vue.vm", "${feature}-card-list.vue", "vue/views/${module}/${feature}/components"},
|
|
||||||
// const.ts 文件
|
|
||||||
new String[]{"/templates/orion-vue-views-types-const.ts.vm", "const.ts", "vue/views/${module}/${feature}/types"},
|
|
||||||
// form.rules.ts 文件
|
// form.rules.ts 文件
|
||||||
new String[]{"/templates/orion-vue-views-types-form.rules.ts.vm", "form.rules.ts", "vue/views/${module}/${feature}/types"},
|
new String[]{"/templates/orion-vue-views-types-form.rules.ts.vm", "form.rules.ts", "vue/views/${module}/${feature}/types"},
|
||||||
|
// -------------------- 前端 - table --------------------
|
||||||
|
// table.vue 文件
|
||||||
|
new String[]{"/templates/orion-vue-views-components-table.vue.vm", "${feature}-table.vue", "vue/views/${module}/${feature}/components"},
|
||||||
// table.columns.ts 文件
|
// table.columns.ts 文件
|
||||||
new String[]{"/templates/orion-vue-views-types-table.columns.ts.vm", "table.columns.ts", "vue/views/${module}/${feature}/types"},
|
new String[]{"/templates/orion-vue-views-types-table.columns.ts.vm", "table.columns.ts", "vue/views/${module}/${feature}/types"},
|
||||||
|
// -------------------- 前端 - card --------------------
|
||||||
|
// card-list.vue 文件
|
||||||
|
new String[]{"/templates/orion-vue-views-components-card-list.vue.vm", "${feature}-card-list.vue", "vue/views/${module}/${feature}/components"},
|
||||||
// card.fields.ts 文件
|
// card.fields.ts 文件
|
||||||
new String[]{"/templates/orion-vue-views-types-card.fields.ts.vm", "card.fields.ts", "vue/views/${module}/${feature}/types"},
|
new String[]{"/templates/orion-vue-views-types-card.fields.ts.vm", "card.fields.ts", "vue/views/${module}/${feature}/types"},
|
||||||
|
// -------------------- sql --------------------
|
||||||
// menu.sql 文件
|
// menu.sql 文件
|
||||||
new String[]{"/templates/orion-sql-menu.sql.vm", "${tableName}-menu.sql", "sql"},
|
new String[]{"/templates/orion-sql-menu.sql.vm", "${tableName}-menu.sql", "sql"},
|
||||||
// dict.sql 文件
|
// dict.sql 文件
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ public class DictParser {
|
|||||||
meta.setComment(Strings.def(tableField.getComment(), meta.getField()));
|
meta.setComment(Strings.def(tableField.getComment(), meta.getField()));
|
||||||
}
|
}
|
||||||
// 设置额外参数 schema
|
// 设置额外参数 schema
|
||||||
if (meta.getExtraValues().size() > 0) {
|
if (!meta.getExtraValues().isEmpty()) {
|
||||||
List<Map<String, String>> extraSchema = meta.getExtraValues().get(0)
|
List<Map<String, String>> extraSchema = meta.getExtraValues().get(0)
|
||||||
.keySet()
|
.keySet()
|
||||||
.stream()
|
.stream()
|
||||||
|
|||||||
@@ -165,6 +165,16 @@ public class DictTemplate extends Template {
|
|||||||
return this.extra(Const.COLOR, colors);
|
return this.extra(Const.COLOR, colors);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加 loading
|
||||||
|
*
|
||||||
|
* @param loading loading
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
public DictTemplate loading(Object... loading) {
|
||||||
|
return this.extra(Const.LOADING, loading);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 添加额外值
|
* 添加额外值
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ public class ${entity} {
|
|||||||
#end
|
#end
|
||||||
## ---------- BEGIN 字段循环遍历 ----------
|
## ---------- BEGIN 字段循环遍历 ----------
|
||||||
#foreach($field in ${table.fields})
|
#foreach($field in ${table.fields})
|
||||||
|
#if("$!field.propertyName" != "id")
|
||||||
|
|
||||||
#if(${field.keyFlag})
|
#if(${field.keyFlag})
|
||||||
#set($keyPropertyName=${field.propertyName})
|
#set($keyPropertyName=${field.propertyName})
|
||||||
@@ -88,5 +89,6 @@ public class ${entity} {
|
|||||||
#end
|
#end
|
||||||
private ${field.propertyType} ${field.propertyName};
|
private ${field.propertyType} ${field.propertyName};
|
||||||
#end
|
#end
|
||||||
|
#end
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -133,14 +133,14 @@
|
|||||||
|
|
||||||
const cardColLayout = useCardColLayout();
|
const cardColLayout = useCardColLayout();
|
||||||
const pagination = useCardPagination();
|
const pagination = useCardPagination();
|
||||||
|
const { loading, setLoading } = useLoading();
|
||||||
const queryOrder = useQueryOrder(TableName, ASC);
|
const queryOrder = useQueryOrder(TableName, ASC);
|
||||||
const { cardFieldConfig, fieldsHook } = useCardFieldConfig(TableName, fieldConfig);
|
const { cardFieldConfig, fieldsHook } = useCardFieldConfig(TableName, fieldConfig);
|
||||||
const { loading, setLoading } = useLoading();
|
|
||||||
#if($dictMap.entrySet().size() > 0)
|
#if($dictMap.entrySet().size() > 0)
|
||||||
const { toOptions, getDictValue } = useDictStore();
|
const { toOptions, getDictValue } = useDictStore();
|
||||||
#end
|
#end
|
||||||
|
|
||||||
const list = ref<${vue.featureEntity}QueryResponse[]>([]);
|
const list = ref<Array<${vue.featureEntity}QueryResponse>>([]);
|
||||||
const formRef = ref();
|
const formRef = ref();
|
||||||
const formModel = reactive<${vue.featureEntity}QueryRequest>({
|
const formModel = reactive<${vue.featureEntity}QueryRequest>({
|
||||||
searchValue: undefined,
|
searchValue: undefined,
|
||||||
|
|||||||
@@ -172,9 +172,9 @@
|
|||||||
const rowSelection = useRowSelection();
|
const rowSelection = useRowSelection();
|
||||||
#end
|
#end
|
||||||
const pagination = useTablePagination();
|
const pagination = useTablePagination();
|
||||||
|
const { loading, setLoading } = useLoading();
|
||||||
const queryOrder = useQueryOrder(TableName, ASC);
|
const queryOrder = useQueryOrder(TableName, ASC);
|
||||||
const { tableColumns, columnsHook } = useTableColumns(TableName, columns);
|
const { tableColumns, columnsHook } = useTableColumns(TableName, columns);
|
||||||
const { loading, setLoading } = useLoading();
|
|
||||||
#if($dictMap.entrySet().size() > 0)
|
#if($dictMap.entrySet().size() > 0)
|
||||||
const { toOptions, getDictValue } = useDictStore();
|
const { toOptions, getDictValue } = useDictStore();
|
||||||
#end
|
#end
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ const fieldConfig = {
|
|||||||
render: ({ record }) => {
|
render: ({ record }) => {
|
||||||
return dateFormat(new Date(record.createTime));
|
return dateFormat(new Date(record.createTime));
|
||||||
},
|
},
|
||||||
|
default: true,
|
||||||
}, {
|
}, {
|
||||||
label: '修改时间',
|
label: '修改时间',
|
||||||
dataIndex: 'updateTime',
|
dataIndex: 'updateTime',
|
||||||
@@ -41,10 +42,17 @@ const fieldConfig = {
|
|||||||
label: '创建人',
|
label: '创建人',
|
||||||
dataIndex: 'creator',
|
dataIndex: 'creator',
|
||||||
slotName: 'creator',
|
slotName: 'creator',
|
||||||
|
width: 148,
|
||||||
|
ellipsis: true,
|
||||||
|
tooltip: true,
|
||||||
|
default: true,
|
||||||
}, {
|
}, {
|
||||||
label: '修改人',
|
label: '修改人',
|
||||||
dataIndex: 'updater',
|
dataIndex: 'updater',
|
||||||
slotName: 'updater',
|
slotName: 'updater',
|
||||||
|
width: 148,
|
||||||
|
ellipsis: true,
|
||||||
|
tooltip: true,
|
||||||
}
|
}
|
||||||
] as CardField[]
|
] as CardField[]
|
||||||
} as CardFieldConfig;
|
} as CardFieldConfig;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
export const TABLE_NAME = '$table.name';
|
export const TableName = '$table.name';
|
||||||
|
|
||||||
#if($dictMap.entrySet().size() > 0)
|
#if($dictMap.entrySet().size() > 0)
|
||||||
#foreach($enumEntity in $dictMap.entrySet())
|
#foreach($enumEntity in $dictMap.entrySet())
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import type { FieldRule } from '@arco-design/web-vue';
|
import type { FieldRule } from '@arco-design/web-vue';
|
||||||
|
|
||||||
#foreach($field in ${table.fields})
|
#foreach($field in ${table.fields})
|
||||||
#if("$!field.propertyName" != "id")
|
#if("$!field.propertyName" != "id")
|
||||||
#if(${field.propertyType} == 'String' && "$field.metaInfo.jdbcType" != "LONGVARCHAR")
|
#if(${field.propertyType} == 'String' && "$field.metaInfo.jdbcType" != "LONGVARCHAR")
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ const columns = [
|
|||||||
minWidth: 238,
|
minWidth: 238,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
tooltip: true,
|
tooltip: true,
|
||||||
|
#elseif(${field.propertyType} == 'Integer' || ${field.propertyType} == 'Long')
|
||||||
|
width: 120,
|
||||||
#elseif(${field.propertyType} == 'Date')
|
#elseif(${field.propertyType} == 'Date')
|
||||||
width: 180,
|
width: 180,
|
||||||
render: ({ record }) => {
|
render: ({ record }) => {
|
||||||
@@ -35,6 +37,7 @@ const columns = [
|
|||||||
render: ({ record }) => {
|
render: ({ record }) => {
|
||||||
return dateFormat(new Date(record.createTime));
|
return dateFormat(new Date(record.createTime));
|
||||||
},
|
},
|
||||||
|
default: true,
|
||||||
}, {
|
}, {
|
||||||
title: '修改时间',
|
title: '修改时间',
|
||||||
dataIndex: 'updateTime',
|
dataIndex: 'updateTime',
|
||||||
@@ -48,6 +51,7 @@ const columns = [
|
|||||||
title: '创建人',
|
title: '创建人',
|
||||||
dataIndex: 'creator',
|
dataIndex: 'creator',
|
||||||
slotName: 'creator',
|
slotName: 'creator',
|
||||||
|
default: true,
|
||||||
}, {
|
}, {
|
||||||
title: '修改人',
|
title: '修改人',
|
||||||
dataIndex: 'updater',
|
dataIndex: 'updater',
|
||||||
@@ -58,6 +62,7 @@ const columns = [
|
|||||||
width: 130,
|
width: 130,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
|
default: true,
|
||||||
},
|
},
|
||||||
] as TableColumnData[];
|
] as TableColumnData[];
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@
|
|||||||
<artifactId>netty-all</artifactId>
|
<artifactId>netty-all</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- test redis noRedis -->
|
<!-- test redis MockRedis -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.fppt</groupId>
|
<groupId>com.github.fppt</groupId>
|
||||||
<artifactId>jedis-mock</artifactId>
|
<artifactId>jedis-mock</artifactId>
|
||||||
|
|||||||
@@ -24,7 +24,8 @@ package org.dromara.visor.framework.redis.configuration;
|
|||||||
|
|
||||||
import com.github.fppt.jedismock.RedisServer;
|
import com.github.fppt.jedismock.RedisServer;
|
||||||
import org.dromara.visor.common.constant.AutoConfigureOrderConst;
|
import org.dromara.visor.common.constant.AutoConfigureOrderConst;
|
||||||
import org.dromara.visor.common.interfaces.Locker;
|
import org.dromara.visor.common.lock.EmptyLocker;
|
||||||
|
import org.dromara.visor.common.lock.Locker;
|
||||||
import org.dromara.visor.common.utils.LockerUtils;
|
import org.dromara.visor.common.utils.LockerUtils;
|
||||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
|
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
|
||||||
@@ -35,20 +36,19 @@ import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
|
|||||||
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
|
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
|
||||||
|
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* noRedis 配置
|
* MockRedis
|
||||||
* 仅用于本地调试无 redis 的情况
|
* 仅用于本地调试无 redis 的情况
|
||||||
*
|
*
|
||||||
* @author Jiahang Li
|
* @author Jiahang Li
|
||||||
* @version 1.0.0
|
* @version 1.0.0
|
||||||
* @since 2024/12/26 10:02
|
* @since 2024/12/26 10:02
|
||||||
*/
|
*/
|
||||||
@ConditionalOnProperty(value = "no.redis", havingValue = "true")
|
@ConditionalOnProperty(value = "spring.redis.mock", havingValue = "true")
|
||||||
@AutoConfiguration
|
@AutoConfiguration
|
||||||
@AutoConfigureOrder(AutoConfigureOrderConst.FRAMEWORK_REDIS - 10)
|
@AutoConfigureOrder(AutoConfigureOrderConst.FRAMEWORK_REDIS - 10)
|
||||||
public class OrionNoRedisAutoConfiguration {
|
public class OrionMockRedisAutoConfiguration {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return mocked redis server
|
* @return mocked redis server
|
||||||
@@ -79,18 +79,7 @@ public class OrionNoRedisAutoConfiguration {
|
|||||||
*/
|
*/
|
||||||
@Bean
|
@Bean
|
||||||
public Locker redisLocker() {
|
public Locker redisLocker() {
|
||||||
Locker locker = new Locker() {
|
EmptyLocker locker = new EmptyLocker();
|
||||||
@Override
|
|
||||||
public boolean tryLock(String key, Runnable run) {
|
|
||||||
run.run();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> T tryLock(String key, Supplier<T> call) {
|
|
||||||
return call.get();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
LockerUtils.setDelegate(locker);
|
LockerUtils.setDelegate(locker);
|
||||||
return locker;
|
return locker;
|
||||||
}
|
}
|
||||||
@@ -22,8 +22,9 @@
|
|||||||
*/
|
*/
|
||||||
package org.dromara.visor.framework.redis.configuration;
|
package org.dromara.visor.framework.redis.configuration;
|
||||||
|
|
||||||
|
import cn.orionsec.kit.lang.define.cache.key.CacheKeyDefine;
|
||||||
import org.dromara.visor.common.constant.AutoConfigureOrderConst;
|
import org.dromara.visor.common.constant.AutoConfigureOrderConst;
|
||||||
import org.dromara.visor.common.interfaces.Locker;
|
import org.dromara.visor.common.lock.Locker;
|
||||||
import org.dromara.visor.common.utils.LockerUtils;
|
import org.dromara.visor.common.utils.LockerUtils;
|
||||||
import org.dromara.visor.framework.redis.configuration.config.RedissonConfig;
|
import org.dromara.visor.framework.redis.configuration.config.RedissonConfig;
|
||||||
import org.dromara.visor.framework.redis.core.lock.RedisLocker;
|
import org.dromara.visor.framework.redis.core.lock.RedisLocker;
|
||||||
@@ -31,6 +32,7 @@ import org.dromara.visor.framework.redis.core.utils.RedisUtils;
|
|||||||
import org.redisson.api.RedissonClient;
|
import org.redisson.api.RedissonClient;
|
||||||
import org.redisson.config.SingleServerConfig;
|
import org.redisson.config.SingleServerConfig;
|
||||||
import org.redisson.spring.starter.RedissonAutoConfigurationCustomizer;
|
import org.redisson.spring.starter.RedissonAutoConfigurationCustomizer;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
|
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
@@ -101,5 +103,15 @@ public class OrionRedisAutoConfiguration {
|
|||||||
return redisLocker;
|
return redisLocker;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置 redis 数据版本
|
||||||
|
*
|
||||||
|
* @param dataVersion dataVersion
|
||||||
|
*/
|
||||||
|
@Value("${spring.redis.data-version}")
|
||||||
|
public void setDataVersion(String dataVersion) {
|
||||||
|
CacheKeyDefine.setGlobalPrefix("v" + dataVersion + ":");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user