Compare commits

..

11 Commits

Author SHA1 Message Date
xiaojunnuo
dbce751464 v1.37.4 2025-10-29 01:30:41 +08:00
xiaojunnuo
b8640d903f build: prepare to build 2025-10-29 01:28:26 +08:00
xiaojunnuo
6e7560ee77 build: prepare to build 2025-10-29 01:25:54 +08:00
xiaojunnuo
efa26a067f fix: 修复站点证书监控复制按钮无效的bug 2025-10-28 23:45:08 +08:00
xiaojunnuo
f7cf7c198d fix: 修复lego模式下 私钥加密类型错误的bug 2025-10-28 15:46:52 +08:00
xiaojunnuo
d32f4fc38e 修复邮箱注册验证码报错的bug 2025-10-28 15:30:31 +08:00
xiaojunnuo
0c8b8647f3 docs: openapi 2025-10-28 10:34:52 +08:00
xiaojunnuo
c38dbbb1d7 perf: 优化数据备份效率,流式写入文件 2025-10-27 15:25:41 +08:00
xiaojunnuo
98cec15625 build: release 2025-10-25 01:26:51 +08:00
xiaojunnuo
bad9828f47 build: publish 2025-10-25 01:15:11 +08:00
xiaojunnuo
18f91ddffa build: trigger build image 2025-10-25 01:14:52 +08:00
44 changed files with 367 additions and 237 deletions

View File

