mirror of
https://github.com/certd/certd.git
synced 2026-04-14 20:40:53 +08:00
Compare commits
67 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0725c663c4 | ||
|
|
ce82239c8b | ||
|
|
2523008cb6 | ||
|
|
69212b9ad1 | ||
|
|
636cb3399b | ||
|
|
86ca35ce33 | ||
|
|
675ab31305 | ||
|
|
83c2d743bc | ||
|
|
2c87b3d906 | ||
|
|
05b6159802 | ||
|
|
c56f48c1e3 | ||
|
|
e18e399ce6 | ||
|
|
d66ade4e47 | ||
|
|
90b045af6d | ||
|
|
5cccb21175 | ||
|
|
1a71969403 | ||
|
|
389a1fbd04 | ||
|
|
ca02ae6183 | ||
|
|
92446cb048 | ||
|
|
954ce4533f | ||
|
|
f7b88f9e3b | ||
|
|
736fe038eb | ||
|
|
abcd257db0 | ||
|
|
c38b5f3cdc | ||
|
|
b649617e04 | ||
|
|
a4e2287101 | ||
|
|
fbb66f3c43 | ||
|
|
fedf90ea78 | ||
|
|
d558d50102 | ||
|
|
656cb89fe8 | ||
|
|
1e6ddd250e | ||
|
|
1de8eee6ea | ||
|
|
425bba67c5 | ||
|
|
8b0daf7200 | ||
|
|
589a373142 | ||
|
|
0cfc71e4bf | ||
|
|
92dabe6276 | ||
|
|
d1b61b6bf9 | ||
|
|
873f2b618b | ||
|
|
4453070060 | ||
|
|
de40be430b | ||
|
|
29a6a992f0 | ||
|
|
0a7d2d6264 | ||
|
|
e09f92f9ee | ||
|
|
9be1ecc8aa | ||
|
|
729b19c8da | ||
|
|
a9fffa5180 | ||
|
|
0069c0e399 | ||
|
|
b6fd38e293 | ||
|
|
36aa7f82b0 | ||
|
|
d01004d530 | ||
|
|
d85a02feeb | ||
|
|
b82e1dcd62 | ||
|
|
74c6a2266f | ||
|
|
9754223f31 | ||
|
|
cfbbac9796 | ||
|
|
fece8955cf | ||
|
|
170b2afb0e | ||
|
|
ee8af18d0a | ||
|
|
27386ea04d | ||
|
|
0d71a8ee50 | ||
|
|
82a72e0b49 | ||
|
|
5035c123f0 | ||
|
|
474b3372d8 | ||
|
|
be87124ada | ||
|
|
aa3032db35 | ||
|
|
a4ead79888 |
61
CHANGELOG.md
61
CHANGELOG.md
@@ -3,6 +3,67 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.31.7](https://github.com/certd/certd/compare/v1.31.6...v1.31.7) (2025-03-24)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 增加服务器时间警告 ([d66ade4](https://github.com/certd/certd/commit/d66ade4e4783850b6c7625c6f164a5a0fc0aa509))
|
||||||
|
* 支持部署到lucky ([e18e399](https://github.com/certd/certd/commit/e18e399ce6529e8c7e36b56c5f674cfdbbd3d3d1))
|
||||||
|
|
||||||
|
## [1.31.6](https://github.com/certd/certd/compare/v1.31.5...v1.31.6) (2025-03-24)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复dns.la无法申请证书的bug ([90b045a](https://github.com/certd/certd/commit/90b045af6d1a4f46986e4b118885c1f050df067c))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 上传到主机支持scp方式 ([05b6159](https://github.com/certd/certd/commit/05b6159802b9e85b6a410361b60b5c28875b48e7))
|
||||||
|
* 优化图标 ([c56f48c](https://github.com/certd/certd/commit/c56f48c1e3c54c4e203fafb380d9091d75681b7e))
|
||||||
|
|
||||||
|
## [1.31.5](https://github.com/certd/certd/compare/v1.31.4...v1.31.5) (2025-03-22)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复通知选择器无法选择的bug ([f7b88f9](https://github.com/certd/certd/commit/f7b88f9e3b7d9d9122e4fd2003a20c555bd50c7d))
|
||||||
|
* 修复证书流水线创建失败的bug ([736fe03](https://github.com/certd/certd/commit/736fe038ebda56648bcc4c12884a700341d2c049))
|
||||||
|
|
||||||
|
## [1.31.4](https://github.com/certd/certd/compare/v1.31.3...v1.31.4) (2025-03-21)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复站点监控通知通过webhook发送失败的bug ([9be1ecc](https://github.com/certd/certd/commit/9be1ecc8aab3ea23dd0dc2dab3688f4edb90ef2c))
|
||||||
|
* 修复dns.la域名申请失败的bug ([1de8eee](https://github.com/certd/certd/commit/1de8eee6ea8307f3c11626af75303d3cc104bb95))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 宝塔支持doker站点证书部署 ([589a373](https://github.com/certd/certd/commit/589a373142ef7f50d64d3aa767a90b1f4b64da93))
|
||||||
|
* 保存调整后的列宽 ([873f2b6](https://github.com/certd/certd/commit/873f2b618b9d7320045baf69d6da83afe48a780f))
|
||||||
|
* 创建证书流水线时,支持更多参数展开 ([36aa7f8](https://github.com/certd/certd/commit/36aa7f82b078a053a102331b3c6f132fb9d492f9))
|
||||||
|
* 流水线页面可以鼠标按住左右拖动 ([d85a02f](https://github.com/certd/certd/commit/d85a02feeb3183c5abd6c1ea790d5923a32d7271))
|
||||||
|
* 流水线增加上传证书快捷方式 ([425bba6](https://github.com/certd/certd/commit/425bba67c539b734e2a85a83a4f9ecc9b2434fb4))
|
||||||
|
* 手动上传证书部署流水线 ([fbb66f3](https://github.com/certd/certd/commit/fbb66f3c4389489aa8a43b194d82bc8cf391607b))
|
||||||
|
* 优化选择任务时手机版展示效果 ([d01004d](https://github.com/certd/certd/commit/d01004d53071a75ac91ee21cc96bde9369f77ff3))
|
||||||
|
* 站点监控,手动测试也发通知 ([729b19c](https://github.com/certd/certd/commit/729b19c8da60d5efb5baef7cf8df0518e7f6b471))
|
||||||
|
* 站点证书监控支持模糊查询 ([0069c0e](https://github.com/certd/certd/commit/0069c0e3992946a8dd6410f299d4fc974ef0e76b))
|
||||||
|
* 支持飞书通知 ([b82e1dc](https://github.com/certd/certd/commit/b82e1dcd6217b09a7d7e21cd648bb31de320cadf))
|
||||||
|
* 支持手动上传证书并部署 ([a9fffa5](https://github.com/certd/certd/commit/a9fffa5180c83da27b35886aa2e858a92a2c5f94))
|
||||||
|
|
||||||
|
## [1.31.3](https://github.com/certd/certd/compare/v1.31.2...v1.31.3) (2025-03-13)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复阿里云fc获取不到列表的bug ([474b337](https://github.com/certd/certd/commit/474b3372d8ce98e6d45900bf8046bc0b3f220686))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 1panel支持 apikey方式授权 ([170b2af](https://github.com/certd/certd/commit/170b2afb0e3b125e4ed057f633fe895b5ac3ac22))
|
||||||
|
* 套餐支持3天7天等选项 ([0d71a8e](https://github.com/certd/certd/commit/0d71a8ee501a0e5bb69decf07e8729026e9d85bf))
|
||||||
|
* 证书仓库增加有效期显示 ([be87124](https://github.com/certd/certd/commit/be87124ada7a093f281ca29a45c86b4ea4644ead))
|
||||||
|
* 支持部署到天翼云CDN ([82a72e0](https://github.com/certd/certd/commit/82a72e0b497efa043d342ad0e33c083a2de79a05))
|
||||||
|
* 支持dns.la ([ee8af18](https://github.com/certd/certd/commit/ee8af18d0ac0af82544d6dda1e4b4c678b733041))
|
||||||
|
* cf授权支持配置http代理 ([27386ea](https://github.com/certd/certd/commit/27386ea04d3c1a5aebe3cfdd7ac48185eaa76629))
|
||||||
|
|
||||||
## [1.31.2](https://github.com/certd/certd/compare/v1.31.1...v1.31.2) (2025-03-12)
|
## [1.31.2](https://github.com/certd/certd/compare/v1.31.1...v1.31.2) (2025-03-12)
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
23:33
|
23:52
|
||||||
|
|||||||
@@ -12,6 +12,9 @@ export default defineConfig({
|
|||||||
md.use(lightbox, {});
|
md.use(lightbox, {});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
sitemap: {
|
||||||
|
hostname: 'https://certd.docmirror.cn'
|
||||||
|
},
|
||||||
head: [
|
head: [
|
||||||
// [
|
// [
|
||||||
// 'meta',
|
// 'meta',
|
||||||
@@ -25,9 +28,9 @@ export default defineConfig({
|
|||||||
name: "keywords",
|
name: "keywords",
|
||||||
content: "证书自动申请、证书自动更新、证书自动续期、证书自动续签、证书管理工具、Certd、SSL证书自动部署、证书自动化,https证书,pfx证书,der证书,TLS证书,nginx证书自动续签自动部署,SSL平台,证书管理平台,证书流水线"
|
content: "证书自动申请、证书自动更新、证书自动续期、证书自动续签、证书管理工具、Certd、SSL证书自动部署、证书自动化,https证书,pfx证书,der证书,TLS证书,nginx证书自动续签自动部署,SSL平台,证书管理平台,证书流水线"
|
||||||
}],
|
}],
|
||||||
["meta", { name: "google-site-verification",content: "V5XLTSnXoT15uQotwpxJoQolUo2d5UbSL-TacsyOsC0"}],
|
// ["meta", { name: "google-site-verification",content: "V5XLTSnXoT15uQotwpxJoQolUo2d5UbSL-TacsyOsC0"}],
|
||||||
//<meta name="baidu-site-verification" content="codeva-MiWN8Y07Ua" />
|
//<meta name="baidu-site-verification" content="codeva-MiWN8Y07Ua" />
|
||||||
["meta", {name: "baidu-site-verification",content: "codeva-MiWN8Y07Ua"}],
|
// ["meta", {name: "baidu-site-verification",content: "codeva-MiWN8Y07Ua"}],
|
||||||
["link", { rel: "icon", href: "/static/logo/logo.svg" }]
|
["link", { rel: "icon", href: "/static/logo/logo.svg" }]
|
||||||
],
|
],
|
||||||
themeConfig: {
|
themeConfig: {
|
||||||
|
|||||||
@@ -3,6 +3,66 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.31.6](https://github.com/certd/certd/compare/v1.31.5...v1.31.6) (2025-03-24)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复dns.la无法申请证书的bug ([90b045a](https://github.com/certd/certd/commit/90b045af6d1a4f46986e4b118885c1f050df067c))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 上传到主机支持scp方式 ([05b6159](https://github.com/certd/certd/commit/05b6159802b9e85b6a410361b60b5c28875b48e7))
|
||||||
|
* 优化图标 ([c56f48c](https://github.com/certd/certd/commit/c56f48c1e3c54c4e203fafb380d9091d75681b7e))
|
||||||
|
|
||||||
|
## [1.31.5](https://github.com/certd/certd/compare/v1.31.4...v1.31.5) (2025-03-22)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复通知选择器无法选择的bug ([f7b88f9](https://github.com/certd/certd/commit/f7b88f9e3b7d9d9122e4fd2003a20c555bd50c7d))
|
||||||
|
* 修复证书流水线创建失败的bug ([736fe03](https://github.com/certd/certd/commit/736fe038ebda56648bcc4c12884a700341d2c049))
|
||||||
|
|
||||||
|
## [1.31.4](https://github.com/certd/certd/compare/v1.31.3...v1.31.4) (2025-03-21)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复站点监控通知通过webhook发送失败的bug ([9be1ecc](https://github.com/certd/certd/commit/9be1ecc8aab3ea23dd0dc2dab3688f4edb90ef2c))
|
||||||
|
* 修复dns.la域名申请失败的bug ([1de8eee](https://github.com/certd/certd/commit/1de8eee6ea8307f3c11626af75303d3cc104bb95))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 宝塔支持doker站点证书部署 ([589a373](https://github.com/certd/certd/commit/589a373142ef7f50d64d3aa767a90b1f4b64da93))
|
||||||
|
* 保存调整后的列宽 ([873f2b6](https://github.com/certd/certd/commit/873f2b618b9d7320045baf69d6da83afe48a780f))
|
||||||
|
* 创建证书流水线时,支持更多参数展开 ([36aa7f8](https://github.com/certd/certd/commit/36aa7f82b078a053a102331b3c6f132fb9d492f9))
|
||||||
|
* 流水线页面可以鼠标按住左右拖动 ([d85a02f](https://github.com/certd/certd/commit/d85a02feeb3183c5abd6c1ea790d5923a32d7271))
|
||||||
|
* 流水线增加上传证书快捷方式 ([425bba6](https://github.com/certd/certd/commit/425bba67c539b734e2a85a83a4f9ecc9b2434fb4))
|
||||||
|
* 手动上传证书部署流水线 ([fbb66f3](https://github.com/certd/certd/commit/fbb66f3c4389489aa8a43b194d82bc8cf391607b))
|
||||||
|
* 优化选择任务时手机版展示效果 ([d01004d](https://github.com/certd/certd/commit/d01004d53071a75ac91ee21cc96bde9369f77ff3))
|
||||||
|
* 站点监控,手动测试也发通知 ([729b19c](https://github.com/certd/certd/commit/729b19c8da60d5efb5baef7cf8df0518e7f6b471))
|
||||||
|
* 站点证书监控支持模糊查询 ([0069c0e](https://github.com/certd/certd/commit/0069c0e3992946a8dd6410f299d4fc974ef0e76b))
|
||||||
|
* 支持飞书通知 ([b82e1dc](https://github.com/certd/certd/commit/b82e1dcd6217b09a7d7e21cd648bb31de320cadf))
|
||||||
|
* 支持手动上传证书并部署 ([a9fffa5](https://github.com/certd/certd/commit/a9fffa5180c83da27b35886aa2e858a92a2c5f94))
|
||||||
|
|
||||||
|
## [1.31.3](https://github.com/certd/certd/compare/v1.31.2...v1.31.3) (2025-03-13)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复阿里云fc获取不到列表的bug ([474b337](https://github.com/certd/certd/commit/474b3372d8ce98e6d45900bf8046bc0b3f220686))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 1panel支持 apikey方式授权 ([170b2af](https://github.com/certd/certd/commit/170b2afb0e3b125e4ed057f633fe895b5ac3ac22))
|
||||||
|
* 套餐支持3天7天等选项 ([0d71a8e](https://github.com/certd/certd/commit/0d71a8ee501a0e5bb69decf07e8729026e9d85bf))
|
||||||
|
* 证书仓库增加有效期显示 ([be87124](https://github.com/certd/certd/commit/be87124ada7a093f281ca29a45c86b4ea4644ead))
|
||||||
|
* 支持部署到天翼云CDN ([82a72e0](https://github.com/certd/certd/commit/82a72e0b497efa043d342ad0e33c083a2de79a05))
|
||||||
|
* 支持dns.la ([ee8af18](https://github.com/certd/certd/commit/ee8af18d0ac0af82544d6dda1e4b4c678b733041))
|
||||||
|
* cf授权支持配置http代理 ([27386ea](https://github.com/certd/certd/commit/27386ea04d3c1a5aebe3cfdd7ac48185eaa76629))
|
||||||
|
|
||||||
|
## [1.31.2](https://github.com/certd/certd/compare/v1.31.1...v1.31.2) (2025-03-12)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复cname记录查找bug ([95fb4e3](https://github.com/certd/certd/commit/95fb4e3e8be6ca13cc43b451f6141d62190ba453))
|
||||||
|
|
||||||
## [1.31.1](https://github.com/certd/certd/compare/v1.31.0...v1.31.1) (2025-03-11)
|
## [1.31.1](https://github.com/certd/certd/compare/v1.31.0...v1.31.1) (2025-03-11)
|
||||||
|
|
||||||
### Performance Improvements
|
### Performance Improvements
|
||||||
|
|||||||
@@ -6,6 +6,10 @@
|
|||||||
|
|
||||||
## 2. 使用示例
|
## 2. 使用示例
|
||||||
```js
|
```js
|
||||||
|
|
||||||
|
// 如果需要引用第三方库,必须使用import语法
|
||||||
|
// const thirdSdk = await import("third-sdk-name")
|
||||||
|
|
||||||
const certPem = ctx.self.cert.crt
|
const certPem = ctx.self.cert.crt
|
||||||
const certKey = ctx.self.cert.key
|
const certKey = ctx.self.cert.key
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 51 KiB |
@@ -9,5 +9,5 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"npmClient": "pnpm",
|
"npmClient": "pnpm",
|
||||||
"version": "1.31.2"
|
"version": "1.31.7"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
"@lerna-lite/run": "^3.9.3",
|
"@lerna-lite/run": "^3.9.3",
|
||||||
"@lerna-lite/version": "^3.9.3",
|
"@lerna-lite/version": "^3.9.3",
|
||||||
"medium-zoom": "^1.1.0",
|
"medium-zoom": "^1.1.0",
|
||||||
"vitepress": "^1.4.1",
|
"vitepress": "^2.0.0-alpha.4",
|
||||||
"vitepress-plugin-lightbox": "^1.0.2"
|
"vitepress-plugin-lightbox": "^1.0.2"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
7
packages/core/acme-client/.prettierrc
Normal file
7
packages/core/acme-client/.prettierrc
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"printWidth": 220,
|
||||||
|
"bracketSpacing": true,
|
||||||
|
"singleQuote": false,
|
||||||
|
"trailingComma": "es5",
|
||||||
|
"arrowParens": "avoid"
|
||||||
|
}
|
||||||
@@ -3,6 +3,26 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.31.7](https://github.com/publishlab/node-acme-client/compare/v1.31.6...v1.31.7) (2025-03-24)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/acme-client
|
||||||
|
|
||||||
|
## [1.31.6](https://github.com/publishlab/node-acme-client/compare/v1.31.5...v1.31.6) (2025-03-24)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/acme-client
|
||||||
|
|
||||||
|
## [1.31.5](https://github.com/publishlab/node-acme-client/compare/v1.31.4...v1.31.5) (2025-03-22)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/acme-client
|
||||||
|
|
||||||
|
## [1.31.4](https://github.com/publishlab/node-acme-client/compare/v1.31.3...v1.31.4) (2025-03-21)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/acme-client
|
||||||
|
|
||||||
|
## [1.31.3](https://github.com/publishlab/node-acme-client/compare/v1.31.2...v1.31.3) (2025-03-13)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/acme-client
|
||||||
|
|
||||||
## [1.31.2](https://github.com/publishlab/node-acme-client/compare/v1.31.1...v1.31.2) (2025-03-12)
|
## [1.31.2](https://github.com/publishlab/node-acme-client/compare/v1.31.1...v1.31.2) (2025-03-12)
|
||||||
|
|
||||||
**Note:** Version bump only for package @certd/acme-client
|
**Note:** Version bump only for package @certd/acme-client
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"description": "Simple and unopinionated ACME client",
|
"description": "Simple and unopinionated ACME client",
|
||||||
"private": false,
|
"private": false,
|
||||||
"author": "nmorsman",
|
"author": "nmorsman",
|
||||||
"version": "1.31.2",
|
"version": "1.31.7",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"module": "scr/index.js",
|
"module": "scr/index.js",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
"types"
|
"types"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@certd/basic": "^1.31.2",
|
"@certd/basic": "^1.31.7",
|
||||||
"@peculiar/x509": "^1.11.0",
|
"@peculiar/x509": "^1.11.0",
|
||||||
"asn1js": "^3.0.5",
|
"asn1js": "^3.0.5",
|
||||||
"axios": "^1.7.2",
|
"axios": "^1.7.2",
|
||||||
@@ -30,6 +30,8 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^20.14.10",
|
"@types/node": "^20.14.10",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^8.26.1",
|
||||||
|
"@typescript-eslint/parser": "^8.26.1",
|
||||||
"chai": "^4.4.1",
|
"chai": "^4.4.1",
|
||||||
"chai-as-promised": "^7.1.2",
|
"chai-as-promised": "^7.1.2",
|
||||||
"eslint": "^8.57.0",
|
"eslint": "^8.57.0",
|
||||||
@@ -65,5 +67,5 @@
|
|||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/publishlab/node-acme-client/issues"
|
"url": "https://github.com/publishlab/node-acme-client/issues"
|
||||||
},
|
},
|
||||||
"gitHead": "2a4d64af9502881e2e553ea86a4479158cfa8918"
|
"gitHead": "86ca35ce3381b98b455538b11219d9856be5d0d6"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,10 +53,10 @@ export default async (client, userOpts) => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
client.getAccountUrl();
|
client.getAccountUrl();
|
||||||
log('[auto] Account URL already exists, skipping account registration');
|
log('[auto] Account URL already exists, skipping account registration( 证书申请账户已存在,跳过注册 )');
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
log('[auto] Registering account');
|
log('[auto] Registering account (注册证书申请账户)');
|
||||||
await client.createAccount(accountPayload);
|
await client.createAccount(accountPayload);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,7 +64,7 @@ export default async (client, userOpts) => {
|
|||||||
* Parse domains from CSR
|
* Parse domains from CSR
|
||||||
*/
|
*/
|
||||||
|
|
||||||
log('[auto] Parsing domains from Certificate Signing Request');
|
log('[auto] Parsing domains from Certificate Signing Request ');
|
||||||
const { commonName, altNames } = readCsrDomains(opts.csr);
|
const { commonName, altNames } = readCsrDomains(opts.csr);
|
||||||
const uniqueDomains = Array.from(new Set([commonName].concat(altNames).filter((d) => d)));
|
const uniqueDomains = Array.from(new Set([commonName].concat(altNames).filter((d) => d)));
|
||||||
|
|
||||||
@@ -120,20 +120,20 @@ export default async (client, userOpts) => {
|
|||||||
// throw new Error('测试异常');
|
// throw new Error('测试异常');
|
||||||
/* Challenge verification */
|
/* Challenge verification */
|
||||||
if (opts.skipChallengeVerification === true) {
|
if (opts.skipChallengeVerification === true) {
|
||||||
log(`[auto] [${d}] Skipping challenge verification since skipChallengeVerification=true,wait 60s`);
|
log(`[auto] [${d}] 跳过本地验证(skipChallengeVerification=true),等待 60s`);
|
||||||
await wait(60 * 1000);
|
await wait(60 * 1000);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
log(`[auto] [${d}] Running challenge verification, type = ${challenge.type}`);
|
log(`[auto] [${d}] 开始本地验证, type = ${challenge.type}`);
|
||||||
try {
|
try {
|
||||||
await client.verifyChallenge(authz, challenge);
|
await client.verifyChallenge(authz, challenge);
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
log(`[auto] [${d}] challenge verification threw error: ${e.message}`);
|
log(`[auto] [${d}] 本地验证失败,尝试请求ACME提供商获取状态: ${e.message}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Complete challenge and wait for valid status */
|
/* Complete challenge and wait for valid status */
|
||||||
log(`[auto] [${d}] Completing challenge with ACME provider and waiting for valid status`);
|
log(`[auto] [${d}] 请求ACME提供商完成验证,等待返回valid状态`);
|
||||||
await client.completeChallenge(challenge);
|
await client.completeChallenge(challenge);
|
||||||
challengeCompleted = true;
|
challengeCompleted = true;
|
||||||
|
|
||||||
|
|||||||
@@ -500,7 +500,7 @@ class AcmeClient {
|
|||||||
await verify[challenge.type](authz, challenge, keyAuthorization);
|
await verify[challenge.type](authz, challenge, keyAuthorization);
|
||||||
};
|
};
|
||||||
|
|
||||||
log('Waiting for ACME challenge verification', this.backoffOpts);
|
log('Waiting for ACME challenge verification(等待ACME挑战验证)', this.backoffOpts);
|
||||||
return util.retry(verifyFn, this.backoffOpts);
|
return util.retry(verifyFn, this.backoffOpts);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -568,14 +568,14 @@ class AcmeClient {
|
|||||||
const resp = await this.api.apiRequest(item.url, null, [200]);
|
const resp = await this.api.apiRequest(item.url, null, [200]);
|
||||||
|
|
||||||
/* Verify status */
|
/* Verify status */
|
||||||
log(`Item has status: ${resp.data.status}`);
|
log(`Item has status(挑战状态): ${resp.data.status}`);
|
||||||
|
|
||||||
if (invalidStates.includes(resp.data.status)) {
|
if (invalidStates.includes(resp.data.status)) {
|
||||||
abort();
|
abort();
|
||||||
throw new Error(util.formatResponseError(resp));
|
throw new Error(util.formatResponseError(resp));
|
||||||
}
|
}
|
||||||
else if (pendingStates.includes(resp.data.status)) {
|
else if (pendingStates.includes(resp.data.status)) {
|
||||||
throw new Error('Operation is pending or processing');
|
throw new Error('Operation is pending or processing(当前仍然在等待状态)');
|
||||||
}
|
}
|
||||||
else if (validStates.includes(resp.data.status)) {
|
else if (validStates.includes(resp.data.status)) {
|
||||||
return resp.data;
|
return resp.data;
|
||||||
@@ -584,7 +584,7 @@ class AcmeClient {
|
|||||||
throw new Error(`Unexpected item status: ${resp.data.status}`);
|
throw new Error(`Unexpected item status: ${resp.data.status}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
log(`Waiting for valid status from: ${item.url}`, this.backoffOpts);
|
log(`Waiting for valid status (等待valid状态): ${item.url}`, this.backoffOpts);
|
||||||
return util.retry(verifyFn, this.backoffOpts);
|
return util.retry(verifyFn, this.backoffOpts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -60,8 +60,9 @@ async function retryPromise(fn, attempts, backoff) {
|
|||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log(`Promise rejected: ${e.message}`);
|
||||||
const duration = backoff.duration();
|
const duration = backoff.duration();
|
||||||
log(`Promise rejected attempt #${backoff.attempts}, retrying in ${duration}ms: ${e.message}`);
|
log(`attempt #${backoff.attempts}, ${duration}ms 后重试: ${e.message}`);
|
||||||
|
|
||||||
await new Promise((resolve) => { setTimeout(resolve, duration); });
|
await new Promise((resolve) => { setTimeout(resolve, duration); });
|
||||||
return retryPromise(fn, attempts, backoff);
|
return retryPromise(fn, attempts, backoff);
|
||||||
@@ -241,7 +242,7 @@ async function resolveDomainBySoaRecord(recordName) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
async function getAuthoritativeDnsResolver(recordName) {
|
async function getAuthoritativeDnsResolver(recordName) {
|
||||||
log(`Locating authoritative NS records for name: ${recordName}`);
|
log(`Locating authoritative NS records for name: ${recordName} (获取域名的权威NS服务器)`);
|
||||||
const resolver = new dns.Resolver();
|
const resolver = new dns.Resolver();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -249,13 +250,14 @@ async function getAuthoritativeDnsResolver(recordName) {
|
|||||||
const domain = await resolveDomainBySoaRecord(recordName);
|
const domain = await resolveDomainBySoaRecord(recordName);
|
||||||
|
|
||||||
/* Resolve authoritative NS addresses */
|
/* Resolve authoritative NS addresses */
|
||||||
log(`Looking up authoritative NS records for domain: ${domain}`);
|
log(`Looking up authoritative NS records for domain(获取域名的权威NS服务器): ${domain}`);
|
||||||
const nsRecords = await dns.resolveNs(domain);
|
const nsRecords = await dns.resolveNs(domain);
|
||||||
|
log(`域名权威NS服务器:${nsRecords}`);
|
||||||
const nsAddrArray = await Promise.all(nsRecords.map(async (r) => dns.resolve4(r)));
|
const nsAddrArray = await Promise.all(nsRecords.map(async (r) => dns.resolve4(r)));
|
||||||
const nsAddresses = [].concat(...nsAddrArray).filter((a) => a);
|
const nsAddresses = [].concat(...nsAddrArray).filter((a) => a);
|
||||||
|
|
||||||
if (!nsAddresses.length) {
|
if (!nsAddresses.length) {
|
||||||
throw new Error(`Unable to locate any valid authoritative NS addresses for domain: ${domain}`);
|
throw new Error(`Unable to locate any valid authoritative NS addresses for domain(获取权威服务器IP失败): ${domain}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Authoritative NS success */
|
/* Authoritative NS success */
|
||||||
@@ -263,12 +265,12 @@ async function getAuthoritativeDnsResolver(recordName) {
|
|||||||
resolver.setServers(nsAddresses);
|
resolver.setServers(nsAddresses);
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
log(`Authoritative NS lookup error: ${e.message}`);
|
log(`Authoritative NS lookup error(获取权威NS服务器地址失败): ${e.message}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return resolver */
|
/* Return resolver */
|
||||||
const addresses = resolver.getServers();
|
const addresses = resolver.getServers();
|
||||||
log(`DNS resolver addresses: ${addresses.join(', ')}`);
|
log(`DNS resolver addresses(域名的权威NS服务器地址): ${addresses.join(', ')}`);
|
||||||
|
|
||||||
return resolver;
|
return resolver;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -113,14 +113,14 @@ export async function walkTxtRecord(recordName) {
|
|||||||
|
|
||||||
async function verifyDnsChallenge(authz, challenge, keyAuthorization, prefix = '_acme-challenge.') {
|
async function verifyDnsChallenge(authz, challenge, keyAuthorization, prefix = '_acme-challenge.') {
|
||||||
const recordName = `${prefix}${authz.identifier.value}`;
|
const recordName = `${prefix}${authz.identifier.value}`;
|
||||||
log(`Resolving DNS TXT from record: ${recordName}`);
|
log(`Resolving DNS TXT from record(解析DNS TXT记录): ${recordName}`);
|
||||||
const recordValues = await walkTxtRecord(recordName);
|
const recordValues = await walkTxtRecord(recordName);
|
||||||
log(`DNS query finished successfully, found ${recordValues.length} TXT records`);
|
log(`DNS query finished successfully(DNS查询成功), found ${recordValues.length} TXT records`);
|
||||||
if (!recordValues.length || !recordValues.includes(keyAuthorization)) {
|
if (!recordValues.length || !recordValues.includes(keyAuthorization)) {
|
||||||
throw new Error(`Authorization not found in DNS TXT record: ${recordName},need:${keyAuthorization},found:${recordValues}`);
|
throw new Error(`Authorization not found in DNS TXT record(没有找到需要的DNS TXT记录): ${recordName},need:${keyAuthorization},found:${recordValues}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
log(`Key authorization match for ${challenge.type}/${recordName}, ACME challenge verified`);
|
log(`Key authorization match for ${challenge.type}/${recordName}, ACME challenge verified(域名所有权校验成功)`);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
"@typescript-eslint/ban-ts-comment": "off",
|
"@typescript-eslint/ban-ts-comment": "off",
|
||||||
"@typescript-eslint/ban-ts-ignore": "off",
|
"@typescript-eslint/ban-ts-ignore": "off",
|
||||||
"@typescript-eslint/no-explicit-any": "off",
|
"@typescript-eslint/no-explicit-any": "off",
|
||||||
// "no-unused-expressions": "off",
|
"@typescript-eslint/no-empty-function": "off",
|
||||||
"max-len": [0, 160, 2, { "ignoreUrls": true }]
|
"@typescript-eslint/no-unused-vars": "off"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
7
packages/core/basic/.prettierrc
Normal file
7
packages/core/basic/.prettierrc
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"printWidth": 220,
|
||||||
|
"bracketSpacing": true,
|
||||||
|
"singleQuote": false,
|
||||||
|
"trailingComma": "es5",
|
||||||
|
"arrowParens": "avoid"
|
||||||
|
}
|
||||||
@@ -3,6 +3,28 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.31.7](https://github.com/certd/certd/compare/v1.31.6...v1.31.7) (2025-03-24)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/basic
|
||||||
|
|
||||||
|
## [1.31.6](https://github.com/certd/certd/compare/v1.31.5...v1.31.6) (2025-03-24)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/basic
|
||||||
|
|
||||||
|
## [1.31.5](https://github.com/certd/certd/compare/v1.31.4...v1.31.5) (2025-03-22)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/basic
|
||||||
|
|
||||||
|
## [1.31.4](https://github.com/certd/certd/compare/v1.31.3...v1.31.4) (2025-03-21)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/basic
|
||||||
|
|
||||||
|
## [1.31.3](https://github.com/certd/certd/compare/v1.31.2...v1.31.3) (2025-03-13)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 支持部署到天翼云CDN ([82a72e0](https://github.com/certd/certd/commit/82a72e0b497efa043d342ad0e33c083a2de79a05))
|
||||||
|
|
||||||
## [1.31.2](https://github.com/certd/certd/compare/v1.31.1...v1.31.2) (2025-03-12)
|
## [1.31.2](https://github.com/certd/certd/compare/v1.31.1...v1.31.2) (2025-03-12)
|
||||||
|
|
||||||
**Note:** Version bump only for package @certd/basic
|
**Note:** Version bump only for package @certd/basic
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
10:23
|
00:01
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@certd/basic",
|
"name": "@certd/basic",
|
||||||
"private": false,
|
"private": false,
|
||||||
"version": "1.31.2",
|
"version": "1.31.7",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
"module": "./dist/index.js",
|
"module": "./dist/index.js",
|
||||||
@@ -33,8 +33,8 @@
|
|||||||
"@types/lodash-es": "^4.17.12",
|
"@types/lodash-es": "^4.17.12",
|
||||||
"@types/mocha": "^10.0.1",
|
"@types/mocha": "^10.0.1",
|
||||||
"@types/node-forge": "^1.3.2",
|
"@types/node-forge": "^1.3.2",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.59.7",
|
"@typescript-eslint/eslint-plugin": "^8.26.1",
|
||||||
"@typescript-eslint/parser": "^5.59.7",
|
"@typescript-eslint/parser": "^8.26.1",
|
||||||
"chai": "4.3.10",
|
"chai": "4.3.10",
|
||||||
"eslint": "^8.41.0",
|
"eslint": "^8.41.0",
|
||||||
"eslint-config-prettier": "^8.8.0",
|
"eslint-config-prettier": "^8.8.0",
|
||||||
@@ -44,5 +44,5 @@
|
|||||||
"tslib": "^2.8.1",
|
"tslib": "^2.8.1",
|
||||||
"typescript": "^5.4.2"
|
"typescript": "^5.4.2"
|
||||||
},
|
},
|
||||||
"gitHead": "2a4d64af9502881e2e553ea86a4479158cfa8918"
|
"gitHead": "86ca35ce3381b98b455538b11219d9856be5d0d6"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,10 @@ function sha256(data: string, digest: BinaryToTextEncoding = 'hex') {
|
|||||||
return crypto.createHash('sha256').update(data).digest(digest);
|
return crypto.createHash('sha256').update(data).digest(digest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function hmacSha256(data: string, digest: BinaryToTextEncoding = 'base64') {
|
||||||
|
return crypto.createHmac('sha256', data).update(Buffer.alloc(0)).digest(digest);
|
||||||
|
}
|
||||||
|
|
||||||
function base64(data: string) {
|
function base64(data: string) {
|
||||||
return Buffer.from(data).toString('base64');
|
return Buffer.from(data).toString('base64');
|
||||||
}
|
}
|
||||||
@@ -14,4 +18,5 @@ export const hashUtils = {
|
|||||||
md5,
|
md5,
|
||||||
sha256,
|
sha256,
|
||||||
base64,
|
base64,
|
||||||
|
hmacSha256,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
"@typescript-eslint/ban-ts-comment": "off",
|
"@typescript-eslint/ban-ts-comment": "off",
|
||||||
"@typescript-eslint/ban-ts-ignore": "off",
|
"@typescript-eslint/ban-ts-ignore": "off",
|
||||||
"@typescript-eslint/no-explicit-any": "off",
|
"@typescript-eslint/no-explicit-any": "off",
|
||||||
// "no-unused-expressions": "off",
|
"@typescript-eslint/no-empty-function": "off",
|
||||||
"max-len": [0, 160, 2, { "ignoreUrls": true }]
|
"@typescript-eslint/no-unused-vars": "off"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
{
|
{
|
||||||
"printWidth": 160
|
"printWidth": 220,
|
||||||
|
"bracketSpacing": true,
|
||||||
|
"singleQuote": false,
|
||||||
|
"trailingComma": "es5",
|
||||||
|
"arrowParens": "avoid"
|
||||||
}
|
}
|
||||||
@@ -3,6 +3,34 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.31.7](https://github.com/certd/certd/compare/v1.31.6...v1.31.7) (2025-03-24)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/pipeline
|
||||||
|
|
||||||
|
## [1.31.6](https://github.com/certd/certd/compare/v1.31.5...v1.31.6) (2025-03-24)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/pipeline
|
||||||
|
|
||||||
|
## [1.31.5](https://github.com/certd/certd/compare/v1.31.4...v1.31.5) (2025-03-22)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/pipeline
|
||||||
|
|
||||||
|
## [1.31.4](https://github.com/certd/certd/compare/v1.31.3...v1.31.4) (2025-03-21)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复站点监控通知通过webhook发送失败的bug ([9be1ecc](https://github.com/certd/certd/commit/9be1ecc8aab3ea23dd0dc2dab3688f4edb90ef2c))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 流水线增加上传证书快捷方式 ([425bba6](https://github.com/certd/certd/commit/425bba67c539b734e2a85a83a4f9ecc9b2434fb4))
|
||||||
|
* 支持飞书通知 ([b82e1dc](https://github.com/certd/certd/commit/b82e1dcd6217b09a7d7e21cd648bb31de320cadf))
|
||||||
|
* 支持手动上传证书并部署 ([a9fffa5](https://github.com/certd/certd/commit/a9fffa5180c83da27b35886aa2e858a92a2c5f94))
|
||||||
|
|
||||||
|
## [1.31.3](https://github.com/certd/certd/compare/v1.31.2...v1.31.3) (2025-03-13)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/pipeline
|
||||||
|
|
||||||
## [1.31.2](https://github.com/certd/certd/compare/v1.31.1...v1.31.2) (2025-03-12)
|
## [1.31.2](https://github.com/certd/certd/compare/v1.31.1...v1.31.2) (2025-03-12)
|
||||||
|
|
||||||
**Note:** Version bump only for package @certd/pipeline
|
**Note:** Version bump only for package @certd/pipeline
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@certd/pipeline",
|
"name": "@certd/pipeline",
|
||||||
"private": false,
|
"private": false,
|
||||||
"version": "1.31.2",
|
"version": "1.31.7",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
"module": "./dist/index.js",
|
"module": "./dist/index.js",
|
||||||
@@ -16,8 +16,8 @@
|
|||||||
"test": "mocha --loader=ts-node/esm"
|
"test": "mocha --loader=ts-node/esm"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@certd/basic": "^1.31.2",
|
"@certd/basic": "^1.31.7",
|
||||||
"@certd/plus-core": "^1.31.2",
|
"@certd/plus-core": "^1.31.7",
|
||||||
"dayjs": "^1.11.7",
|
"dayjs": "^1.11.7",
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"reflect-metadata": "^0.1.13"
|
"reflect-metadata": "^0.1.13"
|
||||||
@@ -31,8 +31,8 @@
|
|||||||
"@types/chai": "^4.3.10",
|
"@types/chai": "^4.3.10",
|
||||||
"@types/lodash-es": "^4.17.12",
|
"@types/lodash-es": "^4.17.12",
|
||||||
"@types/mocha": "^10.0.1",
|
"@types/mocha": "^10.0.1",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.59.7",
|
"@typescript-eslint/eslint-plugin": "^8.26.1",
|
||||||
"@typescript-eslint/parser": "^5.59.7",
|
"@typescript-eslint/parser": "^8.26.1",
|
||||||
"chai": "4.3.10",
|
"chai": "4.3.10",
|
||||||
"eslint": "^8.41.0",
|
"eslint": "^8.41.0",
|
||||||
"eslint-config-prettier": "^8.8.0",
|
"eslint-config-prettier": "^8.8.0",
|
||||||
@@ -43,5 +43,5 @@
|
|||||||
"tslib": "^2.8.1",
|
"tslib": "^2.8.1",
|
||||||
"typescript": "^5.4.2"
|
"typescript": "^5.4.2"
|
||||||
},
|
},
|
||||||
"gitHead": "2a4d64af9502881e2e553ea86a4479158cfa8918"
|
"gitHead": "86ca35ce3381b98b455538b11219d9856be5d0d6"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { createAxiosService, hashUtils, HttpRequestConfig, ILogger, logger, util
|
|||||||
import { IAccessService } from "../access/index.js";
|
import { IAccessService } from "../access/index.js";
|
||||||
import { RegistryItem } from "../registry/index.js";
|
import { RegistryItem } from "../registry/index.js";
|
||||||
import { Decorator } from "../decorator/index.js";
|
import { Decorator } from "../decorator/index.js";
|
||||||
import { ICnameProxyService, IEmailService, IPluginConfigService, IUrlService } from "../service/index.js";
|
import { ICnameProxyService, IEmailService, IPluginConfigService, IServiceGetter, IUrlService } from "../service/index.js";
|
||||||
import { FileStore } from "./file-store.js";
|
import { FileStore } from "./file-store.js";
|
||||||
import { cloneDeep, forEach, merge } from "lodash-es";
|
import { cloneDeep, forEach, merge } from "lodash-es";
|
||||||
import { INotificationService } from "../notification/index.js";
|
import { INotificationService } from "../notification/index.js";
|
||||||
@@ -33,6 +33,7 @@ export type ExecutorOptions = {
|
|||||||
user: UserInfo;
|
user: UserInfo;
|
||||||
baseURL?: string;
|
baseURL?: string;
|
||||||
sysInfo?: SysInfo;
|
sysInfo?: SysInfo;
|
||||||
|
serviceGetter: IServiceGetter;
|
||||||
};
|
};
|
||||||
|
|
||||||
export class Executor {
|
export class Executor {
|
||||||
@@ -365,6 +366,7 @@ export class Executor {
|
|||||||
step,
|
step,
|
||||||
pipeline: this.pipeline,
|
pipeline: this.pipeline,
|
||||||
}),
|
}),
|
||||||
|
serviceGetter: this.options.serviceGetter,
|
||||||
};
|
};
|
||||||
instance.setCtx(taskCtx);
|
instance.setCtx(taskCtx);
|
||||||
|
|
||||||
|
|||||||
@@ -11,11 +11,13 @@ function attachProperty(target: any, propertyKey: string | symbol) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getClassProperties(target: any) {
|
function getClassProperties(target: any) {
|
||||||
//获取父类
|
//获取父类, 向上追溯三层
|
||||||
const parent = Object.getPrototypeOf(target);
|
const parent = Object.getPrototypeOf(target);
|
||||||
|
const pParent = Object.getPrototypeOf(parent);
|
||||||
|
const pParentMap = propertyMap[pParent] || {};
|
||||||
const parentMap = propertyMap[parent] || {};
|
const parentMap = propertyMap[parent] || {};
|
||||||
const current = propertyMap[target] || {};
|
const current = propertyMap[target] || {};
|
||||||
return _.merge({}, parentMap, current);
|
return _.merge({}, pParentMap, parentMap, current);
|
||||||
}
|
}
|
||||||
|
|
||||||
function target(target: any, propertyKey?: string | symbol) {
|
function target(target: any, propertyKey?: string | symbol) {
|
||||||
|
|||||||
@@ -119,10 +119,12 @@ export abstract class BaseNotification implements INotification {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async onTestRequest() {
|
async onTestRequest() {
|
||||||
await this.doSend({
|
return await this.doSend({
|
||||||
userId: 0,
|
userId: 0,
|
||||||
title: "【Certd】测试通知【*.foo.com】,标题长度测试、测试、测试",
|
title: "【Certd】测试通知【*.foo.com】,标题长度测试、测试、测试",
|
||||||
content: "测试通知,*.foo.com",
|
content: `测试通知,*.foo.com
|
||||||
|
换行测试
|
||||||
|
`,
|
||||||
pipeline: {
|
pipeline: {
|
||||||
id: 1,
|
id: 1,
|
||||||
title: "证书申请成功【测试流水线】",
|
title: "证书申请成功【测试流水线】",
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { Registrable } from "../registry/index.js";
|
|||||||
import { FileItem, FormItemProps, Pipeline, Runnable, Step } from "../dt/index.js";
|
import { FileItem, FormItemProps, Pipeline, Runnable, Step } from "../dt/index.js";
|
||||||
import { FileStore } from "../core/file-store.js";
|
import { FileStore } from "../core/file-store.js";
|
||||||
import { IAccessService } from "../access/index.js";
|
import { IAccessService } from "../access/index.js";
|
||||||
import { ICnameProxyService, IEmailService, IUrlService } from "../service/index.js";
|
import { ICnameProxyService, IEmailService, IServiceGetter, IUrlService } from "../service/index.js";
|
||||||
import { CancelError, IContext, RunHistory, RunnableCollection } from "../core/index.js";
|
import { CancelError, IContext, RunHistory, RunnableCollection } from "../core/index.js";
|
||||||
import { HttpRequestConfig, ILogger, logger, utils } from "@certd/basic";
|
import { HttpRequestConfig, ILogger, logger, utils } from "@certd/basic";
|
||||||
import { HttpClient } from "@certd/basic";
|
import { HttpClient } from "@certd/basic";
|
||||||
@@ -55,6 +55,14 @@ export type PluginDefine = Registrable & {
|
|||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
shortcut?: {
|
||||||
|
[key: string]: {
|
||||||
|
title: string;
|
||||||
|
icon: string;
|
||||||
|
action: string;
|
||||||
|
form: any;
|
||||||
|
};
|
||||||
|
};
|
||||||
needPlus?: boolean;
|
needPlus?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -114,6 +122,9 @@ export type TaskInstanceContext = {
|
|||||||
user: UserInfo;
|
user: UserInfo;
|
||||||
|
|
||||||
emitter: TaskEmitter;
|
emitter: TaskEmitter;
|
||||||
|
|
||||||
|
//service 容器
|
||||||
|
serviceGetter?: IServiceGetter;
|
||||||
};
|
};
|
||||||
|
|
||||||
export abstract class AbstractTaskPlugin implements ITaskPlugin {
|
export abstract class AbstractTaskPlugin implements ITaskPlugin {
|
||||||
@@ -221,7 +232,7 @@ export abstract class AbstractTaskPlugin implements ITaskPlugin {
|
|||||||
|
|
||||||
getStepFromPipeline(stepId: string) {
|
getStepFromPipeline(stepId: string) {
|
||||||
let found: any = null;
|
let found: any = null;
|
||||||
RunnableCollection.each(this.ctx.pipeline.stages, (step) => {
|
RunnableCollection.each(this.ctx.pipeline.stages, step => {
|
||||||
if (step.id === stepId) {
|
if (step.id === stepId) {
|
||||||
found = step;
|
found = step;
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -3,3 +3,6 @@ export * from "./cname.js";
|
|||||||
export * from "./config.js";
|
export * from "./config.js";
|
||||||
export * from "./url.js";
|
export * from "./url.js";
|
||||||
export * from "./emit.js";
|
export * from "./emit.js";
|
||||||
|
export type IServiceGetter = {
|
||||||
|
get: (name: string) => Promise<any>;
|
||||||
|
};
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
"@typescript-eslint/ban-ts-ignore": "off",
|
"@typescript-eslint/ban-ts-ignore": "off",
|
||||||
"@typescript-eslint/no-explicit-any": "off",
|
"@typescript-eslint/no-explicit-any": "off",
|
||||||
"@typescript-eslint/no-empty-function": "off",
|
"@typescript-eslint/no-empty-function": "off",
|
||||||
// "no-unused-expressions": "off",
|
"@typescript-eslint/no-unused-vars": "off"
|
||||||
"max-len": [0, 160, 2, { "ignoreUrls": true }]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
{
|
{
|
||||||
"printWidth": 160
|
"printWidth": 220,
|
||||||
|
"bracketSpacing": true,
|
||||||
|
"singleQuote": false,
|
||||||
|
"trailingComma": "es5",
|
||||||
|
"arrowParens": "avoid"
|
||||||
}
|
}
|
||||||
@@ -3,6 +3,26 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.31.7](https://github.com/certd/certd/compare/v1.31.6...v1.31.7) (2025-03-24)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-huawei
|
||||||
|
|
||||||
|
## [1.31.6](https://github.com/certd/certd/compare/v1.31.5...v1.31.6) (2025-03-24)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-huawei
|
||||||
|
|
||||||
|
## [1.31.5](https://github.com/certd/certd/compare/v1.31.4...v1.31.5) (2025-03-22)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-huawei
|
||||||
|
|
||||||
|
## [1.31.4](https://github.com/certd/certd/compare/v1.31.3...v1.31.4) (2025-03-21)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-huawei
|
||||||
|
|
||||||
|
## [1.31.3](https://github.com/certd/certd/compare/v1.31.2...v1.31.3) (2025-03-13)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-huawei
|
||||||
|
|
||||||
## [1.31.2](https://github.com/certd/certd/compare/v1.31.1...v1.31.2) (2025-03-12)
|
## [1.31.2](https://github.com/certd/certd/compare/v1.31.1...v1.31.2) (2025-03-12)
|
||||||
|
|
||||||
**Note:** Version bump only for package @certd/lib-huawei
|
**Note:** Version bump only for package @certd/lib-huawei
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@certd/lib-huawei",
|
"name": "@certd/lib-huawei",
|
||||||
"private": false,
|
"private": false,
|
||||||
"version": "1.31.2",
|
"version": "1.31.7",
|
||||||
"main": "./dist/bundle.js",
|
"main": "./dist/bundle.js",
|
||||||
"module": "./dist/bundle.js",
|
"module": "./dist/bundle.js",
|
||||||
"types": "./dist/d/index.d.ts",
|
"types": "./dist/d/index.d.ts",
|
||||||
@@ -18,8 +18,10 @@
|
|||||||
"rollup": "^3.7.4"
|
"rollup": "^3.7.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@typescript-eslint/eslint-plugin": "^8.26.1",
|
||||||
|
"@typescript-eslint/parser": "^8.26.1",
|
||||||
"prettier": "^2.8.8",
|
"prettier": "^2.8.8",
|
||||||
"tslib": "^2.8.1"
|
"tslib": "^2.8.1"
|
||||||
},
|
},
|
||||||
"gitHead": "2a4d64af9502881e2e553ea86a4479158cfa8918"
|
"gitHead": "86ca35ce3381b98b455538b11219d9856be5d0d6"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
"@typescript-eslint/ban-ts-ignore": "off",
|
"@typescript-eslint/ban-ts-ignore": "off",
|
||||||
"@typescript-eslint/no-explicit-any": "off",
|
"@typescript-eslint/no-explicit-any": "off",
|
||||||
"@typescript-eslint/no-empty-function": "off",
|
"@typescript-eslint/no-empty-function": "off",
|
||||||
// "no-unused-expressions": "off",
|
"@typescript-eslint/no-unused-vars": "off"
|
||||||
"max-len": [0, 160, 2, { "ignoreUrls": true }]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"printWidth": 160,
|
"printWidth": 220,
|
||||||
"bracketSpacing": true,
|
"bracketSpacing": true,
|
||||||
"singleQuote": true,
|
"singleQuote": false,
|
||||||
"trailingComma": "es5",
|
"trailingComma": "es5",
|
||||||
"arrowParens": "avoid"
|
"arrowParens": "avoid"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,26 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.31.7](https://github.com/certd/certd/compare/v1.31.6...v1.31.7) (2025-03-24)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-iframe
|
||||||
|
|
||||||
|
## [1.31.6](https://github.com/certd/certd/compare/v1.31.5...v1.31.6) (2025-03-24)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-iframe
|
||||||
|
|
||||||
|
## [1.31.5](https://github.com/certd/certd/compare/v1.31.4...v1.31.5) (2025-03-22)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-iframe
|
||||||
|
|
||||||
|
## [1.31.4](https://github.com/certd/certd/compare/v1.31.3...v1.31.4) (2025-03-21)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-iframe
|
||||||
|
|
||||||
|
## [1.31.3](https://github.com/certd/certd/compare/v1.31.2...v1.31.3) (2025-03-13)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-iframe
|
||||||
|
|
||||||
## [1.31.2](https://github.com/certd/certd/compare/v1.31.1...v1.31.2) (2025-03-12)
|
## [1.31.2](https://github.com/certd/certd/compare/v1.31.1...v1.31.2) (2025-03-12)
|
||||||
|
|
||||||
**Note:** Version bump only for package @certd/lib-iframe
|
**Note:** Version bump only for package @certd/lib-iframe
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@certd/lib-iframe",
|
"name": "@certd/lib-iframe",
|
||||||
"private": false,
|
"private": false,
|
||||||
"version": "1.31.2",
|
"version": "1.31.7",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
"module": "./dist/index.js",
|
"module": "./dist/index.js",
|
||||||
@@ -20,8 +20,8 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/chai": "^4.3.3",
|
"@types/chai": "^4.3.3",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.38.1",
|
"@typescript-eslint/eslint-plugin": "^8.26.1",
|
||||||
"@typescript-eslint/parser": "^5.38.1",
|
"@typescript-eslint/parser": "^8.26.1",
|
||||||
"eslint": "^8.24.0",
|
"eslint": "^8.24.0",
|
||||||
"eslint-config-prettier": "^8.5.0",
|
"eslint-config-prettier": "^8.5.0",
|
||||||
"eslint-plugin-prettier": "^4.2.1",
|
"eslint-plugin-prettier": "^4.2.1",
|
||||||
@@ -30,5 +30,5 @@
|
|||||||
"tslib": "^2.8.1",
|
"tslib": "^2.8.1",
|
||||||
"typescript": "^5.4.2"
|
"typescript": "^5.4.2"
|
||||||
},
|
},
|
||||||
"gitHead": "2a4d64af9502881e2e553ea86a4479158cfa8918"
|
"gitHead": "86ca35ce3381b98b455538b11219d9856be5d0d6"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"printWidth": 160,
|
"printWidth": 220,
|
||||||
"bracketSpacing": true,
|
"bracketSpacing": true,
|
||||||
"singleQuote": true,
|
"singleQuote": false,
|
||||||
"trailingComma": "es5",
|
"trailingComma": "es5",
|
||||||
"arrowParens": "avoid"
|
"arrowParens": "avoid"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,26 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.31.7](https://github.com/certd/certd/compare/v1.31.6...v1.31.7) (2025-03-24)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-k8s
|
||||||
|
|
||||||
|
## [1.31.6](https://github.com/certd/certd/compare/v1.31.5...v1.31.6) (2025-03-24)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-k8s
|
||||||
|
|
||||||
|
## [1.31.5](https://github.com/certd/certd/compare/v1.31.4...v1.31.5) (2025-03-22)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-k8s
|
||||||
|
|
||||||
|
## [1.31.4](https://github.com/certd/certd/compare/v1.31.3...v1.31.4) (2025-03-21)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-k8s
|
||||||
|
|
||||||
|
## [1.31.3](https://github.com/certd/certd/compare/v1.31.2...v1.31.3) (2025-03-13)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-k8s
|
||||||
|
|
||||||
## [1.31.2](https://github.com/certd/certd/compare/v1.31.1...v1.31.2) (2025-03-12)
|
## [1.31.2](https://github.com/certd/certd/compare/v1.31.1...v1.31.2) (2025-03-12)
|
||||||
|
|
||||||
**Note:** Version bump only for package @certd/lib-k8s
|
**Note:** Version bump only for package @certd/lib-k8s
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@certd/lib-k8s",
|
"name": "@certd/lib-k8s",
|
||||||
"private": false,
|
"private": false,
|
||||||
"version": "1.31.2",
|
"version": "1.31.7",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
"module": "./dist/index.js",
|
"module": "./dist/index.js",
|
||||||
@@ -16,13 +16,13 @@
|
|||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@certd/basic": "^1.31.2",
|
"@certd/basic": "^1.31.7",
|
||||||
"@kubernetes/client-node": "0.21.0"
|
"@kubernetes/client-node": "0.21.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/chai": "^4.3.3",
|
"@types/chai": "^4.3.3",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.38.1",
|
"@typescript-eslint/eslint-plugin": "^8.26.1",
|
||||||
"@typescript-eslint/parser": "^5.38.1",
|
"@typescript-eslint/parser": "^8.26.1",
|
||||||
"eslint": "^8.24.0",
|
"eslint": "^8.24.0",
|
||||||
"eslint-config-prettier": "^8.5.0",
|
"eslint-config-prettier": "^8.5.0",
|
||||||
"eslint-plugin-prettier": "^4.2.1",
|
"eslint-plugin-prettier": "^4.2.1",
|
||||||
@@ -31,5 +31,5 @@
|
|||||||
"tslib": "^2.8.1",
|
"tslib": "^2.8.1",
|
||||||
"typescript": "^5.4.2"
|
"typescript": "^5.4.2"
|
||||||
},
|
},
|
||||||
"gitHead": "2a4d64af9502881e2e553ea86a4479158cfa8918"
|
"gitHead": "86ca35ce3381b98b455538b11219d9856be5d0d6"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"printWidth": 160,
|
"printWidth": 220,
|
||||||
"bracketSpacing": true,
|
"bracketSpacing": true,
|
||||||
"singleQuote": true,
|
"singleQuote": false,
|
||||||
"trailingComma": "es5",
|
"trailingComma": "es5",
|
||||||
"arrowParens": "avoid"
|
"arrowParens": "avoid"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,26 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.31.7](https://github.com/certd/certd/compare/v1.31.6...v1.31.7) (2025-03-24)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-server
|
||||||
|
|
||||||
|
## [1.31.6](https://github.com/certd/certd/compare/v1.31.5...v1.31.6) (2025-03-24)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-server
|
||||||
|
|
||||||
|
## [1.31.5](https://github.com/certd/certd/compare/v1.31.4...v1.31.5) (2025-03-22)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-server
|
||||||
|
|
||||||
|
## [1.31.4](https://github.com/certd/certd/compare/v1.31.3...v1.31.4) (2025-03-21)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-server
|
||||||
|
|
||||||
|
## [1.31.3](https://github.com/certd/certd/compare/v1.31.2...v1.31.3) (2025-03-13)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-server
|
||||||
|
|
||||||
## [1.31.2](https://github.com/certd/certd/compare/v1.31.1...v1.31.2) (2025-03-12)
|
## [1.31.2](https://github.com/certd/certd/compare/v1.31.1...v1.31.2) (2025-03-12)
|
||||||
|
|
||||||
**Note:** Version bump only for package @certd/lib-server
|
**Note:** Version bump only for package @certd/lib-server
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@certd/lib-server",
|
"name": "@certd/lib-server",
|
||||||
"version": "1.31.2",
|
"version": "1.31.7",
|
||||||
"description": "midway with flyway, sql upgrade way ",
|
"description": "midway with flyway, sql upgrade way ",
|
||||||
"private": false,
|
"private": false,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
@@ -27,10 +27,10 @@
|
|||||||
],
|
],
|
||||||
"license": "AGPL",
|
"license": "AGPL",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@certd/acme-client": "^1.31.2",
|
"@certd/acme-client": "^1.31.7",
|
||||||
"@certd/basic": "^1.31.2",
|
"@certd/basic": "^1.31.7",
|
||||||
"@certd/pipeline": "^1.31.2",
|
"@certd/pipeline": "^1.31.7",
|
||||||
"@certd/plus-core": "^1.31.2",
|
"@certd/plus-core": "^1.31.7",
|
||||||
"@midwayjs/cache": "~3.14.0",
|
"@midwayjs/cache": "~3.14.0",
|
||||||
"@midwayjs/core": "~3.20.3",
|
"@midwayjs/core": "~3.20.3",
|
||||||
"@midwayjs/i18n": "~3.20.3",
|
"@midwayjs/i18n": "~3.20.3",
|
||||||
@@ -50,8 +50,8 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/chai": "^4.3.3",
|
"@types/chai": "^4.3.3",
|
||||||
"@types/node": "^18",
|
"@types/node": "^18",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.38.1",
|
"@typescript-eslint/eslint-plugin": "^8.26.1",
|
||||||
"@typescript-eslint/parser": "^5.38.1",
|
"@typescript-eslint/parser": "^8.26.1",
|
||||||
"eslint": "^8.24.0",
|
"eslint": "^8.24.0",
|
||||||
"eslint-config-prettier": "^8.5.0",
|
"eslint-config-prettier": "^8.5.0",
|
||||||
"eslint-plugin-prettier": "^4.2.1",
|
"eslint-plugin-prettier": "^4.2.1",
|
||||||
@@ -61,5 +61,5 @@
|
|||||||
"typeorm": "^0.3.11",
|
"typeorm": "^0.3.11",
|
||||||
"typescript": "^5.4.2"
|
"typescript": "^5.4.2"
|
||||||
},
|
},
|
||||||
"gitHead": "2a4d64af9502881e2e553ea86a4479158cfa8918"
|
"gitHead": "86ca35ce3381b98b455538b11219d9856be5d0d6"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ export abstract class BaseService<T> {
|
|||||||
|
|
||||||
async transaction(callback: (entityManager: EntityManager) => Promise<any>) {
|
async transaction(callback: (entityManager: EntityManager) => Promise<any>) {
|
||||||
const dataSource = this.dataSourceManager.getDataSource('default');
|
const dataSource = this.dataSourceManager.getDataSource('default');
|
||||||
await dataSource.transaction(callback as any);
|
return await dataSource.transaction(callback as any);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"printWidth": 160,
|
"printWidth": 220,
|
||||||
"bracketSpacing": true,
|
"bracketSpacing": true,
|
||||||
"singleQuote": true,
|
"singleQuote": false,
|
||||||
"trailingComma": "es5",
|
"trailingComma": "es5",
|
||||||
"arrowParens": "avoid"
|
"arrowParens": "avoid"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,26 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.31.7](https://github.com/certd/certd/compare/v1.31.6...v1.31.7) (2025-03-24)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/midway-flyway-js
|
||||||
|
|
||||||
|
## [1.31.6](https://github.com/certd/certd/compare/v1.31.5...v1.31.6) (2025-03-24)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/midway-flyway-js
|
||||||
|
|
||||||
|
## [1.31.5](https://github.com/certd/certd/compare/v1.31.4...v1.31.5) (2025-03-22)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/midway-flyway-js
|
||||||
|
|
||||||
|
## [1.31.4](https://github.com/certd/certd/compare/v1.31.3...v1.31.4) (2025-03-21)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/midway-flyway-js
|
||||||
|
|
||||||
|
## [1.31.3](https://github.com/certd/certd/compare/v1.31.2...v1.31.3) (2025-03-13)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/midway-flyway-js
|
||||||
|
|
||||||
## [1.31.2](https://github.com/certd/certd/compare/v1.31.1...v1.31.2) (2025-03-12)
|
## [1.31.2](https://github.com/certd/certd/compare/v1.31.1...v1.31.2) (2025-03-12)
|
||||||
|
|
||||||
**Note:** Version bump only for package @certd/midway-flyway-js
|
**Note:** Version bump only for package @certd/midway-flyway-js
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@certd/midway-flyway-js",
|
"name": "@certd/midway-flyway-js",
|
||||||
"version": "1.31.2",
|
"version": "1.31.7",
|
||||||
"description": "midway with flyway, sql upgrade way ",
|
"description": "midway with flyway, sql upgrade way ",
|
||||||
"private": false,
|
"private": false,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
@@ -33,8 +33,8 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/chai": "^4.3.3",
|
"@types/chai": "^4.3.3",
|
||||||
"@types/node": "^18",
|
"@types/node": "^18",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.38.1",
|
"@typescript-eslint/eslint-plugin": "^8.26.1",
|
||||||
"@typescript-eslint/parser": "^5.38.1",
|
"@typescript-eslint/parser": "^8.26.1",
|
||||||
"eslint": "^8.24.0",
|
"eslint": "^8.24.0",
|
||||||
"eslint-config-prettier": "^8.5.0",
|
"eslint-config-prettier": "^8.5.0",
|
||||||
"eslint-plugin-import": "^2.26.0",
|
"eslint-plugin-import": "^2.26.0",
|
||||||
@@ -46,5 +46,5 @@
|
|||||||
"typeorm": "^0.3.11",
|
"typeorm": "^0.3.11",
|
||||||
"typescript": "^5.4.2"
|
"typescript": "^5.4.2"
|
||||||
},
|
},
|
||||||
"gitHead": "2a4d64af9502881e2e553ea86a4479158cfa8918"
|
"gitHead": "86ca35ce3381b98b455538b11219d9856be5d0d6"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
"@typescript-eslint/ban-ts-ignore": "off",
|
"@typescript-eslint/ban-ts-ignore": "off",
|
||||||
"@typescript-eslint/no-explicit-any": "off",
|
"@typescript-eslint/no-explicit-any": "off",
|
||||||
"@typescript-eslint/no-empty-function": "off",
|
"@typescript-eslint/no-empty-function": "off",
|
||||||
// "no-unused-expressions": "off",
|
"@typescript-eslint/no-unused-vars": "off"
|
||||||
"max-len": [0, 160, 2, { "ignoreUrls": true }]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
{
|
{
|
||||||
"printWidth": 160
|
"printWidth": 220,
|
||||||
|
"bracketSpacing": true,
|
||||||
|
"singleQuote": false,
|
||||||
|
"trailingComma": "es5",
|
||||||
|
"arrowParens": "avoid"
|
||||||
}
|
}
|
||||||
@@ -3,6 +3,36 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.31.7](https://github.com/certd/certd/compare/v1.31.6...v1.31.7) (2025-03-24)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/plugin-cert
|
||||||
|
|
||||||
|
## [1.31.6](https://github.com/certd/certd/compare/v1.31.5...v1.31.6) (2025-03-24)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/plugin-cert
|
||||||
|
|
||||||
|
## [1.31.5](https://github.com/certd/certd/compare/v1.31.4...v1.31.5) (2025-03-22)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/plugin-cert
|
||||||
|
|
||||||
|
## [1.31.4](https://github.com/certd/certd/compare/v1.31.3...v1.31.4) (2025-03-21)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复dns.la域名申请失败的bug ([1de8eee](https://github.com/certd/certd/commit/1de8eee6ea8307f3c11626af75303d3cc104bb95))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 流水线增加上传证书快捷方式 ([425bba6](https://github.com/certd/certd/commit/425bba67c539b734e2a85a83a4f9ecc9b2434fb4))
|
||||||
|
* 手动上传证书部署流水线 ([fbb66f3](https://github.com/certd/certd/commit/fbb66f3c4389489aa8a43b194d82bc8cf391607b))
|
||||||
|
* 支持手动上传证书并部署 ([a9fffa5](https://github.com/certd/certd/commit/a9fffa5180c83da27b35886aa2e858a92a2c5f94))
|
||||||
|
|
||||||
|
## [1.31.3](https://github.com/certd/certd/compare/v1.31.2...v1.31.3) (2025-03-13)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 1panel支持 apikey方式授权 ([170b2af](https://github.com/certd/certd/commit/170b2afb0e3b125e4ed057f633fe895b5ac3ac22))
|
||||||
|
|
||||||
## [1.31.2](https://github.com/certd/certd/compare/v1.31.1...v1.31.2) (2025-03-12)
|
## [1.31.2](https://github.com/certd/certd/compare/v1.31.1...v1.31.2) (2025-03-12)
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@certd/plugin-cert",
|
"name": "@certd/plugin-cert",
|
||||||
"private": false,
|
"private": false,
|
||||||
"version": "1.31.2",
|
"version": "1.31.7",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
"types": "./dist/index.d.ts",
|
"types": "./dist/index.d.ts",
|
||||||
@@ -15,10 +15,10 @@
|
|||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@certd/acme-client": "^1.31.2",
|
"@certd/acme-client": "^1.31.7",
|
||||||
"@certd/basic": "^1.31.2",
|
"@certd/basic": "^1.31.7",
|
||||||
"@certd/pipeline": "^1.31.2",
|
"@certd/pipeline": "^1.31.7",
|
||||||
"@certd/plugin-lib": "^1.31.2",
|
"@certd/plugin-lib": "^1.31.7",
|
||||||
"@google-cloud/publicca": "^1.3.0",
|
"@google-cloud/publicca": "^1.3.0",
|
||||||
"dayjs": "^1.11.7",
|
"dayjs": "^1.11.7",
|
||||||
"jszip": "^3.10.1",
|
"jszip": "^3.10.1",
|
||||||
@@ -30,8 +30,8 @@
|
|||||||
"@types/chai": "^4.3.3",
|
"@types/chai": "^4.3.3",
|
||||||
"@types/mocha": "^10.0.0",
|
"@types/mocha": "^10.0.0",
|
||||||
"@types/psl": "^1.1.3",
|
"@types/psl": "^1.1.3",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.38.1",
|
"@typescript-eslint/eslint-plugin": "^8.26.1",
|
||||||
"@typescript-eslint/parser": "^5.38.1",
|
"@typescript-eslint/parser": "^8.26.1",
|
||||||
"chai": "^4.3.6",
|
"chai": "^4.3.6",
|
||||||
"eslint": "^8.24.0",
|
"eslint": "^8.24.0",
|
||||||
"eslint-config-prettier": "^8.5.0",
|
"eslint-config-prettier": "^8.5.0",
|
||||||
@@ -41,5 +41,5 @@
|
|||||||
"tslib": "^2.8.1",
|
"tslib": "^2.8.1",
|
||||||
"typescript": "^5.4.2"
|
"typescript": "^5.4.2"
|
||||||
},
|
},
|
||||||
"gitHead": "2a4d64af9502881e2e553ea86a4479158cfa8918"
|
"gitHead": "86ca35ce3381b98b455538b11219d9856be5d0d6"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ type AcmeServiceOptions = {
|
|||||||
reverseProxy?: string;
|
reverseProxy?: string;
|
||||||
privateKeyType?: PrivateKeyType;
|
privateKeyType?: PrivateKeyType;
|
||||||
signal?: AbortSignal;
|
signal?: AbortSignal;
|
||||||
|
maxCheckRetryCount?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export class AcmeService {
|
export class AcmeService {
|
||||||
@@ -144,7 +145,7 @@ export class AcmeService {
|
|||||||
accountKey: conf.key,
|
accountKey: conf.key,
|
||||||
accountUrl: conf.accountUrl,
|
accountUrl: conf.accountUrl,
|
||||||
externalAccountBinding: this.eab,
|
externalAccountBinding: this.eab,
|
||||||
backoffAttempts: 20,
|
backoffAttempts: this.options.maxCheckRetryCount || 20,
|
||||||
backoffMin: 5000,
|
backoffMin: 5000,
|
||||||
backoffMax: 10000,
|
backoffMax: 10000,
|
||||||
urlMapping,
|
urlMapping,
|
||||||
@@ -282,15 +283,7 @@ export class AcmeService {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
async challengeRemoveFn(
|
async challengeRemoveFn(authz: any, challenge: any, keyAuthorization: string, recordReq: any, recordRes: any, dnsProvider?: IDnsProvider, httpUploader?: HttpChallengeUploader) {
|
||||||
authz: any,
|
|
||||||
challenge: any,
|
|
||||||
keyAuthorization: string,
|
|
||||||
recordReq: any,
|
|
||||||
recordRes: any,
|
|
||||||
dnsProvider?: IDnsProvider,
|
|
||||||
httpUploader?: HttpChallengeUploader
|
|
||||||
) {
|
|
||||||
this.logger.info("执行清理");
|
this.logger.info("执行清理");
|
||||||
|
|
||||||
/* http-01 */
|
/* http-01 */
|
||||||
@@ -387,14 +380,7 @@ export class AcmeService {
|
|||||||
): Promise<{ recordReq?: any; recordRes?: any; dnsProvider?: any; challenge: Challenge; keyAuthorization: string }> => {
|
): Promise<{ recordReq?: any; recordRes?: any; dnsProvider?: any; challenge: Challenge; keyAuthorization: string }> => {
|
||||||
return await this.challengeCreateFn(authz, keyAuthorizationGetter, providers);
|
return await this.challengeCreateFn(authz, keyAuthorizationGetter, providers);
|
||||||
},
|
},
|
||||||
challengeRemoveFn: async (
|
challengeRemoveFn: async (authz: acme.Authorization, challenge: Challenge, keyAuthorization: string, recordReq: any, recordRes: any, dnsProvider: IDnsProvider): Promise<any> => {
|
||||||
authz: acme.Authorization,
|
|
||||||
challenge: Challenge,
|
|
||||||
keyAuthorization: string,
|
|
||||||
recordReq: any,
|
|
||||||
recordRes: any,
|
|
||||||
dnsProvider: IDnsProvider
|
|
||||||
): Promise<any> => {
|
|
||||||
return await this.challengeRemoveFn(authz, challenge, keyAuthorization, recordReq, recordRes, dnsProvider, httpUploader);
|
return await this.challengeRemoveFn(authz, challenge, keyAuthorization, recordReq, recordRes, dnsProvider, httpUploader);
|
||||||
},
|
},
|
||||||
signal: this.options.signal,
|
signal: this.options.signal,
|
||||||
|
|||||||
@@ -0,0 +1,188 @@
|
|||||||
|
import { AbstractTaskPlugin, IContext, Step, TaskInput, TaskOutput } from "@certd/pipeline";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
import type { CertInfo } from "./acme.js";
|
||||||
|
import { CertReader } from "./cert-reader.js";
|
||||||
|
import JSZip from "jszip";
|
||||||
|
import { CertConverter } from "./convert.js";
|
||||||
|
export const EVENT_CERT_APPLY_SUCCESS = "CertApply.success";
|
||||||
|
|
||||||
|
export abstract class CertApplyBaseConvertPlugin extends AbstractTaskPlugin {
|
||||||
|
@TaskInput({
|
||||||
|
title: "域名",
|
||||||
|
component: {
|
||||||
|
name: "a-select",
|
||||||
|
vModel: "value",
|
||||||
|
mode: "tags",
|
||||||
|
open: false,
|
||||||
|
placeholder: "foo.com / *.foo.com / *.bar.com",
|
||||||
|
tokenSeparators: [",", " ", ",", "、", "|"],
|
||||||
|
},
|
||||||
|
rules: [{ type: "domains" }],
|
||||||
|
required: true,
|
||||||
|
col: {
|
||||||
|
span: 24,
|
||||||
|
},
|
||||||
|
order: -999,
|
||||||
|
helper:
|
||||||
|
"1、支持多个域名打到一个证书上,例如: foo.com,*.foo.com,*.bar.com\n" +
|
||||||
|
"2、子域名被通配符包含的不要填写,例如:www.foo.com已经被*.foo.com包含,不要填写www.foo.com\n" +
|
||||||
|
"3、泛域名只能通配*号那一级(*.foo.com的证书不能用于xxx.yyy.foo.com、不能用于foo.com)\n" +
|
||||||
|
"4、输入一个,空格之后,再输入下一个",
|
||||||
|
})
|
||||||
|
domains!: string[];
|
||||||
|
|
||||||
|
@TaskInput({
|
||||||
|
title: "证书加密密码",
|
||||||
|
component: {
|
||||||
|
name: "input-password",
|
||||||
|
vModel: "value",
|
||||||
|
},
|
||||||
|
required: false,
|
||||||
|
order: 100,
|
||||||
|
helper: "转换成PFX、jks格式证书是否需要加密\njks必须设置密码,不传则默认123456\npfx不传则为空密码",
|
||||||
|
})
|
||||||
|
pfxPassword!: string;
|
||||||
|
|
||||||
|
@TaskInput({
|
||||||
|
title: "PFX证书转换参数",
|
||||||
|
value: "-macalg SHA1 -keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES",
|
||||||
|
component: {
|
||||||
|
name: "a-auto-complete",
|
||||||
|
vModel: "value",
|
||||||
|
options: [
|
||||||
|
{ value: "", label: "兼容 Windows Server 最新" },
|
||||||
|
{ value: "-macalg SHA1 -keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES", label: "兼容 Windows Server 2016" },
|
||||||
|
{ value: "-nomac -keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES", label: "兼容 Windows Server 2008" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
required: false,
|
||||||
|
order: 100,
|
||||||
|
helper: "兼容Windows Server各个版本",
|
||||||
|
})
|
||||||
|
pfxArgs = "-macalg SHA1 -keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES";
|
||||||
|
|
||||||
|
userContext!: IContext;
|
||||||
|
lastStatus!: Step;
|
||||||
|
|
||||||
|
@TaskOutput({
|
||||||
|
title: "域名证书",
|
||||||
|
})
|
||||||
|
cert?: CertInfo;
|
||||||
|
|
||||||
|
async onInstance() {
|
||||||
|
this.userContext = this.ctx.userContext;
|
||||||
|
this.lastStatus = this.ctx.lastStatus as Step;
|
||||||
|
await this.onInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract onInit(): Promise<void>;
|
||||||
|
|
||||||
|
//必须output之后执行
|
||||||
|
async emitCertApplySuccess() {
|
||||||
|
const emitter = this.ctx.emitter;
|
||||||
|
const value = {
|
||||||
|
cert: this.cert,
|
||||||
|
file: this._result.files[0].path,
|
||||||
|
};
|
||||||
|
await emitter.emit(EVENT_CERT_APPLY_SUCCESS, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
async output(certReader: CertReader, isNew: boolean) {
|
||||||
|
const cert: CertInfo = certReader.toCertInfo();
|
||||||
|
this.cert = cert;
|
||||||
|
|
||||||
|
this._result.pipelineVars.certExpiresTime = dayjs(certReader.detail.notAfter).valueOf();
|
||||||
|
if (!this._result.pipelinePrivateVars) {
|
||||||
|
this._result.pipelinePrivateVars = {};
|
||||||
|
}
|
||||||
|
this._result.pipelinePrivateVars.cert = cert;
|
||||||
|
|
||||||
|
if (isNew) {
|
||||||
|
try {
|
||||||
|
const converter = new CertConverter({ logger: this.logger });
|
||||||
|
const res = await converter.convert({
|
||||||
|
cert,
|
||||||
|
pfxPassword: this.pfxPassword,
|
||||||
|
pfxArgs: this.pfxArgs,
|
||||||
|
});
|
||||||
|
if (cert.pfx == null && res.pfx) {
|
||||||
|
cert.pfx = res.pfx;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cert.der == null && res.der) {
|
||||||
|
cert.der = res.der;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cert.jks == null && res.jks) {
|
||||||
|
cert.jks = res.jks;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.logger.info("转换证书格式成功");
|
||||||
|
} catch (e) {
|
||||||
|
this.logger.error("转换证书格式失败", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isNew) {
|
||||||
|
const zipFileName = certReader.buildCertFileName("zip", certReader.detail.notBefore);
|
||||||
|
await this.zipCert(cert, zipFileName);
|
||||||
|
} else {
|
||||||
|
this.extendsFiles();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async zipCert(cert: CertInfo, filename: string) {
|
||||||
|
const zip = new JSZip();
|
||||||
|
zip.file("证书.pem", cert.crt);
|
||||||
|
zip.file("私钥.pem", cert.key);
|
||||||
|
zip.file("中间证书.pem", cert.ic);
|
||||||
|
zip.file("cert.crt", cert.crt);
|
||||||
|
zip.file("cert.key", cert.key);
|
||||||
|
zip.file("intermediate.crt", cert.ic);
|
||||||
|
zip.file("origin.crt", cert.oc);
|
||||||
|
zip.file("one.pem", cert.one);
|
||||||
|
if (cert.pfx) {
|
||||||
|
zip.file("cert.pfx", Buffer.from(cert.pfx, "base64"));
|
||||||
|
}
|
||||||
|
if (cert.der) {
|
||||||
|
zip.file("cert.der", Buffer.from(cert.der, "base64"));
|
||||||
|
}
|
||||||
|
if (cert.jks) {
|
||||||
|
zip.file("cert.jks", Buffer.from(cert.jks, "base64"));
|
||||||
|
}
|
||||||
|
|
||||||
|
zip.file(
|
||||||
|
"说明.txt",
|
||||||
|
`证书文件说明
|
||||||
|
cert.crt:证书文件,包含证书链,pem格式
|
||||||
|
cert.key:私钥文件,pem格式
|
||||||
|
intermediate.crt:中间证书文件,pem格式
|
||||||
|
origin.crt:原始证书文件,不含证书链,pem格式
|
||||||
|
one.pem: 证书和私钥简单合并成一个文件,pem格式,crt正文+key正文
|
||||||
|
cert.pfx:pfx格式证书文件,iis服务器使用
|
||||||
|
cert.der:der格式证书文件
|
||||||
|
cert.jks:jks格式证书文件,java服务器使用
|
||||||
|
`
|
||||||
|
);
|
||||||
|
|
||||||
|
const content = await zip.generateAsync({ type: "nodebuffer" });
|
||||||
|
this.saveFile(filename, content);
|
||||||
|
this.logger.info(`已保存文件:${filename}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
formatCert(pem: string) {
|
||||||
|
pem = pem.replace(/\r/g, "");
|
||||||
|
pem = pem.replace(/\n\n/g, "\n");
|
||||||
|
pem = pem.replace(/\n$/g, "");
|
||||||
|
return pem;
|
||||||
|
}
|
||||||
|
|
||||||
|
formatCerts(cert: { crt: string; key: string; csr: string }) {
|
||||||
|
const newCert: CertInfo = {
|
||||||
|
crt: this.formatCert(cert.crt),
|
||||||
|
key: this.formatCert(cert.key),
|
||||||
|
csr: this.formatCert(cert.csr),
|
||||||
|
};
|
||||||
|
return newCert;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,42 +1,10 @@
|
|||||||
import { AbstractTaskPlugin, IContext, NotificationBody, Step, TaskEmitter, TaskInput, TaskOutput } from "@certd/pipeline";
|
import { NotificationBody, Step, TaskInput } from "@certd/pipeline";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import type { CertInfo } from "./acme.js";
|
|
||||||
import { CertReader } from "./cert-reader.js";
|
import { CertReader } from "./cert-reader.js";
|
||||||
import JSZip from "jszip";
|
|
||||||
import { CertConverter } from "./convert.js";
|
|
||||||
import { pick } from "lodash-es";
|
import { pick } from "lodash-es";
|
||||||
|
import { CertApplyBaseConvertPlugin } from "./base-convert.js";
|
||||||
|
|
||||||
export const EVENT_CERT_APPLY_SUCCESS = "CertApply.success";
|
export abstract class CertApplyBasePlugin extends CertApplyBaseConvertPlugin {
|
||||||
|
|
||||||
export async function emitCertApplySuccess(emitter: TaskEmitter, cert: CertReader) {
|
|
||||||
await emitter.emit(EVENT_CERT_APPLY_SUCCESS, cert);
|
|
||||||
}
|
|
||||||
|
|
||||||
export abstract class CertApplyBasePlugin extends AbstractTaskPlugin {
|
|
||||||
@TaskInput({
|
|
||||||
title: "域名",
|
|
||||||
component: {
|
|
||||||
name: "a-select",
|
|
||||||
vModel: "value",
|
|
||||||
mode: "tags",
|
|
||||||
open: false,
|
|
||||||
placeholder: "foo.com / *.foo.com / *.bar.com",
|
|
||||||
tokenSeparators: [",", " ", ",", "、", "|"],
|
|
||||||
},
|
|
||||||
rules: [{ type: "domains" }],
|
|
||||||
required: true,
|
|
||||||
col: {
|
|
||||||
span: 24,
|
|
||||||
},
|
|
||||||
order: -999,
|
|
||||||
helper:
|
|
||||||
"1、支持多个域名打到一个证书上,例如: foo.com,*.foo.com,*.bar.com\n" +
|
|
||||||
"2、子域名被通配符包含的不要填写,例如:www.foo.com已经被*.foo.com包含,不要填写www.foo.com\n" +
|
|
||||||
"3、泛域名只能通配*号那一级(*.foo.com的证书不能用于xxx.yyy.foo.com、不能用于foo.com)\n" +
|
|
||||||
"4、输入一个,空格之后,再输入下一个",
|
|
||||||
})
|
|
||||||
domains!: string[];
|
|
||||||
|
|
||||||
@TaskInput({
|
@TaskInput({
|
||||||
title: "邮箱",
|
title: "邮箱",
|
||||||
component: {
|
component: {
|
||||||
@@ -50,36 +18,6 @@ export abstract class CertApplyBasePlugin extends AbstractTaskPlugin {
|
|||||||
})
|
})
|
||||||
email!: string;
|
email!: string;
|
||||||
|
|
||||||
@TaskInput({
|
|
||||||
title: "证书密码",
|
|
||||||
component: {
|
|
||||||
name: "input-password",
|
|
||||||
vModel: "value",
|
|
||||||
},
|
|
||||||
required: false,
|
|
||||||
order: 100,
|
|
||||||
helper: "PFX、jks格式证书是否加密\njks必须设置密码,不传则默认123456\npfx不传则为空密码",
|
|
||||||
})
|
|
||||||
pfxPassword!: string;
|
|
||||||
|
|
||||||
@TaskInput({
|
|
||||||
title: "PFX证书转换参数",
|
|
||||||
value: "-macalg SHA1 -keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES",
|
|
||||||
component: {
|
|
||||||
name: "a-auto-complete",
|
|
||||||
vModel: "value",
|
|
||||||
options: [
|
|
||||||
{ value: "", label: "兼容 Windows Server 最新" },
|
|
||||||
{ value: "-macalg SHA1 -keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES", label: "兼容 Windows Server 2016" },
|
|
||||||
{ value: "-nomac -keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES", label: "兼容 Windows Server 2008" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
required: false,
|
|
||||||
order: 100,
|
|
||||||
helper: "兼容Windows Server各个版本",
|
|
||||||
})
|
|
||||||
pfxArgs = "-macalg SHA1 -keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES";
|
|
||||||
|
|
||||||
@TaskInput({
|
@TaskInput({
|
||||||
title: "更新天数",
|
title: "更新天数",
|
||||||
value: 35,
|
value: 35,
|
||||||
@@ -111,14 +49,6 @@ export abstract class CertApplyBasePlugin extends AbstractTaskPlugin {
|
|||||||
// })
|
// })
|
||||||
csrInfo!: string;
|
csrInfo!: string;
|
||||||
|
|
||||||
userContext!: IContext;
|
|
||||||
lastStatus!: Step;
|
|
||||||
|
|
||||||
@TaskOutput({
|
|
||||||
title: "域名证书",
|
|
||||||
})
|
|
||||||
cert?: CertInfo;
|
|
||||||
|
|
||||||
async onInstance() {
|
async onInstance() {
|
||||||
this.userContext = this.ctx.userContext;
|
this.userContext = this.ctx.userContext;
|
||||||
this.lastStatus = this.ctx.lastStatus as Step;
|
this.lastStatus = this.ctx.lastStatus as Step;
|
||||||
@@ -139,7 +69,7 @@ export abstract class CertApplyBasePlugin extends AbstractTaskPlugin {
|
|||||||
if (cert != null) {
|
if (cert != null) {
|
||||||
await this.output(cert, true);
|
await this.output(cert, true);
|
||||||
|
|
||||||
await emitCertApplySuccess(this.ctx.emitter, cert);
|
await this.emitCertApplySuccess();
|
||||||
//清空后续任务的状态,让后续任务能够重新执行
|
//清空后续任务的状态,让后续任务能够重新执行
|
||||||
this.clearLastStatus();
|
this.clearLastStatus();
|
||||||
|
|
||||||
@@ -151,89 +81,6 @@ export abstract class CertApplyBasePlugin extends AbstractTaskPlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async output(certReader: CertReader, isNew: boolean) {
|
|
||||||
const cert: CertInfo = certReader.toCertInfo();
|
|
||||||
this.cert = cert;
|
|
||||||
|
|
||||||
this._result.pipelineVars.certExpiresTime = dayjs(certReader.detail.notAfter).valueOf();
|
|
||||||
if (!this._result.pipelinePrivateVars) {
|
|
||||||
this._result.pipelinePrivateVars = {};
|
|
||||||
}
|
|
||||||
this._result.pipelinePrivateVars.cert = cert;
|
|
||||||
|
|
||||||
if (isNew) {
|
|
||||||
try {
|
|
||||||
const converter = new CertConverter({ logger: this.logger });
|
|
||||||
const res = await converter.convert({
|
|
||||||
cert,
|
|
||||||
pfxPassword: this.pfxPassword,
|
|
||||||
pfxArgs: this.pfxArgs,
|
|
||||||
});
|
|
||||||
if (cert.pfx == null && res.pfx) {
|
|
||||||
cert.pfx = res.pfx;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cert.der == null && res.der) {
|
|
||||||
cert.der = res.der;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cert.jks == null && res.jks) {
|
|
||||||
cert.jks = res.jks;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.logger.info("转换证书格式成功");
|
|
||||||
} catch (e) {
|
|
||||||
this.logger.error("转换证书格式失败", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isNew) {
|
|
||||||
const zipFileName = certReader.buildCertFileName("zip", certReader.detail.notBefore);
|
|
||||||
await this.zipCert(cert, zipFileName);
|
|
||||||
} else {
|
|
||||||
this.extendsFiles();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async zipCert(cert: CertInfo, filename: string) {
|
|
||||||
const zip = new JSZip();
|
|
||||||
zip.file("证书.pem", cert.crt);
|
|
||||||
zip.file("私钥.pem", cert.key);
|
|
||||||
zip.file("中间证书.pem", cert.ic);
|
|
||||||
zip.file("cert.crt", cert.crt);
|
|
||||||
zip.file("cert.key", cert.key);
|
|
||||||
zip.file("intermediate.crt", cert.ic);
|
|
||||||
zip.file("origin.crt", cert.oc);
|
|
||||||
zip.file("one.pem", cert.one);
|
|
||||||
if (cert.pfx) {
|
|
||||||
zip.file("cert.pfx", Buffer.from(cert.pfx, "base64"));
|
|
||||||
}
|
|
||||||
if (cert.der) {
|
|
||||||
zip.file("cert.der", Buffer.from(cert.der, "base64"));
|
|
||||||
}
|
|
||||||
if (cert.jks) {
|
|
||||||
zip.file("cert.jks", Buffer.from(cert.jks, "base64"));
|
|
||||||
}
|
|
||||||
|
|
||||||
zip.file(
|
|
||||||
"说明.txt",
|
|
||||||
`证书文件说明
|
|
||||||
cert.crt:证书文件,包含证书链,pem格式
|
|
||||||
cert.key:私钥文件,pem格式
|
|
||||||
intermediate.crt:中间证书文件,pem格式
|
|
||||||
origin.crt:原始证书文件,不含证书链,pem格式
|
|
||||||
one.pem: 证书和私钥简单合并成一个文件,pem格式,crt正文+key正文
|
|
||||||
cert.pfx:pfx格式证书文件,iis服务器使用
|
|
||||||
cert.der:der格式证书文件
|
|
||||||
cert.jks:jks格式证书文件,java服务器使用
|
|
||||||
`
|
|
||||||
);
|
|
||||||
|
|
||||||
const content = await zip.generateAsync({ type: "nodebuffer" });
|
|
||||||
this.saveFile(filename, content);
|
|
||||||
this.logger.info(`已保存文件:${filename}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否更新证书
|
* 是否更新证书
|
||||||
*/
|
*/
|
||||||
@@ -279,22 +126,6 @@ cert.jks:jks格式证书文件,java服务器使用
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
formatCert(pem: string) {
|
|
||||||
pem = pem.replace(/\r/g, "");
|
|
||||||
pem = pem.replace(/\n\n/g, "\n");
|
|
||||||
pem = pem.replace(/\n$/g, "");
|
|
||||||
return pem;
|
|
||||||
}
|
|
||||||
|
|
||||||
formatCerts(cert: { crt: string; key: string; csr: string }) {
|
|
||||||
const newCert: CertInfo = {
|
|
||||||
crt: this.formatCert(cert.crt),
|
|
||||||
key: this.formatCert(cert.key),
|
|
||||||
csr: this.formatCert(cert.csr),
|
|
||||||
};
|
|
||||||
return newCert;
|
|
||||||
}
|
|
||||||
|
|
||||||
async readLastCert(): Promise<CertReader | undefined> {
|
async readLastCert(): Promise<CertReader | undefined> {
|
||||||
const cert = this.lastStatus?.status?.output?.cert;
|
const cert = this.lastStatus?.status?.output?.cert;
|
||||||
if (cert == null) {
|
if (cert == null) {
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ export class CertReader {
|
|||||||
cert: CertInfo;
|
cert: CertInfo;
|
||||||
|
|
||||||
detail: CertificateInfo;
|
detail: CertificateInfo;
|
||||||
|
//毫秒时间戳
|
||||||
expires: number;
|
expires: number;
|
||||||
constructor(certInfo: CertInfo) {
|
constructor(certInfo: CertInfo) {
|
||||||
this.cert = certInfo;
|
this.cert = certInfo;
|
||||||
@@ -39,9 +40,13 @@ export class CertReader {
|
|||||||
this.cert.one = this.cert.crt + "\n" + this.cert.key;
|
this.cert.one = this.cert.crt + "\n" + this.cert.key;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { detail, expires } = this.getCrtDetail(this.cert.crt);
|
try {
|
||||||
this.detail = detail;
|
const { detail, expires } = this.getCrtDetail(this.cert.crt);
|
||||||
this.expires = expires.getTime();
|
this.detail = detail;
|
||||||
|
this.expires = expires.getTime();
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error("证书解析失败:" + e.message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getIc() {
|
getIc() {
|
||||||
|
|||||||
@@ -0,0 +1,158 @@
|
|||||||
|
import { IsTaskPlugin, pluginGroups, RunStrategy, Step, TaskInput, TaskOutput } from "@certd/pipeline";
|
||||||
|
import type { CertInfo } from "../acme.js";
|
||||||
|
import { CertReader } from "../cert-reader.js";
|
||||||
|
import { CertApplyBaseConvertPlugin } from "../base-convert.js";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
|
||||||
|
export { CertReader };
|
||||||
|
export type { CertInfo };
|
||||||
|
@IsTaskPlugin({
|
||||||
|
name: "CertApplyUpload",
|
||||||
|
icon: "ph:certificate",
|
||||||
|
title: "证书手动上传",
|
||||||
|
group: pluginGroups.cert.key,
|
||||||
|
desc: "在证书仓库手动上传后触发部署证书",
|
||||||
|
default: {
|
||||||
|
strategy: {
|
||||||
|
runStrategy: RunStrategy.AlwaysRun,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
shortcut: {
|
||||||
|
certUpdate: {
|
||||||
|
title: "更新证书",
|
||||||
|
icon: "ion:upload",
|
||||||
|
action: "onCertUpdate",
|
||||||
|
form: {
|
||||||
|
columns: {
|
||||||
|
crt: {
|
||||||
|
title: "证书",
|
||||||
|
type: "text",
|
||||||
|
form: {
|
||||||
|
component: {
|
||||||
|
name: "pem-input",
|
||||||
|
vModel: "modelValue",
|
||||||
|
textarea: {
|
||||||
|
rows: 4,
|
||||||
|
placeholder: "-----BEGIN CERTIFICATE-----\n...\n...\n-----END CERTIFICATE-----",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rules: [{ required: true, message: "此项必填" }],
|
||||||
|
col: { span: 24 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
key: {
|
||||||
|
title: "私钥",
|
||||||
|
type: "text",
|
||||||
|
form: {
|
||||||
|
component: {
|
||||||
|
name: "pem-input",
|
||||||
|
vModel: "modelValue",
|
||||||
|
textarea: {
|
||||||
|
rows: 4,
|
||||||
|
placeholder: "-----BEGIN PRIVATE KEY-----\n...\n...\n-----END PRIVATE KEY----- ",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rules: [{ required: true, message: "此项必填" }],
|
||||||
|
col: { span: 24 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
export class CertApplyUploadPlugin extends CertApplyBaseConvertPlugin {
|
||||||
|
@TaskInput({
|
||||||
|
title: "手动上传证书",
|
||||||
|
component: {
|
||||||
|
name: "cert-info-updater",
|
||||||
|
vModel: "modelValue",
|
||||||
|
},
|
||||||
|
helper: "手动上传证书",
|
||||||
|
order: -9999,
|
||||||
|
required: true,
|
||||||
|
mergeScript: `
|
||||||
|
return {
|
||||||
|
component:{
|
||||||
|
on:{
|
||||||
|
updated(scope){
|
||||||
|
scope.form.input.domains = scope.$event?.domains
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
})
|
||||||
|
uploadCert!: CertInfo;
|
||||||
|
|
||||||
|
@TaskOutput({
|
||||||
|
title: "证书MD5",
|
||||||
|
})
|
||||||
|
certMd5?: string;
|
||||||
|
|
||||||
|
async onInstance() {
|
||||||
|
this.accessService = this.ctx.accessService;
|
||||||
|
this.logger = this.ctx.logger;
|
||||||
|
this.userContext = this.ctx.userContext;
|
||||||
|
this.lastStatus = this.ctx.lastStatus as Step;
|
||||||
|
}
|
||||||
|
async onInit(): Promise<void> {}
|
||||||
|
|
||||||
|
async getCertFromStore() {
|
||||||
|
const certReader = new CertReader(this.uploadCert);
|
||||||
|
if (!certReader.expires && certReader.expires < new Date().getTime()) {
|
||||||
|
throw new Error("证书已过期,停止部署,请重新上传证书");
|
||||||
|
}
|
||||||
|
|
||||||
|
return certReader;
|
||||||
|
}
|
||||||
|
|
||||||
|
async execute(): Promise<string | void> {
|
||||||
|
const certReader = await this.getCertFromStore();
|
||||||
|
const crtMd5 = this.ctx.utils.hash.md5(certReader.cert.crt);
|
||||||
|
|
||||||
|
const leftDays = dayjs(certReader.expires).diff(dayjs(), "day");
|
||||||
|
this.logger.info(`证书过期时间${dayjs(certReader.expires).format("YYYY-MM-DD HH:mm:ss")},剩余${leftDays}天`);
|
||||||
|
|
||||||
|
if (!this.ctx.inputChanged) {
|
||||||
|
this.logger.info("输入参数无变化");
|
||||||
|
const lastCrtMd5 = this.lastStatus?.status?.output?.certMd5;
|
||||||
|
this.logger.info("证书MD5", crtMd5);
|
||||||
|
this.logger.info("上次证书MD5", lastCrtMd5);
|
||||||
|
if (lastCrtMd5 === crtMd5) {
|
||||||
|
this.logger.info("证书无变化,跳过");
|
||||||
|
//输出证书MD5
|
||||||
|
this.certMd5 = crtMd5;
|
||||||
|
await this.output(certReader, false);
|
||||||
|
return "skip";
|
||||||
|
}
|
||||||
|
this.logger.info("证书有变化,重新部署");
|
||||||
|
} else {
|
||||||
|
this.logger.info("输入参数有变化,重新部署");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.clearLastStatus();
|
||||||
|
//输出证书MD5
|
||||||
|
this.certMd5 = crtMd5;
|
||||||
|
await this.output(certReader, true);
|
||||||
|
|
||||||
|
//必须output之后执行
|
||||||
|
await this.emitCertApplySuccess();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
async onCertUpdate(data: any) {
|
||||||
|
const certReader = new CertReader(data);
|
||||||
|
return {
|
||||||
|
input: {
|
||||||
|
uploadCert: {
|
||||||
|
crt: data.crt,
|
||||||
|
key: data.key,
|
||||||
|
},
|
||||||
|
domains: certReader.getAllDomains(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
new CertApplyUploadPlugin();
|
||||||
@@ -66,7 +66,7 @@ export class CertApplyPlugin extends CertApplyBasePlugin {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
required: true,
|
required: true,
|
||||||
helper: `DNS直接验证:域名是在阿里云、腾讯云、华为云、Cloudflare、NameSilo、西数注册的,选它;
|
helper: `DNS直接验证:域名是在阿里云、腾讯云、华为云、Cloudflare、NameSilo、西数、dns.la注册的,选它;
|
||||||
CNAME代理验证:支持任何注册商注册的域名,但第一次需要手动添加CNAME记录;
|
CNAME代理验证:支持任何注册商注册的域名,但第一次需要手动添加CNAME记录;
|
||||||
HTTP文件验证:不支持泛域名,需要配置网站文件上传`,
|
HTTP文件验证:不支持泛域名,需要配置网站文件上传`,
|
||||||
})
|
})
|
||||||
@@ -203,8 +203,7 @@ HTTP文件验证:不支持泛域名,需要配置网站文件上传`,
|
|||||||
},
|
},
|
||||||
maybeNeed: true,
|
maybeNeed: true,
|
||||||
required: false,
|
required: false,
|
||||||
helper:
|
helper: "google服务账号授权与EAB授权选填其中一个,[服务账号授权获取方法](https://certd.docmirror.cn/guide/use/google/)\n服务账号授权需要配置代理或者服务器本身在海外",
|
||||||
"google服务账号授权与EAB授权选填其中一个,[服务账号授权获取方法](https://certd.docmirror.cn/guide/use/google/)\n服务账号授权需要配置代理或者服务器本身在海外",
|
|
||||||
mergeScript: `
|
mergeScript: `
|
||||||
return {
|
return {
|
||||||
show: ctx.compute(({form})=>{
|
show: ctx.compute(({form})=>{
|
||||||
@@ -268,6 +267,17 @@ HTTP文件验证:不支持泛域名,需要配置网站文件上传`,
|
|||||||
})
|
})
|
||||||
skipLocalVerify = false;
|
skipLocalVerify = false;
|
||||||
|
|
||||||
|
@TaskInput({
|
||||||
|
title: "检查解析重试次数",
|
||||||
|
value: 20,
|
||||||
|
component: {
|
||||||
|
name: "a-input-number",
|
||||||
|
vModel: "value",
|
||||||
|
},
|
||||||
|
helper: "检查域名验证解析记录重试次数,如果你的域名服务商解析生效速度慢,可以适当增加此值",
|
||||||
|
})
|
||||||
|
maxCheckRetryCount = 20;
|
||||||
|
|
||||||
acme!: AcmeService;
|
acme!: AcmeService;
|
||||||
|
|
||||||
eab!: EabAccess;
|
eab!: EabAccess;
|
||||||
@@ -314,6 +324,7 @@ HTTP文件验证:不支持泛域名,需要配置网站文件上传`,
|
|||||||
reverseProxy: this.reverseProxy,
|
reverseProxy: this.reverseProxy,
|
||||||
privateKeyType: this.privateKeyType,
|
privateKeyType: this.privateKeyType,
|
||||||
signal: this.ctx.signal,
|
signal: this.ctx.signal,
|
||||||
|
maxCheckRetryCount: this.maxCheckRetryCount,
|
||||||
// cnameProxyService: this.ctx.cnameProxyService,
|
// cnameProxyService: this.ctx.cnameProxyService,
|
||||||
// dnsProviderCreator: this.createDnsProvider.bind(this),
|
// dnsProviderCreator: this.createDnsProvider.bind(this),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,2 +1,6 @@
|
|||||||
|
export { EVENT_CERT_APPLY_SUCCESS } from "./cert-plugin/base-convert.js";
|
||||||
|
|
||||||
export * from "./cert-plugin/index.js";
|
export * from "./cert-plugin/index.js";
|
||||||
export * from "./cert-plugin/lego/index.js";
|
export * from "./cert-plugin/lego/index.js";
|
||||||
|
export * from "./cert-plugin/custom/index.js";
|
||||||
|
export const CertApplyPluginNames = ["CertApply", "CertApplyLego", "CertApplyUpload"];
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
"@typescript-eslint/ban-ts-ignore": "off",
|
"@typescript-eslint/ban-ts-ignore": "off",
|
||||||
"@typescript-eslint/no-explicit-any": "off",
|
"@typescript-eslint/no-explicit-any": "off",
|
||||||
"@typescript-eslint/no-empty-function": "off",
|
"@typescript-eslint/no-empty-function": "off",
|
||||||
// "no-unused-expressions": "off",
|
"@typescript-eslint/no-unused-vars": "off"
|
||||||
"max-len": [0, 160, 2, { "ignoreUrls": true }]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
{
|
{
|
||||||
"printWidth": 160
|
"printWidth": 220,
|
||||||
|
"bracketSpacing": true,
|
||||||
|
"singleQuote": false,
|
||||||
|
"trailingComma": "es5",
|
||||||
|
"arrowParens": "avoid"
|
||||||
}
|
}
|
||||||
@@ -3,6 +3,32 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.31.7](https://github.com/certd/certd/compare/v1.31.6...v1.31.7) (2025-03-24)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/plugin-lib
|
||||||
|
|
||||||
|
## [1.31.6](https://github.com/certd/certd/compare/v1.31.5...v1.31.6) (2025-03-24)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 上传到主机支持scp方式 ([05b6159](https://github.com/certd/certd/commit/05b6159802b9e85b6a410361b60b5c28875b48e7))
|
||||||
|
|
||||||
|
## [1.31.5](https://github.com/certd/certd/compare/v1.31.4...v1.31.5) (2025-03-22)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/plugin-lib
|
||||||
|
|
||||||
|
## [1.31.4](https://github.com/certd/certd/compare/v1.31.3...v1.31.4) (2025-03-21)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 流水线增加上传证书快捷方式 ([425bba6](https://github.com/certd/certd/commit/425bba67c539b734e2a85a83a4f9ecc9b2434fb4))
|
||||||
|
|
||||||
|
## [1.31.3](https://github.com/certd/certd/compare/v1.31.2...v1.31.3) (2025-03-13)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 支持部署到天翼云CDN ([82a72e0](https://github.com/certd/certd/commit/82a72e0b497efa043d342ad0e33c083a2de79a05))
|
||||||
|
|
||||||
## [1.31.2](https://github.com/certd/certd/compare/v1.31.1...v1.31.2) (2025-03-12)
|
## [1.31.2](https://github.com/certd/certd/compare/v1.31.1...v1.31.2) (2025-03-12)
|
||||||
|
|
||||||
**Note:** Version bump only for package @certd/plugin-lib
|
**Note:** Version bump only for package @certd/plugin-lib
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@certd/plugin-lib",
|
"name": "@certd/plugin-lib",
|
||||||
"private": false,
|
"private": false,
|
||||||
"version": "1.31.2",
|
"version": "1.31.7",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
"types": "./dist/index.d.ts",
|
"types": "./dist/index.d.ts",
|
||||||
@@ -16,8 +16,8 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@alicloud/pop-core": "^1.7.10",
|
"@alicloud/pop-core": "^1.7.10",
|
||||||
"@certd/basic": "^1.31.2",
|
"@certd/basic": "^1.31.7",
|
||||||
"@certd/pipeline": "^1.31.2",
|
"@certd/pipeline": "^1.31.7",
|
||||||
"@kubernetes/client-node": "0.21.0",
|
"@kubernetes/client-node": "0.21.0",
|
||||||
"ali-oss": "^6.21.0",
|
"ali-oss": "^6.21.0",
|
||||||
"basic-ftp": "^5.0.5",
|
"basic-ftp": "^5.0.5",
|
||||||
@@ -37,8 +37,8 @@
|
|||||||
"@types/chai": "^4.3.3",
|
"@types/chai": "^4.3.3",
|
||||||
"@types/mocha": "^10.0.0",
|
"@types/mocha": "^10.0.0",
|
||||||
"@types/psl": "^1.1.3",
|
"@types/psl": "^1.1.3",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.38.1",
|
"@typescript-eslint/eslint-plugin": "^8.26.1",
|
||||||
"@typescript-eslint/parser": "^5.38.1",
|
"@typescript-eslint/parser": "^8.26.1",
|
||||||
"chai": "^4.3.6",
|
"chai": "^4.3.6",
|
||||||
"eslint": "^8.24.0",
|
"eslint": "^8.24.0",
|
||||||
"eslint-config-prettier": "^8.5.0",
|
"eslint-config-prettier": "^8.5.0",
|
||||||
@@ -48,5 +48,5 @@
|
|||||||
"tslib": "^2.8.1",
|
"tslib": "^2.8.1",
|
||||||
"typescript": "^5.4.2"
|
"typescript": "^5.4.2"
|
||||||
},
|
},
|
||||||
"gitHead": "2a4d64af9502881e2e553ea86a4479158cfa8918"
|
"gitHead": "86ca35ce3381b98b455538b11219d9856be5d0d6"
|
||||||
}
|
}
|
||||||
|
|||||||
31
packages/plugins/plugin-lib/src/ctyun/access/ctyun-access.ts
Normal file
31
packages/plugins/plugin-lib/src/ctyun/access/ctyun-access.ts
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import { IsAccess, AccessInput, BaseAccess } from "@certd/pipeline";
|
||||||
|
|
||||||
|
@IsAccess({
|
||||||
|
name: "ctyun",
|
||||||
|
title: "天翼云授权",
|
||||||
|
desc: "",
|
||||||
|
icon: "ant-design:aliyun-outlined",
|
||||||
|
})
|
||||||
|
export class CtyunAccess extends BaseAccess {
|
||||||
|
@AccessInput({
|
||||||
|
title: "accessKeyId",
|
||||||
|
component: {
|
||||||
|
placeholder: "accessKeyId",
|
||||||
|
},
|
||||||
|
helper: "[前往创建天翼云AccessKey](https://iam.ctyun.cn/myAccessKey)",
|
||||||
|
required: true,
|
||||||
|
})
|
||||||
|
accessKeyId = "";
|
||||||
|
@AccessInput({
|
||||||
|
title: "securityKey",
|
||||||
|
component: {
|
||||||
|
placeholder: "securityKey",
|
||||||
|
},
|
||||||
|
required: true,
|
||||||
|
encrypt: true,
|
||||||
|
helper: "",
|
||||||
|
})
|
||||||
|
securityKey = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
new CtyunAccess();
|
||||||
1
packages/plugins/plugin-lib/src/ctyun/index.ts
Normal file
1
packages/plugins/plugin-lib/src/ctyun/index.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export * from "./access/ctyun-access.js";
|
||||||
@@ -4,3 +4,4 @@ export * from "./common/index.js";
|
|||||||
export * from "./ftp/index.js";
|
export * from "./ftp/index.js";
|
||||||
export * from "./tencent/index.js";
|
export * from "./tencent/index.js";
|
||||||
export * from "./qiniu/index.js";
|
export * from "./qiniu/index.js";
|
||||||
|
export * from "./ctyun/index.js";
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import { SshAccess } from "./ssh-access.js";
|
|||||||
import stripAnsi from "strip-ansi";
|
import stripAnsi from "strip-ansi";
|
||||||
import { SocksClient } from "socks";
|
import { SocksClient } from "socks";
|
||||||
import { SocksProxy, SocksProxyType } from "socks/typings/common/constants.js";
|
import { SocksProxy, SocksProxyType } from "socks/typings/common/constants.js";
|
||||||
|
import fs from "fs";
|
||||||
|
|
||||||
export type TransportItem = { localPath: string; remotePath: string };
|
export type TransportItem = { localPath: string; remotePath: string };
|
||||||
|
|
||||||
export class AsyncSsh2Client {
|
export class AsyncSsh2Client {
|
||||||
@@ -61,7 +63,17 @@ export class AsyncSsh2Client {
|
|||||||
this.conn = conn;
|
this.conn = conn;
|
||||||
resolve(this.conn);
|
resolve(this.conn);
|
||||||
})
|
})
|
||||||
.connect(this.connConf);
|
.connect({
|
||||||
|
...this.connConf,
|
||||||
|
algorithms: {
|
||||||
|
kex: [
|
||||||
|
"ecdh-sha2-nistp256",
|
||||||
|
"diffie-hellman-group1-sha1",
|
||||||
|
"diffie-hellman-group14-sha1", // 示例:添加服务器支持的旧算法
|
||||||
|
"diffie-hellman-group-exchange-sha256",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
reject(e);
|
reject(e);
|
||||||
}
|
}
|
||||||
@@ -255,15 +267,15 @@ export class SshClient {
|
|||||||
}
|
}
|
||||||
* @param options
|
* @param options
|
||||||
*/
|
*/
|
||||||
async uploadFiles(options: { connectConf: SshAccess; transports: TransportItem[]; mkdirs: boolean; opts?: { mode?: string } }) {
|
async uploadFiles(options: { connectConf: SshAccess; transports: TransportItem[]; mkdirs: boolean; opts?: { mode?: string }; uploadType?: string }) {
|
||||||
const { connectConf, transports, mkdirs, opts } = options;
|
const { connectConf, transports, mkdirs, opts } = options;
|
||||||
await this._call({
|
await this._call({
|
||||||
connectConf,
|
connectConf,
|
||||||
callable: async (conn: AsyncSsh2Client) => {
|
callable: async (conn: AsyncSsh2Client) => {
|
||||||
const sftp = await conn.getSftp();
|
|
||||||
this.logger.info("开始上传");
|
this.logger.info("开始上传");
|
||||||
for (const transport of transports) {
|
if (mkdirs !== false) {
|
||||||
if (mkdirs !== false) {
|
this.logger.info("初始化父目录");
|
||||||
|
for (const transport of transports) {
|
||||||
const filePath = path.dirname(transport.remotePath);
|
const filePath = path.dirname(transport.remotePath);
|
||||||
let mkdirCmd = `mkdir -p ${filePath} `;
|
let mkdirCmd = `mkdir -p ${filePath} `;
|
||||||
if (conn.windows) {
|
if (conn.windows) {
|
||||||
@@ -281,13 +293,60 @@ export class SshClient {
|
|||||||
}
|
}
|
||||||
await conn.exec(mkdirCmd);
|
await conn.exec(mkdirCmd);
|
||||||
}
|
}
|
||||||
await conn.fastPut({ sftp, ...transport, opts });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (options.uploadType === "sftp") {
|
||||||
|
const sftp = await conn.getSftp();
|
||||||
|
for (const transport of transports) {
|
||||||
|
await conn.fastPut({ sftp, ...transport, opts });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//scp
|
||||||
|
for (const transport of transports) {
|
||||||
|
await this.scpUpload({ conn, ...transport, opts });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.logger.info("文件全部上传成功");
|
this.logger.info("文件全部上传成功");
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async scpUpload(options: { conn: any; localPath: string; remotePath: string; opts?: { mode?: string } }) {
|
||||||
|
const { conn, localPath, remotePath } = options;
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
// 关键步骤:构造 SCP 命令
|
||||||
|
try {
|
||||||
|
this.logger.info(`开始上传:${localPath} => ${remotePath}`);
|
||||||
|
conn.conn.exec(
|
||||||
|
`scp -t ${remotePath}`, // -t 表示目标模式
|
||||||
|
(err, stream) => {
|
||||||
|
if (err) {
|
||||||
|
return reject(err);
|
||||||
|
}
|
||||||
|
// 准备 SCP 协议头
|
||||||
|
const fileStats = fs.statSync(localPath);
|
||||||
|
const fileName = path.basename(localPath);
|
||||||
|
|
||||||
|
// SCP 协议格式:C[权限] [文件大小] [文件名]\n
|
||||||
|
stream.write(`C0644 ${fileStats.size} ${fileName}\n`);
|
||||||
|
|
||||||
|
// 通过管道传输文件
|
||||||
|
fs.createReadStream(localPath)
|
||||||
|
.pipe(stream)
|
||||||
|
.on("finish", () => {
|
||||||
|
this.logger.info(`上传文件成功:${localPath} => ${remotePath}`);
|
||||||
|
resolve(true);
|
||||||
|
})
|
||||||
|
.on("error", reject);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
reject(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
async removeFiles(opts: { connectConf: SshAccess; files: string[] }) {
|
async removeFiles(opts: { connectConf: SshAccess; files: string[] }) {
|
||||||
const { connectConf, files } = opts;
|
const { connectConf, files } = opts;
|
||||||
await this._call({
|
await this._call({
|
||||||
|
|||||||
@@ -3,34 +3,34 @@ module.exports = {
|
|||||||
env: {
|
env: {
|
||||||
browser: true,
|
browser: true,
|
||||||
node: true,
|
node: true,
|
||||||
es6: true
|
es6: true,
|
||||||
},
|
},
|
||||||
parser: "vue-eslint-parser",
|
parser: 'vue-eslint-parser',
|
||||||
parserOptions: {
|
parserOptions: {
|
||||||
parser: "@typescript-eslint/parser",
|
parser: '@typescript-eslint/parser',
|
||||||
ecmaVersion: 2020,
|
ecmaVersion: 2020,
|
||||||
sourceType: "module",
|
sourceType: 'module',
|
||||||
jsxPragma: "React",
|
jsxPragma: 'React',
|
||||||
ecmaFeatures: {
|
ecmaFeatures: {
|
||||||
jsx: true,
|
jsx: true,
|
||||||
tsx: true
|
tsx: true,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
extends: ["plugin:vue/vue3-recommended", "plugin:@typescript-eslint/recommended", "plugin:prettier/recommended", "prettier"],
|
extends: ['plugin:vue/vue3-recommended', 'plugin:@typescript-eslint/recommended', 'plugin:prettier/recommended', 'prettier'],
|
||||||
rules: {
|
rules: {
|
||||||
//"max-len": [0, 200, 2, { ignoreUrls: true }],
|
//"max-len": [0, 200, 2, { ignoreUrls: true }],
|
||||||
"@typescript-eslint/no-unused-vars": "off",
|
'@typescript-eslint/no-unused-vars': 'off',
|
||||||
"no-unused-vars": "off",
|
'no-unused-vars': 'off',
|
||||||
"@typescript-eslint/ban-ts-ignore": "off",
|
'@typescript-eslint/ban-ts-ignore': 'off',
|
||||||
"@typescript-eslint/ban-ts-comment": "off",
|
'@typescript-eslint/ban-ts-comment': 'off',
|
||||||
"@typescript-eslint/ban-types": "off",
|
'@typescript-eslint/ban-types': 'off',
|
||||||
"@typescript-eslint/explicit-function-return-type": "off",
|
'@typescript-eslint/explicit-function-return-type': 'off',
|
||||||
"@typescript-eslint/no-explicit-any": "off",
|
'@typescript-eslint/no-explicit-any': 'off',
|
||||||
"@typescript-eslint/no-var-requires": "off",
|
'@typescript-eslint/no-var-requires': 'off',
|
||||||
"@typescript-eslint/no-empty-function": "off",
|
'@typescript-eslint/no-empty-function': 'off',
|
||||||
"@typescript-eslint/no-use-before-define": "off",
|
'@typescript-eslint/no-use-before-define': 'off',
|
||||||
"@typescript-eslint/no-non-null-assertion": "off",
|
'@typescript-eslint/no-non-null-assertion': 'off',
|
||||||
"@typescript-eslint/explicit-module-boundary-types": "off"
|
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
||||||
// "@typescript-eslint/no-unused-vars": [
|
// "@typescript-eslint/no-unused-vars": [
|
||||||
// "error",
|
// "error",
|
||||||
// {
|
// {
|
||||||
@@ -69,5 +69,5 @@ module.exports = {
|
|||||||
// math: "always",
|
// math: "always",
|
||||||
// },
|
// },
|
||||||
// ],
|
// ],
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
{
|
{
|
||||||
|
"printWidth": 220,
|
||||||
"trailingComma": "none",
|
"bracketSpacing": true,
|
||||||
"printWidth": 220
|
"singleQuote": false,
|
||||||
|
"trailingComma": "es5",
|
||||||
|
"arrowParens": "avoid"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,53 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.31.7](https://github.com/certd/certd/compare/v1.31.6...v1.31.7) (2025-03-24)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 增加服务器时间警告 ([d66ade4](https://github.com/certd/certd/commit/d66ade4e4783850b6c7625c6f164a5a0fc0aa509))
|
||||||
|
* 支持部署到lucky ([e18e399](https://github.com/certd/certd/commit/e18e399ce6529e8c7e36b56c5f674cfdbbd3d3d1))
|
||||||
|
|
||||||
|
## [1.31.6](https://github.com/certd/certd/compare/v1.31.5...v1.31.6) (2025-03-24)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 优化图标 ([c56f48c](https://github.com/certd/certd/commit/c56f48c1e3c54c4e203fafb380d9091d75681b7e))
|
||||||
|
|
||||||
|
## [1.31.5](https://github.com/certd/certd/compare/v1.31.4...v1.31.5) (2025-03-22)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复通知选择器无法选择的bug ([f7b88f9](https://github.com/certd/certd/commit/f7b88f9e3b7d9d9122e4fd2003a20c555bd50c7d))
|
||||||
|
* 修复证书流水线创建失败的bug ([736fe03](https://github.com/certd/certd/commit/736fe038ebda56648bcc4c12884a700341d2c049))
|
||||||
|
|
||||||
|
## [1.31.4](https://github.com/certd/certd/compare/v1.31.3...v1.31.4) (2025-03-21)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复站点监控通知通过webhook发送失败的bug ([9be1ecc](https://github.com/certd/certd/commit/9be1ecc8aab3ea23dd0dc2dab3688f4edb90ef2c))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 宝塔支持doker站点证书部署 ([589a373](https://github.com/certd/certd/commit/589a373142ef7f50d64d3aa767a90b1f4b64da93))
|
||||||
|
* 保存调整后的列宽 ([873f2b6](https://github.com/certd/certd/commit/873f2b618b9d7320045baf69d6da83afe48a780f))
|
||||||
|
* 创建证书流水线时,支持更多参数展开 ([36aa7f8](https://github.com/certd/certd/commit/36aa7f82b078a053a102331b3c6f132fb9d492f9))
|
||||||
|
* 流水线页面可以鼠标按住左右拖动 ([d85a02f](https://github.com/certd/certd/commit/d85a02feeb3183c5abd6c1ea790d5923a32d7271))
|
||||||
|
* 流水线增加上传证书快捷方式 ([425bba6](https://github.com/certd/certd/commit/425bba67c539b734e2a85a83a4f9ecc9b2434fb4))
|
||||||
|
* 手动上传证书部署流水线 ([fbb66f3](https://github.com/certd/certd/commit/fbb66f3c4389489aa8a43b194d82bc8cf391607b))
|
||||||
|
* 优化选择任务时手机版展示效果 ([d01004d](https://github.com/certd/certd/commit/d01004d53071a75ac91ee21cc96bde9369f77ff3))
|
||||||
|
* 站点证书监控支持模糊查询 ([0069c0e](https://github.com/certd/certd/commit/0069c0e3992946a8dd6410f299d4fc974ef0e76b))
|
||||||
|
* 支持飞书通知 ([b82e1dc](https://github.com/certd/certd/commit/b82e1dcd6217b09a7d7e21cd648bb31de320cadf))
|
||||||
|
* 支持手动上传证书并部署 ([a9fffa5](https://github.com/certd/certd/commit/a9fffa5180c83da27b35886aa2e858a92a2c5f94))
|
||||||
|
|
||||||
|
## [1.31.3](https://github.com/certd/certd/compare/v1.31.2...v1.31.3) (2025-03-13)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 套餐支持3天7天等选项 ([0d71a8e](https://github.com/certd/certd/commit/0d71a8ee501a0e5bb69decf07e8729026e9d85bf))
|
||||||
|
* 证书仓库增加有效期显示 ([be87124](https://github.com/certd/certd/commit/be87124ada7a093f281ca29a45c86b4ea4644ead))
|
||||||
|
* 支持部署到天翼云CDN ([82a72e0](https://github.com/certd/certd/commit/82a72e0b497efa043d342ad0e33c083a2de79a05))
|
||||||
|
|
||||||
## [1.31.2](https://github.com/certd/certd/compare/v1.31.1...v1.31.2) (2025-03-12)
|
## [1.31.2](https://github.com/certd/certd/compare/v1.31.1...v1.31.2) (2025-03-12)
|
||||||
|
|
||||||
**Note:** Version bump only for package @certd/ui-client
|
**Note:** Version bump only for package @certd/ui-client
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@certd/ui-client",
|
"name": "@certd/ui-client",
|
||||||
"version": "1.31.2",
|
"version": "1.31.7",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite --open",
|
"dev": "vite --open",
|
||||||
@@ -67,6 +67,7 @@
|
|||||||
"lucide-vue-next": "^0.477.0",
|
"lucide-vue-next": "^0.477.0",
|
||||||
"mitt": "^3.0.1",
|
"mitt": "^3.0.1",
|
||||||
"nanoid": "^4.0.0",
|
"nanoid": "^4.0.0",
|
||||||
|
"node-forge": "^1.3.1",
|
||||||
"nprogress": "^0.2.0",
|
"nprogress": "^0.2.0",
|
||||||
"object-assign": "^4.1.1",
|
"object-assign": "^4.1.1",
|
||||||
"pinia": "2.1.7",
|
"pinia": "2.1.7",
|
||||||
@@ -95,8 +96,8 @@
|
|||||||
"zod-defaults": "^0.1.3"
|
"zod-defaults": "^0.1.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@certd/lib-iframe": "^1.31.2",
|
"@certd/lib-iframe": "^1.31.7",
|
||||||
"@certd/pipeline": "^1.31.2",
|
"@certd/pipeline": "^1.31.7",
|
||||||
"@rollup/plugin-commonjs": "^25.0.7",
|
"@rollup/plugin-commonjs": "^25.0.7",
|
||||||
"@rollup/plugin-node-resolve": "^15.2.3",
|
"@rollup/plugin-node-resolve": "^15.2.3",
|
||||||
"@types/chai": "^4.3.12",
|
"@types/chai": "^4.3.12",
|
||||||
|
|||||||
@@ -54,6 +54,72 @@
|
|||||||
<div class="content unicode" style="display: block;">
|
<div class="content unicode" style="display: block;">
|
||||||
<ul class="icon_lists dib-box">
|
<ul class="icon_lists dib-box">
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon iconfont"></span>
|
||||||
|
<div class="name">plesk_</div>
|
||||||
|
<div class="code-name">&#xecc0;</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon iconfont"></span>
|
||||||
|
<div class="name">易支付-01</div>
|
||||||
|
<div class="code-name">&#xe741;</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon iconfont"></span>
|
||||||
|
<div class="name">1Panel</div>
|
||||||
|
<div class="code-name">&#xe606;</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon iconfont"></span>
|
||||||
|
<div class="name">西部数码</div>
|
||||||
|
<div class="code-name">&#xe73c;</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon iconfont"></span>
|
||||||
|
<div class="name">qnap</div>
|
||||||
|
<div class="code-name">&#xe607;</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon iconfont"></span>
|
||||||
|
<div class="name">proxmox</div>
|
||||||
|
<div class="code-name">&#xe9cc;</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon iconfont"></span>
|
||||||
|
<div class="name">aws</div>
|
||||||
|
<div class="code-name">&#xe604;</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon iconfont"></span>
|
||||||
|
<div class="name">uni-app</div>
|
||||||
|
<div class="code-name">&#xe602;</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon iconfont"></span>
|
||||||
|
<div class="name">lucky</div>
|
||||||
|
<div class="code-name">&#xe752;</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon iconfont"></span>
|
||||||
|
<div class="name">ctyun</div>
|
||||||
|
<div class="code-name">&#xe719;</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon iconfont"></span>
|
||||||
|
<div class="name">雷池</div>
|
||||||
|
<div class="code-name">&#xe748;</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
<li class="dib">
|
<li class="dib">
|
||||||
<span class="icon iconfont"></span>
|
<span class="icon iconfont"></span>
|
||||||
<div class="name">华为</div>
|
<div class="name">华为</div>
|
||||||
@@ -108,7 +174,7 @@
|
|||||||
<pre><code class="language-css"
|
<pre><code class="language-css"
|
||||||
>@font-face {
|
>@font-face {
|
||||||
font-family: 'iconfont';
|
font-family: 'iconfont';
|
||||||
src: url('iconfont.svg?t=1730278432006#iconfont') format('svg');
|
src: url('iconfont.svg?t=1742822771904#iconfont') format('svg');
|
||||||
}
|
}
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
|
<h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
|
||||||
@@ -134,6 +200,105 @@
|
|||||||
<div class="content font-class">
|
<div class="content font-class">
|
||||||
<ul class="icon_lists dib-box">
|
<ul class="icon_lists dib-box">
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon iconfont icon-plesk"></span>
|
||||||
|
<div class="name">
|
||||||
|
plesk_
|
||||||
|
</div>
|
||||||
|
<div class="code-name">.icon-plesk
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon iconfont icon-yizhifu"></span>
|
||||||
|
<div class="name">
|
||||||
|
易支付-01
|
||||||
|
</div>
|
||||||
|
<div class="code-name">.icon-yizhifu
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon iconfont icon-onepanel"></span>
|
||||||
|
<div class="name">
|
||||||
|
1Panel
|
||||||
|
</div>
|
||||||
|
<div class="code-name">.icon-onepanel
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon iconfont icon-xibushuma"></span>
|
||||||
|
<div class="name">
|
||||||
|
西部数码
|
||||||
|
</div>
|
||||||
|
<div class="code-name">.icon-xibushuma
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon iconfont icon-qnap"></span>
|
||||||
|
<div class="name">
|
||||||
|
qnap
|
||||||
|
</div>
|
||||||
|
<div class="code-name">.icon-qnap
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon iconfont icon-proxmox"></span>
|
||||||
|
<div class="name">
|
||||||
|
proxmox
|
||||||
|
</div>
|
||||||
|
<div class="code-name">.icon-proxmox
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon iconfont icon-aws"></span>
|
||||||
|
<div class="name">
|
||||||
|
aws
|
||||||
|
</div>
|
||||||
|
<div class="code-name">.icon-aws
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon iconfont icon-uniapp"></span>
|
||||||
|
<div class="name">
|
||||||
|
uni-app
|
||||||
|
</div>
|
||||||
|
<div class="code-name">.icon-uniapp
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon iconfont icon-lucky"></span>
|
||||||
|
<div class="name">
|
||||||
|
lucky
|
||||||
|
</div>
|
||||||
|
<div class="code-name">.icon-lucky
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon iconfont icon-ctyun"></span>
|
||||||
|
<div class="name">
|
||||||
|
ctyun
|
||||||
|
</div>
|
||||||
|
<div class="code-name">.icon-ctyun
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon iconfont icon-safeline"></span>
|
||||||
|
<div class="name">
|
||||||
|
雷池
|
||||||
|
</div>
|
||||||
|
<div class="code-name">.icon-safeline
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
<li class="dib">
|
<li class="dib">
|
||||||
<span class="icon iconfont icon-huawei"></span>
|
<span class="icon iconfont icon-huawei"></span>
|
||||||
<div class="name">
|
<div class="name">
|
||||||
@@ -215,6 +380,94 @@
|
|||||||
<div class="content symbol">
|
<div class="content symbol">
|
||||||
<ul class="icon_lists dib-box">
|
<ul class="icon_lists dib-box">
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<svg class="icon svg-icon" aria-hidden="true">
|
||||||
|
<use xlink:href="#icon-plesk"></use>
|
||||||
|
</svg>
|
||||||
|
<div class="name">plesk_</div>
|
||||||
|
<div class="code-name">#icon-plesk</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<svg class="icon svg-icon" aria-hidden="true">
|
||||||
|
<use xlink:href="#icon-yizhifu"></use>
|
||||||
|
</svg>
|
||||||
|
<div class="name">易支付-01</div>
|
||||||
|
<div class="code-name">#icon-yizhifu</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<svg class="icon svg-icon" aria-hidden="true">
|
||||||
|
<use xlink:href="#icon-onepanel"></use>
|
||||||
|
</svg>
|
||||||
|
<div class="name">1Panel</div>
|
||||||
|
<div class="code-name">#icon-onepanel</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<svg class="icon svg-icon" aria-hidden="true">
|
||||||
|
<use xlink:href="#icon-xibushuma"></use>
|
||||||
|
</svg>
|
||||||
|
<div class="name">西部数码</div>
|
||||||
|
<div class="code-name">#icon-xibushuma</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<svg class="icon svg-icon" aria-hidden="true">
|
||||||
|
<use xlink:href="#icon-qnap"></use>
|
||||||
|
</svg>
|
||||||
|
<div class="name">qnap</div>
|
||||||
|
<div class="code-name">#icon-qnap</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<svg class="icon svg-icon" aria-hidden="true">
|
||||||
|
<use xlink:href="#icon-proxmox"></use>
|
||||||
|
</svg>
|
||||||
|
<div class="name">proxmox</div>
|
||||||
|
<div class="code-name">#icon-proxmox</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<svg class="icon svg-icon" aria-hidden="true">
|
||||||
|
<use xlink:href="#icon-aws"></use>
|
||||||
|
</svg>
|
||||||
|
<div class="name">aws</div>
|
||||||
|
<div class="code-name">#icon-aws</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<svg class="icon svg-icon" aria-hidden="true">
|
||||||
|
<use xlink:href="#icon-uniapp"></use>
|
||||||
|
</svg>
|
||||||
|
<div class="name">uni-app</div>
|
||||||
|
<div class="code-name">#icon-uniapp</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<svg class="icon svg-icon" aria-hidden="true">
|
||||||
|
<use xlink:href="#icon-lucky"></use>
|
||||||
|
</svg>
|
||||||
|
<div class="name">lucky</div>
|
||||||
|
<div class="code-name">#icon-lucky</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<svg class="icon svg-icon" aria-hidden="true">
|
||||||
|
<use xlink:href="#icon-ctyun"></use>
|
||||||
|
</svg>
|
||||||
|
<div class="name">ctyun</div>
|
||||||
|
<div class="code-name">#icon-ctyun</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<svg class="icon svg-icon" aria-hidden="true">
|
||||||
|
<use xlink:href="#icon-safeline"></use>
|
||||||
|
</svg>
|
||||||
|
<div class="name">雷池</div>
|
||||||
|
<div class="code-name">#icon-safeline</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
<li class="dib">
|
<li class="dib">
|
||||||
<svg class="icon svg-icon" aria-hidden="true">
|
<svg class="icon svg-icon" aria-hidden="true">
|
||||||
<use xlink:href="#icon-huawei"></use>
|
<use xlink:href="#icon-huawei"></use>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
@font-face {
|
@font-face {
|
||||||
font-family: "iconfont"; /* Project id 4688792 */
|
font-family: "iconfont"; /* Project id 4688792 */
|
||||||
src: url('iconfont.svg?t=1730278432006#iconfont') format('svg');
|
src: url('iconfont.svg?t=1742822771904#iconfont') format('svg');
|
||||||
}
|
}
|
||||||
|
|
||||||
.iconfont {
|
.iconfont {
|
||||||
@@ -11,6 +11,50 @@
|
|||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.icon-plesk:before {
|
||||||
|
content: "\ecc0";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-yizhifu:before {
|
||||||
|
content: "\e741";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-onepanel:before {
|
||||||
|
content: "\e606";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-xibushuma:before {
|
||||||
|
content: "\e73c";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-qnap:before {
|
||||||
|
content: "\e607";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-proxmox:before {
|
||||||
|
content: "\e9cc";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-aws:before {
|
||||||
|
content: "\e604";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-uniapp:before {
|
||||||
|
content: "\e602";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-lucky:before {
|
||||||
|
content: "\e752";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-ctyun:before {
|
||||||
|
content: "\e719";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-safeline:before {
|
||||||
|
content: "\e748";
|
||||||
|
}
|
||||||
|
|
||||||
.icon-huawei:before {
|
.icon-huawei:before {
|
||||||
content: "\e610";
|
content: "\e610";
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -5,6 +5,83 @@
|
|||||||
"css_prefix_text": "icon-",
|
"css_prefix_text": "icon-",
|
||||||
"description": "",
|
"description": "",
|
||||||
"glyphs": [
|
"glyphs": [
|
||||||
|
{
|
||||||
|
"icon_id": "27272666",
|
||||||
|
"name": "plesk_",
|
||||||
|
"font_class": "plesk",
|
||||||
|
"unicode": "ecc0",
|
||||||
|
"unicode_decimal": 60608
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "23930871",
|
||||||
|
"name": "易支付-01",
|
||||||
|
"font_class": "yizhifu",
|
||||||
|
"unicode": "e741",
|
||||||
|
"unicode_decimal": 59201
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "40476533",
|
||||||
|
"name": "1Panel",
|
||||||
|
"font_class": "onepanel",
|
||||||
|
"unicode": "e606",
|
||||||
|
"unicode_decimal": 58886
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "26435508",
|
||||||
|
"name": "西部数码",
|
||||||
|
"font_class": "xibushuma",
|
||||||
|
"unicode": "e73c",
|
||||||
|
"unicode_decimal": 59196
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "27487624",
|
||||||
|
"name": "qnap",
|
||||||
|
"font_class": "qnap",
|
||||||
|
"unicode": "e607",
|
||||||
|
"unicode_decimal": 58887
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "27268231",
|
||||||
|
"name": "proxmox",
|
||||||
|
"font_class": "proxmox",
|
||||||
|
"unicode": "e9cc",
|
||||||
|
"unicode_decimal": 59852
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "31636255",
|
||||||
|
"name": "aws",
|
||||||
|
"font_class": "aws",
|
||||||
|
"unicode": "e604",
|
||||||
|
"unicode_decimal": 58884
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "34071209",
|
||||||
|
"name": "uni-app",
|
||||||
|
"font_class": "uniapp",
|
||||||
|
"unicode": "e602",
|
||||||
|
"unicode_decimal": 58882
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "3467975",
|
||||||
|
"name": "lucky",
|
||||||
|
"font_class": "lucky",
|
||||||
|
"unicode": "e752",
|
||||||
|
"unicode_decimal": 59218
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "41854563",
|
||||||
|
"name": "ctyun",
|
||||||
|
"font_class": "ctyun",
|
||||||
|
"unicode": "e719",
|
||||||
|
"unicode_decimal": 59161
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "43757703",
|
||||||
|
"name": "雷池",
|
||||||
|
"font_class": "safeline",
|
||||||
|
"unicode": "e748",
|
||||||
|
"unicode_decimal": 59208
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"icon_id": "24164616",
|
"icon_id": "24164616",
|
||||||
"name": "华为",
|
"name": "华为",
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 39 KiB |
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<AConfigProvider :locale="locale" :theme="tokenTheme">
|
<AConfigProvider :locale="locale" :theme="tokenTheme">
|
||||||
<contextHolder />
|
|
||||||
<fs-form-provider>
|
<fs-form-provider>
|
||||||
|
<contextHolder />
|
||||||
<router-view />
|
<router-view />
|
||||||
</fs-form-provider>
|
</fs-form-provider>
|
||||||
</AConfigProvider>
|
</AConfigProvider>
|
||||||
@@ -21,7 +21,7 @@ import AConfigProvider from "ant-design-vue/es/config-provider";
|
|||||||
import { Modal } from "ant-design-vue";
|
import { Modal } from "ant-design-vue";
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: "App"
|
name: "App",
|
||||||
});
|
});
|
||||||
const [modal, contextHolder] = Modal.useModal();
|
const [modal, contextHolder] = Modal.useModal();
|
||||||
provide("modal", modal);
|
provide("modal", modal);
|
||||||
@@ -59,7 +59,7 @@ const tokenTheme = computed(() => {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
algorithm,
|
algorithm,
|
||||||
token: tokens
|
token: tokens,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
//其他初始化
|
//其他初始化
|
||||||
|
|||||||
@@ -7,6 +7,11 @@ export type SiteEnv = {
|
|||||||
contactLink?: string;
|
contactLink?: string;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
export type AppInfo = {
|
||||||
|
version?: string;
|
||||||
|
time?: number;
|
||||||
|
deltaTime?: number;
|
||||||
|
};
|
||||||
export type SiteInfo = {
|
export type SiteInfo = {
|
||||||
title?: string;
|
title?: string;
|
||||||
slogan?: string;
|
slogan?: string;
|
||||||
@@ -71,12 +76,13 @@ export type AllSettings = {
|
|||||||
siteEnv: SiteEnv;
|
siteEnv: SiteEnv;
|
||||||
headerMenus: HeaderMenus;
|
headerMenus: HeaderMenus;
|
||||||
suiteSetting: SuiteSetting;
|
suiteSetting: SuiteSetting;
|
||||||
|
app: AppInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
export async function loadAllSettings(): Promise<AllSettings> {
|
export async function loadAllSettings(): Promise<AllSettings> {
|
||||||
return await request({
|
return await request({
|
||||||
url: "/basic/settings/all",
|
url: "/basic/settings/all",
|
||||||
method: "get"
|
method: "get",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,7 +90,7 @@ export async function bindUrl(data: any): Promise<any> {
|
|||||||
return await request({
|
return await request({
|
||||||
url: "/sys/plus/bindUrl",
|
url: "/sys/plus/bindUrl",
|
||||||
method: "post",
|
method: "post",
|
||||||
data
|
data,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,7 +98,7 @@ export async function sendSmsCode(data: any): Promise<any> {
|
|||||||
return await request({
|
return await request({
|
||||||
url: "/basic/code/sendSmsCode",
|
url: "/basic/code/sendSmsCode",
|
||||||
method: "post",
|
method: "post",
|
||||||
data
|
data,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,6 +106,6 @@ export async function sendEmailCode(data: any): Promise<any> {
|
|||||||
return await request({
|
return await request({
|
||||||
url: "/basic/code/sendEmailCode",
|
url: "/basic/code/sendEmailCode",
|
||||||
method: "post",
|
method: "post",
|
||||||
data
|
data,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
27
packages/ui/certd-client/src/components/file-input.vue
Normal file
27
packages/ui/certd-client/src/components/file-input.vue
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<template>
|
||||||
|
<div class="file-input">
|
||||||
|
<a-button :type="type" @click="onClick">{{ text }}</a-button> {{ fileName }}
|
||||||
|
<div class="hidden">
|
||||||
|
<input ref="fileInputRef" type="file" @change="onFileChange" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, defineEmits, defineProps } from "vue";
|
||||||
|
const fileInputRef = ref<HTMLInputElement | null>(null);
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
text: string;
|
||||||
|
type: string;
|
||||||
|
}>();
|
||||||
|
const fileName = ref("");
|
||||||
|
const emit = defineEmits(["change"]);
|
||||||
|
function onClick() {
|
||||||
|
fileInputRef.value.click();
|
||||||
|
}
|
||||||
|
function onFileChange(e: any) {
|
||||||
|
fileName.value = e.target.files[0].name;
|
||||||
|
emit("change", e);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -10,10 +10,14 @@ import Plugins from "./plugins/index";
|
|||||||
import LoadingButton from "./loading-button.vue";
|
import LoadingButton from "./loading-button.vue";
|
||||||
import IconSelect from "./icon-select.vue";
|
import IconSelect from "./icon-select.vue";
|
||||||
import ExpiresTimeText from "./expires-time-text.vue";
|
import ExpiresTimeText from "./expires-time-text.vue";
|
||||||
|
import FileInput from "./file-input.vue";
|
||||||
|
import PemInput from "./pem-input.vue";
|
||||||
export default {
|
export default {
|
||||||
install(app: any) {
|
install(app: any) {
|
||||||
app.component("PiContainer", PiContainer);
|
app.component("PiContainer", PiContainer);
|
||||||
app.component("TextEditable", TextEditable);
|
app.component("TextEditable", TextEditable);
|
||||||
|
app.component("FileInput", FileInput);
|
||||||
|
app.component("PemInput", PemInput);
|
||||||
|
|
||||||
app.component("CronLight", CronLight);
|
app.component("CronLight", CronLight);
|
||||||
app.component("CronEditor", CronEditor);
|
app.component("CronEditor", CronEditor);
|
||||||
@@ -29,5 +33,5 @@ export default {
|
|||||||
app.component("ExpiresTimeText", ExpiresTimeText);
|
app.component("ExpiresTimeText", ExpiresTimeText);
|
||||||
app.use(vip);
|
app.use(vip);
|
||||||
app.use(Plugins);
|
app.use(Plugins);
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
60
packages/ui/certd-client/src/components/pem-input.vue
Normal file
60
packages/ui/certd-client/src/components/pem-input.vue
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
<template>
|
||||||
|
<div class="pem-input">
|
||||||
|
<FileInput v-bind="fileInput" class="mb-5" type="primary" text="选择文件" @change="onChange" />
|
||||||
|
<a-textarea v-bind="textarea" v-model:value="textRef"></a-textarea>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { notification } from "ant-design-vue";
|
||||||
|
import { ref, watch, defineEmits } from "vue";
|
||||||
|
import FileInput from "/@/components/file-input.vue";
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
modelValue?: string;
|
||||||
|
textarea?: any;
|
||||||
|
fileInput?: any;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const emit = defineEmits(["update:modelValue"]);
|
||||||
|
const textRef = ref();
|
||||||
|
|
||||||
|
function emitValue(value: string) {
|
||||||
|
emit("update:modelValue", value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onChange(e: any) {
|
||||||
|
const file = e.target.files[0];
|
||||||
|
const size = file.size;
|
||||||
|
if (size > 100 * 1024) {
|
||||||
|
notification.error({
|
||||||
|
message: "文件超过100k,请选择正确的证书文件",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const fileReader = new FileReader();
|
||||||
|
fileReader.onload = function (e: any) {
|
||||||
|
const value = e.target.result;
|
||||||
|
emitValue(value);
|
||||||
|
};
|
||||||
|
fileReader.readAsText(file); // 以文本形式读取文件
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.modelValue,
|
||||||
|
value => {
|
||||||
|
textRef.value = value;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
immediate: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less">
|
||||||
|
.pem-input {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 5px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -60,6 +60,9 @@ const doTest = async () => {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
message.value = "测试请求成功";
|
message.value = "测试请求成功";
|
||||||
|
if (res) {
|
||||||
|
message.value += `,返回:${JSON.stringify(res)}`;
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import DnsProviderSelector from "/@/components/plugins/cert/dns-provider-selecto
|
|||||||
import DomainsVerifyPlanEditor from "/@/components/plugins/cert/domains-verify-plan-editor/index.vue";
|
import DomainsVerifyPlanEditor from "/@/components/plugins/cert/domains-verify-plan-editor/index.vue";
|
||||||
import AccessSelector from "/@/views/certd/access/access-selector/index.vue";
|
import AccessSelector from "/@/views/certd/access/access-selector/index.vue";
|
||||||
import InputPassword from "./common/input-password.vue";
|
import InputPassword from "./common/input-password.vue";
|
||||||
|
import CertInfoUpdater from "/@/views/certd/pipeline/cert-upload/index.vue";
|
||||||
import ApiTest from "./common/api-test.vue";
|
import ApiTest from "./common/api-test.vue";
|
||||||
export * from "./cert/index.js";
|
export * from "./cert/index.js";
|
||||||
export default {
|
export default {
|
||||||
@@ -14,11 +15,13 @@ export default {
|
|||||||
app.component("DnsProviderSelector", DnsProviderSelector);
|
app.component("DnsProviderSelector", DnsProviderSelector);
|
||||||
app.component("DomainsVerifyPlanEditor", DomainsVerifyPlanEditor);
|
app.component("DomainsVerifyPlanEditor", DomainsVerifyPlanEditor);
|
||||||
app.component("AccessSelector", AccessSelector);
|
app.component("AccessSelector", AccessSelector);
|
||||||
|
app.component("CertInfoUpdater", CertInfoUpdater);
|
||||||
|
|
||||||
app.component("ApiTest", ApiTest);
|
app.component("ApiTest", ApiTest);
|
||||||
|
|
||||||
app.component("SynologyDeviceIdGetter", SynologyIdDeviceGetter);
|
app.component("SynologyDeviceIdGetter", SynologyIdDeviceGetter);
|
||||||
app.component("RemoteSelect", RemoteSelect);
|
app.component("RemoteSelect", RemoteSelect);
|
||||||
app.component("CertDomainsGetter", CertDomainsGetter);
|
app.component("CertDomainsGetter", CertDomainsGetter);
|
||||||
app.component("InputPassword", InputPassword);
|
app.component("InputPassword", InputPassword);
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -24,9 +24,9 @@ export async function doRequest(req: RequestHandleReq, opts: any = {}) {
|
|||||||
typeName,
|
typeName,
|
||||||
action,
|
action,
|
||||||
data,
|
data,
|
||||||
input
|
input,
|
||||||
},
|
},
|
||||||
...opts
|
...opts,
|
||||||
});
|
});
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,16 +6,48 @@ import { FsExtendsCopyable, FsExtendsEditor, FsExtendsJson, FsExtendsTime, FsExt
|
|||||||
import "@fast-crud/fast-extends/dist/style.css";
|
import "@fast-crud/fast-extends/dist/style.css";
|
||||||
import UiAntdv from "@fast-crud/ui-antdv4";
|
import UiAntdv from "@fast-crud/ui-antdv4";
|
||||||
import "@fast-crud/ui-antdv4/dist/style.css";
|
import "@fast-crud/ui-antdv4/dist/style.css";
|
||||||
import { merge } from "lodash-es";
|
import { debounce, merge } from "lodash-es";
|
||||||
import { useCrudPermission } from "../permission";
|
import { useCrudPermission } from "../permission";
|
||||||
import { App } from "vue";
|
import { App } from "vue";
|
||||||
import { notification } from "ant-design-vue";
|
import { notification } from "ant-design-vue";
|
||||||
import { usePreferences } from "/@/vben/preferences";
|
import { usePreferences } from "/@/vben/preferences";
|
||||||
|
import { LocalStorage } from "/@/utils/util.storage";
|
||||||
|
|
||||||
|
class ColumnSizeSaver {
|
||||||
|
save: (key: string, size: number) => void;
|
||||||
|
constructor() {
|
||||||
|
this.save = debounce((key: string, size: number) => {
|
||||||
|
const saveKey = this.getKey();
|
||||||
|
let data = LocalStorage.get(saveKey);
|
||||||
|
if (!data) {
|
||||||
|
data = {};
|
||||||
|
}
|
||||||
|
data[key] = size;
|
||||||
|
LocalStorage.set(saveKey, data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
getKey() {
|
||||||
|
const loc = window.location;
|
||||||
|
const currentUrl = `${loc.pathname}${loc.search}${loc.hash}`;
|
||||||
|
return `columnSize-${currentUrl}`;
|
||||||
|
}
|
||||||
|
get(key: string) {
|
||||||
|
const saveKey = this.getKey();
|
||||||
|
const row = LocalStorage.get(saveKey);
|
||||||
|
return row?.[key];
|
||||||
|
}
|
||||||
|
clear() {
|
||||||
|
const saveKey = this.getKey();
|
||||||
|
LocalStorage.remove(saveKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const columnSizeSaver = new ColumnSizeSaver();
|
||||||
|
|
||||||
function install(app: App, options: any = {}) {
|
function install(app: App, options: any = {}) {
|
||||||
app.use(UiAntdv);
|
app.use(UiAntdv);
|
||||||
//设置日志级别
|
//设置日志级别
|
||||||
setLogger({ level: "info" });
|
setLogger({ level: "info" });
|
||||||
|
|
||||||
app.use(FastCrud, {
|
app.use(FastCrud, {
|
||||||
i18n: options.i18n,
|
i18n: options.i18n,
|
||||||
async dictRequest({ url }: any) {
|
async dictRequest({ url }: any) {
|
||||||
@@ -39,20 +71,21 @@ function install(app: App, options: any = {}) {
|
|||||||
mobile: {
|
mobile: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
props: {
|
props: {
|
||||||
isMobile: isMobile
|
isMobile: isMobile,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
table: {
|
table: {
|
||||||
scroll: {
|
scroll: {
|
||||||
x: 960
|
x: 960,
|
||||||
},
|
},
|
||||||
size: "small",
|
size: "small",
|
||||||
pagination: false,
|
pagination: false,
|
||||||
onResizeColumn: (w: number | string, col: any) => {
|
onResizeColumn: (w: number, col: any) => {
|
||||||
if (crudBinding.value?.table?.columnsMap && crudBinding.value?.table?.columnsMap[col.key]) {
|
if (crudBinding.value?.table?.columnsMap && crudBinding.value?.table?.columnsMap[col.key]) {
|
||||||
crudBinding.value.table.columnsMap[col.key].width = w;
|
crudBinding.value.table.columnsMap[col.key].width = w;
|
||||||
|
columnSizeSaver.save(col.key, w);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
conditionalRender: {
|
conditionalRender: {
|
||||||
@@ -70,13 +103,18 @@ function install(app: App, options: any = {}) {
|
|||||||
},
|
},
|
||||||
render() {
|
render() {
|
||||||
return "-";
|
return "-";
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
toolbar: {
|
toolbar: {
|
||||||
export: {
|
export: {
|
||||||
fileType: "excel"
|
fileType: "excel",
|
||||||
}
|
},
|
||||||
|
columnsFilter: {
|
||||||
|
async onReset() {
|
||||||
|
columnSizeSaver.clear();
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
rowHandle: {
|
rowHandle: {
|
||||||
fixed: "right",
|
fixed: "right",
|
||||||
@@ -84,13 +122,15 @@ function install(app: App, options: any = {}) {
|
|||||||
view: { type: "link", text: null, icon: "ion:eye-outline" },
|
view: { type: "link", text: null, icon: "ion:eye-outline" },
|
||||||
copy: { show: true, type: "link", text: null, icon: "ion:copy-outline" },
|
copy: { show: true, type: "link", text: null, icon: "ion:copy-outline" },
|
||||||
edit: { type: "link", text: null, icon: "ion:create-outline" },
|
edit: { type: "link", text: null, icon: "ion:create-outline" },
|
||||||
remove: { type: "link", style: { color: "red" }, text: null, icon: "ion:trash-outline" }
|
remove: { type: "link", style: { color: "red" }, text: null, icon: "ion:trash-outline" },
|
||||||
},
|
},
|
||||||
dropdown: {
|
dropdown: {
|
||||||
more: {
|
more: {
|
||||||
type: "link"
|
type: "link",
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
|
resizable: true,
|
||||||
|
width: 200,
|
||||||
},
|
},
|
||||||
request: {
|
request: {
|
||||||
transformQuery: ({ page, form, sort }: PageQuery): UserPageQuery => {
|
transformQuery: ({ page, form, sort }: PageQuery): UserPageQuery => {
|
||||||
@@ -103,10 +143,10 @@ function install(app: App, options: any = {}) {
|
|||||||
return {
|
return {
|
||||||
page: {
|
page: {
|
||||||
limit,
|
limit,
|
||||||
offset
|
offset,
|
||||||
},
|
},
|
||||||
query: form,
|
query: form,
|
||||||
sort
|
sort,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
transformRes: ({ res }: TransformResProps): PageRes => {
|
transformRes: ({ res }: TransformResProps): PageRes => {
|
||||||
@@ -116,16 +156,16 @@ function install(app: App, options: any = {}) {
|
|||||||
currentPage++;
|
currentPage++;
|
||||||
}
|
}
|
||||||
return { currentPage, pageSize, records: res.records, total: res.total, ...res };
|
return { currentPage, pageSize, records: res.records, total: res.total, ...res };
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
search: {
|
search: {
|
||||||
formItem: {
|
formItem: {
|
||||||
wrapperCol: {
|
wrapperCol: {
|
||||||
style: {
|
style: {
|
||||||
width: "50%"
|
width: "50%",
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
form: {
|
form: {
|
||||||
display: "flex",
|
display: "flex",
|
||||||
@@ -133,8 +173,8 @@ function install(app: App, options: any = {}) {
|
|||||||
//固定label宽度
|
//固定label宽度
|
||||||
span: null,
|
span: null,
|
||||||
style: {
|
style: {
|
||||||
width: "145px"
|
width: "145px",
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
async afterSubmit({ mode }) {
|
async afterSubmit({ mode }) {
|
||||||
if (mode === "add") {
|
if (mode === "add") {
|
||||||
@@ -144,13 +184,13 @@ function install(app: App, options: any = {}) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
wrapperCol: {
|
wrapperCol: {
|
||||||
span: null
|
span: null,
|
||||||
},
|
},
|
||||||
wrapper: {
|
wrapper: {
|
||||||
saveRemind: true
|
saveRemind: true,
|
||||||
// inner: true,
|
// inner: true,
|
||||||
// innerContainerSelector: "main.fs-framework-content"
|
// innerContainerSelector: "main.fs-framework-content"
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
columns: {
|
columns: {
|
||||||
//最后一列空白,用于自动伸缩列宽
|
//最后一列空白,用于自动伸缩列宽
|
||||||
@@ -158,23 +198,23 @@ function install(app: App, options: any = {}) {
|
|||||||
title: "",
|
title: "",
|
||||||
type: "text",
|
type: "text",
|
||||||
form: {
|
form: {
|
||||||
show: false
|
show: false,
|
||||||
},
|
},
|
||||||
column: {
|
column: {
|
||||||
order: 99999,
|
order: 99999,
|
||||||
width: -1,
|
width: -1,
|
||||||
columnSetShow: false,
|
columnSetShow: false,
|
||||||
resizable: false
|
resizable: false,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// 从 useCrud({permission}) 里获取permission参数,去设置各个按钮的权限
|
// 从 useCrud({permission}) 里获取permission参数,去设置各个按钮的权限
|
||||||
const permission = props.context?.permission || null;
|
const permission = props.context?.permission || null;
|
||||||
const crudPermission = useCrudPermission({ permission });
|
const crudPermission = useCrudPermission({ permission });
|
||||||
return crudPermission.merge(opts);
|
return crudPermission.merge(opts);
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// fast-extends里面的扩展组件均为异步组件,只有在使用时才会被加载,并不会影响首页加载速度
|
// fast-extends里面的扩展组件均为异步组件,只有在使用时才会被加载,并不会影响首页加载速度
|
||||||
@@ -202,19 +242,19 @@ function install(app: App, options: any = {}) {
|
|||||||
url: action,
|
url: action,
|
||||||
method: "post",
|
method: "post",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "multipart/form-data"
|
"Content-Type": "multipart/form-data",
|
||||||
},
|
},
|
||||||
timeout: 60000,
|
timeout: 60000,
|
||||||
data,
|
data,
|
||||||
onUploadProgress: (p: any) => {
|
onUploadProgress: (p: any) => {
|
||||||
onProgress({ percent: Math.round((p.loaded / p.total) * 100) });
|
onProgress({ percent: Math.round((p.loaded / p.total) * 100) });
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
successHandle(res: any) {
|
successHandle(res: any) {
|
||||||
return res;
|
return res;
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
//安装editor
|
//安装editor
|
||||||
@@ -222,10 +262,10 @@ function install(app: App, options: any = {}) {
|
|||||||
//编辑器的公共配置
|
//编辑器的公共配置
|
||||||
wangEditor: {
|
wangEditor: {
|
||||||
editorConfig: {
|
editorConfig: {
|
||||||
MENU_CONF: {}
|
MENU_CONF: {},
|
||||||
},
|
},
|
||||||
toolbarConfig: {}
|
toolbarConfig: {},
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
app.use(FsExtendsJson);
|
app.use(FsExtendsJson);
|
||||||
app.use(FsExtendsTime);
|
app.use(FsExtendsTime);
|
||||||
@@ -250,8 +290,8 @@ function install(app: App, options: any = {}) {
|
|||||||
column: { component: { name: "fs-date-format", format: "YYYY-MM-DD" } },
|
column: { component: { name: "fs-date-format", format: "YYYY-MM-DD" } },
|
||||||
valueBuilder(context: any) {
|
valueBuilder(context: any) {
|
||||||
console.log("time2,valueBuilder", context);
|
console.log("time2,valueBuilder", context);
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// 此处演示自定义字段合并插件
|
// 此处演示自定义字段合并插件
|
||||||
@@ -266,32 +306,14 @@ function install(app: App, options: any = {}) {
|
|||||||
// 合并column配置
|
// 合并column配置
|
||||||
merge(columnProps, {
|
merge(columnProps, {
|
||||||
form: { show: false },
|
form: { show: false },
|
||||||
viewForm: { show: true }
|
viewForm: { show: true },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return columnProps;
|
return columnProps;
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
//默认宽度,支持自动拖动调整列宽
|
//默认宽度,支持自动拖动调整列宽
|
||||||
registerMergeColumnPlugin({
|
|
||||||
name: "resize-column-plugin",
|
|
||||||
order: 2,
|
|
||||||
handle: (columnProps: ColumnCompositionProps) => {
|
|
||||||
if (!columnProps.column) {
|
|
||||||
columnProps.column = {};
|
|
||||||
}
|
|
||||||
if (columnProps.column.resizable == null) {
|
|
||||||
columnProps.column.resizable = true;
|
|
||||||
if (!columnProps.column.width) {
|
|
||||||
columnProps.column.width = 200;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return columnProps;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
registerMergeColumnPlugin({
|
registerMergeColumnPlugin({
|
||||||
name: "resize-column-plugin",
|
name: "resize-column-plugin",
|
||||||
order: 2,
|
order: 2,
|
||||||
@@ -300,16 +322,19 @@ function install(app: App, options: any = {}) {
|
|||||||
columnProps.column = {};
|
columnProps.column = {};
|
||||||
}
|
}
|
||||||
columnProps.column.resizable = true;
|
columnProps.column.resizable = true;
|
||||||
if (columnProps.column.width == null) {
|
const savedColumnWidth = columnSizeSaver.get(columnProps.key as string);
|
||||||
|
if (savedColumnWidth) {
|
||||||
|
columnProps.column.width = savedColumnWidth;
|
||||||
|
} else if (columnProps.column.width == null) {
|
||||||
columnProps.column.width = 200;
|
columnProps.column.width = 200;
|
||||||
} else if (typeof columnProps.column?.width === "string" && columnProps.column.width.indexOf("px") > -1) {
|
} else if (typeof columnProps.column?.width === "string" && columnProps.column.width.indexOf("px") > -1) {
|
||||||
columnProps.column.width = parseInt(columnProps.column.width.replace("px", ""));
|
columnProps.column.width = parseInt(columnProps.column.width.replace("px", ""));
|
||||||
}
|
}
|
||||||
return columnProps;
|
return columnProps;
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
install
|
install,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -67,13 +67,24 @@ export const certdResources = [
|
|||||||
title: "设置",
|
title: "设置",
|
||||||
name: "MineSetting",
|
name: "MineSetting",
|
||||||
path: "/certd/setting",
|
path: "/certd/setting",
|
||||||
redirect: "/certd/cname/record",
|
redirect: "/certd/access",
|
||||||
meta: {
|
meta: {
|
||||||
icon: "ion:settings-outline",
|
icon: "ion:settings-outline",
|
||||||
auth: true,
|
auth: true,
|
||||||
cache: true
|
cache: true
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
|
{
|
||||||
|
title: "授权管理",
|
||||||
|
name: "AccessManager",
|
||||||
|
path: "/certd/access",
|
||||||
|
component: "/certd/access/index.vue",
|
||||||
|
meta: {
|
||||||
|
icon: "ion:disc-outline",
|
||||||
|
auth: true,
|
||||||
|
cache: true
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: "CNAME记录管理",
|
title: "CNAME记录管理",
|
||||||
name: "CnameRecord",
|
name: "CnameRecord",
|
||||||
@@ -94,17 +105,7 @@ export const certdResources = [
|
|||||||
auth: true
|
auth: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
title: "授权管理",
|
|
||||||
name: "AccessManager",
|
|
||||||
path: "/certd/access",
|
|
||||||
component: "/certd/access/index.vue",
|
|
||||||
meta: {
|
|
||||||
icon: "ion:disc-outline",
|
|
||||||
auth: true,
|
|
||||||
cache: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
title: "OpenKey",
|
title: "OpenKey",
|
||||||
name: "OpenKey",
|
name: "OpenKey",
|
||||||
|
|||||||
@@ -1,11 +1,8 @@
|
|||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
import { Modal, notification } from "ant-design-vue";
|
import { Modal, notification } from "ant-design-vue";
|
||||||
import * as _ from "lodash-es";
|
import * as _ from "lodash-es";
|
||||||
// @ts-ignore
|
|
||||||
import { LocalStorage } from "/src/utils/util.storage";
|
|
||||||
|
|
||||||
import * as basicApi from "/@/api/modules/api.basic";
|
import * as basicApi from "/@/api/modules/api.basic";
|
||||||
import { HeaderMenus, PlusInfo, SiteEnv, SiteInfo, SuiteSetting, SysInstallInfo, SysPublicSetting } from "/@/api/modules/api.basic";
|
import { AppInfo, HeaderMenus, PlusInfo, SiteEnv, SiteInfo, SuiteSetting, SysInstallInfo, SysPublicSetting } from "/@/api/modules/api.basic";
|
||||||
import { useUserStore } from "/@/store/modules/user";
|
import { useUserStore } from "/@/store/modules/user";
|
||||||
import { mitter } from "/@/utils/util.mitt";
|
import { mitter } from "/@/utils/util.mitt";
|
||||||
import { env } from "/@/utils/util.env";
|
import { env } from "/@/utils/util.env";
|
||||||
@@ -29,6 +26,11 @@ export interface SettingState {
|
|||||||
headerMenus?: HeaderMenus;
|
headerMenus?: HeaderMenus;
|
||||||
inited?: boolean;
|
inited?: boolean;
|
||||||
suiteSetting?: SuiteSetting;
|
suiteSetting?: SuiteSetting;
|
||||||
|
app: {
|
||||||
|
version?: string;
|
||||||
|
time?: number;
|
||||||
|
deltaTime?: number;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultSiteInfo: SiteInfo = {
|
const defaultSiteInfo: SiteInfo = {
|
||||||
@@ -37,7 +39,7 @@ const defaultSiteInfo: SiteInfo = {
|
|||||||
logo: env.LOGO || "/static/images/logo/logo.svg",
|
logo: env.LOGO || "/static/images/logo/logo.svg",
|
||||||
loginLogo: env.LOGIN_LOGO || "/static/images/logo/rect-block.svg",
|
loginLogo: env.LOGIN_LOGO || "/static/images/logo/rect-block.svg",
|
||||||
licenseTo: "",
|
licenseTo: "",
|
||||||
licenseToUrl: ""
|
licenseToUrl: "",
|
||||||
};
|
};
|
||||||
export const useSettingStore = defineStore({
|
export const useSettingStore = defineStore({
|
||||||
id: "app.setting",
|
id: "app.setting",
|
||||||
@@ -45,33 +47,38 @@ export const useSettingStore = defineStore({
|
|||||||
plusInfo: {
|
plusInfo: {
|
||||||
isPlus: false,
|
isPlus: false,
|
||||||
vipType: "free",
|
vipType: "free",
|
||||||
isComm: false
|
isComm: false,
|
||||||
},
|
},
|
||||||
sysPublic: {
|
sysPublic: {
|
||||||
registerEnabled: false,
|
registerEnabled: false,
|
||||||
managerOtherUserPipeline: false,
|
managerOtherUserPipeline: false,
|
||||||
icpNo: env.ICP_NO || ""
|
icpNo: env.ICP_NO || "",
|
||||||
},
|
},
|
||||||
installInfo: {
|
installInfo: {
|
||||||
siteId: "",
|
siteId: "",
|
||||||
bindUserId: null,
|
bindUserId: null,
|
||||||
bindUrl: "",
|
bindUrl: "",
|
||||||
accountServerBaseUrl: "",
|
accountServerBaseUrl: "",
|
||||||
appKey: ""
|
appKey: "",
|
||||||
},
|
},
|
||||||
siteInfo: defaultSiteInfo,
|
siteInfo: defaultSiteInfo,
|
||||||
siteEnv: {
|
siteEnv: {
|
||||||
agent: {
|
agent: {
|
||||||
enabled: undefined,
|
enabled: undefined,
|
||||||
contactText: "",
|
contactText: "",
|
||||||
contactLink: ""
|
contactLink: "",
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
headerMenus: {
|
headerMenus: {
|
||||||
menus: []
|
menus: [],
|
||||||
},
|
},
|
||||||
suiteSetting: { enabled: false },
|
suiteSetting: { enabled: false },
|
||||||
inited: false
|
inited: false,
|
||||||
|
app: {
|
||||||
|
version: "",
|
||||||
|
time: 0,
|
||||||
|
deltaTime: 0,
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
getters: {
|
getters: {
|
||||||
getSysPublic(): SysPublicSetting {
|
getSysPublic(): SysPublicSetting {
|
||||||
@@ -96,7 +103,7 @@ export const useSettingStore = defineStore({
|
|||||||
const vipLabelMap: any = {
|
const vipLabelMap: any = {
|
||||||
free: "基础版",
|
free: "基础版",
|
||||||
plus: "专业版",
|
plus: "专业版",
|
||||||
comm: "商业版"
|
comm: "商业版",
|
||||||
};
|
};
|
||||||
return vipLabelMap[this.plusInfo?.vipType || "free"];
|
return vipLabelMap[this.plusInfo?.vipType || "free"];
|
||||||
},
|
},
|
||||||
@@ -113,21 +120,21 @@ export const useSettingStore = defineStore({
|
|||||||
title: menu.title,
|
title: menu.title,
|
||||||
icon: menu.icon,
|
icon: menu.icon,
|
||||||
link: menu.path,
|
link: menu.path,
|
||||||
order: 99999
|
order: 99999,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
isSuiteEnabled(): boolean {
|
isSuiteEnabled(): boolean {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
return this.suiteSetting?.enabled === true;
|
return this.suiteSetting?.enabled === true;
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
checkPlus() {
|
checkPlus() {
|
||||||
if (!this.isPlus) {
|
if (!this.isPlus) {
|
||||||
notification.warn({
|
notification.warn({
|
||||||
message: "此为专业版功能,请先升级到专业版"
|
message: "此为专业版功能,请先升级到专业版",
|
||||||
});
|
});
|
||||||
throw new Error("此为专业版功能,请升级到专业版");
|
throw new Error("此为专业版功能,请升级到专业版");
|
||||||
}
|
}
|
||||||
@@ -142,6 +149,12 @@ export const useSettingStore = defineStore({
|
|||||||
_.merge(this.suiteSetting, allSettings.suiteSetting || {});
|
_.merge(this.suiteSetting, allSettings.suiteSetting || {});
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
this.initSiteInfo(allSettings.siteInfo || {});
|
this.initSiteInfo(allSettings.siteInfo || {});
|
||||||
|
this.initAppInfo(allSettings.app || {});
|
||||||
|
},
|
||||||
|
initAppInfo(appInfo: AppInfo) {
|
||||||
|
this.app.time = appInfo.time;
|
||||||
|
this.app.version = appInfo.version;
|
||||||
|
this.app.deltaTime = new Date().getTime() - this.app.time;
|
||||||
},
|
},
|
||||||
initSiteInfo(siteInfo: SiteInfo) {
|
initSiteInfo(siteInfo: SiteInfo) {
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
@@ -158,15 +171,15 @@ export const useSettingStore = defineStore({
|
|||||||
if (this.siteInfo.logo) {
|
if (this.siteInfo.logo) {
|
||||||
updatePreferences({
|
updatePreferences({
|
||||||
logo: {
|
logo: {
|
||||||
source: this.siteInfo.logo
|
source: this.siteInfo.logo,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (this.siteInfo.title) {
|
if (this.siteInfo.title) {
|
||||||
updatePreferences({
|
updatePreferences({
|
||||||
app: {
|
app: {
|
||||||
name: this.siteInfo.title
|
name: this.siteInfo.title,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
useTitle(this.siteInfo.title);
|
useTitle(this.siteInfo.title);
|
||||||
}
|
}
|
||||||
@@ -210,7 +223,7 @@ export const useSettingStore = defineStore({
|
|||||||
cancelText: "不是,回到原来的地址",
|
cancelText: "不是,回到原来的地址",
|
||||||
onCancel: () => {
|
onCancel: () => {
|
||||||
window.location.href = bindUrl;
|
window.location.href = bindUrl;
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -224,8 +237,8 @@ export const useSettingStore = defineStore({
|
|||||||
}
|
}
|
||||||
await this.init();
|
await this.init();
|
||||||
this.inited = true;
|
this.inited = true;
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
mitter.on("app.login", async () => {
|
mitter.on("app.login", async () => {
|
||||||
|
|||||||
@@ -88,4 +88,9 @@ body a{
|
|||||||
&:hover{
|
&:hover{
|
||||||
color: #40a9ff;
|
color: #40a9ff;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
span.fs-icon-svg{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
@@ -4,6 +4,10 @@ export function createAccessApi(from = "user") {
|
|||||||
const apiPrefix = from === "sys" ? "/sys/access" : "/pi/access";
|
const apiPrefix = from === "sys" ? "/sys/access" : "/pi/access";
|
||||||
return {
|
return {
|
||||||
async GetList(query: any) {
|
async GetList(query: any) {
|
||||||
|
if (query?.query) {
|
||||||
|
delete query.query.access;
|
||||||
|
}
|
||||||
|
|
||||||
return await request({
|
return await request({
|
||||||
url: apiPrefix + "/page",
|
url: apiPrefix + "/page",
|
||||||
method: "post",
|
method: "post",
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ export function getCommonColumnDefine(crudExpose: any, typeRef: any, api: any) {
|
|||||||
type: "dict-select",
|
type: "dict-select",
|
||||||
dict: AccessTypeDictRef,
|
dict: AccessTypeDictRef,
|
||||||
search: {
|
search: {
|
||||||
show: false
|
show: true
|
||||||
},
|
},
|
||||||
column: {
|
column: {
|
||||||
width: 200,
|
width: 200,
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ export const certInfoApi = {
|
|||||||
return await request({
|
return await request({
|
||||||
url: apiPrefix + "/page",
|
url: apiPrefix + "/page",
|
||||||
method: "post",
|
method: "post",
|
||||||
data: query
|
data: query,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -15,7 +15,7 @@ export const certInfoApi = {
|
|||||||
return await request({
|
return await request({
|
||||||
url: apiPrefix + "/add",
|
url: apiPrefix + "/add",
|
||||||
method: "post",
|
method: "post",
|
||||||
data: obj
|
data: obj,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@ export const certInfoApi = {
|
|||||||
return await request({
|
return await request({
|
||||||
url: apiPrefix + "/update",
|
url: apiPrefix + "/update",
|
||||||
method: "post",
|
method: "post",
|
||||||
data: obj
|
data: obj,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@ export const certInfoApi = {
|
|||||||
return await request({
|
return await request({
|
||||||
url: apiPrefix + "/delete",
|
url: apiPrefix + "/delete",
|
||||||
method: "post",
|
method: "post",
|
||||||
params: { id }
|
params: { id },
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -39,27 +39,35 @@ export const certInfoApi = {
|
|||||||
return await request({
|
return await request({
|
||||||
url: apiPrefix + "/info",
|
url: apiPrefix + "/info",
|
||||||
method: "post",
|
method: "post",
|
||||||
params: { id }
|
params: { id },
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
async ListAll() {
|
async ListAll() {
|
||||||
return await request({
|
return await request({
|
||||||
url: apiPrefix + "/all",
|
url: apiPrefix + "/all",
|
||||||
method: "post"
|
method: "post",
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
async Upload(body: { id?: number; cert: { crt: string; key: string } }) {
|
async Upload(body: { id?: number; cert: { crt: string; key: string } }) {
|
||||||
return await request({
|
return await request({
|
||||||
url: apiPrefix + "/upload",
|
url: apiPrefix + "/upload",
|
||||||
method: "post",
|
method: "post",
|
||||||
data: body
|
data: body,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
async GetCert(id: number): Promise<CertInfo> {
|
async GetCert(id: number): Promise<CertInfo> {
|
||||||
return await request({
|
return await request({
|
||||||
url: apiPrefix + "/getCert",
|
url: apiPrefix + "/getCert",
|
||||||
method: "post",
|
method: "post",
|
||||||
params: { id: id }
|
params: { id: id },
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
|
|
||||||
|
async GetOptionsByIds(ids: number[]): Promise<any[]> {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/getOptionsByIds",
|
||||||
|
method: "post",
|
||||||
|
data: { ids },
|
||||||
|
});
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,17 +1,15 @@
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, EditReq, useFormWrapper, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
|
import { AddReq, compute, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, useFormWrapper, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
|
||||||
import { certInfoApi } from "./api";
|
import { certInfoApi } from "./api";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import { useUserStore } from "/@/store/modules/user";
|
|
||||||
import { useRouter } from "vue-router";
|
import { useRouter } from "vue-router";
|
||||||
import { useModal } from "/@/use/use-modal";
|
import { useModal } from "/@/use/use-modal";
|
||||||
import * as api from "/@/views/certd/pipeline/api";
|
|
||||||
import { notification } from "ant-design-vue";
|
import { notification } from "ant-design-vue";
|
||||||
import CertView from "/@/views/certd/pipeline/cert-view.vue";
|
import CertView from "/@/views/certd/pipeline/cert-view.vue";
|
||||||
|
import { useCertUpload } from "/@/views/certd/pipeline/cert-upload/use";
|
||||||
|
|
||||||
export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
|
export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
|
||||||
const { t } = useI18n();
|
|
||||||
const api = certInfoApi;
|
const api = certInfoApi;
|
||||||
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
|
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
|
||||||
return await api.GetList(query);
|
return await api.GetList(query);
|
||||||
@@ -50,32 +48,33 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||||||
width: 800,
|
width: 800,
|
||||||
content: () => {
|
content: () => {
|
||||||
return <CertView cert={cert}></CertView>;
|
return <CertView cert={cert}></CertView>;
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const { openUploadCreateDialog, openUpdateCertDialog } = useCertUpload();
|
||||||
return {
|
return {
|
||||||
crudOptions: {
|
crudOptions: {
|
||||||
request: {
|
request: {
|
||||||
pageRequest,
|
pageRequest,
|
||||||
addRequest,
|
addRequest,
|
||||||
editRequest,
|
editRequest,
|
||||||
delRequest
|
delRequest,
|
||||||
},
|
},
|
||||||
form: {
|
form: {
|
||||||
labelCol: {
|
labelCol: {
|
||||||
//固定label宽度
|
//固定label宽度
|
||||||
span: null,
|
span: null,
|
||||||
style: {
|
style: {
|
||||||
width: "100px"
|
width: "100px",
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
col: {
|
col: {
|
||||||
span: 22
|
span: 22,
|
||||||
},
|
},
|
||||||
wrapper: {
|
wrapper: {
|
||||||
width: 600
|
width: 600,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
actionbar: {
|
actionbar: {
|
||||||
show: true,
|
show: true,
|
||||||
@@ -85,62 +84,17 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||||||
type: "primary",
|
type: "primary",
|
||||||
show: false,
|
show: false,
|
||||||
async click() {
|
async click() {
|
||||||
function createCrudOptions() {
|
await openUploadCreateDialog();
|
||||||
return {
|
},
|
||||||
crudOptions: {
|
},
|
||||||
request: {
|
},
|
||||||
addRequest: async (form: any) => {
|
},
|
||||||
return await api.Upload(form);
|
tabs: {
|
||||||
},
|
name: "fromType",
|
||||||
editRequest: async (form: any) => {
|
show: true,
|
||||||
return await api.Upload(form);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
columns: {
|
|
||||||
id: {
|
|
||||||
title: "ID",
|
|
||||||
type: "number",
|
|
||||||
form: {
|
|
||||||
show: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"cert.crt": {
|
|
||||||
title: "证书",
|
|
||||||
type: "textarea",
|
|
||||||
form: {
|
|
||||||
component: {
|
|
||||||
rows: 4
|
|
||||||
},
|
|
||||||
rules: [{ required: true, message: "此项必填" }]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"cert.key": {
|
|
||||||
title: "私钥",
|
|
||||||
type: "textarea",
|
|
||||||
form: {
|
|
||||||
component: {
|
|
||||||
rows: 4
|
|
||||||
},
|
|
||||||
rules: [{ required: true, message: "此项必填" }]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
form: {
|
|
||||||
wrapper: {
|
|
||||||
title: "上传自定义证书"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
const { crudOptions } = createCrudOptions();
|
|
||||||
const wrapperRef = await openCrudFormDialog({ crudOptions });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
rowHandle: {
|
rowHandle: {
|
||||||
width: 200,
|
width: 100,
|
||||||
fixed: "right",
|
fixed: "right",
|
||||||
buttons: {
|
buttons: {
|
||||||
view: { show: false },
|
view: { show: false },
|
||||||
@@ -151,12 +105,28 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||||||
icon: "ph:certificate",
|
icon: "ph:certificate",
|
||||||
async click({ row }) {
|
async click({ row }) {
|
||||||
await viewCert(row);
|
await viewCert(row);
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
copy: { show: false },
|
copy: { show: false },
|
||||||
edit: { show: false },
|
edit: { show: false },
|
||||||
remove: { show: false }
|
remove: {
|
||||||
}
|
order: 10,
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
download: {
|
||||||
|
order: 9,
|
||||||
|
title: "下载证书",
|
||||||
|
type: "link",
|
||||||
|
icon: "ant-design:download-outlined",
|
||||||
|
async click({ row }) {
|
||||||
|
if (!row.certFile) {
|
||||||
|
notification.error({ message: "证书还未生成,请先运行流水线" });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
window.open("/api/monitor/cert/download?id=" + row.id);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
columns: {
|
columns: {
|
||||||
id: {
|
id: {
|
||||||
@@ -164,77 +134,91 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||||||
key: "id",
|
key: "id",
|
||||||
type: "number",
|
type: "number",
|
||||||
search: {
|
search: {
|
||||||
show: false
|
show: false,
|
||||||
},
|
},
|
||||||
column: {
|
column: {
|
||||||
width: 100,
|
width: 100,
|
||||||
editable: {
|
editable: {
|
||||||
disabled: true
|
disabled: true,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
form: {
|
form: {
|
||||||
show: false
|
show: false,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
// domain: {
|
fromType: {
|
||||||
// title: "主域名",
|
title: "来源",
|
||||||
// search: {
|
|
||||||
// show: true
|
|
||||||
// },
|
|
||||||
// type: "text",
|
|
||||||
// form: {
|
|
||||||
// show: false
|
|
||||||
// },
|
|
||||||
// column: {
|
|
||||||
// width: 180,
|
|
||||||
// sorter: true,
|
|
||||||
// component: {
|
|
||||||
// name: "fs-values-format"
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
domains: {
|
|
||||||
title: "全部域名",
|
|
||||||
search: {
|
search: {
|
||||||
show: true
|
show: true,
|
||||||
|
},
|
||||||
|
type: "dict-select",
|
||||||
|
dict: dict({
|
||||||
|
data: [
|
||||||
|
{ label: "流水线", value: "pipeline" },
|
||||||
|
{ label: "手动上传", value: "upload" },
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
form: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
width: 100,
|
||||||
|
sorter: true,
|
||||||
|
component: {
|
||||||
|
color: "auto",
|
||||||
|
},
|
||||||
|
conditionalRender: false,
|
||||||
|
},
|
||||||
|
valueBuilder({ value, row, key }) {
|
||||||
|
if (!value) {
|
||||||
|
row[key] = "pipeline";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
domains: {
|
||||||
|
title: "域名",
|
||||||
|
search: {
|
||||||
|
show: true,
|
||||||
},
|
},
|
||||||
type: "text",
|
type: "text",
|
||||||
form: {
|
form: {
|
||||||
rules: [{ required: true, message: "请输入域名" }]
|
rules: [{ required: true, message: "请输入域名" }],
|
||||||
},
|
},
|
||||||
column: {
|
column: {
|
||||||
width: 450,
|
width: 450,
|
||||||
sorter: true,
|
sorter: true,
|
||||||
component: {
|
component: {
|
||||||
name: "fs-values-format",
|
name: "fs-values-format",
|
||||||
color: "auto"
|
color: "auto",
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
domainCount: {
|
domainCount: {
|
||||||
title: "域名数量",
|
title: "域名数量",
|
||||||
type: "number",
|
type: "number",
|
||||||
form: {
|
form: {
|
||||||
show: false
|
show: false,
|
||||||
},
|
},
|
||||||
column: {
|
column: {
|
||||||
width: 120,
|
width: 120,
|
||||||
sorter: true,
|
sorter: true,
|
||||||
show: false
|
show: false,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
expiresTime: {
|
expiresLeft: {
|
||||||
title: "过期时间",
|
title: "有效天数",
|
||||||
search: {
|
search: {
|
||||||
show: false
|
show: false,
|
||||||
},
|
},
|
||||||
type: "date",
|
type: "date",
|
||||||
form: {
|
form: {
|
||||||
show: false
|
show: false,
|
||||||
},
|
},
|
||||||
column: {
|
column: {
|
||||||
sorter: true,
|
sorter: true,
|
||||||
cellRender({ value }) {
|
conditionalRender: false,
|
||||||
|
cellRender({ row }) {
|
||||||
|
const value = row.expiresTime;
|
||||||
if (!value) {
|
if (!value) {
|
||||||
return "-";
|
return "-";
|
||||||
}
|
}
|
||||||
@@ -243,41 +227,54 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||||||
const color = leftDays < 20 ? "red" : "#389e0d";
|
const color = leftDays < 20 ? "red" : "#389e0d";
|
||||||
const percent = (leftDays / 90) * 100;
|
const percent = (leftDays / 90) * 100;
|
||||||
return <a-progress title={expireDate + "过期"} percent={percent} strokeColor={color} format={(percent: number) => `${leftDays}天`} />;
|
return <a-progress title={expireDate + "过期"} percent={percent} strokeColor={color} format={(percent: number) => `${leftDays}天`} />;
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
|
},
|
||||||
|
expiresTime: {
|
||||||
|
title: "过期时间",
|
||||||
|
search: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
type: "datetime",
|
||||||
|
form: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
sorter: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
certProvider: {
|
certProvider: {
|
||||||
title: "证书颁发机构",
|
title: "证书颁发机构",
|
||||||
search: {
|
search: {
|
||||||
show: false
|
show: false,
|
||||||
},
|
},
|
||||||
type: "text",
|
type: "text",
|
||||||
form: {
|
form: {
|
||||||
show: false
|
show: false,
|
||||||
},
|
},
|
||||||
column: {
|
column: {
|
||||||
width: 200
|
width: 200,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
applyTime: {
|
applyTime: {
|
||||||
title: "申请时间",
|
title: "申请时间",
|
||||||
search: {
|
search: {
|
||||||
show: false
|
show: false,
|
||||||
},
|
},
|
||||||
type: "datetime",
|
type: "datetime",
|
||||||
form: {
|
form: {
|
||||||
show: false
|
show: false,
|
||||||
},
|
},
|
||||||
column: {
|
column: {
|
||||||
sorter: true
|
sorter: true,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
"pipeline.title": {
|
"pipeline.title": {
|
||||||
title: "关联流水线",
|
title: "关联流水线",
|
||||||
search: { show: false },
|
search: { show: false },
|
||||||
type: "link",
|
type: "link",
|
||||||
form: {
|
form: {
|
||||||
show: false
|
show: false,
|
||||||
},
|
},
|
||||||
column: {
|
column: {
|
||||||
width: 350,
|
width: 350,
|
||||||
@@ -286,12 +283,12 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||||||
on: {
|
on: {
|
||||||
onClick({ row }) {
|
onClick({ row }) {
|
||||||
router.push({ path: "/certd/pipeline/detail", query: { id: row.pipelineId, editMode: "false" } });
|
router.push({ path: "/certd/pipeline/detail", query: { id: row.pipelineId, editMode: "false" } });
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<template #header>
|
<template #header>
|
||||||
<div class="title">
|
<div class="title">
|
||||||
证书仓库
|
证书仓库
|
||||||
<span class="sub">从流水线生成的证书,后续将支持手动上传证书并部署</span>
|
<span class="sub">从流水线生成的证书</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<fs-crud ref="crudRef" v-bind="crudBinding"> </fs-crud>
|
<fs-crud ref="crudRef" v-bind="crudBinding"> </fs-crud>
|
||||||
@@ -11,12 +11,12 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { defineComponent, onActivated, onMounted } from "vue";
|
import { onActivated, onMounted } from "vue";
|
||||||
import { useFs } from "@fast-crud/fast-crud";
|
import { useFs } from "@fast-crud/fast-crud";
|
||||||
import createCrudOptions from "./crud";
|
import createCrudOptions from "./crud";
|
||||||
import { createApi } from "./api";
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: "CertStore"
|
name: "CertStore",
|
||||||
});
|
});
|
||||||
const { crudBinding, crudRef, crudExpose } = useFs({ createCrudOptions, context: {} });
|
const { crudBinding, crudRef, crudExpose } = useFs({ createCrudOptions, context: {} });
|
||||||
|
|
||||||
|
|||||||
@@ -34,28 +34,35 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||||||
|
|
||||||
const settingsStore = useSettingStore();
|
const settingsStore = useSettingStore();
|
||||||
|
|
||||||
|
const checkStatusDict = dict({
|
||||||
|
data: [
|
||||||
|
{ label: "成功", value: "ok", color: "green" },
|
||||||
|
{ label: "检查中", value: "checking", color: "blue" },
|
||||||
|
{ label: "异常", value: "error", color: "red" },
|
||||||
|
],
|
||||||
|
});
|
||||||
return {
|
return {
|
||||||
crudOptions: {
|
crudOptions: {
|
||||||
request: {
|
request: {
|
||||||
pageRequest,
|
pageRequest,
|
||||||
addRequest,
|
addRequest,
|
||||||
editRequest,
|
editRequest,
|
||||||
delRequest
|
delRequest,
|
||||||
},
|
},
|
||||||
form: {
|
form: {
|
||||||
labelCol: {
|
labelCol: {
|
||||||
//固定label宽度
|
//固定label宽度
|
||||||
span: null,
|
span: null,
|
||||||
style: {
|
style: {
|
||||||
width: "100px"
|
width: "100px",
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
col: {
|
col: {
|
||||||
span: 22
|
span: 22,
|
||||||
},
|
},
|
||||||
wrapper: {
|
wrapper: {
|
||||||
width: 600
|
width: 600,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
actionbar: {
|
actionbar: {
|
||||||
buttons: {
|
buttons: {
|
||||||
@@ -65,7 +72,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||||||
//非plus
|
//非plus
|
||||||
if (crudBinding.value.data.length >= 1) {
|
if (crudBinding.value.data.length >= 1) {
|
||||||
notification.error({
|
notification.error({
|
||||||
message: "基础版只能添加一个监控站点,请赞助升级专业版"
|
message: "基础版只能添加一个监控站点,请赞助升级专业版",
|
||||||
});
|
});
|
||||||
mitter.emit("openVipModal");
|
mitter.emit("openVipModal");
|
||||||
return;
|
return;
|
||||||
@@ -79,15 +86,15 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||||||
const max = suiteDetail.monitorCount.max;
|
const max = suiteDetail.monitorCount.max;
|
||||||
if (max != -1 && max <= suiteDetail.monitorCount.used) {
|
if (max != -1 && max <= suiteDetail.monitorCount.used) {
|
||||||
notification.error({
|
notification.error({
|
||||||
message: `对不起,您最多只能创建条${max}监控记录,请购买或升级套餐`
|
message: `对不起,您最多只能创建条${max}监控记录,请购买或升级套餐`,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await crudExpose.openAdd({});
|
await crudExpose.openAdd({});
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
rowHandle: {
|
rowHandle: {
|
||||||
fixed: "right",
|
fixed: "right",
|
||||||
@@ -98,18 +105,18 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||||||
type: "link",
|
type: "link",
|
||||||
text: null,
|
text: null,
|
||||||
tooltip: {
|
tooltip: {
|
||||||
title: "立即检查"
|
title: "立即检查",
|
||||||
},
|
},
|
||||||
icon: "ion:play-sharp",
|
icon: "ion:play-sharp",
|
||||||
click: async ({ row }) => {
|
click: async ({ row }) => {
|
||||||
await api.DoCheck(row.id);
|
await api.DoCheck(row.id);
|
||||||
await crudExpose.doRefresh();
|
await crudExpose.doRefresh();
|
||||||
notification.success({
|
notification.success({
|
||||||
message: "检查完成"
|
message: "检查完成",
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
columns: {
|
columns: {
|
||||||
id: {
|
id: {
|
||||||
@@ -117,77 +124,67 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||||||
key: "id",
|
key: "id",
|
||||||
type: "number",
|
type: "number",
|
||||||
search: {
|
search: {
|
||||||
show: false
|
show: false,
|
||||||
},
|
},
|
||||||
column: {
|
column: {
|
||||||
width: 80,
|
width: 80,
|
||||||
align: "center"
|
align: "center",
|
||||||
},
|
},
|
||||||
form: {
|
form: {
|
||||||
show: false
|
show: false,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
name: {
|
name: {
|
||||||
title: "站点名称",
|
title: "站点名称",
|
||||||
search: {
|
search: {
|
||||||
show: true
|
show: true,
|
||||||
},
|
},
|
||||||
type: "text",
|
type: "text",
|
||||||
form: {
|
form: {
|
||||||
rules: [{ required: true, message: "请输入站点名称" }]
|
rules: [{ required: true, message: "请输入站点名称" }],
|
||||||
},
|
},
|
||||||
column: {
|
column: {
|
||||||
width: 160
|
width: 160,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
domain: {
|
domain: {
|
||||||
title: "网站域名",
|
title: "网站域名",
|
||||||
search: {
|
search: {
|
||||||
show: true
|
show: true,
|
||||||
},
|
},
|
||||||
type: "text",
|
type: "text",
|
||||||
form: {
|
form: {
|
||||||
rules: [
|
rules: [
|
||||||
{ required: true, message: "请输入域名" },
|
{ required: true, message: "请输入域名" },
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
{ type: "domains", message: "请输入正确的域名" }
|
{ type: "domains", message: "请输入正确的域名" },
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
column: {
|
column: {
|
||||||
width: 200,
|
width: 230,
|
||||||
sorter: true,
|
sorter: true,
|
||||||
cellRender({ value }) {
|
cellRender({ value, row }) {
|
||||||
|
const url = `https://${value}:${row.httpsPort}`;
|
||||||
return (
|
return (
|
||||||
<a-tooltip title={value} placement="left">
|
<a-tooltip title={value} placement="left">
|
||||||
<fs-copyable modelValue={value}></fs-copyable>
|
<fs-copyable modelValue={value}>
|
||||||
|
<a target="_blank" href={url}>
|
||||||
|
{value}:{row.httpsPort}
|
||||||
|
</a>
|
||||||
|
</fs-copyable>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
}
|
|
||||||
},
|
|
||||||
httpsPort: {
|
|
||||||
title: "HTTPS端口",
|
|
||||||
search: {
|
|
||||||
show: false
|
|
||||||
},
|
},
|
||||||
type: "number",
|
|
||||||
form: {
|
|
||||||
value: 443,
|
|
||||||
rules: [{ required: true, message: "请输入端口" }]
|
|
||||||
},
|
|
||||||
column: {
|
|
||||||
align: "center",
|
|
||||||
width: 100
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
certDomains: {
|
certDomains: {
|
||||||
title: "证书域名",
|
title: "证书域名",
|
||||||
search: {
|
search: {
|
||||||
show: false
|
show: true,
|
||||||
},
|
},
|
||||||
type: "text",
|
type: "text",
|
||||||
form: {
|
form: {
|
||||||
show: false
|
show: false,
|
||||||
},
|
},
|
||||||
column: {
|
column: {
|
||||||
width: 200,
|
width: 200,
|
||||||
@@ -199,55 +196,56 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||||||
{value}
|
{value}
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
certProvider: {
|
certProvider: {
|
||||||
title: "证书颁发者",
|
title: "颁发机构",
|
||||||
search: {
|
search: {
|
||||||
show: false
|
show: false,
|
||||||
},
|
},
|
||||||
type: "text",
|
type: "text",
|
||||||
form: {
|
form: {
|
||||||
show: false
|
show: false,
|
||||||
},
|
},
|
||||||
column: {
|
column: {
|
||||||
width: 200,
|
width: 200,
|
||||||
sorter: true,
|
sorter: true,
|
||||||
cellRender({ value }) {
|
cellRender({ value }) {
|
||||||
return <a-tooltip title={value}>{value}</a-tooltip>;
|
return <a-tooltip title={value}>{value}</a-tooltip>;
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
certStatus: {
|
certStatus: {
|
||||||
title: "证书状态",
|
title: "证书状态",
|
||||||
search: {
|
search: {
|
||||||
show: true
|
show: true,
|
||||||
},
|
},
|
||||||
type: "dict-select",
|
type: "dict-select",
|
||||||
dict: dict({
|
dict: dict({
|
||||||
data: [
|
data: [
|
||||||
{ label: "正常", value: "ok", color: "green" },
|
{ label: "正常", value: "ok", color: "green" },
|
||||||
{ label: "过期", value: "expired", color: "red" }
|
{ label: "过期", value: "expired", color: "red" },
|
||||||
]
|
],
|
||||||
}),
|
}),
|
||||||
form: {
|
form: {
|
||||||
show: false
|
show: false,
|
||||||
},
|
},
|
||||||
column: {
|
column: {
|
||||||
width: 100,
|
width: 100,
|
||||||
sorter: true,
|
sorter: true,
|
||||||
show: false
|
show: true,
|
||||||
}
|
align: "center",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
certExpiresTime: {
|
certExpiresTime: {
|
||||||
title: "证书到期时间",
|
title: "证书到期时间",
|
||||||
search: {
|
search: {
|
||||||
show: false
|
show: false,
|
||||||
},
|
},
|
||||||
type: "date",
|
type: "date",
|
||||||
form: {
|
form: {
|
||||||
show: false
|
show: false,
|
||||||
},
|
},
|
||||||
column: {
|
column: {
|
||||||
sorter: true,
|
sorter: true,
|
||||||
@@ -260,109 +258,111 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||||||
const color = leftDays < 20 ? "red" : "#389e0d";
|
const color = leftDays < 20 ? "red" : "#389e0d";
|
||||||
const percent = (leftDays / 90) * 100;
|
const percent = (leftDays / 90) * 100;
|
||||||
return <a-progress title={expireDate + "过期"} percent={percent} strokeColor={color} format={(percent: number) => `${leftDays}天`} />;
|
return <a-progress title={expireDate + "过期"} percent={percent} strokeColor={color} format={(percent: number) => `${leftDays}天`} />;
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
lastCheckTime: {
|
lastCheckTime: {
|
||||||
title: "上次检查时间",
|
title: "上次检查时间",
|
||||||
search: {
|
search: {
|
||||||
show: false
|
show: false,
|
||||||
},
|
},
|
||||||
type: "datetime",
|
type: "datetime",
|
||||||
form: {
|
form: {
|
||||||
show: false
|
show: false,
|
||||||
},
|
},
|
||||||
column: {
|
column: {
|
||||||
sorter: true,
|
sorter: true,
|
||||||
width: 155
|
width: 155,
|
||||||
}
|
|
||||||
},
|
|
||||||
checkStatus: {
|
|
||||||
title: "检查状态",
|
|
||||||
search: {
|
|
||||||
show: false
|
|
||||||
},
|
},
|
||||||
type: "dict-select",
|
|
||||||
dict: dict({
|
|
||||||
data: [
|
|
||||||
{ label: "正常", value: "ok", color: "green" },
|
|
||||||
{ label: "检查中", value: "checking", color: "blue" },
|
|
||||||
{ label: "异常", value: "error", color: "red" }
|
|
||||||
]
|
|
||||||
}),
|
|
||||||
form: {
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
column: {
|
|
||||||
width: 100,
|
|
||||||
align: "center",
|
|
||||||
sorter: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
error: {
|
|
||||||
title: "错误信息",
|
|
||||||
search: {
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
type: "text",
|
|
||||||
form: {
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
column: {
|
|
||||||
width: 200,
|
|
||||||
sorter: true,
|
|
||||||
cellRender({ value }) {
|
|
||||||
return <a-tooltip title={value}>{value}</a-tooltip>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
pipelineId: {
|
|
||||||
title: "关联流水线id",
|
|
||||||
search: {
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
form: { show: false },
|
|
||||||
type: "number",
|
|
||||||
column: {
|
|
||||||
width: 200,
|
|
||||||
sorter: true,
|
|
||||||
show: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
certInfoId: {
|
|
||||||
title: "证书id",
|
|
||||||
search: {
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
type: "number",
|
|
||||||
form: { show: false },
|
|
||||||
column: {
|
|
||||||
width: 100,
|
|
||||||
sorter: true,
|
|
||||||
show: false
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
disabled: {
|
disabled: {
|
||||||
title: "禁用启用",
|
title: "禁用启用",
|
||||||
search: {
|
search: {
|
||||||
show: false
|
show: false,
|
||||||
},
|
},
|
||||||
type: "dict-switch",
|
type: "dict-switch",
|
||||||
dict: dict({
|
dict: dict({
|
||||||
data: [
|
data: [
|
||||||
{ label: "启用", value: false, color: "green" },
|
{ label: "启用", value: false, color: "green" },
|
||||||
{ label: "禁用", value: true, color: "red" }
|
{ label: "禁用", value: true, color: "red" },
|
||||||
]
|
],
|
||||||
}),
|
}),
|
||||||
form: {
|
form: {
|
||||||
value: false
|
value: false,
|
||||||
},
|
},
|
||||||
column: {
|
column: {
|
||||||
width: 90,
|
width: 100,
|
||||||
sorter: true
|
sorter: true,
|
||||||
}
|
align: "center",
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
checkStatus: {
|
||||||
|
title: "检查状态",
|
||||||
|
search: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
type: "dict-select",
|
||||||
|
dict: checkStatusDict,
|
||||||
|
form: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
width: 100,
|
||||||
|
align: "center",
|
||||||
|
sorter: true,
|
||||||
|
cellRender({ value, row, key }) {
|
||||||
|
return (
|
||||||
|
<a-tooltip title={row.error}>
|
||||||
|
<fs-values-format v-model={value} dict={checkStatusDict}></fs-values-format>
|
||||||
|
</a-tooltip>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// error: {
|
||||||
|
// title: "错误信息",
|
||||||
|
// search: {
|
||||||
|
// show: false
|
||||||
|
// },
|
||||||
|
// type: "text",
|
||||||
|
// form: {
|
||||||
|
// show: false
|
||||||
|
// },
|
||||||
|
// column: {
|
||||||
|
// width: 200,
|
||||||
|
// sorter: true,
|
||||||
|
// cellRender({ value }) {
|
||||||
|
// return <a-tooltip title={value}>{value}</a-tooltip>;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
pipelineId: {
|
||||||
|
title: "关联流水线id",
|
||||||
|
search: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
form: { show: false },
|
||||||
|
type: "number",
|
||||||
|
column: {
|
||||||
|
width: 200,
|
||||||
|
sorter: true,
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
certInfoId: {
|
||||||
|
title: "证书id",
|
||||||
|
search: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
type: "number",
|
||||||
|
form: { show: false },
|
||||||
|
column: {
|
||||||
|
width: 100,
|
||||||
|
sorter: true,
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<div class="title flex items-center">
|
<div class="title flex items-center">
|
||||||
站点证书监控
|
站点证书监控
|
||||||
<div class="sub flex-1">
|
<div class="sub flex-1">
|
||||||
<div>每天0点,检查网站证书的过期时间,并发出提醒;</div>
|
<div>每天0点,检查网站证书的过期时间,到期前10天时将发出提醒(使用默认通知渠道);</div>
|
||||||
<div class="flex items-center">基础版限制1条,专业版以上无限制,当前<vip-button class="ml-5" mode="nav"></vip-button></div>
|
<div class="flex items-center">基础版限制1条,专业版以上无限制,当前<vip-button class="ml-5" mode="nav"></vip-button></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,16 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="notification-selector">
|
<div class="notification-selector">
|
||||||
<div class="flex-o w-100">
|
<div class="flex-o w-100">
|
||||||
<fs-dict-select
|
<fs-dict-select class="flex-1" :value="modelValue" :dict="optionsDictRef" :disabled="disabled" :render-label="renderLabel" :slots="selectSlots" :allow-clear="true" @update:value="onChange" />
|
||||||
class="flex-1"
|
|
||||||
:value="modelValue"
|
|
||||||
:dict="optionsDictRef"
|
|
||||||
:disabled="disabled"
|
|
||||||
:render-label="renderLabel"
|
|
||||||
:slots="selectSlots"
|
|
||||||
:allow-clear="true"
|
|
||||||
@update:value="onChange"
|
|
||||||
/>
|
|
||||||
<fs-table-select
|
<fs-table-select
|
||||||
ref="tableSelectRef"
|
ref="tableSelectRef"
|
||||||
class="flex-0"
|
class="flex-0"
|
||||||
@@ -21,9 +12,9 @@
|
|||||||
search: { show: false },
|
search: { show: false },
|
||||||
table: {
|
table: {
|
||||||
scroll: {
|
scroll: {
|
||||||
x: 540
|
x: 540,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}"
|
}"
|
||||||
:show-current="false"
|
:show-current="false"
|
||||||
:show-select="false"
|
:show-select="false"
|
||||||
@@ -50,7 +41,7 @@ import createCrudOptions from "../crud";
|
|||||||
import { notificationProvide } from "/@/views/certd/notification/common";
|
import { notificationProvide } from "/@/views/certd/notification/common";
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: "NotificationSelector"
|
name: "NotificationSelector",
|
||||||
});
|
});
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
@@ -89,12 +80,12 @@ const optionsDictRef = dict({
|
|||||||
{
|
{
|
||||||
id: 0,
|
id: 0,
|
||||||
name: "使用默认通知",
|
name: "使用默认通知",
|
||||||
icon: "ion:notifications"
|
icon: "ion:notifications",
|
||||||
},
|
},
|
||||||
...dict.data
|
...dict.data,
|
||||||
];
|
];
|
||||||
dict.setData(data);
|
dict.setData(data);
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
const renderLabel = (option: any) => {
|
const renderLabel = (option: any) => {
|
||||||
return <span>{option.name}</span>;
|
return <span>{option.name}</span>;
|
||||||
@@ -115,7 +106,7 @@ const selectSlots = ref({
|
|||||||
// res.push(<a-space style="padding: 4px 8px" />);
|
// res.push(<a-space style="padding: 4px 8px" />);
|
||||||
// res.push(<fs-button class="w-100" type="text" icon="plus-outlined" text="新建通知渠道" onClick={openTableSelectDialog}></fs-button>);
|
// res.push(<fs-button class="w-100" type="text" icon="plus-outlined" text="新建通知渠道" onClick={openTableSelectDialog}></fs-button>);
|
||||||
return res;
|
return res;
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const target: Ref<any> = ref({});
|
const target: Ref<any> = ref({});
|
||||||
@@ -141,13 +132,13 @@ watch(
|
|||||||
() => {
|
() => {
|
||||||
return props.modelValue;
|
return props.modelValue;
|
||||||
},
|
},
|
||||||
async (value) => {
|
async value => {
|
||||||
await optionsDictRef.loadDict();
|
await optionsDictRef.loadDict();
|
||||||
target.value = optionsDictRef.dataMap[value];
|
target.value = optionsDictRef.dataMap[value];
|
||||||
emit("selectedChange", target.value);
|
emit("selectedChange", target.value);
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
immediate: true
|
immediate: true,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ const apiPrefix = "/pi/plugin";
|
|||||||
const defaultInputDefine = {
|
const defaultInputDefine = {
|
||||||
component: {
|
component: {
|
||||||
name: "a-input",
|
name: "a-input",
|
||||||
vModel: "modelValue"
|
vModel: "modelValue",
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
function initPlugins(plugins: any) {
|
function initPlugins(plugins: any) {
|
||||||
@@ -35,7 +35,7 @@ export async function GetList(query: any) {
|
|||||||
const plugins = await request({
|
const plugins = await request({
|
||||||
url: apiPrefix + "/list",
|
url: apiPrefix + "/list",
|
||||||
method: "post",
|
method: "post",
|
||||||
params: query
|
params: query,
|
||||||
});
|
});
|
||||||
initPlugins(plugins);
|
initPlugins(plugins);
|
||||||
return plugins;
|
return plugins;
|
||||||
@@ -45,7 +45,7 @@ export async function GetGroups(query: any) {
|
|||||||
const groups = await request({
|
const groups = await request({
|
||||||
url: apiPrefix + "/groups",
|
url: apiPrefix + "/groups",
|
||||||
method: "post",
|
method: "post",
|
||||||
params: query
|
params: query,
|
||||||
});
|
});
|
||||||
const plugins: any = [];
|
const plugins: any = [];
|
||||||
for (const groupKey in groups) {
|
for (const groupKey in groups) {
|
||||||
@@ -60,8 +60,8 @@ export async function GetPluginDefine(type: string) {
|
|||||||
url: apiPrefix + "/getDefineByType",
|
url: apiPrefix + "/getDefineByType",
|
||||||
method: "post",
|
method: "post",
|
||||||
data: {
|
data: {
|
||||||
type
|
type,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
initPlugins([define]);
|
initPlugins([define]);
|
||||||
return define;
|
return define;
|
||||||
@@ -71,6 +71,6 @@ export async function GetPluginConfig(req: { id?: number; name: string; type: st
|
|||||||
return await request({
|
return await request({
|
||||||
url: apiPrefix + "/config",
|
url: apiPrefix + "/config",
|
||||||
method: "post",
|
method: "post",
|
||||||
data: req
|
data: req,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export async function GetList(query: any) {
|
|||||||
return await request({
|
return await request({
|
||||||
url: apiPrefix + "/page",
|
url: apiPrefix + "/page",
|
||||||
method: "post",
|
method: "post",
|
||||||
data: query
|
data: query,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ export async function AddObj(obj: any) {
|
|||||||
return await request({
|
return await request({
|
||||||
url: apiPrefix + "/add",
|
url: apiPrefix + "/add",
|
||||||
method: "post",
|
method: "post",
|
||||||
data: obj
|
data: obj,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -24,7 +24,7 @@ export async function UpdateObj(obj: any) {
|
|||||||
return await request({
|
return await request({
|
||||||
url: apiPrefix + "/update",
|
url: apiPrefix + "/update",
|
||||||
method: "post",
|
method: "post",
|
||||||
data: obj
|
data: obj,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ export async function DelObj(id: any) {
|
|||||||
return await request({
|
return await request({
|
||||||
url: apiPrefix + "/delete",
|
url: apiPrefix + "/delete",
|
||||||
method: "post",
|
method: "post",
|
||||||
params: { id }
|
params: { id },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,7 +40,7 @@ export async function GetObj(id: any) {
|
|||||||
return await request({
|
return await request({
|
||||||
url: apiPrefix + "/info",
|
url: apiPrefix + "/info",
|
||||||
method: "post",
|
method: "post",
|
||||||
params: { id }
|
params: { id },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,7 +48,7 @@ export async function GetDetail(id: any) {
|
|||||||
return await request({
|
return await request({
|
||||||
url: apiPrefix + "/detail",
|
url: apiPrefix + "/detail",
|
||||||
method: "post",
|
method: "post",
|
||||||
params: { id }
|
params: { id },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,7 +56,7 @@ export async function Save(pipelineEntity: any) {
|
|||||||
return await request({
|
return await request({
|
||||||
url: apiPrefix + "/save",
|
url: apiPrefix + "/save",
|
||||||
method: "post",
|
method: "post",
|
||||||
data: pipelineEntity
|
data: pipelineEntity,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,7 +64,7 @@ export async function Trigger(id: any, stepId?: string) {
|
|||||||
return await request({
|
return await request({
|
||||||
url: apiPrefix + "/trigger",
|
url: apiPrefix + "/trigger",
|
||||||
method: "post",
|
method: "post",
|
||||||
params: { id, stepId }
|
params: { id, stepId },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,7 +72,7 @@ export async function Cancel(historyId: any) {
|
|||||||
return await request({
|
return await request({
|
||||||
url: apiPrefix + "/cancel",
|
url: apiPrefix + "/cancel",
|
||||||
method: "post",
|
method: "post",
|
||||||
params: { historyId }
|
params: { historyId },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,7 +80,7 @@ export async function BatchUpdateGroup(pipelineIds: number[], groupId: number):
|
|||||||
return await request({
|
return await request({
|
||||||
url: apiPrefix + "/batchUpdateGroup",
|
url: apiPrefix + "/batchUpdateGroup",
|
||||||
method: "post",
|
method: "post",
|
||||||
data: { ids: pipelineIds, groupId }
|
data: { ids: pipelineIds, groupId },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,7 +88,7 @@ export async function BatchDelete(pipelineIds: number[]): Promise<CertInfo> {
|
|||||||
return await request({
|
return await request({
|
||||||
url: apiPrefix + "/batchDelete",
|
url: apiPrefix + "/batchDelete",
|
||||||
method: "post",
|
method: "post",
|
||||||
data: { ids: pipelineIds }
|
data: { ids: pipelineIds },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,14 +96,14 @@ export async function GetFiles(pipelineId: number) {
|
|||||||
return await request({
|
return await request({
|
||||||
url: historyApiPrefix + "/files",
|
url: historyApiPrefix + "/files",
|
||||||
method: "post",
|
method: "post",
|
||||||
params: { pipelineId }
|
params: { pipelineId },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function GetCount() {
|
export async function GetCount() {
|
||||||
return await request({
|
return await request({
|
||||||
url: apiPrefix + "/count",
|
url: apiPrefix + "/count",
|
||||||
method: "post"
|
method: "post",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,6 +119,6 @@ export async function GetCert(pipelineId: number): Promise<CertInfo> {
|
|||||||
return await request({
|
return await request({
|
||||||
url: certApiPrefix + "/get",
|
url: certApiPrefix + "/get",
|
||||||
method: "post",
|
method: "post",
|
||||||
params: { id: pipelineId }
|
params: { id: pipelineId },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import { request } from "/src/api/service";
|
||||||
|
|
||||||
|
const apiPrefix = "/monitor/cert";
|
||||||
|
export async function UploadCert(body: { id?: number; cert: { crt: string; key: string }; pipeline?: any }) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/upload",
|
||||||
|
method: "post",
|
||||||
|
data: body,
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
<template>
|
||||||
|
<div class="cert-info-updater w-full flex items-center">
|
||||||
|
<div class="flex-o">
|
||||||
|
<a-tag>{{ domain }}</a-tag>
|
||||||
|
<fs-button type="primary" size="small" class="ml-1" icon="ion:upload" text="更新证书" @click="onUploadClick" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="tsx" setup>
|
||||||
|
import { computed, inject } from "vue";
|
||||||
|
import { useCertUpload } from "./use";
|
||||||
|
import { getAllDomainsFromCrt } from "/@/views/certd/pipeline/utils";
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: "CertInfoUpdater",
|
||||||
|
});
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
modelValue?: { crt: string; key: string };
|
||||||
|
type?: string;
|
||||||
|
placeholder?: string;
|
||||||
|
size?: string;
|
||||||
|
disabled?: boolean;
|
||||||
|
}>();
|
||||||
|
const emit = defineEmits(["updated", "update:modelValue"]);
|
||||||
|
|
||||||
|
const { openUpdateCertDialog } = useCertUpload();
|
||||||
|
|
||||||
|
const domain = computed(() => {
|
||||||
|
if (!props.modelValue?.crt) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
const domains = getAllDomainsFromCrt(props.modelValue?.crt);
|
||||||
|
|
||||||
|
return domains[0];
|
||||||
|
});
|
||||||
|
|
||||||
|
function onUpdated(res: { uploadCert: any }) {
|
||||||
|
debugger;
|
||||||
|
emit("update:modelValue", res.uploadCert);
|
||||||
|
const domains = getAllDomainsFromCrt(res.uploadCert.crt);
|
||||||
|
emit("updated", { domains });
|
||||||
|
}
|
||||||
|
|
||||||
|
const pipeline: any = inject("pipeline");
|
||||||
|
function onUploadClick() {
|
||||||
|
debugger;
|
||||||
|
openUpdateCertDialog({
|
||||||
|
onSubmit: onUpdated,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="less">
|
||||||
|
.cert-info-selector {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user