mirror of
https://github.com/certd/certd.git
synced 2026-04-30 09:17:24 +08:00
Compare commits
25 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7b6b71cd4b | |||
| df98463325 | |||
| f7492db8bd | |||
| 70b46d4a8f | |||
| 411486e1e7 | |||
| 6f81305232 | |||
| 79bc22d8ce | |||
| 1c634a702a | |||
| 909a9e4050 | |||
| b5cc794061 | |||
| 73b8e85976 | |||
| 282b5d6893 | |||
| c6628e7311 | |||
| 6b109d172f | |||
| 6b29972399 | |||
| 0fcd3c09fd | |||
| af503442b8 | |||
| c875971b71 | |||
| d1a65922d7 | |||
| 6ef34f95d5 | |||
| 8b79022179 | |||
| 21aec77e5c | |||
| 74c5259af8 | |||
| a3e7d4414d | |||
| 986d32eb81 |
@@ -163,6 +163,16 @@ async doRequest(req: { action: string, data?: any }) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
--- 开发技巧:实现统一的 API 请求封装
|
||||||
|
|
||||||
|
**好处:**
|
||||||
|
- **代码复用**:避免在每个 API 方法中重复编写相同的 header 设置和错误处理逻辑
|
||||||
|
- **错误处理一致**:统一捕获和处理各种错误情况,确保错误信息格式统一
|
||||||
|
- **日志记录完善**:集中记录详细的错误信息,便于调试和问题排查
|
||||||
|
- **接口调用简化**:调用方只需关注业务逻辑,无需关心底层请求细节
|
||||||
|
- **易于维护**:统一修改 API 调用方式时,只需修改一处代码
|
||||||
|
|
||||||
|
|
||||||
## 注意事项
|
## 注意事项
|
||||||
|
|
||||||
1. **插件命名**:插件名称应简洁明了,反映其功能。
|
1. **插件命名**:插件名称应简洁明了,反映其功能。
|
||||||
@@ -170,9 +180,12 @@ async doRequest(req: { action: string, data?: any }) {
|
|||||||
3. **日志输出**:必须使用 `this.ctx.logger` 输出日志,而不是 `console`。
|
3. **日志输出**:必须使用 `this.ctx.logger` 输出日志,而不是 `console`。
|
||||||
4. **错误处理**:API 调用失败时应抛出明确的错误信息。
|
4. **错误处理**:API 调用失败时应抛出明确的错误信息。
|
||||||
5. **测试方法**:实现 `onTestRequest` 方法,以便用户可以测试授权是否正常。
|
5. **测试方法**:实现 `onTestRequest` 方法,以便用户可以测试授权是否正常。
|
||||||
|
6. **统一接口调用方法**:封装统一的 API 请求方法,避免在每个 API 方法调用中重复编写错误处理逻辑。
|
||||||
|
|
||||||
## 完整示例
|
## 完整示例
|
||||||
|
|
||||||
|
### 示例 1: 通用授权插件
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { AccessInput, BaseAccess, IsAccess, Pager, PageRes, PageSearch } from '@certd/pipeline';
|
import { AccessInput, BaseAccess, IsAccess, Pager, PageRes, PageSearch } from '@certd/pipeline';
|
||||||
import { DomainRecord } from '@certd/plugin-lib';
|
import { DomainRecord } from '@certd/plugin-lib';
|
||||||
|
|||||||
@@ -6,9 +6,8 @@ Access:存储用户的第三放应用的授权数据,比如用户名密码
|
|||||||
Task: 部署任务插件,它继承AbstractTaskPlugin类,被流水线调用execute方法,将证书部署到对应的应用上
|
Task: 部署任务插件,它继承AbstractTaskPlugin类,被流水线调用execute方法,将证书部署到对应的应用上
|
||||||
DnsProvider: DNS提供商插件,它用于在ACME申请证书时给域名添加txt解析记录。
|
DnsProvider: DNS提供商插件,它用于在ACME申请证书时给域名添加txt解析记录。
|
||||||
|
|
||||||
在开始工作前,请阅读并加载.trae/skills下面的技能,根据skills进行相应的插件开发
|
注意事项:
|
||||||
当开发过程中遇到问题,需要参考plugins目录下的其他插件,或者用户提醒你更好的做法时,你需要总结经验,更新相应的skills,让skills越来越完善,能够在以后得新插件开发中具备指导意义。
|
1、使用技能:在开始工作前,请阅读并加载.trae/skills下面的技能,根据skills进行相应的插件开发
|
||||||
|
2、迭代技能:当开发过程用户提醒你更好的做法时,你需要总结经验,更新相应的skills,让skills越来越完善,能够在以后得新插件开发中具备指导意义。
|
||||||
一般调用的api接口文档会比较复杂,你不知道接口是什么时,请务必询问用户,让用户提供API接口文档
|
3、一般调用的api接口文档会比较复杂,你不知道接口是什么时,请务必询问用户,让用户提供API接口文档
|
||||||
|
4、完成开发后无需测试,通知用户自己去测试
|
||||||
完成开发后无需测试,通知用户自己去测试
|
|
||||||
@@ -126,6 +126,8 @@ if (isDev()) {
|
|||||||
|
|
||||||
## 完整示例
|
## 完整示例
|
||||||
|
|
||||||
|
### 示例:通用 DNS Provider
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { AbstractDnsProvider, CreateRecordOptions, IsDnsProvider, RemoveRecordOptions } from '@certd/plugin-cert';
|
import { AbstractDnsProvider, CreateRecordOptions, IsDnsProvider, RemoveRecordOptions } from '@certd/plugin-cert';
|
||||||
import { DemoAccess } from './access.js';
|
import { DemoAccess } from './access.js';
|
||||||
|
|||||||
@@ -3,6 +3,22 @@
|
|||||||
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.39.9](https://github.com/certd/certd/compare/v1.39.8...v1.39.9) (2026-04-05)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复cn域名获取不到到期时间的问题 ([73b8e85](https://github.com/certd/certd/commit/73b8e859766097b5251fc4e5051593d686669eb2))
|
||||||
|
* 修复某些情况下报无法修改通知的问题 ([d1a6592](https://github.com/certd/certd/commit/d1a65922d7e152d6edcf6c53b70079f16b54a0d3))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 腾讯云CLB大区增加台北 ([6b109d1](https://github.com/certd/certd/commit/6b109d172f0c7b6ce6ec164dc196d646a65f529f))
|
||||||
|
* 优化腾讯云CLB插件支持选择证书id ([c875971](https://github.com/certd/certd/commit/c875971b71dc6d392e56f0a7605281c40d9bb405))
|
||||||
|
* 支持域名到期时间监控通知 ([c6628e7](https://github.com/certd/certd/commit/c6628e7311d6c43c2a784581fb25ec37b29c168d))
|
||||||
|
* **monitor:** 支持查看监控执行记录 ([b5cc794](https://github.com/certd/certd/commit/b5cc794061c11b7200b669473c25c4bbfc944b61))
|
||||||
|
* **plugin-dnsmgr:** 添加彩虹DNS插件支持 ([af50344](https://github.com/certd/certd/commit/af503442b8298c5b89d11cf2ea351d62e66a609e))
|
||||||
|
* **spaceship:** 新增Spaceship DNS插件和授权模块 ([21aec77](https://github.com/certd/certd/commit/21aec77e5c3307b5973d4185baba33edcb28926f))
|
||||||
|
|
||||||
## [1.39.8](https://github.com/certd/certd/compare/v1.39.7...v1.39.8) (2026-03-31)
|
## [1.39.8](https://github.com/certd/certd/compare/v1.39.7...v1.39.8) (2026-03-31)
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|||||||
@@ -211,3 +211,4 @@ https://certd.handfree.work/
|
|||||||
| --------- |--------- |----------- |
|
| --------- |--------- |----------- |
|
||||||
| [fast-crud](https://gitee.com/fast-crud/fast-crud/) | <img alt="GitHub stars" src="https://img.shields.io/github/stars/fast-crud/fast-crud?logo=github"/> | 基于vue3的crud快速开发框架 |
|
| [fast-crud](https://gitee.com/fast-crud/fast-crud/) | <img alt="GitHub stars" src="https://img.shields.io/github/stars/fast-crud/fast-crud?logo=github"/> | 基于vue3的crud快速开发框架 |
|
||||||
| [dev-sidecar](https://github.com/docmirror/dev-sidecar/) | <img alt="GitHub stars" src="https://img.shields.io/github/stars/docmirror/dev-sidecar?logo=github"/> | 直连访问github工具,无需FQ,解决github无法访问的问题 |
|
| [dev-sidecar](https://github.com/docmirror/dev-sidecar/) | <img alt="GitHub stars" src="https://img.shields.io/github/stars/docmirror/dev-sidecar?logo=github"/> | 直连访问github工具,无需FQ,解决github无法访问的问题 |
|
||||||
|
| [winsvc-manager](https://github.com/greper/winsvc-manager/) | <img alt="GitHub stars" src="https://img.shields.io/github/stars/greper/winsvc-manager?logo=github"/> | 可视化包装应用成为一个Windows服务,使其后台运行 |
|
||||||
|
|||||||
@@ -124,6 +124,7 @@ export default defineConfig({
|
|||||||
{text: "子域名托管", link: "/guide/use/cert/subdomain.md"},
|
{text: "子域名托管", link: "/guide/use/cert/subdomain.md"},
|
||||||
{text: "流水线有效期", link: "/guide/use/pipeline/valid.md"},
|
{text: "流水线有效期", link: "/guide/use/pipeline/valid.md"},
|
||||||
{text: "IP证书申请", link: "/guide/use/cert/ip.md"},
|
{text: "IP证书申请", link: "/guide/use/cert/ip.md"},
|
||||||
|
{text: "企业模式", link: "/guide/use/mode/enterprise.md"},
|
||||||
{text: "插件开发", link: "/guide/use/dev/plugin.md"},
|
{text: "插件开发", link: "/guide/use/dev/plugin.md"},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -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.39.9](https://github.com/certd/certd/compare/v1.39.8...v1.39.9) (2026-04-05)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复cn域名获取不到到期时间的问题 ([73b8e85](https://github.com/certd/certd/commit/73b8e859766097b5251fc4e5051593d686669eb2))
|
||||||
|
* 修复某些情况下报无法修改通知的问题 ([d1a6592](https://github.com/certd/certd/commit/d1a65922d7e152d6edcf6c53b70079f16b54a0d3))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 腾讯云CLB大区增加台北 ([6b109d1](https://github.com/certd/certd/commit/6b109d172f0c7b6ce6ec164dc196d646a65f529f))
|
||||||
|
* 优化腾讯云CLB插件支持选择证书id ([c875971](https://github.com/certd/certd/commit/c875971b71dc6d392e56f0a7605281c40d9bb405))
|
||||||
|
* 支持域名到期时间监控通知 ([c6628e7](https://github.com/certd/certd/commit/c6628e7311d6c43c2a784581fb25ec37b29c168d))
|
||||||
|
* **monitor:** 支持查看监控执行记录 ([b5cc794](https://github.com/certd/certd/commit/b5cc794061c11b7200b669473c25c4bbfc944b61))
|
||||||
|
* **plugin-dnsmgr:** 添加彩虹DNS插件支持 ([af50344](https://github.com/certd/certd/commit/af503442b8298c5b89d11cf2ea351d62e66a609e))
|
||||||
|
* **spaceship:** 新增Spaceship DNS插件和授权模块 ([21aec77](https://github.com/certd/certd/commit/21aec77e5c3307b5973d4185baba33edcb28926f))
|
||||||
|
|
||||||
|
## [1.39.8](https://github.com/certd/certd/compare/v1.39.7...v1.39.8) (2026-03-31)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复某些情况下报没有匹配到任何校验方式的bug ([fe02ce7](https://github.com/certd/certd/commit/fe02ce7b64cf23c4dc4c30daccd5330059a35e9a))
|
||||||
|
* 修复上传头像退出登录的bug ([6eb20a1](https://github.com/certd/certd/commit/6eb20a1f2e31d984d9135edbf39c97cdd15621f9))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 阿里云CDN部署支持根据证书域名自动匹配部署 ([a68301e](https://github.com/certd/certd/commit/a68301e4dcea8b7391ad751aa57555d566297ad9))
|
||||||
|
* 阿里云dcdn支持根据证书域名匹配模式 ([df012de](https://github.com/certd/certd/commit/df012dec90590ecba85a69ed6355cfa8382c1da3))
|
||||||
|
* 支持部署证书到百度CCE ([a19ea74](https://github.com/certd/certd/commit/a19ea7489c01cdbf795fb51f804bd6d00389f604))
|
||||||
|
* dcdn自动匹配部署,支持新增域名感知 ([c6a988b](https://github.com/certd/certd/commit/c6a988bc925886bd7163c1270f2b7a10a57b1c5b))
|
||||||
|
|
||||||
## [1.39.7](https://github.com/certd/certd/compare/v1.39.6...v1.39.7) (2026-03-25)
|
## [1.39.7](https://github.com/certd/certd/compare/v1.39.6...v1.39.7) (2026-03-25)
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|||||||
@@ -28,51 +28,53 @@
|
|||||||
| 24.| **中国移动CND授权** | |
|
| 24.| **中国移动CND授权** | |
|
||||||
| 25.| **授权插件示例** | 这是一个示例授权插件,用于演示如何实现一个授权插件 |
|
| 25.| **授权插件示例** | 这是一个示例授权插件,用于演示如何实现一个授权插件 |
|
||||||
| 26.| **dns.la授权** | |
|
| 26.| **dns.la授权** | |
|
||||||
| 27.| **多吉云** | |
|
| 27.| **彩虹DNS** | 彩虹DNS管理系统授权 |
|
||||||
| 28.| **Dokploy授权** | |
|
| 28.| **多吉云** | |
|
||||||
| 29.| **farcdn授权** | |
|
| 29.| **Dokploy授权** | |
|
||||||
| 30.| **FlexCDN授权** | |
|
| 30.| **farcdn授权** | |
|
||||||
| 31.| **Gcore** | Gcore |
|
| 31.| **FlexCDN授权** | |
|
||||||
| 32.| **Github授权** | |
|
| 32.| **Gcore** | Gcore |
|
||||||
| 33.| **godaddy授权** | |
|
| 33.| **Github授权** | |
|
||||||
| 34.| **金山云授权** | |
|
| 34.| **godaddy授权** | |
|
||||||
| 35.| **FTP授权** | |
|
| 35.| **金山云授权** | |
|
||||||
| 36.| **七牛OSS授权** | |
|
| 36.| **FTP授权** | |
|
||||||
| 37.| **腾讯云COS授权** | 腾讯云对象存储授权,包含地域和存储桶 |
|
| 37.| **七牛OSS授权** | |
|
||||||
| 38.| **s3/minio授权** | S3/minio oss授权 |
|
| 38.| **腾讯云COS授权** | 腾讯云对象存储授权,包含地域和存储桶 |
|
||||||
| 39.| **namesilo授权** | |
|
| 39.| **s3/minio授权** | S3/minio oss授权 |
|
||||||
| 40.| **Next Terminal 授权** | 用于访问 Next Terminal API 的授权配置 |
|
| 40.| **namesilo授权** | |
|
||||||
| 41.| **1panel授权** | 账号和密码 |
|
| 41.| **Next Terminal 授权** | 用于访问 Next Terminal API 的授权配置 |
|
||||||
| 42.| **支付宝** | |
|
| 42.| **1panel授权** | 账号和密码 |
|
||||||
| 43.| **白山云授权** | |
|
| 43.| **支付宝** | |
|
||||||
| 44.| **宝塔云WAF授权** | 用于连接和管理宝塔云WAF服务的授权配置 |
|
| 44.| **白山云授权** | |
|
||||||
| 45.| **cdnfly授权** | |
|
| 45.| **宝塔云WAF授权** | 用于连接和管理宝塔云WAF服务的授权配置 |
|
||||||
| 46.| **k8s授权** | |
|
| 46.| **cdnfly授权** | |
|
||||||
| 47.| **括彩云cdn授权** | 括彩云CDN,每月免费30G,[注册即领](https://kuocaicdn.com/register?code=8mn536rrzfbf8) |
|
| 47.| **k8s授权** | |
|
||||||
| 48.| **LeCDN授权** | |
|
| 48.| **括彩云cdn授权** | 括彩云CDN,每月免费30G,[注册即领](https://kuocaicdn.com/register?code=8mn536rrzfbf8) |
|
||||||
| 49.| **lucky** | |
|
| 49.| **LeCDN授权** | |
|
||||||
| 50.| **猫云授权** | |
|
| 50.| **lucky** | |
|
||||||
| 51.| **plesk授权** | |
|
| 51.| **猫云授权** | |
|
||||||
| 52.| **长亭雷池授权** | |
|
| 52.| **plesk授权** | |
|
||||||
| 53.| **群晖登录授权** | |
|
| 53.| **长亭雷池授权** | |
|
||||||
| 54.| **uniCloud** | unicloud授权 |
|
| 54.| **群晖登录授权** | |
|
||||||
| 55.| **微信支付** | |
|
| 55.| **uniCloud** | unicloud授权 |
|
||||||
| 56.| **易盾rcdn授权** | 易盾CDN,每月免费30G,[注册即领](https://rhcdn.yiduncdn.com/register?code=8mn536rrzfbf8) |
|
| 56.| **微信支付** | |
|
||||||
| 57.| **易发云短信** | sms.yfyidc.cn/ |
|
| 57.| **易盾rcdn授权** | 易盾CDN,每月免费30G,[注册即领](https://rhcdn.yiduncdn.com/register?code=8mn536rrzfbf8) |
|
||||||
| 58.| **易盾DCDN授权** | https://user.yiduncdn.com |
|
| 58.| **易发云短信** | sms.yfyidc.cn/ |
|
||||||
| 59.| **易支付** | |
|
| 59.| **易盾DCDN授权** | https://user.yiduncdn.com |
|
||||||
| 60.| **proxmox** | |
|
| 60.| **易支付** | |
|
||||||
| 61.| **UCloud授权** | 优刻得授权 |
|
| 61.| **proxmox** | |
|
||||||
| 62.| **又拍云** | |
|
| 62.| **Spaceship.com 授权** | Spaceship.com API 授权插件 |
|
||||||
| 63.| **网宿授权** | |
|
| 63.| **UCloud授权** | 优刻得授权 |
|
||||||
| 64.| **西部数码授权** | |
|
| 64.| **又拍云** | |
|
||||||
| 65.| **我爱云授权** | 我爱云CDN |
|
| 65.| **网宿授权** | |
|
||||||
| 66.| **新网授权(代理方式)** | |
|
| 66.| **西部数码授权** | |
|
||||||
| 67.| **新网授权** | |
|
| 67.| **我爱云授权** | 我爱云CDN |
|
||||||
| 68.| **新网互联授权** | 仅支持代理账号,ip需要加入白名单 |
|
| 68.| **新网授权(代理方式)** | |
|
||||||
| 69.| **Zenlayer授权** | Zenlayer授权 |
|
| 69.| **新网授权** | |
|
||||||
| 70.| **GoEdge授权** | |
|
| 70.| **新网互联授权** | 仅支持代理账号,ip需要加入白名单 |
|
||||||
| 71.| **雨云授权** | https://app.rainyun.com/ |
|
| 71.| **Zenlayer授权** | Zenlayer授权 |
|
||||||
|
| 72.| **GoEdge授权** | |
|
||||||
|
| 73.| **雨云授权** | https://app.rainyun.com/ |
|
||||||
|
|
||||||
<style module>
|
<style module>
|
||||||
table th:first-of-type {
|
table th:first-of-type {
|
||||||
|
|||||||
@@ -20,8 +20,10 @@
|
|||||||
| 16.| **腾讯云EO DNS** | 腾讯云EO DNS解析提供者 |
|
| 16.| **腾讯云EO DNS** | 腾讯云EO DNS解析提供者 |
|
||||||
| 17.| **西部数码** | west dns provider |
|
| 17.| **西部数码** | west dns provider |
|
||||||
| 18.| **Dns提供商Demo** | dns provider示例 |
|
| 18.| **Dns提供商Demo** | dns provider示例 |
|
||||||
| 19.| **51dns** | 51DNS |
|
| 19.| **彩虹DNS** | 彩虹DNS管理系统 |
|
||||||
| 20.| **新网互联** | 新网互联 |
|
| 20.| **Spaceship** | Spaceship 域名解析 |
|
||||||
|
| 21.| **51dns** | 51DNS |
|
||||||
|
| 22.| **新网互联** | 新网互联 |
|
||||||
|
|
||||||
<style module>
|
<style module>
|
||||||
table th:first-of-type {
|
table th:first-of-type {
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
# 企业模式(项目管理)
|
||||||
|
|
||||||
|
## 模式简介
|
||||||
|
Certd支持两种管理模式,`SaaS模式(默认)`和`企业模式`。
|
||||||
|
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## SaaS模式
|
||||||
|
* 默认的模式,每个用户管理自己的流水线和授权资源,每个用户独立使用。
|
||||||
|
* Certd系统作为SaaS提供证书自动申请部署服务,您的客户注册即可使用,无需自己部署
|
||||||
|
|
||||||
|
|
||||||
|
## 企业模式
|
||||||
|
|
||||||
|
* 通过项目合作管理流水线证书和授权资源,所有用户视为企业内部员工。
|
||||||
|
|
||||||
|
* 当你想在企业内部使用,企业内部有多个项目,各个项目成员共同管理项目资源和证书时可以启用此模式
|
||||||
|
|
||||||
|
* 需要在"系统设置->管理模式"中开启`企业模式`
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
::: warning
|
||||||
|
* 建议在开始使用时固定一个合适的模式,之后就不要随意切换了。
|
||||||
|
* 商业版不能使用企业模式,因为商业版提供功能价值在于SaaS服务,与企业模式冲突
|
||||||
|
:::
|
||||||
|
|
||||||
|
### 数据迁移
|
||||||
|
模式之间数据不互通,您可以通过个人数据迁移功能将数据转到项目之下
|
||||||
|
|
||||||
|
#### 个人数据迁移到项目
|
||||||
|
注意:此操作不可逆,请谨慎操作
|
||||||
|

|
||||||
|
|
||||||
|
#### 流水线数据转到其他项目
|
||||||
|
项目之间流水线数据可以转移,依赖的授权数据会同步复制一份
|
||||||
|
|
||||||
|

|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 95 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 118 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 145 KiB |
+1
-1
@@ -9,5 +9,5 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"npmClient": "pnpm",
|
"npmClient": "pnpm",
|
||||||
"version": "1.39.8"
|
"version": "1.39.9"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,10 @@
|
|||||||
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.39.9](https://github.com/publishlab/node-acme-client/compare/v1.39.8...v1.39.9) (2026-04-05)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/acme-client
|
||||||
|
|
||||||
## [1.39.8](https://github.com/publishlab/node-acme-client/compare/v1.39.7...v1.39.8) (2026-03-31)
|
## [1.39.8](https://github.com/publishlab/node-acme-client/compare/v1.39.7...v1.39.8) (2026-03-31)
|
||||||
|
|
||||||
**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.39.8",
|
"version": "1.39.9",
|
||||||
"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.39.8",
|
"@certd/basic": "^1.39.9",
|
||||||
"@peculiar/x509": "^1.11.0",
|
"@peculiar/x509": "^1.11.0",
|
||||||
"asn1js": "^3.0.5",
|
"asn1js": "^3.0.5",
|
||||||
"axios": "^1.9.0",
|
"axios": "^1.9.0",
|
||||||
@@ -70,5 +70,5 @@
|
|||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/publishlab/node-acme-client/issues"
|
"url": "https://github.com/publishlab/node-acme-client/issues"
|
||||||
},
|
},
|
||||||
"gitHead": "adc3e6118b941818926705c3536babfca117c247"
|
"gitHead": "1c634a702af9298d25542acc270d68f71d9b1049"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,12 @@
|
|||||||
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.39.9](https://github.com/certd/certd/compare/v1.39.8...v1.39.9) (2026-04-05)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* **spaceship:** 新增Spaceship DNS插件和授权模块 ([21aec77](https://github.com/certd/certd/commit/21aec77e5c3307b5973d4185baba33edcb28926f))
|
||||||
|
|
||||||
## [1.39.8](https://github.com/certd/certd/compare/v1.39.7...v1.39.8) (2026-03-31)
|
## [1.39.8](https://github.com/certd/certd/compare/v1.39.7...v1.39.8) (2026-03-31)
|
||||||
|
|
||||||
**Note:** Version bump only for package @certd/basic
|
**Note:** Version bump only for package @certd/basic
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
23:54
|
01:21
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@certd/basic",
|
"name": "@certd/basic",
|
||||||
"private": false,
|
"private": false,
|
||||||
"version": "1.39.8",
|
"version": "1.39.9",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
"module": "./dist/index.js",
|
"module": "./dist/index.js",
|
||||||
@@ -47,5 +47,5 @@
|
|||||||
"tslib": "^2.8.1",
|
"tslib": "^2.8.1",
|
||||||
"typescript": "^5.4.2"
|
"typescript": "^5.4.2"
|
||||||
},
|
},
|
||||||
"gitHead": "adc3e6118b941818926705c3536babfca117c247"
|
"gitHead": "1c634a702af9298d25542acc270d68f71d9b1049"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -271,7 +271,7 @@ export function createAxiosService({ logger }: { logger: ILogger }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const originalRequest = error.config || {};
|
const originalRequest = error.config || {};
|
||||||
logger.info(`config`, originalRequest);
|
// logger.info(`config`, originalRequest);
|
||||||
const retry = originalRequest.retry || {};
|
const retry = originalRequest.retry || {};
|
||||||
if (retry.status && retry.status.includes(status)) {
|
if (retry.status && retry.status.includes(status)) {
|
||||||
if (retry.max > 0 && retry.count < retry.max) {
|
if (retry.max > 0 && retry.count < retry.max) {
|
||||||
|
|||||||
@@ -3,6 +3,12 @@
|
|||||||
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.39.9](https://github.com/certd/certd/compare/v1.39.8...v1.39.9) (2026-04-05)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 支持域名到期时间监控通知 ([c6628e7](https://github.com/certd/certd/commit/c6628e7311d6c43c2a784581fb25ec37b29c168d))
|
||||||
|
|
||||||
## [1.39.8](https://github.com/certd/certd/compare/v1.39.7...v1.39.8) (2026-03-31)
|
## [1.39.8](https://github.com/certd/certd/compare/v1.39.7...v1.39.8) (2026-03-31)
|
||||||
|
|
||||||
### Performance Improvements
|
### Performance Improvements
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@certd/pipeline",
|
"name": "@certd/pipeline",
|
||||||
"private": false,
|
"private": false,
|
||||||
"version": "1.39.8",
|
"version": "1.39.9",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
"module": "./dist/index.js",
|
"module": "./dist/index.js",
|
||||||
@@ -18,8 +18,8 @@
|
|||||||
"compile": "tsc --skipLibCheck --watch"
|
"compile": "tsc --skipLibCheck --watch"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@certd/basic": "^1.39.8",
|
"@certd/basic": "^1.39.9",
|
||||||
"@certd/plus-core": "^1.39.8",
|
"@certd/plus-core": "^1.39.9",
|
||||||
"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"
|
||||||
@@ -45,5 +45,5 @@
|
|||||||
"tslib": "^2.8.1",
|
"tslib": "^2.8.1",
|
||||||
"typescript": "^5.4.2"
|
"typescript": "^5.4.2"
|
||||||
},
|
},
|
||||||
"gitHead": "adc3e6118b941818926705c3536babfca117c247"
|
"gitHead": "1c634a702af9298d25542acc270d68f71d9b1049"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { IEmailService } from "../service/index.js";
|
|||||||
|
|
||||||
export type NotificationBody = {
|
export type NotificationBody = {
|
||||||
userId?: number;
|
userId?: number;
|
||||||
|
projectId?: number;
|
||||||
title: string;
|
title: string;
|
||||||
content: string;
|
content: string;
|
||||||
pipeline?: Pipeline;
|
pipeline?: Pipeline;
|
||||||
@@ -20,6 +21,7 @@ export type NotificationBody = {
|
|||||||
pipelineResult?: string;
|
pipelineResult?: string;
|
||||||
pipelineTitle?: string;
|
pipelineTitle?: string;
|
||||||
errors?: string;
|
errors?: string;
|
||||||
|
[key: string]: any; // 其他templateData
|
||||||
};
|
};
|
||||||
|
|
||||||
export type NotificationRequestHandleReqInput<T = any> = {
|
export type NotificationRequestHandleReqInput<T = any> = {
|
||||||
|
|||||||
@@ -3,6 +3,10 @@
|
|||||||
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.39.9](https://github.com/certd/certd/compare/v1.39.8...v1.39.9) (2026-04-05)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-huawei
|
||||||
|
|
||||||
## [1.39.8](https://github.com/certd/certd/compare/v1.39.7...v1.39.8) (2026-03-31)
|
## [1.39.8](https://github.com/certd/certd/compare/v1.39.7...v1.39.8) (2026-03-31)
|
||||||
|
|
||||||
**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.39.8",
|
"version": "1.39.9",
|
||||||
"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",
|
||||||
@@ -24,5 +24,5 @@
|
|||||||
"prettier": "^2.8.8",
|
"prettier": "^2.8.8",
|
||||||
"tslib": "^2.8.1"
|
"tslib": "^2.8.1"
|
||||||
},
|
},
|
||||||
"gitHead": "adc3e6118b941818926705c3536babfca117c247"
|
"gitHead": "1c634a702af9298d25542acc270d68f71d9b1049"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,10 @@
|
|||||||
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.39.9](https://github.com/certd/certd/compare/v1.39.8...v1.39.9) (2026-04-05)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-iframe
|
||||||
|
|
||||||
## [1.39.8](https://github.com/certd/certd/compare/v1.39.7...v1.39.8) (2026-03-31)
|
## [1.39.8](https://github.com/certd/certd/compare/v1.39.7...v1.39.8) (2026-03-31)
|
||||||
|
|
||||||
**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.39.8",
|
"version": "1.39.9",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
"module": "./dist/index.js",
|
"module": "./dist/index.js",
|
||||||
@@ -31,5 +31,5 @@
|
|||||||
"tslib": "^2.8.1",
|
"tslib": "^2.8.1",
|
||||||
"typescript": "^5.4.2"
|
"typescript": "^5.4.2"
|
||||||
},
|
},
|
||||||
"gitHead": "adc3e6118b941818926705c3536babfca117c247"
|
"gitHead": "1c634a702af9298d25542acc270d68f71d9b1049"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,10 @@
|
|||||||
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.39.9](https://github.com/certd/certd/compare/v1.39.8...v1.39.9) (2026-04-05)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/jdcloud
|
||||||
|
|
||||||
## [1.39.8](https://github.com/certd/certd/compare/v1.39.7...v1.39.8) (2026-03-31)
|
## [1.39.8](https://github.com/certd/certd/compare/v1.39.7...v1.39.8) (2026-03-31)
|
||||||
|
|
||||||
**Note:** Version bump only for package @certd/jdcloud
|
**Note:** Version bump only for package @certd/jdcloud
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@certd/jdcloud",
|
"name": "@certd/jdcloud",
|
||||||
"version": "1.39.8",
|
"version": "1.39.9",
|
||||||
"description": "jdcloud openApi sdk",
|
"description": "jdcloud openApi sdk",
|
||||||
"main": "./dist/bundle.js",
|
"main": "./dist/bundle.js",
|
||||||
"module": "./dist/bundle.js",
|
"module": "./dist/bundle.js",
|
||||||
@@ -56,5 +56,5 @@
|
|||||||
"fetch"
|
"fetch"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"gitHead": "adc3e6118b941818926705c3536babfca117c247"
|
"gitHead": "1c634a702af9298d25542acc270d68f71d9b1049"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,10 @@
|
|||||||
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.39.9](https://github.com/certd/certd/compare/v1.39.8...v1.39.9) (2026-04-05)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-k8s
|
||||||
|
|
||||||
## [1.39.8](https://github.com/certd/certd/compare/v1.39.7...v1.39.8) (2026-03-31)
|
## [1.39.8](https://github.com/certd/certd/compare/v1.39.7...v1.39.8) (2026-03-31)
|
||||||
|
|
||||||
### Performance Improvements
|
### Performance Improvements
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@certd/lib-k8s",
|
"name": "@certd/lib-k8s",
|
||||||
"private": false,
|
"private": false,
|
||||||
"version": "1.39.8",
|
"version": "1.39.9",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
"module": "./dist/index.js",
|
"module": "./dist/index.js",
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
"compile": "tsc --skipLibCheck --watch"
|
"compile": "tsc --skipLibCheck --watch"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@certd/basic": "^1.39.8",
|
"@certd/basic": "^1.39.9",
|
||||||
"@kubernetes/client-node": "0.21.0"
|
"@kubernetes/client-node": "0.21.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -33,5 +33,5 @@
|
|||||||
"tslib": "^2.8.1",
|
"tslib": "^2.8.1",
|
||||||
"typescript": "^5.4.2"
|
"typescript": "^5.4.2"
|
||||||
},
|
},
|
||||||
"gitHead": "adc3e6118b941818926705c3536babfca117c247"
|
"gitHead": "1c634a702af9298d25542acc270d68f71d9b1049"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,10 @@
|
|||||||
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.39.9](https://github.com/certd/certd/compare/v1.39.8...v1.39.9) (2026-04-05)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-server
|
||||||
|
|
||||||
## [1.39.8](https://github.com/certd/certd/compare/v1.39.7...v1.39.8) (2026-03-31)
|
## [1.39.8](https://github.com/certd/certd/compare/v1.39.7...v1.39.8) (2026-03-31)
|
||||||
|
|
||||||
**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.39.8",
|
"version": "1.39.9",
|
||||||
"description": "midway with flyway, sql upgrade way ",
|
"description": "midway with flyway, sql upgrade way ",
|
||||||
"private": false,
|
"private": false,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
@@ -28,11 +28,11 @@
|
|||||||
],
|
],
|
||||||
"license": "AGPL",
|
"license": "AGPL",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@certd/acme-client": "^1.39.8",
|
"@certd/acme-client": "^1.39.9",
|
||||||
"@certd/basic": "^1.39.8",
|
"@certd/basic": "^1.39.9",
|
||||||
"@certd/pipeline": "^1.39.8",
|
"@certd/pipeline": "^1.39.9",
|
||||||
"@certd/plugin-lib": "^1.39.8",
|
"@certd/plugin-lib": "^1.39.9",
|
||||||
"@certd/plus-core": "^1.39.8",
|
"@certd/plus-core": "^1.39.9",
|
||||||
"@midwayjs/cache": "3.14.0",
|
"@midwayjs/cache": "3.14.0",
|
||||||
"@midwayjs/core": "3.20.11",
|
"@midwayjs/core": "3.20.11",
|
||||||
"@midwayjs/i18n": "3.20.13",
|
"@midwayjs/i18n": "3.20.13",
|
||||||
@@ -64,5 +64,5 @@
|
|||||||
"typeorm": "^0.3.11",
|
"typeorm": "^0.3.11",
|
||||||
"typescript": "^5.4.2"
|
"typescript": "^5.4.2"
|
||||||
},
|
},
|
||||||
"gitHead": "adc3e6118b941818926705c3536babfca117c247"
|
"gitHead": "1c634a702af9298d25542acc270d68f71d9b1049"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,10 +76,12 @@ export abstract class BaseService<T> {
|
|||||||
* @param where
|
* @param where
|
||||||
*/
|
*/
|
||||||
async delete(ids: string | any[], where?: any) {
|
async delete(ids: string | any[], where?: any) {
|
||||||
const idArr = this.resolveIdArr(ids);
|
let idArr = this.resolveIdArr(ids);
|
||||||
|
idArr = this.filterIds(idArr);
|
||||||
if (idArr.length === 0) {
|
if (idArr.length === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.getRepository().delete({
|
await this.getRepository().delete({
|
||||||
id: In(idArr),
|
id: In(idArr),
|
||||||
...where,
|
...where,
|
||||||
@@ -94,7 +96,9 @@ export abstract class BaseService<T> {
|
|||||||
}
|
}
|
||||||
if (typeof ids === 'string') {
|
if (typeof ids === 'string') {
|
||||||
return ids.split(',');
|
return ids.split(',');
|
||||||
} else {
|
} else if(!Array.isArray(ids)){
|
||||||
|
return [ids];
|
||||||
|
}else {
|
||||||
return ids;
|
return ids;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -217,6 +221,7 @@ export abstract class BaseService<T> {
|
|||||||
if (!Array.isArray(ids)) {
|
if (!Array.isArray(ids)) {
|
||||||
ids = [ids];
|
ids = [ids];
|
||||||
}
|
}
|
||||||
|
ids = this.filterIds(ids);
|
||||||
const res = await this.getRepository().find({
|
const res = await this.getRepository().find({
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
@@ -234,7 +239,16 @@ export abstract class BaseService<T> {
|
|||||||
throw new PermissionException('权限不足');
|
throw new PermissionException('权限不足');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
filterIds(ids: any[]) {
|
||||||
|
if (!ids) {
|
||||||
|
throw new ValidateException('ids不能为空');
|
||||||
|
}
|
||||||
|
return ids.filter((item) => {
|
||||||
|
return item!=null && item != ""
|
||||||
|
});
|
||||||
|
}
|
||||||
async batchDelete(ids: number[], userId: number,projectId?:number) {
|
async batchDelete(ids: number[], userId: number,projectId?:number) {
|
||||||
|
ids = this.filterIds(ids);
|
||||||
if(userId!=null){
|
if(userId!=null){
|
||||||
const list = await this.getRepository().find({
|
const list = await this.getRepository().find({
|
||||||
where: {
|
where: {
|
||||||
|
|||||||
@@ -3,6 +3,10 @@
|
|||||||
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.39.9](https://github.com/certd/certd/compare/v1.39.8...v1.39.9) (2026-04-05)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/midway-flyway-js
|
||||||
|
|
||||||
## [1.39.8](https://github.com/certd/certd/compare/v1.39.7...v1.39.8) (2026-03-31)
|
## [1.39.8](https://github.com/certd/certd/compare/v1.39.7...v1.39.8) (2026-03-31)
|
||||||
|
|
||||||
**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.39.8",
|
"version": "1.39.9",
|
||||||
"description": "midway with flyway, sql upgrade way ",
|
"description": "midway with flyway, sql upgrade way ",
|
||||||
"private": false,
|
"private": false,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
@@ -46,5 +46,5 @@
|
|||||||
"typeorm": "^0.3.11",
|
"typeorm": "^0.3.11",
|
||||||
"typescript": "^5.4.2"
|
"typescript": "^5.4.2"
|
||||||
},
|
},
|
||||||
"gitHead": "adc3e6118b941818926705c3536babfca117c247"
|
"gitHead": "1c634a702af9298d25542acc270d68f71d9b1049"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,10 @@
|
|||||||
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.39.9](https://github.com/certd/certd/compare/v1.39.8...v1.39.9) (2026-04-05)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/plugin-cert
|
||||||
|
|
||||||
## [1.39.8](https://github.com/certd/certd/compare/v1.39.7...v1.39.8) (2026-03-31)
|
## [1.39.8](https://github.com/certd/certd/compare/v1.39.7...v1.39.8) (2026-03-31)
|
||||||
|
|
||||||
**Note:** Version bump only for package @certd/plugin-cert
|
**Note:** Version bump only for package @certd/plugin-cert
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@certd/plugin-cert",
|
"name": "@certd/plugin-cert",
|
||||||
"private": false,
|
"private": false,
|
||||||
"version": "1.39.8",
|
"version": "1.39.9",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
"types": "./dist/index.d.ts",
|
"types": "./dist/index.d.ts",
|
||||||
@@ -17,10 +17,10 @@
|
|||||||
"compile": "tsc --skipLibCheck --watch"
|
"compile": "tsc --skipLibCheck --watch"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@certd/acme-client": "^1.39.8",
|
"@certd/acme-client": "^1.39.9",
|
||||||
"@certd/basic": "^1.39.8",
|
"@certd/basic": "^1.39.9",
|
||||||
"@certd/pipeline": "^1.39.8",
|
"@certd/pipeline": "^1.39.9",
|
||||||
"@certd/plugin-lib": "^1.39.8",
|
"@certd/plugin-lib": "^1.39.9",
|
||||||
"psl": "^1.9.0",
|
"psl": "^1.9.0",
|
||||||
"punycode.js": "^2.3.1"
|
"punycode.js": "^2.3.1"
|
||||||
},
|
},
|
||||||
@@ -38,5 +38,5 @@
|
|||||||
"tslib": "^2.8.1",
|
"tslib": "^2.8.1",
|
||||||
"typescript": "^5.4.2"
|
"typescript": "^5.4.2"
|
||||||
},
|
},
|
||||||
"gitHead": "adc3e6118b941818926705c3536babfca117c247"
|
"gitHead": "1c634a702af9298d25542acc270d68f71d9b1049"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,10 @@
|
|||||||
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.39.9](https://github.com/certd/certd/compare/v1.39.8...v1.39.9) (2026-04-05)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/plugin-lib
|
||||||
|
|
||||||
## [1.39.8](https://github.com/certd/certd/compare/v1.39.7...v1.39.8) (2026-03-31)
|
## [1.39.8](https://github.com/certd/certd/compare/v1.39.7...v1.39.8) (2026-03-31)
|
||||||
|
|
||||||
### Performance Improvements
|
### Performance Improvements
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@certd/plugin-lib",
|
"name": "@certd/plugin-lib",
|
||||||
"private": false,
|
"private": false,
|
||||||
"version": "1.39.8",
|
"version": "1.39.9",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
"types": "./dist/index.d.ts",
|
"types": "./dist/index.d.ts",
|
||||||
@@ -22,10 +22,10 @@
|
|||||||
"@alicloud/pop-core": "^1.7.10",
|
"@alicloud/pop-core": "^1.7.10",
|
||||||
"@alicloud/tea-util": "^1.4.11",
|
"@alicloud/tea-util": "^1.4.11",
|
||||||
"@aws-sdk/client-s3": "^3.964.0",
|
"@aws-sdk/client-s3": "^3.964.0",
|
||||||
"@certd/acme-client": "^1.39.8",
|
"@certd/acme-client": "^1.39.9",
|
||||||
"@certd/basic": "^1.39.8",
|
"@certd/basic": "^1.39.9",
|
||||||
"@certd/pipeline": "^1.39.8",
|
"@certd/pipeline": "^1.39.9",
|
||||||
"@certd/plus-core": "^1.39.8",
|
"@certd/plus-core": "^1.39.9",
|
||||||
"@kubernetes/client-node": "0.21.0",
|
"@kubernetes/client-node": "0.21.0",
|
||||||
"ali-oss": "^6.22.0",
|
"ali-oss": "^6.22.0",
|
||||||
"basic-ftp": "^5.0.5",
|
"basic-ftp": "^5.0.5",
|
||||||
@@ -57,5 +57,5 @@
|
|||||||
"tslib": "^2.8.1",
|
"tslib": "^2.8.1",
|
||||||
"typescript": "^5.4.2"
|
"typescript": "^5.4.2"
|
||||||
},
|
},
|
||||||
"gitHead": "adc3e6118b941818926705c3536babfca117c247"
|
"gitHead": "1c634a702af9298d25542acc270d68f71d9b1049"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,17 @@
|
|||||||
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.39.9](https://github.com/certd/certd/compare/v1.39.8...v1.39.9) (2026-04-05)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复某些情况下报无法修改通知的问题 ([d1a6592](https://github.com/certd/certd/commit/d1a65922d7e152d6edcf6c53b70079f16b54a0d3))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 支持域名到期时间监控通知 ([c6628e7](https://github.com/certd/certd/commit/c6628e7311d6c43c2a784581fb25ec37b29c168d))
|
||||||
|
* **monitor:** 支持查看监控执行记录 ([b5cc794](https://github.com/certd/certd/commit/b5cc794061c11b7200b669473c25c4bbfc944b61))
|
||||||
|
|
||||||
## [1.39.8](https://github.com/certd/certd/compare/v1.39.7...v1.39.8) (2026-03-31)
|
## [1.39.8](https://github.com/certd/certd/compare/v1.39.7...v1.39.8) (2026-03-31)
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@certd/ui-client",
|
"name": "@certd/ui-client",
|
||||||
"version": "1.39.8",
|
"version": "1.39.9",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite --open",
|
"dev": "vite --open",
|
||||||
@@ -106,8 +106,8 @@
|
|||||||
"zod-defaults": "^0.1.3"
|
"zod-defaults": "^0.1.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@certd/lib-iframe": "^1.39.8",
|
"@certd/lib-iframe": "^1.39.9",
|
||||||
"@certd/pipeline": "^1.39.8",
|
"@certd/pipeline": "^1.39.9",
|
||||||
"@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",
|
||||||
|
|||||||
@@ -204,13 +204,13 @@ const vipTypeDefine: any = {
|
|||||||
desc: t("vip.community_free_version"),
|
desc: t("vip.community_free_version"),
|
||||||
type: "free",
|
type: "free",
|
||||||
icon: "lucide:package-open",
|
icon: "lucide:package-open",
|
||||||
privilege: [t("vip.unlimited_certificate_application"), t("vip.unlimited_domain_count"), t("vip.unlimited_certificate_pipelines"), t("vip.common_deployment_plugins"), t("vip.email_webhook_notifications")],
|
privilege: t("vip.free_privilege").split("\n"),
|
||||||
},
|
},
|
||||||
plus: {
|
plus: {
|
||||||
title: t("vip.professional_edition"),
|
title: t("vip.professional_edition"),
|
||||||
desc: t("vip.open_source_support"),
|
desc: t("vip.open_source_support"),
|
||||||
type: "plus",
|
type: "plus",
|
||||||
privilege: [t("vip.vip_group_priority"), t("vip.unlimited_site_certificate_monitoring"), t("vip.more_notification_methods"), t("vip.plugins_fully_open")],
|
privilege: t("vip.plus_privilege").split("\n"),
|
||||||
trial: {
|
trial: {
|
||||||
title: t("vip.click_to_get_7_day_trial"),
|
title: t("vip.click_to_get_7_day_trial"),
|
||||||
click: () => {
|
click: () => {
|
||||||
@@ -227,7 +227,7 @@ const vipTypeDefine: any = {
|
|||||||
desc: t("vip.commercial_license"),
|
desc: t("vip.commercial_license"),
|
||||||
type: "comm",
|
type: "comm",
|
||||||
icon: "vaadin:handshake",
|
icon: "vaadin:handshake",
|
||||||
privilege: [t("vip.all_pro_privileges"), t("vip.allow_commercial_use_modify_logo_title"), t("vip.data_statistics"), t("vip.plugin_management"), t("vip.unlimited_multi_users"), t("vip.support_user_payment")],
|
privilege: t("vip.comm_privilege").split("\n"),
|
||||||
priceText: props.productInfo.comm.priceText || `¥${props.productInfo.comm.price}/${t("vip.years")}`,
|
priceText: props.productInfo.comm.priceText || `¥${props.productInfo.comm.price}/${t("vip.years")}`,
|
||||||
discountText: props.productInfo.comm.discountText || `¥${props.productInfo.comm.price3}/3${t("vip.years")}`,
|
discountText: props.productInfo.comm.discountText || `¥${props.productInfo.comm.price3}/3${t("vip.years")}`,
|
||||||
tooltip: props.productInfo.comm.tooltip,
|
tooltip: props.productInfo.comm.tooltip,
|
||||||
|
|||||||
@@ -221,6 +221,7 @@ export default {
|
|||||||
projectJoin: "Join Project",
|
projectJoin: "Join Project",
|
||||||
currentProject: "Current Project",
|
currentProject: "Current Project",
|
||||||
projectMemberManager: "Project Member",
|
projectMemberManager: "Project Member",
|
||||||
|
domainMonitorSetting: "Domain Monitor Settings",
|
||||||
},
|
},
|
||||||
certificateRepo: {
|
certificateRepo: {
|
||||||
title: "Certificate Repository",
|
title: "Certificate Repository",
|
||||||
|
|||||||
@@ -64,10 +64,41 @@ export default {
|
|||||||
dnsServerHelper: "Use a custom domain name resolution server, such as: 1.1.1.1 , support multiple",
|
dnsServerHelper: "Use a custom domain name resolution server, such as: 1.1.1.1 , support multiple",
|
||||||
certValidDays: "Certificate Valid Days",
|
certValidDays: "Certificate Valid Days",
|
||||||
certValidDaysHelper: "Number of days before expiration to send a notification",
|
certValidDaysHelper: "Number of days before expiration to send a notification",
|
||||||
|
|
||||||
|
domain: {
|
||||||
|
monitorSettings: "Domain Monitor Settings",
|
||||||
|
enabled: "Enable Domain Monitor",
|
||||||
|
enabledHelper: "Enable to monitor all domain registration expiration time",
|
||||||
|
notificationChannel: "Notification Channel",
|
||||||
|
setNotificationChannel: "Set the notification channel",
|
||||||
|
willExpireDays: "Will Expire Days",
|
||||||
|
willExpireDaysHelper: "Number of days before expiration to send a notification",
|
||||||
|
monitorCronSetting: "Monitoring Schedule",
|
||||||
|
cronTrigger: "Scheduled trigger for monitoring",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
cert: {
|
cert: {
|
||||||
expired: "Expired",
|
expired: "Expired",
|
||||||
expiring: "Expiring",
|
expiring: "Expiring",
|
||||||
noExpired: "Not Expired",
|
noExpired: "Not Expired",
|
||||||
},
|
},
|
||||||
|
history: {
|
||||||
|
title: "Monitoring Execution Records",
|
||||||
|
description: "Monitoring execution records",
|
||||||
|
resultTitle: "Status",
|
||||||
|
contentTitle: "Content",
|
||||||
|
titleTitle: "Title",
|
||||||
|
jobTypeTitle: "Job Type",
|
||||||
|
startAtTitle: "Start Time",
|
||||||
|
endAtTitle: "End Time",
|
||||||
|
jobResultTitle: "Result",
|
||||||
|
jobResult: {
|
||||||
|
done: "Done",
|
||||||
|
start: "Start",
|
||||||
|
},
|
||||||
|
jobType: {
|
||||||
|
domainExpirationCheck: "Domain Expiration Check",
|
||||||
|
siteCertMonitor: "Site Certificate Monitor",
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ export default {
|
|||||||
unlimited_certificate_pipelines: "Unlimited certificate pipelines",
|
unlimited_certificate_pipelines: "Unlimited certificate pipelines",
|
||||||
common_deployment_plugins: "Common host, cloud platform, CDN, Baota, 1Panel deployment plugins",
|
common_deployment_plugins: "Common host, cloud platform, CDN, Baota, 1Panel deployment plugins",
|
||||||
email_webhook_notifications: "Email, webhook notification methods",
|
email_webhook_notifications: "Email, webhook notification methods",
|
||||||
|
free_privilege: "Unlimited certificate applications\nUnlimited domain count\nUnlimited certificate pipelines\nCommon host, cloud platform, CDN, Baota, 1Panel deployment plugins\nEmail, webhook notification methods",
|
||||||
|
|
||||||
professional_edition: "Professional Edition",
|
professional_edition: "Professional Edition",
|
||||||
open_source_support: "Open source requires your sponsorship support",
|
open_source_support: "Open source requires your sponsorship support",
|
||||||
@@ -60,6 +61,7 @@ export default {
|
|||||||
unlimited_site_certificate_monitoring: "Unlimited site certificate monitoring",
|
unlimited_site_certificate_monitoring: "Unlimited site certificate monitoring",
|
||||||
more_notification_methods: "More notification methods",
|
more_notification_methods: "More notification methods",
|
||||||
plugins_fully_open: "All plugins open, including Synology and more",
|
plugins_fully_open: "All plugins open, including Synology and more",
|
||||||
|
plus_privilege: "Access to VIP group, your requests will have priority\nUnlimited site certificate monitoring\nMore notification methods\nAll plugins open, including Synology and more",
|
||||||
click_to_get_7_day_trial: "Click to get 7-day trial",
|
click_to_get_7_day_trial: "Click to get 7-day trial",
|
||||||
years: "years",
|
years: "years",
|
||||||
afdian_support_vip: "Obtain the permanent professional version coupon",
|
afdian_support_vip: "Obtain the permanent professional version coupon",
|
||||||
@@ -73,6 +75,7 @@ export default {
|
|||||||
plugin_management: "Plugin management",
|
plugin_management: "Plugin management",
|
||||||
unlimited_multi_users: "Unlimited multi-users",
|
unlimited_multi_users: "Unlimited multi-users",
|
||||||
support_user_payment: "Supports user payments",
|
support_user_payment: "Supports user payments",
|
||||||
|
comm_privilege: "All professional edition privileges\nAllows commercial use, can modify logo and title\nData statistics\nPlugin management\nUnlimited multi-users\nSupports user payments",
|
||||||
contact_author_for_trial: "Buy It Now",
|
contact_author_for_trial: "Buy It Now",
|
||||||
activate: "Activate",
|
activate: "Activate",
|
||||||
get_pro_code_after_support: "Go to sponsoring",
|
get_pro_code_after_support: "Go to sponsoring",
|
||||||
|
|||||||
@@ -226,6 +226,8 @@ export default {
|
|||||||
projectJoin: "加入项目",
|
projectJoin: "加入项目",
|
||||||
currentProject: "当前项目",
|
currentProject: "当前项目",
|
||||||
projectMemberManager: "项目成员管理",
|
projectMemberManager: "项目成员管理",
|
||||||
|
domainMonitorSetting: "域名监控设置",
|
||||||
|
jobHistory: "监控执行记录",
|
||||||
},
|
},
|
||||||
certificateRepo: {
|
certificateRepo: {
|
||||||
title: "证书仓库",
|
title: "证书仓库",
|
||||||
|
|||||||
@@ -68,10 +68,40 @@ export default {
|
|||||||
dnsServerHelper: "使用自定义的域名解析服务器,如:1.1.1.1 , 支持多个",
|
dnsServerHelper: "使用自定义的域名解析服务器,如:1.1.1.1 , 支持多个",
|
||||||
certValidDays: "证书到期前天数",
|
certValidDays: "证书到期前天数",
|
||||||
certValidDaysHelper: "证书到期前多少天发送通知",
|
certValidDaysHelper: "证书到期前多少天发送通知",
|
||||||
|
domain: {
|
||||||
|
monitorSettings: "域名监控设置",
|
||||||
|
enabled: "启用域名监控",
|
||||||
|
enabledHelper: "启用后,监控“域名管理”中域名的过期时间,到期前通知提醒",
|
||||||
|
notificationChannel: "通知渠道",
|
||||||
|
setNotificationChannel: "设置通知渠道",
|
||||||
|
willExpireDays: "到期前天数",
|
||||||
|
willExpireDaysHelper: "域名有效期到期前多少天发送通知",
|
||||||
|
monitorCronSetting: "监控定时设置",
|
||||||
|
cronTrigger: "定时触发监控",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
cert: {
|
cert: {
|
||||||
expired: "已过期",
|
expired: "已过期",
|
||||||
expiring: "即将过期",
|
expiring: "即将过期",
|
||||||
noExpired: "未过期",
|
noExpired: "未过期",
|
||||||
},
|
},
|
||||||
|
history: {
|
||||||
|
title: "监控执行记录",
|
||||||
|
description: "站点证书、域名等监控任务的执行记录",
|
||||||
|
resultTitle: "状态",
|
||||||
|
contentTitle: "内容",
|
||||||
|
titleTitle: "标题",
|
||||||
|
jobTypeTitle: "任务类型",
|
||||||
|
startAtTitle: "开始时间",
|
||||||
|
endAtTitle: "结束时间",
|
||||||
|
jobResultTitle: "任务结果",
|
||||||
|
jobResult: {
|
||||||
|
done: "完成",
|
||||||
|
start: "开始",
|
||||||
|
},
|
||||||
|
jobType: {
|
||||||
|
domainExpirationCheck: "域名到期检查",
|
||||||
|
siteCertMonitor: "站点证书监控",
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ export default {
|
|||||||
unlimited_certificate_pipelines: "证书流水线数量无限制",
|
unlimited_certificate_pipelines: "证书流水线数量无限制",
|
||||||
common_deployment_plugins: "常用的主机、云平台、cdn、宝塔、1Panel等部署插件",
|
common_deployment_plugins: "常用的主机、云平台、cdn、宝塔、1Panel等部署插件",
|
||||||
email_webhook_notifications: "邮件、webhook通知方式",
|
email_webhook_notifications: "邮件、webhook通知方式",
|
||||||
|
free_privilege: "证书申请无限制\n域名数量无限制\n证书流水线数量无限制\n常用的主机、云平台、cdn、宝塔、1Panel等部署插件\n邮件、webhook通知方式",
|
||||||
|
|
||||||
professional_edition: "专业版",
|
professional_edition: "专业版",
|
||||||
open_source_support: "开源需要您的赞助支持,个人和企业内部使用",
|
open_source_support: "开源需要您的赞助支持,个人和企业内部使用",
|
||||||
@@ -60,6 +61,7 @@ export default {
|
|||||||
unlimited_site_certificate_monitoring: "站点证书监控无限制",
|
unlimited_site_certificate_monitoring: "站点证书监控无限制",
|
||||||
more_notification_methods: "更多通知方式",
|
more_notification_methods: "更多通知方式",
|
||||||
plugins_fully_open: "插件全开放,群晖等更多插件",
|
plugins_fully_open: "插件全开放,群晖等更多插件",
|
||||||
|
plus_privilege: "可加VIP群,您的需求将优先实现\n站点证书监控无限制\n更多通知方式\n插件全开放,群晖等更多插件\n企业模式,项目管理\n域名到期监控\n第三方登录,PassKey登录",
|
||||||
click_to_get_7_day_trial: "点击获取7天试用",
|
click_to_get_7_day_trial: "点击获取7天试用",
|
||||||
years: "年",
|
years: "年",
|
||||||
afdian_support_vip: "新用户开通永久专业版立享50优惠券",
|
afdian_support_vip: "新用户开通永久专业版立享50优惠券",
|
||||||
@@ -73,6 +75,7 @@ export default {
|
|||||||
plugin_management: "插件管理",
|
plugin_management: "插件管理",
|
||||||
unlimited_multi_users: "多用户无限制",
|
unlimited_multi_users: "多用户无限制",
|
||||||
support_user_payment: "支持用户支付(购买套餐,按流水线条数、域名数量、部署次数计费)",
|
support_user_payment: "支持用户支付(购买套餐,按流水线条数、域名数量、部署次数计费)",
|
||||||
|
comm_privilege: "拥有专业版所有特权\n允许商用,可修改logo、标题\n数据统计\n插件管理\n多用户无限制\n支持用户支付(购买套餐,按流水线条数、域名数量、部署次数计费)",
|
||||||
activate: "激活",
|
activate: "激活",
|
||||||
get_pro_code_after_support: "前往获取",
|
get_pro_code_after_support: "前往获取",
|
||||||
business_contact_author: "",
|
business_contact_author: "",
|
||||||
|
|||||||
@@ -241,6 +241,28 @@ export const certdResources = [
|
|||||||
isMenu: true,
|
isMenu: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: "certd.sysResources.domainMonitorSetting",
|
||||||
|
name: "DomainMonitorSetting",
|
||||||
|
path: "/certd/cert/domain/setting",
|
||||||
|
component: "/certd/cert/domain/setting/index.vue",
|
||||||
|
meta: {
|
||||||
|
icon: "ion:stopwatch-outline",
|
||||||
|
auth: true,
|
||||||
|
isMenu: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "certd.sysResources.jobHistory",
|
||||||
|
name: "JobHistory",
|
||||||
|
path: "/certd/monitor/history",
|
||||||
|
component: "/certd/monitor/history/index.vue",
|
||||||
|
meta: {
|
||||||
|
icon: "ion:barcode-outline",
|
||||||
|
auth: true,
|
||||||
|
isMenu: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: "certd.userSecurity",
|
title: "certd.userSecurity",
|
||||||
name: "UserSecurity",
|
name: "UserSecurity",
|
||||||
|
|||||||
@@ -21,7 +21,8 @@ import { defineComponent, reactive, ref, watch, inject } from "vue";
|
|||||||
import CertAccessModal from "./access/index.vue";
|
import CertAccessModal from "./access/index.vue";
|
||||||
import { createAccessApi } from "../api";
|
import { createAccessApi } from "../api";
|
||||||
import { message } from "ant-design-vue";
|
import { message } from "ant-design-vue";
|
||||||
|
import { useUserStore } from "/@/store/user";
|
||||||
|
import { useProjectStore } from "/@/store/project";
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "AccessSelector",
|
name: "AccessSelector",
|
||||||
components: { CertAccessModal },
|
components: { CertAccessModal },
|
||||||
@@ -71,11 +72,27 @@ export default defineComponent({
|
|||||||
emitValue(null);
|
emitValue(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const userStore = useUserStore();
|
||||||
|
const projectStore = useProjectStore();
|
||||||
|
|
||||||
async function emitValue(value) {
|
async function emitValue(value) {
|
||||||
if (pipeline && pipeline?.value && target?.value && pipeline.value.userId !== target.value.userId) {
|
const userId = userStore.userInfo.id;
|
||||||
message.error("对不起,您不能修改他人流水线的授权");
|
const isEnterprice = projectStore.isEnterprise;
|
||||||
return;
|
if (pipeline?.value) {
|
||||||
|
if (isEnterprice) {
|
||||||
|
const projectId = projectStore.currentProjectId;
|
||||||
|
if (pipeline?.value?.projectId !== projectId) {
|
||||||
|
message.error(`对不起,您不能修改其他项目流水线的授权`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (pipeline?.value && pipeline.value.userId !== userId) {
|
||||||
|
message.error(`对不起,您不能修改他人流水线的授权`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
selectedId.value = "";
|
selectedId.value = "";
|
||||||
target.value = null;
|
target.value = null;
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ import createCrudOptions from "../crud";
|
|||||||
import { addonProvide } from "../common";
|
import { addonProvide } from "../common";
|
||||||
import { useUserStore } from "/@/store/user";
|
import { useUserStore } from "/@/store/user";
|
||||||
import { useI18n } from "/src/locales";
|
import { useI18n } from "/src/locales";
|
||||||
|
import { useProjectStore } from "/@/store/project";
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
@@ -127,13 +128,24 @@ function clear() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
|
const projectStore = useProjectStore();
|
||||||
async function emitValue(value: any) {
|
async function emitValue(value: any) {
|
||||||
// target.value = optionsDictRef.dataMap[value];
|
// target.value = optionsDictRef.dataMap[value];
|
||||||
const userId = userStore.userInfo.id;
|
if (pipeline.value) {
|
||||||
if (pipeline?.value && pipeline.value.userId !== userId) {
|
const userId = userStore.userInfo.id;
|
||||||
message.error(`对不起,您不能修改他人流水线的${props.addonType}设置`);
|
const isEnterprice = projectStore.isEnterprise;
|
||||||
return;
|
if (isEnterprice) {
|
||||||
|
const projectId = projectStore.currentProjectId;
|
||||||
|
if (pipeline?.value?.projectId !== projectId) {
|
||||||
|
message.error(`对不起,您不能修改其他项目流水线的${props.addonType}设置`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (pipeline?.value && pipeline.value.userId !== userId) {
|
||||||
|
message.error(`对不起,您不能修改他人流水线的${props.addonType}设置`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
emit("change", value);
|
emit("change", value);
|
||||||
emit("update:modelValue", value);
|
emit("update:modelValue", value);
|
||||||
|
|||||||
@@ -128,6 +128,18 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||||||
}, 2000);
|
}, 2000);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
monitorSettingSave: {
|
||||||
|
show: hasActionPermission("write"),
|
||||||
|
title: "域名过期监控设置",
|
||||||
|
type: "primary",
|
||||||
|
icon: "ion:save-outline",
|
||||||
|
text: "域名过期监控设置",
|
||||||
|
click: async () => {
|
||||||
|
router.push({
|
||||||
|
path: "/certd/cert/domain/setting",
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
columns: {
|
columns: {
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
// @ts-ignore
|
||||||
|
import { request } from "/src/api/service";
|
||||||
|
const apiPrefix = "/cert/domain/setting";
|
||||||
|
export type UserDomainMonitorSetting = {
|
||||||
|
enabled?: boolean;
|
||||||
|
notificationId?: number;
|
||||||
|
cron?: string;
|
||||||
|
willExpireDays?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function DomainMonitorSettingsGet() {
|
||||||
|
const res = await request({
|
||||||
|
url: apiPrefix + "/get",
|
||||||
|
method: "post",
|
||||||
|
});
|
||||||
|
if (!res) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
return res as UserDomainMonitorSetting;
|
||||||
|
}
|
||||||
|
export async function DomainMonitorSettingsSave(data: UserDomainMonitorSetting) {
|
||||||
|
await request({
|
||||||
|
url: apiPrefix + "/save",
|
||||||
|
method: "post",
|
||||||
|
data: data,
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
<template>
|
||||||
|
<fs-page class="page-user-settings page-domain-monitor-setting">
|
||||||
|
<template #header>
|
||||||
|
<div class="title">{{ t("monitor.setting.domain.monitorSettings") }}</div>
|
||||||
|
</template>
|
||||||
|
<div class="user-settings-form settings-form">
|
||||||
|
<a-form :model="formState" name="basic" :label-col="{ span: 8 }" :wrapper-col="{ span: 16 }" autocomplete="off">
|
||||||
|
<a-form-item :label="t('monitor.setting.domain.enabled')" :name="['enabled']">
|
||||||
|
<div class="flex flex-baseline">
|
||||||
|
<a-switch v-model:checked="formState.enabled" :disabled="!settingsStore.isPlus" />
|
||||||
|
<vip-button class="ml-5" mode="button"></vip-button>
|
||||||
|
</div>
|
||||||
|
<div class="helper">{{ t("monitor.setting.domain.enabledHelper") }}</div>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item v-if="formState.enabled" :label="t('monitor.setting.domain.notificationChannel')" :name="['notificationId']">
|
||||||
|
<div class="flex">
|
||||||
|
<NotificationSelector v-model="formState.notificationId" />
|
||||||
|
</div>
|
||||||
|
<div class="helper">{{ t("monitor.setting.domain.setNotificationChannel") }}</div>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item v-if="formState.enabled" :label="t('monitor.setting.domain.willExpireDays')" :name="['willExpireDays']">
|
||||||
|
<div class="flex">
|
||||||
|
<a-input-number v-model:value="formState.willExpireDays" />
|
||||||
|
</div>
|
||||||
|
<div class="helper">{{ t("monitor.setting.domain.willExpireDaysHelper") }}</div>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item v-if="formState.enabled" :label="t('monitor.setting.domain.monitorCronSetting')" :name="['cron']">
|
||||||
|
<div class="flex flex-baseline">
|
||||||
|
<cron-editor v-model="formState.cron" :disabled="!settingsStore.isPlus" :allow-every-min="userStore.isAdmin" />
|
||||||
|
<vip-button class="ml-5" mode="button"></vip-button>
|
||||||
|
</div>
|
||||||
|
<div class="helper">{{ t("monitor.setting.domain.cronTrigger") }}</div>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label=" " :colon="false" :wrapper-col="{ span: 16 }">
|
||||||
|
<loading-button type="primary" html-type="button" :click="doSave" :disabled="!hasActionPermission('write')">{{ t("certd.save") }}</loading-button>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</div>
|
||||||
|
</fs-page>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="tsx">
|
||||||
|
import { notification } from "ant-design-vue";
|
||||||
|
import { merge } from "lodash-es";
|
||||||
|
import { reactive } from "vue";
|
||||||
|
import * as api from "./api";
|
||||||
|
import { UserDomainMonitorSetting } from "./api";
|
||||||
|
import { useUserStore } from "/@/store/user";
|
||||||
|
import { utils } from "/@/utils";
|
||||||
|
import NotificationSelector from "/@/views/certd/notification/notification-selector/index.vue";
|
||||||
|
import { useI18n } from "/src/locales";
|
||||||
|
import { useSettingStore } from "/src/store/settings";
|
||||||
|
import { useCrudPermission } from "/@/plugin/permission";
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
const settingsStore = useSettingStore();
|
||||||
|
const userStore = useUserStore();
|
||||||
|
defineOptions({
|
||||||
|
name: "DomainMonitorSetting",
|
||||||
|
});
|
||||||
|
|
||||||
|
const randomHour = Math.floor(Math.random() * 9);
|
||||||
|
const randomMin = Math.floor(Math.random() * 59);
|
||||||
|
const randomCron = `0 ${randomMin} ${randomHour} * * *`;
|
||||||
|
|
||||||
|
const formState = reactive<Partial<UserDomainMonitorSetting>>({
|
||||||
|
enabled: false,
|
||||||
|
notificationId: 0,
|
||||||
|
cron: randomCron,
|
||||||
|
willExpireDays: 30,
|
||||||
|
});
|
||||||
|
|
||||||
|
async function loadUserSettings() {
|
||||||
|
const data: any = await api.DomainMonitorSettingsGet();
|
||||||
|
merge(formState, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
const { hasActionPermission } = useCrudPermission({ permission: { isProjectPermission: true } });
|
||||||
|
|
||||||
|
loadUserSettings();
|
||||||
|
const doSave = async (form: any) => {
|
||||||
|
await utils.sleep(300);
|
||||||
|
await api.DomainMonitorSettingsSave({
|
||||||
|
...formState,
|
||||||
|
});
|
||||||
|
notification.success({
|
||||||
|
message: t("certd.saveSuccess"),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less">
|
||||||
|
.page-domain-monitor-setting {
|
||||||
|
.settings-form {
|
||||||
|
width: 700px;
|
||||||
|
margin: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
import { request } from "/src/api/service";
|
||||||
|
|
||||||
|
const apiPrefix = "/monitor/job-history";
|
||||||
|
|
||||||
|
export const jobHistoryApi = {
|
||||||
|
async GetList(query: any) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/page",
|
||||||
|
method: "post",
|
||||||
|
data: query,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
async DelObj(id: number) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/delete",
|
||||||
|
method: "post",
|
||||||
|
params: { id },
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
async BatchDelObj(ids: number[]) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/batchDelete",
|
||||||
|
method: "post",
|
||||||
|
data: { ids },
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
async GetObj(id: number) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/info",
|
||||||
|
method: "post",
|
||||||
|
params: { id },
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -0,0 +1,257 @@
|
|||||||
|
// @ts-ignore
|
||||||
|
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
|
||||||
|
import { message, Modal } from "ant-design-vue";
|
||||||
|
import { ref } from "vue";
|
||||||
|
import { createGroupDictRef } from "../../basic/group/api";
|
||||||
|
import { useDicts } from "../../dicts";
|
||||||
|
import { jobHistoryApi } from "./api";
|
||||||
|
import { useCrudPermission } from "/@/plugin/permission";
|
||||||
|
import { useProjectStore } from "/@/store/project";
|
||||||
|
import { useI18n } from "/src/locales";
|
||||||
|
export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
|
||||||
|
const { t } = useI18n();
|
||||||
|
const api = jobHistoryApi;
|
||||||
|
const { crudBinding } = crudExpose;
|
||||||
|
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
|
||||||
|
return await api.GetList(query);
|
||||||
|
};
|
||||||
|
const editRequest = async (req: EditReq) => {};
|
||||||
|
const delRequest = async (req: DelReq) => {
|
||||||
|
const { row } = req;
|
||||||
|
return await api.DelObj(row.id);
|
||||||
|
};
|
||||||
|
|
||||||
|
const addRequest = async (req: AddReq) => {};
|
||||||
|
const { myProjectDict } = useDicts();
|
||||||
|
|
||||||
|
const historyResultDict = dict({
|
||||||
|
data: [
|
||||||
|
{ label: t("monitor.history.jobResult.done"), value: "done", color: "green" },
|
||||||
|
{ label: t("monitor.history.jobResult.start"), value: "start", color: "blue" },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const jobTypeDict = dict({
|
||||||
|
data: [
|
||||||
|
{ label: t("monitor.history.jobType.domainExpirationCheck"), value: "domainExpirationCheck", color: "green" },
|
||||||
|
{ label: t("monitor.history.jobType.siteCertMonitor"), value: "siteCertMonitor", color: "blue" },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const selectedRowKeys = ref([]);
|
||||||
|
|
||||||
|
const handleBatchDelete = () => {
|
||||||
|
if (selectedRowKeys.value?.length > 0) {
|
||||||
|
Modal.confirm({
|
||||||
|
title: "确认",
|
||||||
|
content: `确定要批量删除这${selectedRowKeys.value.length}条记录吗`,
|
||||||
|
async onOk() {
|
||||||
|
await api.BatchDelObj(selectedRowKeys.value);
|
||||||
|
message.info("删除成功");
|
||||||
|
crudExpose.doRefresh();
|
||||||
|
selectedRowKeys.value = [];
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
message.error("请先勾选记录");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
context.handleBatchDelete = handleBatchDelete;
|
||||||
|
|
||||||
|
const GroupTypeSite = "site";
|
||||||
|
const groupDictRef = createGroupDictRef(GroupTypeSite);
|
||||||
|
|
||||||
|
function getDefaultGroupId() {
|
||||||
|
const searchFrom = crudExpose.getSearchValidatedFormData();
|
||||||
|
if (searchFrom.groupId) {
|
||||||
|
return searchFrom.groupId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const projectStore = useProjectStore();
|
||||||
|
const { hasActionPermission } = useCrudPermission({ permission: context.permission });
|
||||||
|
return {
|
||||||
|
id: "jobHistoryCrud",
|
||||||
|
crudOptions: {
|
||||||
|
request: {
|
||||||
|
pageRequest,
|
||||||
|
addRequest,
|
||||||
|
editRequest,
|
||||||
|
delRequest,
|
||||||
|
},
|
||||||
|
// tabs: {
|
||||||
|
// name: "groupId",
|
||||||
|
// show: true,
|
||||||
|
// },
|
||||||
|
toolbar: {
|
||||||
|
buttons: {
|
||||||
|
export: {
|
||||||
|
show: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
pagination: {
|
||||||
|
pageSizeOptions: ["10", "20", "50", "100", "200"],
|
||||||
|
},
|
||||||
|
settings: {
|
||||||
|
plugins: {
|
||||||
|
//这里使用行选择插件,生成行选择crudOptions配置,最终会与crudOptions合并
|
||||||
|
rowSelection: {
|
||||||
|
enabled: true,
|
||||||
|
props: {
|
||||||
|
multiple: true,
|
||||||
|
crossPage: false,
|
||||||
|
selectedRowKeys: () => {
|
||||||
|
return selectedRowKeys;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
form: {
|
||||||
|
labelCol: {
|
||||||
|
//固定label宽度
|
||||||
|
span: null,
|
||||||
|
style: {
|
||||||
|
width: "100px",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
col: {
|
||||||
|
span: 22,
|
||||||
|
},
|
||||||
|
wrapper: {
|
||||||
|
width: 600,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
actionbar: {
|
||||||
|
buttons: {
|
||||||
|
add: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rowHandle: {
|
||||||
|
fixed: "right",
|
||||||
|
width: 280,
|
||||||
|
buttons: {
|
||||||
|
edit: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// tabs: {
|
||||||
|
// name: "disabled",
|
||||||
|
// show: true,
|
||||||
|
// },
|
||||||
|
search: {
|
||||||
|
initialForm: {
|
||||||
|
...projectStore.getSearchForm(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
columns: {
|
||||||
|
id: {
|
||||||
|
title: "ID",
|
||||||
|
key: "id",
|
||||||
|
type: "number",
|
||||||
|
search: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
width: 80,
|
||||||
|
align: "center",
|
||||||
|
},
|
||||||
|
form: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
title: t("monitor.history.jobTypeTitle"),
|
||||||
|
search: {
|
||||||
|
show: true,
|
||||||
|
},
|
||||||
|
type: "dict-select",
|
||||||
|
dict: jobTypeDict,
|
||||||
|
form: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
width: 120,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
title: t("monitor.history.titleTitle"),
|
||||||
|
search: {
|
||||||
|
show: true,
|
||||||
|
},
|
||||||
|
type: "text",
|
||||||
|
column: {
|
||||||
|
width: 200,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
content: {
|
||||||
|
title: t("monitor.history.contentTitle"),
|
||||||
|
search: {
|
||||||
|
show: true,
|
||||||
|
},
|
||||||
|
type: "text",
|
||||||
|
column: {
|
||||||
|
width: 460,
|
||||||
|
ellipsis: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
result: {
|
||||||
|
title: t("monitor.history.resultTitle"),
|
||||||
|
search: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
type: "dict-select",
|
||||||
|
dict: historyResultDict,
|
||||||
|
form: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
width: 100,
|
||||||
|
align: "center",
|
||||||
|
sorter: true,
|
||||||
|
cellRender({ value, row }) {
|
||||||
|
return (
|
||||||
|
<a-tooltip title={row.error}>
|
||||||
|
<fs-values-format v-model={value} dict={historyResultDict}></fs-values-format>
|
||||||
|
</a-tooltip>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
startAt: {
|
||||||
|
title: t("monitor.history.startAtTitle"),
|
||||||
|
search: {
|
||||||
|
show: true,
|
||||||
|
},
|
||||||
|
type: "datetime",
|
||||||
|
column: {
|
||||||
|
width: 160,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
endAt: {
|
||||||
|
title: t("monitor.history.endAtTitle"),
|
||||||
|
search: {
|
||||||
|
show: true,
|
||||||
|
},
|
||||||
|
type: "datetime",
|
||||||
|
column: {
|
||||||
|
width: 160,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
projectId: {
|
||||||
|
title: t("certd.fields.projectName"),
|
||||||
|
type: "dict-select",
|
||||||
|
dict: myProjectDict,
|
||||||
|
form: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
<template>
|
||||||
|
<fs-page>
|
||||||
|
<template #header>
|
||||||
|
<div class="title flex items-center">
|
||||||
|
{{ t("monitor.history.title") }}
|
||||||
|
<div class="sub flex-1">
|
||||||
|
<div>
|
||||||
|
{{ t("monitor.history.description") }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<fs-crud ref="crudRef" v-bind="crudBinding">
|
||||||
|
<template #pagination-left>
|
||||||
|
<a-tooltip title="批量删除">
|
||||||
|
<fs-button icon="DeleteOutlined" @click="handleBatchDelete"></fs-button>
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
</fs-crud>
|
||||||
|
</fs-page>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { useFs } from "@fast-crud/fast-crud";
|
||||||
|
import { onActivated, onMounted } from "vue";
|
||||||
|
import createCrudOptions from "./crud";
|
||||||
|
import { useI18n } from "/src/locales";
|
||||||
|
const { t } = useI18n();
|
||||||
|
defineOptions({
|
||||||
|
name: "JobHistory",
|
||||||
|
});
|
||||||
|
const context: any = {
|
||||||
|
permission: {
|
||||||
|
isProjectPermission: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const { crudBinding, crudRef, crudExpose } = useFs({ createCrudOptions, context });
|
||||||
|
|
||||||
|
const handleBatchDelete = context.handleBatchDelete;
|
||||||
|
|
||||||
|
// 页面打开后获取列表数据
|
||||||
|
onMounted(() => {
|
||||||
|
crudExpose.doRefresh();
|
||||||
|
});
|
||||||
|
onActivated(() => {
|
||||||
|
crudExpose.doRefresh();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
+15
-4
@@ -42,6 +42,7 @@ import createCrudOptions from "../crud";
|
|||||||
import { notificationProvide } from "/@/views/certd/notification/common";
|
import { notificationProvide } from "/@/views/certd/notification/common";
|
||||||
import { useUserStore } from "/@/store/user";
|
import { useUserStore } from "/@/store/user";
|
||||||
import { useI18n } from "/src/locales";
|
import { useI18n } from "/src/locales";
|
||||||
|
import { useProjectStore } from "/@/store/project";
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
@@ -127,13 +128,23 @@ function clear() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
|
const projectStore = useProjectStore();
|
||||||
async function emitValue(value: any) {
|
async function emitValue(value: any) {
|
||||||
// target.value = optionsDictRef.dataMap[value];
|
// target.value = optionsDictRef.dataMap[value];
|
||||||
const userId = userStore.userInfo.id;
|
const userId = userStore.userInfo.id;
|
||||||
if (pipeline?.value && pipeline.value.userId !== userId) {
|
const isEnterprice = projectStore.isEnterprise;
|
||||||
message.error("对不起,您不能修改他人流水线的通知");
|
|
||||||
return;
|
if (isEnterprice) {
|
||||||
|
const projectId = projectStore.currentProjectId;
|
||||||
|
if (pipeline?.value?.projectId !== projectId) {
|
||||||
|
message.error("对不起,您不能修改其他项目流水线的通知");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (pipeline?.value?.userId !== userId) {
|
||||||
|
message.error("对不起,您不能修改他人流水线的通知");
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
emit("change", value);
|
emit("change", value);
|
||||||
emit("update:modelValue", value);
|
emit("update:modelValue", value);
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import yaml from "js-yaml";
|
|||||||
import { usePluginImport } from "./use-import";
|
import { usePluginImport } from "./use-import";
|
||||||
import { usePluginConfig } from "./use-config";
|
import { usePluginConfig } from "./use-config";
|
||||||
import { useSettingStore } from "/src/store/settings/index";
|
import { useSettingStore } from "/src/store/settings/index";
|
||||||
|
import { usePluginStore } from "/@/store/plugin";
|
||||||
|
|
||||||
export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
|
export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@@ -43,6 +44,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||||||
const { openConfigDialog } = usePluginConfig();
|
const { openConfigDialog } = usePluginConfig();
|
||||||
|
|
||||||
const settingStore = useSettingStore();
|
const settingStore = useSettingStore();
|
||||||
|
const pluginStore = usePluginStore();
|
||||||
return {
|
return {
|
||||||
crudOptions: {
|
crudOptions: {
|
||||||
settings: {
|
settings: {
|
||||||
@@ -83,6 +85,15 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
table: {
|
||||||
|
rowKey: "name",
|
||||||
|
remove: {
|
||||||
|
afterRemove: async context => {
|
||||||
|
await pluginStore.reload();
|
||||||
|
},
|
||||||
|
confirmMessage: "确定要删除吗?如果该插件已被使用,删除可能会导致流水线执行失败!",
|
||||||
|
},
|
||||||
|
},
|
||||||
rowHandle: {
|
rowHandle: {
|
||||||
show: true,
|
show: true,
|
||||||
minWidth: 200,
|
minWidth: 200,
|
||||||
@@ -142,9 +153,6 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
table: {
|
|
||||||
rowKey: "name",
|
|
||||||
},
|
|
||||||
tabs: {
|
tabs: {
|
||||||
name: "type",
|
name: "type",
|
||||||
show: true,
|
show: true,
|
||||||
|
|||||||
@@ -3,6 +3,21 @@
|
|||||||
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.39.9](https://github.com/certd/certd/compare/v1.39.8...v1.39.9) (2026-04-05)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复cn域名获取不到到期时间的问题 ([73b8e85](https://github.com/certd/certd/commit/73b8e859766097b5251fc4e5051593d686669eb2))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 腾讯云CLB大区增加台北 ([6b109d1](https://github.com/certd/certd/commit/6b109d172f0c7b6ce6ec164dc196d646a65f529f))
|
||||||
|
* 优化腾讯云CLB插件支持选择证书id ([c875971](https://github.com/certd/certd/commit/c875971b71dc6d392e56f0a7605281c40d9bb405))
|
||||||
|
* 支持域名到期时间监控通知 ([c6628e7](https://github.com/certd/certd/commit/c6628e7311d6c43c2a784581fb25ec37b29c168d))
|
||||||
|
* **monitor:** 支持查看监控执行记录 ([b5cc794](https://github.com/certd/certd/commit/b5cc794061c11b7200b669473c25c4bbfc944b61))
|
||||||
|
* **plugin-dnsmgr:** 添加彩虹DNS插件支持 ([af50344](https://github.com/certd/certd/commit/af503442b8298c5b89d11cf2ea351d62e66a609e))
|
||||||
|
* **spaceship:** 新增Spaceship DNS插件和授权模块 ([21aec77](https://github.com/certd/certd/commit/21aec77e5c3307b5973d4185baba33edcb28926f))
|
||||||
|
|
||||||
## [1.39.8](https://github.com/certd/certd/compare/v1.39.7...v1.39.8) (2026-03-31)
|
## [1.39.8](https://github.com/certd/certd/compare/v1.39.7...v1.39.8) (2026-03-31)
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
|
||||||
|
CREATE TABLE `cd_job_history`
|
||||||
|
(
|
||||||
|
`id` bigint PRIMARY KEY AUTO_INCREMENT NOT NULL,
|
||||||
|
`user_id` bigint NOT NULL,
|
||||||
|
`project_id` bigint ,
|
||||||
|
`type` varchar(100) NOT NULL,
|
||||||
|
`title` varchar(512) NOT NULL,
|
||||||
|
`related_id` varchar(100),
|
||||||
|
`result` varchar(100) NOT NULL,
|
||||||
|
`content` longtext ,
|
||||||
|
`start_at` bigint NOT NULL,
|
||||||
|
`end_at` bigint ,
|
||||||
|
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CREATE INDEX `index_job_history_user_id` ON `cd_job_history` (`user_id`);
|
||||||
|
CREATE INDEX `index_job_history_project_id` ON `cd_job_history` (`project_id`);
|
||||||
|
CREATE INDEX `index_job_history_type` ON `cd_job_history` (`type`);
|
||||||
|
|
||||||
|
ALTER TABLE `cd_job_history` ENGINE = InnoDB;
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
|
||||||
|
CREATE TABLE "cd_job_history"
|
||||||
|
(
|
||||||
|
"id" bigint PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY NOT NULL,
|
||||||
|
"user_id" bigint NOT NULL,
|
||||||
|
"project_id" bigint ,
|
||||||
|
"type" varchar(100) NOT NULL,
|
||||||
|
"title" varchar(512) NOT NULL,
|
||||||
|
"related_id" varchar(100),
|
||||||
|
"result" varchar(100) NOT NULL,
|
||||||
|
"content" text ,
|
||||||
|
"start_at" bigint NOT NULL,
|
||||||
|
"end_at" bigint ,
|
||||||
|
"create_time" timestamp NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||||
|
"update_time" timestamp NOT NULL DEFAULT (CURRENT_TIMESTAMP)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CREATE INDEX "index_job_history_user_id" ON "cd_job_history" ("user_id");
|
||||||
|
CREATE INDEX "index_job_history_project_id" ON "cd_job_history" ("project_id");
|
||||||
|
CREATE INDEX "index_job_history_type" ON "cd_job_history" ("type");
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
|
||||||
|
CREATE TABLE "cd_job_history"
|
||||||
|
(
|
||||||
|
"id" integer PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||||
|
"user_id" integer NOT NULL,
|
||||||
|
"project_id" integer ,
|
||||||
|
"type" varchar(100) NOT NULL,
|
||||||
|
"title" varchar(512) NOT NULL,
|
||||||
|
"related_id" varchar(100),
|
||||||
|
"result" varchar(100) NOT NULL,
|
||||||
|
"content" text ,
|
||||||
|
"start_at" integer NOT NULL,
|
||||||
|
"end_at" integer ,
|
||||||
|
"create_time" datetime NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||||
|
"update_time" datetime NOT NULL DEFAULT (CURRENT_TIMESTAMP)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CREATE INDEX "index_job_history_user_id" ON "cd_job_history" ("user_id");
|
||||||
|
CREATE INDEX "index_job_history_project_id" ON "cd_job_history" ("project_id");
|
||||||
|
CREATE INDEX "index_job_history_type" ON "cd_job_history" ("type");
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
name: dnsmgr
|
||||||
|
title: 彩虹DNS
|
||||||
|
icon: clarity:plugin-line
|
||||||
|
desc: 彩虹DNS管理系统授权
|
||||||
|
input:
|
||||||
|
endpoint:
|
||||||
|
title: 系统地址
|
||||||
|
component:
|
||||||
|
name: a-input
|
||||||
|
allowClear: true
|
||||||
|
placeholder: https://dnsmgr.example.com
|
||||||
|
required: true
|
||||||
|
uid:
|
||||||
|
title: 用户ID
|
||||||
|
component:
|
||||||
|
name: a-input
|
||||||
|
allowClear: true
|
||||||
|
placeholder: '123456'
|
||||||
|
required: true
|
||||||
|
key:
|
||||||
|
title: API密钥
|
||||||
|
required: true
|
||||||
|
encrypt: true
|
||||||
|
testRequest:
|
||||||
|
title: 测试
|
||||||
|
component:
|
||||||
|
name: api-test
|
||||||
|
action: TestRequest
|
||||||
|
helper: 点击测试接口是否正常
|
||||||
|
pluginType: access
|
||||||
|
type: builtIn
|
||||||
|
scriptFilePath: /plugins/plugin-dnsmgr/access.js
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
name: spaceship
|
||||||
|
title: Spaceship.com 授权
|
||||||
|
icon: clarity:plugin-line
|
||||||
|
desc: Spaceship.com API 授权插件
|
||||||
|
input:
|
||||||
|
apiKey:
|
||||||
|
title: API Key
|
||||||
|
component:
|
||||||
|
placeholder: 请输入 API Key
|
||||||
|
required: true
|
||||||
|
encrypt: true
|
||||||
|
helper: 前往 [获取 API Key](https://www.spaceship.com/application/api-manager/)
|
||||||
|
apiSecret:
|
||||||
|
title: API Secret
|
||||||
|
component:
|
||||||
|
name: a-input-password
|
||||||
|
vModel: value
|
||||||
|
placeholder: 请输入 API Secret
|
||||||
|
required: true
|
||||||
|
encrypt: true
|
||||||
|
testRequest:
|
||||||
|
title: 测试
|
||||||
|
component:
|
||||||
|
name: api-test
|
||||||
|
action: TestRequest
|
||||||
|
helper: 测试 API 连接是否正常
|
||||||
|
pluginType: access
|
||||||
|
type: builtIn
|
||||||
|
scriptFilePath: /plugins/plugin-spaceship/access.js
|
||||||
@@ -8,6 +8,24 @@ icon: svg:icon-tencentcloud
|
|||||||
group: tencent
|
group: tencent
|
||||||
desc: 暂时只支持单向认证证书,暂时只支持通用负载均衡
|
desc: 暂时只支持单向认证证书,暂时只支持通用负载均衡
|
||||||
input:
|
input:
|
||||||
|
cert:
|
||||||
|
title: 域名证书
|
||||||
|
helper: 请选择前置任务输出的域名证书
|
||||||
|
component:
|
||||||
|
name: output-selector
|
||||||
|
from:
|
||||||
|
- ':cert:'
|
||||||
|
- UploadCertToTencent
|
||||||
|
required: true
|
||||||
|
order: 0
|
||||||
|
accessId:
|
||||||
|
title: Access提供者
|
||||||
|
helper: access授权
|
||||||
|
component:
|
||||||
|
name: access-selector
|
||||||
|
type: tencent
|
||||||
|
required: true
|
||||||
|
order: 0
|
||||||
region:
|
region:
|
||||||
title: 大区
|
title: 大区
|
||||||
component:
|
component:
|
||||||
@@ -33,14 +51,12 @@ input:
|
|||||||
- value: na-siliconvalley
|
- value: na-siliconvalley
|
||||||
- value: na-toronto
|
- value: na-toronto
|
||||||
- value: sa-saopaulo
|
- value: sa-saopaulo
|
||||||
|
- value: ap-taipei
|
||||||
|
helper: 如果列表中没有,您可以手动输入
|
||||||
required: true
|
required: true
|
||||||
order: 0
|
order: 0
|
||||||
certName:
|
|
||||||
title: 证书名称前缀
|
|
||||||
order: 0
|
|
||||||
loadBalancerId:
|
loadBalancerId:
|
||||||
title: 负载均衡ID
|
title: 负载均衡ID
|
||||||
helper: 如果没有配置,则根据域名匹配负载均衡下的监听器(根据域名匹配时暂时只支持前100个)
|
|
||||||
required: true
|
required: true
|
||||||
order: 0
|
order: 0
|
||||||
listenerId:
|
listenerId:
|
||||||
@@ -57,22 +73,8 @@ input:
|
|||||||
mode: tags
|
mode: tags
|
||||||
helper: 如果开启了sni,则此项必须填写,未开启,则不要填写
|
helper: 如果开启了sni,则此项必须填写,未开启,则不要填写
|
||||||
order: 0
|
order: 0
|
||||||
cert:
|
certName:
|
||||||
title: 域名证书
|
title: 证书名称前缀
|
||||||
helper: 请选择前置任务输出的域名证书
|
|
||||||
component:
|
|
||||||
name: output-selector
|
|
||||||
from:
|
|
||||||
- ':cert:'
|
|
||||||
required: true
|
|
||||||
order: 0
|
|
||||||
accessId:
|
|
||||||
title: Access提供者
|
|
||||||
helper: access授权
|
|
||||||
component:
|
|
||||||
name: access-selector
|
|
||||||
type: tencent
|
|
||||||
required: true
|
|
||||||
order: 0
|
order: 0
|
||||||
output: {}
|
output: {}
|
||||||
pluginType: deploy
|
pluginType: deploy
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
name: dnsmgr
|
||||||
|
title: 彩虹DNS
|
||||||
|
desc: 彩虹DNS管理系统
|
||||||
|
icon: clarity:plugin-line
|
||||||
|
accessType: dnsmgr
|
||||||
|
order: 99
|
||||||
|
pluginType: dnsProvider
|
||||||
|
type: builtIn
|
||||||
|
scriptFilePath: /plugins/plugin-dnsmgr/dns-provider.js
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
name: spaceship
|
||||||
|
title: Spaceship
|
||||||
|
desc: Spaceship 域名解析
|
||||||
|
icon: clarity:plugin-line
|
||||||
|
accessType: spaceship
|
||||||
|
order: 99
|
||||||
|
pluginType: dnsProvider
|
||||||
|
type: builtIn
|
||||||
|
scriptFilePath: /plugins/plugin-spaceship/dns-provider.js
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@certd/ui-server",
|
"name": "@certd/ui-server",
|
||||||
"version": "1.39.8",
|
"version": "1.39.9",
|
||||||
"description": "fast-server base midway",
|
"description": "fast-server base midway",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
@@ -50,20 +50,20 @@
|
|||||||
"@aws-sdk/client-route-53": "^3.964.0",
|
"@aws-sdk/client-route-53": "^3.964.0",
|
||||||
"@aws-sdk/client-s3": "^3.964.0",
|
"@aws-sdk/client-s3": "^3.964.0",
|
||||||
"@aws-sdk/client-sts": "^3.990.0",
|
"@aws-sdk/client-sts": "^3.990.0",
|
||||||
"@certd/acme-client": "^1.39.8",
|
"@certd/acme-client": "^1.39.9",
|
||||||
"@certd/basic": "^1.39.8",
|
"@certd/basic": "^1.39.9",
|
||||||
"@certd/commercial-core": "^1.39.8",
|
"@certd/commercial-core": "^1.39.9",
|
||||||
"@certd/cv4pve-api-javascript": "^8.4.2",
|
"@certd/cv4pve-api-javascript": "^8.4.2",
|
||||||
"@certd/jdcloud": "^1.39.8",
|
"@certd/jdcloud": "^1.39.9",
|
||||||
"@certd/lib-huawei": "^1.39.8",
|
"@certd/lib-huawei": "^1.39.9",
|
||||||
"@certd/lib-k8s": "^1.39.8",
|
"@certd/lib-k8s": "^1.39.9",
|
||||||
"@certd/lib-server": "^1.39.8",
|
"@certd/lib-server": "^1.39.9",
|
||||||
"@certd/midway-flyway-js": "^1.39.8",
|
"@certd/midway-flyway-js": "^1.39.9",
|
||||||
"@certd/pipeline": "^1.39.8",
|
"@certd/pipeline": "^1.39.9",
|
||||||
"@certd/plugin-cert": "^1.39.8",
|
"@certd/plugin-cert": "^1.39.9",
|
||||||
"@certd/plugin-lib": "^1.39.8",
|
"@certd/plugin-lib": "^1.39.9",
|
||||||
"@certd/plugin-plus": "^1.39.8",
|
"@certd/plugin-plus": "^1.39.9",
|
||||||
"@certd/plus-core": "^1.39.8",
|
"@certd/plus-core": "^1.39.9",
|
||||||
"@google-cloud/publicca": "^1.3.0",
|
"@google-cloud/publicca": "^1.3.0",
|
||||||
"@huaweicloud/huaweicloud-sdk-cdn": "^3.1.185",
|
"@huaweicloud/huaweicloud-sdk-cdn": "^3.1.185",
|
||||||
"@huaweicloud/huaweicloud-sdk-core": "^3.1.185",
|
"@huaweicloud/huaweicloud-sdk-core": "^3.1.185",
|
||||||
@@ -141,6 +141,7 @@
|
|||||||
"typeorm": "^0.3.20",
|
"typeorm": "^0.3.20",
|
||||||
"uuid": "^10.0.0",
|
"uuid": "^10.0.0",
|
||||||
"wechatpay-node-v3": "^2.2.1",
|
"wechatpay-node-v3": "^2.2.1",
|
||||||
|
"whoiser": "2.0.0-beta.10",
|
||||||
"xml2js": "^0.6.2"
|
"xml2js": "^0.6.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@@ -58,7 +58,8 @@ export class PluginController extends CrudController<PluginService> {
|
|||||||
|
|
||||||
@Post('/delete', { description: 'sys:settings:edit' })
|
@Post('/delete', { description: 'sys:settings:edit' })
|
||||||
async delete(@Query('id') id: number) {
|
async delete(@Query('id') id: number) {
|
||||||
return super.deleteByIds([id]);
|
const res = await this.service.deleteByIds([id]);
|
||||||
|
return this.ok(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post('/deleteByIds', { description: 'sys:settings:edit' })
|
@Post('/deleteByIds', { description: 'sys:settings:edit' })
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ export class DomainController extends CrudController<DomainService> {
|
|||||||
|
|
||||||
@Post('/page', { description: Constants.per.authOnly, summary: "查询域名分页列表" })
|
@Post('/page', { description: Constants.per.authOnly, summary: "查询域名分页列表" })
|
||||||
async page(@Body(ALL) body: any) {
|
async page(@Body(ALL) body: any) {
|
||||||
const {projectId,userId} = await this.getProjectUserIdRead();
|
const { projectId, userId } = await this.getProjectUserIdRead();
|
||||||
body.query = body.query ?? {};
|
body.query = body.query ?? {};
|
||||||
body.query.projectId = projectId;
|
body.query.projectId = projectId;
|
||||||
body.query.userId = userId;
|
body.query.userId = userId;
|
||||||
@@ -44,7 +44,7 @@ export class DomainController extends CrudController<DomainService> {
|
|||||||
|
|
||||||
@Post('/list', { description: Constants.per.authOnly, summary: "查询域名列表" })
|
@Post('/list', { description: Constants.per.authOnly, summary: "查询域名列表" })
|
||||||
async list(@Body(ALL) body: any) {
|
async list(@Body(ALL) body: any) {
|
||||||
const {projectId,userId} = await this.getProjectUserIdRead();
|
const { projectId, userId } = await this.getProjectUserIdRead();
|
||||||
body.query = body.query ?? {};
|
body.query = body.query ?? {};
|
||||||
body.query.projectId = projectId;
|
body.query.projectId = projectId;
|
||||||
body.query.userId = userId;
|
body.query.userId = userId;
|
||||||
@@ -54,7 +54,7 @@ export class DomainController extends CrudController<DomainService> {
|
|||||||
|
|
||||||
@Post('/add', { description: Constants.per.authOnly, summary: "添加域名" })
|
@Post('/add', { description: Constants.per.authOnly, summary: "添加域名" })
|
||||||
async add(@Body(ALL) bean: any) {
|
async add(@Body(ALL) bean: any) {
|
||||||
const {projectId,userId} = await this.getProjectUserIdRead();
|
const { projectId, userId } = await this.getProjectUserIdRead();
|
||||||
bean.projectId = projectId;
|
bean.projectId = projectId;
|
||||||
bean.userId = userId;
|
bean.userId = userId;
|
||||||
return super.add(bean);
|
return super.add(bean);
|
||||||
@@ -82,7 +82,7 @@ export class DomainController extends CrudController<DomainService> {
|
|||||||
|
|
||||||
@Post('/deleteByIds', { description: Constants.per.authOnly, summary: "批量删除域名" })
|
@Post('/deleteByIds', { description: Constants.per.authOnly, summary: "批量删除域名" })
|
||||||
async deleteByIds(@Body(ALL) body: any) {
|
async deleteByIds(@Body(ALL) body: any) {
|
||||||
const {projectId,userId} = await this.getProjectUserIdRead();
|
const { projectId, userId } = await this.getProjectUserIdRead();
|
||||||
await this.service.delete(body.ids, {
|
await this.service.delete(body.ids, {
|
||||||
userId: userId,
|
userId: userId,
|
||||||
projectId: projectId,
|
projectId: projectId,
|
||||||
@@ -94,10 +94,10 @@ export class DomainController extends CrudController<DomainService> {
|
|||||||
@Post('/import/start', { description: Constants.per.authOnly, summary: "开始域名导入任务" })
|
@Post('/import/start', { description: Constants.per.authOnly, summary: "开始域名导入任务" })
|
||||||
async importStart(@Body(ALL) body: any) {
|
async importStart(@Body(ALL) body: any) {
|
||||||
checkPlus();
|
checkPlus();
|
||||||
const {projectId,userId} = await this.getProjectUserIdRead();
|
const { projectId, userId } = await this.getProjectUserIdRead();
|
||||||
const { key } = body;
|
const { key } = body;
|
||||||
const req = {
|
const req = {
|
||||||
key,
|
key,
|
||||||
userId: userId,
|
userId: userId,
|
||||||
projectId: projectId,
|
projectId: projectId,
|
||||||
}
|
}
|
||||||
@@ -107,7 +107,7 @@ export class DomainController extends CrudController<DomainService> {
|
|||||||
|
|
||||||
@Post('/import/status', { description: Constants.per.authOnly, summary: "查询域名导入任务状态" })
|
@Post('/import/status', { description: Constants.per.authOnly, summary: "查询域名导入任务状态" })
|
||||||
async importStatus() {
|
async importStatus() {
|
||||||
const {projectId,userId} = await this.getProjectUserIdRead();
|
const { projectId, userId } = await this.getProjectUserIdRead();
|
||||||
const req = {
|
const req = {
|
||||||
userId: userId,
|
userId: userId,
|
||||||
projectId: projectId,
|
projectId: projectId,
|
||||||
@@ -119,7 +119,7 @@ export class DomainController extends CrudController<DomainService> {
|
|||||||
|
|
||||||
@Post('/import/delete', { description: Constants.per.authOnly, summary: "删除域名导入任务" })
|
@Post('/import/delete', { description: Constants.per.authOnly, summary: "删除域名导入任务" })
|
||||||
async importDelete(@Body(ALL) body: any) {
|
async importDelete(@Body(ALL) body: any) {
|
||||||
const {projectId,userId} = await this.getProjectUserIdRead();
|
const { projectId, userId } = await this.getProjectUserIdRead();
|
||||||
const { key } = body;
|
const { key } = body;
|
||||||
const req = {
|
const req = {
|
||||||
userId: userId,
|
userId: userId,
|
||||||
@@ -133,12 +133,12 @@ export class DomainController extends CrudController<DomainService> {
|
|||||||
@Post('/import/save', { description: Constants.per.authOnly, summary: "保存域名导入任务" })
|
@Post('/import/save', { description: Constants.per.authOnly, summary: "保存域名导入任务" })
|
||||||
async importSave(@Body(ALL) body: any) {
|
async importSave(@Body(ALL) body: any) {
|
||||||
checkPlus();
|
checkPlus();
|
||||||
const {projectId,userId} = await this.getProjectUserIdRead();
|
const { projectId, userId } = await this.getProjectUserIdRead();
|
||||||
const { dnsProviderType, dnsProviderAccessId, key } = body;
|
const { dnsProviderType, dnsProviderAccessId, key } = body;
|
||||||
const req = {
|
const req = {
|
||||||
userId: userId,
|
userId: userId,
|
||||||
projectId: projectId,
|
projectId: projectId,
|
||||||
dnsProviderType, dnsProviderAccessId, key
|
dnsProviderType, dnsProviderAccessId, key
|
||||||
}
|
}
|
||||||
const item = await this.service.saveDomainImportTask(req);
|
const item = await this.service.saveDomainImportTask(req);
|
||||||
return this.ok(item);
|
return this.ok(item);
|
||||||
@@ -147,7 +147,7 @@ export class DomainController extends CrudController<DomainService> {
|
|||||||
|
|
||||||
@Post('/sync/expiration/start', { description: Constants.per.authOnly, summary: "开始同步域名过期时间任务" })
|
@Post('/sync/expiration/start', { description: Constants.per.authOnly, summary: "开始同步域名过期时间任务" })
|
||||||
async syncExpirationStart(@Body(ALL) body: any) {
|
async syncExpirationStart(@Body(ALL) body: any) {
|
||||||
const {projectId,userId} = await this.getProjectUserIdRead();
|
const { projectId, userId } = await this.getProjectUserIdRead();
|
||||||
await this.service.startSyncExpirationTask({
|
await this.service.startSyncExpirationTask({
|
||||||
userId: userId,
|
userId: userId,
|
||||||
projectId: projectId,
|
projectId: projectId,
|
||||||
@@ -156,7 +156,7 @@ export class DomainController extends CrudController<DomainService> {
|
|||||||
}
|
}
|
||||||
@Post('/sync/expiration/status', { description: Constants.per.authOnly, summary: "查询同步域名过期时间任务状态" })
|
@Post('/sync/expiration/status', { description: Constants.per.authOnly, summary: "查询同步域名过期时间任务状态" })
|
||||||
async syncExpirationStatus(@Body(ALL) body: any) {
|
async syncExpirationStatus(@Body(ALL) body: any) {
|
||||||
const {projectId,userId} = await this.getProjectUserIdRead();
|
const { projectId, userId } = await this.getProjectUserIdRead();
|
||||||
const status = await this.service.getSyncExpirationTaskStatus({
|
const status = await this.service.getSyncExpirationTaskStatus({
|
||||||
userId: userId,
|
userId: userId,
|
||||||
projectId: projectId,
|
projectId: projectId,
|
||||||
@@ -165,4 +165,26 @@ export class DomainController extends CrudController<DomainService> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Post('/setting/save', { description: Constants.per.authOnly, summary: "保存域名监控设置" })
|
||||||
|
async settingSave(@Body(ALL) body: any) {
|
||||||
|
const { projectId, userId } = await this.getProjectUserIdWrite();
|
||||||
|
await this.service.monitorSettingSave({
|
||||||
|
userId: userId,
|
||||||
|
projectId: projectId,
|
||||||
|
setting: {...body},
|
||||||
|
})
|
||||||
|
return this.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post('/setting/get', { description: Constants.per.authOnly, summary: "查询域名监控设置" })
|
||||||
|
async settingGet() {
|
||||||
|
const { projectId, userId } = await this.getProjectUserIdRead();
|
||||||
|
const setting = await this.service.monitorSettingGet({
|
||||||
|
userId: userId,
|
||||||
|
projectId: projectId,
|
||||||
|
})
|
||||||
|
return this.ok(setting);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,65 @@
|
|||||||
|
import { Constants, CrudController } from "@certd/lib-server";
|
||||||
|
import { ALL, Body, Controller, Inject, Post, Provide, Query } from "@midwayjs/core";
|
||||||
|
import { ApiTags } from "@midwayjs/swagger";
|
||||||
|
import { SiteInfoService } from "../../../modules/monitor/index.js";
|
||||||
|
import { JobHistoryService } from "../../../modules/monitor/service/job-history-service.js";
|
||||||
|
import { AuthService } from "../../../modules/sys/authority/service/auth-service.js";
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
@Provide()
|
||||||
|
@Controller('/api/monitor/job-history')
|
||||||
|
@ApiTags(['monitor'])
|
||||||
|
export class JobHistoryController extends CrudController<JobHistoryService> {
|
||||||
|
@Inject()
|
||||||
|
service: JobHistoryService;
|
||||||
|
@Inject()
|
||||||
|
authService: AuthService;
|
||||||
|
@Inject()
|
||||||
|
siteInfoService: SiteInfoService;
|
||||||
|
|
||||||
|
getService(): JobHistoryService {
|
||||||
|
return this.service;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post('/page', { description: Constants.per.authOnly, summary: "查询监控运行历史分页列表" })
|
||||||
|
async page(@Body(ALL) body: any) {
|
||||||
|
const { projectId, userId } = await this.getProjectUserIdRead()
|
||||||
|
body.query = body.query ?? {};
|
||||||
|
body.query.userId = userId;
|
||||||
|
body.query.projectId = projectId
|
||||||
|
const res = await this.service.page({
|
||||||
|
query: body.query,
|
||||||
|
page: body.page,
|
||||||
|
sort: body.sort,
|
||||||
|
});
|
||||||
|
return this.ok(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post('/list', { description: Constants.per.authOnly, summary: "查询监控运行历史列表" })
|
||||||
|
async list(@Body(ALL) body: any) {
|
||||||
|
body.query = body.query ?? {};
|
||||||
|
const { projectId, userId } = await this.getProjectUserIdRead()
|
||||||
|
body.query.userId = userId;
|
||||||
|
body.query.projectId = projectId
|
||||||
|
return await super.list(body);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post('/info', { description: Constants.per.authOnly, summary: "查询监控运行历史详情" })
|
||||||
|
async info(@Query('id') id: number) {
|
||||||
|
await this.checkOwner(this.service,id,"read");
|
||||||
|
return await super.info(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post('/delete', { description: Constants.per.authOnly, summary: "删除监控运行历史" })
|
||||||
|
async delete(@Query('id') id: number) {
|
||||||
|
await this.checkOwner(this.service,id,"write");
|
||||||
|
return await super.delete(id);
|
||||||
|
}
|
||||||
|
@Post('/batchDelete', { description: Constants.per.authOnly, summary: "批量删除监控运行历史" })
|
||||||
|
async batchDelete(@Body('ids') ids: number[]) {
|
||||||
|
const { projectId, userId } = await this.getProjectUserIdWrite()
|
||||||
|
await this.service.batchDelete(ids,userId,projectId);
|
||||||
|
return this.ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -67,6 +67,7 @@ export class AutoCRegisterCron {
|
|||||||
await this.registerUserExpireCheckCron();
|
await this.registerUserExpireCheckCron();
|
||||||
|
|
||||||
await this.registerDomainExpireCheckCron();
|
await this.registerDomainExpireCheckCron();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async registerSiteMonitorCron() {
|
async registerSiteMonitorCron() {
|
||||||
@@ -211,11 +212,11 @@ export class AutoCRegisterCron {
|
|||||||
if (!isPlus()){
|
if (!isPlus()){
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// 添加域名即将到期检查任务
|
// 添加域名即将到期同步任务
|
||||||
const randomWeek = Math.floor(Math.random() * 7) + 1
|
const randomWeek = Math.floor(Math.random() * 7) + 1
|
||||||
const randomHour = Math.floor(Math.random() * 24)
|
const randomHour = Math.floor(Math.random() * 24)
|
||||||
const randomMinute = Math.floor(Math.random() * 60)
|
const randomMinute = Math.floor(Math.random() * 60)
|
||||||
logger.info(`注册域名注册过期时间检查任务,每周${randomWeek} ${randomHour}:${randomMinute}检查一次`)
|
logger.info(`注册域名注册过期时间同步任务,每周${randomWeek} ${randomHour}:${randomMinute}检查一次`)
|
||||||
this.cron.register({
|
this.cron.register({
|
||||||
name: 'domain-expire-check',
|
name: 'domain-expire-check',
|
||||||
cron: `0 ${randomMinute} ${randomHour} ? * ${randomWeek}`, // 每周随机一天检查一次
|
cron: `0 ${randomMinute} ${randomHour} ? * ${randomWeek}`, // 每周随机一天检查一次
|
||||||
|
|||||||
@@ -1,20 +1,24 @@
|
|||||||
import { http, logger, utils } from '@certd/basic';
|
import { http, logger, utils } from '@certd/basic';
|
||||||
import { AccessService, BaseService } from '@certd/lib-server';
|
import { AccessService, BaseService, isEnterprise } from '@certd/lib-server';
|
||||||
import { doPageTurn, Pager, PageRes } from '@certd/pipeline';
|
import { doPageTurn, Pager, PageRes } from '@certd/pipeline';
|
||||||
import { DomainVerifiers } from "@certd/plugin-cert";
|
import { DomainVerifiers } from "@certd/plugin-cert";
|
||||||
import { createDnsProvider, dnsProviderRegistry, DomainParser, parseDomainByPsl } from "@certd/plugin-lib";
|
import { createDnsProvider, dnsProviderRegistry, DomainParser } from "@certd/plugin-lib";
|
||||||
import { Inject, Provide, Scope, ScopeEnum } from '@midwayjs/core';
|
import { Inject, Provide, Scope, ScopeEnum } from '@midwayjs/core';
|
||||||
import { InjectEntityModel } from '@midwayjs/typeorm';
|
import { InjectEntityModel } from '@midwayjs/typeorm';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import { In, Not, Repository } from 'typeorm';
|
import { merge } from 'lodash-es';
|
||||||
|
import { In, LessThan, Not, Repository } from 'typeorm';
|
||||||
import { BackTask, taskExecutor } from '../../basic/service/task-executor.js';
|
import { BackTask, taskExecutor } from '../../basic/service/task-executor.js';
|
||||||
import { CnameRecordEntity } from "../../cname/entity/cname-record.js";
|
import { CnameRecordEntity } from "../../cname/entity/cname-record.js";
|
||||||
import { CnameRecordService } from '../../cname/service/cname-record-service.js';
|
import { CnameRecordService } from '../../cname/service/cname-record-service.js';
|
||||||
import { UserDomainImportSetting } from '../../mine/service/models.js';
|
import { Cron } from '../../cron/cron.js';
|
||||||
|
import { UserDomainImportSetting, UserDomainMonitorSetting } from '../../mine/service/models.js';
|
||||||
import { UserSettingsService } from '../../mine/service/user-settings-service.js';
|
import { UserSettingsService } from '../../mine/service/user-settings-service.js';
|
||||||
|
import { JobHistoryService } from '../../monitor/service/job-history-service.js';
|
||||||
import { TaskServiceBuilder } from '../../pipeline/service/getter/task-service-getter.js';
|
import { TaskServiceBuilder } from '../../pipeline/service/getter/task-service-getter.js';
|
||||||
import { SubDomainService } from "../../pipeline/service/sub-domain-service.js";
|
import { SubDomainService } from "../../pipeline/service/sub-domain-service.js";
|
||||||
import { DomainEntity } from '../entity/domain.js';
|
import { DomainEntity } from '../entity/domain.js';
|
||||||
|
import { TldClient } from './tld-client.js';
|
||||||
|
|
||||||
export interface SyncFromProviderReq {
|
export interface SyncFromProviderReq {
|
||||||
userId: number;
|
userId: number;
|
||||||
@@ -27,6 +31,8 @@ export interface SyncFromProviderReq {
|
|||||||
const DOMAIN_IMPORT_TASK_TYPE = 'domainImportTask'
|
const DOMAIN_IMPORT_TASK_TYPE = 'domainImportTask'
|
||||||
const DOMAIN_EXPIRE_TASK_TYPE = 'domainExpirationSyncTask'
|
const DOMAIN_EXPIRE_TASK_TYPE = 'domainExpirationSyncTask'
|
||||||
|
|
||||||
|
const DOMAIN_EXPIRE_CHECK_TYPE = 'domainExpirationCheck'
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -51,6 +57,14 @@ export class DomainService extends BaseService<DomainEntity> {
|
|||||||
@Inject()
|
@Inject()
|
||||||
userSettingService: UserSettingsService;
|
userSettingService: UserSettingsService;
|
||||||
|
|
||||||
|
@Inject()
|
||||||
|
jobHistoryService: JobHistoryService;
|
||||||
|
|
||||||
|
@Inject()
|
||||||
|
cron: Cron;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
getRepository() {
|
getRepository() {
|
||||||
return this.repository;
|
return this.repository;
|
||||||
@@ -320,9 +334,9 @@ export class DomainService extends BaseService<DomainEntity> {
|
|||||||
logger.info(`从域名提供商${dnsProviderType}导入域名完成(${key}),共导入${task.total}个域名,跳过${task.getSkipCount()}个域名,成功${task.getSuccessCount()}个域名,失败${task.getErrorCount()}个域名`)
|
logger.info(`从域名提供商${dnsProviderType}导入域名完成(${key}),共导入${task.total}个域名,跳过${task.getSkipCount()}个域名,成功${task.getSuccessCount()}个域名,失败${task.getErrorCount()}个域名`)
|
||||||
}
|
}
|
||||||
|
|
||||||
async getDomainImportTaskStatus(req: { userId?: number ,projectId?: number}) {
|
async getDomainImportTaskStatus(req: { userId?: number, projectId?: number }) {
|
||||||
const userId = req.userId || 0
|
const userId = req.userId || 0
|
||||||
const projectId = req.projectId
|
const projectId = req.projectId
|
||||||
|
|
||||||
const setting = await this.userSettingService.getSetting<UserDomainImportSetting>(userId, projectId, UserDomainImportSetting)
|
const setting = await this.userSettingService.getSetting<UserDomainImportSetting>(userId, projectId, UserDomainImportSetting)
|
||||||
const list = setting?.domainImportList || []
|
const list = setting?.domainImportList || []
|
||||||
@@ -429,8 +443,6 @@ export class DomainService extends BaseService<DomainEntity> {
|
|||||||
await this.deleteDomainImportTask({ userId, projectId, key })
|
await this.deleteDomainImportTask({ userId, projectId, key })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return await this.addDomainImportTask({ userId, projectId, dnsProviderType, dnsProviderAccessId, index })
|
return await this.addDomainImportTask({ userId, projectId, dnsProviderType, dnsProviderAccessId, index })
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -441,7 +453,7 @@ export class DomainService extends BaseService<DomainEntity> {
|
|||||||
const userId = req.userId ?? 'all'
|
const userId = req.userId ?? 'all'
|
||||||
const projectId = req.projectId
|
const projectId = req.projectId
|
||||||
let key = `user_${userId}`
|
let key = `user_${userId}`
|
||||||
if (projectId!=null) {
|
if (projectId != null) {
|
||||||
key += `_${projectId}`
|
key += `_${projectId}`
|
||||||
}
|
}
|
||||||
const task = taskExecutor.get(DOMAIN_EXPIRE_TASK_TYPE, key)
|
const task = taskExecutor.get(DOMAIN_EXPIRE_TASK_TYPE, key)
|
||||||
@@ -452,7 +464,7 @@ export class DomainService extends BaseService<DomainEntity> {
|
|||||||
const userId = req.userId
|
const userId = req.userId
|
||||||
const projectId = req.projectId
|
const projectId = req.projectId
|
||||||
let key = `user_${userId ?? 'all'}`
|
let key = `user_${userId ?? 'all'}`
|
||||||
if (projectId!=null) {
|
if (projectId != null) {
|
||||||
key += `_${projectId}`
|
key += `_${projectId}`
|
||||||
}
|
}
|
||||||
taskExecutor.start(new BackTask({
|
taskExecutor.start(new BackTask({
|
||||||
@@ -461,61 +473,22 @@ export class DomainService extends BaseService<DomainEntity> {
|
|||||||
title: `同步注册域名过期时间(${key}))`,
|
title: `同步注册域名过期时间(${key}))`,
|
||||||
run: async (task: BackTask) => {
|
run: async (task: BackTask) => {
|
||||||
await this._syncDomainsExpirationDate({ userId, projectId, task })
|
await this._syncDomainsExpirationDate({ userId, projectId, task })
|
||||||
|
if (userId != null) {
|
||||||
|
await this.startCheckDomainExpiration({ userId, projectId })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _syncDomainsExpirationDate(req: { userId?: number, projectId?: number, task: BackTask }) {
|
private async _syncDomainsExpirationDate(req: { userId?: number, projectId?: number, task: BackTask }) {
|
||||||
|
|
||||||
//同步所有域名的过期时间
|
//同步所有域名的过期时间
|
||||||
const pager = new Pager({
|
const pager = new Pager({
|
||||||
pageNo: 1,
|
pageNo: 1,
|
||||||
pageSize: 100,
|
pageSize: 100,
|
||||||
})
|
})
|
||||||
|
|
||||||
const dnsJson = await http.request({
|
const tldClient = new TldClient();
|
||||||
url: "https://data.iana.org/rdap/dns.json",
|
|
||||||
method: "GET",
|
|
||||||
})
|
|
||||||
const rdapMap: Record<string, string> = {}
|
|
||||||
for (const item of dnsJson.services) {
|
|
||||||
// [["store","work"], ["https://rdap.centralnic.com/store/"]],
|
|
||||||
const suffixes = item[0]
|
|
||||||
const urls = item[1]
|
|
||||||
for (const suffix of suffixes) {
|
|
||||||
rdapMap[suffix] = urls[0]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const getDomainExpirationDate = async (domain: string) => {
|
|
||||||
const parsed = parseDomainByPsl(domain)
|
|
||||||
const mainDomain = parsed.domain || ''
|
|
||||||
if (mainDomain !== domain) {
|
|
||||||
req.task.addError(`【${domain}】为子域名,跳过同步`)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const suffix = parsed.tld || ''
|
|
||||||
const rdapUrl = rdapMap[suffix]
|
|
||||||
if (!rdapUrl) {
|
|
||||||
req.task.addError(`【${domain}】未找到${suffix}的rdap地址`)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// https://rdap.nic.work/domain/handsfree.work
|
|
||||||
const rdap = await http.request({
|
|
||||||
url: `${rdapUrl}domain/${domain}`,
|
|
||||||
method: "GET",
|
|
||||||
})
|
|
||||||
|
|
||||||
let res: any = {}
|
|
||||||
const events = rdap.events || []
|
|
||||||
for (const item of events) {
|
|
||||||
if (item.eventAction === 'expiration') {
|
|
||||||
res.expirationDate = dayjs(item.eventDate).valueOf()
|
|
||||||
} else if (item.eventAction === 'registration') {
|
|
||||||
res.registrationDate = dayjs(item.eventDate).valueOf()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
const query: any = {
|
const query: any = {
|
||||||
challengeType: "dns",
|
challengeType: "dns",
|
||||||
}
|
}
|
||||||
@@ -546,10 +519,7 @@ export class DomainService extends BaseService<DomainEntity> {
|
|||||||
const itemHandle = async (item: any) => {
|
const itemHandle = async (item: any) => {
|
||||||
req.task.incrementCurrent()
|
req.task.incrementCurrent()
|
||||||
try {
|
try {
|
||||||
const res = await getDomainExpirationDate(item.domain)
|
const res = await tldClient.getDomainExpirationDate(item.domain)
|
||||||
if (!res) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const { expirationDate, registrationDate } = res
|
const { expirationDate, registrationDate } = res
|
||||||
if (!expirationDate) {
|
if (!expirationDate) {
|
||||||
req.task.addError(`【${item.domain}】获取域名${item.domain}过期时间失败`)
|
req.task.addError(`【${item.domain}】获取域名${item.domain}过期时间失败`)
|
||||||
@@ -566,6 +536,7 @@ export class DomainService extends BaseService<DomainEntity> {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
const errorMsg = `【${item.domain}】${error.message ?? error}`
|
const errorMsg = `【${item.domain}】${error.message ?? error}`
|
||||||
req.task.addError(errorMsg)
|
req.task.addError(errorMsg)
|
||||||
|
logger.error(errorMsg)
|
||||||
} finally {
|
} finally {
|
||||||
await utils.sleep(1000)
|
await utils.sleep(1000)
|
||||||
}
|
}
|
||||||
@@ -573,7 +544,151 @@ export class DomainService extends BaseService<DomainEntity> {
|
|||||||
|
|
||||||
await doPageTurn({ pager, getPage: getDomainPage, itemHandle: itemHandle })
|
await doPageTurn({ pager, getPage: getDomainPage, itemHandle: itemHandle })
|
||||||
const key = `user_${req.userId || 'all'}`
|
const key = `user_${req.userId || 'all'}`
|
||||||
logger.info(`同步用户(${key})注册域名过期时间完成(${req.task.getSuccessCount()}个成功,${req.task.getErrorCount()}个失败)`)
|
const log = `同步用户(${key})注册域名过期时间完成(${req.task.getSuccessCount()}个成功,${req.task.getErrorCount()}个失败)`
|
||||||
|
logger.info(log)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async startCheckDomainExpiration(req: { userId?: number, projectId?: number }) {
|
||||||
|
const { userId, projectId } = req
|
||||||
|
if (userId == null) {
|
||||||
|
throw new Error('userId is required');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (projectId && !isEnterprise()) {
|
||||||
|
logger.warn(`当前未开启企业模式,跳过检查项目(${projectId})的域名过期时间`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const setting = await this.monitorSettingGet({ userId, projectId })
|
||||||
|
if (!setting || !setting.enabled) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const jobHistory: any = {
|
||||||
|
userId,
|
||||||
|
projectId,
|
||||||
|
type: DOMAIN_EXPIRE_CHECK_TYPE,
|
||||||
|
title: `检查注册域名过期时间`,
|
||||||
|
startAt: dayjs().valueOf(),
|
||||||
|
result: "start",
|
||||||
|
}
|
||||||
|
await this.jobHistoryService.add(jobHistory)
|
||||||
|
|
||||||
|
const expireDays = setting.willExpireDays || 30
|
||||||
|
const ltTime = dayjs().add(expireDays, 'day').valueOf()
|
||||||
|
|
||||||
|
const total = await this.repository.count({
|
||||||
|
where:{
|
||||||
|
userId,
|
||||||
|
projectId,
|
||||||
|
disabled: false,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
//开始检查域名过期时间
|
||||||
|
const list = await this.repository.find({
|
||||||
|
where: {
|
||||||
|
userId,
|
||||||
|
projectId,
|
||||||
|
disabled: false,
|
||||||
|
expirationDate: LessThan(ltTime)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const now = dayjs().valueOf()
|
||||||
|
let willExpireDomains = []
|
||||||
|
let hasExpireDomains = []
|
||||||
|
|
||||||
|
for (const item of list) {
|
||||||
|
const { expirationDate } = item
|
||||||
|
const leftDays = dayjs(expirationDate).diff(dayjs(), 'day')
|
||||||
|
//@ts-ignore
|
||||||
|
item.leftDays = leftDays
|
||||||
|
if (expirationDate < now) {
|
||||||
|
hasExpireDomains.push(item)
|
||||||
|
} else {
|
||||||
|
willExpireDomains.push(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const title = `域名过期检查:即将过期 ${willExpireDomains.length} 个域名,已过期 ${hasExpireDomains.length} 个域名,共 ${total} 个域名`
|
||||||
|
|
||||||
|
try {
|
||||||
|
await this.jobHistoryService.update({
|
||||||
|
id: jobHistory.id,
|
||||||
|
content: title,
|
||||||
|
result: "done",
|
||||||
|
endAt: dayjs().valueOf(),
|
||||||
|
})
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
logger.error(`更新域名过期检查任务状态失败:${error.message ?? error}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (list.length == 0) {
|
||||||
|
//没有过期域名 不发通知
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//发送通知
|
||||||
|
const willExpireDomainsStr = willExpireDomains.map(item => `${item.domain} (剩余${item.leftDays}天)`).join('\n ')
|
||||||
|
const hasExpireDomainsStr = hasExpireDomains.map(item => `${item.domain} (已过期${item.leftDays}天)`).join('\n ')
|
||||||
|
const content = `您有域名即将过期,请尽快续费
|
||||||
|
|
||||||
|
即将过期域名: ${willExpireDomains.length} 个 (有效期<${expireDays}天)
|
||||||
|
${willExpireDomainsStr}
|
||||||
|
|
||||||
|
已过期域名: ${hasExpireDomains.length} 个
|
||||||
|
${hasExpireDomainsStr}`
|
||||||
|
const taskService = this.taskServiceBuilder.create({ userId: userId, projectId: projectId });
|
||||||
|
|
||||||
|
const notificationService = await taskService.getNotificationService()
|
||||||
|
const url = await notificationService.getBindUrl("#/certd/cert/domain");
|
||||||
|
await notificationService.send({
|
||||||
|
id: setting.notificationId,
|
||||||
|
useDefault: true,
|
||||||
|
logger: logger,
|
||||||
|
body: {
|
||||||
|
title: title,
|
||||||
|
content: content,
|
||||||
|
url: url,
|
||||||
|
errorMessage: title,
|
||||||
|
notificationType: DOMAIN_EXPIRE_CHECK_TYPE,
|
||||||
|
willExpireDomains,
|
||||||
|
hasExpireDomains,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async monitorSettingGet(req: { userId?: number, projectId?: number }) {
|
||||||
|
const { userId, projectId } = req
|
||||||
|
const setting = await this.userSettingService.getSetting<UserDomainMonitorSetting>(userId, projectId, UserDomainMonitorSetting)
|
||||||
|
return setting || {}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async monitorSettingSave(req: { userId?: number, projectId?: number, setting?: any }) {
|
||||||
|
const { userId, projectId, setting } = req
|
||||||
|
const bean: UserDomainMonitorSetting = new UserDomainMonitorSetting()
|
||||||
|
merge(bean, setting)
|
||||||
|
await this.userSettingService.saveSetting<UserDomainMonitorSetting>(userId, projectId, bean)
|
||||||
|
await this.registerMonitorCron({ userId, projectId })
|
||||||
|
}
|
||||||
|
|
||||||
|
public async registerMonitorCron(req: { userId?: number, projectId?: number }) {
|
||||||
|
const { userId, projectId } = req
|
||||||
|
const setting = await this.monitorSettingGet(req)
|
||||||
|
const key = `${DOMAIN_EXPIRE_CHECK_TYPE}:${userId}_${projectId || ''}`
|
||||||
|
this.cron.remove(key)
|
||||||
|
if (setting.enabled) {
|
||||||
|
this.cron.register({
|
||||||
|
cron: setting.cron,
|
||||||
|
name: key,
|
||||||
|
job: async () => {
|
||||||
|
await this.startCheckDomainExpiration({ userId, projectId })
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,128 @@
|
|||||||
|
|
||||||
|
import { http, logger } from '@certd/basic';
|
||||||
|
import { parseDomainByPsl } from "@certd/plugin-lib";
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
|
export interface DomainInfo {
|
||||||
|
expirationDate?: number;
|
||||||
|
registrationDate?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class TldClient {
|
||||||
|
private rdapMap: Record<string, string> = {}
|
||||||
|
private isInitialized = false;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
}
|
||||||
|
|
||||||
|
async init() {
|
||||||
|
if (this.isInitialized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const dnsJson = await http.request({
|
||||||
|
url: "https://data.iana.org/rdap/dns.json",
|
||||||
|
method: "GET",
|
||||||
|
})
|
||||||
|
for (const item of dnsJson.services) {
|
||||||
|
const suffixes = item[0]
|
||||||
|
const urls = item[1]
|
||||||
|
for (const suffix of suffixes) {
|
||||||
|
this.rdapMap[suffix] = urls[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.isInitialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getDomainExpirationDate(domain: string): Promise<DomainInfo> {
|
||||||
|
await this.init();
|
||||||
|
|
||||||
|
const parsed = parseDomainByPsl(domain)
|
||||||
|
const mainDomain = parsed.domain || ''
|
||||||
|
if (mainDomain !== domain) {
|
||||||
|
const message= `【${domain}】为子域名,无法获取过期时间`
|
||||||
|
logger.warn(message)
|
||||||
|
throw new Error(message)
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return await this.getDomainExpirationByRdap(domain, parsed.tld || '')
|
||||||
|
} catch (error) {
|
||||||
|
logger.error(error.message)
|
||||||
|
return await this.getDomainExpirationByWhoiser(domain)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async getDomainExpirationByRdap(domain: string, suffix: string): Promise<DomainInfo> {
|
||||||
|
const rdapUrl = this.rdapMap[suffix]
|
||||||
|
if (!rdapUrl) {
|
||||||
|
throw new Error(`【${domain}】未找到${suffix}的rdap地址`)
|
||||||
|
}
|
||||||
|
|
||||||
|
const rdap = await http.request({
|
||||||
|
url: `${rdapUrl}domain/${domain}`,
|
||||||
|
method: "GET",
|
||||||
|
})
|
||||||
|
|
||||||
|
let res: DomainInfo = {}
|
||||||
|
const events = rdap.events || []
|
||||||
|
for (const item of events) {
|
||||||
|
if (item.eventAction === 'expiration') {
|
||||||
|
res.expirationDate = dayjs(item.eventDate).valueOf()
|
||||||
|
} else if (item.eventAction === 'registration') {
|
||||||
|
res.registrationDate = dayjs(item.eventDate).valueOf()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
private async getDomainExpirationByWhoiser(domain: string): Promise<DomainInfo> {
|
||||||
|
const whoiser = await import("whoiser")
|
||||||
|
const result = await whoiser.whoisDomain(domain, {
|
||||||
|
follow: 2,
|
||||||
|
timeout: 5000
|
||||||
|
})
|
||||||
|
|
||||||
|
let res: DomainInfo = {}
|
||||||
|
/**
|
||||||
|
* {
|
||||||
|
"Domain Status": [
|
||||||
|
"ok",
|
||||||
|
],
|
||||||
|
"Name Server": [
|
||||||
|
"dns21.hichina.com",
|
||||||
|
"dns22.hichina.com",
|
||||||
|
],
|
||||||
|
text: [
|
||||||
|
"",
|
||||||
|
],
|
||||||
|
"Domain Name": "docmirror.cn",
|
||||||
|
ROID: "20200907s10001s31265717-cn",
|
||||||
|
"Registrant Name": "肖君诺",
|
||||||
|
"Registrant Email": "252959493@qq.com",
|
||||||
|
Registrar: "阿里巴巴云计算(北京)有限公司",
|
||||||
|
"Created Date": "2020-09-07 09:22:54",
|
||||||
|
"Expiry Date": "2026-09-07 09:22:54",
|
||||||
|
DNSSEC: "unsigned",
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
for (const server in result) {
|
||||||
|
const data = result[server] as any
|
||||||
|
if (data['Expiry Date']) {
|
||||||
|
res.expirationDate = dayjs(data['Expiry Date']).valueOf()
|
||||||
|
}
|
||||||
|
if (data['Created Date']) {
|
||||||
|
res.registrationDate = dayjs(data['Created Date']).valueOf()
|
||||||
|
}
|
||||||
|
if (res.expirationDate && res.registrationDate) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!res.expirationDate) {
|
||||||
|
throw new Error(`【${domain}】whois查询未找到过期时间`)
|
||||||
|
}
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
import { Config, Configuration, Logger } from '@midwayjs/core';
|
import { logger } from '@certd/basic';
|
||||||
import { ILogger } from '@midwayjs/logger';
|
import { Config, Configuration, IMidwayContainer } from '@midwayjs/core';
|
||||||
import { IMidwayContainer } from '@midwayjs/core';
|
|
||||||
import { Cron } from './cron.js';
|
import { Cron } from './cron.js';
|
||||||
|
|
||||||
// ... (see below) ...
|
// ... (see below) ...
|
||||||
@@ -11,18 +10,15 @@ import { Cron } from './cron.js';
|
|||||||
export class CronConfiguration {
|
export class CronConfiguration {
|
||||||
@Config()
|
@Config()
|
||||||
config;
|
config;
|
||||||
@Logger()
|
|
||||||
logger: ILogger;
|
|
||||||
|
|
||||||
cron: Cron;
|
cron: Cron;
|
||||||
async onReady(container: IMidwayContainer) {
|
async onReady(container: IMidwayContainer) {
|
||||||
this.logger.info('cron start');
|
logger.info('cron start');
|
||||||
this.cron = new Cron({
|
this.cron = new Cron({
|
||||||
logger: this.logger,
|
logger: logger,
|
||||||
...this.config,
|
...this.config,
|
||||||
});
|
});
|
||||||
container.registerObject('cron', this.cron);
|
container.registerObject('cron', this.cron);
|
||||||
this.cron.start();
|
this.cron.start();
|
||||||
this.logger.info('cron started');
|
logger.info('cron started');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,18 @@ export class UserSiteMonitorSetting extends BaseSettings {
|
|||||||
certValidDays?:number = 14;
|
certValidDays?:number = 14;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export class UserDomainMonitorSetting extends BaseSettings {
|
||||||
|
static __title__ = "域名到期监控设置";
|
||||||
|
static __key__ = "user.domain.monitor";
|
||||||
|
|
||||||
|
enabled?:boolean = false;
|
||||||
|
notificationId?:number= 0;
|
||||||
|
cron?:string = undefined;
|
||||||
|
willExpireDays?:number = 30;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export class UserEmailSetting extends BaseSettings {
|
export class UserEmailSetting extends BaseSettings {
|
||||||
static __title__ = "用户邮箱设置";
|
static __title__ = "用户邮箱设置";
|
||||||
static __key__ = "user.email";
|
static __key__ = "user.email";
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
|
||||||
|
import { PipelineEntity } from '../../pipeline/entity/pipeline.js';
|
||||||
|
|
||||||
|
@Entity('cd_job_history')
|
||||||
|
export class JobHistoryEntity {
|
||||||
|
@PrimaryGeneratedColumn()
|
||||||
|
id: number;
|
||||||
|
|
||||||
|
@Column({ name: 'user_id', comment: '用户id' })
|
||||||
|
userId: number;
|
||||||
|
|
||||||
|
@Column({ name: 'project_id', comment: '项目id' })
|
||||||
|
projectId: number;
|
||||||
|
|
||||||
|
|
||||||
|
@Column({ name: 'type', comment: '类型' })
|
||||||
|
type: string;
|
||||||
|
|
||||||
|
@Column({ name: 'title', comment: '标题' })
|
||||||
|
title: string;
|
||||||
|
|
||||||
|
@Column({ name: 'content', comment: '内容' })
|
||||||
|
content: string;
|
||||||
|
|
||||||
|
@Column({ name: 'related_id', comment: '关联id' })
|
||||||
|
relatedId: string;
|
||||||
|
|
||||||
|
@Column({ name: 'result', comment: '结果' })
|
||||||
|
result: string;
|
||||||
|
|
||||||
|
@Column({ name: 'start_at', comment: '开始时间' })
|
||||||
|
startAt: number;
|
||||||
|
|
||||||
|
@Column({ name: 'end_at', comment: '结束时间' })
|
||||||
|
endAt: number;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
name: 'create_time',
|
||||||
|
comment: '创建时间',
|
||||||
|
default: () => 'CURRENT_TIMESTAMP',
|
||||||
|
})
|
||||||
|
createTime: Date;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
name: 'update_time',
|
||||||
|
comment: '修改时间',
|
||||||
|
default: () => 'CURRENT_TIMESTAMP',
|
||||||
|
})
|
||||||
|
updateTime: Date;
|
||||||
|
|
||||||
|
pipeline?: PipelineEntity;
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import { BaseService } from "@certd/lib-server";
|
||||||
|
import { Inject, Provide, Scope, ScopeEnum } from "@midwayjs/core";
|
||||||
|
import { InjectEntityModel } from "@midwayjs/typeorm";
|
||||||
|
import { Repository } from "typeorm";
|
||||||
|
import { UserSettingsService } from "../../mine/service/user-settings-service.js";
|
||||||
|
import { JobHistoryEntity } from "../entity/job-history.js";
|
||||||
|
|
||||||
|
|
||||||
|
@Provide()
|
||||||
|
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||||
|
export class JobHistoryService extends BaseService<JobHistoryEntity> {
|
||||||
|
@InjectEntityModel(JobHistoryEntity)
|
||||||
|
repository: Repository<JobHistoryEntity>;
|
||||||
|
|
||||||
|
|
||||||
|
@Inject()
|
||||||
|
userSettingsService: UserSettingsService;
|
||||||
|
|
||||||
|
//@ts-ignore
|
||||||
|
getRepository() {
|
||||||
|
return this.repository;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,6 +17,8 @@ import {SiteIpEntity} from "../entity/site-ip.js";
|
|||||||
import {Cron} from "../../cron/cron.js";
|
import {Cron} from "../../cron/cron.js";
|
||||||
import { dnsContainer } from "./dns-custom.js";
|
import { dnsContainer } from "./dns-custom.js";
|
||||||
import { merge } from "lodash-es";
|
import { merge } from "lodash-es";
|
||||||
|
import { JobHistoryService } from "./job-history-service.js";
|
||||||
|
import { JobHistoryEntity } from "../entity/job-history.js";
|
||||||
|
|
||||||
@Provide()
|
@Provide()
|
||||||
@Scope(ScopeEnum.Request, {allowDowngrade: true})
|
@Scope(ScopeEnum.Request, {allowDowngrade: true})
|
||||||
@@ -39,6 +41,9 @@ export class SiteInfoService extends BaseService<SiteInfoEntity> {
|
|||||||
@Inject()
|
@Inject()
|
||||||
siteIpService: SiteIpService;
|
siteIpService: SiteIpService;
|
||||||
|
|
||||||
|
@Inject()
|
||||||
|
jobHistoryService: JobHistoryService;
|
||||||
|
|
||||||
|
|
||||||
@Inject()
|
@Inject()
|
||||||
cron: Cron;
|
cron: Cron;
|
||||||
@@ -352,10 +357,11 @@ export class SiteInfoService extends BaseService<SiteInfoEntity> {
|
|||||||
if (userId==null) {
|
if (userId==null) {
|
||||||
throw new Error("userId is required");
|
throw new Error("userId is required");
|
||||||
}
|
}
|
||||||
const sites = await this.repository.find({
|
// const sites = await this.repository.find({
|
||||||
where: {userId,projectId}
|
// where: {userId,projectId}
|
||||||
});
|
// });
|
||||||
this.checkList(sites,false);
|
// this.checkList(sites,false);
|
||||||
|
await this.triggerJobOnce(userId,projectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
async checkList(sites: SiteInfoEntity[],isCommon: boolean) {
|
async checkList(sites: SiteInfoEntity[],isCommon: boolean) {
|
||||||
@@ -516,6 +522,7 @@ export class SiteInfoService extends BaseService<SiteInfoEntity> {
|
|||||||
async triggerJobOnce(userId?:number,projectId?:number) {
|
async triggerJobOnce(userId?:number,projectId?:number) {
|
||||||
logger.info(`站点证书检查开始执行[${userId??'所有用户'}_${projectId??'所有项目'}]`);
|
logger.info(`站点证书检查开始执行[${userId??'所有用户'}_${projectId??'所有项目'}]`);
|
||||||
const query:any = { disabled: false };
|
const query:any = { disabled: false };
|
||||||
|
let jobEntity :Partial<JobHistoryEntity> = null;
|
||||||
if(userId!=null){
|
if(userId!=null){
|
||||||
query.userId = userId;
|
query.userId = userId;
|
||||||
if(projectId){
|
if(projectId){
|
||||||
@@ -523,12 +530,22 @@ export class SiteInfoService extends BaseService<SiteInfoEntity> {
|
|||||||
}
|
}
|
||||||
//判断是否已关闭
|
//判断是否已关闭
|
||||||
const setting = await this.userSettingsService.getSetting<UserSiteMonitorSetting>(userId,projectId, UserSiteMonitorSetting);
|
const setting = await this.userSettingsService.getSetting<UserSiteMonitorSetting>(userId,projectId, UserSiteMonitorSetting);
|
||||||
if (!setting.cron) {
|
if (setting && !setting.cron) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
jobEntity = {
|
||||||
|
userId,
|
||||||
|
projectId,
|
||||||
|
type:"siteCertMonitor",
|
||||||
|
title: '站点证书检查',
|
||||||
|
result:"start",
|
||||||
|
startAt:new Date().getTime(),
|
||||||
|
}
|
||||||
|
await this.jobHistoryService.add(jobEntity);
|
||||||
}
|
}
|
||||||
let offset = 0;
|
let offset = 0;
|
||||||
const limit = 50;
|
const limit = 50;
|
||||||
|
let count = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
const res = await this.page({
|
const res = await this.page({
|
||||||
query: query,
|
query: query,
|
||||||
@@ -541,10 +558,20 @@ export class SiteInfoService extends BaseService<SiteInfoEntity> {
|
|||||||
}
|
}
|
||||||
offset += records.length;
|
offset += records.length;
|
||||||
const isCommon = !userId;
|
const isCommon = !userId;
|
||||||
|
count += records.length;
|
||||||
await this.checkList(records,isCommon);
|
await this.checkList(records,isCommon);
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.info(`站点证书检查完成[${userId??'所有用户'}_${projectId??'所有项目'}]`);
|
logger.info(`站点证书检查完成[${userId??'所有用户'}_${projectId??'所有项目'}]`);
|
||||||
|
if(jobEntity){
|
||||||
|
await this.jobHistoryService.update({
|
||||||
|
id: jobEntity.id,
|
||||||
|
result: "done",
|
||||||
|
content:`共检查${count}个站点`,
|
||||||
|
endAt:new Date().getTime(),
|
||||||
|
updateTime:new Date(),
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async batchDelete(ids: number[], userId: number,projectId?:number): Promise<void> {
|
async batchDelete(ids: number[], userId: number,projectId?:number): Promise<void> {
|
||||||
|
|||||||
@@ -23,4 +23,8 @@ export class NotificationGetter implements INotificationService {
|
|||||||
async send(req: NotificationSendReq): Promise<void> {
|
async send(req: NotificationSendReq): Promise<void> {
|
||||||
return await this.notificationService.send(req, this.userId, this.projectId);
|
return await this.notificationService.send(req, this.userId, this.projectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getBindUrl(url: string) {
|
||||||
|
return await this.notificationService.getBindUrl(url);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -524,15 +524,12 @@ export class PluginService extends BaseService<PluginEntity> {
|
|||||||
id: pluginEntity.id
|
id: pluginEntity.id
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async deleteByIds(ids: any[]) {
|
async deleteByIds(ids: any[]) {
|
||||||
|
ids = this.filterIds(ids);
|
||||||
for (const id of ids) {
|
for (const id of ids) {
|
||||||
await this.unRegisterById(id)
|
await this.unRegisterById(id);
|
||||||
await this.delete(id);
|
await this.delete(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,4 +44,5 @@
|
|||||||
// export * from './plugin-lib/index.js'
|
// export * from './plugin-lib/index.js'
|
||||||
// export * from './plugin-plus/index.js'
|
// export * from './plugin-plus/index.js'
|
||||||
// export * from './plugin-cert/index.js'
|
// export * from './plugin-cert/index.js'
|
||||||
// export * from './plugin-zenlayer/index.js'
|
// export * from './plugin-zenlayer/index.js'
|
||||||
|
export * from './plugin-dnsmgr/index.js'
|
||||||
@@ -156,7 +156,7 @@ export abstract class CertApplyBasePlugin extends CertApplyBaseConvertPlugin {
|
|||||||
if(maxDays < 2){
|
if(maxDays < 2){
|
||||||
maxDays = 2;
|
maxDays = 2;
|
||||||
}
|
}
|
||||||
this.logger.warn(`为避免每次运行都更新证书,更新天数自动减半,调整为${maxDays}`);
|
this.logger.warn(`为避免每次运行都更新证书,更新天数自动减半(即证书最大时长${totalDays}天减半),调整为${maxDays}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -0,0 +1,144 @@
|
|||||||
|
import { AccessInput, BaseAccess, IsAccess, Pager, PageRes, PageSearch } from '@certd/pipeline';
|
||||||
|
import { DomainRecord } from '@certd/plugin-lib';
|
||||||
|
|
||||||
|
@IsAccess({
|
||||||
|
name: 'dnsmgr',
|
||||||
|
title: '彩虹DNS',
|
||||||
|
icon: 'clarity:plugin-line',
|
||||||
|
desc: '彩虹DNS管理系统授权',
|
||||||
|
})
|
||||||
|
export class DnsmgrAccess extends BaseAccess {
|
||||||
|
@AccessInput({
|
||||||
|
title: '系统地址',
|
||||||
|
component: {
|
||||||
|
name: "a-input",
|
||||||
|
allowClear: true,
|
||||||
|
placeholder: 'https://dnsmgr.example.com',
|
||||||
|
},
|
||||||
|
required: true,
|
||||||
|
})
|
||||||
|
endpoint = '';
|
||||||
|
|
||||||
|
@AccessInput({
|
||||||
|
title: '用户ID',
|
||||||
|
component: {
|
||||||
|
name: "a-input",
|
||||||
|
allowClear: true,
|
||||||
|
placeholder: '123456',
|
||||||
|
},
|
||||||
|
required: true,
|
||||||
|
})
|
||||||
|
uid = '';
|
||||||
|
|
||||||
|
@AccessInput({
|
||||||
|
title: 'API密钥',
|
||||||
|
required: true,
|
||||||
|
encrypt: true,
|
||||||
|
})
|
||||||
|
key = '';
|
||||||
|
|
||||||
|
@AccessInput({
|
||||||
|
title: "测试",
|
||||||
|
component: {
|
||||||
|
name: "api-test",
|
||||||
|
action: "TestRequest"
|
||||||
|
},
|
||||||
|
helper: "点击测试接口是否正常"
|
||||||
|
})
|
||||||
|
testRequest = true;
|
||||||
|
|
||||||
|
async onTestRequest() {
|
||||||
|
await this.GetDomainList({});
|
||||||
|
return "ok";
|
||||||
|
}
|
||||||
|
|
||||||
|
async GetDomainList(req: PageSearch): Promise<PageRes<DomainRecord>> {
|
||||||
|
this.ctx.logger.info(`获取域名列表,req:${JSON.stringify(req)}`);
|
||||||
|
const pager = new Pager(req);
|
||||||
|
const resp = await this.doRequest({
|
||||||
|
url: '/api/domain',
|
||||||
|
data: {
|
||||||
|
offset: pager.getOffset(),
|
||||||
|
limit: pager.pageSize,
|
||||||
|
kw: req.searchKey,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const total = resp?.total || 0;
|
||||||
|
let list = resp?.rows?.map((item: any) => {
|
||||||
|
return {
|
||||||
|
domain: item.name,
|
||||||
|
...item,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
total,
|
||||||
|
list,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
async createDnsRecord(domainId: string, record: string, value: string, type: string, domain: string) {
|
||||||
|
this.ctx.logger.info(`创建DNS记录:${record} ${type} ${value}`);
|
||||||
|
const resp = await this.doRequest({
|
||||||
|
url: `/api/record/add/${domainId}`,
|
||||||
|
data: {
|
||||||
|
name: record.replace(`.${domain}`, ''),
|
||||||
|
type,
|
||||||
|
value,
|
||||||
|
line: 'default',
|
||||||
|
ttl: 600,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getDnsRecords(domainId: string, type?: string, name?: string, value?: string) {
|
||||||
|
this.ctx.logger.info(`获取DNS记录列表:domainId=${domainId}, type=${type}, name=${name}`);
|
||||||
|
const resp = await this.doRequest({
|
||||||
|
url: `/api/record/data/${domainId}`,
|
||||||
|
data: {
|
||||||
|
type,
|
||||||
|
subdomain: name,
|
||||||
|
value,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
async deleteDnsRecord(domainId: string, recordId: string) {
|
||||||
|
this.ctx.logger.info(`删除DNS记录:domainId=${domainId}, recordId=${recordId}`);
|
||||||
|
const resp = await this.doRequest({
|
||||||
|
url: `/api/record/delete/${domainId}`,
|
||||||
|
data: {
|
||||||
|
recordid: recordId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
async doRequest(req: { url: string; data?: any }) {
|
||||||
|
const timestamp = Math.floor(Date.now() / 1000);
|
||||||
|
const sign = this.ctx.utils.hash.md5(`${this.uid}${timestamp}${this.key}`);
|
||||||
|
const url = `${this.endpoint}${req.url}`;
|
||||||
|
|
||||||
|
const res = await this.ctx.http.request({
|
||||||
|
url,
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded',
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
uid: this.uid,
|
||||||
|
timestamp,
|
||||||
|
sign,
|
||||||
|
...req.data,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (res.code !== undefined && res.code !== 0) {
|
||||||
|
throw new Error(res.msg || '请求失败');
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
import { AbstractDnsProvider, CreateRecordOptions, DomainRecord, IsDnsProvider, RemoveRecordOptions } from '@certd/plugin-cert';
|
||||||
|
import { DnsmgrAccess } from './access.js';
|
||||||
|
import { PageRes, PageSearch } from '@certd/pipeline';
|
||||||
|
|
||||||
|
type DnsmgrRecord = {
|
||||||
|
domainId: string;
|
||||||
|
name: string;
|
||||||
|
value: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
@IsDnsProvider({
|
||||||
|
name: 'dnsmgr',
|
||||||
|
title: '彩虹DNS',
|
||||||
|
desc: '彩虹DNS管理系统',
|
||||||
|
icon: 'clarity:plugin-line',
|
||||||
|
accessType: 'dnsmgr',
|
||||||
|
order: 99,
|
||||||
|
})
|
||||||
|
export class DnsmgrDnsProvider extends AbstractDnsProvider<DnsmgrRecord> {
|
||||||
|
access!: DnsmgrAccess;
|
||||||
|
|
||||||
|
async onInstance() {
|
||||||
|
this.access = this.ctx.access as DnsmgrAccess;
|
||||||
|
this.logger.debug('access', this.access);
|
||||||
|
}
|
||||||
|
|
||||||
|
async createRecord(options: CreateRecordOptions): Promise<any> {
|
||||||
|
const { fullRecord, value, type, domain } = options;
|
||||||
|
this.logger.info('添加域名解析:', fullRecord, value, type, domain);
|
||||||
|
|
||||||
|
const domainList = await this.access.GetDomainList({ searchKey: domain });
|
||||||
|
const domainInfo = domainList.list?.find((item: any) => item.name === domain);
|
||||||
|
|
||||||
|
if (!domainInfo) {
|
||||||
|
throw new Error(`未找到域名:${domain}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const name = fullRecord.replace(`.${domain}`, '');
|
||||||
|
const res = await this.access.createDnsRecord(domainInfo.id, fullRecord, value, type, domain);
|
||||||
|
return { domainId: domainInfo.id, name, value,res };
|
||||||
|
}
|
||||||
|
|
||||||
|
async removeRecord(options: RemoveRecordOptions<DnsmgrRecord>): Promise<void> {
|
||||||
|
const { fullRecord, value } = options.recordReq;
|
||||||
|
const record = options.recordRes;
|
||||||
|
this.logger.info('删除域名解析:', fullRecord, value, record);
|
||||||
|
|
||||||
|
if (record && record.domainId) {
|
||||||
|
const records = await this.access.getDnsRecords(record.domainId, 'TXT', record.name, record.value);
|
||||||
|
if (records && records.rows && records.rows.length > 0) {
|
||||||
|
const recordToDelete = records.rows[0];
|
||||||
|
await this.access.deleteDnsRecord(record.domainId, recordToDelete.RecordId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.logger.info('删除域名解析成功:', fullRecord, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
async getDomainListPage(req: PageSearch): Promise<PageRes<DomainRecord>> {
|
||||||
|
const res = await this.access.GetDomainList(req);
|
||||||
|
res.list = res.list?.map((item: any) => {
|
||||||
|
return {
|
||||||
|
id: item.id,
|
||||||
|
domain: item.name,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
new DnsmgrDnsProvider();
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
export * from './access.js';
|
||||||
|
export * from './dns-provider.js';
|
||||||
@@ -0,0 +1,148 @@
|
|||||||
|
import { IsAccess, AccessInput, BaseAccess, PageSearch } from "@certd/pipeline";
|
||||||
|
|
||||||
|
@IsAccess({
|
||||||
|
name: "spaceship",
|
||||||
|
title: "Spaceship.com 授权",
|
||||||
|
icon: "clarity:plugin-line",
|
||||||
|
desc: "Spaceship.com API 授权插件"
|
||||||
|
})
|
||||||
|
export class SpaceshipAccess extends BaseAccess {
|
||||||
|
|
||||||
|
@AccessInput({
|
||||||
|
title: "API Key",
|
||||||
|
component: {
|
||||||
|
placeholder: "请输入 API Key"
|
||||||
|
},
|
||||||
|
required: true,
|
||||||
|
encrypt: true,
|
||||||
|
helper: "前往 [获取 API Key](https://www.spaceship.com/application/api-manager/)"
|
||||||
|
})
|
||||||
|
apiKey = "";
|
||||||
|
|
||||||
|
@AccessInput({
|
||||||
|
title: "API Secret",
|
||||||
|
component: {
|
||||||
|
name: "a-input-password",
|
||||||
|
vModel: "value",
|
||||||
|
placeholder: "请输入 API Secret"
|
||||||
|
},
|
||||||
|
required: true,
|
||||||
|
encrypt: true
|
||||||
|
})
|
||||||
|
apiSecret = "";
|
||||||
|
|
||||||
|
@AccessInput({
|
||||||
|
title: "测试",
|
||||||
|
component: {
|
||||||
|
name: "api-test",
|
||||||
|
action: "TestRequest"
|
||||||
|
},
|
||||||
|
helper: "测试 API 连接是否正常,需要域名查询权限"
|
||||||
|
})
|
||||||
|
testRequest = true;
|
||||||
|
|
||||||
|
async onTestRequest() {
|
||||||
|
await this.GetDomainList({});
|
||||||
|
return "ok";
|
||||||
|
}
|
||||||
|
|
||||||
|
async doRequest(options: {
|
||||||
|
url: string;
|
||||||
|
method: 'GET' | 'POST' | 'DELETE' | 'PUT';
|
||||||
|
params?: any;
|
||||||
|
data?: any;
|
||||||
|
}) {
|
||||||
|
const headers = {
|
||||||
|
"X-Api-Key": this.apiKey,
|
||||||
|
"X-Api-Secret": this.apiSecret
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await this.ctx.http.request({
|
||||||
|
url: options.url,
|
||||||
|
method: options.method,
|
||||||
|
headers,
|
||||||
|
params: options.params,
|
||||||
|
data: options.data
|
||||||
|
});
|
||||||
|
return res;
|
||||||
|
} catch (error: any) {
|
||||||
|
const errorMsg = [];
|
||||||
|
const status = error.status || error.response?.status;
|
||||||
|
if (error.response) {
|
||||||
|
const headers = error.response.headers;
|
||||||
|
const data = error.response.data;
|
||||||
|
|
||||||
|
errorMsg.push(`API 请求失败: ${status}`);
|
||||||
|
|
||||||
|
if (headers['spaceship-error-code']) {
|
||||||
|
errorMsg.push(`错误代码: ${headers['spaceship-error-code']}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (headers['spaceship-operation-id']) {
|
||||||
|
errorMsg.push(`操作ID: ${headers['spaceship-operation-id']}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data && data.detail) {
|
||||||
|
errorMsg.push(`错误详情: ${data.detail}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.ctx.logger.error(`Spaceship API 错误: ${errorMsg.join(' | ')}`);
|
||||||
|
} else if (error.request) {
|
||||||
|
errorMsg.push(`请求发送失败: ${error.message}`);
|
||||||
|
this.ctx.logger.error(`Spaceship API 请求发送失败: ${error.message}`);
|
||||||
|
} else {
|
||||||
|
errorMsg.push(`请求配置错误: ${error.message}`);
|
||||||
|
this.ctx.logger.error(`Spaceship API 请求配置错误: ${error.message}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const error2 = new Error(errorMsg.join(' | '));
|
||||||
|
//@ts-ignore
|
||||||
|
error2.status = status;
|
||||||
|
throw error2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async GetDomainList(req: PageSearch) {
|
||||||
|
const take = req.pageSize || 100;
|
||||||
|
const skip = ((req.pageNo || 1) - 1) * take;
|
||||||
|
|
||||||
|
const res = await this.doRequest({
|
||||||
|
url: "https://spaceship.dev/api/v1/domains",
|
||||||
|
method: "GET",
|
||||||
|
params: {
|
||||||
|
take,
|
||||||
|
skip
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
total: res.total || 0,
|
||||||
|
list: res.items || []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async getDomainInfo(domain: string) {
|
||||||
|
try {
|
||||||
|
const res = await this.doRequest({
|
||||||
|
url: `https://spaceship.dev/api/v1/domains/${domain}`,
|
||||||
|
method: "GET"
|
||||||
|
});
|
||||||
|
return res;
|
||||||
|
} catch (error: any) {
|
||||||
|
if (error.status === 404) {
|
||||||
|
throw new Error(`域名 ${domain} 不存在于当前账号中`);
|
||||||
|
}
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getCacheKey() {
|
||||||
|
const hashStr = this.apiKey + this.apiSecret;
|
||||||
|
const hashCode = this.ctx.utils.hash.sha256(hashStr);
|
||||||
|
return `spaceship-${hashCode}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
new SpaceshipAccess();
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
import { AbstractDnsProvider, CreateRecordOptions, DomainRecord, IsDnsProvider, RemoveRecordOptions } from "@certd/plugin-cert";
|
||||||
|
import { SpaceshipAccess } from "./access.js";
|
||||||
|
import { PageRes, PageSearch } from "@certd/pipeline";
|
||||||
|
|
||||||
|
export type SpaceshipRecord = {
|
||||||
|
name: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
@IsDnsProvider({
|
||||||
|
name: "spaceship",
|
||||||
|
title: "Spaceship",
|
||||||
|
desc: "Spaceship 域名解析",
|
||||||
|
icon: "clarity:plugin-line",
|
||||||
|
accessType: "spaceship",
|
||||||
|
order: 99
|
||||||
|
})
|
||||||
|
export class SpaceshipProvider extends AbstractDnsProvider<SpaceshipRecord> {
|
||||||
|
access!: SpaceshipAccess;
|
||||||
|
|
||||||
|
async onInstance() {
|
||||||
|
this.access = this.ctx.access as SpaceshipAccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
async createRecord(options: CreateRecordOptions): Promise<SpaceshipRecord> {
|
||||||
|
const { fullRecord, hostRecord, value, type, domain } = options;
|
||||||
|
this.logger.info("添加域名解析:", fullRecord, value, type, domain);
|
||||||
|
|
||||||
|
await this.access.getDomainInfo(domain);
|
||||||
|
|
||||||
|
const recordRes = await this.access.doRequest({
|
||||||
|
// https://spaceship.dev/api/v1/dns/records/{domain}
|
||||||
|
url: `https://spaceship.dev/api/v1/dns/records/${domain}`,
|
||||||
|
method: "PUT",
|
||||||
|
data: {
|
||||||
|
force: false,
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
type: type,
|
||||||
|
value: value,
|
||||||
|
name: hostRecord,
|
||||||
|
ttl: 60
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return recordRes;
|
||||||
|
}
|
||||||
|
|
||||||
|
async removeRecord(options: RemoveRecordOptions<SpaceshipRecord>): Promise<void> {
|
||||||
|
const recordReq = options.recordReq;
|
||||||
|
this.logger.info("删除域名解析:", recordReq);
|
||||||
|
|
||||||
|
await this.access.doRequest({
|
||||||
|
// https://spaceship.dev/api/v1/dns/records/xxx.net
|
||||||
|
url: `https://spaceship.dev/api/v1/dns/records/${recordReq.domain}`,
|
||||||
|
method: "DELETE",
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
type: recordReq.type,
|
||||||
|
value: recordReq.value,
|
||||||
|
name: recordReq.hostRecord
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
this.logger.info("删除域名解析成功:", JSON.stringify(recordReq));
|
||||||
|
}
|
||||||
|
|
||||||
|
async getDomainListPage(req: PageSearch): Promise<PageRes<DomainRecord>> {
|
||||||
|
const res = await this.access.GetDomainList(req);
|
||||||
|
|
||||||
|
const list = res.list.map((item: any) => ({
|
||||||
|
domain: item.name,
|
||||||
|
id: item.name
|
||||||
|
}));
|
||||||
|
|
||||||
|
return {
|
||||||
|
total: res.total || 0,
|
||||||
|
list: list || []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
new SpaceshipProvider();
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
import "./access.js";
|
||||||
|
import "./dns-provider.js";
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from '@certd/pipeline';
|
import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from '@certd/pipeline';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import { TencentAccess } from '../../../plugin-lib/tencent/index.js';
|
import { TencentAccess } from '../../../plugin-lib/tencent/index.js';
|
||||||
import { CertApplyPluginNames} from '@certd/plugin-cert';
|
import { CertApplyPluginNames, CertInfo } from '@certd/plugin-cert';
|
||||||
@IsTaskPlugin({
|
@IsTaskPlugin({
|
||||||
name: 'DeployCertToTencentCLB',
|
name: 'DeployCertToTencentCLB',
|
||||||
title: '腾讯云-部署到CLB',
|
title: '腾讯云-部署到CLB',
|
||||||
@@ -15,6 +15,31 @@ import { CertApplyPluginNames} from '@certd/plugin-cert';
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
export class DeployCertToTencentCLB extends AbstractTaskPlugin {
|
export class DeployCertToTencentCLB extends AbstractTaskPlugin {
|
||||||
|
|
||||||
|
@TaskInput({
|
||||||
|
title: '域名证书',
|
||||||
|
helper: '请选择前置任务输出的域名证书',
|
||||||
|
component: {
|
||||||
|
name: 'output-selector',
|
||||||
|
from: [...CertApplyPluginNames, 'UploadCertToTencent'],
|
||||||
|
},
|
||||||
|
required: true,
|
||||||
|
})
|
||||||
|
cert!: string | CertInfo;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@TaskInput({
|
||||||
|
title: 'Access提供者',
|
||||||
|
helper: 'access授权',
|
||||||
|
component: {
|
||||||
|
name: 'access-selector',
|
||||||
|
type: 'tencent',
|
||||||
|
},
|
||||||
|
required: true,
|
||||||
|
})
|
||||||
|
accessId!: string;
|
||||||
|
|
||||||
@TaskInput({
|
@TaskInput({
|
||||||
title: '大区',
|
title: '大区',
|
||||||
component: {
|
component: {
|
||||||
@@ -40,20 +65,18 @@ export class DeployCertToTencentCLB extends AbstractTaskPlugin {
|
|||||||
{ value: 'na-siliconvalley' },
|
{ value: 'na-siliconvalley' },
|
||||||
{ value: 'na-toronto' },
|
{ value: 'na-toronto' },
|
||||||
{ value: 'sa-saopaulo' },
|
{ value: 'sa-saopaulo' },
|
||||||
|
{ value: 'ap-taipei' },
|
||||||
],
|
],
|
||||||
|
helper: '如果列表中没有,您可以手动输入',
|
||||||
},
|
},
|
||||||
required: true,
|
required: true,
|
||||||
})
|
})
|
||||||
region!: string;
|
region!: string;
|
||||||
|
|
||||||
@TaskInput({
|
|
||||||
title: '证书名称前缀',
|
|
||||||
})
|
|
||||||
certName!: string;
|
|
||||||
|
|
||||||
@TaskInput({
|
@TaskInput({
|
||||||
title: '负载均衡ID',
|
title: '负载均衡ID',
|
||||||
helper: '如果没有配置,则根据域名匹配负载均衡下的监听器(根据域名匹配时暂时只支持前100个)',
|
|
||||||
required: true,
|
required: true,
|
||||||
})
|
})
|
||||||
loadBalancerId!: string;
|
loadBalancerId!: string;
|
||||||
@@ -78,26 +101,10 @@ export class DeployCertToTencentCLB extends AbstractTaskPlugin {
|
|||||||
domain!: string | string[];
|
domain!: string | string[];
|
||||||
|
|
||||||
@TaskInput({
|
@TaskInput({
|
||||||
title: '域名证书',
|
title: '证书名称前缀',
|
||||||
helper: '请选择前置任务输出的域名证书',
|
|
||||||
component: {
|
|
||||||
name: 'output-selector',
|
|
||||||
from: [...CertApplyPluginNames],
|
|
||||||
},
|
|
||||||
required: true,
|
|
||||||
})
|
})
|
||||||
cert!: any;
|
certName!: string;
|
||||||
|
|
||||||
@TaskInput({
|
|
||||||
title: 'Access提供者',
|
|
||||||
helper: 'access授权',
|
|
||||||
component: {
|
|
||||||
name: 'access-selector',
|
|
||||||
type: 'tencent',
|
|
||||||
},
|
|
||||||
required: true,
|
|
||||||
})
|
|
||||||
accessId!: string;
|
|
||||||
|
|
||||||
client: any;
|
client: any;
|
||||||
async onInstance() {
|
async onInstance() {
|
||||||
@@ -234,12 +241,23 @@ export class DeployCertToTencentCLB extends AbstractTaskPlugin {
|
|||||||
return name + '-' + dayjs().format('YYYYMMDD-HHmmss');
|
return name + '-' + dayjs().format('YYYYMMDD-HHmmss');
|
||||||
}
|
}
|
||||||
buildProps() {
|
buildProps() {
|
||||||
|
const certId = this.cert as string;
|
||||||
|
const certInfo = this.cert as CertInfo;
|
||||||
|
if (typeof this.cert === 'string') {
|
||||||
|
return {
|
||||||
|
Certificate: {
|
||||||
|
CertId: certId,
|
||||||
|
},
|
||||||
|
LoadBalancerId: this.loadBalancerId,
|
||||||
|
ListenerId: this.listenerId,
|
||||||
|
};
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
Certificate: {
|
Certificate: {
|
||||||
SSLMode: 'UNIDIRECTIONAL', // 单向认证
|
SSLMode: 'UNIDIRECTIONAL', // 单向认证
|
||||||
CertName: this.appendTimeSuffix(this.certName || this.cert.domain),
|
CertName: this.appendTimeSuffix(this.certName || "certd"),
|
||||||
CertKey: this.cert.key,
|
CertKey: certInfo.key,
|
||||||
CertContent: this.cert.crt,
|
CertContent: certInfo.crt,
|
||||||
},
|
},
|
||||||
LoadBalancerId: this.loadBalancerId,
|
LoadBalancerId: this.loadBalancerId,
|
||||||
ListenerId: this.listenerId,
|
ListenerId: this.listenerId,
|
||||||
|
|||||||
Generated
+115
-38
@@ -49,7 +49,7 @@ importers:
|
|||||||
packages/core/acme-client:
|
packages/core/acme-client:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@certd/basic':
|
'@certd/basic':
|
||||||
specifier: ^1.39.7
|
specifier: ^1.39.9
|
||||||
version: link:../basic
|
version: link:../basic
|
||||||
'@peculiar/x509':
|
'@peculiar/x509':
|
||||||
specifier: ^1.11.0
|
specifier: ^1.11.0
|
||||||
@@ -213,11 +213,11 @@ importers:
|
|||||||
packages/core/pipeline:
|
packages/core/pipeline:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@certd/basic':
|
'@certd/basic':
|
||||||
specifier: ^1.39.7
|
specifier: ^1.39.9
|
||||||
version: link:../basic
|
version: link:../basic
|
||||||
'@certd/plus-core':
|
'@certd/plus-core':
|
||||||
specifier: ^1.39.7
|
specifier: ^1.39.9
|
||||||
version: link:../../pro/plus-core
|
version: 1.39.9
|
||||||
dayjs:
|
dayjs:
|
||||||
specifier: ^1.11.7
|
specifier: ^1.11.7
|
||||||
version: 1.11.13
|
version: 1.11.13
|
||||||
@@ -412,7 +412,7 @@ importers:
|
|||||||
packages/libs/lib-k8s:
|
packages/libs/lib-k8s:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@certd/basic':
|
'@certd/basic':
|
||||||
specifier: ^1.39.7
|
specifier: ^1.39.9
|
||||||
version: link:../../core/basic
|
version: link:../../core/basic
|
||||||
'@kubernetes/client-node':
|
'@kubernetes/client-node':
|
||||||
specifier: 0.21.0
|
specifier: 0.21.0
|
||||||
@@ -452,20 +452,20 @@ importers:
|
|||||||
packages/libs/lib-server:
|
packages/libs/lib-server:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@certd/acme-client':
|
'@certd/acme-client':
|
||||||
specifier: ^1.39.7
|
specifier: ^1.39.9
|
||||||
version: link:../../core/acme-client
|
version: link:../../core/acme-client
|
||||||
'@certd/basic':
|
'@certd/basic':
|
||||||
specifier: ^1.39.7
|
specifier: ^1.39.9
|
||||||
version: link:../../core/basic
|
version: link:../../core/basic
|
||||||
'@certd/pipeline':
|
'@certd/pipeline':
|
||||||
specifier: ^1.39.7
|
specifier: ^1.39.9
|
||||||
version: link:../../core/pipeline
|
version: link:../../core/pipeline
|
||||||
'@certd/plugin-lib':
|
'@certd/plugin-lib':
|
||||||
specifier: ^1.39.7
|
specifier: ^1.39.9
|
||||||
version: link:../../plugins/plugin-lib
|
version: link:../../plugins/plugin-lib
|
||||||
'@certd/plus-core':
|
'@certd/plus-core':
|
||||||
specifier: ^1.39.7
|
specifier: ^1.39.9
|
||||||
version: link:../../pro/plus-core
|
version: 1.39.9
|
||||||
'@midwayjs/cache':
|
'@midwayjs/cache':
|
||||||
specifier: 3.14.0
|
specifier: 3.14.0
|
||||||
version: 3.14.0
|
version: 3.14.0
|
||||||
@@ -610,16 +610,16 @@ importers:
|
|||||||
packages/plugins/plugin-cert:
|
packages/plugins/plugin-cert:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@certd/acme-client':
|
'@certd/acme-client':
|
||||||
specifier: ^1.39.7
|
specifier: ^1.39.9
|
||||||
version: link:../../core/acme-client
|
version: link:../../core/acme-client
|
||||||
'@certd/basic':
|
'@certd/basic':
|
||||||
specifier: ^1.39.7
|
specifier: ^1.39.9
|
||||||
version: link:../../core/basic
|
version: link:../../core/basic
|
||||||
'@certd/pipeline':
|
'@certd/pipeline':
|
||||||
specifier: ^1.39.7
|
specifier: ^1.39.9
|
||||||
version: link:../../core/pipeline
|
version: link:../../core/pipeline
|
||||||
'@certd/plugin-lib':
|
'@certd/plugin-lib':
|
||||||
specifier: ^1.39.7
|
specifier: ^1.39.9
|
||||||
version: link:../plugin-lib
|
version: link:../plugin-lib
|
||||||
psl:
|
psl:
|
||||||
specifier: ^1.9.0
|
specifier: ^1.9.0
|
||||||
@@ -683,17 +683,17 @@ importers:
|
|||||||
specifier: ^3.964.0
|
specifier: ^3.964.0
|
||||||
version: 3.964.0(aws-crt@1.26.2)
|
version: 3.964.0(aws-crt@1.26.2)
|
||||||
'@certd/acme-client':
|
'@certd/acme-client':
|
||||||
specifier: ^1.39.7
|
specifier: ^1.39.9
|
||||||
version: link:../../core/acme-client
|
version: link:../../core/acme-client
|
||||||
'@certd/basic':
|
'@certd/basic':
|
||||||
specifier: ^1.39.7
|
specifier: ^1.39.9
|
||||||
version: link:../../core/basic
|
version: link:../../core/basic
|
||||||
'@certd/pipeline':
|
'@certd/pipeline':
|
||||||
specifier: ^1.39.7
|
specifier: ^1.39.9
|
||||||
version: link:../../core/pipeline
|
version: link:../../core/pipeline
|
||||||
'@certd/plus-core':
|
'@certd/plus-core':
|
||||||
specifier: ^1.39.7
|
specifier: ^1.39.9
|
||||||
version: link:../../pro/plus-core
|
version: 1.39.9
|
||||||
'@kubernetes/client-node':
|
'@kubernetes/client-node':
|
||||||
specifier: 0.21.0
|
specifier: 0.21.0
|
||||||
version: 0.21.0
|
version: 0.21.0
|
||||||
@@ -1249,10 +1249,10 @@ importers:
|
|||||||
version: 0.1.3(zod@3.24.4)
|
version: 0.1.3(zod@3.24.4)
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@certd/lib-iframe':
|
'@certd/lib-iframe':
|
||||||
specifier: ^1.39.7
|
specifier: ^1.39.9
|
||||||
version: link:../../libs/lib-iframe
|
version: link:../../libs/lib-iframe
|
||||||
'@certd/pipeline':
|
'@certd/pipeline':
|
||||||
specifier: ^1.39.7
|
specifier: ^1.39.9
|
||||||
version: link:../../core/pipeline
|
version: link:../../core/pipeline
|
||||||
'@rollup/plugin-commonjs':
|
'@rollup/plugin-commonjs':
|
||||||
specifier: ^25.0.7
|
specifier: ^25.0.7
|
||||||
@@ -1447,47 +1447,47 @@ importers:
|
|||||||
specifier: ^3.990.0
|
specifier: ^3.990.0
|
||||||
version: 3.990.0(aws-crt@1.26.2)
|
version: 3.990.0(aws-crt@1.26.2)
|
||||||
'@certd/acme-client':
|
'@certd/acme-client':
|
||||||
specifier: ^1.39.7
|
specifier: ^1.39.9
|
||||||
version: link:../../core/acme-client
|
version: link:../../core/acme-client
|
||||||
'@certd/basic':
|
'@certd/basic':
|
||||||
specifier: ^1.39.7
|
specifier: ^1.39.9
|
||||||
version: link:../../core/basic
|
version: link:../../core/basic
|
||||||
'@certd/commercial-core':
|
'@certd/commercial-core':
|
||||||
specifier: ^1.39.7
|
specifier: ^1.39.9
|
||||||
version: link:../../pro/commercial-core
|
version: 1.39.9(better-sqlite3@11.10.0)(mysql2@3.14.1)(pg@8.16.0)(reflect-metadata@0.2.2)(ts-node@10.9.2(@types/node@18.19.100)(typescript@5.9.3))
|
||||||
'@certd/cv4pve-api-javascript':
|
'@certd/cv4pve-api-javascript':
|
||||||
specifier: ^8.4.2
|
specifier: ^8.4.2
|
||||||
version: 8.4.2
|
version: 8.4.2
|
||||||
'@certd/jdcloud':
|
'@certd/jdcloud':
|
||||||
specifier: ^1.39.7
|
specifier: ^1.39.9
|
||||||
version: link:../../libs/lib-jdcloud
|
version: link:../../libs/lib-jdcloud
|
||||||
'@certd/lib-huawei':
|
'@certd/lib-huawei':
|
||||||
specifier: ^1.39.7
|
specifier: ^1.39.9
|
||||||
version: link:../../libs/lib-huawei
|
version: link:../../libs/lib-huawei
|
||||||
'@certd/lib-k8s':
|
'@certd/lib-k8s':
|
||||||
specifier: ^1.39.7
|
specifier: ^1.39.9
|
||||||
version: link:../../libs/lib-k8s
|
version: link:../../libs/lib-k8s
|
||||||
'@certd/lib-server':
|
'@certd/lib-server':
|
||||||
specifier: ^1.39.7
|
specifier: ^1.39.9
|
||||||
version: link:../../libs/lib-server
|
version: link:../../libs/lib-server
|
||||||
'@certd/midway-flyway-js':
|
'@certd/midway-flyway-js':
|
||||||
specifier: ^1.39.7
|
specifier: ^1.39.9
|
||||||
version: link:../../libs/midway-flyway-js
|
version: link:../../libs/midway-flyway-js
|
||||||
'@certd/pipeline':
|
'@certd/pipeline':
|
||||||
specifier: ^1.39.7
|
specifier: ^1.39.9
|
||||||
version: link:../../core/pipeline
|
version: link:../../core/pipeline
|
||||||
'@certd/plugin-cert':
|
'@certd/plugin-cert':
|
||||||
specifier: ^1.39.7
|
specifier: ^1.39.9
|
||||||
version: link:../../plugins/plugin-cert
|
version: link:../../plugins/plugin-cert
|
||||||
'@certd/plugin-lib':
|
'@certd/plugin-lib':
|
||||||
specifier: ^1.39.7
|
specifier: ^1.39.9
|
||||||
version: link:../../plugins/plugin-lib
|
version: link:../../plugins/plugin-lib
|
||||||
'@certd/plugin-plus':
|
'@certd/plugin-plus':
|
||||||
specifier: ^1.39.7
|
specifier: ^1.39.9
|
||||||
version: link:../../pro/plugin-plus
|
version: 1.39.9
|
||||||
'@certd/plus-core':
|
'@certd/plus-core':
|
||||||
specifier: ^1.39.7
|
specifier: ^1.39.9
|
||||||
version: link:../../pro/plus-core
|
version: 1.39.9
|
||||||
'@google-cloud/publicca':
|
'@google-cloud/publicca':
|
||||||
specifier: ^1.3.0
|
specifier: ^1.3.0
|
||||||
version: 1.3.0(encoding@0.1.13)
|
version: 1.3.0(encoding@0.1.13)
|
||||||
@@ -1719,6 +1719,9 @@ importers:
|
|||||||
wechatpay-node-v3:
|
wechatpay-node-v3:
|
||||||
specifier: ^2.2.1
|
specifier: ^2.2.1
|
||||||
version: 2.2.1
|
version: 2.2.1
|
||||||
|
whoiser:
|
||||||
|
specifier: 2.0.0-beta.10
|
||||||
|
version: 2.0.0-beta.10
|
||||||
xml2js:
|
xml2js:
|
||||||
specifier: ^0.6.2
|
specifier: ^0.6.2
|
||||||
version: 0.6.2
|
version: 0.6.2
|
||||||
@@ -2835,9 +2838,18 @@ packages:
|
|||||||
'@better-scroll/zoom@2.5.1':
|
'@better-scroll/zoom@2.5.1':
|
||||||
resolution: {integrity: sha512-aGvFY5ooeZWS4RcxQLD+pGLpQHQxpPy0sMZV3yadcd2QK53PK9gS4Dp+BYfRv8lZ4/P2LoNEhr6Wq1DN6+uPlA==}
|
resolution: {integrity: sha512-aGvFY5ooeZWS4RcxQLD+pGLpQHQxpPy0sMZV3yadcd2QK53PK9gS4Dp+BYfRv8lZ4/P2LoNEhr6Wq1DN6+uPlA==}
|
||||||
|
|
||||||
|
'@certd/commercial-core@1.39.9':
|
||||||
|
resolution: {integrity: sha512-oq4rWrK6Xxy9hkxZaUbQbZ2pFgtRcPuqlg9Ud1vtzO8zmFkZY48j+vsUH0V32k1dNr75BIl9r9RFY2Vwc6rcVg==}
|
||||||
|
|
||||||
'@certd/cv4pve-api-javascript@8.4.2':
|
'@certd/cv4pve-api-javascript@8.4.2':
|
||||||
resolution: {integrity: sha512-udGce7ewrVl4DmZvX+17PjsnqsdDIHEDatr8QP0AVrY2p+8JkaSPW4mXCKiLGf82C9K2+GXgT+qNIqgW7tfF9Q==}
|
resolution: {integrity: sha512-udGce7ewrVl4DmZvX+17PjsnqsdDIHEDatr8QP0AVrY2p+8JkaSPW4mXCKiLGf82C9K2+GXgT+qNIqgW7tfF9Q==}
|
||||||
|
|
||||||
|
'@certd/plugin-plus@1.39.9':
|
||||||
|
resolution: {integrity: sha512-OdY0glIHQeaGUYwH8KvN++go4QB5KUBmRvw1jzIDKu5pHZEKkEij0UBfeDv8a5CC9ynA+4/aoNPCvB0tncNuCg==}
|
||||||
|
|
||||||
|
'@certd/plus-core@1.39.9':
|
||||||
|
resolution: {integrity: sha512-75Wo4KQoHFxhWwLB3XjRC+ihButagGiaxiwS1u4oVzESW9EqQ+XKcGEw/WJF3oh81dE7orexo2nA4p/PdoTSlg==}
|
||||||
|
|
||||||
'@certd/vue-js-cron-core@6.0.3':
|
'@certd/vue-js-cron-core@6.0.3':
|
||||||
resolution: {integrity: sha512-kqzoAMhYz9j6FGNWEODRYtt4NpUEUwjpkU89z5WVg2tCtOcI5VhwyUGOd8AxiBCRfd6PtXvzuqw85PaOps9wrQ==}
|
resolution: {integrity: sha512-kqzoAMhYz9j6FGNWEODRYtt4NpUEUwjpkU89z5WVg2tCtOcI5VhwyUGOd8AxiBCRfd6PtXvzuqw85PaOps9wrQ==}
|
||||||
|
|
||||||
@@ -10743,6 +10755,10 @@ packages:
|
|||||||
pump@3.0.2:
|
pump@3.0.2:
|
||||||
resolution: {integrity: sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==}
|
resolution: {integrity: sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==}
|
||||||
|
|
||||||
|
punycode-esm@1.0.15:
|
||||||
|
resolution: {integrity: sha512-pR7pzaunGU4g3v3vMIXD9WnrGUiEBs2ezcVYr9piTC/HVem9F+MJ+JNdSeYD9pK7EumLMUMO9F3Gsa3RS+o7pA==}
|
||||||
|
engines: {node: '>=20'}
|
||||||
|
|
||||||
punycode.js@2.3.1:
|
punycode.js@2.3.1:
|
||||||
resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==}
|
resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
@@ -12737,6 +12753,9 @@ packages:
|
|||||||
engines: {node: ^16.13.0 || >=18.0.0}
|
engines: {node: ^16.13.0 || >=18.0.0}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
whoiser@2.0.0-beta.10:
|
||||||
|
resolution: {integrity: sha512-Y1uyLNR6zQnKj/mZPYtofs6u/9ZAnBzAuiTgU1aEMKjlnknrQdLyOKv9ErmIeF2mySMjGFj0tCam+DpxotBXHw==}
|
||||||
|
|
||||||
why-is-node-running@2.3.0:
|
why-is-node-running@2.3.0:
|
||||||
resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==}
|
resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
@@ -15136,12 +15155,64 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@better-scroll/core': 2.5.1
|
'@better-scroll/core': 2.5.1
|
||||||
|
|
||||||
|
'@certd/commercial-core@1.39.9(better-sqlite3@11.10.0)(mysql2@3.14.1)(pg@8.16.0)(reflect-metadata@0.2.2)(ts-node@10.9.2(@types/node@18.19.100)(typescript@5.9.3))':
|
||||||
|
dependencies:
|
||||||
|
'@certd/basic': link:packages/core/basic
|
||||||
|
'@certd/lib-server': link:packages/libs/lib-server
|
||||||
|
'@certd/pipeline': link:packages/core/pipeline
|
||||||
|
'@certd/plus-core': 1.39.9
|
||||||
|
'@midwayjs/core': 3.20.11
|
||||||
|
'@midwayjs/koa': 3.20.13
|
||||||
|
'@midwayjs/logger': 3.4.2
|
||||||
|
'@midwayjs/swagger': 3.20.11
|
||||||
|
'@midwayjs/typeorm': 3.20.11
|
||||||
|
dayjs: 1.11.13
|
||||||
|
typeorm: 0.3.24(better-sqlite3@11.10.0)(mysql2@3.14.1)(pg@8.16.0)(reflect-metadata@0.2.2)(ts-node@10.9.2(@types/node@18.19.100)(typescript@5.9.3))
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- '@google-cloud/spanner'
|
||||||
|
- '@sap/hana-client'
|
||||||
|
- babel-plugin-macros
|
||||||
|
- better-sqlite3
|
||||||
|
- hdb-pool
|
||||||
|
- ioredis
|
||||||
|
- mongodb
|
||||||
|
- mssql
|
||||||
|
- mysql2
|
||||||
|
- oracledb
|
||||||
|
- pg
|
||||||
|
- pg-native
|
||||||
|
- pg-query-stream
|
||||||
|
- redis
|
||||||
|
- reflect-metadata
|
||||||
|
- sql.js
|
||||||
|
- sqlite3
|
||||||
|
- supports-color
|
||||||
|
- ts-node
|
||||||
|
- typeorm-aurora-data-api-driver
|
||||||
|
|
||||||
'@certd/cv4pve-api-javascript@8.4.2':
|
'@certd/cv4pve-api-javascript@8.4.2':
|
||||||
dependencies:
|
dependencies:
|
||||||
debug: 4.4.3(supports-color@8.1.1)
|
debug: 4.4.3(supports-color@8.1.1)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
|
'@certd/plugin-plus@1.39.9':
|
||||||
|
dependencies:
|
||||||
|
'@certd/basic': link:packages/core/basic
|
||||||
|
'@certd/pipeline': link:packages/core/pipeline
|
||||||
|
'@certd/plugin-lib': link:packages/plugins/plugin-lib
|
||||||
|
'@certd/plus-core': 1.39.9
|
||||||
|
crypto-js: 4.2.0
|
||||||
|
dayjs: 1.11.13
|
||||||
|
form-data: 4.0.2
|
||||||
|
jsrsasign: 11.1.0
|
||||||
|
querystring: 0.2.1
|
||||||
|
|
||||||
|
'@certd/plus-core@1.39.9':
|
||||||
|
dependencies:
|
||||||
|
'@certd/basic': link:packages/core/basic
|
||||||
|
dayjs: 1.11.13
|
||||||
|
|
||||||
'@certd/vue-js-cron-core@6.0.3':
|
'@certd/vue-js-cron-core@6.0.3':
|
||||||
dependencies:
|
dependencies:
|
||||||
mustache: 4.2.0
|
mustache: 4.2.0
|
||||||
@@ -24561,6 +24632,8 @@ snapshots:
|
|||||||
end-of-stream: 1.4.4
|
end-of-stream: 1.4.4
|
||||||
once: 1.4.0
|
once: 1.4.0
|
||||||
|
|
||||||
|
punycode-esm@1.0.15: {}
|
||||||
|
|
||||||
punycode.js@2.3.1: {}
|
punycode.js@2.3.1: {}
|
||||||
|
|
||||||
punycode@1.4.1: {}
|
punycode@1.4.1: {}
|
||||||
@@ -26843,6 +26916,10 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
isexe: 3.1.1
|
isexe: 3.1.1
|
||||||
|
|
||||||
|
whoiser@2.0.0-beta.10:
|
||||||
|
dependencies:
|
||||||
|
punycode-esm: 1.0.15
|
||||||
|
|
||||||
why-is-node-running@2.3.0:
|
why-is-node-running@2.3.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
siginfo: 2.0.0
|
siginfo: 2.0.0
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
01:07
|
01:26
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
01:28
|
01:53
|
||||||
|
|||||||
Reference in New Issue
Block a user