Compare commits
74 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
876e763fcc | ||
|
|
32d60a4d43 | ||
|
|
6ffc5d27b5 | ||
|
|
ac412b0dde | ||
|
|
4bdb61870a | ||
|
|
24ad1f64df | ||
|
|
6774376418 | ||
|
|
364120c143 | ||
|
|
cb59390fed | ||
|
|
69bc5b859f | ||
|
|
c420747c6f | ||
|
|
1881086e98 | ||
|
|
eb8d618c2a | ||
|
|
8aa8cda677 | ||
|
|
e67ee60361 | ||
|
|
29fcdd311e | ||
|
|
bb243cf195 | ||
|
|
670e40f6f0 | ||
|
|
feb379f85f | ||
|
|
a8de5ab713 | ||
|
|
4b0c91f106 | ||
|
|
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 |
22
.env.example
22
.env.example
@@ -1,11 +1,17 @@
|
|||||||
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
|
||||||
|
API_EXPOSE_TOKEN=pmqeHOyZaumHm0Wt
|
||||||
SECRET_KEY=uQeacXV8b3isvKLK
|
SECRET_KEY=uQeacXV8b3isvKLK
|
||||||
|
|
||||||
|
NGINX_SERVICE_HOST=service
|
||||||
|
NGINX_SERVICE_PORT=9200
|
||||||
|
|
||||||
MYSQL_HOST=mysql
|
MYSQL_HOST=mysql
|
||||||
MYSQL_PORT=3306
|
MYSQL_PORT=3306
|
||||||
MYSQL_DATABASE=orion_visor
|
MYSQL_DATABASE=orion_visor
|
||||||
@@ -20,4 +26,16 @@ 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
|
||||||
|
|
||||||
|
### 测试用例
|
||||||
|
|
||||||
|
### 修复效果的截屏
|
||||||
|
|
||||||
50
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
Normal file
50
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
name: 错误报告
|
||||||
|
description: File a bug report.
|
||||||
|
title: "[错误报告]: "
|
||||||
|
labels: [ "" ]
|
||||||
|
body:
|
||||||
|
- 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: "参考资料"
|
||||||
@@ -41,6 +41,10 @@ jobs:
|
|||||||
pnpm install
|
pnpm install
|
||||||
pnpm build
|
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
|
- name: 📁 Prepare build context
|
||||||
run: |
|
run: |
|
||||||
cp -r ./sql ./docker/mysql/sql
|
cp -r ./sql ./docker/mysql/sql
|
||||||
@@ -62,7 +66,7 @@ jobs:
|
|||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
service: [ adminer, guacd, mysql, redis, service, ui ]
|
service: [ adminer, guacd, mysql, redis, influxdb, service, ui ]
|
||||||
|
|
||||||
env:
|
env:
|
||||||
GITHUB_REGISTRY: ghcr.io
|
GITHUB_REGISTRY: ghcr.io
|
||||||
@@ -117,11 +121,15 @@ jobs:
|
|||||||
type=semver,pattern={{major}}
|
type=semver,pattern={{major}}
|
||||||
|
|
||||||
- name: 🛠️ Build and push Docker image for orion-visor-${{ matrix.service }}
|
- name: 🛠️ Build and push Docker image for orion-visor-${{ matrix.service }}
|
||||||
uses: docker/build-push-action@v5
|
uses: docker/build-push-action@v6
|
||||||
with:
|
with:
|
||||||
context: ./docker
|
context: ./docker
|
||||||
file: ./docker/${{ matrix.service }}/Dockerfile
|
file: ./docker/${{ matrix.service }}/Dockerfile
|
||||||
push: true
|
push: true
|
||||||
|
cache-from: type=gha
|
||||||
|
cache-to: type=gha,mode=max
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
tags: |
|
tags: |
|
||||||
${{ env.DOCKERHUB_NAMESPACE }}/orion-visor-${{ matrix.service }}:${{ steps.meta.outputs.version }}
|
${{ env.DOCKERHUB_NAMESPACE }}/orion-visor-${{ matrix.service }}:${{ steps.meta.outputs.version }}
|
||||||
${{ env.DOCKERHUB_NAMESPACE }}/orion-visor-${{ matrix.service }}:latest
|
${{ env.DOCKERHUB_NAMESPACE }}/orion-visor-${{ matrix.service }}:latest
|
||||||
@@ -129,5 +137,3 @@ jobs:
|
|||||||
${{ env.GITHUB_REGISTRY }}/${{ github.repository_owner }}/orion-visor-${{ matrix.service }}:latest
|
${{ 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 }}:${{ steps.meta.outputs.version }}
|
||||||
${{ env.ALIYUN_REGISTRY }}/${{ env.ALIYUN_NAMESPACE }}/orion-visor-${{ matrix.service }}:latest
|
${{ env.ALIYUN_REGISTRY }}/${{ env.ALIYUN_NAMESPACE }}/orion-visor-${{ matrix.service }}:latest
|
||||||
labels: ${{ steps.meta.outputs.labels }}
|
|
||||||
platforms: linux/amd64,linux/arm64
|
|
||||||
9
.github/workflows/e2e.yaml
vendored
9
.github/workflows/e2e.yaml
vendored
@@ -1,9 +1,10 @@
|
|||||||
name: E2E
|
name: E2E
|
||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request:
|
workflow_dispatch:
|
||||||
branches:
|
# pull_request:
|
||||||
- main
|
# branches:
|
||||||
|
# - main
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: ${{github.workflow}} - ${{github.ref}}
|
group: ${{github.workflow}} - ${{github.ref}}
|
||||||
@@ -18,4 +19,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
|
||||||
|
|||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -16,7 +16,8 @@ target/
|
|||||||
.sts4-cache
|
.sts4-cache
|
||||||
|
|
||||||
### IntelliJ IDEA ###
|
### IntelliJ IDEA ###
|
||||||
.idea
|
**/.idea/*
|
||||||
|
!**/.idea/icon.png
|
||||||
*.iws
|
*.iws
|
||||||
*.iml
|
*.iml
|
||||||
*.ipr
|
*.ipr
|
||||||
|
|||||||
BIN
.idea/icon.png
generated
Normal file
BIN
.idea/icon.png
generated
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.8 KiB |
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
@@ -52,6 +52,7 @@
|
|||||||
* **文件管理**:支持远程主机 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,13 @@ docker compose up -d
|
|||||||
|
|
||||||

|

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

|
||||||
|

|
||||||
|

|
||||||
|

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

|