@@ -3,6 +3,17 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.37.4](https://github.com/certd/certd/compare/v1.37.3...v1.37.4) (2025-10-28)
### Bug Fixes
* 修复站点证书监控复制按钮无效的bug ([efa26a0](https://github.com/certd/certd/commit/efa26a067f06402f30befc016d9934cadcd5a563))
* 修复lego模式下 私钥加密类型错误的bug ([f7cf7c1](https://github.com/certd/certd/commit/f7cf7c198d7f77b222099770f81accc637bc6619))
### Performance Improvements
* 优化数据备份效率,流式写入文件 ([c38dbbb](https://github.com/certd/certd/commit/c38dbbb1d72bd00a92fe275b76aea82a791e7199))
## [1.37.3](https://github.com/certd/certd/compare/v1.37.2...v1.37.3) (2025-10-24)
### Bug Fixes

View File

@@ -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

View File

@@ -9,6 +9,7 @@
https://apifox.com/apidoc/shared-2e76f8c4-7c58-413b-a32d-a1316529af44/254949529e0
## Token生成方法
header中传入x-certd-token即可调用开放接口
@@ -17,6 +18,12 @@ header中传入x-certd-token即可调用开放接口
3、将content加上keySecret进行签名 sign = md5(content + keySecret)
4、然后将content和sign分别base64后用.号连接: x-certd-token = base64(content) +"."+base64(sign)
## 补充说明
1.证书申请接口支持证书id和域名两种方式获取证书。
2.autoApply=true将在没有证书时自动触发申请申请过程中会提示`正在申请中`,可轮循获取状态,直到证书申请成功。
## SDK
待开发

View File

@@ -62,7 +62,9 @@
| 58.| **Dokploy授权** | |
| 59.| **godaddy授权** | |
| 60.| **新网授权** | |
| 61.| **雨云授权** | https://app.rainyun.com/ |
| 61.| **新网授权(代理方式)** | |
| 62.| **新网互联授权** | 仅支持代理账号ip需要加入白名单 |
| 63.| **雨云授权** | https://app.rainyun.com/ |
<style module>
table th:first-of-type {

View File

@@ -77,7 +77,7 @@
| 9.| **阿里云-部署至NLB网络负载均衡** | NLB,网络负载均衡,更新监听器的默认证书 |
| 10.| **阿里云-部署至CLB(传统负载均衡)** | 部署证书到阿里云CLB(传统负载均衡) |
| 11.| **阿里云-部署至阿里云FC(3.0)** | 部署证书到阿里云函数计算FC3.0 |
| 12.| **阿里云-部署至ESA** | 部署证书到阿里云ESA(边缘安全加速) |
| 12.| **阿里云-部署至ESA** | 部署证书到阿里云ESA(边缘安全加速),自动删除过期证书 |
| 13.| **阿里云-部署至VOD** | 部署证书到阿里云视频点播vod |
| 14.| **阿里云-部署证书至API网关** | 自动部署域名证书至阿里云API网关APIGateway |
| 15.| **阿里云-部署至云原生API网关/AI网关** | 自动部署域名证书至云原生API网关、AI网关 |
@@ -86,7 +86,7 @@
| 序号 | 名称 | 说明 |
|-----|-----|-----|
| 1.| **华为云-部署证书至CDN** | |
| 2.| **华为云-上传证书至CCM** | 上传证书到华为云CCM |
| 2.| **华为云-上传证书至CCM** | 上传证书到华为云云证书管理(CCM |
| 3.| **华为云-部署证书至OBS** | |
## 7. 腾讯云

View File

@@ -7,15 +7,17 @@
| 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 |
| 6.| **新网(代理方式)** | 新网域名解析(代理方式) |
| 7.| **腾讯** | 腾讯云域名DNS解析提供 |
| 8.| **华为云** | 华为云DNS解析提供商 |
| 9.| **西部数码** | west dns provider |
| 10.| **dns.la** | dns.la |
| 11.| **雨云** | 雨云DNS解析提供商 |
| 12.| **cloudflare** | cloudflare dns provider |
| 13.| **namesilo** | namesilo dns provider |
| 14.| **godaddy** | GoDaddy |
| 15.| **51dns** | 51DNS |
| 16.| **新网互联** | 新网互联 |
<style module>
table th:first-of-type {

View File

@@ -2,10 +2,10 @@
| 序号 | 名称 | 说明 |
|-----|-----|-----|
| 1.| **企业微信通知** | 企业微信群聊机器人通知 |
| 2.| **电子邮件** | 电子邮件通知 |
| 3.| **爱语飞飞微信通知(iyuu)** | https://iyuu.cn/ |
| 4.| **自定义webhook** | 根据模版自定义http请求 |
| 1.| **电子邮件** | 电子邮件通知 |
| 2.| **自定义webhook** | 根据模版自定义http请求 |
| 3.| **企业微信通知** | 企业微信群聊机器人通知 |
| 4.| **爱语飞飞微信通知(iyuu)** | https://iyuu.cn/ |
| 5.| **Server酱ᵀ** | https://sct.ftqq.com/ |
| 6.| **Server酱³** | https://doc.sc3.ft07.com/serverchan3 |
| 7.| **AnPush** | https://anpush.com |
@@ -17,6 +17,7 @@
| 13.| **钉钉通知** | 钉钉群聊通知 |
| 14.| **VoceChat通知** | https://voce.chat |
| 15.| **OneBot V11 通知** | 通过动态拼接URL发送 OneBot V11 协议消息 |
| 16.| **MeoW通知** | https://api.chuckfang.com/ |
<style module>
table th:first-of-type {

View File

@@ -9,5 +9,5 @@
}
},
"npmClient": "pnpm",
"version": "1.37.3"
"version": "1.37.4"
}

View File

@@ -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.4](https://github.com/publishlab/node-acme-client/compare/v1.37.3...v1.37.4) (2025-10-28)
**Note:** Version bump only for package @certd/acme-client
## [1.37.3](https://github.com/publishlab/node-acme-client/compare/v1.37.2...v1.37.3) (2025-10-24)
### Bug Fixes

View File

@@ -3,7 +3,7 @@
"description": "Simple and unopinionated ACME client",
"private": false,
"author": "nmorsman",
"version": "1.37.3",
"version": "1.37.4",
"type": "module",
"module": "scr/index.js",
"main": "src/index.js",
@@ -18,7 +18,7 @@
"types"
],
"dependencies": {
"@certd/basic": "^1.37.3",
"@certd/basic": "^1.37.4",
"@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": "e1daaf07ce2fda6ce44998d65f8a989fc6af88db"
"gitHead": "335745d3651461fcc934154238a98a85be455e4f"
}

View File

@@ -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.4](https://github.com/certd/certd/compare/v1.37.3...v1.37.4) (2025-10-28)
**Note:** Version bump only for package @certd/basic
## [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

View File

@@ -1 +1 @@
01:10
01:28

View File

@@ -1,7 +1,7 @@
{
"name": "@certd/basic",
"private": false,
"version": "1.37.3",
"version": "1.37.4",
"type": "module",
"main": "./dist/index.js",
"module": "./dist/index.js",
@@ -46,5 +46,5 @@
"tslib": "^2.8.1",
"typescript": "^5.4.2"
},
"gitHead": "e1daaf07ce2fda6ce44998d65f8a989fc6af88db"
"gitHead": "335745d3651461fcc934154238a98a85be455e4f"
}

View File

@@ -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.4](https://github.com/certd/certd/compare/v1.37.3...v1.37.4) (2025-10-28)
**Note:** Version bump only for package @certd/pipeline
## [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

View File

@@ -1,7 +1,7 @@
{
"name": "@certd/pipeline",
"private": false,
"version": "1.37.3",
"version": "1.37.4",
"type": "module",
"main": "./dist/index.js",
"module": "./dist/index.js",
@@ -18,8 +18,8 @@
"compile": "tsc --skipLibCheck --watch"
},
"dependencies": {
"@certd/basic": "^1.37.3",
"@certd/plus-core": "^1.37.3",
"@certd/basic": "^1.37.4",
"@certd/plus-core": "^1.37.4",
"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": "e1daaf07ce2fda6ce44998d65f8a989fc6af88db"
"gitHead": "335745d3651461fcc934154238a98a85be455e4f"
}

View File

@@ -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.4](https://github.com/certd/certd/compare/v1.37.3...v1.37.4) (2025-10-28)
**Note:** Version bump only for package @certd/lib-huawei
## [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

View File

@@ -1,7 +1,7 @@
{
"name": "@certd/lib-huawei",
"private": false,
"version": "1.37.3",
"version": "1.37.4",
"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": "e1daaf07ce2fda6ce44998d65f8a989fc6af88db"
"gitHead": "335745d3651461fcc934154238a98a85be455e4f"
}

View File

@@ -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.4](https://github.com/certd/certd/compare/v1.37.3...v1.37.4) (2025-10-28)
**Note:** Version bump only for package @certd/lib-iframe
## [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

View File

@@ -1,7 +1,7 @@
{
"name": "@certd/lib-iframe",
"private": false,
"version": "1.37.3",
"version": "1.37.4",
"type": "module",
"main": "./dist/index.js",
"module": "./dist/index.js",
@@ -31,5 +31,5 @@
"tslib": "^2.8.1",
"typescript": "^5.4.2"
},
"gitHead": "e1daaf07ce2fda6ce44998d65f8a989fc6af88db"
"gitHead": "335745d3651461fcc934154238a98a85be455e4f"
}

View File

@@ -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.4](https://github.com/certd/certd/compare/v1.37.3...v1.37.4) (2025-10-28)
**Note:** Version bump only for package @certd/jdcloud
## [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

View File

@@ -1,6 +1,6 @@
{
"name": "@certd/jdcloud",
"version": "1.37.3",
"version": "1.37.4",
"description": "jdcloud openApi sdk",
"main": "./dist/bundle.js",
"module": "./dist/bundle.js",
@@ -61,5 +61,5 @@
"fetch"
]
},
"gitHead": "e1daaf07ce2fda6ce44998d65f8a989fc6af88db"
"gitHead": "335745d3651461fcc934154238a98a85be455e4f"
}

View File

@@ -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.4](https://github.com/certd/certd/compare/v1.37.3...v1.37.4) (2025-10-28)
**Note:** Version bump only for package @certd/lib-k8s
## [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

View File

@@ -1,7 +1,7 @@
{
"name": "@certd/lib-k8s",
"private": false,
"version": "1.37.3",
"version": "1.37.4",
"type": "module",
"main": "./dist/index.js",
"module": "./dist/index.js",
@@ -17,7 +17,7 @@
"pub": "npm publish"
},
"dependencies": {
"@certd/basic": "^1.37.3",
"@certd/basic": "^1.37.4",
"@kubernetes/client-node": "0.21.0"
},
"devDependencies": {
@@ -32,5 +32,5 @@
"tslib": "^2.8.1",
"typescript": "^5.4.2"
},
"gitHead": "e1daaf07ce2fda6ce44998d65f8a989fc6af88db"
"gitHead": "335745d3651461fcc934154238a98a85be455e4f"
}

View File

@@ -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.4](https://github.com/certd/certd/compare/v1.37.3...v1.37.4) (2025-10-28)
**Note:** Version bump only for package @certd/lib-server
## [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

View File

@@ -1,6 +1,6 @@
{
"name": "@certd/lib-server",
"version": "1.37.3",
"version": "1.37.4",
"description": "midway with flyway, sql upgrade way ",
"private": false,
"type": "module",
@@ -28,11 +28,11 @@
],
"license": "AGPL",
"dependencies": {
"@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",
"@certd/acme-client": "^1.37.4",
"@certd/basic": "^1.37.4",
"@certd/pipeline": "^1.37.4",
"@certd/plugin-lib": "^1.37.4",
"@certd/plus-core": "^1.37.4",
"@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": "e1daaf07ce2fda6ce44998d65f8a989fc6af88db"
"gitHead": "335745d3651461fcc934154238a98a85be455e4f"
}

View File

@@ -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.4](https://github.com/certd/certd/compare/v1.37.3...v1.37.4) (2025-10-28)
**Note:** Version bump only for package @certd/midway-flyway-js
## [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

View File

@@ -1,6 +1,6 @@
{
"name": "@certd/midway-flyway-js",
"version": "1.37.3",
"version": "1.37.4",
"description": "midway with flyway, sql upgrade way ",
"private": false,
"type": "module",
@@ -46,5 +46,5 @@
"typeorm": "^0.3.11",
"typescript": "^5.4.2"
},
"gitHead": "e1daaf07ce2fda6ce44998d65f8a989fc6af88db"
"gitHead": "335745d3651461fcc934154238a98a85be455e4f"
}

View File

@@ -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.4](https://github.com/certd/certd/compare/v1.37.3...v1.37.4) (2025-10-28)
### Bug Fixes
* 修复lego模式下 私钥加密类型错误的bug ([f7cf7c1](https://github.com/certd/certd/commit/f7cf7c198d7f77b222099770f81accc637bc6619))
## [1.37.3](https://github.com/certd/certd/compare/v1.37.2...v1.37.3) (2025-10-24)
### Bug Fixes

View File

@@ -1,7 +1,7 @@
{
"name": "@certd/plugin-cert",
"private": false,
"version": "1.37.3",
"version": "1.37.4",
"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.3",
"@certd/basic": "^1.37.3",
"@certd/pipeline": "^1.37.3",
"@certd/plugin-lib": "^1.37.3",
"@certd/acme-client": "^1.37.4",
"@certd/basic": "^1.37.4",
"@certd/pipeline": "^1.37.4",
"@certd/plugin-lib": "^1.37.4",
"@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": "e1daaf07ce2fda6ce44998d65f8a989fc6af88db"
"gitHead": "335745d3651461fcc934154238a98a85be455e4f"
}

View File

@@ -158,7 +158,7 @@ export class CertApplyLegoPlugin extends CertApplyBasePlugin {
if (this.eab) {
eabArgs = ` --eab --kid "${this.eab.kid}" --hmac "${this.eab.hmacKey}"`;
}
const keyType = `-k ${this.privateKeyType}`;
const keyType = `-k ${this.privateKeyType?.replaceAll("_", "")}`;
const saveDir = `./data/.lego/pipeline_${this.pipeline.id}/`;
const savePathArgs = `--path "${saveDir}"`;

View File

@@ -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.4](https://github.com/certd/certd/compare/v1.37.3...v1.37.4) (2025-10-28)
**Note:** Version bump only for package @certd/plugin-lib
## [1.37.3](https://github.com/certd/certd/compare/v1.37.2...v1.37.3) (2025-10-24)
### Performance Improvements

View File

@@ -1,7 +1,7 @@
{
"name": "@certd/plugin-lib",
"private": false,
"version": "1.37.3",
"version": "1.37.4",
"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.3",
"@certd/pipeline": "^1.37.3",
"@certd/basic": "^1.37.4",
"@certd/pipeline": "^1.37.4",
"@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": "e1daaf07ce2fda6ce44998d65f8a989fc6af88db"
"gitHead": "335745d3651461fcc934154238a98a85be455e4f"
}

View File

@@ -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.4](https://github.com/certd/certd/compare/v1.37.3...v1.37.4) (2025-10-28)
### Bug Fixes
* 修复站点证书监控复制按钮无效的bug ([efa26a0](https://github.com/certd/certd/commit/efa26a067f06402f30befc016d9934cadcd5a563))
## [1.37.3](https://github.com/certd/certd/compare/v1.37.2...v1.37.3) (2025-10-24)
### Performance Improvements

View File

@@ -1,6 +1,6 @@
{
"name": "@certd/ui-client",
"version": "1.37.3",
"version": "1.37.4",
"private": true,
"scripts": {
"dev": "vite --open",
@@ -106,8 +106,8 @@
"zod-defaults": "^0.1.3"
},
"devDependencies": {
"@certd/lib-iframe": "^1.37.3",
"@certd/pipeline": "^1.37.3",
"@certd/lib-iframe": "^1.37.4",
"@certd/pipeline": "^1.37.4",
"@rollup/plugin-commonjs": "^25.0.7",
"@rollup/plugin-node-resolve": "^15.2.3",
"@types/chai": "^4.3.12",

View File

@@ -56,10 +56,10 @@ function onChange(data: any) {
}
async function getCaptchaForm() {
return await captchaRef.value.getCaptchaForm();
return await captchaRef.value?.getCaptchaForm();
}
async function reset() {
await captchaRef.value.reset();
await captchaRef.value?.reset();
}
defineExpose({
getCaptchaForm,

View File

@@ -53,6 +53,13 @@ function callback(res: { ret: number; ticket: string; randstr: string; errorCode
// res验证成功 = {ret: 0, ticket: "String", randstr: "String"}
// res请求验证码发生错误验证码自动返回trerror_前缀的容灾票据 = {ret: 0, ticket: "String", randstr: "String", errorCode: Number, errorMessage: "String"}
// 此处代码仅为验证结果的展示示例真实业务接入建议基于ticket和errorCode情况做不同的业务处理
if (res.errorCode && res.errorCode > 0) {
notification.error({
message: `验证码验证失败:${res.errorMessage || res.errorCode}`,
});
}
if (res.ret === 0) {
emitChange({
ticket: res.ticket,
@@ -116,7 +123,7 @@ function emitChange(value: any) {
emit("change", value);
}
function reset() {
captchaInstanceRef.value.instance.reset();
captchaInstanceRef.value?.instance?.reset();
}
watch(

View File

@@ -33,6 +33,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
const addRequest = async (req: AddReq) => {
const { form } = req;
delete form.id;
const res = await api.AddObj(form);
return res;
};

View File

@@ -61,7 +61,7 @@
</a-input-password>
</a-form-item>
<a-form-item has-feedback name="imgCode" label="验证码" :rules="rules.imgCode">
<a-form-item has-feedback name="captchaForEmail" label="验证码" :rules="rules.captchaForEmail">
<CaptchaInput v-model:model-value="formState.captchaForEmail"></CaptchaInput>
</a-form-item>
@@ -118,6 +118,7 @@ export default defineComponent({
password: "",
confirmPassword: "",
captcha: null,
captchaForEmail: null,
});
const rules = {
@@ -180,10 +181,10 @@ export default defineComponent({
message: "请通过验证码",
},
],
imgCode: [
captchaForEmail: [
{
required: true,
message: "请输入验证码",
message: "请通过验证码",
},
],
};
@@ -204,7 +205,7 @@ export default defineComponent({
password: formState.password,
username: formState.username,
email: formState.email,
captcha: formState.captcha,
captcha: registerType.value === "email" ? formState.captchaForEmail : formState.captcha,
validateCode: formState.validateCode,
}) as any
);

View File

@@ -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.4](https://github.com/certd/certd/compare/v1.37.3...v1.37.4) (2025-10-28)
### Performance Improvements
* 优化数据备份效率,流式写入文件 ([c38dbbb](https://github.com/certd/certd/commit/c38dbbb1d72bd00a92fe275b76aea82a791e7199))
## [1.37.3](https://github.com/certd/certd/compare/v1.37.2...v1.37.3) (2025-10-24)
### Bug Fixes

View File

@@ -1,6 +1,6 @@
{
"name": "@certd/ui-server",
"version": "1.37.3",
"version": "1.37.4",
"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.3",
"@certd/basic": "^1.37.3",
"@certd/commercial-core": "^1.37.3",
"@certd/acme-client": "^1.37.4",
"@certd/basic": "^1.37.4",
"@certd/commercial-core": "^1.37.4",
"@certd/cv4pve-api-javascript": "^8.4.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",
"@certd/jdcloud": "^1.37.4",
"@certd/lib-huawei": "^1.37.4",
"@certd/lib-k8s": "^1.37.4",
"@certd/lib-server": "^1.37.4",
"@certd/midway-flyway-js": "^1.37.4",
"@certd/pipeline": "^1.37.4",
"@certd/plugin-cert": "^1.37.4",
"@certd/plugin-lib": "^1.37.4",
"@certd/plugin-plus": "^1.37.4",
"@certd/plus-core": "^1.37.4",
"@huaweicloud/huaweicloud-sdk-cdn": "^3.1.120",
"@huaweicloud/huaweicloud-sdk-core": "^3.1.120",
"@koa/cors": "^5.0.0",

View File

@@ -6,15 +6,15 @@ import { AbstractPlusTaskPlugin } from "@certd/plugin-plus";
import JSZip from "jszip";
import * as os from "node:os";
import { OssClientContext, ossClientFactory, OssClientRemoveByOpts, SshAccess, SshClient } from "@certd/plugin-lib";
const defaultBackupDir = 'certd_backup';
const defaultFilePrefix = 'db_backup';
import { pipeline } from "stream/promises";
const defaultBackupDir = "certd_backup";
const defaultFilePrefix = "db_backup";
@IsTaskPlugin({
name: 'DBBackupPlugin',
title: '数据库备份',
icon: 'lucide:database-backup',
desc: '【仅管理员可用】仅支持备份SQLite数据库',
name: "DBBackupPlugin",
title: "数据库备份",
icon: "lucide:database-backup",
desc: "【仅管理员可用】仅支持备份SQLite数据库",
group: pluginGroups.admin.key,
showRunStrategy: true,
default: {
@@ -22,32 +22,32 @@ const defaultFilePrefix = 'db_backup';
runStrategy: RunStrategy.AlwaysRun,
},
},
onlyAdmin:true,
onlyAdmin: true,
needPlus: true,
})
export class DBBackupPlugin extends AbstractPlusTaskPlugin {
@TaskInput({
title: '备份方式',
value: 'local',
title: "备份方式",
value: "local",
component: {
name: 'a-select',
name: "a-select",
options: [
{label: '本地复制', value: 'local'},
{label: 'ssh上传', value: 'ssh'},
{label: 'oss上传', value: 'oss'},
{ label: "本地复制", value: "local" },
{ label: "ssh上传", value: "ssh" },
{ label: "oss上传", value: "oss" },
],
placeholder: '',
placeholder: "",
},
helper: '支持本地复制、ssh上传',
helper: "支持本地复制、ssh上传",
required: true,
})
backupMode = 'local';
backupMode = "local";
@TaskInput({
title: '主机登录授权',
title: "主机登录授权",
component: {
name: 'access-selector',
type: 'ssh',
name: "access-selector",
type: "ssh",
},
mergeScript: `
return {
@@ -60,19 +60,18 @@ export class DBBackupPlugin extends AbstractPlusTaskPlugin {
})
sshAccessId!: number;
@TaskInput({
title: 'OSS类型',
title: "OSS类型",
component: {
name: 'a-select',
name: "a-select",
options: [
{value: "alioss", label: "阿里云OSS"},
{value: "s3", label: "MinIO/S3"},
{value: "qiniuoss", label: "七牛云"},
{value: "tencentcos", label: "腾讯云COS"},
{value: "ftp", label: "Ftp"},
{value: "sftp", label: "Sftp"},
]
{ value: "alioss", label: "阿里云OSS" },
{ value: "s3", label: "MinIO/S3" },
{ value: "qiniuoss", label: "七牛云" },
{ value: "tencentcos", label: "腾讯云COS" },
{ value: "ftp", label: "Ftp" },
{ value: "sftp", label: "Sftp" },
],
},
mergeScript: `
return {
@@ -86,9 +85,9 @@ export class DBBackupPlugin extends AbstractPlusTaskPlugin {
ossType!: string;
@TaskInput({
title: 'OSS授权',
title: "OSS授权",
component: {
name: 'access-selector',
name: "access-selector",
},
mergeScript: `
return {
@@ -106,12 +105,11 @@ export class DBBackupPlugin extends AbstractPlusTaskPlugin {
})
ossAccessId!: number;
@TaskInput({
title: '备份保存目录',
title: "备份保存目录",
component: {
name: 'a-input',
type: 'value',
name: "a-input",
type: "value",
placeholder: `默认${defaultBackupDir}`,
},
helper: `ssh方式默认保存在当前用户的${defaultBackupDir}目录下本地方式默认保存在data/${defaultBackupDir}目录下,也可以填写绝对路径`,
@@ -120,10 +118,10 @@ export class DBBackupPlugin extends AbstractPlusTaskPlugin {
backupDir: string = defaultBackupDir;
@TaskInput({
title: '备份文件前缀',
title: "备份文件前缀",
component: {
name: 'a-input',
vModel: 'value',
name: "a-input",
vModel: "value",
placeholder: `默认${defaultFilePrefix}`,
},
required: false,
@@ -131,11 +129,11 @@ export class DBBackupPlugin extends AbstractPlusTaskPlugin {
filePrefix: string = defaultFilePrefix;
@TaskInput({
title: '附加上传文件',
title: "附加上传文件",
value: true,
component: {
name: 'a-switch',
vModel: 'checked',
name: "a-switch",
vModel: "checked",
placeholder: `是否备份上传的头像等文件`,
},
required: false,
@@ -143,99 +141,119 @@ export class DBBackupPlugin extends AbstractPlusTaskPlugin {
withUpload = true;
@TaskInput({
title: '删除过期备份',
title: "删除过期备份",
component: {
name: 'a-input-number',
vModel: 'value',
placeholder: '20',
name: "a-input-number",
vModel: "value",
placeholder: "20",
},
helper: '删除多少天前的备份,不填则不删除windows暂不支持',
helper: "删除多少天前的备份,不填则不删除windows暂不支持",
required: false,
})
retainDays!: number;
async onInstance() {
}
async onInstance() {}
async execute(): Promise<void> {
if (!this.isAdmin()) {
throw new Error('只有管理员才能运行此任务');
throw new Error("只有管理员才能运行此任务");
}
this.logger.info('开始备份数据库');
this.logger.info("开始备份数据库");
let dbPath = process.env.certd_typeorm_dataSource_default_database;
dbPath = dbPath || './data/db.sqlite';
dbPath = dbPath || "./data/db.sqlite";
if (!fs.existsSync(dbPath)) {
this.logger.error('数据库文件不存在:', dbPath);
this.logger.error("数据库文件不存在:", dbPath);
return;
}
const dbTmpFilename = `${this.filePrefix}_${dayjs().format('YYYYMMDD_HHmmss')}_sqlite`;
const dbTmpFilename = `${this.filePrefix}_${dayjs().format("YYYYMMDD_HHmmss")}_sqlite`;
const dbZipFilename = `${dbTmpFilename}.zip`;
const tempDir = path.resolve(os.tmpdir(), 'certd_backup');
const tempDir = path.resolve(os.tmpdir(), "certd_backup");
if (!fs.existsSync(tempDir)) {
await fs.promises.mkdir(tempDir, {recursive: true});
await fs.promises.mkdir(tempDir, { recursive: true });
}
const dbTmpPath = path.resolve(tempDir, dbTmpFilename);
const dbZipPath = path.resolve(tempDir, dbZipFilename);
//复制到临时目录
await fs.promises.copyFile(dbPath, dbTmpPath);
//本地压缩
const zip = new JSZip();
const stream = fs.createReadStream(dbTmpPath);
// 使用流的方式添加文件内容
zip.file(dbTmpFilename, stream, {binary: true, compression: 'DEFLATE'});
try {
//复制到临时目录
await fs.promises.copyFile(dbPath, dbTmpPath);
// //本地压缩
// const zip = new JSZip();
// const stream = fs.createReadStream(dbTmpPath);
// // 使用流的方式添加文件内容
// zip.file(dbTmpFilename, stream, {binary: true, compression: 'DEFLATE'});
const uploadDir = path.resolve('data', 'upload');
if (this.withUpload && fs.existsSync(uploadDir)) {
zip.folder(uploadDir);
}
// const uploadDir = path.resolve('data', 'upload');
// if (this.withUpload && fs.existsSync(uploadDir)) {
// zip.folder(uploadDir);
// }
const content = await zip.generateAsync({type: 'nodebuffer'});
// const content = await zip.generateAsync({type: 'nodebuffer'});
await fs.promises.writeFile(dbZipPath, content);
this.logger.info(`数据库文件压缩完成:${dbZipPath}`);
// await fs.promises.writeFile(dbZipPath, content);
// 创建可写流
const outputStream = fs.createWriteStream(dbZipPath);
const zip = new JSZip();
this.logger.info('开始备份,当前备份方式:', this.backupMode);
const backupDir = this.backupDir || defaultBackupDir;
const backupFilePath = `${backupDir}/${dbZipFilename}`;
// 添加数据库文件
const dbStream = fs.createReadStream(dbTmpPath);
zip.file(dbTmpFilename, dbStream, { binary: true, compression: "DEFLATE" });
try{
if (this.backupMode === 'local') {
// 处理上传目录
const uploadDir = path.resolve("data", "upload");
if (this.withUpload && fs.existsSync(uploadDir)) {
zip.folder("upload"); // 注意:这里应该是相对路径
}
// 使用流式生成
const zipStream = zip.generateNodeStream({
type: "nodebuffer",
streamFiles: true,
compression: "DEFLATE",
});
// 管道传输
await pipeline(zipStream, outputStream);
this.logger.info(`数据库文件压缩完成:${dbZipPath}`);
this.logger.info("开始备份,当前备份方式:", this.backupMode);
const backupDir = this.backupDir || defaultBackupDir;
const backupFilePath = `${backupDir}/${dbZipFilename}`;
if (this.backupMode === "local") {
await this.localBackup(dbZipPath, backupDir, backupFilePath);
} else if (this.backupMode === 'ssh') {
} else if (this.backupMode === "ssh") {
await this.sshBackup(dbZipPath, backupDir, backupFilePath);
} else if (this.backupMode === 'oss') {
} else if (this.backupMode === "oss") {
await this.ossBackup(dbZipPath, backupDir, backupFilePath);
} else {
throw new Error(`不支持的备份方式:${this.backupMode}`);
}
}finally{
} finally {
//删除临时目录
await fs.promises.rm(tempDir, {recursive: true, force: true});
await fs.promises.rm(tempDir, { recursive: true, force: true });
}
this.logger.info('数据库备份完成');
this.logger.info("数据库备份完成");
}
private async localBackup(dbPath: string, backupDir: string, backupPath: string) {
if (!backupPath.startsWith('/')) {
backupPath = path.join('./data/', backupPath);
if (!backupPath.startsWith("/")) {
backupPath = path.join("./data/", backupPath);
}
const dir = path.dirname(backupPath);
if (!fs.existsSync(dir)) {
await fs.promises.mkdir(dir, {recursive: true});
await fs.promises.mkdir(dir, { recursive: true });
}
backupPath = path.resolve(backupPath);
await fs.promises.copyFile(dbPath, backupPath);
this.logger.info('备份文件路径:', backupPath);
this.logger.info("备份文件路径:", backupPath);
if (this.retainDays > 0) {
// 删除过期备份
this.logger.info('开始删除过期备份文件');
this.logger.info("开始删除过期备份文件");
const files = fs.readdirSync(dir);
const now = Date.now();
let count = 0;
@@ -245,76 +263,76 @@ export class DBBackupPlugin extends AbstractPlusTaskPlugin {
if (now - stat.mtimeMs > this.retainDays * 24 * 60 * 60 * 1000) {
fs.unlinkSync(filePath as fs.PathLike);
count++;
this.logger.info('删除过期备份文件:', filePath);
this.logger.info("删除过期备份文件:", filePath);
}
});
this.logger.info('删除过期备份文件数:', count);
this.logger.info("删除过期备份文件数:", count);
}
}
private async sshBackup(dbPath: string, backupDir: string, backupPath: string) {
const access: SshAccess = await this.getAccess(this.sshAccessId);
const sshClient = new SshClient(this.logger);
this.logger.info('备份目录:', backupPath);
this.logger.info("备份目录:", backupPath);
await sshClient.uploadFiles({
connectConf: access,
transports: [{localPath: dbPath, remotePath: backupPath}],
transports: [{ localPath: dbPath, remotePath: backupPath }],
mkdirs: true,
});
this.logger.info('备份文件上传完成');
this.logger.info("备份文件上传完成");
if (this.retainDays > 0) {
// 删除过期备份
this.logger.info('开始删除过期备份文件');
this.logger.info("开始删除过期备份文件");
const isWin = access.windows;
let script: string[] = [];
if (isWin) {
throw new Error('删除过期文件暂不支持windows系统');
throw new Error("删除过期文件暂不支持windows系统");
// script = `forfiles /p ${backupDir} /s /d -${this.retainDays} /c "cmd /c del @path"`;
} else {
script = [`cd ${backupDir}`, 'echo 备份目录', 'pwd', `find . -type f -mtime +${this.retainDays} -name '${this.filePrefix}*' -exec rm -f {} \\;`];
script = [`cd ${backupDir}`, "echo 备份目录", "pwd", `find . -type f -mtime +${this.retainDays} -name '${this.filePrefix}*' -exec rm -f {} \\;`];
}
await sshClient.exec({
connectConf: access,
script,
});
this.logger.info('删除过期备份文件完成');
this.logger.info("删除过期备份文件完成");
}
}
private async ossBackup(dbPath: string, backupDir: string, backupPath: string) {
if (!this.ossAccessId) {
throw new Error('未配置ossAccessId');
throw new Error("未配置ossAccessId");
}
const access = await this.getAccess(this.ossAccessId);
const ossType = this.ossType
const ossType = this.ossType;
const ctx: OssClientContext = {
logger: this.logger,
utils: this.ctx.utils,
accessService:this.accessService
}
accessService: this.accessService,
};
this.logger.info(`开始备份文件到:${ossType}`);
const client = await ossClientFactory.createOssClientByType(ossType, {
const client = await ossClientFactory.createOssClientByType(ossType, {
access,
ctx,
})
});
await client.upload(backupPath, dbPath);
if (this.retainDays > 0) {
// 删除过期备份
this.logger.info('开始删除过期备份文件');
this.logger.info("开始删除过期备份文件");
const removeByOpts: OssClientRemoveByOpts = {
dir: backupDir,
beforeDays: this.retainDays,
};
await client.removeBy(removeByOpts);
this.logger.info('删除过期备份文件完成');
}else{
this.logger.info('已禁止删除过期文件');
this.logger.info("删除过期备份文件完成");
} else {
this.logger.info("已禁止删除过期文件");
}
}
}

View File

@@ -3,57 +3,54 @@ import { ICaptchaAddon } from "../api.js";
import { TencentAccess } from "@certd/plugin-lib";
@IsAddon({
addonType:"captcha",
name: 'tencent',
title: '腾讯云验证码',
desc: '',
showTest:false,
addonType: "captcha",
name: "tencent",
title: "腾讯云验证码",
desc: "",
showTest: false,
})
export class TencentCaptcha extends BaseAddon implements ICaptchaAddon{
export class TencentCaptcha extends BaseAddon implements ICaptchaAddon {
@AddonInput({
title: '腾讯云授权',
helper: '腾讯云授权',
title: "腾讯云授权",
helper: "腾讯云授权",
component: {
name: 'access-selector',
vModel:"modelValue",
name: "access-selector",
vModel: "modelValue",
from: "sys",
type: 'tencent', //固定授权类型
type: "tencent", //固定授权类型
},
required: true,
})
accessId :number;
accessId: number;
@AddonInput({
title: '验证ID',
title: "验证ID",
component: {
name:"a-input-number",
placeholder: 'CaptchaAppId',
name: "a-input-number",
placeholder: "CaptchaAppId",
},
helper:"[腾讯云验证码](https://cloud.tencent.com/act/cps/redirect?redirect=37716&cps_key=b3ef73330335d7a6efa4a4bbeeb6b2c9)",
helper: "[腾讯云验证码](https://cloud.tencent.com/act/cps/redirect?redirect=37716&cps_key=b3ef73330335d7a6efa4a4bbeeb6b2c9)",
required: true,
})
captchaAppId:number;
captchaAppId: number;
@AddonInput({
title: '验证Key',
title: "验证Key",
component: {
placeholder: 'AppSecretKey',
placeholder: "AppSecretKey",
},
required: true,
})
appSecretKey = '';
appSecretKey = "";
async onValidate(data?:any) {
async onValidate(data?: any) {
if (!data) {
return false
return false;
}
const access = await this.getAccess<TencentAccess>(this.accessId);
const access = await this.getAccess<TencentAccess>(this.accessId)
const sdk =await import("tencentcloud-sdk-nodejs/tencentcloud/services/captcha/v20190722/index.js");
const sdk = await import("tencentcloud-sdk-nodejs/tencentcloud/services/captcha/v20190722/index.js");
const CaptchaClient = sdk.v20190722.Client;
@@ -70,35 +67,40 @@ export class TencentCaptcha extends BaseAddon implements ICaptchaAddon{
},
};
// 实例化要请求产品的client对象,clientProfile是可选的
// 实例化要请求产品的client对象,clientProfile是可选的
const client = new CaptchaClient(clientConfig);
const params = {
"CaptchaType": 9, //固定值9
"UserIp": "127.0.0.1",
"Ticket": data.ticket,
"Randstr": data.randstr,
"AppSecretKey": this.appSecretKey,
"CaptchaAppId": this.captchaAppId,
CaptchaType: 9, //固定值9
UserIp: "127.0.0.1",
Ticket: data.ticket,
Randstr: data.randstr,
AppSecretKey: this.appSecretKey,
CaptchaAppId: this.captchaAppId,
};
const res = await client.DescribeCaptchaResult(params)
if (res.CaptchaCode == 1) {
// 验证成功
// verification successful
return true;
} else {
// 验证失败
// verification failed
this.logger.error("腾讯云验证码验证失败",res.CaptchaMsg)
return false;
try {
const res = await client.DescribeCaptchaResult(params);
if (res.CaptchaCode == 1) {
// 验证成功
// verification successful
return true;
} else {
// 验证失败
// verification failed
this.logger.error("腾讯云验证码验证失败", res.CaptchaMsg);
return false;
}
} catch (err) {
if (data.ticket.startsWith("trerror_") && err.message.includes("账户已欠费")) {
this.logger.error("腾讯云验证码账户欠费,临时放行:", err.message);
return true;
}
throw err
}
}
async getCaptcha(): Promise<any> {
async getCaptcha(): Promise<any> {
return {
captchaAppId: this.captchaAppId,
}
};
}
}

View File

@@ -1 +1 @@
22:52
01:14

View File

@@ -1 +1 @@
23:24
01:26