mirror of
https://github.com/certd/certd.git
synced 2026-04-08 09:00:56 +08:00
Compare commits
37 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
335745d365 | ||
|
|
4204b31398 | ||
|
|
029a568645 | ||
|
|
6b2f1fcd3e | ||
|
|
3bdc610249 | ||
|
|
c03a70fde2 | ||
|
|
c77645e173 | ||
|
|
6531002d61 | ||
|
|
fea808ca5f | ||
|
|
59ba408070 | ||
|
|
3a8931feef | ||
|
|
7ebd8f6bf5 | ||
|
|
73883979c6 | ||
|
|
d8935b46b3 | ||
|
|
1505d04622 | ||
|
|
3b690cc31f | ||
|
|
b3814920bd | ||
|
|
8bf1f828b9 | ||
|
|
911e69e3bc | ||
|
|
77b4a1eaf6 | ||
|
|
2ed12c429e | ||
|
|
e578c52fdf | ||
|
|
5ff4e3c4ea | ||
|
|
1c2e7256c1 | ||
|
|
7a51ca225a | ||
|
|
8d242d8072 | ||
|
|
543b068efa | ||
|
|
eadbd5e821 | ||
|
|
c771f5a13c | ||
|
|
f13b3111c3 | ||
|
|
bb2714ff24 | ||
|
|
54c42b1fc2 | ||
|
|
1f42f933f0 | ||
|
|
6c533d225b | ||
|
|
67a89d1289 | ||
|
|
0b9bef2f38 | ||
|
|
1c4649409d |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -29,4 +29,5 @@ test/**/*.js
|
||||
/packages/ui/certd-server/data/db.sqlite
|
||||
/packages/ui/certd-server/data/keys.yaml
|
||||
/packages/pro/
|
||||
test.js
|
||||
test.js
|
||||
.history
|
||||
2
.npmrc
2
.npmrc
@@ -3,4 +3,4 @@ prefer-workspace-packages=true
|
||||
better_sqlite3_binary_host=https://registry.npmmirror.com/-/binary/better-sqlite3
|
||||
better_sqlite3_binary_host_mirror=https://registry.npmmirror.com/-/binary/better-sqlite3
|
||||
better-sqlite3_binary_host=https://registry.npmmirror.com/-/binary/better-sqlite3
|
||||
better-sqlite3_binary_host_mirror=https://registry.npmmirror.com/-/binary/better-sqlite3
|
||||
better-sqlite3_binary_host_mirror=https://registry.npmmirror.com/-/binary/better-sqlite3
|
||||
|
||||
30
.vscode/launch.json
vendored
30
.vscode/launch.json
vendored
@@ -24,6 +24,36 @@
|
||||
"runtimeArgs": ["dev"],
|
||||
"console": "integratedTerminal",
|
||||
"internalConsoleOptions": "neverOpen"
|
||||
},
|
||||
{
|
||||
"name": "server-mysql",
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"cwd": "${workspaceFolder}/packages/ui/certd-server",
|
||||
"runtimeExecutable": "pnpm",
|
||||
"runtimeArgs": ["dev-mysql"],
|
||||
"console": "integratedTerminal",
|
||||
"internalConsoleOptions": "neverOpen"
|
||||
},
|
||||
{
|
||||
"name": "server-pg",
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"cwd": "${workspaceFolder}/packages/ui/certd-server",
|
||||
"runtimeExecutable": "pnpm",
|
||||
"runtimeArgs": ["dev-pg"],
|
||||
"console": "integratedTerminal",
|
||||
"internalConsoleOptions": "neverOpen"
|
||||
},
|
||||
{
|
||||
"name": "server-common",
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"cwd": "${workspaceFolder}/packages/ui/certd-server",
|
||||
"runtimeExecutable": "pnpm",
|
||||
"runtimeArgs": ["dev-commpro"],
|
||||
"console": "integratedTerminal",
|
||||
"internalConsoleOptions": "neverOpen"
|
||||
},
|
||||
{
|
||||
"name": "server-local-plus",
|
||||
|
||||
5
.vscode/settings.json
vendored
5
.vscode/settings.json
vendored
@@ -1,5 +1,8 @@
|
||||
{
|
||||
"eslint.debug": false,
|
||||
"eslint.format.enable": true,
|
||||
"typescript.tsc.autoDetect": "watch"
|
||||
"typescript.tsc.autoDetect": "watch",
|
||||
"git.scanRepositories": [
|
||||
"./packages/pro"
|
||||
]
|
||||
}
|
||||
20
CHANGELOG.md
20
CHANGELOG.md
@@ -3,6 +3,26 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.37.3](https://github.com/certd/certd/compare/v1.37.2...v1.37.3) (2025-10-24)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 修复并发情况下证书申请日志混乱的bug ([bb2714f](https://github.com/certd/certd/commit/bb2714ff241f9db4a71d805b23a1b0f9f2f6413a))
|
||||
* 修复网络测试,telnet的bug ([c03a70f](https://github.com/certd/certd/commit/c03a70fde23c8e840bd0fdb4fcbca8990f6c65eb))
|
||||
* 修复站点证书监控,证书已经更新到最新日期了,仍然发出警告通知的bug ([1f42f93](https://github.com/certd/certd/commit/1f42f933f07860b27aa3d016e40916ff2b063eac))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 注册页面增加手机注册tab页签 ([6b2f1fc](https://github.com/certd/certd/commit/6b2f1fcd3e058061b814c3331cda8ce1b2d80d73))
|
||||
* 流水线创建时支持添加到证书监控 ([59ba408](https://github.com/certd/certd/commit/59ba4080706548828ef1c0a9cd893c1c9a7d591f))
|
||||
* 流水线支持有效期设置 ([911e69e](https://github.com/certd/certd/commit/911e69e3bc0cdd48b62953b5d0981d640fc1f8ac))
|
||||
* 群辉增加请求超时时长设置 ([b381492](https://github.com/certd/certd/commit/b3814920bdcabc911f860a8e19b5b9b3a04709ac))
|
||||
* 通知支持meow ([c77645e](https://github.com/certd/certd/commit/c77645e1733670214aaca5544cf8759d7e4adda4))
|
||||
* 站点证书监控增加导出和分组功能 ([2ed12c4](https://github.com/certd/certd/commit/2ed12c429eb58274a4f9dd0ed3b66e160d283ded))
|
||||
* 证书监控增加批量删除 ([e578c52](https://github.com/certd/certd/commit/e578c52fdf2f838038062aa4209b655fbae461fb))
|
||||
* esa 自动删除过期证书提示 ([8bf1f82](https://github.com/certd/certd/commit/8bf1f828b9eaa9208f32e8ee7460b86420fed0c7))
|
||||
* ssh 增加禁止-i参数提示 ([3a8931f](https://github.com/certd/certd/commit/3a8931feeffd7157163ff7d46b693e5e1a434b9c))
|
||||
|
||||
## [1.37.2](https://github.com/certd/certd/compare/v1.37.1...v1.37.2) (2025-10-14)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -95,10 +95,10 @@ export default defineConfig({
|
||||
},
|
||||
{
|
||||
text: "插件列表", items: [
|
||||
{text: "授权提供商", link: "/guide/plugins/access.md"},
|
||||
{text: "DNS提供商", link: "/guide/plugins/dns-provider.md"},
|
||||
{text: "任务插件", link: "/guide/plugins/deploy.md"},
|
||||
{text: "通知插件", link: "/guide/plugins/notification.md"},
|
||||
{text: "授权提供商", link: "/guide/plugins/access.md"},
|
||||
]
|
||||
},
|
||||
]
|
||||
|
||||
@@ -3,6 +3,23 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.37.2](https://github.com/certd/certd/compare/v1.37.1...v1.37.2) (2025-10-14)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 修复飞牛证书部署后无法生效的bug ([bf156a1](https://github.com/certd/certd/commit/bf156a13bd443cdadb73c9dff79bbef7231b4401))
|
||||
* aliyunoss 选择证书接入点选择新加坡无法上传的bug ([e00733a](https://github.com/certd/certd/commit/e00733a34644c23ffe926486b15dc96bf2fa4b57))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 优化start.sh脚本,去掉删除非ui目录的操作及提示 ([7993a7c](https://github.com/certd/certd/commit/7993a7cdb01885535950c63187e3f67d67ba2f75))
|
||||
* 增加飞牛证书id选择的提示 ([5a4d812](https://github.com/certd/certd/commit/5a4d8121462b1afe921d028465687be8c9679814))
|
||||
* 证书监控支持设置证书即将过期天数 ([cd35568](https://github.com/certd/certd/commit/cd35568e042e6ab928685efad51cdbed823d2d4f))
|
||||
* 支持网络测试 ([2bef608](https://github.com/certd/certd/commit/2bef608e07ceb56d52007f290667e0afef401b22))
|
||||
* 支持新网代理方式 ([f612509](https://github.com/certd/certd/commit/f612509cac87b859e81a7a52fe94b2eaccad22f9))
|
||||
* dns支持新网互联 ([f415190](https://github.com/certd/certd/commit/f41519048326d971acd9e0a30462231f77a299a6))
|
||||
* start.sh脚本支持根据当前系统判断是否使用sudo ([567cb7d](https://github.com/certd/certd/commit/567cb7d737023e26ec58403c6f28f109e212d379))
|
||||
|
||||
## [1.37.1](https://github.com/certd/certd/compare/v1.37.0...v1.37.1) (2025-09-29)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -2,50 +2,67 @@
|
||||
|
||||
| 序号 | 名称 | 说明 |
|
||||
|-----|-----|-----|
|
||||
| 1.| **阿里云授权** | |
|
||||
| 2.| **EAB授权** | ZeroSSL证书申请需要EAB授权 |
|
||||
| 3.| **google cloud** | 谷歌云授权 |
|
||||
| 4.| **主机登录授权** | |
|
||||
| 5.| **SFTP授权** | |
|
||||
| 6.| **阿里云OSS授权** | 包含地域和Bucket |
|
||||
| 7.| **FTP授权** | |
|
||||
| 8.| **腾讯云** | |
|
||||
| 9.| **腾讯云COS授权** | 腾讯云对象存储授权,包含地域和存储桶 |
|
||||
| 10.| **七牛云授权** | |
|
||||
| 11.| **七牛OSS授权** | |
|
||||
| 12.| **天翼云授权** | |
|
||||
| 13.| **s3/minio授权** | S3/minio oss授权 |
|
||||
| 14.| **baota授权** | |
|
||||
| 15.| **易盾DCDN授权** | https://user.yiduncdn.com |
|
||||
| 16.| **易盾rcdn授权** | 易盾CDN,每月免费30G,[注册即领](https://rhcdn.yiduncdn.com/register?code=8mn536rrzfbf8) |
|
||||
| 17.| **易发云短信** | sms.yfyidc.cn/ |
|
||||
| 18.| **cdnfly授权** | |
|
||||
| 19.| **群晖登录授权** | |
|
||||
| 20.| **k8s授权** | |
|
||||
| 21.| **1panel授权** | 账号和密码 |
|
||||
| 22.| **百度云授权** | |
|
||||
| 23.| **LeCDN授权** | |
|
||||
| 24.| **白山云授权** | |
|
||||
| 25.| **plesk授权** | |
|
||||
| 26.| **易支付** | |
|
||||
| 27.| **支付宝** | |
|
||||
| 28.| **微信支付** | |
|
||||
| 29.| **长亭雷池授权** | |
|
||||
| 30.| **lucky** | |
|
||||
| 31.| **括彩云cdn授权** | 括彩云CDN,每月免费30G,[注册即领](https://kuocaicdn.com/register?code=8mn536rrzfbf8) |
|
||||
| 32.| **uniCloud** | unicloud授权 |
|
||||
| 33.| **华为云授权** | |
|
||||
| 34.| **西部数码授权** | |
|
||||
| 35.| **多吉云** | |
|
||||
| 36.| **我爱云授权** | 我爱云CDN |
|
||||
| 37.| **CacheFly** | CacheFly |
|
||||
| 38.| **Gcore** | Gcore |
|
||||
| 39.| **亚马逊云aws授权** | |
|
||||
| 40.| **dns.la授权** | |
|
||||
| 41.| **又拍云** | |
|
||||
| 42.| **火山引擎** | |
|
||||
| 43.| **京东云** | |
|
||||
| 44.| **51dns授权** | |
|
||||
| 1.| **主机登录授权** | |
|
||||
| 2.| **阿里云授权** | |
|
||||
| 3.| **阿里云ESA授权** | |
|
||||
| 4.| **腾讯云** | |
|
||||
| 5.| **华为云授权** | |
|
||||
| 6.| **火山引擎** | |
|
||||
| 7.| **京东云** | |
|
||||
| 8.| **七牛云授权** | |
|
||||
| 9.| **天翼云授权** | |
|
||||
| 10.| **baota授权** | |
|
||||
| 11.| **百度云授权** | |
|
||||
| 12.| **EAB授权** | ZeroSSL证书申请需要EAB授权 |
|
||||
| 13.| **google cloud** | 谷歌云授权 |
|
||||
| 14.| **SFTP授权** | |
|
||||
| 15.| **阿里云OSS授权** | 包含地域和Bucket |
|
||||
| 16.| **FTP授权** | |
|
||||
| 17.| **腾讯云COS授权** | 腾讯云对象存储授权,包含地域和存储桶 |
|
||||
| 18.| **七牛OSS授权** | |
|
||||
| 19.| **s3/minio授权** | S3/minio oss授权 |
|
||||
| 20.| **宝塔云WAF授权** | 用于连接和管理宝塔云WAF服务的授权配置 |
|
||||
| 21.| **易盾DCDN授权** | https://user.yiduncdn.com |
|
||||
| 22.| **易盾rcdn授权** | 易盾CDN,每月免费30G,[注册即领](https://rhcdn.yiduncdn.com/register?code=8mn536rrzfbf8) |
|
||||
| 23.| **易发云短信** | sms.yfyidc.cn/ |
|
||||
| 24.| **cdnfly授权** | |
|
||||
| 25.| **群晖登录授权** | |
|
||||
| 26.| **k8s授权** | |
|
||||
| 27.| **1panel授权** | 账号和密码 |
|
||||
| 28.| **LeCDN授权** | |
|
||||
| 29.| **白山云授权** | |
|
||||
| 30.| **plesk授权** | |
|
||||
| 31.| **易支付** | |
|
||||
| 32.| **支付宝** | |
|
||||
| 33.| **微信支付** | |
|
||||
| 34.| **长亭雷池授权** | |
|
||||
| 35.| **lucky** | |
|
||||
| 36.| **括彩云cdn授权** | 括彩云CDN,每月免费30G,[注册即领](https://kuocaicdn.com/register?code=8mn536rrzfbf8) |
|
||||
| 37.| **uniCloud** | unicloud授权 |
|
||||
| 38.| **猫云授权** | |
|
||||
| 39.| **西部数码授权** | |
|
||||
| 40.| **多吉云** | |
|
||||
| 41.| **我爱云授权** | 我爱云CDN |
|
||||
| 42.| **CacheFly** | CacheFly |
|
||||
| 43.| **Gcore** | Gcore |
|
||||
| 44.| **亚马逊云aws授权** | |
|
||||
| 45.| **亚马逊云科技(国区)授权** | |
|
||||
| 46.| **dns.la授权** | |
|
||||
| 47.| **又拍云** | |
|
||||
| 48.| **51dns授权** | |
|
||||
| 49.| **FlexCDN授权** | |
|
||||
| 50.| **farcdn授权** | |
|
||||
| 51.| **cloudflare授权** | |
|
||||
| 52.| **Github授权** | |
|
||||
| 53.| **namesilo授权** | |
|
||||
| 54.| **proxmox** | |
|
||||
| 55.| **网宿授权** | |
|
||||
| 56.| **金山云授权** | |
|
||||
| 57.| **APISIX授权** | |
|
||||
| 58.| **Dokploy授权** | |
|
||||
| 59.| **godaddy授权** | |
|
||||
| 60.| **新网授权** | |
|
||||
| 61.| **雨云授权** | https://app.rainyun.com/ |
|
||||
|
||||
<style module>
|
||||
table th:first-of-type {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# 任务插件
|
||||
共 `70` 款任务插件
|
||||
共 `102` 款任务插件
|
||||
## 1. 证书申请
|
||||
|
||||
| 序号 | 名称 | 说明 |
|
||||
@@ -15,6 +15,8 @@
|
||||
| 2.| **IIS-部署到IIS站点** | |
|
||||
| 3.| **主机-执行远程主机脚本命令** | 可以执行重启nginx等操作让证书生效 |
|
||||
| 4.| **主机-部署证书到SSH主机** | SFTP上传证书到主机,然后SSH执行部署脚本命令 |
|
||||
| 5.| **主机-复制到本机** | 【仅管理员使用】实际上是复制证书到docker容器内的某个路径,需要做目录映射到宿主机 |
|
||||
| 6.| **上传证书到对象存储OSS** | 支持阿里云OSS、腾讯云COS、七牛云KODO、S3、MinIO、FTP、SFTP |
|
||||
## 3. CDN
|
||||
|
||||
| 序号 | 名称 | 说明 |
|
||||
@@ -22,33 +24,44 @@
|
||||
| 1.| **易盾-部署到易盾DCDN** | 主要是防御,http://user.yiduncdn.com/ |
|
||||
| 2.| **易盾-部署到易盾RCDN** | 易盾CDN,每月免费30G,[注册即领](https://rhcdn.yiduncdn.com/register?code=8mn536rrzfbf8) |
|
||||
| 3.| **cdnfly-部署证书到cdnfly** | cdnfly |
|
||||
| 4.| **百度云-部署证书到CDN** | 部署到百度云CDN |
|
||||
| 5.| **LeCDN-更新证书** | |
|
||||
| 6.| **LeCDN-更新证书V2** | 支持新版本LeCDN |
|
||||
| 7.| **白山云-更新证书** | |
|
||||
| 8.| **天翼云-部署证书到CDN** | 部署证书到天翼云CDN和全站加速 |
|
||||
| 9.| **括彩云-部署到括彩云CDN** | 括彩云CDN,每月免费30G,[注册即领](https://kuocaicdn.com/register?code=8mn536rrzfbf8) |
|
||||
| 10.| **多吉云-部署到多吉云CDN** | |
|
||||
| 11.| **我爱云-部署证书到我爱云CDN** | 部署证书到我爱云CDN |
|
||||
| 12.| **CacheFly-部署证书到CacheFly** | 部署证书到 CacheFly |
|
||||
| 13.| **Gcore-部署证书到Gcore** | 仅上传 并不会部署到cdn |
|
||||
| 14.| **Gcore-刷新Gcore证书** | 刷新现有的证书 |
|
||||
| 15.| **又拍云-部署证书到CDN/USS** | 支持又拍云CDN,又拍云云存储USS |
|
||||
| 4.| **LeCDN-更新证书** | |
|
||||
| 5.| **LeCDN-更新证书V2** | 支持新版本LeCDN |
|
||||
| 6.| **白山云-更新证书** | |
|
||||
| 7.| **天翼云-部署证书到CDN** | 部署证书到天翼云CDN和全站加速 |
|
||||
| 8.| **括彩云-部署到括彩云CDN** | 括彩云CDN,每月免费30G,[注册即领](https://kuocaicdn.com/register?code=8mn536rrzfbf8) |
|
||||
| 9.| **多吉云-部署到多吉云CDN** | |
|
||||
| 10.| **我爱云-部署证书到我爱云CDN** | 部署证书到我爱云CDN |
|
||||
| 11.| **CacheFly-部署证书到CacheFly** | 部署证书到 CacheFly |
|
||||
| 12.| **Gcore-部署证书到Gcore** | 仅上传 并不会部署到cdn |
|
||||
| 13.| **Gcore-刷新Gcore证书** | 刷新现有的证书 |
|
||||
| 14.| **又拍云-部署证书到CDN/USS** | 支持又拍云CDN,又拍云云存储USS |
|
||||
| 15.| **FlexCDN-更新证书** | |
|
||||
| 16.| **farcdn-更新证书** | www.farcdn.net |
|
||||
| 17.| **雨云-更新证书** | app.rainyun.com |
|
||||
| 18.| **网宿-更新证书** | 网宿证书自动更新 |
|
||||
| 19.| **金山云-更新CDN证书** | 金山云自动更新CDN证书 |
|
||||
| 20.| **APISIX-更新证书** | 自动更新APISIX证书 |
|
||||
## 4. 面板
|
||||
|
||||
| 序号 | 名称 | 说明 |
|
||||
|-----|-----|-----|
|
||||
| 1.| **宝塔-面板证书部署** | 部署宝塔面板本身的ssl证书 |
|
||||
| 2.| **宝塔-网站证书部署** | 部署宝塔管理的站点的ssl证书,目前支持网站站点、docker站点等 |
|
||||
| 3.| **群晖-部署证书到群晖面板** | Synology,支持6.x以上版本 |
|
||||
| 4.| **K8S-部署证书到Secret** | 部署证书到k8s的secret |
|
||||
| 5.| **K8S-Ingress 证书部署** | 部署证书到k8s的Ingress |
|
||||
| 6.| **1Panel-部署证书到1Panel** | 更新1Panel的证书 |
|
||||
| 7.| **Plesk-部署Plesk网站证书** | |
|
||||
| 8.| **雷池-更新证书** | 更新长亭雷池WAF的证书 |
|
||||
| 9.| **lucky-更新Lucky证书** | |
|
||||
| 10.| **uniCloud-部署到服务空间** | 部署到服务空间 |
|
||||
| 11.| **威联通-部署证书到威联通** | 部署证书到qnap |
|
||||
| 2.| **宝塔-网站证书部署** | 部署宝塔管理的站点的ssl证书,目前支持网站站点、docker站点等。本插件也支持aaPanel。 |
|
||||
| 3.| **宝塔-WAF证书部署** | 部署宝塔云WAF/aaWAF |
|
||||
| 4.| **宝塔win-网站证书部署** | 部署到Windows版宝塔管理的站点的ssl证书 |
|
||||
| 5.| **宝塔-删除过期证书** | 删除证书夹中过期证书 |
|
||||
| 6.| **群晖-部署证书到群晖面板** | Synology,支持6.x以上版本 |
|
||||
| 7.| **K8S-部署证书到Secret** | 部署证书到k8s的secret |
|
||||
| 8.| **K8S-Ingress 证书部署** | 部署证书到k8s的Ingress |
|
||||
| 9.| **1Panel-部署证书到1Panel** | 更新1Panel的证书 |
|
||||
| 10.| **Plesk-部署Plesk网站证书** | |
|
||||
| 11.| **雷池-更新证书** | 更新长亭雷池WAF的证书 |
|
||||
| 12.| **lucky-更新Lucky证书** | |
|
||||
| 13.| **uniCloud-部署到服务空间** | 部署到服务空间 |
|
||||
| 14.| **威联通-部署证书到威联通** | 部署证书到qnap |
|
||||
| 15.| **飞牛NAS-部署证书** | |
|
||||
| 16.| **Proxmox-上传证书到Proxmox** | |
|
||||
| 17.| **Dokploy-更新证书** | 自动更新Dokploy证书 |
|
||||
## 5. 阿里云
|
||||
|
||||
| 序号 | 名称 | 说明 |
|
||||
@@ -57,18 +70,24 @@
|
||||
| 2.| **阿里云-部署至任意云资源** | 【不建议使用】需要消耗阿里云自动部署次数,支持SLB、LIVE、webHosting、VOD、CR、DCDN、DDoS、CDN、ALB、APIGateway、FC、GA、MSE、NLB、OSS、SAE、WAF等云产品 |
|
||||
| 3.| **阿里云-部署证书至CDN** | 自动部署域名证书至阿里云CDN |
|
||||
| 4.| **阿里云-部署证书至DCDN** | 依赖证书申请前置任务,自动部署域名证书至阿里云DCDN |
|
||||
| 5.| **阿里云-部署证书至OSS** | 自动部署域名证书至阿里云OSS |
|
||||
| 6.| **阿里云-上传证书到阿里云** | 如果不想在阿里云上同一份证书上传多次,可以把此任务作为前置任务,其他阿里云任务证书那一项选择此任务的输出 |
|
||||
| 5.| **阿里云-部署证书至OSS** | 部署域名证书至阿里云OSS自定义域名,不是上传到阿里云oss |
|
||||
| 6.| **阿里云-上传证书到阿里云CAS** | 上传证书到阿里云数字证书管理服务(CAS),注意:不会部署到任何应用上;如果不想在阿里云上同一份证书上传多次,可以把此任务作为前置任务,其他阿里云任务证书那一项选择此任务的输出 |
|
||||
| 7.| **阿里云-部署至阿里云WAF** | 部署证书到阿里云WAF |
|
||||
| 8.| **阿里云-部署至ALB(应用负载均衡)** | ALB,更新监听器的默认证书 |
|
||||
| 9.| **阿里云-部署至NLB(网络负载均衡)** | NLB,网络负载均衡,更新监听器的默认证书 |
|
||||
| 10.| **阿里云-部署至SLB(传统负载均衡)** | 部署证书到阿里云SLB(传统负载均衡) |
|
||||
| 11.| **阿里云-部署至阿里云FC(3.0)** | 部署证书到阿里云函数计算(FC3.0),【注意】证书的加密算法必须选择【pkcs1旧版】 |
|
||||
| 10.| **阿里云-部署至CLB(传统负载均衡)** | 部署证书到阿里云CLB(传统负载均衡) |
|
||||
| 11.| **阿里云-部署至阿里云FC(3.0)** | 部署证书到阿里云函数计算(FC3.0) |
|
||||
| 12.| **阿里云-部署至ESA** | 部署证书到阿里云ESA(边缘安全加速) |
|
||||
| 13.| **阿里云-部署至VOD** | 部署证书到阿里云视频点播(vod) |
|
||||
| 14.| **阿里云-部署证书至API网关** | 自动部署域名证书至阿里云API网关(APIGateway) |
|
||||
| 15.| **阿里云-部署至云原生API网关/AI网关** | 自动部署域名证书至云原生API网关、AI网关 |
|
||||
## 6. 华为云
|
||||
|
||||
| 序号 | 名称 | 说明 |
|
||||
|-----|-----|-----|
|
||||
| 1.| **华为云-部署证书至CDN** | |
|
||||
| 2.| **华为云-上传证书至CCM** | 上传证书到华为云CCM |
|
||||
| 3.| **华为云-部署证书至OBS** | |
|
||||
## 7. 腾讯云
|
||||
|
||||
| 序号 | 名称 | 说明 |
|
||||
@@ -79,9 +98,15 @@
|
||||
| 4.| **腾讯云-部署到CDN-v2** | 推荐使用 |
|
||||
| 5.| **腾讯云-上传证书到腾讯云** | 上传成功后输出:tencentCertId |
|
||||
| 6.| **腾讯云-部署证书到COS** | 部署到腾讯云COS源站域名证书【注意:很不稳定,需要重试很多次偶尔才能成功一次】 |
|
||||
| 7.| **腾讯云-部署到腾讯云EO** | 腾讯云边缘安全加速平台EO,必须配置上传证书到腾讯云任务 |
|
||||
| 7.| **腾讯云-部署到腾讯云EO** | 腾讯云边缘安全加速平台EdgeOne(EO),必须配置上传证书到腾讯云任务 |
|
||||
| 8.| **腾讯云-删除即将过期证书** | 仅删除未使用的证书 |
|
||||
| 9.| **腾讯云-部署到TKE-ingress** | serverless集群请使用K8S部署插件;Qcloud类型需要【上传到腾讯云】作为前置任务;ApiServer未开启外网访问则需要做域名的内网IP映射 |
|
||||
| 9.| **腾讯云-部署到TKE** | 修改TKE集群密钥配置,支持Opaque和TLS证书类型。注意:
|
||||
1. serverless集群请使用K8S部署插件;
|
||||
2. Opaque类型需要【上传到腾讯云】作为前置任务;
|
||||
3. ApiServer需要开通公网访问(或者certd可访问),实际上底层仍然是通过KubeClient进行部署 |
|
||||
| 10.| **腾讯云-部署到腾讯云直播** | https://console.cloud.tencent.com/live/ |
|
||||
| 11.| **腾讯云-实例开关机** | 腾讯云实例开关机 |
|
||||
| 12.| **腾讯云-更新证书(Id不变)** | 根据证书id一键更新腾讯云证书并自动部署(Id不变),注意该接口为腾讯云白名单功能,非白名单用户无法使用该功能 |
|
||||
## 8. 火山引擎
|
||||
|
||||
| 序号 | 名称 | 说明 |
|
||||
@@ -91,6 +116,8 @@
|
||||
| 3.| **火山引擎-上传证书至证书中心** | 上传证书至火山引擎证书中心 |
|
||||
| 4.| **火山引擎-部署证书至ALB** | 部署至火山引擎应用负载均衡 |
|
||||
| 5.| **火山引擎-部署证书至Live** | 部署至火山引擎视频直播 |
|
||||
| 6.| **火山引擎-部署证书至DCDN** | 部署至火山引擎全站加速 |
|
||||
| 7.| **火山引擎-部署证书至VOD** | 部署至火山引擎视频点播(暂不可用) |
|
||||
## 9. 京东云
|
||||
|
||||
| 序号 | 名称 | 说明 |
|
||||
@@ -98,26 +125,43 @@
|
||||
| 1.| **京东云-部署证书至CDN** | 京东云内容分发网络 |
|
||||
| 2.| **京东云-更新已有证书** | 更新SSL数字证书中的证书 |
|
||||
| 3.| **京东云-上传新证书** | 上传证书到SSL数字证书中心 |
|
||||
## 10. 七牛云
|
||||
## 10. 百度云
|
||||
|
||||
| 序号 | 名称 | 说明 |
|
||||
|-----|-----|-----|
|
||||
| 1.| **百度云-部署证书到CDN** | 部署到百度云CDN |
|
||||
| 2.| **百度云-部署证书到负载均衡** | 部署到百度云负载均衡,包括BLB、APPBLB |
|
||||
| 3.| **百度云-上传到证书托管** | 上传证书到百度云证书托管中心 |
|
||||
## 11. 七牛云
|
||||
|
||||
| 序号 | 名称 | 说明 |
|
||||
|-----|-----|-----|
|
||||
| 1.| **七牛云-部署证书至OSS** | 自动部署域名证书至七牛云KODO,注意是自定义源站域名,不是CDN域名 |
|
||||
| 2.| **七牛云-部署证书至CDN** | 自动部署域名证书至七牛云CDN |
|
||||
## 11. 亚马逊云
|
||||
| 2.| **七牛云-部署证书至CDN/DCDN** | 自动部署域名证书至七牛云CDN、DCDN |
|
||||
| 3.| **七牛云-上传证书到七牛云** | 上传到七牛云 |
|
||||
## 12. 亚马逊云
|
||||
|
||||
| 序号 | 名称 | 说明 |
|
||||
|-----|-----|-----|
|
||||
| 1.| **AWS-部署证书到CloudFront** | 部署证书到 AWS CloudFront |
|
||||
## 12. 其他
|
||||
| 2.| **AWS-上传证书到ACM** | 上传证书 AWS ACM |
|
||||
| 3.| **AWS(国区)-部署证书到CloudFront** | 部署证书到 AWS CloudFront |
|
||||
## 13. 其他
|
||||
|
||||
| 序号 | 名称 | 说明 |
|
||||
|-----|-----|-----|
|
||||
| 1.| **Demo-测试插件** | |
|
||||
| 2.| **重启 Certd** | 【仅管理员可用】 重启 certd的https服务,用于更新 Certd 的 ssl 证书 |
|
||||
| 3.| **自定义js脚本** | 【仅管理员】运行自定义js脚本执行 |
|
||||
| 4.| **等待** | 等待一段时间 |
|
||||
| 5.| **数据库备份** | 仅支持备份SQLite数据库 |
|
||||
| 2.| **等待** | 等待一段时间 |
|
||||
| 3.| **邮件发送证书** | 通过邮件发送证书 |
|
||||
| 4.| **webhook方式部署证书** | 调用webhook部署证书 |
|
||||
| 5.| **Github-检查Release版本** | 检查最新Release版本并推送消息 |
|
||||
## 14. 管理
|
||||
|
||||
| 序号 | 名称 | 说明 |
|
||||
|-----|-----|-----|
|
||||
| 1.| **重启 Certd** | 【仅管理员可用】 重启 certd的https服务,用于更新 Certd 的 ssl 证书 |
|
||||
| 2.| **自定义js脚本** | 【仅管理员】运行自定义js脚本执行 |
|
||||
| 3.| **数据库备份** | 【仅管理员可用】仅支持备份SQLite数据库 |
|
||||
|
||||
<style module>
|
||||
table th:first-of-type {
|
||||
|
||||
@@ -3,13 +3,19 @@
|
||||
| 序号 | 名称 | 说明 |
|
||||
|-----|-----|-----|
|
||||
| 1.| **阿里云** | 阿里云DNS解析提供商 |
|
||||
| 2.| **腾讯云** | 腾讯云域名DNS解析提供者 |
|
||||
| 3.| **华为云** | 华为云DNS解析提供商 |
|
||||
| 4.| **西部数码** | west dns provider |
|
||||
| 5.| **dns.la** | dns.la |
|
||||
| 6.| **火山引擎** | 火山引擎DNS解析提供商 |
|
||||
| 7.| **京东云** | 京东云DNS解析提供商 |
|
||||
| 8.| **51dns** | 51DNS |
|
||||
| 2.| **阿里ESA** | 阿里ESA DNS解析 |
|
||||
| 3.| **火山引擎** | 火山引擎DNS解析提供商 |
|
||||
| 4.| **京东云** | 京东云DNS解析提供商 |
|
||||
| 5.| **新网** | 新网域名解析 |
|
||||
| 6.| **腾讯云** | 腾讯云域名DNS解析提供者 |
|
||||
| 7.| **华为云** | 华为云DNS解析提供商 |
|
||||
| 8.| **西部数码** | west dns provider |
|
||||
| 9.| **dns.la** | dns.la |
|
||||
| 10.| **雨云** | 雨云DNS解析提供商 |
|
||||
| 11.| **cloudflare** | cloudflare dns provider |
|
||||
| 12.| **namesilo** | namesilo dns provider |
|
||||
| 13.| **godaddy** | GoDaddy |
|
||||
| 14.| **51dns** | 51DNS |
|
||||
|
||||
<style module>
|
||||
table th:first-of-type {
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
| 10.| **Slack通知** | Slack消息推送通知 |
|
||||
| 11.| **Bark 通知** | Bark 推送通知插件 |
|
||||
| 12.| **飞书通知** | 飞书群聊webhook通知 |
|
||||
| 13.| **钉钉通知** | 钉钉群聊通知 |
|
||||
| 14.| **VoceChat通知** | https://voce.chat |
|
||||
| 15.| **OneBot V11 通知** | 通过动态拼接URL发送 OneBot V11 协议消息 |
|
||||
|
||||
<style module>
|
||||
table th:first-of-type {
|
||||
|
||||
@@ -9,5 +9,5 @@
|
||||
}
|
||||
},
|
||||
"npmClient": "pnpm",
|
||||
"version": "1.37.2"
|
||||
"version": "1.37.3"
|
||||
}
|
||||
|
||||
@@ -18,8 +18,9 @@
|
||||
"devb": "lerna run dev-build",
|
||||
"i-all": "lerna link && lerna exec npm install ",
|
||||
"publish": "npm run prepublishOnly2 && lerna publish --force-publish=pro/plus-core --conventional-commits --create-release github && npm run afterpublishOnly && npm run commitAll",
|
||||
"afterpublishOnly": "npm run copylogs && time /t >trigger/build.trigger && git add ./trigger/build.trigger && git commit -m \"build: trigger build image\" && TIMEOUT /T 10 && git push",
|
||||
"afterpublishOnly": "npm run plugin-doc-gen && npm run copylogs && time /t >trigger/build.trigger && git add ./trigger/build.trigger && git commit -m \"build: trigger build image\" && TIMEOUT /T 10 && git push",
|
||||
"transform-sql": "cd ./packages/ui/certd-server/db/ && node --experimental-json-modules transform.js",
|
||||
"plugin-doc-gen": "cd ./packages/ui/certd-server/ && npm run export-md",
|
||||
"commitAll": "git add . && git commit -m \"build: publish\" && git push && npm run commitPro",
|
||||
"commitPro": "cd ./packages/pro/ && git add . && git commit -m \"build: publish\" && git push",
|
||||
"copylogs": "copyfiles \"CHANGELOG.md\" ./docs/guide/changelogs/",
|
||||
@@ -34,7 +35,8 @@
|
||||
"docs:build": "npm run copylogs && vitepress build docs",
|
||||
"docs:preview": "vitepress preview docs",
|
||||
"pub": "echo 1",
|
||||
"dev": "pnpm run -r --parallel compile "
|
||||
"dev": "pnpm run -r --parallel compile ",
|
||||
"release": "time /t >trigger/release.trigger && git add trigger/release.trigger && git commit -m \"build: release\" && git push"
|
||||
},
|
||||
"license": "AGPL-3.0",
|
||||
"dependencies": {
|
||||
|
||||
@@ -3,6 +3,12 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.37.3](https://github.com/publishlab/node-acme-client/compare/v1.37.2...v1.37.3) (2025-10-24)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 修复并发情况下证书申请日志混乱的bug ([bb2714f](https://github.com/publishlab/node-acme-client/commit/bb2714ff241f9db4a71d805b23a1b0f9f2f6413a))
|
||||
|
||||
## [1.37.2](https://github.com/publishlab/node-acme-client/compare/v1.37.1...v1.37.2) (2025-10-14)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"description": "Simple and unopinionated ACME client",
|
||||
"private": false,
|
||||
"author": "nmorsman",
|
||||
"version": "1.37.2",
|
||||
"version": "1.37.3",
|
||||
"type": "module",
|
||||
"module": "scr/index.js",
|
||||
"main": "src/index.js",
|
||||
@@ -18,7 +18,7 @@
|
||||
"types"
|
||||
],
|
||||
"dependencies": {
|
||||
"@certd/basic": "^1.37.2",
|
||||
"@certd/basic": "^1.37.3",
|
||||
"@peculiar/x509": "^1.11.0",
|
||||
"asn1js": "^3.0.5",
|
||||
"axios": "^1.7.2",
|
||||
@@ -70,5 +70,5 @@
|
||||
"bugs": {
|
||||
"url": "https://github.com/publishlab/node-acme-client/issues"
|
||||
},
|
||||
"gitHead": "c725cee0445dbe1ebd1b6588373bde31697113da"
|
||||
"gitHead": "e1daaf07ce2fda6ce44998d65f8a989fc6af88db"
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ class AcmeApi {
|
||||
}
|
||||
}
|
||||
}
|
||||
console.log(locationUrl, mapping);
|
||||
return locationUrl;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* ACME auto helper
|
||||
*/
|
||||
import { readCsrDomains } from "./crypto/index.js";
|
||||
import { log } from "./logger.js";
|
||||
import { wait } from "./wait.js";
|
||||
import { CancelError } from "./error.js";
|
||||
|
||||
@@ -45,6 +44,9 @@ export default async (client, userOpts) => {
|
||||
accountPayload.externalAccountBinding = opts.externalAccountBinding;
|
||||
}
|
||||
|
||||
const log = (...args)=>{
|
||||
return client.logger.info(...args);
|
||||
}
|
||||
/**
|
||||
* Register account
|
||||
*/
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
*/
|
||||
import axios from 'axios';
|
||||
import { parseRetryAfterHeader } from './util.js';
|
||||
import { log } from './logger.js';
|
||||
const { AxiosError } = axios;
|
||||
import {getGlobalAgents, HttpError} from '@certd/basic'
|
||||
import { log } from './logger.js';
|
||||
/**
|
||||
* Defaults
|
||||
*/
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
*/
|
||||
import { createHash } from 'crypto';
|
||||
import { getPemBodyAsB64u } from './crypto/index.js';
|
||||
import { log } from './logger.js';
|
||||
import HttpClient from './http.js';
|
||||
import AcmeApi from './api.js';
|
||||
import verify from './verify.js';
|
||||
@@ -104,8 +103,13 @@ class AcmeClient {
|
||||
max: this.opts.backoffMax,
|
||||
};
|
||||
|
||||
this.http = new HttpClient(this.opts.directoryUrl, this.opts.accountKey, this.opts.externalAccountBinding, this.opts.urlMapping);
|
||||
this.http = new HttpClient(this.opts.directoryUrl, this.opts.accountKey, this.opts.externalAccountBinding, this.opts.urlMapping, opts.logger);
|
||||
this.api = new AcmeApi(this.http, this.opts.accountUrl);
|
||||
this.logger = opts.logger;
|
||||
}
|
||||
|
||||
log(...args) {
|
||||
this.logger.info(...args);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -177,7 +181,7 @@ class AcmeClient {
|
||||
this.getAccountUrl();
|
||||
|
||||
/* Account URL exists */
|
||||
log('Account URL exists, returning updateAccount()');
|
||||
this.log('Account URL exists, returning updateAccount()');
|
||||
return this.updateAccount(data);
|
||||
}
|
||||
catch (e) {
|
||||
@@ -185,7 +189,7 @@ class AcmeClient {
|
||||
|
||||
/* HTTP 200: Account exists */
|
||||
if (resp.status === 200) {
|
||||
log('Account already exists (HTTP 200), returning updateAccount()');
|
||||
this.log('Account already exists (HTTP 200), returning updateAccount()');
|
||||
return this.updateAccount(data);
|
||||
}
|
||||
|
||||
@@ -214,7 +218,7 @@ class AcmeClient {
|
||||
this.api.getAccountUrl();
|
||||
}
|
||||
catch (e) {
|
||||
log('No account URL found, returning createAccount()');
|
||||
this.log('No account URL found, returning createAccount()');
|
||||
return this.createAccount(data);
|
||||
}
|
||||
|
||||
@@ -502,7 +506,7 @@ class AcmeClient {
|
||||
await verify[challenge.type](authz, challenge, keyAuthorization);
|
||||
};
|
||||
|
||||
log('Waiting for ACME challenge verification(等待ACME检查验证)');
|
||||
this.log('Waiting for ACME challenge verification(等待ACME检查验证)');
|
||||
return util.retry(verifyFn, this.backoffOpts);
|
||||
}
|
||||
|
||||
@@ -570,7 +574,7 @@ class AcmeClient {
|
||||
const resp = await this.api.apiRequest(item.url, null, [200]);
|
||||
|
||||
/* Verify status */
|
||||
log(`[${d}] Item has status(检查状态): ${resp.data.status}`);
|
||||
this.log(`[${d}] Item has status(检查状态): ${resp.data.status}`);
|
||||
|
||||
if (invalidStates.includes(resp.data.status)) {
|
||||
abort();
|
||||
@@ -586,7 +590,7 @@ class AcmeClient {
|
||||
throw new Error(`[${d}] Unexpected item status: ${resp.data.status}`);
|
||||
};
|
||||
|
||||
log(`[${d}] Waiting for valid status (等待valid状态): ${item.url}`, this.backoffOpts);
|
||||
this.log(`[${d}] Waiting for valid status (等待valid状态): ${item.url}`, this.backoffOpts);
|
||||
return util.retry(verifyFn, this.backoffOpts);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ import { getJwk } from './crypto/index.js';
|
||||
*/
|
||||
|
||||
class HttpClient {
|
||||
constructor(directoryUrl, accountKey, externalAccountBinding = {}, urlMapping = {}) {
|
||||
constructor(directoryUrl, accountKey, externalAccountBinding = {}, urlMapping = {},logger) {
|
||||
this.directoryUrl = directoryUrl;
|
||||
this.accountKey = accountKey;
|
||||
this.externalAccountBinding = externalAccountBinding;
|
||||
@@ -31,6 +31,7 @@ class HttpClient {
|
||||
this.directoryMaxAge = 86400;
|
||||
this.directoryTimestamp = 0;
|
||||
this.urlMapping = urlMapping;
|
||||
this.log = logger? logger.info.bind(logger) : log;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,7 +49,7 @@ class HttpClient {
|
||||
for (const key in this.urlMapping.mappings) {
|
||||
if (url.includes(key)) {
|
||||
const newUrl = url.replace(key, this.urlMapping.mappings[key]);
|
||||
log(`use reverse proxy: ${newUrl}`);
|
||||
this.log(`use reverse proxy: ${newUrl}`);
|
||||
url = newUrl;
|
||||
}
|
||||
}
|
||||
@@ -65,10 +66,10 @@ class HttpClient {
|
||||
opts.headers['Content-Type'] = 'application/jose+json';
|
||||
|
||||
/* Request */
|
||||
log(`HTTP request: ${method} ${url}`);
|
||||
this.log(`HTTP request: ${method} ${url}`);
|
||||
const resp = await axios.request(opts);
|
||||
|
||||
log(`RESP ${resp.status} ${method} ${url}`);
|
||||
this.log(`RESP ${resp.status} ${method} ${url}`);
|
||||
return resp;
|
||||
}
|
||||
|
||||
@@ -85,7 +86,7 @@ class HttpClient {
|
||||
const age = (now - this.directoryTimestamp);
|
||||
|
||||
if (!this.directoryCache || (age > this.directoryMaxAge)) {
|
||||
log(`Refreshing ACME directory, age: ${age}`);
|
||||
this.log(`Refreshing ACME directory, age: ${age}`);
|
||||
const resp = await this.request(this.directoryUrl, 'get');
|
||||
|
||||
if (resp.status >= 400) {
|
||||
@@ -187,7 +188,7 @@ class HttpClient {
|
||||
|
||||
/* Nonce */
|
||||
if (nonce) {
|
||||
log(`Using nonce: ${nonce}`);
|
||||
this.log(`Using nonce: ${nonce}`);
|
||||
header.nonce = nonce;
|
||||
}
|
||||
|
||||
@@ -314,7 +315,7 @@ class HttpClient {
|
||||
nonce = resp.headers['replay-nonce'] || null;
|
||||
attempts += 1;
|
||||
|
||||
log(`Caught invalid nonce error, retrying (${attempts}/${this.maxBadNonceRetries}) signed request to: ${url}`);
|
||||
this.log(`Caught invalid nonce error, retrying (${attempts}/${this.maxBadNonceRetries}) signed request to: ${url}`);
|
||||
return this.signedRequest(url, payload, { kid, nonce, includeExternalAccountBinding }, attempts);
|
||||
}
|
||||
|
||||
|
||||
1
packages/core/acme-client/types/index.d.ts
vendored
1
packages/core/acme-client/types/index.d.ts
vendored
@@ -49,6 +49,7 @@ export interface ClientOptions {
|
||||
backoffMax?: number;
|
||||
urlMapping?: UrlMapping;
|
||||
signal?: AbortSignal;
|
||||
logger?:any
|
||||
}
|
||||
|
||||
export interface ClientExternalAccountBindingOptions {
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.37.3](https://github.com/certd/certd/compare/v1.37.2...v1.37.3) (2025-10-24)
|
||||
|
||||
**Note:** Version bump only for package @certd/basic
|
||||
|
||||
## [1.37.2](https://github.com/certd/certd/compare/v1.37.1...v1.37.2) (2025-10-14)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
@@ -1 +1 @@
|
||||
22:48
|
||||
01:10
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/basic",
|
||||
"private": false,
|
||||
"version": "1.37.2",
|
||||
"version": "1.37.3",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.js",
|
||||
@@ -46,5 +46,5 @@
|
||||
"tslib": "^2.8.1",
|
||||
"typescript": "^5.4.2"
|
||||
},
|
||||
"gitHead": "c725cee0445dbe1ebd1b6588373bde31697113da"
|
||||
"gitHead": "e1daaf07ce2fda6ce44998d65f8a989fc6af88db"
|
||||
}
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
export * from './utils/index.js';
|
||||
export * from './utils/util.id.js';
|
||||
export * from "./utils/index.js";
|
||||
|
||||
@@ -37,6 +37,9 @@ import { mitter } from "./util.mitter.js";
|
||||
|
||||
import * as request from "./util.request.js";
|
||||
export * from "./util.cache.js";
|
||||
|
||||
export * from "./util.id.js";
|
||||
|
||||
export const utils = {
|
||||
sleep,
|
||||
http,
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.37.3](https://github.com/certd/certd/compare/v1.37.2...v1.37.3) (2025-10-24)
|
||||
|
||||
**Note:** Version bump only for package @certd/pipeline
|
||||
|
||||
## [1.37.2](https://github.com/certd/certd/compare/v1.37.1...v1.37.2) (2025-10-14)
|
||||
|
||||
**Note:** Version bump only for package @certd/pipeline
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/pipeline",
|
||||
"private": false,
|
||||
"version": "1.37.2",
|
||||
"version": "1.37.3",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.js",
|
||||
@@ -18,8 +18,8 @@
|
||||
"compile": "tsc --skipLibCheck --watch"
|
||||
},
|
||||
"dependencies": {
|
||||
"@certd/basic": "^1.37.2",
|
||||
"@certd/plus-core": "^1.37.2",
|
||||
"@certd/basic": "^1.37.3",
|
||||
"@certd/plus-core": "^1.37.3",
|
||||
"dayjs": "^1.11.7",
|
||||
"lodash-es": "^4.17.21",
|
||||
"reflect-metadata": "^0.1.13"
|
||||
@@ -45,5 +45,5 @@
|
||||
"tslib": "^2.8.1",
|
||||
"typescript": "^5.4.2"
|
||||
},
|
||||
"gitHead": "c725cee0445dbe1ebd1b6588373bde31697113da"
|
||||
"gitHead": "e1daaf07ce2fda6ce44998d65f8a989fc6af88db"
|
||||
}
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.37.3](https://github.com/certd/certd/compare/v1.37.2...v1.37.3) (2025-10-24)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-huawei
|
||||
|
||||
## [1.37.2](https://github.com/certd/certd/compare/v1.37.1...v1.37.2) (2025-10-14)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-huawei
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/lib-huawei",
|
||||
"private": false,
|
||||
"version": "1.37.2",
|
||||
"version": "1.37.3",
|
||||
"main": "./dist/bundle.js",
|
||||
"module": "./dist/bundle.js",
|
||||
"types": "./dist/d/index.d.ts",
|
||||
@@ -24,5 +24,5 @@
|
||||
"prettier": "^2.8.8",
|
||||
"tslib": "^2.8.1"
|
||||
},
|
||||
"gitHead": "c725cee0445dbe1ebd1b6588373bde31697113da"
|
||||
"gitHead": "e1daaf07ce2fda6ce44998d65f8a989fc6af88db"
|
||||
}
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.37.3](https://github.com/certd/certd/compare/v1.37.2...v1.37.3) (2025-10-24)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-iframe
|
||||
|
||||
## [1.37.2](https://github.com/certd/certd/compare/v1.37.1...v1.37.2) (2025-10-14)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-iframe
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/lib-iframe",
|
||||
"private": false,
|
||||
"version": "1.37.2",
|
||||
"version": "1.37.3",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.js",
|
||||
@@ -31,5 +31,5 @@
|
||||
"tslib": "^2.8.1",
|
||||
"typescript": "^5.4.2"
|
||||
},
|
||||
"gitHead": "c725cee0445dbe1ebd1b6588373bde31697113da"
|
||||
"gitHead": "e1daaf07ce2fda6ce44998d65f8a989fc6af88db"
|
||||
}
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.37.3](https://github.com/certd/certd/compare/v1.37.2...v1.37.3) (2025-10-24)
|
||||
|
||||
**Note:** Version bump only for package @certd/jdcloud
|
||||
|
||||
## [1.37.2](https://github.com/certd/certd/compare/v1.37.1...v1.37.2) (2025-10-14)
|
||||
|
||||
**Note:** Version bump only for package @certd/jdcloud
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@certd/jdcloud",
|
||||
"version": "1.37.2",
|
||||
"version": "1.37.3",
|
||||
"description": "jdcloud openApi sdk",
|
||||
"main": "./dist/bundle.js",
|
||||
"module": "./dist/bundle.js",
|
||||
@@ -61,5 +61,5 @@
|
||||
"fetch"
|
||||
]
|
||||
},
|
||||
"gitHead": "c725cee0445dbe1ebd1b6588373bde31697113da"
|
||||
"gitHead": "e1daaf07ce2fda6ce44998d65f8a989fc6af88db"
|
||||
}
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.37.3](https://github.com/certd/certd/compare/v1.37.2...v1.37.3) (2025-10-24)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-k8s
|
||||
|
||||
## [1.37.2](https://github.com/certd/certd/compare/v1.37.1...v1.37.2) (2025-10-14)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-k8s
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/lib-k8s",
|
||||
"private": false,
|
||||
"version": "1.37.2",
|
||||
"version": "1.37.3",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.js",
|
||||
@@ -17,7 +17,7 @@
|
||||
"pub": "npm publish"
|
||||
},
|
||||
"dependencies": {
|
||||
"@certd/basic": "^1.37.2",
|
||||
"@certd/basic": "^1.37.3",
|
||||
"@kubernetes/client-node": "0.21.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -32,5 +32,5 @@
|
||||
"tslib": "^2.8.1",
|
||||
"typescript": "^5.4.2"
|
||||
},
|
||||
"gitHead": "c725cee0445dbe1ebd1b6588373bde31697113da"
|
||||
"gitHead": "e1daaf07ce2fda6ce44998d65f8a989fc6af88db"
|
||||
}
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.37.3](https://github.com/certd/certd/compare/v1.37.2...v1.37.3) (2025-10-24)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-server
|
||||
|
||||
## [1.37.2](https://github.com/certd/certd/compare/v1.37.1...v1.37.2) (2025-10-14)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-server
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@certd/lib-server",
|
||||
"version": "1.37.2",
|
||||
"version": "1.37.3",
|
||||
"description": "midway with flyway, sql upgrade way ",
|
||||
"private": false,
|
||||
"type": "module",
|
||||
@@ -28,11 +28,11 @@
|
||||
],
|
||||
"license": "AGPL",
|
||||
"dependencies": {
|
||||
"@certd/acme-client": "^1.37.2",
|
||||
"@certd/basic": "^1.37.2",
|
||||
"@certd/pipeline": "^1.37.2",
|
||||
"@certd/plugin-lib": "^1.37.2",
|
||||
"@certd/plus-core": "^1.37.2",
|
||||
"@certd/acme-client": "^1.37.3",
|
||||
"@certd/basic": "^1.37.3",
|
||||
"@certd/pipeline": "^1.37.3",
|
||||
"@certd/plugin-lib": "^1.37.3",
|
||||
"@certd/plus-core": "^1.37.3",
|
||||
"@midwayjs/cache": "3.14.0",
|
||||
"@midwayjs/core": "3.20.11",
|
||||
"@midwayjs/i18n": "3.20.13",
|
||||
@@ -64,5 +64,5 @@
|
||||
"typeorm": "^0.3.11",
|
||||
"typescript": "^5.4.2"
|
||||
},
|
||||
"gitHead": "c725cee0445dbe1ebd1b6588373bde31697113da"
|
||||
"gitHead": "e1daaf07ce2fda6ce44998d65f8a989fc6af88db"
|
||||
}
|
||||
|
||||
@@ -47,4 +47,12 @@ export abstract class BaseController {
|
||||
}
|
||||
return user;
|
||||
}
|
||||
|
||||
isAdmin() {
|
||||
const roleIds: number[] = this.ctx?.user?.roles;
|
||||
if (roleIds?.includes(1)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -37,6 +37,15 @@ export class SysPublicSettings extends BaseSettings {
|
||||
//验证码类型
|
||||
captchaType?: string;
|
||||
captchaAddonId?:number;
|
||||
|
||||
|
||||
|
||||
//流水线是否启用有效期
|
||||
pipelineValidTimeEnabled?: boolean = false;
|
||||
|
||||
//证书域名添加到监控
|
||||
certDomainAddToMonitorEnabled?: boolean = false;
|
||||
|
||||
}
|
||||
|
||||
export class SysPrivateSettings extends BaseSettings {
|
||||
@@ -51,6 +60,8 @@ export class SysPrivateSettings extends BaseSettings {
|
||||
dnsResultOrder? = '';
|
||||
commonCnameEnabled?: boolean = true;
|
||||
|
||||
httpRequestTimeout?: number = 30;
|
||||
|
||||
sms?: {
|
||||
type?: string;
|
||||
config?: any;
|
||||
@@ -214,3 +225,4 @@ export class SysSafeSetting extends BaseSettings {
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.37.3](https://github.com/certd/certd/compare/v1.37.2...v1.37.3) (2025-10-24)
|
||||
|
||||
**Note:** Version bump only for package @certd/midway-flyway-js
|
||||
|
||||
## [1.37.2](https://github.com/certd/certd/compare/v1.37.1...v1.37.2) (2025-10-14)
|
||||
|
||||
**Note:** Version bump only for package @certd/midway-flyway-js
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@certd/midway-flyway-js",
|
||||
"version": "1.37.2",
|
||||
"version": "1.37.3",
|
||||
"description": "midway with flyway, sql upgrade way ",
|
||||
"private": false,
|
||||
"type": "module",
|
||||
@@ -46,5 +46,5 @@
|
||||
"typeorm": "^0.3.11",
|
||||
"typescript": "^5.4.2"
|
||||
},
|
||||
"gitHead": "c725cee0445dbe1ebd1b6588373bde31697113da"
|
||||
"gitHead": "e1daaf07ce2fda6ce44998d65f8a989fc6af88db"
|
||||
}
|
||||
|
||||
@@ -3,6 +3,12 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.37.3](https://github.com/certd/certd/compare/v1.37.2...v1.37.3) (2025-10-24)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 修复并发情况下证书申请日志混乱的bug ([bb2714f](https://github.com/certd/certd/commit/bb2714ff241f9db4a71d805b23a1b0f9f2f6413a))
|
||||
|
||||
## [1.37.2](https://github.com/certd/certd/compare/v1.37.1...v1.37.2) (2025-10-14)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/plugin-cert",
|
||||
"private": false,
|
||||
"version": "1.37.2",
|
||||
"version": "1.37.3",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -17,10 +17,10 @@
|
||||
"compile": "tsc --skipLibCheck --watch"
|
||||
},
|
||||
"dependencies": {
|
||||
"@certd/acme-client": "^1.37.2",
|
||||
"@certd/basic": "^1.37.2",
|
||||
"@certd/pipeline": "^1.37.2",
|
||||
"@certd/plugin-lib": "^1.37.2",
|
||||
"@certd/acme-client": "^1.37.3",
|
||||
"@certd/basic": "^1.37.3",
|
||||
"@certd/pipeline": "^1.37.3",
|
||||
"@certd/plugin-lib": "^1.37.3",
|
||||
"@google-cloud/publicca": "^1.3.0",
|
||||
"dayjs": "^1.11.7",
|
||||
"jszip": "^3.10.1",
|
||||
@@ -43,5 +43,5 @@
|
||||
"tslib": "^2.8.1",
|
||||
"typescript": "^5.4.2"
|
||||
},
|
||||
"gitHead": "c725cee0445dbe1ebd1b6588373bde31697113da"
|
||||
"gitHead": "e1daaf07ce2fda6ce44998d65f8a989fc6af88db"
|
||||
}
|
||||
|
||||
@@ -82,9 +82,9 @@ export class AcmeService {
|
||||
this.sslProvider = options.sslProvider || "letsencrypt";
|
||||
this.eab = options.eab;
|
||||
this.skipLocalVerify = options.skipLocalVerify ?? false;
|
||||
acme.setLogger((message: any, ...args: any[]) => {
|
||||
this.logger.info(message, ...args);
|
||||
});
|
||||
// acme.setLogger((message: any, ...args: any[]) => {
|
||||
// this.logger.info(message, ...args);
|
||||
// });
|
||||
}
|
||||
|
||||
async getAccountConfig(email: string, urlMapping: UrlMapping): Promise<any> {
|
||||
@@ -155,6 +155,7 @@ export class AcmeService {
|
||||
backoffMax: 10000,
|
||||
urlMapping,
|
||||
signal: this.options.signal,
|
||||
logger: this.logger,
|
||||
});
|
||||
|
||||
if (conf.accountUrl == null) {
|
||||
|
||||
@@ -3,6 +3,12 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.37.3](https://github.com/certd/certd/compare/v1.37.2...v1.37.3) (2025-10-24)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* ssh 增加禁止-i参数提示 ([3a8931f](https://github.com/certd/certd/commit/3a8931feeffd7157163ff7d46b693e5e1a434b9c))
|
||||
|
||||
## [1.37.2](https://github.com/certd/certd/compare/v1.37.1...v1.37.2) (2025-10-14)
|
||||
|
||||
**Note:** Version bump only for package @certd/plugin-lib
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/plugin-lib",
|
||||
"private": false,
|
||||
"version": "1.37.2",
|
||||
"version": "1.37.3",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -22,8 +22,8 @@
|
||||
"@alicloud/pop-core": "^1.7.10",
|
||||
"@alicloud/tea-util": "^1.4.10",
|
||||
"@aws-sdk/client-s3": "^3.787.0",
|
||||
"@certd/basic": "^1.37.2",
|
||||
"@certd/pipeline": "^1.37.2",
|
||||
"@certd/basic": "^1.37.3",
|
||||
"@certd/pipeline": "^1.37.3",
|
||||
"@kubernetes/client-node": "0.21.0",
|
||||
"ali-oss": "^6.22.0",
|
||||
"basic-ftp": "^5.0.5",
|
||||
@@ -53,5 +53,5 @@
|
||||
"tslib": "^2.8.1",
|
||||
"typescript": "^5.4.2"
|
||||
},
|
||||
"gitHead": "c725cee0445dbe1ebd1b6588373bde31697113da"
|
||||
"gitHead": "e1daaf07ce2fda6ce44998d65f8a989fc6af88db"
|
||||
}
|
||||
|
||||
@@ -7,4 +7,4 @@ export * from "./qiniu/index.js";
|
||||
export * from "./ctyun/index.js";
|
||||
export * from "./oss/index.js";
|
||||
export * from "./s3/index.js";
|
||||
export * from "./lib/index.js";
|
||||
export * from "./lib/index.js";
|
||||
@@ -188,6 +188,11 @@ export class AsyncSsh2Client {
|
||||
// script += "\r\nexit\r\n";
|
||||
// //保证windows下正常退出
|
||||
// }
|
||||
|
||||
if (script.includes(" -i ")) {
|
||||
this.logger.warn("不支持交互式命令,请不要使用-i参数");
|
||||
}
|
||||
|
||||
return safePromise((resolve, reject) => {
|
||||
this.logger.info(`执行命令:[${this.connConf.host}][exec]: \n` + script);
|
||||
// pty 伪终端,window下的输出会带上conhost.exe之类的多余的字符串,影响返回结果判断
|
||||
|
||||
@@ -3,6 +3,16 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.37.3](https://github.com/certd/certd/compare/v1.37.2...v1.37.3) (2025-10-24)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 注册页面增加手机注册tab页签 ([6b2f1fc](https://github.com/certd/certd/commit/6b2f1fcd3e058061b814c3331cda8ce1b2d80d73))
|
||||
* 流水线创建时支持添加到证书监控 ([59ba408](https://github.com/certd/certd/commit/59ba4080706548828ef1c0a9cd893c1c9a7d591f))
|
||||
* 流水线支持有效期设置 ([911e69e](https://github.com/certd/certd/commit/911e69e3bc0cdd48b62953b5d0981d640fc1f8ac))
|
||||
* 站点证书监控增加导出和分组功能 ([2ed12c4](https://github.com/certd/certd/commit/2ed12c429eb58274a4f9dd0ed3b66e160d283ded))
|
||||
* 证书监控增加批量删除 ([e578c52](https://github.com/certd/certd/commit/e578c52fdf2f838038062aa4209b655fbae461fb))
|
||||
|
||||
## [1.37.2](https://github.com/certd/certd/compare/v1.37.1...v1.37.2) (2025-10-14)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@certd/ui-client",
|
||||
"version": "1.37.2",
|
||||
"version": "1.37.3",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite --open",
|
||||
@@ -106,8 +106,8 @@
|
||||
"zod-defaults": "^0.1.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@certd/lib-iframe": "^1.37.2",
|
||||
"@certd/pipeline": "^1.37.2",
|
||||
"@certd/lib-iframe": "^1.37.3",
|
||||
"@certd/pipeline": "^1.37.3",
|
||||
"@rollup/plugin-commonjs": "^25.0.7",
|
||||
"@rollup/plugin-node-resolve": "^15.2.3",
|
||||
"@types/chai": "^4.3.12",
|
||||
|
||||
@@ -57,6 +57,7 @@ export default {
|
||||
suiteBuy: "Suite Purchase",
|
||||
myTrade: "My Orders",
|
||||
paymentReturn: "Payment Return",
|
||||
hasExpired: "Expired",
|
||||
user: {
|
||||
greeting: "Hello",
|
||||
profile: "Account Info",
|
||||
@@ -136,10 +137,16 @@ export default {
|
||||
triggerType: "Trigger Type",
|
||||
pipelineId: "Pipeline Id",
|
||||
},
|
||||
|
||||
pi: {
|
||||
validTime: "Piepline Valid Time",
|
||||
validTimeHelper: "Not filled in means permanent validity",
|
||||
},
|
||||
types: {
|
||||
certApply: "Certificate Application",
|
||||
certUpload: "Certificate Upload",
|
||||
certApply: "Cert Apply",
|
||||
certUpload: "Cert Upload",
|
||||
custom: "Custom",
|
||||
template: "Template",
|
||||
},
|
||||
myPipelines: "My Pipelines",
|
||||
selectedCount: "Selected {count} items",
|
||||
@@ -224,9 +231,13 @@ export default {
|
||||
notificationWhen: "Notification Timing",
|
||||
notificationHelper: "Get real-time alerts when the task fails",
|
||||
groupIdTitle: "Pipeline Group",
|
||||
|
||||
addToMonitorEnabled: "Add to Cert Monitor",
|
||||
addToMonitorDomains: "Add to Monitor Domains",
|
||||
},
|
||||
notificationDefault: "Use Default Notification",
|
||||
monitor: {
|
||||
remark: "Remark",
|
||||
title: "Site Certificate Monitoring",
|
||||
description: "Check website certificates' expiration at 0:00 daily; reminders sent 10 days before expiration (using default notification channel);",
|
||||
settingLink: "Site Monitoring Settings",
|
||||
@@ -248,6 +259,7 @@ export default {
|
||||
certDomains: "Certificate Domains",
|
||||
certProvider: "Issuer",
|
||||
certStatus: "Certificate Status",
|
||||
error: "Error",
|
||||
status: {
|
||||
ok: "Valid",
|
||||
expired: "Expired",
|
||||
@@ -292,7 +304,7 @@ export default {
|
||||
},
|
||||
domainList: {
|
||||
title: "Domain List",
|
||||
helper: "Format: domain:port:name, one per line. Port and name are optional.\nExamples:\nwww.baidu.com:443:Baidu\nwww.taobao.com::Taobao\nwww.google.com",
|
||||
helper: "Format: domain:port:name:remark, one per line. Port and name are optional.\nExamples:\nwww.baidu.com:443:Baidu:remarkText\nwww.taobao.com::Taobao\nwww.google.com",
|
||||
required: "Please enter domains to import",
|
||||
placeholder: "www.baidu.com:443:Baidu\nwww.taobao.com::Taobao\nwww.google.com\n",
|
||||
},
|
||||
@@ -719,8 +731,18 @@ export default {
|
||||
addonName: "Name",
|
||||
addonNameHelper: "Fill freely, helps to distinguish when multiple same type exist",
|
||||
addonTypeSelect: "Select type",
|
||||
dates: {
|
||||
years: "{count} years",
|
||||
months: "{count} months",
|
||||
},
|
||||
sys: {
|
||||
setting: {
|
||||
baseSetting: "Base Settings",
|
||||
registerSetting: "Register Settings",
|
||||
safeSetting: "Safe Settings",
|
||||
paymentSetting: "Payment Settings",
|
||||
captchaSetting: "Captcha Setting",
|
||||
pipelineSetting: "Pipeline Settings",
|
||||
showRunStrategy: "Show RunStrategy",
|
||||
showRunStrategyHelper: "Allow modify the run strategy of the task",
|
||||
|
||||
@@ -730,11 +752,11 @@ export default {
|
||||
captchaTest: "Captcha Test",
|
||||
// 保存后再点击测试,请务必测试通过了,再开启登录验证码
|
||||
captchaTestHelper: "Save and click test, please make sure the test is passed before enabling login captcha",
|
||||
baseSetting: "Base Settings",
|
||||
registerSetting: "Register Settings",
|
||||
safeSetting: "Safe Settings",
|
||||
paymentSetting: "Payment Settings",
|
||||
captchaSetting: "Captcha Setting",
|
||||
|
||||
pipelineValidTimeEnabled: "Enable Pipeline Valid Time",
|
||||
pipelineValidTimeEnabledHelper: "Whether to enable the valid time of the pipeline",
|
||||
certDomainAddToMonitorEnabled: "Add Domain to Certificate Monitor",
|
||||
certDomainAddToMonitorEnabledHelper: "Whether to add the domain to the certificate monitor",
|
||||
},
|
||||
},
|
||||
modal: {
|
||||
|
||||
@@ -62,6 +62,7 @@ export default {
|
||||
suiteBuy: "套餐购买",
|
||||
myTrade: "我的订单",
|
||||
paymentReturn: "支付返回",
|
||||
hasExpired: "已过期",
|
||||
|
||||
user: {
|
||||
greeting: "您好",
|
||||
@@ -142,10 +143,15 @@ export default {
|
||||
triggerType: "触发类型",
|
||||
pipelineId: "流水线Id",
|
||||
},
|
||||
pi: {
|
||||
validTime: "流水线有效期",
|
||||
validTimeHelper: "不填则为永久有效",
|
||||
},
|
||||
types: {
|
||||
certApply: "证书申请",
|
||||
certUpload: "证书上传",
|
||||
custom: "自定义",
|
||||
template: "模版",
|
||||
},
|
||||
myPipelines: "我的流水线",
|
||||
selectedCount: "已选择 {count} 项",
|
||||
@@ -229,9 +235,12 @@ export default {
|
||||
notificationWhen: "通知时机",
|
||||
notificationHelper: "任务执行失败实时提醒",
|
||||
groupIdTitle: "流水线分组",
|
||||
addToMonitorEnabled: "添加到证书监控",
|
||||
addToMonitorDomains: "添加到监控域名",
|
||||
},
|
||||
notificationDefault: "使用默认通知",
|
||||
monitor: {
|
||||
remark: "备注",
|
||||
title: "站点证书监控",
|
||||
description: "每天0点,检查网站证书的过期时间,到期前10天时将发出提醒(使用默认通知渠道);",
|
||||
settingLink: "站点监控设置",
|
||||
@@ -253,6 +262,7 @@ export default {
|
||||
certDomains: "证书域名",
|
||||
certProvider: "颁发机构",
|
||||
certStatus: "证书状态",
|
||||
error: "错误信息",
|
||||
status: {
|
||||
ok: "正常",
|
||||
expired: "过期",
|
||||
@@ -297,9 +307,9 @@ export default {
|
||||
},
|
||||
domainList: {
|
||||
title: "域名列表",
|
||||
helper: "格式【域名:端口:名称】,一行一个,其中端口、名称可以省略\n比如:\nwww.baidu.com:443:百度\nwww.taobao.com::淘宝\nwww.google.com",
|
||||
helper: "格式【域名:端口:名称:备注】,一行一个,其中端口、名称、备注可以省略\n比如:\nwww.baidu.com:443:百度:备注文本\nwww.taobao.com::淘宝\nwww.google.com",
|
||||
required: "请输入要导入的域名",
|
||||
placeholder: "www.baidu.com:443:百度\nwww.taobao.com::淘宝\nwww.google.com\n",
|
||||
placeholder: "www.baidu.com:443:百度:备注文本\nwww.taobao.com::淘宝\nwww.google.com\n",
|
||||
},
|
||||
accountInfo: "账号信息",
|
||||
securitySettings: "认证安全设置",
|
||||
@@ -721,8 +731,19 @@ export default {
|
||||
copyPipelineConfig: "复制该流水线配置作为模板来源",
|
||||
pipeline: "流水线",
|
||||
},
|
||||
dates: {
|
||||
years: "{count}年",
|
||||
months: "{count}月",
|
||||
},
|
||||
sys: {
|
||||
setting: {
|
||||
baseSetting: "基本设置",
|
||||
registerSetting: "注册设置",
|
||||
safeSetting: "安全设置",
|
||||
paymentSetting: "支付设置",
|
||||
captchaSetting: "验证码设置",
|
||||
pipelineSetting: "流水线设置",
|
||||
|
||||
showRunStrategy: "显示运行策略选择",
|
||||
showRunStrategyHelper: "任务设置中是否允许选择运行策略",
|
||||
|
||||
@@ -731,11 +752,11 @@ export default {
|
||||
captchaType: "验证码配置",
|
||||
captchaTest: "测试验证码",
|
||||
captchaTestHelper: "保存后再点击测试,请务必测试通过了,再开启登录验证码",
|
||||
baseSetting: "基本设置",
|
||||
registerSetting: "注册设置",
|
||||
safeSetting: "安全设置",
|
||||
paymentSetting: "支付设置",
|
||||
captchaSetting: "验证码设置",
|
||||
|
||||
pipelineValidTimeEnabled: "启用流水线有效期",
|
||||
pipelineValidTimeEnabledHelper: "是否启用流水线有效期",
|
||||
certDomainAddToMonitorEnabled: "证书域名添加到证书监控",
|
||||
certDomainAddToMonitorEnabledHelper: "创建证书流水线时是否可以选择将域名添加到证书监控",
|
||||
},
|
||||
},
|
||||
modal: {
|
||||
|
||||
@@ -50,6 +50,12 @@ export type SysPublicSetting = {
|
||||
captchaEnabled?: boolean;
|
||||
captchaType?: number;
|
||||
captchaAddonId?: number;
|
||||
|
||||
//流水线是否启用有效期
|
||||
pipelineValidTimeEnabled?: boolean;
|
||||
|
||||
//证书域名添加到监控
|
||||
certDomainAddToMonitorEnabled?: boolean;
|
||||
};
|
||||
export type SuiteSetting = {
|
||||
enabled?: boolean;
|
||||
@@ -63,6 +69,9 @@ export type SysPrivateSetting = {
|
||||
type?: string;
|
||||
config?: any;
|
||||
};
|
||||
|
||||
//http请求超时时间
|
||||
httpRequestTimeout?: number;
|
||||
};
|
||||
export type SysInstallInfo = {
|
||||
siteId: string;
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
width: 12px !important;
|
||||
height: 12px !important;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
width: 8px;
|
||||
width: 12px !important;
|
||||
background: rgba(#101f1c, 0.1);
|
||||
-webkit-border-radius: 2em;
|
||||
-moz-border-radius: 2em;
|
||||
border-radius: 2em;
|
||||
-webkit-border-radius: 4em;
|
||||
-moz-border-radius: 4em;
|
||||
border-radius: 4em;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
// background-color: rgba(#101F1C, 0.5);
|
||||
background-clip: padding-box;
|
||||
min-height: 28px;
|
||||
-webkit-border-radius: 2em;
|
||||
-moz-border-radius: 2em;
|
||||
border-radius: 2em;
|
||||
-webkit-border-radius: 4em;
|
||||
-moz-border-radius: 4em;
|
||||
border-radius: 4em;
|
||||
background-color: #b3b3b3;
|
||||
box-shadow: 0px 1px 1px #eee inset;
|
||||
}
|
||||
|
||||
64
packages/ui/certd-client/src/views/certd/basic/group/api.ts
Normal file
64
packages/ui/certd-client/src/views/certd/basic/group/api.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
import { dict } from "@fast-crud/fast-crud";
|
||||
import { request } from "/src/api/service";
|
||||
|
||||
export function createApi() {
|
||||
const apiPrefix = "/basic/group";
|
||||
return {
|
||||
async GetList(query: any) {
|
||||
return await request({
|
||||
url: apiPrefix + "/page",
|
||||
method: "post",
|
||||
data: query,
|
||||
});
|
||||
},
|
||||
|
||||
async AddObj(obj: any) {
|
||||
return await request({
|
||||
url: apiPrefix + "/add",
|
||||
method: "post",
|
||||
data: obj,
|
||||
});
|
||||
},
|
||||
|
||||
async UpdateObj(obj: any) {
|
||||
return await request({
|
||||
url: apiPrefix + "/update",
|
||||
method: "post",
|
||||
data: obj,
|
||||
});
|
||||
},
|
||||
|
||||
async DelObj(id: number) {
|
||||
return await request({
|
||||
url: apiPrefix + "/delete",
|
||||
method: "post",
|
||||
params: { id },
|
||||
});
|
||||
},
|
||||
|
||||
async GetObj(id: number) {
|
||||
return await request({
|
||||
url: apiPrefix + "/info",
|
||||
method: "post",
|
||||
params: { id },
|
||||
});
|
||||
},
|
||||
async ListAll(type: string) {
|
||||
return await request({
|
||||
url: apiPrefix + "/all",
|
||||
method: "post",
|
||||
params: { type },
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export const pipelineGroupApi = createApi();
|
||||
|
||||
export function createGroupDictRef(type: string) {
|
||||
return dict({
|
||||
url: "/basic/group/all?type=" + type,
|
||||
value: "id",
|
||||
label: "name",
|
||||
});
|
||||
}
|
||||
142
packages/ui/certd-client/src/views/certd/basic/group/crud.tsx
Normal file
142
packages/ui/certd-client/src/views/certd/basic/group/crud.tsx
Normal file
@@ -0,0 +1,142 @@
|
||||
import { useI18n } from "/src/locales";
|
||||
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
|
||||
import { pipelineGroupApi } from "./api";
|
||||
import { ref } from "vue";
|
||||
|
||||
export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
|
||||
const { t } = useI18n();
|
||||
const api = pipelineGroupApi;
|
||||
const typeRef = ref(context.type);
|
||||
|
||||
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
|
||||
return await api.GetList(query);
|
||||
};
|
||||
const editRequest = async (req: EditReq) => {
|
||||
const { form, row } = req;
|
||||
form.id = row.id;
|
||||
const res = await api.UpdateObj(form);
|
||||
return res;
|
||||
};
|
||||
const delRequest = async (req: DelReq) => {
|
||||
const { row } = req;
|
||||
return await api.DelObj(row.id);
|
||||
};
|
||||
|
||||
const addRequest = async (req: AddReq) => {
|
||||
const { form } = req;
|
||||
form.type = typeRef.value;
|
||||
const res = await api.AddObj(form);
|
||||
return res;
|
||||
};
|
||||
|
||||
return {
|
||||
crudOptions: {
|
||||
settings: {
|
||||
plugins: {
|
||||
mobile: {
|
||||
props: {
|
||||
rowHandle: {
|
||||
width: 160,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
request: {
|
||||
pageRequest,
|
||||
addRequest,
|
||||
editRequest,
|
||||
delRequest,
|
||||
},
|
||||
search: {
|
||||
initialForm: {
|
||||
type: typeRef.value,
|
||||
},
|
||||
},
|
||||
form: {
|
||||
labelCol: {
|
||||
//固定label宽度
|
||||
span: null,
|
||||
style: {
|
||||
width: "100px",
|
||||
},
|
||||
},
|
||||
col: {
|
||||
span: 22,
|
||||
},
|
||||
wrapper: {
|
||||
width: 600,
|
||||
},
|
||||
},
|
||||
rowHandle: {
|
||||
width: 200,
|
||||
group: {
|
||||
editable: {
|
||||
edit: {
|
||||
text: t("certd.edit"),
|
||||
order: -1,
|
||||
type: "primary",
|
||||
click({ row, index }) {
|
||||
crudExpose.openEdit({
|
||||
index,
|
||||
row,
|
||||
});
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
table: {
|
||||
editable: {
|
||||
enabled: true,
|
||||
mode: "cell",
|
||||
exclusive: true,
|
||||
//排他式激活效果,将其他行的编辑状态触发保存
|
||||
exclusiveEffect: "save", //自动保存其他行编辑状态,cancel = 自动关闭其他行编辑状态
|
||||
async updateCell(opts) {
|
||||
const { row, key, value } = opts;
|
||||
//如果是添加,需要返回{[rowKey]:xxx},比如:{id:2}
|
||||
return await api.UpdateObj({ id: row.id, [key]: value });
|
||||
},
|
||||
},
|
||||
},
|
||||
columns: {
|
||||
id: {
|
||||
title: "ID",
|
||||
key: "id",
|
||||
type: "number",
|
||||
search: {
|
||||
show: true,
|
||||
},
|
||||
column: {
|
||||
width: 100,
|
||||
editable: {
|
||||
disabled: true,
|
||||
},
|
||||
},
|
||||
form: {
|
||||
show: false,
|
||||
},
|
||||
},
|
||||
name: {
|
||||
title: t("certd.groupName"),
|
||||
search: {
|
||||
show: true,
|
||||
},
|
||||
type: "text",
|
||||
form: {
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: t("certd.enterGroupName"),
|
||||
},
|
||||
],
|
||||
},
|
||||
column: {
|
||||
width: 400,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<template>
|
||||
<div class="pi-group-selector flex full-w">
|
||||
<div class="flex-1">
|
||||
<fs-dict-select :value="modelValue" :dict="groupDictRef" :allow-clear="true" @update:value="doUpdate"></fs-dict-select>
|
||||
</div>
|
||||
|
||||
<fs-table-select
|
||||
class="flex-0"
|
||||
:create-crud-options="createCrudOptions"
|
||||
:crud-options-override="{
|
||||
search: { show: false, initialForm: { type: props.type } },
|
||||
table: {
|
||||
scroll: {
|
||||
x: 540,
|
||||
},
|
||||
},
|
||||
}"
|
||||
:model-value="modelValue"
|
||||
:dict="groupDictRef"
|
||||
:show-current="false"
|
||||
:show-select="false"
|
||||
:dialog="{ width: 960 }"
|
||||
:destroy-on-close="false"
|
||||
height="400px"
|
||||
@update:model-value="doUpdate"
|
||||
@dialog-closed="doRefresh"
|
||||
>
|
||||
<template #default="scope">
|
||||
<fs-button class="ml-5" type="primary" icon="ant-design:edit-outlined" @click="scope.open({ context: { type: props.type } })"></fs-button>
|
||||
</template>
|
||||
</fs-table-select>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { createGroupDictRef } from "./api";
|
||||
import createCrudOptions from "./crud";
|
||||
import { dict, FsDictSelect } from "@fast-crud/fast-crud";
|
||||
|
||||
const props = defineProps<{
|
||||
modelValue?: number;
|
||||
type: string;
|
||||
}>();
|
||||
|
||||
defineOptions({
|
||||
name: "GroupSelector",
|
||||
});
|
||||
const groupDictRef = createGroupDictRef(props.type);
|
||||
const emit = defineEmits(["refresh", "update:modelValue", "change"]);
|
||||
function doRefresh() {
|
||||
emit("refresh");
|
||||
groupDictRef.reloadDict();
|
||||
}
|
||||
|
||||
function doUpdate(value: any) {
|
||||
emit("update:modelValue", value);
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,37 @@
|
||||
<template>
|
||||
<fs-page>
|
||||
<template #header>
|
||||
<div class="title">
|
||||
分组管理
|
||||
<span class="sub">流水线分组</span>
|
||||
</div>
|
||||
</template>
|
||||
<fs-crud ref="crudRef" v-bind="crudBinding"> </fs-crud>
|
||||
</fs-page>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, onActivated, onMounted } from "vue";
|
||||
import { useFs } from "@fast-crud/fast-crud";
|
||||
import createCrudOptions from "./crud";
|
||||
|
||||
export default defineComponent({
|
||||
name: "BasicGroupManager",
|
||||
setup() {
|
||||
const { crudBinding, crudRef, crudExpose } = useFs({ createCrudOptions, context: {} });
|
||||
|
||||
// 页面打开后获取列表数据
|
||||
onMounted(() => {
|
||||
crudExpose.doRefresh();
|
||||
});
|
||||
onActivated(() => {
|
||||
crudExpose.doRefresh();
|
||||
});
|
||||
|
||||
return {
|
||||
crudBinding,
|
||||
crudRef,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@@ -35,6 +35,14 @@ export const siteInfoApi = {
|
||||
});
|
||||
},
|
||||
|
||||
async BatchDelObj(ids: number[]) {
|
||||
return await request({
|
||||
url: apiPrefix + "/batchDelete",
|
||||
method: "post",
|
||||
data: { ids },
|
||||
});
|
||||
},
|
||||
|
||||
async GetObj(id: number) {
|
||||
return await request({
|
||||
url: apiPrefix + "/info",
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
// @ts-ignore
|
||||
import { useI18n } from "/src/locales";
|
||||
import { AddReq, ColumnCompositionProps, compute, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
|
||||
import { AddReq, ColumnCompositionProps, ColumnProps, compute, CreateCrudOptionsProps, CreateCrudOptionsRet, DataFormatterContext, DelReq, dict, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
|
||||
import { siteInfoApi } from "./api";
|
||||
import * as settingApi from "./setting/api";
|
||||
import dayjs from "dayjs";
|
||||
import { Modal, notification } from "ant-design-vue";
|
||||
import { message, Modal, notification } from "ant-design-vue";
|
||||
import { useSettingStore } from "/@/store/settings";
|
||||
import { mySuiteApi } from "/@/views/certd/suite/mine/api";
|
||||
import { mitter } from "/@/utils/util.mitt";
|
||||
import { useSiteIpMonitor } from "./ip/use";
|
||||
import { useSiteImport } from "/@/views/certd/monitor/site/use";
|
||||
import { ref } from "vue";
|
||||
|
||||
import GroupSelector from "../../basic/group/group-selector.vue";
|
||||
import { createGroupDictRef } from "../../basic/group/api";
|
||||
export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
|
||||
const { t } = useI18n();
|
||||
const api = siteInfoApi;
|
||||
@@ -57,6 +58,27 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
}
|
||||
loadSetting();
|
||||
|
||||
const selectedRowKeys = ref([]);
|
||||
|
||||
const handleBatchDelete = () => {
|
||||
if (selectedRowKeys.value?.length > 0) {
|
||||
Modal.confirm({
|
||||
title: "确认",
|
||||
content: `确定要批量删除这${selectedRowKeys.value.length}条记录吗`,
|
||||
async onOk() {
|
||||
await api.BatchDelObj(selectedRowKeys.value);
|
||||
message.info("删除成功");
|
||||
crudExpose.doRefresh();
|
||||
selectedRowKeys.value = [];
|
||||
},
|
||||
});
|
||||
} else {
|
||||
message.error("请先勾选记录");
|
||||
}
|
||||
};
|
||||
|
||||
context.handleBatchDelete = handleBatchDelete;
|
||||
|
||||
function checkAll() {
|
||||
Modal.confirm({
|
||||
title: t("certd.monitor.confirmTitle"), // "确认"
|
||||
@@ -70,6 +92,16 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const GroupTypeSite = "site";
|
||||
const groupDictRef = createGroupDictRef(GroupTypeSite);
|
||||
|
||||
function getDefaultGroupId() {
|
||||
const searchFrom = crudExpose.getSearchValidatedFormData();
|
||||
if (searchFrom.groupId) {
|
||||
return searchFrom.groupId;
|
||||
}
|
||||
}
|
||||
return {
|
||||
id: "siteMonitorCrud",
|
||||
crudOptions: {
|
||||
@@ -79,6 +111,68 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
editRequest,
|
||||
delRequest,
|
||||
},
|
||||
tabs: {
|
||||
name: "groupId",
|
||||
show: true,
|
||||
},
|
||||
toolbar: {
|
||||
buttons: {
|
||||
export: {
|
||||
show: true,
|
||||
},
|
||||
},
|
||||
export: {
|
||||
dataFrom: "search",
|
||||
columnFilter: (col: ColumnProps) => {
|
||||
//列过滤器,返回true则导出该列
|
||||
//例如: 只导出show=true的列
|
||||
return col.show === true;
|
||||
},
|
||||
dataFormatter: (opts: DataFormatterContext) => {
|
||||
//例如 格式化日期
|
||||
const { row, originalRow, col, exportCol } = opts;
|
||||
const key = col.key;
|
||||
const element = originalRow[key];
|
||||
if (key.includes("Time") && element) {
|
||||
row[key] = dayjs(element).format("YYYY-MM-DD HH:mm:ss");
|
||||
}
|
||||
|
||||
if (col.width) {
|
||||
exportCol.width = col.width / 10;
|
||||
}
|
||||
|
||||
if (col.key === "certInfo" && originalRow?.certProvider) {
|
||||
row[key] = originalRow?.certProvider + " " + originalRow?.certDomains;
|
||||
}
|
||||
|
||||
//参数说明
|
||||
// DataFormatterContext = {row: any,originalRow: any, key: string, col: ColumnProps, exportCol:ExportColumn}
|
||||
// row = 当前行数据
|
||||
// originalRow = 当前行原始数据
|
||||
// key = 当前列的key
|
||||
// col = 当前列的配置
|
||||
// exportCol = 当前列的导出配置
|
||||
},
|
||||
},
|
||||
},
|
||||
pagination: {
|
||||
pageSizeOptions: ["10", "20", "50", "100", "200"],
|
||||
},
|
||||
settings: {
|
||||
plugins: {
|
||||
//这里使用行选择插件,生成行选择crudOptions配置,最终会与crudOptions合并
|
||||
rowSelection: {
|
||||
enabled: true,
|
||||
props: {
|
||||
multiple: true,
|
||||
crossPage: false,
|
||||
selectedRowKeys: () => {
|
||||
return selectedRowKeys;
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
form: {
|
||||
labelCol: {
|
||||
//固定label宽度
|
||||
@@ -122,7 +216,10 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
}
|
||||
}
|
||||
|
||||
await crudExpose.openAdd({});
|
||||
const defaultGroupId = getDefaultGroupId();
|
||||
await crudExpose.openAdd({
|
||||
row: { groupId: defaultGroupId },
|
||||
});
|
||||
},
|
||||
},
|
||||
//导入按钮
|
||||
@@ -131,7 +228,9 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
text: t("certd.monitor.bulkImport"),
|
||||
type: "primary",
|
||||
async click() {
|
||||
const defaultGroupId = getDefaultGroupId();
|
||||
openSiteImportDialog({
|
||||
defaultGroupId,
|
||||
afterSubmit() {
|
||||
crudExpose.doRefresh();
|
||||
},
|
||||
@@ -183,10 +282,10 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
},
|
||||
},
|
||||
},
|
||||
tabs: {
|
||||
name: "disabled",
|
||||
show: true,
|
||||
},
|
||||
// tabs: {
|
||||
// name: "disabled",
|
||||
// show: true,
|
||||
// },
|
||||
columns: {
|
||||
id: {
|
||||
title: "ID",
|
||||
@@ -367,6 +466,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
column: {
|
||||
sorter: true,
|
||||
width: 155,
|
||||
show: false,
|
||||
},
|
||||
},
|
||||
certExpiresTime: {
|
||||
@@ -415,6 +515,46 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
},
|
||||
},
|
||||
},
|
||||
groupId: {
|
||||
title: t("certd.fields.group"),
|
||||
type: "dict-select",
|
||||
search: {
|
||||
show: true,
|
||||
},
|
||||
dict: groupDictRef,
|
||||
form: {
|
||||
component: {
|
||||
name: GroupSelector,
|
||||
vModel: "modelValue",
|
||||
type: GroupTypeSite,
|
||||
onRefresh() {
|
||||
groupDictRef.reloadDict();
|
||||
},
|
||||
},
|
||||
},
|
||||
column: {
|
||||
width: 130,
|
||||
align: "center",
|
||||
component: {
|
||||
color: "auto",
|
||||
},
|
||||
sorter: true,
|
||||
},
|
||||
},
|
||||
remark: {
|
||||
title: t("certd.monitor.remark"),
|
||||
search: {
|
||||
show: false,
|
||||
},
|
||||
type: "text",
|
||||
column: {
|
||||
width: 200,
|
||||
sorter: true,
|
||||
cellRender({ value }) {
|
||||
return <a-tooltip title={value}>{value}</a-tooltip>;
|
||||
},
|
||||
},
|
||||
},
|
||||
lastCheckTime: {
|
||||
title: t("certd.monitor.lastCheckTime"),
|
||||
search: {
|
||||
@@ -582,6 +722,21 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
show: false,
|
||||
},
|
||||
},
|
||||
error: {
|
||||
title: t("certd.monitor.error"),
|
||||
search: {
|
||||
show: false,
|
||||
},
|
||||
type: "text",
|
||||
form: { show: false },
|
||||
column: {
|
||||
width: 200,
|
||||
sorter: true,
|
||||
cellRender({ value }) {
|
||||
return <a-tooltip title={value}>{value}</a-tooltip>;
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -15,23 +15,28 @@
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<fs-crud ref="crudRef" v-bind="crudBinding"> </fs-crud>
|
||||
<fs-crud ref="crudRef" v-bind="crudBinding">
|
||||
<template #pagination-left>
|
||||
<a-tooltip title="批量删除">
|
||||
<fs-button icon="DeleteOutlined" @click="handleBatchDelete"></fs-button>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</fs-crud>
|
||||
</fs-page>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onActivated, onMounted } from "vue";
|
||||
import { useFs } from "@fast-crud/fast-crud";
|
||||
import { onActivated, onMounted } from "vue";
|
||||
import createCrudOptions from "./crud";
|
||||
import { siteInfoApi } from "./api";
|
||||
import { Modal, notification } from "ant-design-vue";
|
||||
import { useI18n } from "/src/locales";
|
||||
|
||||
const { t } = useI18n();
|
||||
defineOptions({
|
||||
name: "SiteCertMonitor",
|
||||
});
|
||||
const { crudBinding, crudRef, crudExpose } = useFs({ createCrudOptions, context: {} });
|
||||
const { crudBinding, crudRef, crudExpose, context } = useFs({ createCrudOptions });
|
||||
|
||||
const handleBatchDelete = context.handleBatchDelete;
|
||||
|
||||
// 页面打开后获取列表数据
|
||||
onMounted(() => {
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { useFormWrapper } from "@fast-crud/fast-crud";
|
||||
import { siteInfoApi } from "./api";
|
||||
import { useI18n } from "/src/locales";
|
||||
|
||||
import GroupSelector from "../../basic/group/group-selector.vue";
|
||||
export function useSiteImport() {
|
||||
const { t } = useI18n();
|
||||
const { openCrudFormDialog } = useFormWrapper();
|
||||
|
||||
async function openSiteImportDialog(opts: { afterSubmit: any }) {
|
||||
const { afterSubmit } = opts;
|
||||
async function openSiteImportDialog(opts: { afterSubmit: any; defaultGroupId?: number }) {
|
||||
const { afterSubmit, defaultGroupId } = opts;
|
||||
await openCrudFormDialog<any>({
|
||||
crudOptions: {
|
||||
columns: {
|
||||
@@ -26,6 +26,21 @@ export function useSiteImport() {
|
||||
},
|
||||
},
|
||||
},
|
||||
groupId: {
|
||||
type: "select",
|
||||
title: t("certd.fields.group"),
|
||||
form: {
|
||||
value: defaultGroupId,
|
||||
component: {
|
||||
name: GroupSelector,
|
||||
vModel: "modelValue",
|
||||
type: "site",
|
||||
},
|
||||
col: {
|
||||
span: 24,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
form: {
|
||||
|
||||
@@ -6,12 +6,13 @@ import { useRouter } from "vue-router";
|
||||
import { compute, CreateCrudOptionsRet, dict, useFormWrapper } from "@fast-crud/fast-crud";
|
||||
import NotificationSelector from "/@/views/certd/notification/notification-selector/index.vue";
|
||||
import { useReference } from "/@/use/use-refrence";
|
||||
import { ref } from "vue";
|
||||
import { computed, ref } from "vue";
|
||||
import * as api from "../api";
|
||||
import { PluginGroup, usePluginStore } from "/@/store/plugin";
|
||||
import { createNotificationApi } from "/@/views/certd/notification/api";
|
||||
import GroupSelector from "../group/group-selector.vue";
|
||||
import { useI18n } from "/src/locales";
|
||||
import { useSettingStore } from "/@/store/settings";
|
||||
|
||||
export function fillPipelineByDefaultForm(pipeline: any, form: any) {
|
||||
const triggers = [];
|
||||
@@ -78,6 +79,7 @@ export function useCertPipelineCreator() {
|
||||
const { openCrudFormDialog } = useFormWrapper();
|
||||
|
||||
const pluginStore = usePluginStore();
|
||||
const settingStore = useSettingStore();
|
||||
const router = useRouter();
|
||||
|
||||
function createCrudOptions(certPlugins: any[], getFormData: any, doSubmit: any): CreateCrudOptionsRet {
|
||||
@@ -251,7 +253,48 @@ export function useCertPipelineCreator() {
|
||||
name: GroupSelector,
|
||||
vModel: "modelValue",
|
||||
},
|
||||
order: 9999,
|
||||
order: 888,
|
||||
},
|
||||
},
|
||||
addToMonitorEnabled: {
|
||||
title: t("certd.pipelineForm.addToMonitorEnabled"),
|
||||
type: "switch",
|
||||
form: {
|
||||
show: computed(() => {
|
||||
return settingStore.isPlus && settingStore.sysPublic?.certDomainAddToMonitorEnabled;
|
||||
}),
|
||||
value: false,
|
||||
component: {
|
||||
name: "a-switch",
|
||||
vModel: "checked",
|
||||
},
|
||||
col: {
|
||||
span: 24,
|
||||
},
|
||||
order: 999,
|
||||
valueChange({ value, form }) {
|
||||
if (value) {
|
||||
form.addToMonitorDomains = form.domains.join("\n").replaceAll("*", "www");
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
addToMonitorDomains: {
|
||||
title: t("certd.pipelineForm.addToMonitorDomains"),
|
||||
type: "text",
|
||||
form: {
|
||||
show: compute(({ form }) => {
|
||||
return form.addToMonitorEnabled;
|
||||
}),
|
||||
component: {
|
||||
name: "a-textarea",
|
||||
vModel: "value",
|
||||
},
|
||||
col: {
|
||||
span: 24,
|
||||
},
|
||||
helper: t("certd.domainList.helper"),
|
||||
order: 999,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -330,6 +373,8 @@ export function useCertPipelineCreator() {
|
||||
keepHistoryCount: 30,
|
||||
type: "cert",
|
||||
groupId,
|
||||
addToMonitorEnabled: form.addToMonitorEnabled,
|
||||
addToMonitorDomains: form.addToMonitorDomains,
|
||||
});
|
||||
if (form.email) {
|
||||
try {
|
||||
|
||||
@@ -466,7 +466,7 @@ export default function ({ crudExpose, context: { groupDictRef, selectedRowKeys
|
||||
},
|
||||
column: {
|
||||
sorter: true,
|
||||
width: 80,
|
||||
width: 100,
|
||||
align: "center",
|
||||
component: {
|
||||
name: "fs-dict-switch",
|
||||
@@ -513,7 +513,7 @@ export default function ({ crudExpose, context: { groupDictRef, selectedRowKeys
|
||||
{ value: "cert", label: t("certd.types.certApply") },
|
||||
{ value: "cert_upload", label: t("certd.types.certUpload") },
|
||||
{ value: "custom", label: t("certd.types.custom") },
|
||||
{ value: "template", label: "模版" },
|
||||
{ value: "template", label: t("certd.types.template") },
|
||||
],
|
||||
}),
|
||||
form: {
|
||||
@@ -522,7 +522,7 @@ export default function ({ crudExpose, context: { groupDictRef, selectedRowKeys
|
||||
},
|
||||
column: {
|
||||
sorter: true,
|
||||
width: 90,
|
||||
width: 110,
|
||||
align: "center",
|
||||
show: true,
|
||||
component: {
|
||||
@@ -555,16 +555,53 @@ export default function ({ crudExpose, context: { groupDictRef, selectedRowKeys
|
||||
sorter: true,
|
||||
},
|
||||
},
|
||||
createTime: {
|
||||
title: t("certd.fields.createTime"),
|
||||
type: "datetime",
|
||||
validTime: {
|
||||
title: t("certd.pi.validTime"),
|
||||
type: "date",
|
||||
form: {
|
||||
show: false,
|
||||
show: computed(() => {
|
||||
return settingStore.isPlus && settingStore.sysPublic.pipelineValidTimeEnabled && userStore.isAdmin;
|
||||
}),
|
||||
helper: t("certd.pi.validTimeHelper"),
|
||||
valueResolve({ form, key, value }) {
|
||||
if (value) {
|
||||
form[key] = value.valueOf();
|
||||
}
|
||||
},
|
||||
valueBuilder({ form, key, value }) {
|
||||
if (value) {
|
||||
form[key] = dayjs(value);
|
||||
}
|
||||
},
|
||||
component: {
|
||||
presets: [
|
||||
{ label: t("certd.dates.months", { count: 3 }), value: dayjs().add(3, "month") },
|
||||
{ label: t("certd.dates.months", { count: 6 }), value: dayjs().add(6, "month") },
|
||||
{ label: t("certd.dates.years", { count: 1 }), value: dayjs().add(1, "year") },
|
||||
{ label: t("certd.dates.years", { count: 2 }), value: dayjs().add(2, "year") },
|
||||
{ label: t("certd.dates.years", { count: 3 }), value: dayjs().add(3, "year") },
|
||||
{ label: t("certd.dates.years", { count: 4 }), value: dayjs().add(4, "year") },
|
||||
{ label: t("certd.dates.years", { count: 5 }), value: dayjs().add(5, "year") },
|
||||
{ label: t("certd.dates.years", { count: 6 }), value: dayjs().add(6, "year") },
|
||||
],
|
||||
},
|
||||
},
|
||||
column: {
|
||||
show: computed(() => {
|
||||
return settingStore.isPlus && settingStore.sysPublic.pipelineValidTimeEnabled;
|
||||
}),
|
||||
sorter: true,
|
||||
width: 155,
|
||||
align: "center",
|
||||
cellRender({ value }) {
|
||||
if (!value || value <= 0) {
|
||||
return "-";
|
||||
}
|
||||
if (value < Date.now()) {
|
||||
return t("certd.hasExpired");
|
||||
}
|
||||
return dayjs(value).format("YYYY-MM-DD");
|
||||
},
|
||||
},
|
||||
},
|
||||
updateTime: {
|
||||
|
||||
@@ -37,6 +37,7 @@ const pipelineOptions: PipelineOptions = {
|
||||
type: detail.pipeline.type,
|
||||
from: detail.pipeline.from,
|
||||
},
|
||||
validTime: detail.pipeline.validTime,
|
||||
} as PipelineDetail;
|
||||
},
|
||||
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
import { onActivated, onMounted, ref } from "vue";
|
||||
import { dict, useFs } from "@fast-crud/fast-crud";
|
||||
import createCrudOptions from "./crud";
|
||||
import PiCertdForm from "./certd-form/index.vue";
|
||||
import ChangeGroup from "./components/change-group.vue";
|
||||
import ChangeTrigger from "./components/change-trigger.vue";
|
||||
import { Modal, notification } from "ant-design-vue";
|
||||
|
||||
@@ -28,6 +28,13 @@
|
||||
未设置触发源,不会自动执行
|
||||
</span>
|
||||
</a-tag>
|
||||
<a-tag v-if="pipelineEntity.validTime > 0 && settingStore.sysPublic.pipelineValidTimeEnabled && settingStore.isPlus" :color="pipelineEntity.validTime > Date.now() ? 'green' : 'red'">
|
||||
<span class="flex">
|
||||
<fs-icon icon="ion:time-outline"></fs-icon>
|
||||
<span v-if="pipelineEntity.validTime > Date.now()"> 有效期:<FsTimeHumanize :model-value="pipelineEntity.validTime" :options="{ units: ['d'] }" format="YYYY-MM-DD"></FsTimeHumanize> </span>
|
||||
<span v-else> 已过期 </span>
|
||||
</span>
|
||||
</a-tag>
|
||||
</div>
|
||||
<div class="basis-40 flex justify-end mr-10">
|
||||
<template v-if="editMode">
|
||||
@@ -343,7 +350,7 @@ export default defineComponent({
|
||||
const { t } = useI18n();
|
||||
const currentPipeline: Ref<any> = ref({});
|
||||
const pipeline: Ref<any> = ref({});
|
||||
|
||||
const pipelineEntity: Ref<any> = ref({});
|
||||
const histories: Ref<RunHistory[]> = ref([]);
|
||||
|
||||
const currentHistory: Ref<any> = ref({});
|
||||
@@ -490,6 +497,7 @@ export default defineComponent({
|
||||
return;
|
||||
}
|
||||
const detail: PipelineDetail = await props.options.getPipelineDetail({ pipelineId: value });
|
||||
pipelineEntity.value = detail;
|
||||
currentPipeline.value = merge(
|
||||
{
|
||||
title: "新管道流程",
|
||||
@@ -808,7 +816,7 @@ export default defineComponent({
|
||||
return nodes;
|
||||
},
|
||||
});
|
||||
throw new Error(errorMessage);
|
||||
throw new Error(errorMessages?.join(","));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -970,6 +978,7 @@ export default defineComponent({
|
||||
nextTriggerTimes,
|
||||
viewCert,
|
||||
downloadCert,
|
||||
pipelineEntity,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
@@ -3,6 +3,7 @@ import { PluginGroups } from "/@/store/plugin";
|
||||
|
||||
export type PipelineDetail = {
|
||||
pipeline: Pipeline;
|
||||
validTime?: number;
|
||||
};
|
||||
|
||||
export type RunHistory = {
|
||||
|
||||
@@ -95,11 +95,14 @@ import SmsCode from "/@/views/framework/login/sms-code.vue";
|
||||
import { useI18n } from "/@/locales";
|
||||
import { LanguageToggle } from "/@/vben/layouts";
|
||||
import CaptchaInput from "/@/components/captcha/captcha-input.vue";
|
||||
import { useRoute } from "vue-router";
|
||||
export default defineComponent({
|
||||
name: "LoginPage",
|
||||
components: { LanguageToggle, SmsCode, CaptchaInput },
|
||||
setup() {
|
||||
const { t } = useI18n();
|
||||
const route = useRoute();
|
||||
const urlLoginType = route.query.loginType as string | undefined;
|
||||
const verifyCodeInputRef = ref();
|
||||
const loading = ref(false);
|
||||
const userStore = useUserStore();
|
||||
@@ -110,7 +113,7 @@ export default defineComponent({
|
||||
phoneCode: "86",
|
||||
mobile: "",
|
||||
password: "",
|
||||
loginType: "password", //password
|
||||
loginType: urlLoginType || "password", //password
|
||||
smsCode: "",
|
||||
captcha: null,
|
||||
smsCaptcha: null,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="main">
|
||||
<a-form ref="formRef" class="user-layout-register" name="custom-validation" :model="formState" :rules="rules" v-bind="layout" :label-col="{ span: 6 }" @finish="handleFinish" @finish-failed="handleFinishFailed">
|
||||
<a-tabs v-model:active-key="registerType">
|
||||
<a-tabs v-model:active-key="registerType" @change="handleTabChange">
|
||||
<a-tab-pane key="username" tab="用户名注册" :disabled="!settingsStore.sysPublic.usernameRegisterEnabled">
|
||||
<template v-if="registerType === 'username'">
|
||||
<a-form-item required has-feedback name="username" label="用户名" :rules="rules.username">
|
||||
@@ -70,6 +70,8 @@
|
||||
</a-form-item>
|
||||
</template>
|
||||
</a-tab-pane>
|
||||
|
||||
<a-tab-pane v-if="settingsStore.sysPublic.smsLoginEnabled" key="mobile" tab="手机号注册"> </a-tab-pane>
|
||||
</a-tabs>
|
||||
|
||||
<a-form-item>
|
||||
@@ -90,6 +92,7 @@ import EmailCode from "./email-code.vue";
|
||||
import { useSettingStore } from "/@/store/settings";
|
||||
import { notification } from "ant-design-vue";
|
||||
import CaptchaInput from "/@/components/captcha/captcha-input.vue";
|
||||
import { useRouter } from "vue-router";
|
||||
export default defineComponent({
|
||||
name: "RegisterPage",
|
||||
components: { CaptchaInput, EmailCode },
|
||||
@@ -171,6 +174,18 @@ export default defineComponent({
|
||||
message: "请输入邮件验证码",
|
||||
},
|
||||
],
|
||||
captcha: [
|
||||
{
|
||||
required: true,
|
||||
message: "请通过验证码",
|
||||
},
|
||||
],
|
||||
imgCode: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入验证码",
|
||||
},
|
||||
],
|
||||
};
|
||||
const layout = {
|
||||
labelCol: {
|
||||
@@ -206,6 +221,13 @@ export default defineComponent({
|
||||
formRef.value.resetFields();
|
||||
};
|
||||
|
||||
const router = useRouter();
|
||||
const handleTabChange = (key: string) => {
|
||||
if (key === "mobile") {
|
||||
router.push({ path: "/login", query: { loginType: "sms" } });
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
formState,
|
||||
formRef,
|
||||
@@ -216,6 +238,7 @@ export default defineComponent({
|
||||
resetForm,
|
||||
registerType,
|
||||
settingsStore,
|
||||
handleTabChange,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
@@ -20,6 +20,9 @@
|
||||
<a-tab-pane key="captcha" :tab="t('certd.sys.setting.captchaSetting')">
|
||||
<SettingCaptcha v-if="activeKey === 'captcha'" />
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="pipeline" :tab="t('certd.sys.setting.pipelineSetting')">
|
||||
<SettingPipeline v-if="activeKey === 'pipeline'" />
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
</div>
|
||||
</fs-page>
|
||||
@@ -31,7 +34,7 @@ import SettingRegister from "/@/views/sys/settings/tabs/register.vue";
|
||||
import SettingPayment from "/@/views/sys/settings/tabs/payment.vue";
|
||||
import SettingSafe from "/@/views/sys/settings/tabs/safe.vue";
|
||||
import SettingCaptcha from "/@/views/sys/settings/tabs/captcha.vue";
|
||||
|
||||
import SettingPipeline from "/@/views/sys/settings/tabs/pipeline.vue";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { ref } from "vue";
|
||||
import { useSettingStore } from "/@/store/settings";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="sys-settings-form sys-settings-base">
|
||||
<a-form :model="formState" name="basic" :label-col="{ span: 8 }" :wrapper-col="{ span: 16 }" autocomplete="off" @finish="onFinish" @finish-failed="onFinishFailed">
|
||||
<a-form :model="formState" name="basic" :label-col="{ span: 8 }" :wrapper-col="{ span: 16 }" autocomplete="off" @finish="onFinish">
|
||||
<a-form-item :label="t('certd.icpRegistrationNumber')" :name="['public', 'icpNo']">
|
||||
<a-input v-model:value="formState.public.icpNo" :placeholder="t('certd.icpPlaceholder')" />
|
||||
</a-form-item>
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
<template>
|
||||
<div class="sys-settings-form sys-settings-pipeline">
|
||||
<a-form :model="formState" name="basic" :label-col="{ span: 8 }" :wrapper-col="{ span: 16 }" autocomplete="off" @finish="onFinish">
|
||||
<a-form-item :label="t('certd.manageOtherUserPipeline')" :name="['public', 'managerOtherUserPipeline']">
|
||||
<a-switch v-model:checked="formState.public.managerOtherUserPipeline" />
|
||||
</a-form-item>
|
||||
<a-form-item :label="t('certd.limitUserPipelineCount')" :name="['public', 'limitUserPipelineCount']">
|
||||
<a-input-number v-model:value="formState.public.limitUserPipelineCount" />
|
||||
<div class="helper">{{ t("certd.limitUserPipelineCountHelper") }}</div>
|
||||
</a-form-item>
|
||||
<a-form-item :label="t('certd.sys.setting.pipelineValidTimeEnabled')" :name="['public', 'pipelineValidTimeEnabled']">
|
||||
<div class="flex items-center">
|
||||
<a-switch v-model:checked="formState.public.pipelineValidTimeEnabled" :disabled="!settingsStore.isPlus" />
|
||||
<vip-button class="ml-5" mode="button"></vip-button>
|
||||
</div>
|
||||
|
||||
<div class="helper">{{ t("certd.sys.setting.pipelineValidTimeEnabledHelper") }}</div>
|
||||
</a-form-item>
|
||||
<a-form-item :label="t('certd.sys.setting.certDomainAddToMonitorEnabled')" :name="['public', 'certDomainAddToMonitorEnabled']">
|
||||
<div class="flex items-center">
|
||||
<a-switch v-model:checked="formState.public.certDomainAddToMonitorEnabled" :disabled="!settingsStore.isPlus" />
|
||||
<vip-button class="ml-5" mode="button"></vip-button>
|
||||
</div>
|
||||
<div class="helper">{{ t("certd.sys.setting.certDomainAddToMonitorEnabledHelper") }}</div>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label=" " :colon="false" :wrapper-col="{ span: 8 }">
|
||||
<a-button :loading="saveLoading" type="primary" html-type="submit">{{ t("certd.saveButton") }}</a-button>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="tsx">
|
||||
import { reactive, ref } from "vue";
|
||||
import { SysSettings } from "/@/views/sys/settings/api";
|
||||
import * as api from "/@/views/sys/settings/api";
|
||||
import { merge } from "lodash-es";
|
||||
import { useSettingStore } from "/@/store/settings";
|
||||
import { notification } from "ant-design-vue";
|
||||
import { useI18n } from "/src/locales";
|
||||
const { t } = useI18n();
|
||||
|
||||
defineOptions({
|
||||
name: "SettingPipeline",
|
||||
});
|
||||
|
||||
const formState = reactive<Partial<SysSettings>>({
|
||||
public: {},
|
||||
private: {},
|
||||
});
|
||||
|
||||
async function loadSysSettings() {
|
||||
const data: any = await api.SysSettingsGet();
|
||||
merge(formState, data);
|
||||
}
|
||||
|
||||
const saveLoading = ref(false);
|
||||
loadSysSettings();
|
||||
const settingsStore = useSettingStore();
|
||||
const onFinish = async (form: any) => {
|
||||
try {
|
||||
saveLoading.value = true;
|
||||
|
||||
await api.SysSettingsSave(form);
|
||||
await settingsStore.loadSysSettings();
|
||||
notification.success({
|
||||
message: t("certd.saveSuccess"),
|
||||
});
|
||||
} finally {
|
||||
saveLoading.value = false;
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="less"></style>
|
||||
@@ -1,13 +1,6 @@
|
||||
<template>
|
||||
<div class="sys-settings-form sys-settings-register">
|
||||
<a-form :model="formState" name="register" :label-col="{ span: 8 }" :wrapper-col="{ span: 16 }" autocomplete="off" @finish="onFinish">
|
||||
<a-form-item :label="t('certd.manageOtherUserPipeline')" :name="['public', 'managerOtherUserPipeline']">
|
||||
<a-switch v-model:checked="formState.public.managerOtherUserPipeline" />
|
||||
</a-form-item>
|
||||
<a-form-item :label="t('certd.limitUserPipelineCount')" :name="['public', 'limitUserPipelineCount']">
|
||||
<a-input-number v-model:value="formState.public.limitUserPipelineCount" />
|
||||
<div class="helper">{{ t("certd.limitUserPipelineCountHelper") }}</div>
|
||||
</a-form-item>
|
||||
<a-form-item :label="t('certd.enableSelfRegistration')" :name="['public', 'registerEnabled']">
|
||||
<a-switch v-model:checked="formState.public.registerEnabled" />
|
||||
</a-form-item>
|
||||
|
||||
@@ -3,6 +3,24 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.37.3](https://github.com/certd/certd/compare/v1.37.2...v1.37.3) (2025-10-24)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 修复网络测试,telnet的bug ([c03a70f](https://github.com/certd/certd/commit/c03a70fde23c8e840bd0fdb4fcbca8990f6c65eb))
|
||||
* 修复站点证书监控,证书已经更新到最新日期了,仍然发出警告通知的bug ([1f42f93](https://github.com/certd/certd/commit/1f42f933f07860b27aa3d016e40916ff2b063eac))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 注册页面增加手机注册tab页签 ([6b2f1fc](https://github.com/certd/certd/commit/6b2f1fcd3e058061b814c3331cda8ce1b2d80d73))
|
||||
* 流水线创建时支持添加到证书监控 ([59ba408](https://github.com/certd/certd/commit/59ba4080706548828ef1c0a9cd893c1c9a7d591f))
|
||||
* 流水线支持有效期设置 ([911e69e](https://github.com/certd/certd/commit/911e69e3bc0cdd48b62953b5d0981d640fc1f8ac))
|
||||
* 通知支持meow ([c77645e](https://github.com/certd/certd/commit/c77645e1733670214aaca5544cf8759d7e4adda4))
|
||||
* 站点证书监控增加导出和分组功能 ([2ed12c4](https://github.com/certd/certd/commit/2ed12c429eb58274a4f9dd0ed3b66e160d283ded))
|
||||
* 证书监控增加批量删除 ([e578c52](https://github.com/certd/certd/commit/e578c52fdf2f838038062aa4209b655fbae461fb))
|
||||
* esa 自动删除过期证书提示 ([8bf1f82](https://github.com/certd/certd/commit/8bf1f828b9eaa9208f32e8ee7460b86420fed0c7))
|
||||
* ssh 增加禁止-i参数提示 ([3a8931f](https://github.com/certd/certd/commit/3a8931feeffd7157163ff7d46b693e5e1a434b9c))
|
||||
|
||||
## [1.37.2](https://github.com/certd/certd/compare/v1.37.1...v1.37.2) (2025-10-14)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
ALTER TABLE cd_site_info ADD COLUMN `remark` varchar(512);
|
||||
|
||||
CREATE TABLE `cd_group`
|
||||
(
|
||||
`id` bigint PRIMARY KEY AUTO_INCREMENT NOT NULL,
|
||||
`user_id` bigint NOT NULL,
|
||||
`name` varchar(100) NOT NULL,
|
||||
`icon` varchar(100),
|
||||
`favorite` boolean NOT NULL DEFAULT false,
|
||||
`type` varchar(512),
|
||||
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
ALTER TABLE cd_site_info ADD COLUMN `group_id` bigint;
|
||||
|
||||
ALTER TABLE pi_pipeline ADD COLUMN `valid_time` bigint;
|
||||
@@ -0,0 +1,17 @@
|
||||
ALTER TABLE cd_site_info ADD COLUMN "remark" varchar(512);
|
||||
|
||||
CREATE TABLE "cd_group"
|
||||
(
|
||||
"id" bigint PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY NOT NULL,
|
||||
"user_id" bigint NOT NULL,
|
||||
"name" varchar(100) NOT NULL,
|
||||
"icon" varchar(100),
|
||||
"favorite" boolean NOT NULL DEFAULT (false),
|
||||
"type" varchar(512),
|
||||
"create_time" timestamp NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
"update_time" timestamp NOT NULL DEFAULT (CURRENT_TIMESTAMP)
|
||||
);
|
||||
|
||||
ALTER TABLE cd_site_info ADD COLUMN "group_id" bigint;
|
||||
|
||||
ALTER TABLE pi_pipeline ADD COLUMN "valid_time" bigint;
|
||||
@@ -0,0 +1,17 @@
|
||||
ALTER TABLE cd_site_info ADD COLUMN "remark" varchar(512);
|
||||
|
||||
CREATE TABLE "cd_group"
|
||||
(
|
||||
"id" integer PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
"user_id" integer NOT NULL,
|
||||
"name" varchar(100) NOT NULL,
|
||||
"icon" varchar(100),
|
||||
"favorite" boolean NOT NULL DEFAULT (false),
|
||||
"type" varchar(512),
|
||||
"create_time" datetime NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
"update_time" datetime NOT NULL DEFAULT (CURRENT_TIMESTAMP)
|
||||
);
|
||||
|
||||
ALTER TABLE cd_site_info ADD COLUMN "group_id" integer;
|
||||
|
||||
ALTER TABLE pi_pipeline ADD COLUMN "valid_time" integer;
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@certd/ui-server",
|
||||
"version": "1.37.2",
|
||||
"version": "1.37.3",
|
||||
"description": "fast-server base midway",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
@@ -45,20 +45,20 @@
|
||||
"@aws-sdk/client-cloudfront": "^3.699.0",
|
||||
"@aws-sdk/client-iam": "^3.699.0",
|
||||
"@aws-sdk/client-s3": "^3.705.0",
|
||||
"@certd/acme-client": "^1.37.2",
|
||||
"@certd/basic": "^1.37.2",
|
||||
"@certd/commercial-core": "^1.37.2",
|
||||
"@certd/acme-client": "^1.37.3",
|
||||
"@certd/basic": "^1.37.3",
|
||||
"@certd/commercial-core": "^1.37.3",
|
||||
"@certd/cv4pve-api-javascript": "^8.4.2",
|
||||
"@certd/jdcloud": "^1.37.2",
|
||||
"@certd/lib-huawei": "^1.37.2",
|
||||
"@certd/lib-k8s": "^1.37.2",
|
||||
"@certd/lib-server": "^1.37.2",
|
||||
"@certd/midway-flyway-js": "^1.37.2",
|
||||
"@certd/pipeline": "^1.37.2",
|
||||
"@certd/plugin-cert": "^1.37.2",
|
||||
"@certd/plugin-lib": "^1.37.2",
|
||||
"@certd/plugin-plus": "^1.37.2",
|
||||
"@certd/plus-core": "^1.37.2",
|
||||
"@certd/jdcloud": "^1.37.3",
|
||||
"@certd/lib-huawei": "^1.37.3",
|
||||
"@certd/lib-k8s": "^1.37.3",
|
||||
"@certd/lib-server": "^1.37.3",
|
||||
"@certd/midway-flyway-js": "^1.37.3",
|
||||
"@certd/pipeline": "^1.37.3",
|
||||
"@certd/plugin-cert": "^1.37.3",
|
||||
"@certd/plugin-lib": "^1.37.3",
|
||||
"@certd/plugin-plus": "^1.37.3",
|
||||
"@certd/plus-core": "^1.37.3",
|
||||
"@huaweicloud/huaweicloud-sdk-cdn": "^3.1.120",
|
||||
"@huaweicloud/huaweicloud-sdk-core": "^3.1.120",
|
||||
"@koa/cors": "^5.0.0",
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
import { ALL, Body, Controller, Inject, Post, Provide, Query } from '@midwayjs/core';
|
||||
import { Constants, CrudController } from '@certd/lib-server';
|
||||
import { AuthService } from '../../../modules/sys/authority/service/auth-service.js';
|
||||
import { GroupService } from '../../../modules/basic/service/group-service.js';
|
||||
|
||||
/**
|
||||
* 通知
|
||||
*/
|
||||
@Provide()
|
||||
@Controller('/api/basic/group')
|
||||
export class GroupController extends CrudController<GroupService> {
|
||||
@Inject()
|
||||
service: GroupService;
|
||||
@Inject()
|
||||
authService: AuthService;
|
||||
|
||||
getService(): GroupService {
|
||||
return this.service;
|
||||
}
|
||||
|
||||
@Post('/page', { summary: Constants.per.authOnly })
|
||||
async page(@Body(ALL) body: any) {
|
||||
body.query = body.query ?? {};
|
||||
delete body.query.userId;
|
||||
const buildQuery = qb => {
|
||||
qb.andWhere('user_id = :userId', { userId: this.getUserId() });
|
||||
};
|
||||
const res = await this.service.page({
|
||||
query: body.query,
|
||||
page: body.page,
|
||||
sort: body.sort,
|
||||
buildQuery,
|
||||
});
|
||||
return this.ok(res);
|
||||
}
|
||||
|
||||
@Post('/list', { summary: Constants.per.authOnly })
|
||||
async list(@Body(ALL) body: any) {
|
||||
body.query = body.query ?? {};
|
||||
body.query.userId = this.getUserId();
|
||||
return await super.list(body);
|
||||
}
|
||||
|
||||
@Post('/add', { summary: Constants.per.authOnly })
|
||||
async add(@Body(ALL) bean: any) {
|
||||
bean.userId = this.getUserId();
|
||||
return await super.add(bean);
|
||||
}
|
||||
|
||||
@Post('/update', { summary: Constants.per.authOnly })
|
||||
async update(@Body(ALL) bean) {
|
||||
await this.service.checkUserId(bean.id, this.getUserId());
|
||||
delete bean.userId;
|
||||
return await super.update(bean);
|
||||
}
|
||||
@Post('/info', { summary: Constants.per.authOnly })
|
||||
async info(@Query('id') id: number) {
|
||||
await this.service.checkUserId(id, this.getUserId());
|
||||
return await super.info(id);
|
||||
}
|
||||
|
||||
@Post('/delete', { summary: Constants.per.authOnly })
|
||||
async delete(@Query('id') id: number) {
|
||||
await this.service.checkUserId(id, this.getUserId());
|
||||
return await super.delete(id);
|
||||
}
|
||||
|
||||
@Post('/all', { summary: Constants.per.authOnly })
|
||||
async all(@Query('type') type: string) {
|
||||
const list: any = await this.service.find({
|
||||
where: {
|
||||
userId: this.getUserId(),
|
||||
type,
|
||||
},
|
||||
});
|
||||
return this.ok(list);
|
||||
}
|
||||
}
|
||||
@@ -92,6 +92,14 @@ export class SiteInfoController extends CrudController<SiteInfoService> {
|
||||
return await super.delete(id);
|
||||
}
|
||||
|
||||
|
||||
@Post('/batchDelete', { summary: Constants.per.authOnly })
|
||||
async batchDelete(@Body(ALL) body: any) {
|
||||
const userId = this.getUserId();
|
||||
await this.service.batchDelete(body.ids,userId);
|
||||
return this.ok();
|
||||
}
|
||||
|
||||
@Post('/check', { summary: Constants.per.authOnly })
|
||||
async check(@Body('id') id: number) {
|
||||
await this.service.checkUserId(id, this.getUserId());
|
||||
@@ -111,6 +119,7 @@ export class SiteInfoController extends CrudController<SiteInfoService> {
|
||||
const userId = this.getUserId();
|
||||
await this.service.doImport({
|
||||
text:body.text,
|
||||
groupId:body.groupId,
|
||||
userId
|
||||
})
|
||||
return this.ok();
|
||||
|
||||
@@ -107,6 +107,9 @@ export class NotificationController extends CrudController<NotificationService>
|
||||
icon: item.icon,
|
||||
});
|
||||
}
|
||||
dict = dict.sort(a => {
|
||||
return a.order ? 0 : -1;
|
||||
});
|
||||
dict = dict.sort(a => {
|
||||
return a.needPlus ? 0 : -1;
|
||||
});
|
||||
|
||||
@@ -4,6 +4,8 @@ import { PipelineService } from '../../../modules/pipeline/service/pipeline-serv
|
||||
import { PipelineEntity } from '../../../modules/pipeline/entity/pipeline.js';
|
||||
import { HistoryService } from '../../../modules/pipeline/service/history-service.js';
|
||||
import { AuthService } from '../../../modules/sys/authority/service/auth-service.js';
|
||||
import { SiteInfoService } from '../../../modules/monitor/index.js';
|
||||
import { isPlus } from '@certd/plus-core';
|
||||
|
||||
/**
|
||||
* 证书
|
||||
@@ -20,6 +22,9 @@ export class PipelineController extends CrudController<PipelineService> {
|
||||
@Inject()
|
||||
sysSettingsService: SysSettingsService;
|
||||
|
||||
@Inject()
|
||||
siteInfoService: SiteInfoService;
|
||||
|
||||
getService() {
|
||||
return this.service;
|
||||
}
|
||||
@@ -74,13 +79,30 @@ export class PipelineController extends CrudController<PipelineService> {
|
||||
}
|
||||
|
||||
@Post('/save', { summary: Constants.per.authOnly })
|
||||
async save(@Body(ALL) bean: PipelineEntity) {
|
||||
async save(@Body(ALL) bean: {addToMonitorEnabled: boolean, addToMonitorDomains: string} & PipelineEntity) {
|
||||
if (bean.id > 0) {
|
||||
await this.authService.checkEntityUserId(this.ctx, this.getService(), bean.id);
|
||||
} else {
|
||||
bean.userId = this.getUserId();
|
||||
}
|
||||
|
||||
if(!this.isAdmin()){
|
||||
// 非管理员用户 不允许设置流水线有效期
|
||||
delete bean.validTime
|
||||
}
|
||||
|
||||
await this.service.save(bean);
|
||||
//是否增加证书监控
|
||||
if (bean.addToMonitorEnabled && bean.addToMonitorDomains) {
|
||||
const sysPublicSettings = await this.sysSettingsService.getPublicSettings();
|
||||
if (isPlus() && sysPublicSettings.certDomainAddToMonitorEnabled) {
|
||||
//增加证书监控
|
||||
await this.siteInfoService.doImport({
|
||||
text: bean.addToMonitorDomains,
|
||||
userId: this.getUserId(),
|
||||
});
|
||||
}
|
||||
}
|
||||
return this.ok(bean.id);
|
||||
}
|
||||
|
||||
@@ -101,7 +123,7 @@ export class PipelineController extends CrudController<PipelineService> {
|
||||
@Post('/trigger', { summary: Constants.per.authOnly })
|
||||
async trigger(@Query('id') id: number, @Query('stepId') stepId?: string) {
|
||||
await this.authService.checkEntityUserId(this.ctx, this.getService(), id);
|
||||
await this.service.trigger(id, stepId);
|
||||
await this.service.trigger(id, stepId,true);
|
||||
return this.ok({});
|
||||
}
|
||||
|
||||
|
||||
38
packages/ui/certd-server/src/modules/basic/entity/group.ts
Normal file
38
packages/ui/certd-server/src/modules/basic/entity/group.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
|
||||
|
||||
export const GROUP_TYPE_SITE = 'site';
|
||||
|
||||
@Entity('cd_group')
|
||||
export class GroupEntity {
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column({ name: 'user_id', comment: '用户id' })
|
||||
userId: number;
|
||||
|
||||
@Column({ name: 'name', comment: '分组名称' })
|
||||
name: string;
|
||||
|
||||
@Column({ name: 'icon', comment: '图标' })
|
||||
icon: string;
|
||||
|
||||
@Column({ name: 'favorite', comment: '收藏' })
|
||||
favorite: boolean;
|
||||
|
||||
@Column({ name: 'type', comment: '类型', length: 512 })
|
||||
type: string;
|
||||
|
||||
@Column({
|
||||
name: 'create_time',
|
||||
comment: '创建时间',
|
||||
default: () => 'CURRENT_TIMESTAMP',
|
||||
})
|
||||
createTime: Date;
|
||||
|
||||
@Column({
|
||||
name: 'update_time',
|
||||
comment: '修改时间',
|
||||
default: () => 'CURRENT_TIMESTAMP',
|
||||
})
|
||||
updateTime: Date;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
import { Provide, Scope, ScopeEnum } from '@midwayjs/core';
|
||||
import { BaseService } from '@certd/lib-server';
|
||||
import { InjectEntityModel } from '@midwayjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
import { merge } from 'lodash-es';
|
||||
import { GroupEntity } from '../entity/group.js';
|
||||
|
||||
@Provide()
|
||||
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||
export class GroupService extends BaseService<GroupEntity> {
|
||||
@InjectEntityModel(GroupEntity)
|
||||
repository: Repository<GroupEntity>;
|
||||
|
||||
//@ts-ignore
|
||||
getRepository() {
|
||||
return this.repository;
|
||||
}
|
||||
|
||||
async add(bean: any) {
|
||||
if (!bean.type) {
|
||||
throw new Error('type is required');
|
||||
}
|
||||
bean = merge(
|
||||
{
|
||||
favorite: false,
|
||||
},
|
||||
bean
|
||||
);
|
||||
return await this.repository.save(bean);
|
||||
}
|
||||
}
|
||||
@@ -56,6 +56,12 @@ export class SiteInfoEntity {
|
||||
@Column({ name: 'disabled', comment: '禁用启用' })
|
||||
disabled: boolean;
|
||||
|
||||
@Column({ name: 'remark', comment: '备注', length: 512 })
|
||||
remark: string;
|
||||
|
||||
@Column({ name: 'group_id', comment: '分组id' })
|
||||
groupId: number;
|
||||
|
||||
@Column({ name: 'create_time', comment: '创建时间', default: () => 'CURRENT_TIMESTAMP' })
|
||||
createTime: Date;
|
||||
@Column({ name: 'update_time', comment: '修改时间', default: () => 'CURRENT_TIMESTAMP' })
|
||||
|
||||
@@ -169,8 +169,9 @@ export class SiteInfoService extends BaseService<SiteInfoEntity> {
|
||||
if (!notify) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await this.sendExpiresNotify(site);
|
||||
await this.sendExpiresNotify(site.id);
|
||||
} catch (e) {
|
||||
logger.error("send notify error", e);
|
||||
}
|
||||
@@ -186,7 +187,7 @@ export class SiteInfoService extends BaseService<SiteInfoEntity> {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await this.sendCheckErrorNotify(site);
|
||||
await this.sendCheckErrorNotify(site.id);
|
||||
} catch (e) {
|
||||
logger.error("send notify error", e);
|
||||
}
|
||||
@@ -231,8 +232,7 @@ export class SiteInfoService extends BaseService<SiteInfoEntity> {
|
||||
ipErrorCount: errorCount
|
||||
});
|
||||
try {
|
||||
site = await this.info(site.id);
|
||||
await this.sendCheckErrorNotify(site, true);
|
||||
await this.sendCheckErrorNotify(site.id, true);
|
||||
} catch (e) {
|
||||
logger.error("send notify error", e);
|
||||
}
|
||||
@@ -254,7 +254,8 @@ export class SiteInfoService extends BaseService<SiteInfoEntity> {
|
||||
return await this.doCheck(site, notify, retryTimes);
|
||||
}
|
||||
|
||||
async sendCheckErrorNotify(site: SiteInfoEntity, fromIpCheck = false) {
|
||||
async sendCheckErrorNotify(siteId: number, fromIpCheck = false) {
|
||||
const site = await this.info(siteId);
|
||||
const url = await this.notificationService.getBindUrl("#/certd/monitor/site");
|
||||
const setting = await this.userSettingsService.getSetting<UserSiteMonitorSetting>(site.userId, UserSiteMonitorSetting)
|
||||
// 发邮件
|
||||
@@ -274,7 +275,8 @@ export class SiteInfoService extends BaseService<SiteInfoEntity> {
|
||||
);
|
||||
}
|
||||
|
||||
async sendExpiresNotify(site: SiteInfoEntity) {
|
||||
async sendExpiresNotify(siteId: number) {
|
||||
const site = await this.info(siteId);
|
||||
const setting = await this.userSettingsService.getSetting<UserSiteMonitorSetting>(site.userId, UserSiteMonitorSetting)
|
||||
const tipDays = setting?.certValidDays || 10;
|
||||
|
||||
@@ -391,7 +393,7 @@ export class SiteInfoService extends BaseService<SiteInfoEntity> {
|
||||
}
|
||||
}
|
||||
|
||||
async doImport(req: { text: string; userId: number }) {
|
||||
async doImport(req: { text: string; userId: number,groupId?:number }) {
|
||||
if (!req.text) {
|
||||
throw new Error("text is required");
|
||||
}
|
||||
@@ -419,17 +421,22 @@ export class SiteInfoService extends BaseService<SiteInfoEntity> {
|
||||
} catch (e) {
|
||||
throw new Error(`${item}格式错误`);
|
||||
}
|
||||
|
||||
}
|
||||
if (arr.length > 2) {
|
||||
name = arr[2] || domain;
|
||||
}
|
||||
let remark:string = "";
|
||||
if (arr.length > 3) {
|
||||
remark = arr[3] || "";
|
||||
}
|
||||
|
||||
list.push({
|
||||
domain,
|
||||
name,
|
||||
httpsPort: port,
|
||||
userId: req.userId
|
||||
userId: req.userId,
|
||||
remark,
|
||||
groupId: req.groupId
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -43,28 +43,19 @@ export class PipelineEntity {
|
||||
@Column({ name:"is_template", comment: '是否模版', nullable: true, default: false })
|
||||
isTemplate: boolean;
|
||||
|
||||
@Column({
|
||||
name: 'last_history_time',
|
||||
comment: '最后一次执行时间',
|
||||
nullable: true,
|
||||
})
|
||||
@Column({name: 'last_history_time',comment: '最后一次执行时间',nullable: true,})
|
||||
lastHistoryTime: number;
|
||||
|
||||
@Column({name: 'valid_time',comment: '到期时间',nullable: true,default: 0})
|
||||
validTime: number;
|
||||
|
||||
// 变量
|
||||
lastVars: any;
|
||||
|
||||
@Column({
|
||||
name: 'order',
|
||||
comment: '排序',
|
||||
nullable: true,
|
||||
})
|
||||
@Column({name: 'order', comment: '排序', nullable: true,})
|
||||
order: number;
|
||||
|
||||
@Column({
|
||||
name: 'create_time',
|
||||
comment: '创建时间',
|
||||
default: () => 'CURRENT_TIMESTAMP',
|
||||
})
|
||||
@Column({name: 'create_time',comment: '创建时间', default: () => 'CURRENT_TIMESTAMP',})
|
||||
createTime: Date;
|
||||
@Column({
|
||||
name: 'update_time',
|
||||
|
||||
@@ -368,17 +368,21 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
||||
}
|
||||
|
||||
if (immediateTriggerOnce) {
|
||||
await this.trigger(pipeline.id);
|
||||
await sleep(200);
|
||||
try{
|
||||
await this.trigger(pipeline.id);
|
||||
await sleep(200);
|
||||
}catch(e){
|
||||
logger.error(e);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
async trigger(id: any, stepId?: string) {
|
||||
async trigger(id: any, stepId?: string , doCheck = false) {
|
||||
const entity: PipelineEntity = await this.info(id);
|
||||
if (isComm()) {
|
||||
await this.checkHasDeployCount(id, entity.userId);
|
||||
if (doCheck) {
|
||||
await this.beforeCheck(entity);
|
||||
}
|
||||
await this.checkUserStatus(entity.userId);
|
||||
this.cron.register({
|
||||
name: `pipeline.${id}.trigger.once`,
|
||||
cron: null,
|
||||
@@ -457,11 +461,11 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
||||
return;
|
||||
}
|
||||
cron = cron.trim();
|
||||
if (cron.startsWith("* *")) {
|
||||
cron = cron.replace("\* \*", "0 0");
|
||||
if (cron.startsWith("* * ")) {
|
||||
cron = "0 0 " + cron.substring(5);
|
||||
}
|
||||
if (cron.startsWith("*")) {
|
||||
cron = cron.replace("\*", "0");
|
||||
if (cron.startsWith("* ")) {
|
||||
cron = "0 " + cron.substring(2);
|
||||
}
|
||||
const triggerId = trigger.id;
|
||||
const name = this.buildCronKey(pipelineId, triggerId);
|
||||
@@ -485,6 +489,17 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
||||
logger.info("当前定时器数量:", this.cron.getTaskSize());
|
||||
}
|
||||
|
||||
|
||||
async isPipelineValidTimeEnabled(entity: PipelineEntity) {
|
||||
const settings = await this.sysSettingsService.getPublicSettings();
|
||||
if (isPlus() && settings.pipelineValidTimeEnabled){
|
||||
if (entity.validTime > 0 && entity.validTime < Date.now()){
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param id
|
||||
@@ -496,20 +511,34 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
||||
await this.doRun(entity, triggerId, stepId);
|
||||
}
|
||||
|
||||
async doRun(entity: PipelineEntity, triggerId: string, stepId?: string) {
|
||||
const id = entity.id;
|
||||
async beforeCheck(entity: PipelineEntity) {
|
||||
const validTimeEnabled = await this.isPipelineValidTimeEnabled(entity)
|
||||
if (!validTimeEnabled) {
|
||||
throw new Error(`流水线${entity.id}已过期,不予执行`);
|
||||
}
|
||||
|
||||
let suite: UserSuiteEntity = null;
|
||||
if (isComm()) {
|
||||
suite = await this.checkHasDeployCount(id, entity.userId);
|
||||
suite = await this.checkHasDeployCount(entity.id, entity.userId);
|
||||
}
|
||||
try {
|
||||
await this.checkUserStatus(entity.userId);
|
||||
await this.checkUserStatus(entity.userId);
|
||||
|
||||
return {
|
||||
suite
|
||||
}
|
||||
}
|
||||
|
||||
async doRun(entity: PipelineEntity, triggerId: string, stepId?: string) {
|
||||
|
||||
let suite:any = null
|
||||
try{
|
||||
const res = await this.beforeCheck(entity);
|
||||
suite = res.suite
|
||||
} catch (e) {
|
||||
logger.info(e.message);
|
||||
return;
|
||||
logger.error(`流水线${entity.id}触发${triggerId}失败:${e.message}`);
|
||||
}
|
||||
|
||||
|
||||
const id = entity.id;
|
||||
const pipeline = JSON.parse(entity.content);
|
||||
if (!pipeline.id) {
|
||||
pipeline.id = id;
|
||||
|
||||
@@ -20,7 +20,7 @@ export class AuthService {
|
||||
return true;
|
||||
}
|
||||
|
||||
async isAdmin(ctx: any) {
|
||||
isAdmin(ctx: any) {
|
||||
const roleIds: number[] = ctx.user.roles;
|
||||
if (roleIds.includes(1)) {
|
||||
return true;
|
||||
|
||||
@@ -42,7 +42,7 @@ export class NetTestService {
|
||||
// 判断测试是否成功
|
||||
const success = this.isWindows()
|
||||
? output.includes('端口连接成功')
|
||||
: output.includes('Connected to');
|
||||
: output.includes(' open');
|
||||
|
||||
// 处理结果
|
||||
return {
|
||||
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
title: "阿里云-部署至ESA",
|
||||
icon: "svg:icon-aliyun",
|
||||
group: pluginGroups.aliyun.key,
|
||||
desc: "部署证书到阿里云ESA(边缘安全加速)",
|
||||
desc: "部署证书到阿里云ESA(边缘安全加速),自动删除过期证书",
|
||||
needPlus: false,
|
||||
default: {
|
||||
strategy: {
|
||||
@@ -125,6 +125,7 @@ export class AliyunDeployCertToESA extends AbstractTaskPlugin {
|
||||
const { certId, certName } = await this.getAliyunCertId(access);
|
||||
|
||||
for (const siteId of this.siteIds) {
|
||||
|
||||
try {
|
||||
const res = await client.doRequest({
|
||||
// 接口名称
|
||||
@@ -159,6 +160,7 @@ export class AliyunDeployCertToESA extends AbstractTaskPlugin {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async getClient(access: AliyunAccess) {
|
||||
const endpoint = `esa.${this.regionId}.aliyuncs.com`;
|
||||
return access.getClient(endpoint);
|
||||
@@ -211,19 +213,24 @@ export class AliyunDeployCertToESA extends AbstractTaskPlugin {
|
||||
this.logger.info(`证书${item.Name}状态:${item.Status}`);
|
||||
if (item.Status === "Expired") {
|
||||
this.logger.info(`证书${item.Name}已过期,执行删除`);
|
||||
await client.doRequest({
|
||||
action: "DeleteCertificate",
|
||||
version: "2024-09-10",
|
||||
// 接口 HTTP 方法
|
||||
method: "GET",
|
||||
data:{
|
||||
query: {
|
||||
SiteId: siteId,
|
||||
Id: item.id
|
||||
}
|
||||
}
|
||||
});
|
||||
this.logger.info(`证书${item.Name}已删除`);
|
||||
try{
|
||||
await client.doRequest({
|
||||
action: "DeleteCertificate",
|
||||
version: "2024-09-10",
|
||||
// 接口 HTTP 方法
|
||||
method: "GET",
|
||||
data:{
|
||||
query: {
|
||||
SiteId: siteId,
|
||||
Id: item.id
|
||||
}
|
||||
}
|
||||
});
|
||||
this.logger.info(`证书${item.Name}已删除`);
|
||||
}catch (e) {
|
||||
this.logger.error(`过期证书${item.Name}删除失败:`,e.message)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -246,7 +246,7 @@ export class UploadCertToHostPlugin extends AbstractTaskPlugin {
|
||||
rows: 5,
|
||||
placeholder: 'systemctl restart nginx ',
|
||||
},
|
||||
helper: '上传后执行脚本命令,让证书生效(比如重启nginx),不填则不执行\n注意:sudo需要配置免密\n注意:如果目标主机是windows,且终端是cmd,系统会自动将多行命令通过“&&”连接成一行',
|
||||
helper: '上传后执行脚本命令,让证书生效(比如重启nginx),不填则不执行\n注意:sudo需要配置免密,不要使用-i这种交互式命令\n注意:如果目标主机是windows,且终端是cmd,系统会自动将多行命令通过“&&”连接成一行',
|
||||
required: false,
|
||||
})
|
||||
script!: string;
|
||||
|
||||
@@ -10,7 +10,7 @@ import { resetLogConfigure } from "@certd/basic";
|
||||
title: '华为云-上传证书至CCM',
|
||||
icon: 'svg:icon-huawei',
|
||||
group: pluginGroups.huawei.key,
|
||||
desc: '上传证书到华为云CCM',
|
||||
desc: '上传证书到华为云云证书管理(CCM)',
|
||||
default: {
|
||||
strategy: {
|
||||
runStrategy: RunStrategy.SkipWhenSucceed,
|
||||
|
||||
@@ -4,6 +4,7 @@ import { BaseNotification, IsNotification, NotificationBody, NotificationInput }
|
||||
name: 'email',
|
||||
title: '电子邮件',
|
||||
desc: '电子邮件通知',
|
||||
order: -100,
|
||||
})
|
||||
export class EmailNotification extends BaseNotification {
|
||||
@NotificationInput({
|
||||
|
||||
@@ -12,4 +12,5 @@ export * from './bark/index.js';
|
||||
export * from './feishu/index.js';
|
||||
export * from './dingtalk/index.js';
|
||||
export * from './vocechat/index.js';
|
||||
export * from './onebot/index.js';
|
||||
export * from './onebot/index.js';
|
||||
export * from './meow/index.js';
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
import { BaseNotification, IsNotification, NotificationBody, NotificationInput } from '@certd/pipeline';
|
||||
|
||||
/**
|
||||
* POST请求
|
||||
支持格式
|
||||
application/json
|
||||
text/plain
|
||||
multipart/form-data
|
||||
application/x-www-form-urlencoded
|
||||
表单格式
|
||||
POST /{昵称}/[title] HTTP/1.1
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
title=可选标题&msg=必填内容&url=可选链接&msgType=html&htmlHeight=400
|
||||
|
||||
纯文本格式
|
||||
POST /{昵称}/[title] HTTP/1.1
|
||||
Content-Type: text/plain
|
||||
|
||||
这里放置消息内容
|
||||
|
||||
POST JSON示例
|
||||
POST /JohnDoe?msgType=html&htmlHeight=350 HTTP/1.1
|
||||
Host: api.chuckfang.com
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"title": "系统通知",
|
||||
"msg": "<p><b>欢迎使用</b>,这是 <i>HTML</i> 格式的消息</p>",
|
||||
"url": "https://example.com"
|
||||
}
|
||||
|
||||
===
|
||||
返回值:
|
||||
{
|
||||
"status": 200,
|
||||
"message": "推送成功"
|
||||
}
|
||||
*/
|
||||
@IsNotification({
|
||||
name: 'meow',
|
||||
title: 'MeoW通知',
|
||||
desc: 'https://api.chuckfang.com/',
|
||||
needPlus: false,
|
||||
})
|
||||
export class MeowNotification extends BaseNotification {
|
||||
|
||||
@NotificationInput({
|
||||
title: 'MeoW接口地址',
|
||||
component: {
|
||||
placeholder: 'https://api.xxxxxx.com',
|
||||
},
|
||||
required: true,
|
||||
})
|
||||
endpoint = '';
|
||||
|
||||
@NotificationInput({
|
||||
title: '昵称',
|
||||
component: {
|
||||
placeholder: '',
|
||||
},
|
||||
required: true,
|
||||
})
|
||||
nickName = '';
|
||||
|
||||
async send(body: NotificationBody) {
|
||||
if (!this.nickName) {
|
||||
throw new Error('昵称不能为空');
|
||||
}
|
||||
let endpoint = this.endpoint;
|
||||
if (!endpoint.endsWith('/')) {
|
||||
endpoint += '/';
|
||||
}
|
||||
const url = `${endpoint}${this.nickName}/`;
|
||||
const res = await this.http.request({
|
||||
url: url,
|
||||
method: 'POST',
|
||||
data: {
|
||||
text: body.title,
|
||||
msg: body.content,
|
||||
url: body.url,
|
||||
},
|
||||
});
|
||||
|
||||
if (res.status !== 200) {
|
||||
throw new Error(res.message || res.msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import qs from 'qs';
|
||||
name: 'webhook',
|
||||
title: '自定义webhook',
|
||||
desc: '根据模版自定义http请求',
|
||||
order: -100,
|
||||
})
|
||||
export class WebhookNotification extends BaseNotification {
|
||||
@NotificationInput({
|
||||
|
||||
466
pnpm-lock.yaml
generated
466
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user