|
||||||
@@ -130,7 +136,8 @@ docker compose up -d
|
|||||||
|
|
||||||
## 关于我
|
## 关于我
|
||||||
|
|
||||||
本人专注于使用 Java 和 Vue 进行全栈开发, 并在系统自动化运维方面拥有丰富开发的经验。如果您在这些领域有需求或遇到痛点, 请随时联系我, 并备注“合作”。
|
本人专注于使用 Java 和 Vue 进行全栈开发, 并在系统自动化运维方面拥有丰富开发的经验, 并提供企业级的解决方案。如果您在这些领域有需求或遇到痛点, 请随时联系我,
|
||||||
|
并备注“合作”。
|
||||||
|
|
||||||
## 联系我
|
## 联系我
|
||||||
|
|
||||||
@@ -156,6 +163,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,6 @@
|
|||||||
version: '3.3'
|
version: '3.3'
|
||||||
|
|
||||||
# latest = 2.4.2
|
# latest = 2.5.2
|
||||||
|
|
||||||
# 支持以下源
|
# 支持以下源
|
||||||
# lijiahangmax/*
|
# lijiahangmax/*
|
||||||
@@ -12,6 +12,9 @@ services:
|
|||||||
image: registry.cn-hangzhou.aliyuncs.com/orionsec/orion-visor-ui:latest
|
image: registry.cn-hangzhou.aliyuncs.com/orionsec/orion-visor-ui:latest
|
||||||
ports:
|
ports:
|
||||||
- ${SERVICE_PORT:-1081}:80
|
- ${SERVICE_PORT:-1081}:80
|
||||||
|
environment:
|
||||||
|
NGINX_SERVICE_HOST: ${NGINX_SERVICE_HOST:-service}
|
||||||
|
NGINX_SERVICE_PORT: ${NGINX_SERVICE_PORT:-9200}
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
depends_on:
|
depends_on:
|
||||||
service:
|
service:
|
||||||
@@ -23,7 +26,11 @@ 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"
|
||||||
|
ulimits:
|
||||||
|
nofile:
|
||||||
|
soft: 65536
|
||||||
|
hard: 65536
|
||||||
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}
|
||||||
@@ -35,10 +42,18 @@ services:
|
|||||||
REDIS_PASSWORD: ${REDIS_PASSWORD:-Data@123456}
|
REDIS_PASSWORD: ${REDIS_PASSWORD:-Data@123456}
|
||||||
REDIS_DATABASE: ${REDIS_DATABASE:-0}
|
REDIS_DATABASE: ${REDIS_DATABASE:-0}
|
||||||
REDIS_DATA_VERSION: ${REDIS_DATA_VERSION:-1}
|
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:-uQeacXV8b3isvKLK}
|
||||||
|
API_EXPOSE_TOKEN: ${API_EXPOSE_TOKEN:-pmqeHOyZaumHm0Wt}
|
||||||
|
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
|
||||||
@@ -54,6 +69,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
|
||||||
|
|
||||||
@@ -61,7 +78,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}
|
||||||
@@ -84,7 +101,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:
|
||||||
@@ -100,10 +117,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
|
||||||
@@ -125,7 +167,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:
|
||||||
@@ -41,7 +41,7 @@ if [ "$DEMO_MODE" = true ]; then
|
|||||||
echo "Starting services for demo mode..."
|
echo "Starting services for demo mode..."
|
||||||
|
|
||||||
# 启动指定的服务
|
# 启动指定的服务
|
||||||
docker compose up -d --remove-orphans mysql redis ui service guacd adminer
|
docker compose up -d --remove-orphans mysql redis ui service guacd influxdb adminer
|
||||||
echo "Started services for demo mode..."
|
echo "Started services for demo mode..."
|
||||||
else
|
else
|
||||||
# 启动所有服务
|
# 启动所有服务
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
FROM --platform=$BUILDPLATFORM adminer:latest
|
FROM --platform=$TARGETPLATFORM adminer:latest
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
FROM maven:3.9.10-eclipse-temurin-8-alpine AS builder
|
#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
|
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
#FROM --platform=$BUILDPLATFORM node:18-alpine AS builder
|
||||||
FROM node:18-alpine AS builder
|
FROM node:18-alpine AS builder
|
||||||
|
|
||||||
# 设置阿里云镜像加速
|
# 设置阿里云镜像加速
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ set -e
|
|||||||
source ./project-build.sh "$@"
|
source ./project-build.sh "$@"
|
||||||
|
|
||||||
# 版本号
|
# 版本号
|
||||||
version=2.4.2
|
version=2.5.2
|
||||||
# 是否推送镜像
|
# 是否推送镜像
|
||||||
push_image=false
|
push_image=false
|
||||||
# 是否构建 latest
|
# 是否构建 latest
|
||||||
@@ -46,6 +46,7 @@ declare -A images=(
|
|||||||
["./service/Dockerfile"]="orion-visor-service"
|
["./service/Dockerfile"]="orion-visor-service"
|
||||||
["./mysql/Dockerfile"]="orion-visor-mysql"
|
["./mysql/Dockerfile"]="orion-visor-mysql"
|
||||||
["./redis/Dockerfile"]="orion-visor-redis"
|
["./redis/Dockerfile"]="orion-visor-redis"
|
||||||
|
["./influxdb/Dockerfile"]="orion-visor-influxdb"
|
||||||
["./adminer/Dockerfile"]="orion-visor-adminer"
|
["./adminer/Dockerfile"]="orion-visor-adminer"
|
||||||
["./guacd/Dockerfile"]="orion-visor-guacd"
|
["./guacd/Dockerfile"]="orion-visor-guacd"
|
||||||
)
|
)
|
||||||
@@ -68,6 +69,30 @@ function prepare_app_jar() {
|
|||||||
fi
|
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 目录
|
# 准备前端 dist 目录
|
||||||
function prepare_dist_directory() {
|
function prepare_dist_directory() {
|
||||||
local source_dir="../orion-visor-ui/dist"
|
local source_dir="../orion-visor-ui/dist"
|
||||||
@@ -115,7 +140,7 @@ function modify_dockerfiles() {
|
|||||||
if [ -f "$file" ]; then
|
if [ -f "$file" ]; then
|
||||||
echo "备份并修改: $file"
|
echo "备份并修改: $file"
|
||||||
cp "$file" "$file$backup_suffix"
|
cp "$file" "$file$backup_suffix"
|
||||||
sed -i 's/--platform=\$BUILDPLATFORM//g' "$file"
|
sed -i 's/--platform=\TARGETPLATFORM//g' "$file"
|
||||||
else
|
else
|
||||||
echo "文件不存在 -> $file"
|
echo "文件不存在 -> $file"
|
||||||
fi
|
fi
|
||||||
@@ -185,6 +210,7 @@ fi
|
|||||||
# 检查资源
|
# 检查资源
|
||||||
echo "正在检查并准备必要的构建资源..."
|
echo "正在检查并准备必要的构建资源..."
|
||||||
prepare_app_jar
|
prepare_app_jar
|
||||||
|
prepare_instance_agent
|
||||||
prepare_dist_directory
|
prepare_dist_directory
|
||||||
prepare_sql_directory
|
prepare_sql_directory
|
||||||
echo "所有前置资源已准备完毕"
|
echo "所有前置资源已准备完毕"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM --platform=$BUILDPLATFORM guacamole/guacd:1.6.0
|
FROM --platform=$TARGETPLATFORM guacamole/guacd:1.6.0
|
||||||
|
|
||||||
USER root
|
USER root
|
||||||
|
|
||||||
|
|||||||
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,4 +1,4 @@
|
|||||||
FROM --platform=$BUILDPLATFORM mysql:8.0.28
|
FROM --platform=$TARGETPLATFORM mysql:8.0.39
|
||||||
|
|
||||||
# 系统时区
|
# 系统时区
|
||||||
ARG TZ=Asia/Shanghai
|
ARG TZ=Asia/Shanghai
|
||||||
@@ -12,3 +12,7 @@ COPY ./mysql/my.cnf /etc/mysql/conf.d/my.cnf
|
|||||||
|
|
||||||
# 复制初始化脚本
|
# 复制初始化脚本
|
||||||
COPY ./mysql/sql/init-*.sql /docker-entrypoint-initdb.d/
|
COPY ./mysql/sql/init-*.sql /docker-entrypoint-initdb.d/
|
||||||
|
|
||||||
|
# 心跳检测
|
||||||
|
HEALTHCHECK --interval=10s --timeout=3s --start-period=3s --retries=3 \
|
||||||
|
CMD mysqladmin ping -h localhost -u root --password=${MYSQL_ROOT_PASSWORD} || exit 1
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ set -e
|
|||||||
# DockerContext: orion-visor
|
# DockerContext: orion-visor
|
||||||
|
|
||||||
# 版本号
|
# 版本号
|
||||||
version=2.4.2
|
version=2.5.2
|
||||||
# 是否构建 service
|
# 是否构建 service
|
||||||
export build_service=false
|
export build_service=false
|
||||||
# 是否构建 ui
|
# 是否构建 ui
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM --platform=$BUILDPLATFORM redis:6.0.16-alpine
|
FROM --platform=$TARGETPLATFORM redis:6.0.16-alpine
|
||||||
|
|
||||||
WORKDIR /data
|
WORKDIR /data
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM --platform=$BUILDPLATFORM openjdk:8-jdk-alpine
|
FROM --platform=$TARGETPLATFORM openjdk:8-jdk-alpine
|
||||||
|
|
||||||
USER root
|
USER root
|
||||||
|
|
||||||
@@ -17,8 +17,19 @@ RUN \
|
|||||||
ln -sf /usr/share/zoneinfo/${TZ} /etc/localtime && \
|
ln -sf /usr/share/zoneinfo/${TZ} /etc/localtime && \
|
||||||
echo "${TZ}" > /etc/timezone
|
echo "${TZ}" > /etc/timezone
|
||||||
|
|
||||||
|
# 复制启动脚本
|
||||||
|
COPY ./service/entrypoint.sh /app/entrypoint.sh
|
||||||
|
RUN chmod +x /app/entrypoint.sh
|
||||||
|
|
||||||
# 复制 jar 包
|
# 复制 jar 包
|
||||||
COPY ./service/orion-visor-launch.jar /app/app.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"]
|
||||||
|
|||||||
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,4 +1,4 @@
|
|||||||
FROM --platform=$BUILDPLATFORM nginx:alpine
|
FROM --platform=$TARGETPLATFORM nginx:alpine
|
||||||
|
|
||||||
# 系统时区
|
# 系统时区
|
||||||
ARG TZ=Asia/Shanghai
|
ARG TZ=Asia/Shanghai
|
||||||
@@ -11,13 +11,20 @@ RUN \
|
|||||||
ln -sf /usr/share/zoneinfo/${TZ} /etc/localtime && \
|
ln -sf /usr/share/zoneinfo/${TZ} /etc/localtime && \
|
||||||
echo "${TZ}" > /etc/timezone && \
|
echo "${TZ}" > /etc/timezone && \
|
||||||
rm -rf /var/cache/apk/* && \
|
rm -rf /var/cache/apk/* && \
|
||||||
|
rm -rf /etc/nginx/nginx.conf && \
|
||||||
rm -rf /etc/nginx/conf.d/*
|
rm -rf /etc/nginx/conf.d/*
|
||||||
|
|
||||||
# 复制包
|
# 复制前端静态文件
|
||||||
COPY ./ui/dist /usr/share/nginx/html
|
COPY ./ui/dist /usr/share/nginx/html
|
||||||
|
|
||||||
# 复制配置
|
# 复制配置
|
||||||
COPY ./ui/nginx.conf /etc/nginx/conf.d
|
COPY ./ui/nginx.conf /etc/nginx
|
||||||
|
COPY ./ui/service.conf /etc/nginx/conf.d
|
||||||
|
|
||||||
|
# 复制启动脚本
|
||||||
|
COPY ./ui/entrypoint.sh /entrypoint.sh
|
||||||
|
RUN chmod +x /entrypoint.sh
|
||||||
|
|
||||||
# 启动
|
# 启动
|
||||||
|
ENTRYPOINT ["/entrypoint.sh"]
|
||||||
CMD ["nginx", "-g", "daemon off;"]
|
CMD ["nginx", "-g", "daemon off;"]
|
||||||
11
docker/ui/entrypoint.sh
Normal file
11
docker/ui/entrypoint.sh
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# 设置环境变量
|
||||||
|
NGINX_SERVICE_HOST="${NGINX_SERVICE_HOST:-service}"
|
||||||
|
NGINX_SERVICE_PORT="${NGINX_SERVICE_PORT:-9200}"
|
||||||
|
|
||||||
|
# 替换环境变量
|
||||||
|
sed -i "s|\${NGINX_SERVICE_HOST}|${NGINX_SERVICE_HOST}|g" /etc/nginx/conf.d/service.conf
|
||||||
|
sed -i "s|\${NGINX_SERVICE_PORT}|${NGINX_SERVICE_PORT}|g" /etc/nginx/conf.d/service.conf
|
||||||
|
|
||||||
|
exec "$@"
|
||||||
@@ -1,56 +1,30 @@
|
|||||||
server {
|
user nginx;
|
||||||
listen 80;
|
worker_processes auto;
|
||||||
server_name localhost;
|
|
||||||
client_max_body_size 1024m;
|
|
||||||
|
|
||||||
# 是否启动 gzip 压缩
|
error_log /var/log/nginx/error.log notice;
|
||||||
gzip on;
|
pid /run/nginx.pid;
|
||||||
# 需要压缩的常见静态资源
|
|
||||||
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
|
|
||||||
# 如果文件大于 1k 就启动压缩
|
|
||||||
gzip_min_length 1k;
|
|
||||||
# 缓冲区
|
|
||||||
gzip_buffers 4 16k;
|
|
||||||
# 压缩的等级
|
|
||||||
gzip_comp_level 2;
|
|
||||||
# access_log /var/log/nginx/host.access.log main;
|
|
||||||
|
|
||||||
location / {
|
|
||||||
root /usr/share/nginx/html;
|
|
||||||
index index.html index.htm;
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
# web history 模式 404
|
|
||||||
try_files $uri $uri/ /index.html;
|
|
||||||
}
|
|
||||||
|
|
||||||
location /orion-visor/api {
|
|
||||||
proxy_pass http://service:9200/orion-visor/api;
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
}
|
|
||||||
|
|
||||||
location /orion-visor/keep-alive {
|
|
||||||
proxy_pass http://service:9200/orion-visor/keep-alive;
|
|
||||||
proxy_http_version 1.1;
|
|
||||||
proxy_set_header Upgrade $http_upgrade;
|
|
||||||
proxy_set_header Connection "upgrade";
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
proxy_read_timeout 3600s;
|
|
||||||
proxy_send_timeout 3600s;
|
|
||||||
}
|
|
||||||
|
|
||||||
error_page 500 502 503 504 /50x.html;
|
|
||||||
location = /50x.html {
|
|
||||||
root /usr/share/nginx/html;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
events {
|
||||||
|
worker_connections 1024;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
http {
|
||||||
|
include /etc/nginx/mime.types;
|
||||||
|
default_type application/octet-stream;
|
||||||
|
server_tokens off;
|
||||||
|
|
||||||
|
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||||
|
'$status $body_bytes_sent "$http_referer" '
|
||||||
|
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||||
|
|
||||||
|
access_log /var/log/nginx/access.log main;
|
||||||
|
|
||||||
|
sendfile on;
|
||||||
|
#tcp_nopush on;
|
||||||
|
|
||||||
|
keepalive_timeout 65;
|
||||||
|
|
||||||
|
#gzip on;
|
||||||
|
|
||||||
|
include /etc/nginx/conf.d/*.conf;
|
||||||
|
}
|
||||||
|
|||||||
56
docker/ui/service.conf
Normal file
56
docker/ui/service.conf
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name localhost;
|
||||||
|
client_max_body_size 1024m;
|
||||||
|
|
||||||
|
# 是否启动 gzip 压缩
|
||||||
|
gzip on;
|
||||||
|
# 需要压缩的常见静态资源
|
||||||
|
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
|
||||||
|
# 如果文件大于 1k 就启动压缩
|
||||||
|
gzip_min_length 1k;
|
||||||
|
# 缓冲区
|
||||||
|
gzip_buffers 4 16k;
|
||||||
|
# 压缩的等级
|
||||||
|
gzip_comp_level 2;
|
||||||
|
# access_log /var/log/nginx/host.access.log main;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html index.htm;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
# web history 模式 404
|
||||||
|
try_files $uri $uri/ /index.html;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /orion-visor/api {
|
||||||
|
proxy_pass http://${NGINX_SERVICE_HOST}:${NGINX_SERVICE_PORT}/orion-visor/api;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /orion-visor/keep-alive {
|
||||||
|
proxy_pass http://${NGINX_SERVICE_HOST}:${NGINX_SERVICE_PORT}/orion-visor/keep-alive;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection "upgrade";
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
proxy_read_timeout 3600s;
|
||||||
|
proxy_send_timeout 3600s;
|
||||||
|
}
|
||||||
|
|
||||||
|
error_page 500 502 503 504 /50x.html;
|
||||||
|
location = /50x.html {
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
## 文档已迁移至网页端
|
## 文档已迁移至在线文档
|
||||||
|
|
||||||
* https://visor.dromara.org
|
* https://visor.dromara.org
|
||||||
* https://visor.dromara.org.cn
|
* https://visor.dromara.org.cn
|
||||||
|
|||||||
BIN
docs/assets/screenshot/monitor-alarm.png
Normal file
BIN
docs/assets/screenshot/monitor-alarm.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 MiB |
BIN
docs/assets/screenshot/monitor-chart.png
Normal file
BIN
docs/assets/screenshot/monitor-chart.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 |
BIN
docs/assets/screenshot/monitor-override.png
Normal file
BIN
docs/assets/screenshot/monitor-override.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 201 KiB |
@@ -1,5 +1,9 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
# 清空
|
||||||
git clean -df
|
git clean -df
|
||||||
|
# 切换到 HEAD
|
||||||
git reset --hard HEAD
|
git reset --hard HEAD
|
||||||
|
# 拉取远程
|
||||||
git pull
|
git pull
|
||||||
|
# 查看日志
|
||||||
git log -n 1
|
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.2";
|
String VERSION = "2.5.2";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 同 ${spring.application.name}
|
* 同 ${spring.application.name}
|
||||||
|
|||||||
@@ -53,21 +53,25 @@ 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 + 2610;
|
||||||
|
|
||||||
int FRAMEWORK_MONITOR = Integer.MIN_VALUE + 2700;
|
int FRAMEWORK_JOB_ASYNC = Integer.MIN_VALUE + 2620;
|
||||||
|
|
||||||
int FRAMEWORK_BIZ_OPERATOR_LOG = Integer.MIN_VALUE + 2800;
|
int FRAMEWORK_BIZ_PUSH = Integer.MIN_VALUE + 2700;
|
||||||
|
|
||||||
|
int FRAMEWORK_BIZ_OPERATOR_LOG = Integer.MIN_VALUE + 7000;
|
||||||
|
|
||||||
|
int FRAMEWORK_MONITOR = Integer.MIN_VALUE + 9000;
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,4 +33,8 @@ 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, "未找到该资源"),
|
||||||
|
|||||||
@@ -100,9 +100,15 @@ public interface ErrorMessage {
|
|||||||
|
|
||||||
String GROUP_ABSENT = "分组不存在";
|
String GROUP_ABSENT = "分组不存在";
|
||||||
|
|
||||||
|
String METRICS_ABSENT = "指标不存在";
|
||||||
|
|
||||||
|
String RULE_ABSENT = "规则不存在";
|
||||||
|
|
||||||
|
String ALARM_POLICY_ABSENT = "告警策略不存在";
|
||||||
|
|
||||||
String HOST_TYPE_ERROR = "主机类型错误";
|
String HOST_TYPE_ERROR = "主机类型错误";
|
||||||
|
|
||||||
String HOST_NOT_ENABLED = "主机未启用";
|
String HOST_NOT_ENABLED = "{} 主机未启用";
|
||||||
|
|
||||||
String CONFIG_NOT_ENABLED = "配置未启用";
|
String CONFIG_NOT_ENABLED = "配置未启用";
|
||||||
|
|
||||||
@@ -132,6 +138,8 @@ public interface ErrorMessage {
|
|||||||
|
|
||||||
String CURRENT_USER_UNSUPPORTED_OPT = "当前" + USER_UNSUPPORTED_OPT;
|
String CURRENT_USER_UNSUPPORTED_OPT = "当前" + USER_UNSUPPORTED_OPT;
|
||||||
|
|
||||||
|
String PUSH_USER_NOT_EMPTY = "推送用户不能为空";
|
||||||
|
|
||||||
String PATH_NOT_NORMALIZE = "路径不合法";
|
String PATH_NOT_NORMALIZE = "路径不合法";
|
||||||
|
|
||||||
String OPERATE_ERROR = "操作失败";
|
String OPERATE_ERROR = "操作失败";
|
||||||
@@ -140,12 +148,16 @@ public interface ErrorMessage {
|
|||||||
|
|
||||||
String DECRYPT_ERROR = "数据解密失败";
|
String DECRYPT_ERROR = "数据解密失败";
|
||||||
|
|
||||||
|
String GET_REQUEST_URL_ERROR = "获取请求路径失败";
|
||||||
|
|
||||||
String UNKNOWN_TYPE = "未知类型";
|
String UNKNOWN_TYPE = "未知类型";
|
||||||
|
|
||||||
String ERROR_TYPE = "错误的类型";
|
String ERROR_TYPE = "错误的类型";
|
||||||
|
|
||||||
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 +170,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 +196,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 +225,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 +254,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 +275,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,62 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 推送用户
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2025/9/18 21:46
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Schema(name = "PushUser", description = "推送用户")
|
||||||
|
public class PushUser implements Serializable {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Schema(description = "用户id")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Schema(description = "用户名")
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
@Schema(description = "花名")
|
||||||
|
private String nickname;
|
||||||
|
|
||||||
|
@Schema(description = "手机号")
|
||||||
|
private String mobile;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
|||||||
@@ -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 数据加密工具类
|
||||||
|
|||||||
@@ -37,13 +37,13 @@ import java.util.Set;
|
|||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 验证器
|
* 断言
|
||||||
*
|
*
|
||||||
* @author Jiahang Li
|
* @author Jiahang Li
|
||||||
* @version 1.0.0
|
* @version 1.0.0
|
||||||
* @since 2023/7/18 11:23
|
* @since 2023/7/18 11:23
|
||||||
*/
|
*/
|
||||||
public class Valid extends cn.orionsec.kit.lang.utils.Valid {
|
public class Assert extends cn.orionsec.kit.lang.utils.Assert {
|
||||||
|
|
||||||
private static final Validator validator = SpringHolder.getBean(Validator.class);
|
private static final Validator validator = SpringHolder.getBean(Validator.class);
|
||||||
|
|
||||||
@@ -155,8 +155,8 @@ public class Valid extends cn.orionsec.kit.lang.utils.Valid {
|
|||||||
* @param path path
|
* @param path path
|
||||||
*/
|
*/
|
||||||
public static String checkNormalize(String path) {
|
public static String checkNormalize(String path) {
|
||||||
Valid.notBlank(path);
|
Assert.notBlank(path);
|
||||||
Valid.isTrue(Files1.isNormalize(path), ErrorMessage.PATH_NOT_NORMALIZE);
|
Assert.isTrue(Files1.isNormalize(path), ErrorMessage.PATH_NOT_NORMALIZE);
|
||||||
return Files1.getPath(path);
|
return Files1.getPath(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -168,8 +168,8 @@ public class Valid extends cn.orionsec.kit.lang.utils.Valid {
|
|||||||
* @return file
|
* @return file
|
||||||
*/
|
*/
|
||||||
public static String checkSuffix(String file, String suffix) {
|
public static String checkSuffix(String file, String suffix) {
|
||||||
Valid.notBlank(file);
|
Assert.notBlank(file);
|
||||||
Valid.isTrue(file.toLowerCase().endsWith(Const.DOT + suffix), ErrorMessage.PLEASE_SELECT_SUFFIX_FILE, suffix);
|
Assert.isTrue(file.toLowerCase().endsWith(Const.DOT + suffix), ErrorMessage.PLEASE_SELECT_SUFFIX_FILE, suffix);
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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.2</revision>
|
<revision>2.5.2</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.2</orion.kit.version>
|
<orion.kit.version>2.0.4</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,16 @@
|
|||||||
<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>
|
||||||
|
<groupId>org.dromara.visor</groupId>
|
||||||
|
<artifactId>orion-visor-spring-boot-starter-biz-push</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 +287,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;
|
||||||
|
|||||||
@@ -23,8 +23,11 @@
|
|||||||
package org.dromara.visor.framework.biz.operator.log.core.factory;
|
package org.dromara.visor.framework.biz.operator.log.core.factory;
|
||||||
|
|
||||||
import cn.orionsec.kit.lang.utils.Arrays1;
|
import cn.orionsec.kit.lang.utils.Arrays1;
|
||||||
|
import cn.orionsec.kit.spring.SpringHolder;
|
||||||
import org.dromara.visor.framework.biz.operator.log.core.annotation.Module;
|
import org.dromara.visor.framework.biz.operator.log.core.annotation.Module;
|
||||||
import org.dromara.visor.framework.biz.operator.log.core.model.OperatorType;
|
import org.dromara.visor.framework.biz.operator.log.core.model.OperatorType;
|
||||||
|
import org.springframework.beans.factory.BeanNameAware;
|
||||||
|
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
|
|
||||||
@@ -35,7 +38,14 @@ import javax.annotation.PostConstruct;
|
|||||||
* @version 1.0.0
|
* @version 1.0.0
|
||||||
* @since 2023/10/13 17:45
|
* @since 2023/10/13 17:45
|
||||||
*/
|
*/
|
||||||
public abstract class InitializingOperatorTypes implements OperatorTypeDefinition {
|
public abstract class InitializingOperatorTypes implements OperatorTypeDefinition, BeanNameAware {
|
||||||
|
|
||||||
|
private String beanName;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBeanName(String name) {
|
||||||
|
this.beanName = name;
|
||||||
|
}
|
||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void init() {
|
public void init() {
|
||||||
@@ -55,6 +65,8 @@ public abstract class InitializingOperatorTypes implements OperatorTypeDefinitio
|
|||||||
type.setModule(module);
|
type.setModule(module);
|
||||||
OperatorTypeHolder.set(type);
|
OperatorTypeHolder.set(type);
|
||||||
}
|
}
|
||||||
|
// 自动销毁
|
||||||
|
((BeanDefinitionRegistry) SpringHolder.getBeanFactory()).removeBeanDefinition(beanName);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
<?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-biz-push</artifactId>
|
||||||
|
<name>${project.artifactId}</name>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<description>项目业务推送包</description>
|
||||||
|
<url>https://github.com/dromara/orion-visor</url>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.dromara.visor</groupId>
|
||||||
|
<artifactId>orion-visor-common</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- web -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,121 @@
|
|||||||
|
/*
|
||||||
|
* 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.biz.push.configuration;
|
||||||
|
|
||||||
|
import cn.orionsec.kit.lang.function.Functions;
|
||||||
|
import org.dromara.visor.common.constant.AutoConfigureOrderConst;
|
||||||
|
import org.dromara.visor.framework.biz.push.core.enums.PushChannelEnum;
|
||||||
|
import org.dromara.visor.framework.biz.push.core.framework.service.PushTemplateFrameworkService;
|
||||||
|
import org.dromara.visor.framework.biz.push.core.framework.service.PushTemplateFrameworkServiceDelegate;
|
||||||
|
import org.dromara.visor.framework.biz.push.core.framework.service.WebsiteMessageFrameworkService;
|
||||||
|
import org.dromara.visor.framework.biz.push.core.listener.PushMessageEventListener;
|
||||||
|
import org.dromara.visor.framework.biz.push.core.message.PushMessage;
|
||||||
|
import org.dromara.visor.framework.biz.push.core.service.*;
|
||||||
|
import org.dromara.visor.framework.biz.push.core.utils.MessageChannelUtils;
|
||||||
|
import org.dromara.visor.framework.biz.push.core.utils.PushUtils;
|
||||||
|
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||||
|
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Primary;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 推送自动配置类
|
||||||
|
*
|
||||||
|
* @author Shihao Lv
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2025/9/17 23:04
|
||||||
|
*/
|
||||||
|
@AutoConfiguration
|
||||||
|
@AutoConfigureOrder(AutoConfigureOrderConst.FRAMEWORK_BIZ_PUSH)
|
||||||
|
public class OrionPushAutoConfiguration {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return 钉钉推送服务
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public DingPushService dingPushService() {
|
||||||
|
return new DingPushService();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return 飞书推送服务
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public FeiShuPushService feiShuPushService() {
|
||||||
|
return new FeiShuPushService();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return 企业微信推送服务
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public WeComPushService weComPushService() {
|
||||||
|
return new WeComPushService();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param websiteMessageFrameworkService websiteMessageFrameworkService
|
||||||
|
* @return 站内信推送服务
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public WebsitePushService websitePushService(WebsiteMessageFrameworkService websiteMessageFrameworkService) {
|
||||||
|
return new WebsitePushService(websiteMessageFrameworkService);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param impl impl
|
||||||
|
* @return 推送模板服务
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
@Primary
|
||||||
|
@ConditionalOnBean(PushTemplateFrameworkService.class)
|
||||||
|
public PushTemplateFrameworkService pushTemplateFrameworkService(PushTemplateFrameworkService impl) {
|
||||||
|
PushTemplateFrameworkServiceDelegate delegate = new PushTemplateFrameworkServiceDelegate(impl);
|
||||||
|
// 设置到工具类
|
||||||
|
PushUtils.setPushTemplateFrameworkService(delegate);
|
||||||
|
return delegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param pushServices 推送服务
|
||||||
|
* @return 消息推送事件监听器
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public PushMessageEventListener pushMessageEventListener(List<IPushService<? extends PushMessage>> pushServices) {
|
||||||
|
// 服务列表
|
||||||
|
Map<PushChannelEnum, IPushService<? extends PushMessage>> serviceMap = pushServices.stream()
|
||||||
|
.collect(Collectors.toMap(
|
||||||
|
MessageChannelUtils::getPushChannel,
|
||||||
|
Function.identity(),
|
||||||
|
Functions.right()));
|
||||||
|
// 创建监听器
|
||||||
|
return new PushMessageEventListener(serviceMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* 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.biz.push.core.annotation;
|
||||||
|
|
||||||
|
import org.dromara.visor.framework.biz.push.core.enums.PushChannelEnum;
|
||||||
|
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息渠道
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2025/9/18 21:58
|
||||||
|
*/
|
||||||
|
@Target({ElementType.TYPE})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Documented
|
||||||
|
public @interface MessageChannel {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息渠道
|
||||||
|
*
|
||||||
|
* @return channel
|
||||||
|
*/
|
||||||
|
PushChannelEnum value();
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
/*
|
||||||
|
* 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.biz.push.core.entity;
|
||||||
|
|
||||||
|
import cn.orionsec.kit.lang.able.IJsonObject;
|
||||||
|
import com.alibaba.fastjson.annotation.JSONField;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 钉钉请求体
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2025/9/18 18:41
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class DingRequestBody implements Serializable, IJsonObject {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息类型
|
||||||
|
*/
|
||||||
|
@JSONField(name = "msgtype")
|
||||||
|
private String msgType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* markdown 内容
|
||||||
|
*/
|
||||||
|
private DingRequestBody.MarkdownPayload markdown;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* at 配置
|
||||||
|
*/
|
||||||
|
private DingRequestBody.AtPayload at;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public static class MarkdownPayload implements Serializable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 标题
|
||||||
|
*/
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 内容
|
||||||
|
*/
|
||||||
|
private String text;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public static class AtPayload implements Serializable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 被 at 的手机号
|
||||||
|
*/
|
||||||
|
private List<String> atMobiles;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 被 at 的 userId
|
||||||
|
*/
|
||||||
|
private List<String> atUserIds;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否 at 所有人
|
||||||
|
*/
|
||||||
|
private Boolean isAtAll;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* 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.biz.push.core.entity;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.annotation.JSONField;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 钉钉响应体
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2025/9/18 18:41
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class DingResponseBody implements Serializable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 错误码值
|
||||||
|
*/
|
||||||
|
@JSONField(name = "errcode")
|
||||||
|
private Integer errCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 错误码描述
|
||||||
|
*/
|
||||||
|
@JSONField(name = "errmsg")
|
||||||
|
private String errMsg;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
* 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.biz.push.core.entity;
|
||||||
|
|
||||||
|
import cn.orionsec.kit.lang.able.IJsonObject;
|
||||||
|
import com.alibaba.fastjson.annotation.JSONField;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 飞书请求体
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2025/9/18 18:41
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class FeiShuRequestBody implements Serializable, IJsonObject {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 时间戳
|
||||||
|
*/
|
||||||
|
private Long timestamp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 签名
|
||||||
|
*/
|
||||||
|
private String sign;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息类型
|
||||||
|
*/
|
||||||
|
@JSONField(name = "msg_type")
|
||||||
|
private String msgType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* text 内容
|
||||||
|
*/
|
||||||
|
private TextPayload content;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public static class TextPayload implements Serializable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 内容
|
||||||
|
*/
|
||||||
|
private String text;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -20,36 +20,36 @@
|
|||||||
* 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.framework.biz.push.core.entity;
|
||||||
|
|
||||||
import java.util.function.Supplier;
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 分布式锁
|
* 飞书响应体
|
||||||
*
|
*
|
||||||
* @author Jiahang Li
|
* @author Jiahang Li
|
||||||
* @version 1.0.0
|
* @version 1.0.0
|
||||||
* @since 2024/5/16 12:24
|
* @since 2025/9/18 18:41
|
||||||
*/
|
*/
|
||||||
public interface Locker {
|
@Data
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class FeiShuResponseBody implements Serializable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 尝试获取锁
|
* code
|
||||||
*
|
|
||||||
* @param key key
|
|
||||||
* @param run run
|
|
||||||
* @return 是否获取到锁
|
|
||||||
*/
|
*/
|
||||||
boolean tryLock(String key, Runnable run);
|
private Integer code;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 尝试获取锁
|
* msg
|
||||||
*
|
|
||||||
* @param key key
|
|
||||||
* @param call call
|
|
||||||
* @param <T> T
|
|
||||||
* @return 执行结果
|
|
||||||
*/
|
*/
|
||||||
<T> T tryLock(String key, Supplier<T> call);
|
private String msg;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* 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.biz.push.core.entity;
|
||||||
|
|
||||||
|
import cn.orionsec.kit.lang.able.IJsonObject;
|
||||||
|
import com.alibaba.fastjson.annotation.JSONField;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 企业微信请求体
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2025/9/18 18:41
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class WeComRequestBody implements Serializable, IJsonObject {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息类型
|
||||||
|
*/
|
||||||
|
@JSONField(name = "msgtype")
|
||||||
|
private String msgType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* markdown 内容
|
||||||
|
*/
|
||||||
|
private MarkdownPayload markdown;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 被 at 的 userId
|
||||||
|
*/
|
||||||
|
@JSONField(name = "mentioned_list")
|
||||||
|
private List<String> mentionedList;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public static class MarkdownPayload implements Serializable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 内容
|
||||||
|
*/
|
||||||
|
private String content;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* 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.biz.push.core.entity;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.annotation.JSONField;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 企业微信响应体
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2025/9/18 18:41
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class WeComResponseBody implements Serializable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 错误码值
|
||||||
|
*/
|
||||||
|
@JSONField(name = "errcode")
|
||||||
|
private Integer errCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 错误码描述
|
||||||
|
*/
|
||||||
|
@JSONField(name = "errmsg")
|
||||||
|
private String errMsg;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
* 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.biz.push.core.enums;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
import org.dromara.visor.framework.biz.push.core.message.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通知模板类型枚举
|
||||||
|
*
|
||||||
|
* @author Shihao Lv
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2025/9/15 23:20
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public enum PushChannelEnum {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 站内信
|
||||||
|
*/
|
||||||
|
WEBSITE(WebsiteMessage.class),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 钉钉
|
||||||
|
*/
|
||||||
|
DING(DingPushMessage.class),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 飞书
|
||||||
|
*/
|
||||||
|
FEI_SHU(FeiShuPushMessage.class),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 企业微信
|
||||||
|
*/
|
||||||
|
WE_COM(WeComPushMessage.class),
|
||||||
|
|
||||||
|
;
|
||||||
|
|
||||||
|
public final Class<?> messageClass;
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <T extends PushMessage> T createMessage(String config) {
|
||||||
|
try {
|
||||||
|
return (T) JSON.parseObject(config, messageClass);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据渠道名称获取枚举
|
||||||
|
*
|
||||||
|
* @param channel 渠道名称
|
||||||
|
* @return 枚举
|
||||||
|
*/
|
||||||
|
public static PushChannelEnum of(String channel) {
|
||||||
|
for (PushChannelEnum value : values()) {
|
||||||
|
if (value.name().equalsIgnoreCase(channel)) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return WEBSITE;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* 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.biz.push.core.event;
|
||||||
|
|
||||||
|
import org.dromara.visor.framework.biz.push.core.message.PushMessage;
|
||||||
|
import org.springframework.context.ApplicationEvent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息推送事件
|
||||||
|
*
|
||||||
|
* @author Shihao Lv
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2025/1/15
|
||||||
|
*/
|
||||||
|
public class PushMessageEvent extends ApplicationEvent {
|
||||||
|
|
||||||
|
public PushMessageEvent(PushMessage message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* 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.biz.push.core.framework.service;
|
||||||
|
|
||||||
|
import org.dromara.visor.framework.biz.push.core.message.PushMessage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 推送消息模板框架服务
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2025/9/21 16:26
|
||||||
|
*/
|
||||||
|
public interface PushTemplateFrameworkService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据 templateId 获取消息
|
||||||
|
*
|
||||||
|
* @param templateId templateId
|
||||||
|
* @return message
|
||||||
|
*/
|
||||||
|
PushMessage getPushMessageByTemplateId(Long templateId);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* 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.biz.push.core.framework.service;
|
||||||
|
|
||||||
|
import org.dromara.visor.framework.biz.push.core.message.PushMessage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 推送消息模板框架服务委托类
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2025/9/21 16:26
|
||||||
|
*/
|
||||||
|
public class PushTemplateFrameworkServiceDelegate implements PushTemplateFrameworkService {
|
||||||
|
|
||||||
|
private final PushTemplateFrameworkService delegate;
|
||||||
|
|
||||||
|
public PushTemplateFrameworkServiceDelegate(PushTemplateFrameworkService delegate) {
|
||||||
|
this.delegate = delegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PushMessage getPushMessageByTemplateId(Long templateId) {
|
||||||
|
return delegate.getPushMessageByTemplateId(templateId);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* 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.biz.push.core.framework.service;
|
||||||
|
|
||||||
|
import org.dromara.visor.framework.biz.push.core.message.WebsiteMessage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送站内信框架服务
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2025/9/18 22:09
|
||||||
|
*/
|
||||||
|
public interface WebsiteMessageFrameworkService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送站内信
|
||||||
|
*
|
||||||
|
* @param message message
|
||||||
|
*/
|
||||||
|
void push(WebsiteMessage message);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* 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.biz.push.core.listener;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.dromara.visor.framework.biz.push.core.enums.PushChannelEnum;
|
||||||
|
import org.dromara.visor.framework.biz.push.core.event.PushMessageEvent;
|
||||||
|
import org.dromara.visor.framework.biz.push.core.message.PushMessage;
|
||||||
|
import org.dromara.visor.framework.biz.push.core.service.IPushService;
|
||||||
|
import org.springframework.context.ApplicationListener;
|
||||||
|
import org.springframework.scheduling.annotation.Async;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息推送事件监听器
|
||||||
|
*
|
||||||
|
* @author Shihao Lv
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2025/1/15
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class PushMessageEventListener implements ApplicationListener<PushMessageEvent> {
|
||||||
|
|
||||||
|
private final Map<PushChannelEnum, IPushService<? extends PushMessage>> pushServiceMap;
|
||||||
|
|
||||||
|
public PushMessageEventListener(Map<PushChannelEnum, IPushService<? extends PushMessage>> pushServiceMap) {
|
||||||
|
this.pushServiceMap = pushServiceMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME
|
||||||
|
@Async("asyncExecutor")
|
||||||
|
@Override
|
||||||
|
public void onApplicationEvent(PushMessageEvent event) {
|
||||||
|
try {
|
||||||
|
// 获取消息
|
||||||
|
PushMessage message = (PushMessage) event.getSource();
|
||||||
|
// 发送消息
|
||||||
|
this.getPushService(message).push(message);
|
||||||
|
log.info("PushMessageEventListener push success");
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("PushMessageEventListener push error", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private <T extends PushMessage> IPushService<T> getPushService(PushMessage message) {
|
||||||
|
return (IPushService<T>) pushServiceMap.get(message.getChannel());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* 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.biz.push.core.message;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.SuperBuilder;
|
||||||
|
import org.dromara.visor.common.entity.PushUser;
|
||||||
|
|
||||||
|
import javax.validation.Valid;
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 推送消息基类
|
||||||
|
*
|
||||||
|
* @author Shihao Lv
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2025/9/15 23:28
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@SuperBuilder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Schema(name = "BasePushMessage", description = "推送消息基类")
|
||||||
|
public abstract class BasePushMessage implements PushMessage, Serializable {
|
||||||
|
|
||||||
|
@NotBlank
|
||||||
|
@Schema(description = "消息模板")
|
||||||
|
private String template;
|
||||||
|
|
||||||
|
@Schema(description = "消息参数")
|
||||||
|
private Map<String, Object> params;
|
||||||
|
|
||||||
|
@Valid
|
||||||
|
@Schema(description = "推送用户")
|
||||||
|
private List<PushUser> pushUsers;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* 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.biz.push.core.message;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.SuperBuilder;
|
||||||
|
import org.dromara.visor.framework.biz.push.core.enums.PushChannelEnum;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 钉钉推送消息
|
||||||
|
*
|
||||||
|
* @author Shihao Lv
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2025/9/15 23:29
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@SuperBuilder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Schema(name = "DingPushMessage", description = "钉钉推送消息")
|
||||||
|
public class DingPushMessage extends BasePushMessage {
|
||||||
|
|
||||||
|
@NotBlank
|
||||||
|
@Schema(description = "webhook")
|
||||||
|
private String webhook;
|
||||||
|
|
||||||
|
@Schema(description = "密钥")
|
||||||
|
private String secret;
|
||||||
|
|
||||||
|
@NotBlank
|
||||||
|
@Schema(description = "推送标题")
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PushChannelEnum getChannel() {
|
||||||
|
return PushChannelEnum.DING;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* 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.biz.push.core.message;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.SuperBuilder;
|
||||||
|
import org.dromara.visor.framework.biz.push.core.enums.PushChannelEnum;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 飞书推送消息
|
||||||
|
*
|
||||||
|
* @author Shihao Lv
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2025/9/16 00:26
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@SuperBuilder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Schema(name = "FeiShuPushMessage", description = "飞书推送消息")
|
||||||
|
public class FeiShuPushMessage extends BasePushMessage {
|
||||||
|
|
||||||
|
@NotBlank
|
||||||
|
@Schema(description = "webhook")
|
||||||
|
private String webhook;
|
||||||
|
|
||||||
|
@Schema(description = "密钥")
|
||||||
|
private String secret;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PushChannelEnum getChannel() {
|
||||||
|
return PushChannelEnum.FEI_SHU;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* 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.biz.push.core.message;
|
||||||
|
|
||||||
|
import org.dromara.visor.common.entity.PushUser;
|
||||||
|
import org.dromara.visor.framework.biz.push.core.enums.PushChannelEnum;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 推送消息接口
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2025/9/18 18:42
|
||||||
|
*/
|
||||||
|
public interface PushMessage extends Serializable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取模板
|
||||||
|
*
|
||||||
|
* @return 模板
|
||||||
|
*/
|
||||||
|
String getTemplate();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置模板
|
||||||
|
*
|
||||||
|
* @param template template
|
||||||
|
*/
|
||||||
|
void setTemplate(String template);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取参数
|
||||||
|
*
|
||||||
|
* @return 参数
|
||||||
|
*/
|
||||||
|
Map<String, Object> getParams();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置参数
|
||||||
|
*
|
||||||
|
* @param params params
|
||||||
|
*/
|
||||||
|
void setParams(Map<String, Object> params);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取推送用户
|
||||||
|
*
|
||||||
|
* @return 推送用户
|
||||||
|
*/
|
||||||
|
List<PushUser> getPushUsers();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置推送用户列表
|
||||||
|
*
|
||||||
|
* @param pushUsers pushUsers
|
||||||
|
*/
|
||||||
|
void setPushUsers(List<PushUser> pushUsers);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取推送渠道
|
||||||
|
*
|
||||||
|
* @return 推送渠道
|
||||||
|
*/
|
||||||
|
PushChannelEnum getChannel();
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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.biz.push.core.message;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.SuperBuilder;
|
||||||
|
import org.dromara.visor.framework.biz.push.core.enums.PushChannelEnum;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 企业微信推送消息
|
||||||
|
*
|
||||||
|
* @author Shihao Lv
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2025/9/15 23:30
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@SuperBuilder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Schema(name = "WeComPushMessage", description = "企业微信推送消息")
|
||||||
|
public class WeComPushMessage extends BasePushMessage {
|
||||||
|
|
||||||
|
@NotBlank
|
||||||
|
@Schema(description = "webhook")
|
||||||
|
private String webhook;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PushChannelEnum getChannel() {
|
||||||
|
return PushChannelEnum.WE_COM;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
* 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.biz.push.core.message;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.SuperBuilder;
|
||||||
|
import org.dromara.visor.framework.biz.push.core.enums.PushChannelEnum;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
import javax.validation.constraints.Size;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 站内信推送
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2025/9/18 19:56
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@SuperBuilder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Schema(name = "WebsiteMessage", description = "站内信消息")
|
||||||
|
public class WebsiteMessage extends BasePushMessage {
|
||||||
|
|
||||||
|
@NotBlank
|
||||||
|
@Size(max = 10)
|
||||||
|
@Schema(description = "消息分类")
|
||||||
|
private String messageClassify;
|
||||||
|
|
||||||
|
@NotBlank
|
||||||
|
@Size(max = 32)
|
||||||
|
@Schema(description = "消息类型")
|
||||||
|
private String messageType;
|
||||||
|
|
||||||
|
@Schema(description = "消息关联")
|
||||||
|
private String relKey;
|
||||||
|
|
||||||
|
@NotBlank
|
||||||
|
@Size(max = 128)
|
||||||
|
@Schema(description = "标题")
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PushChannelEnum getChannel() {
|
||||||
|
return PushChannelEnum.WEBSITE;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,126 @@
|
|||||||
|
/*
|
||||||
|
* 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.biz.push.core.service;
|
||||||
|
|
||||||
|
import cn.orionsec.kit.lang.utils.Strings;
|
||||||
|
import cn.orionsec.kit.lang.utils.collect.Lists;
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.dromara.visor.common.constant.Const;
|
||||||
|
import org.dromara.visor.common.entity.PushUser;
|
||||||
|
import org.dromara.visor.common.utils.Assert;
|
||||||
|
import org.dromara.visor.framework.biz.push.core.message.PushMessage;
|
||||||
|
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息推送抽象服务
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2025/9/18 18:51
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public abstract class BasePushService<Message extends PushMessage> implements IPushService<Message> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void push(Message message) {
|
||||||
|
try {
|
||||||
|
// 验证消息
|
||||||
|
this.validateMessage(message);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("BasePushService validateMessage message: {}", JSON.toJSONString(message), e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 请求路径
|
||||||
|
String url = this.buildRequestUrl(message);
|
||||||
|
// 构建请求体
|
||||||
|
String body = this.buildRequestBody(message);
|
||||||
|
// 发送请求
|
||||||
|
this.sendRequest(message, url, body);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证消息
|
||||||
|
*
|
||||||
|
* @param message message
|
||||||
|
*/
|
||||||
|
protected void validateMessage(Message message) {
|
||||||
|
// 验证消息
|
||||||
|
Assert.valid(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建请求 url
|
||||||
|
*
|
||||||
|
* @param message message
|
||||||
|
* @return url
|
||||||
|
*/
|
||||||
|
protected abstract String buildRequestUrl(Message message);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建请求体
|
||||||
|
*
|
||||||
|
* @param message message
|
||||||
|
* @return body
|
||||||
|
*/
|
||||||
|
protected abstract String buildRequestBody(Message message);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送请求
|
||||||
|
*
|
||||||
|
* @param message message
|
||||||
|
* @param url url
|
||||||
|
* @param body body
|
||||||
|
*/
|
||||||
|
protected abstract void sendRequest(Message message, String url, String body);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 追加 at 用户
|
||||||
|
*
|
||||||
|
* @param message message
|
||||||
|
* @param content content
|
||||||
|
* @return content
|
||||||
|
*/
|
||||||
|
protected String appendAtUsers(Message message, String content) {
|
||||||
|
if (Lists.isEmpty(message.getPushUsers())) {
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
return content + Const.LF + this.getAtUsers(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 @ 的用户
|
||||||
|
*
|
||||||
|
* @param message message
|
||||||
|
* @return users
|
||||||
|
*/
|
||||||
|
protected String getAtUsers(Message message) {
|
||||||
|
return Lists.stream(message.getPushUsers())
|
||||||
|
.map(PushUser::getNickname)
|
||||||
|
.filter(Strings::isNotBlank)
|
||||||
|
.map(s -> Const.AT + s)
|
||||||
|
.collect(Collectors.joining(Const.SPACE));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
/*
|
||||||
|
* 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.biz.push.core.service;
|
||||||
|
|
||||||
|
import cn.orionsec.kit.http.ok.OkRequests;
|
||||||
|
import cn.orionsec.kit.http.ok.OkResponse;
|
||||||
|
import cn.orionsec.kit.lang.constant.StandardContentType;
|
||||||
|
import cn.orionsec.kit.lang.utils.Assert;
|
||||||
|
import cn.orionsec.kit.lang.utils.Exceptions;
|
||||||
|
import cn.orionsec.kit.lang.utils.Strings;
|
||||||
|
import cn.orionsec.kit.lang.utils.codec.Base64s;
|
||||||
|
import cn.orionsec.kit.lang.utils.crypto.Signatures;
|
||||||
|
import cn.orionsec.kit.lang.utils.math.Hex;
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.dromara.visor.common.constant.ErrorMessage;
|
||||||
|
import org.dromara.visor.framework.biz.push.core.annotation.MessageChannel;
|
||||||
|
import org.dromara.visor.framework.biz.push.core.entity.DingRequestBody;
|
||||||
|
import org.dromara.visor.framework.biz.push.core.entity.DingResponseBody;
|
||||||
|
import org.dromara.visor.framework.biz.push.core.enums.PushChannelEnum;
|
||||||
|
import org.dromara.visor.framework.biz.push.core.message.DingPushMessage;
|
||||||
|
import org.dromara.visor.framework.biz.push.core.utils.MessageUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 钉钉推送服务类
|
||||||
|
* <p>
|
||||||
|
* <a href="https://open.dingtalk.com/document/dingstart/obtain-the-webhook-address-of-a-custom-robot">doc</a>
|
||||||
|
*
|
||||||
|
* @author Shihao Lv
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2025/9/17 23:13
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@MessageChannel(value = PushChannelEnum.DING)
|
||||||
|
public class DingPushService extends BasePushService<DingPushMessage> {
|
||||||
|
|
||||||
|
private static final String MARKDOWN = "markdown";
|
||||||
|
|
||||||
|
private static final Integer SUCCESS_CODE = 0;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String buildRequestUrl(DingPushMessage message) {
|
||||||
|
String secret = message.getSecret();
|
||||||
|
if (Strings.isBlank(secret)) {
|
||||||
|
return message.getWebhook();
|
||||||
|
}
|
||||||
|
// 加签
|
||||||
|
try {
|
||||||
|
long timestamp = System.currentTimeMillis();
|
||||||
|
String plainText = timestamp + "\n" + secret;
|
||||||
|
String hexSign = Signatures.hmacSha256(plainText, secret);
|
||||||
|
if (hexSign == null) {
|
||||||
|
log.error("DingPushService-sign error plain: {}", plainText);
|
||||||
|
throw Exceptions.argument(ErrorMessage.GET_REQUEST_URL_ERROR);
|
||||||
|
}
|
||||||
|
byte[] signData = Hex.hexToBytes(hexSign);
|
||||||
|
String sign = Base64s.encodeToString(signData);
|
||||||
|
// 实际请求地址
|
||||||
|
return message.getWebhook() + "×tamp=" + timestamp + "&sign=" + sign;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("DingPushService-buildRequestUrl error", e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String buildRequestBody(DingPushMessage message) {
|
||||||
|
// 格式化内容
|
||||||
|
String formattedContent = MessageUtils.format(message.getTemplate(), message.getParams());
|
||||||
|
String formattedTitle = MessageUtils.format(message.getTitle(), message.getParams());
|
||||||
|
// at 用户
|
||||||
|
formattedContent = this.appendAtUsers(message, formattedContent);
|
||||||
|
|
||||||
|
// 构建请求体
|
||||||
|
return DingRequestBody.builder()
|
||||||
|
.msgType(MARKDOWN)
|
||||||
|
.markdown(DingRequestBody.MarkdownPayload.builder()
|
||||||
|
.title(formattedTitle)
|
||||||
|
.text(formattedContent)
|
||||||
|
.build())
|
||||||
|
.build()
|
||||||
|
.toJsonString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void sendRequest(DingPushMessage message, String url, String body) {
|
||||||
|
// 发送请求
|
||||||
|
OkResponse response = OkRequests.post(url, StandardContentType.APPLICATION_JSON_UTF8, body);
|
||||||
|
DingResponseBody responseBody = JSON.parseObject(response.getBodyString(), DingResponseBody.class);
|
||||||
|
// 验证发送结果
|
||||||
|
Assert.eq(responseBody.getErrCode(), SUCCESS_CODE, responseBody.getErrMsg());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,118 @@
|
|||||||
|
/*
|
||||||
|
* 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.biz.push.core.service;
|
||||||
|
|
||||||
|
import cn.orionsec.kit.http.ok.OkRequests;
|
||||||
|
import cn.orionsec.kit.http.ok.OkResponse;
|
||||||
|
import cn.orionsec.kit.lang.constant.Const;
|
||||||
|
import cn.orionsec.kit.lang.constant.StandardContentType;
|
||||||
|
import cn.orionsec.kit.lang.utils.Strings;
|
||||||
|
import cn.orionsec.kit.lang.utils.codec.Base64s;
|
||||||
|
import cn.orionsec.kit.lang.utils.crypto.Signatures;
|
||||||
|
import cn.orionsec.kit.lang.utils.crypto.enums.SecretKeySpecMode;
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.dromara.visor.common.utils.Assert;
|
||||||
|
import org.dromara.visor.framework.biz.push.core.annotation.MessageChannel;
|
||||||
|
import org.dromara.visor.framework.biz.push.core.entity.FeiShuRequestBody;
|
||||||
|
import org.dromara.visor.framework.biz.push.core.entity.FeiShuResponseBody;
|
||||||
|
import org.dromara.visor.framework.biz.push.core.enums.PushChannelEnum;
|
||||||
|
import org.dromara.visor.framework.biz.push.core.message.FeiShuPushMessage;
|
||||||
|
import org.dromara.visor.framework.biz.push.core.utils.MessageUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 飞书推送服务类
|
||||||
|
* <p>
|
||||||
|
* <a href="https://open.feishu.cn/document/client-docs/bot-v3/add-custom-bot?lang=zh-CN">doc</a>
|
||||||
|
*
|
||||||
|
* @author Shihao Lv
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2025/9/17 23:13
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@MessageChannel(value = PushChannelEnum.FEI_SHU)
|
||||||
|
public class FeiShuPushService extends BasePushService<FeiShuPushMessage> {
|
||||||
|
|
||||||
|
private static final String TEXT = "text";
|
||||||
|
|
||||||
|
private static final Integer SUCCESS_CODE = 0;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String buildRequestUrl(FeiShuPushMessage message) {
|
||||||
|
return message.getWebhook();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成签名
|
||||||
|
*
|
||||||
|
* @param message message
|
||||||
|
* @param timestamp timestamp
|
||||||
|
* @return sign
|
||||||
|
*/
|
||||||
|
protected String buildSign(FeiShuPushMessage message, long timestamp) {
|
||||||
|
String secret = message.getSecret();
|
||||||
|
if (Strings.isBlank(secret)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// 加签
|
||||||
|
try {
|
||||||
|
String stringToSign = timestamp + "\n" + secret;
|
||||||
|
byte[] signData = Signatures.hmacHashSignBytes(new byte[]{}, Strings.bytes(stringToSign), SecretKeySpecMode.HMAC_SHA256);
|
||||||
|
return Base64s.encodeToString(signData);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("FeiShuPushService-buildSign error", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String buildRequestBody(FeiShuPushMessage message) {
|
||||||
|
long timestamp = System.currentTimeMillis() / Const.MS_S_1;
|
||||||
|
// 加签
|
||||||
|
String sign = this.buildSign(message, timestamp);
|
||||||
|
// 格式化内容
|
||||||
|
String formattedContent = MessageUtils.format(message.getTemplate(), message.getParams());
|
||||||
|
// at 的用户
|
||||||
|
formattedContent = this.appendAtUsers(message, formattedContent);
|
||||||
|
// 构建请求体
|
||||||
|
return FeiShuRequestBody.builder()
|
||||||
|
.timestamp(timestamp)
|
||||||
|
.sign(sign)
|
||||||
|
.msgType(TEXT)
|
||||||
|
.content(FeiShuRequestBody.TextPayload.builder()
|
||||||
|
.text(formattedContent)
|
||||||
|
.build())
|
||||||
|
.build()
|
||||||
|
.toJsonString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void sendRequest(FeiShuPushMessage message, String url, String body) {
|
||||||
|
// 发送请求
|
||||||
|
OkResponse response = OkRequests.post(url, StandardContentType.APPLICATION_JSON_UTF8, body);
|
||||||
|
FeiShuResponseBody responseBody = JSON.parseObject(response.getBodyString(), FeiShuResponseBody.class);
|
||||||
|
// 验证发送结果
|
||||||
|
Assert.eq(responseBody.getCode(), SUCCESS_CODE, responseBody.getMsg());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* 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.biz.push.core.service;
|
||||||
|
|
||||||
|
import org.dromara.visor.framework.biz.push.core.message.PushMessage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息推送服务
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2025/9/17 17:17
|
||||||
|
*/
|
||||||
|
public interface IPushService<Message extends PushMessage> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 推送消息
|
||||||
|
*
|
||||||
|
* @param message message
|
||||||
|
*/
|
||||||
|
void push(Message message);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
* 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.biz.push.core.service;
|
||||||
|
|
||||||
|
import cn.orionsec.kit.http.ok.OkRequests;
|
||||||
|
import cn.orionsec.kit.http.ok.OkResponse;
|
||||||
|
import cn.orionsec.kit.lang.constant.StandardContentType;
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.dromara.visor.common.utils.Assert;
|
||||||
|
import org.dromara.visor.framework.biz.push.core.annotation.MessageChannel;
|
||||||
|
import org.dromara.visor.framework.biz.push.core.entity.WeComRequestBody;
|
||||||
|
import org.dromara.visor.framework.biz.push.core.entity.WeComResponseBody;
|
||||||
|
import org.dromara.visor.framework.biz.push.core.enums.PushChannelEnum;
|
||||||
|
import org.dromara.visor.framework.biz.push.core.message.WeComPushMessage;
|
||||||
|
import org.dromara.visor.framework.biz.push.core.utils.MessageUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 企业微信推送服务
|
||||||
|
* <p>
|
||||||
|
* <a href="https://developer.work.weixin.qq.com/document/path/99110">docs</a>
|
||||||
|
*
|
||||||
|
* @author Shihao Lv
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2025/9/17 23:13
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@MessageChannel(value = PushChannelEnum.WE_COM)
|
||||||
|
public class WeComPushService extends BasePushService<WeComPushMessage> {
|
||||||
|
|
||||||
|
private static final String MAKRDOWN = "markdown";
|
||||||
|
|
||||||
|
private static final Integer SUCCESS_CODE = 0;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String buildRequestUrl(WeComPushMessage message) {
|
||||||
|
return message.getWebhook();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String buildRequestBody(WeComPushMessage message) {
|
||||||
|
// 格式化内容
|
||||||
|
String formattedContent = MessageUtils.format(message.getTemplate(), message.getParams());
|
||||||
|
// at 用户
|
||||||
|
formattedContent = this.appendAtUsers(message, formattedContent);
|
||||||
|
// 构建请求体
|
||||||
|
WeComRequestBody.WeComRequestBodyBuilder builder = WeComRequestBody.builder()
|
||||||
|
.msgType(MAKRDOWN)
|
||||||
|
.markdown(WeComRequestBody.MarkdownPayload.builder()
|
||||||
|
.content(formattedContent)
|
||||||
|
.build());
|
||||||
|
|
||||||
|
return builder.build().toJsonString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void sendRequest(WeComPushMessage message, String url, String body) {
|
||||||
|
// 发送请求
|
||||||
|
OkResponse response = OkRequests.post(url, StandardContentType.APPLICATION_JSON_UTF8, body);
|
||||||
|
WeComResponseBody responseBody = JSON.parseObject(response.getBodyString(), WeComResponseBody.class);
|
||||||
|
// 验证发送结果
|
||||||
|
Assert.eq(responseBody.getErrCode(), SUCCESS_CODE, responseBody.getErrMsg());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* 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.biz.push.core.service;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.dromara.visor.framework.biz.push.core.annotation.MessageChannel;
|
||||||
|
import org.dromara.visor.framework.biz.push.core.enums.PushChannelEnum;
|
||||||
|
import org.dromara.visor.framework.biz.push.core.framework.service.WebsiteMessageFrameworkService;
|
||||||
|
import org.dromara.visor.framework.biz.push.core.message.WebsiteMessage;
|
||||||
|
import org.dromara.visor.framework.biz.push.core.utils.MessageUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 站内信推送服务
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2025/9/18 22:13
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@MessageChannel(value = PushChannelEnum.WEBSITE)
|
||||||
|
public class WebsitePushService extends BasePushService<WebsiteMessage> {
|
||||||
|
|
||||||
|
private final WebsiteMessageFrameworkService websiteMessageFrameworkService;
|
||||||
|
|
||||||
|
public WebsitePushService(WebsiteMessageFrameworkService websiteMessageFrameworkService) {
|
||||||
|
this.websiteMessageFrameworkService = websiteMessageFrameworkService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String buildRequestUrl(WebsiteMessage message) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String buildRequestBody(WebsiteMessage message) {
|
||||||
|
// 格式化内容
|
||||||
|
message.setTemplate(MessageUtils.format(message.getTemplate(), message.getParams()));
|
||||||
|
// 格式化标题
|
||||||
|
message.setTitle(MessageUtils.format(message.getTitle(), message.getParams()));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void sendRequest(WebsiteMessage message, String url, String body) {
|
||||||
|
websiteMessageFrameworkService.push(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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.framework.biz.push.core.utils;
|
||||||
|
|
||||||
|
import cn.orionsec.kit.lang.utils.Strings;
|
||||||
|
import org.dromara.visor.framework.biz.push.core.annotation.MessageChannel;
|
||||||
|
import org.dromara.visor.framework.biz.push.core.enums.PushChannelEnum;
|
||||||
|
import org.dromara.visor.framework.biz.push.core.message.PushMessage;
|
||||||
|
import org.dromara.visor.framework.biz.push.core.service.IPushService;
|
||||||
|
import org.springframework.beans.factory.BeanInitializationException;
|
||||||
|
import org.springframework.core.annotation.AnnotationUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息渠道工具类
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2025/9/18 22:05
|
||||||
|
*/
|
||||||
|
public class MessageChannelUtils {
|
||||||
|
|
||||||
|
private MessageChannelUtils() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取推送渠道
|
||||||
|
*
|
||||||
|
* @param service service
|
||||||
|
* @return channel
|
||||||
|
*/
|
||||||
|
public static PushChannelEnum getPushChannel(IPushService<? extends PushMessage> service) {
|
||||||
|
// 获取类型注解
|
||||||
|
MessageChannel messageChannel = AnnotationUtils.findAnnotation(service.getClass(), MessageChannel.class);
|
||||||
|
if (messageChannel == null) {
|
||||||
|
throw new BeanInitializationException(Strings.format("Push service [{}] not found @MessageChannel annotation", service.getClass().getName()));
|
||||||
|
}
|
||||||
|
return messageChannel.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* 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.biz.push.core.utils;
|
||||||
|
|
||||||
|
import cn.orionsec.kit.lang.utils.json.matcher.NoMatchStrategy;
|
||||||
|
import cn.orionsec.kit.lang.utils.json.matcher.ReplacementFormatter;
|
||||||
|
import cn.orionsec.kit.lang.utils.json.matcher.ReplacementFormatters;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息工具类
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2025/1/16 17:28
|
||||||
|
*/
|
||||||
|
public class MessageUtils {
|
||||||
|
|
||||||
|
private static final ReplacementFormatter FORMATTER = ReplacementFormatters.create("@{{ ", " }}")
|
||||||
|
.noMatchStrategy(NoMatchStrategy.KEEP);
|
||||||
|
|
||||||
|
private MessageUtils() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 替换模板
|
||||||
|
*
|
||||||
|
* @param template template
|
||||||
|
* @param params params
|
||||||
|
* @return template
|
||||||
|
*/
|
||||||
|
public static String format(String template, Map<String, Object> params) {
|
||||||
|
if (params == null) {
|
||||||
|
return template;
|
||||||
|
}
|
||||||
|
return FORMATTER.format(template, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 替换模板
|
||||||
|
*
|
||||||
|
* @param template template
|
||||||
|
* @param json json
|
||||||
|
* @return template
|
||||||
|
*/
|
||||||
|
public static String format(String template, String json) {
|
||||||
|
return FORMATTER.format(template, json);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
* 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.biz.push.core.utils;
|
||||||
|
|
||||||
|
import cn.orionsec.kit.lang.utils.Exceptions;
|
||||||
|
import cn.orionsec.kit.spring.SpringHolder;
|
||||||
|
import org.dromara.visor.common.entity.PushUser;
|
||||||
|
import org.dromara.visor.framework.biz.push.core.event.PushMessageEvent;
|
||||||
|
import org.dromara.visor.framework.biz.push.core.framework.service.PushTemplateFrameworkService;
|
||||||
|
import org.dromara.visor.framework.biz.push.core.message.PushMessage;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息推送工具类
|
||||||
|
*
|
||||||
|
* @author Shihao Lv
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2025/9/17 23:13
|
||||||
|
*/
|
||||||
|
public class PushUtils {
|
||||||
|
|
||||||
|
private static PushTemplateFrameworkService pushTemplateFrameworkService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发布消息推送事件
|
||||||
|
*
|
||||||
|
* @param pushMessage 推送消息配置
|
||||||
|
*/
|
||||||
|
public static void push(PushMessage pushMessage) {
|
||||||
|
SpringHolder.publishEvent(new PushMessageEvent(pushMessage));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据模板推送消息
|
||||||
|
*
|
||||||
|
* @param templateId 模板ID
|
||||||
|
* @param params 模板参数
|
||||||
|
*/
|
||||||
|
public static void pushTemplate(Long templateId, Map<String, Object> params) {
|
||||||
|
pushTemplate(templateId, params, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据模板推送消息
|
||||||
|
*
|
||||||
|
* @param templateId 模板ID
|
||||||
|
* @param params 模板参数
|
||||||
|
* @param pushUsers 推送用户
|
||||||
|
*/
|
||||||
|
public static void pushTemplate(Long templateId, Map<String, Object> params, List<PushUser> pushUsers) {
|
||||||
|
PushMessage pushMessage = pushTemplateFrameworkService.getPushMessageByTemplateId(templateId);
|
||||||
|
if (pushMessage == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 设置模板参数
|
||||||
|
pushMessage.setParams(params);
|
||||||
|
pushMessage.setPushUsers(pushUsers);
|
||||||
|
// 发布消息
|
||||||
|
push(pushMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setPushTemplateFrameworkService(PushTemplateFrameworkService pushTemplateFrameworkService) {
|
||||||
|
if (PushUtils.pushTemplateFrameworkService != null) {
|
||||||
|
// unmodified
|
||||||
|
throw Exceptions.state();
|
||||||
|
}
|
||||||
|
PushUtils.pushTemplateFrameworkService = pushTemplateFrameworkService;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
org.dromara.visor.framework.biz.push.configuration.OrionPushAutoConfiguration
|
||||||
@@ -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;
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user