Compare commits

...

30 Commits

Author SHA1 Message Date
xiaojunnuo
adc3e6118b v1.39.7 2026-03-26 01:06:27 +08:00
xiaojunnuo
d933493c31 build: prepare to build 2026-03-26 01:02:42 +08:00
xiaojunnuo
f91d591b03 perf: 支持部署证书到火山引擎vod 2026-03-26 01:01:52 +08:00
xiaojunnuo
af6deb99cd perf: 支持部署到火山云tos自定义域名证书
https://github.com/certd/certd/issues/693
2026-03-26 00:05:30 +08:00
xiaojunnuo
c5d285f755 Merge branch 'v2-dev' of https://github.com/certd/certd into v2-dev 2026-03-25 12:48:56 +08:00
xiaojunnuo
b1eb706925 fix: 修复cname校验报该授权无权限的bug 2026-03-25 12:48:47 +08:00
xiaojunnuo
5a01634ca3 build: release 2026-03-23 00:23:32 +08:00
xiaojunnuo
487676ce13 build: publish 2026-03-23 00:07:52 +08:00
xiaojunnuo
0280ca7b1a build: trigger build image 2026-03-23 00:07:40 +08:00
xiaojunnuo
b0ccab41e1 v1.39.6 2026-03-23 00:06:18 +08:00
xiaojunnuo
ccda3a3325 build: prepare to build 2026-03-23 00:03:15 +08:00
xiaojunnuo
4b7eeaa6e0 perf: 新增阿里云证书清理插件 2026-03-23 00:02:46 +08:00
xiaojunnuo
2951f0030d build: prepare to build 2026-03-22 23:33:45 +08:00
xiaojunnuo
acc2df29de perf: 支持复制粘贴任务步骤 2026-03-22 23:31:24 +08:00
xiaojunnuo
431afd618f perf: 企业模式下面增加个人数据迁移的引导 2026-03-22 00:49:54 +08:00
xiaojunnuo
6d5e5bd692 chore: 优化access edit 请求参数,删除多余的参数 2026-03-21 23:59:11 +08:00
xiaojunnuo
ffd2e8149e perf: 火山引擎部署alb证书插件支持部署扩展证书以及删除已过期扩展证书 2026-03-21 23:51:30 +08:00
xiaojunnuo
2ab92dc13e chore: cnb_sync 2026-03-20 18:14:31 +08:00
xiaojunnuo
7f6a8bc87e perf: 优化远程数据选择框,选择数据时不刷新闪烁 2026-03-20 18:04:13 +08:00
xiaojunnuo
b1ff163a28 fix: 修复模版id不正确导致修改到错误的模版流水线bug 2026-03-20 17:48:47 +08:00
xiaojunnuo
440d55ccb8 chore: sync push 2026-03-20 13:53:12 +08:00
xiaojunnuo
285532d431 fix: remote-select默认pageSize设置为50,阿里云WAF不支持pageSize100 2026-03-20 13:44:49 +08:00
xiaojunnuo
f2c47459f8 Merge branch 'v2' of https://github.com/certd/certd into v2 2026-03-20 12:09:01 +08:00
xiaojunnuo
49703f08e5 fix: 修复批量执行按钮无效的bug 2026-03-20 12:08:55 +08:00
xiaojunnuo
1d0aa9573b Merge branch 'v2' of https://github.com/certd/certd into v2 2026-03-19 01:12:34 +08:00
xiaojunnuo
b2014cf88b build: release 2026-03-19 01:11:46 +08:00
xiaojunnuo
a0e0078bad build: prepare to build 2026-03-19 01:09:00 +08:00
xiaojunnuo
5ebca21c32 build: publish 2026-03-19 00:52:27 +08:00
xiaojunnuo
970aea90c9 build: trigger build image 2026-03-19 00:52:15 +08:00
xiaojunnuo
3332d2288f chore: 支持推送到cnb 2026-03-18 16:16:22 +08:00
72 changed files with 1630 additions and 294 deletions

View File

@@ -17,6 +17,7 @@ jobs:
with:
fetch-depth: 0
lfs: true
ref: v2-dev
- name: Set git user # 2. 给git命令设置用户名和邮箱,↙↙↙ 改成你的name和email
run: |
git config --global user.name "xiaojunnuo"

View File

@@ -17,6 +17,7 @@ jobs:
with:
fetch-depth: 0
lfs: true
ref: v2
- name: Set git user # 2. 给git命令设置用户名和邮箱,↙↙↙ 改成你的name和email
run: |
git config --global user.name "xiaojunnuo"

35
.github/workflows/sync-to-cnb-dev.yml vendored Normal file
View File

@@ -0,0 +1,35 @@
name: sync-to-cnb-dev
on:
push:
branches: ['v2-dev']
# schedule:
# - # 国际时间 19:17 执行北京时间3:17 ↙↙↙ 改成你想要每天自动执行的时间
# - cron: '17 19 * * *'
permissions:
contents: read
jobs:
sync:
runs-on: ubuntu-latest
steps:
- name: Checkout work repo # 1. 检出当前仓库(certd-sync-work)
uses: actions/checkout@v4
with:
fetch-depth: 0
lfs: true
ref: v2-dev
- name: Set git user # 2. 给git命令设置用户名和邮箱,↙↙↙ 改成你的name和email
run: |
git config --global user.name "xiaojunnuo"
git config --global user.email "xiaojunnuo@qq.com"
- name: Set git token # 3. 给git命令设置token用于push到目标仓库
uses: de-vri-es/setup-git-credentials@v2
with: # token 格式为: username:password
credentials: https://cnb:${{secrets.CNB_TOKEN}}@cnb.cool
- name: push to cnb # 4. 执行同步
run: |
git remote add upstream https://cnb.cool/certd/certd.git
git push --set-upstream upstream v2-dev

34
.github/workflows/sync-to-cnb.yml vendored Normal file
View File

@@ -0,0 +1,34 @@
name: sync-to-cnb
on:
push:
branches: ['v2']
# schedule:
# - # 国际时间 19:17 执行北京时间3:17 ↙↙↙ 改成你想要每天自动执行的时间
# - cron: '17 19 * * *'
permissions:
contents: read
jobs:
sync:
runs-on: ubuntu-latest
steps:
- name: Checkout work repo # 1. 检出当前仓库(certd-sync-work)
uses: actions/checkout@v4
with:
fetch-depth: 0
lfs: true
- name: Set git user # 2. 给git命令设置用户名和邮箱,↙↙↙ 改成你的name和email
run: |
git config --global user.name "xiaojunnuo"
git config --global user.email "xiaojunnuo@qq.com"
- name: Set git token # 3. 给git命令设置token用于push到目标仓库
uses: de-vri-es/setup-git-credentials@v2
with: # token 格式为: username:password
credentials: https://cnb:${{secrets.CNB_TOKEN}}@cnb.cool
- name: push to cnb # 4. 执行同步
run: |
git remote add upstream https://cnb.cool/certd/certd.git
git push --set-upstream upstream v2

View File

@@ -17,6 +17,7 @@ jobs:
with:
fetch-depth: 0
lfs: true
ref: v2-dev
- name: Set git user # 2. 给git命令设置用户名和邮箱,↙↙↙ 改成你的name和email
run: |
git config --global user.name "xiaojunnuo"

14
.trae/skills/agent.md Normal file
View File

@@ -0,0 +1,14 @@
你是一名资深nodejs工程师擅长开发Certd开源系统的任务插件。
certd是一款全自动证书申请部署管理工具基于流水线的方式通过里面申请证书插件申请证书然后将证书传递给下一个部署任务插件不同的部署任务插件将证书部署到用户的各个应用系统当中。
certd插件分成以下几种类型
Access存储用户的第三放应用的授权数据比如用户名密码accessSecret 或 accessToken等。同时它里面的方法还负责对接第三方的api接口
Task 部署任务插件它继承AbstractTaskPlugin类被流水线调用execute方法将证书部署到对应的应用上
DnsProvider: DNS提供商插件它用于在ACME申请证书时给域名添加txt解析记录。
在开始工作前,请阅读并加载.trae/skills下面的技能根据skills进行相应的插件开发
当开发过程中遇到问题需要参考plugins目录下的其他插件或者用户提醒你更好的做法时你需要总结经验更新相应的skills让skills越来越完善能够在以后得新插件开发中具备指导意义。
一般调用的api接口文档会比较复杂你不知道接口是什么时请务必询问用户让用户提供API接口文档
完成开发后无需测试,通知用户自己去测试

View File

@@ -3,6 +3,33 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.39.7](https://github.com/certd/certd/compare/v1.39.6...v1.39.7) (2026-03-25)
### Bug Fixes
* 修复cname校验报该授权无权限的bug ([b1eb706](https://github.com/certd/certd/commit/b1eb7069258d6ff2b128091911fa448eaffc5f33))
### Performance Improvements
* 支持部署到火山云tos自定义域名证书 ([af6deb9](https://github.com/certd/certd/commit/af6deb99cd24a69a189b1fdd1df51c8f7816dcda))
* 支持部署证书到火山引擎vod ([f91d591](https://github.com/certd/certd/commit/f91d591b03c50166d9fa352ba11c62d963869aa5))
## [1.39.6](https://github.com/certd/certd/compare/v1.39.5...v1.39.6) (2026-03-22)
### Bug Fixes
* 修复模版id不正确导致修改到错误的模版流水线bug ([b1ff163](https://github.com/certd/certd/commit/b1ff163a2828b205297408d5aed21cf1eff335e8))
* 修复批量执行按钮无效的bug ([49703f0](https://github.com/certd/certd/commit/49703f08e55b303851086d9f36aca562d7999be6))
* remote-select默认pageSize设置为50阿里云WAF不支持pageSize100 ([285532d](https://github.com/certd/certd/commit/285532d4318b90d0d7f8154f070274c0a0ec0269))
### Performance Improvements
* 火山引擎部署alb证书插件支持部署扩展证书以及删除已过期扩展证书 ([ffd2e81](https://github.com/certd/certd/commit/ffd2e8149e3a06bf3eec456ff85dbed793af9e90))
* 企业模式下面增加个人数据迁移的引导 ([431afd6](https://github.com/certd/certd/commit/431afd618f547cecf9a29433f46d4367619e2ecf))
* 新增阿里云证书清理插件 ([4b7eeaa](https://github.com/certd/certd/commit/4b7eeaa6e0a14d2e461c7c473a920a0966b1fe8e))
* 优化远程数据选择框,选择数据时不刷新闪烁 ([7f6a8bc](https://github.com/certd/certd/commit/7f6a8bc87e364685defe7f039264b2de064806c5))
* 支持复制粘贴任务步骤 ([acc2df2](https://github.com/certd/certd/commit/acc2df29def017fb8165f931b41ef95414966afc))
## [1.39.5](https://github.com/certd/certd/compare/v1.39.4...v1.39.5) (2026-03-18)
### Bug Fixes

View File

@@ -3,6 +3,34 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.39.6](https://github.com/certd/certd/compare/v1.39.5...v1.39.6) (2026-03-22)
### Bug Fixes
* 修复模版id不正确导致修改到错误的模版流水线bug ([b1ff163](https://github.com/certd/certd/commit/b1ff163a2828b205297408d5aed21cf1eff335e8))
* 修复批量执行按钮无效的bug ([49703f0](https://github.com/certd/certd/commit/49703f08e55b303851086d9f36aca562d7999be6))
* remote-select默认pageSize设置为50阿里云WAF不支持pageSize100 ([285532d](https://github.com/certd/certd/commit/285532d4318b90d0d7f8154f070274c0a0ec0269))
### Performance Improvements
* 火山引擎部署alb证书插件支持部署扩展证书以及删除已过期扩展证书 ([ffd2e81](https://github.com/certd/certd/commit/ffd2e8149e3a06bf3eec456ff85dbed793af9e90))
* 企业模式下面增加个人数据迁移的引导 ([431afd6](https://github.com/certd/certd/commit/431afd618f547cecf9a29433f46d4367619e2ecf))
* 新增阿里云证书清理插件 ([4b7eeaa](https://github.com/certd/certd/commit/4b7eeaa6e0a14d2e461c7c473a920a0966b1fe8e))
* 优化远程数据选择框,选择数据时不刷新闪烁 ([7f6a8bc](https://github.com/certd/certd/commit/7f6a8bc87e364685defe7f039264b2de064806c5))
* 支持复制粘贴任务步骤 ([acc2df2](https://github.com/certd/certd/commit/acc2df29def017fb8165f931b41ef95414966afc))
## [1.39.5](https://github.com/certd/certd/compare/v1.39.4...v1.39.5) (2026-03-18)
### Bug Fixes
* 修复修改分组报错的bug ([224db7d](https://github.com/certd/certd/commit/224db7da57dbdddf25bcac7faa0a29eb228c5a33))
### Performance Improvements
* 移除passkey的counter递增校验 ([68b669d](https://github.com/certd/certd/commit/68b669d3ff3e13b931939093320ce7237bb02b1b))
* passkey 支持Bitwarden ([29f44c6](https://github.com/certd/certd/commit/29f44c67c808bed9ff1c9d4884d39a1a62d043a7))
* passkey登录放到下方其他登录位置 ([1413e1a](https://github.com/certd/certd/commit/1413e1aff4aabcfd471716338c210fbcfd76c8f9))
## [1.39.4](https://github.com/certd/certd/compare/v1.39.3...v1.39.4) (2026-03-17)
### Bug Fixes

View File

@@ -1,5 +1,5 @@
# 任务插件
`125` 款任务插件
`128` 款任务插件
## 1. 证书申请
| 序号 | 名称 | 说明 |
@@ -81,22 +81,23 @@
| 序号 | 名称 | 说明 |
|-----|-----|-----|
| 1.| **阿里云-部署到Ack** | 部署到阿里云Ack集群Ingress等通过Secret管理证书的应用 |
| 2.| **阿里云-部署至ALB应用负载均衡** | ALB,更新监听器的默认证书 |
| 3.| **阿里云-部署至任意云资源** | 【不建议使用】需要消耗阿里云自动部署次数支持SLB、LIVE、webHosting、VOD、CR、DCDN、DDoS、CDN、ALB、APIGateway、FC、GA、MSE、NLB、OSS、SAE、WAF等云产品 |
| 4.| **阿里云-部署至云原生API网关/AI网关** | 自动部署域名证书至云原生API网关、AI网关 |
| 5.| **阿里云-部署证书至API网关** | 自动部署域名证书至阿里云API网关APIGateway |
| 6.| **阿里云-部署证书至CDN** | 自动部署域名证书至阿里云CDN |
| 7.| **阿里云-部署证书至DCDN** | 依赖证书申请前置任务,自动部署域名证书至阿里云DCDN |
| 8.| **阿里云-部署至ESA** | 部署证书到阿里云ESA(边缘安全加速),自动删除过期证书 |
| 9.| **阿里云-部署至阿里云FC(3.0)** | 部署证书到阿里云函数计算FC3.0 |
| 10.| **阿里云-部署至GA** | 部署证书到阿里云GA(全球加速),支持更新默认证书和扩展证书 |
| 11.| **阿里云-部署至NLB网络负载均衡** | NLB,网络负载均衡,更新监听器的默认证书 |
| 12.| **阿里云-部署证书至OSS** | 部署域名证书至阿里云OSS自定义域名不是上传到阿里云oss |
| 13.| **阿里云-部署至CLB(传统负载均衡)** | 部署证书到阿里云CLB(传统负载均衡) |
| 14.| **阿里云-部署至VOD** | 部署证书到阿里云视频点播vod |
| 15.| **阿里云-部署至阿里云WAF** | 部署证书到阿里云WAF |
| 16.| **阿里云-上传证书到CAS** | 上传证书到阿里云证书管理服务CAS如果不想在阿里云上同一份证书上传多次可以把此任务作为前置任务其他阿里云任务证书那一项选择此任务的输出 |
| 1.| **阿里云-删除即将过期证书** | 仅删除未使用的证书 |
| 2.| **阿里云-部署到Ack** | 部署到阿里云Ack集群Ingress等通过Secret管理证书的应用 |
| 3.| **阿里云-部署至ALB应用负载均衡** | ALB,更新监听器的默认证书 |
| 4.| **阿里云-部署至任意云资源** | 【不建议使用】需要消耗阿里云自动部署次数支持SLB、LIVE、webHosting、VOD、CR、DCDN、DDoS、CDN、ALB、APIGateway、FC、GA、MSE、NLB、OSS、SAE、WAF等云产品 |
| 5.| **阿里云-部署至云原生API网关/AI网关** | 自动部署域名证书至云原生API网关、AI网关 |
| 6.| **阿里云-部署证书至API网关** | 自动部署域名证书至阿里云API网关APIGateway |
| 7.| **阿里云-部署证书至CDN** | 自动部署域名证书至阿里云CDN |
| 8.| **阿里云-部署证书至DCDN** | 依赖证书申请前置任务自动部署域名证书至阿里云DCDN |
| 9.| **阿里云-部署至ESA** | 部署证书到阿里云ESA(边缘安全加速),自动删除过期证书 |
| 10.| **阿里云-部署至阿里云FC(3.0)** | 部署证书到阿里云函数计算FC3.0 |
| 11.| **阿里云-部署至GA** | 部署证书到阿里云GA(全球加速),支持更新默认证书和扩展证书 |
| 12.| **阿里云-部署至NLB网络负载均衡** | NLB,网络负载均衡,更新监听器的默认证书 |
| 13.| **阿里云-部署证书至OSS** | 部署域名证书至阿里云OSS自定义域名不是上传到阿里云oss |
| 14.| **阿里云-部署至CLB(传统负载均衡)** | 部署证书到阿里云CLB(传统负载均衡) |
| 15.| **阿里云-部署至VOD** | 部署证书到阿里云视频点播vod |
| 16.| **阿里云-部署至阿里云WAF** | 部署证书到阿里云WAF |
| 17.| **阿里云-上传证书到CAS** | 上传证书到阿里云证书管理服务CAS如果不想在阿里云上同一份证书上传多次可以把此任务作为前置任务其他阿里云任务证书那一项选择此任务的输出 |
## 6. 华为云
| 序号 | 名称 | 说明 |
@@ -130,8 +131,9 @@
| 3.| **火山引擎-部署证书至CLB** | 部署至火山引擎负载均衡 |
| 4.| **火山引擎-部署证书至DCDN** | 部署至火山引擎全站加速 |
| 5.| **火山引擎-部署证书至Live** | 部署至火山引擎视频直播 |
| 6.| **火山引擎-部署证书至VOD** | 部署至火山引擎视频点播(暂不可用) |
| 7.| **火山引擎-上传证书至证书中心** | 上传证书至火山引擎证书中心 |
| 6.| **火山引擎-部署证书至TOS自定义域名** | 仅限TOS自定义域名加速域名请选择火山引擎的CDN插件 |
| 7.| **火山引擎-部署证书至VOD** | 部署至火山引擎视频点播 |
| 8.| **火山引擎-上传证书至证书中心** | 上传证书至火山引擎证书中心 |
## 9. 京东云
| 序号 | 名称 | 说明 |

View File

@@ -9,5 +9,5 @@
}
},
"npmClient": "pnpm",
"version": "1.39.5"
"version": "1.39.7"
}

View File

@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.39.7](https://github.com/publishlab/node-acme-client/compare/v1.39.6...v1.39.7) (2026-03-25)
**Note:** Version bump only for package @certd/acme-client
## [1.39.6](https://github.com/publishlab/node-acme-client/compare/v1.39.5...v1.39.6) (2026-03-22)
**Note:** Version bump only for package @certd/acme-client
## [1.39.5](https://github.com/publishlab/node-acme-client/compare/v1.39.4...v1.39.5) (2026-03-18)
**Note:** Version bump only for package @certd/acme-client

View File

@@ -3,7 +3,7 @@
"description": "Simple and unopinionated ACME client",
"private": false,
"author": "nmorsman",
"version": "1.39.5",
"version": "1.39.7",
"type": "module",
"module": "scr/index.js",
"main": "src/index.js",
@@ -18,7 +18,7 @@
"types"
],
"dependencies": {
"@certd/basic": "^1.39.5",
"@certd/basic": "^1.39.7",
"@peculiar/x509": "^1.11.0",
"asn1js": "^3.0.5",
"axios": "^1.9.0",
@@ -70,5 +70,5 @@
"bugs": {
"url": "https://github.com/publishlab/node-acme-client/issues"
},
"gitHead": "aacee4a94c2e2481be8a307fb5a6a5d04a09dda7"
"gitHead": "b0ccab41e17cb16c87bfc0ec3b052d5e8a5d8435"
}

View File

@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.39.7](https://github.com/certd/certd/compare/v1.39.6...v1.39.7) (2026-03-25)
**Note:** Version bump only for package @certd/basic
## [1.39.6](https://github.com/certd/certd/compare/v1.39.5...v1.39.6) (2026-03-22)
**Note:** Version bump only for package @certd/basic
## [1.39.5](https://github.com/certd/certd/compare/v1.39.4...v1.39.5) (2026-03-18)
**Note:** Version bump only for package @certd/basic

View File

@@ -1 +1 @@
00:48
01:02

View File

@@ -1,7 +1,7 @@
{
"name": "@certd/basic",
"private": false,
"version": "1.39.5",
"version": "1.39.7",
"type": "module",
"main": "./dist/index.js",
"module": "./dist/index.js",
@@ -47,5 +47,5 @@
"tslib": "^2.8.1",
"typescript": "^5.4.2"
},
"gitHead": "aacee4a94c2e2481be8a307fb5a6a5d04a09dda7"
"gitHead": "b0ccab41e17cb16c87bfc0ec3b052d5e8a5d8435"
}

View File

@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.39.7](https://github.com/certd/certd/compare/v1.39.6...v1.39.7) (2026-03-25)
**Note:** Version bump only for package @certd/pipeline
## [1.39.6](https://github.com/certd/certd/compare/v1.39.5...v1.39.6) (2026-03-22)
**Note:** Version bump only for package @certd/pipeline
## [1.39.5](https://github.com/certd/certd/compare/v1.39.4...v1.39.5) (2026-03-18)
**Note:** Version bump only for package @certd/pipeline

View File

@@ -1,7 +1,7 @@
{
"name": "@certd/pipeline",
"private": false,
"version": "1.39.5",
"version": "1.39.7",
"type": "module",
"main": "./dist/index.js",
"module": "./dist/index.js",
@@ -18,8 +18,8 @@
"compile": "tsc --skipLibCheck --watch"
},
"dependencies": {
"@certd/basic": "^1.39.5",
"@certd/plus-core": "^1.39.5",
"@certd/basic": "^1.39.7",
"@certd/plus-core": "^1.39.7",
"dayjs": "^1.11.7",
"lodash-es": "^4.17.21",
"reflect-metadata": "^0.1.13"
@@ -45,5 +45,5 @@
"tslib": "^2.8.1",
"typescript": "^5.4.2"
},
"gitHead": "aacee4a94c2e2481be8a307fb5a6a5d04a09dda7"
"gitHead": "b0ccab41e17cb16c87bfc0ec3b052d5e8a5d8435"
}

View File

@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.39.7](https://github.com/certd/certd/compare/v1.39.6...v1.39.7) (2026-03-25)
**Note:** Version bump only for package @certd/lib-huawei
## [1.39.6](https://github.com/certd/certd/compare/v1.39.5...v1.39.6) (2026-03-22)
**Note:** Version bump only for package @certd/lib-huawei
## [1.39.5](https://github.com/certd/certd/compare/v1.39.4...v1.39.5) (2026-03-18)
**Note:** Version bump only for package @certd/lib-huawei

View File

@@ -1,7 +1,7 @@
{
"name": "@certd/lib-huawei",
"private": false,
"version": "1.39.5",
"version": "1.39.7",
"main": "./dist/bundle.js",
"module": "./dist/bundle.js",
"types": "./dist/d/index.d.ts",
@@ -24,5 +24,5 @@
"prettier": "^2.8.8",
"tslib": "^2.8.1"
},
"gitHead": "aacee4a94c2e2481be8a307fb5a6a5d04a09dda7"
"gitHead": "b0ccab41e17cb16c87bfc0ec3b052d5e8a5d8435"
}

View File

@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.39.7](https://github.com/certd/certd/compare/v1.39.6...v1.39.7) (2026-03-25)
**Note:** Version bump only for package @certd/lib-iframe
## [1.39.6](https://github.com/certd/certd/compare/v1.39.5...v1.39.6) (2026-03-22)
**Note:** Version bump only for package @certd/lib-iframe
## [1.39.5](https://github.com/certd/certd/compare/v1.39.4...v1.39.5) (2026-03-18)
**Note:** Version bump only for package @certd/lib-iframe

View File

@@ -1,7 +1,7 @@
{
"name": "@certd/lib-iframe",
"private": false,
"version": "1.39.5",
"version": "1.39.7",
"type": "module",
"main": "./dist/index.js",
"module": "./dist/index.js",
@@ -31,5 +31,5 @@
"tslib": "^2.8.1",
"typescript": "^5.4.2"
},
"gitHead": "aacee4a94c2e2481be8a307fb5a6a5d04a09dda7"
"gitHead": "b0ccab41e17cb16c87bfc0ec3b052d5e8a5d8435"
}

View File

@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.39.7](https://github.com/certd/certd/compare/v1.39.6...v1.39.7) (2026-03-25)
**Note:** Version bump only for package @certd/jdcloud
## [1.39.6](https://github.com/certd/certd/compare/v1.39.5...v1.39.6) (2026-03-22)
**Note:** Version bump only for package @certd/jdcloud
## [1.39.5](https://github.com/certd/certd/compare/v1.39.4...v1.39.5) (2026-03-18)
**Note:** Version bump only for package @certd/jdcloud

View File

@@ -1,6 +1,6 @@
{
"name": "@certd/jdcloud",
"version": "1.39.5",
"version": "1.39.7",
"description": "jdcloud openApi sdk",
"main": "./dist/bundle.js",
"module": "./dist/bundle.js",
@@ -56,5 +56,5 @@
"fetch"
]
},
"gitHead": "aacee4a94c2e2481be8a307fb5a6a5d04a09dda7"
"gitHead": "b0ccab41e17cb16c87bfc0ec3b052d5e8a5d8435"
}

View File

@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.39.7](https://github.com/certd/certd/compare/v1.39.6...v1.39.7) (2026-03-25)
**Note:** Version bump only for package @certd/lib-k8s
## [1.39.6](https://github.com/certd/certd/compare/v1.39.5...v1.39.6) (2026-03-22)
**Note:** Version bump only for package @certd/lib-k8s
## [1.39.5](https://github.com/certd/certd/compare/v1.39.4...v1.39.5) (2026-03-18)
**Note:** Version bump only for package @certd/lib-k8s

View File

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

View File

@@ -3,6 +3,16 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.39.7](https://github.com/certd/certd/compare/v1.39.6...v1.39.7) (2026-03-25)
### Bug Fixes
* 修复cname校验报该授权无权限的bug ([b1eb706](https://github.com/certd/certd/commit/b1eb7069258d6ff2b128091911fa448eaffc5f33))
## [1.39.6](https://github.com/certd/certd/compare/v1.39.5...v1.39.6) (2026-03-22)
**Note:** Version bump only for package @certd/lib-server
## [1.39.5](https://github.com/certd/certd/compare/v1.39.4...v1.39.5) (2026-03-18)
**Note:** Version bump only for package @certd/lib-server

View File

@@ -1,6 +1,6 @@
{
"name": "@certd/lib-server",
"version": "1.39.5",
"version": "1.39.7",
"description": "midway with flyway, sql upgrade way ",
"private": false,
"type": "module",
@@ -28,11 +28,11 @@
],
"license": "AGPL",
"dependencies": {
"@certd/acme-client": "^1.39.5",
"@certd/basic": "^1.39.5",
"@certd/pipeline": "^1.39.5",
"@certd/plugin-lib": "^1.39.5",
"@certd/plus-core": "^1.39.5",
"@certd/acme-client": "^1.39.7",
"@certd/basic": "^1.39.7",
"@certd/pipeline": "^1.39.7",
"@certd/plugin-lib": "^1.39.7",
"@certd/plus-core": "^1.39.7",
"@midwayjs/cache": "3.14.0",
"@midwayjs/core": "3.20.11",
"@midwayjs/i18n": "3.20.13",
@@ -64,5 +64,5 @@
"typeorm": "^0.3.11",
"typescript": "^5.4.2"
},
"gitHead": "aacee4a94c2e2481be8a307fb5a6a5d04a09dda7"
"gitHead": "b0ccab41e17cb16c87bfc0ec3b052d5e8a5d8435"
}

View File

@@ -3,8 +3,8 @@ import { IAccessService } from '@certd/pipeline';
export class AccessGetter implements IAccessService {
userId: number;
projectId?: number;
getter: <T>(id: any, userId?: number, projectId?: number) => Promise<T>;
constructor(userId: number, projectId: number, getter: (id: any, userId: number, projectId?: number) => Promise<any>) {
getter: <T>(id: any, userId?: number, projectId?: number, ignorePermission?: boolean) => Promise<T>;
constructor(userId: number, projectId: number, getter: (id: any, userId: number, projectId?: number, ignorePermission?: boolean) => Promise<any>) {
this.userId = userId;
this.projectId = projectId;
this.getter = getter;

View File

@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.39.7](https://github.com/certd/certd/compare/v1.39.6...v1.39.7) (2026-03-25)
**Note:** Version bump only for package @certd/midway-flyway-js
## [1.39.6](https://github.com/certd/certd/compare/v1.39.5...v1.39.6) (2026-03-22)
**Note:** Version bump only for package @certd/midway-flyway-js
## [1.39.5](https://github.com/certd/certd/compare/v1.39.4...v1.39.5) (2026-03-18)
**Note:** Version bump only for package @certd/midway-flyway-js

View File

@@ -1,6 +1,6 @@
{
"name": "@certd/midway-flyway-js",
"version": "1.39.5",
"version": "1.39.7",
"description": "midway with flyway, sql upgrade way ",
"private": false,
"type": "module",
@@ -46,5 +46,5 @@
"typeorm": "^0.3.11",
"typescript": "^5.4.2"
},
"gitHead": "aacee4a94c2e2481be8a307fb5a6a5d04a09dda7"
"gitHead": "b0ccab41e17cb16c87bfc0ec3b052d5e8a5d8435"
}

View File

@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.39.7](https://github.com/certd/certd/compare/v1.39.6...v1.39.7) (2026-03-25)
**Note:** Version bump only for package @certd/plugin-cert
## [1.39.6](https://github.com/certd/certd/compare/v1.39.5...v1.39.6) (2026-03-22)
**Note:** Version bump only for package @certd/plugin-cert
## [1.39.5](https://github.com/certd/certd/compare/v1.39.4...v1.39.5) (2026-03-18)
**Note:** Version bump only for package @certd/plugin-cert

View File

@@ -1,7 +1,7 @@
{
"name": "@certd/plugin-cert",
"private": false,
"version": "1.39.5",
"version": "1.39.7",
"type": "module",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
@@ -17,10 +17,10 @@
"compile": "tsc --skipLibCheck --watch"
},
"dependencies": {
"@certd/acme-client": "^1.39.5",
"@certd/basic": "^1.39.5",
"@certd/pipeline": "^1.39.5",
"@certd/plugin-lib": "^1.39.5",
"@certd/acme-client": "^1.39.7",
"@certd/basic": "^1.39.7",
"@certd/pipeline": "^1.39.7",
"@certd/plugin-lib": "^1.39.7",
"psl": "^1.9.0",
"punycode.js": "^2.3.1"
},
@@ -38,5 +38,5 @@
"tslib": "^2.8.1",
"typescript": "^5.4.2"
},
"gitHead": "aacee4a94c2e2481be8a307fb5a6a5d04a09dda7"
"gitHead": "b0ccab41e17cb16c87bfc0ec3b052d5e8a5d8435"
}

View File

@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.39.7](https://github.com/certd/certd/compare/v1.39.6...v1.39.7) (2026-03-25)
**Note:** Version bump only for package @certd/plugin-lib
## [1.39.6](https://github.com/certd/certd/compare/v1.39.5...v1.39.6) (2026-03-22)
**Note:** Version bump only for package @certd/plugin-lib
## [1.39.5](https://github.com/certd/certd/compare/v1.39.4...v1.39.5) (2026-03-18)
**Note:** Version bump only for package @certd/plugin-lib

View File

@@ -1,7 +1,7 @@
{
"name": "@certd/plugin-lib",
"private": false,
"version": "1.39.5",
"version": "1.39.7",
"type": "module",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
@@ -22,10 +22,10 @@
"@alicloud/pop-core": "^1.7.10",
"@alicloud/tea-util": "^1.4.11",
"@aws-sdk/client-s3": "^3.964.0",
"@certd/acme-client": "^1.39.5",
"@certd/basic": "^1.39.5",
"@certd/pipeline": "^1.39.5",
"@certd/plus-core": "^1.39.5",
"@certd/acme-client": "^1.39.7",
"@certd/basic": "^1.39.7",
"@certd/pipeline": "^1.39.7",
"@certd/plus-core": "^1.39.7",
"@kubernetes/client-node": "0.21.0",
"ali-oss": "^6.22.0",
"basic-ftp": "^5.0.5",
@@ -57,5 +57,5 @@
"tslib": "^2.8.1",
"typescript": "^5.4.2"
},
"gitHead": "aacee4a94c2e2481be8a307fb5a6a5d04a09dda7"
"gitHead": "b0ccab41e17cb16c87bfc0ec3b052d5e8a5d8435"
}

View File

@@ -3,6 +3,23 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.39.7](https://github.com/certd/certd/compare/v1.39.6...v1.39.7) (2026-03-25)
**Note:** Version bump only for package @certd/ui-client
## [1.39.6](https://github.com/certd/certd/compare/v1.39.5...v1.39.6) (2026-03-22)
### Bug Fixes
* 修复模版id不正确导致修改到错误的模版流水线bug ([b1ff163](https://github.com/certd/certd/commit/b1ff163a2828b205297408d5aed21cf1eff335e8))
* remote-select默认pageSize设置为50阿里云WAF不支持pageSize100 ([285532d](https://github.com/certd/certd/commit/285532d4318b90d0d7f8154f070274c0a0ec0269))
### Performance Improvements
* 企业模式下面增加个人数据迁移的引导 ([431afd6](https://github.com/certd/certd/commit/431afd618f547cecf9a29433f46d4367619e2ecf))
* 优化远程数据选择框,选择数据时不刷新闪烁 ([7f6a8bc](https://github.com/certd/certd/commit/7f6a8bc87e364685defe7f039264b2de064806c5))
* 支持复制粘贴任务步骤 ([acc2df2](https://github.com/certd/certd/commit/acc2df29def017fb8165f931b41ef95414966afc))
## [1.39.5](https://github.com/certd/certd/compare/v1.39.4...v1.39.5) (2026-03-18)
### Bug Fixes

View File

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

View File

@@ -104,7 +104,7 @@ const loading = ref(false);
const pagerRef: Ref = ref({
pageNo: 1,
total: 0,
pageSize: props.pageSize || 100,
pageSize: props.pageSize || 50,
});
const getOptions = async () => {
if (loading.value) {
@@ -182,7 +182,7 @@ const getOptions = async () => {
pagerRef.value.pageNo = res.pageNo ?? 1;
}
if (res.pageSize != null) {
pagerRef.value.pageSize = res.pageSize ?? 100;
pagerRef.value.pageSize = res.pageSize ?? pageSize;
}
if (res.total != null) {
pagerRef.value.total = res.total ?? list.length;
@@ -235,9 +235,10 @@ watch(
const { form } = value;
const oldForm: any = oldValue?.form;
let changed = oldForm == null || optionsRef.value.length == 0;
debugger;
if (props.watches && props.watches.length > 0) {
for (const key of props.watches) {
if (oldForm && form[key] != oldForm[key]) {
if (oldForm && JSON.stringify(form[key]) != JSON.stringify(oldForm[key])) {
changed = true;
break;
}

View File

@@ -795,6 +795,8 @@ export default {
reverseProxyEmpty: "No reverse proxy list configured",
environmentVars: "Environment Variables",
environmentVarsHelper: "configure the runtime environment variables, one per line, format: KEY=VALUE",
bindUrl: "Bind URL",
},
},
modal: {

View File

@@ -804,6 +804,7 @@ export default {
reverseProxyEmpty: "未配置反向代理",
environmentVars: "环境变量",
environmentVarsHelper: "配置运行时环境变量每行一个格式KEY=VALUE",
bindUrl: "绑定URL",
},
},
modal: {

View File

@@ -272,14 +272,27 @@ export const useSettingStore = defineStore({
},
async checkUrlBound() {
const userStore = useUserStore();
const settingStore = useSettingStore();
if (!userStore.isAdmin) {
return;
}
const bindUrl = this.installInfo.bindUrl;
const bindUrl2 = this.installInfo.bindUrl2;
if (!bindUrl) {
//绑定url
await this.doBindUrl("url");
} else {
//检查当前url 是否与绑定的url一致
const url = window.location.href;
if (!url.startsWith(bindUrl) && !url.startsWith(bindUrl2)) {
this.openBindUrlModal();
}
}
},
openBindUrlModal() {
const event: any = { ModalRef: null };
mitter.emit("getModal", event);
const Modal = event.ModalRef;
let modalRef: any = null;
const bindUrl = this.installInfo.bindUrl;
const bindUrl2 = this.installInfo.bindUrl2;
@@ -289,57 +302,47 @@ export const useSettingStore = defineStore({
modalRef.destroy();
}
};
if (!bindUrl) {
//绑定url
await this.doBindUrl("url");
} else {
//检查当前url 是否与绑定的url一致
const url = window.location.href;
if (!url.startsWith(bindUrl) && !url.startsWith(bindUrl2)) {
modalRef = Modal.warning({
title: "URL地址未绑定是否绑定此地址",
width: 500,
keyboard: false,
content: () => {
return (
<div class="p-4">
<div class="flex items-center justify-between">
<span>
1
<a-tag color="green">{bindUrl || "未占用"}</a-tag>
</span>
<a-button type="primary" onClick={() => doBindRequest("url")}>
1
</a-button>
</div>
<div class="flex items-center justify-between mt-3">
<span>
2
<a-tag color="green">{bindUrl2 || "未占用"}</a-tag>
</span>
<a-button type="primary" onClick={() => doBindRequest("url2")}>
2
</a-button>
</div>
</div>
);
},
onOk: async () => {
// await this.doBindUrl();
window.location.href = bindUrl;
},
okButtonProps: {
danger: true,
},
okText: "不,回到原来的地址",
cancelText: "不,回到原来的地址",
onCancel: () => {
window.location.href = bindUrl;
},
});
}
}
const modalRef: any = Modal.warning({
title: "URL地址未绑定是否绑定此地址",
width: 500,
keyboard: false,
content: () => {
return (
<div class="p-4">
<div class="flex items-center justify-between">
<span>
1
<a-tag color="green">{bindUrl || "未占用"}</a-tag>
</span>
<a-button type="primary" onClick={() => doBindRequest("url")}>
1
</a-button>
</div>
<div class="flex items-center justify-between mt-3">
<span>
2
<a-tag color="green">{bindUrl2 || "未占用"}</a-tag>
</span>
<a-button type="primary" onClick={() => doBindRequest("url2")}>
2
</a-button>
</div>
</div>
);
},
onOk: async () => {
// await this.doBindUrl();
window.location.href = bindUrl;
},
okButtonProps: {
danger: true,
},
okText: "不,回到原来的地址",
cancelText: "不,回到原来的地址",
onCancel: () => {
window.location.href = bindUrl;
},
});
},
async loadProductInfo() {
try {

View File

@@ -118,3 +118,16 @@ span.fs-icon-svg {
}
}
button.ant-btn.ant-btn-default.isPlus{
color: #c5913f;
border: 1px solid #c5913f;
&:disabled {
cursor: not-allowed;
border-color: hsl(240 5.9% 90%);
color: rgba(50, 54, 57, 0.25);
background-color: rgba(50, 54, 57, 0.04);
box-shadow: none;
}
}

View File

@@ -18,6 +18,8 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
const { form, row } = req;
form.id = row.id;
form.type = props.type;
delete form.access;
delete form.keyId;
const res = await context.api.UpdateObj(form);
lastResRef.value = res;
return res;
@@ -30,6 +32,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
const addRequest = async (req: AddReq) => {
const { form } = req;
form.type = props.type;
delete form.access;
const res = await context.api.AddObj(form);
lastResRef.value = res;
return res;
@@ -70,6 +73,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
width: "1050px",
},
},
rowHandle: {
width: 200,
},
@@ -89,6 +93,9 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
}, // 点击行
};
},
remove: {
confirmMessage: "授权如果已经被使用,可能会导致流水线无法正常运行,请谨慎操作",
},
},
columns: {
id: {

View File

@@ -15,6 +15,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
const editRequest = async (req: EditReq) => {
const { form, row } = req;
form.id = row.id;
delete form.access;
const res = await api.UpdateObj(form);
return res;
};
@@ -25,6 +26,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
const addRequest = async (req: AddReq) => {
const { form } = req;
delete form.access;
const res = await api.AddObj(form);
return res;
};

View File

@@ -16,6 +16,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
const editRequest = async (req: EditReq) => {
const { form, row } = req;
form.id = row.id;
delete form.body;
const res = await api.UpdateObj(form);
return res;
};
@@ -26,6 +27,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
const addRequest = async (req: AddReq) => {
const { form } = req;
delete form.body;
const res = await api.AddObj(form);
return res;
};

View File

@@ -11,6 +11,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
const editRequest = async (req: EditReq) => {
const { form, row } = req;
form.id = row.id;
delete form.body;
const res = await api.UpdateObj(form);
return res;
};
@@ -21,6 +22,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
const addRequest = async (req: AddReq) => {
const { form } = req;
delete form.body;
const res = await api.AddObj(form);
return res;
};

View File

@@ -14,6 +14,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
const editRequest = async (req: EditReq) => {
const { form, row } = req;
form.id = row.id;
delete form.body;
const res = await context.api.UpdateObj(form);
lastResRef.value = res;
return res;
@@ -25,6 +26,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
const addRequest = async (req: AddReq) => {
const { form } = req;
delete form.body;
const res = await context.api.AddObj(form);
lastResRef.value = res;
return res;

View File

@@ -29,15 +29,15 @@ const pipelineOptions: PipelineOptions = {
onLoaded(detail);
return {
pipeline: {
id: detail.pipeline.id,
stages: [],
triggers: [],
...JSON.parse(detail.pipeline.content || "{}"),
type: detail.pipeline.type,
from: detail.pipeline.from,
id: detail.pipeline.id,
userId: detail.pipeline.userId,
projectId: detail.pipeline.projectId,
},
type: detail.pipeline.type,
from: detail.pipeline.from,
validTime: detail.pipeline.validTime,
webhookKey: detail.pipeline.webhookKey,
id: detail.pipeline.id,

View File

@@ -0,0 +1,39 @@
import { reactive, ref } from "vue";
export class CopyeStore {
type: "step" | "steps" | "task" | "tasks";
target: any;
getCopyedCount() {
if (this.type === "step") {
return 1;
} else if (this.type === "steps") {
return this.target.length;
} else if (this.type === "task") {
return 1;
} else if (this.type === "tasks") {
return this.target.length;
} else {
return 0;
}
}
setStep(target: any) {
this.target = target;
this.type = "step";
}
setSteps(target: any) {
this.target = target;
this.type = "steps";
}
setTask(target: any) {
this.target = target;
this.type = "task";
}
setTasks(target: any) {
this.target = target;
this.type = "tasks";
}
}
export const Copyed: any = reactive(new CopyeStore());

View File

@@ -29,7 +29,17 @@
<a-form-item :value="currentTask.steps" name="steps" label="" :wrapper-col="{ span: 24 }" :rules="[{ required: true, message: '至少需要一个步骤,或者你可以点击标题右边删除按钮删除此任务' }]">
<a-descriptions title="任务步骤" size="small">
<template #extra>
<a-button type="primary" @click="stepAdd(currentTask)">添加步骤</a-button>
<div class="flex gap-1">
<a-button type="primary" @click="stepAdd(currentTask)">添加步骤</a-button>
<a-tooltip title="复制此任务下的所有步骤">
<a-button type="default" class="isPlus" :disabled="currentTask.steps?.length === 0" @click="stepsCopy(currentTask)">复制</a-button>
</a-tooltip>
<a-tooltip title="可以从其他任务复制后到此处粘贴">
<a-badge :count="Copyed.getCopyedCount()">
<a-button type="default" class="isPlus" :disabled="Copyed.getCopyedCount() === 0" @click="stepPaste(currentTask)">粘贴</a-button>
</a-badge>
</a-tooltip>
</div>
</template>
</a-descriptions>
<v-draggable v-model="currentTask.steps" class="step-list" handle=".handle" item-key="id" :disabled="!settingStore.isPlus">
@@ -68,14 +78,15 @@
<script lang="ts">
import { provide, Ref, ref } from "vue";
import * as _ from "lodash-es";
import { nanoid } from "nanoid";
import PiStepForm from "../step-form/index.vue";
import { Modal } from "ant-design-vue";
import { message, Modal } from "ant-design-vue";
import VDraggable from "vuedraggable";
import { useUserStore } from "/@/store/user";
import { useSettingStore } from "/@/store/settings";
import { filter } from "lodash-es";
import { Copyed } from "./copy";
import { cloneDeep, merge } from "lodash-es";
export default {
name: "PiTaskForm",
components: { PiStepForm, VDraggable },
@@ -89,6 +100,7 @@ export default {
setup(props: any, ctx: any) {
const userStore = useUserStore();
const settingStore = useSettingStore();
function useStep() {
const stepFormRef: Ref<any> = ref(null);
const currentStepIndex = ref(0);
@@ -106,10 +118,42 @@ export default {
};
const stepCopy = (task: any, step: any, stepIndex: any) => {
step = _.cloneDeep(step);
settingStore.checkPlus();
step = cloneDeep(step);
step.id = nanoid();
step.title = step.title + "_copy";
stepAdd(task, step);
Copyed.type = "step";
Copyed.target = step;
message.success("步骤配置复制成功,您可以到其他任务编辑页面进行粘贴");
};
const stepsCopy = (task: any) => {
settingStore.checkPlus();
const steps = cloneDeep(task.steps);
Copyed.type = "steps";
Copyed.target = steps;
message.success("本任务的所有步骤复制成功,您可以到其他任务编辑页面进行粘贴");
};
const stepPaste = (task: any) => {
settingStore.checkPlus();
if (!Copyed.target) {
message.error("请先复制");
return;
}
if (Copyed.type === "step") {
const step = cloneDeep(Copyed.target);
step.id = nanoid();
step.title = step.title + "_copy";
task.steps.push(step);
} else if (Copyed.type === "steps") {
const steps = cloneDeep(Copyed.target);
for (const item of steps) {
item.id = nanoid();
item.title = item.title + "_copy";
task.steps.push(item);
}
}
message.success("粘贴成功");
};
const stepEdit = (task: any, step: any, stepIndex: any) => {
currentStepIndex.value = stepIndex;
@@ -144,7 +188,7 @@ export default {
step.disabled = !!!step.disabled;
};
return { stepAdd, stepEdit, stepCopy, stepDelete, toggleDisabled, stepFormRef };
return { stepAdd, stepEdit, stepCopy, stepDelete, toggleDisabled, stepFormRef, stepPaste, stepsCopy };
}
/**
@@ -181,7 +225,7 @@ export default {
const taskOpen = (task: any, emit: any) => {
callback.value = emit;
currentTask.value = _.merge({ steps: {} }, task);
currentTask.value = merge({ steps: {} }, task);
console.log("currentTaskOpen", currentTask.value);
taskDrawerShow();
};
@@ -189,7 +233,7 @@ export default {
const taskAdd = (emit: any, taskMerge: any) => {
mode.value = "add";
const blankTask: any = { id: nanoid(), title: "新任务", steps: [], status: null };
const task: any = _.merge(blankTask, taskMerge);
const task: any = merge(blankTask, taskMerge);
taskOpen(task, emit);
};
@@ -262,6 +306,7 @@ export default {
wrapperCol: { span: 20 },
...useTaskForm(),
...useStep(),
Copyed,
};
},
};

View File

@@ -49,6 +49,7 @@ defineOptions({
const route = useRoute();
const projectIdStr = route.query.projectId as string;
const migrate = route.query.migrate as string;
let projectId = Number(projectIdStr);
const projectStore = useProjectStore();
if (!projectId) {
@@ -116,7 +117,11 @@ onMounted(async () => {
return;
}
await loadProjectDetail();
crudExpose.doRefresh();
await crudExpose.doRefresh();
if (migrate === "true") {
openTransferDialog();
}
});
onActivated(async () => {
await crudExpose.doRefresh();

View File

@@ -8,9 +8,10 @@
</div>
<div class="helper">SaaS模式每个用户管理自己的流水线和授权资源独立使用</div>
<div class="helper">企业模式通过项目合作管理流水线证书和授权资源所有用户视为企业内部员工</div>
<div class="helper"><a @click="adminModeIntroOpen = true">更多管理模式介绍</a></div>
<div class="helper text-red-500">建议在开始使用时固定一个合适的模式之后就不要随意切换了</div>
<div v-if="formState.public.adminMode === 'enterprise'" class="helper">设置为企业模式之后,之前创建的个人数据不会显示,您可以选择<a @click="goCurrentProject"> 将个人数据迁移到项目</a></div>
<div v-if="settingsStore.isComm" class="helper text-red-500">商业版不建议设置为企业模式除非你确定要转成企业内部使用</div>
<div><a @click="adminModeIntroOpen = true"> 更多管理模式介绍</a></div>
</a-form-item>
<a-form-item label=" " :colon="false" :wrapper-col="{ span: 8 }">
@@ -33,6 +34,7 @@ import { useI18n } from "/src/locales";
import { dict } from "@fast-crud/fast-crud";
import { useProjectStore } from "/@/store/project";
import AdminModeIntro from "/@/views/sys/enterprise/project/intro.vue";
import { useRouter } from "vue-router";
const { t } = useI18n();
defineOptions({
@@ -82,5 +84,15 @@ const onFinish = async (form: any) => {
saveLoading.value = false;
}
};
const router = useRouter();
const goCurrentProject = () => {
router.push({
path: "/certd/project/detail",
query: {
migrate: "true",
},
});
};
</script>
<style lang="less"></style>

View File

@@ -8,7 +8,7 @@
</div>
<pre class="helper pre">{{ t("certd.sys.setting.passkeyEnabledHelper", [bindDomain]) }}</pre>
<div v-if="!bindDomainIsSame" class="text-red-500 text-sm mt-2">
{{ t("certd.sys.setting.passkeyHostnameNotSame") }}
{{ t("certd.sys.setting.passkeyHostnameNotSame") }} <a-button class="ml-2" size="small" type="primary" @click="settingsStore.openBindUrlModal()">{{ t("certd.sys.setting.bindUrl") }}</a-button>
</div>
</a-form-item>
<a-form-item :label="t('certd.sys.setting.enableOauth')" :name="['public', 'oauthEnabled']">

View File

@@ -3,6 +3,29 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.39.7](https://github.com/certd/certd/compare/v1.39.6...v1.39.7) (2026-03-25)
### Bug Fixes
* 修复cname校验报该授权无权限的bug ([b1eb706](https://github.com/certd/certd/commit/b1eb7069258d6ff2b128091911fa448eaffc5f33))
### Performance Improvements
* 支持部署到火山云tos自定义域名证书 ([af6deb9](https://github.com/certd/certd/commit/af6deb99cd24a69a189b1fdd1df51c8f7816dcda))
* 支持部署证书到火山引擎vod ([f91d591](https://github.com/certd/certd/commit/f91d591b03c50166d9fa352ba11c62d963869aa5))
## [1.39.6](https://github.com/certd/certd/compare/v1.39.5...v1.39.6) (2026-03-22)
### Bug Fixes
* 修复模版id不正确导致修改到错误的模版流水线bug ([b1ff163](https://github.com/certd/certd/commit/b1ff163a2828b205297408d5aed21cf1eff335e8))
* 修复批量执行按钮无效的bug ([49703f0](https://github.com/certd/certd/commit/49703f08e55b303851086d9f36aca562d7999be6))
### Performance Improvements
* 火山引擎部署alb证书插件支持部署扩展证书以及删除已过期扩展证书 ([ffd2e81](https://github.com/certd/certd/commit/ffd2e8149e3a06bf3eec456ff85dbed793af9e90))
* 新增阿里云证书清理插件 ([4b7eeaa](https://github.com/certd/certd/commit/4b7eeaa6e0a14d2e461c7c473a920a0966b1fe8e))
## [1.39.5](https://github.com/certd/certd/compare/v1.39.4...v1.39.5) (2026-03-18)
### Performance Improvements

View File

@@ -0,0 +1,63 @@
showRunStrategy: false
default:
strategy:
runStrategy: 0
name: AliyunDeleteExpiringCert
title: 阿里云-删除即将过期证书
icon: ant-design:aliyun-outlined
group: aliyun
desc: 仅删除未使用的证书
needPlus: true
input:
accessId:
title: Access提供者
helper: access 授权
component:
name: access-selector
type: aliyun
required: true
order: 0
endpoint:
title: 地域
helper: 阿里云CAS证书服务地域
component:
name: a-select
options:
- value: cas.aliyuncs.com
label: 中国大陆
- value: cas.ap-southeast-1.aliyuncs.com
label: 新加坡
required: true
value: cas.aliyuncs.com
order: 0
maxCount:
title: 最大删除数量
helper: 单次运行最大删除数量
value: 100
component:
name: a-input-number
vModel: value
required: true
order: 0
expiringDays:
title: 即将过期天数
helper: 仅删除有效期小于此天数的证书,0表示完全过期时才删除
value: 0
component:
name: a-input-number
vModel: value
required: true
order: 0
checkTimeout:
title: 检查超时时间
helper: 检查删除任务结果超时时间,单位分钟
value: 10
component:
name: a-input-number
vModel: value
required: true
order: 0
output: {}
pluginType: deploy
type: builtIn
scriptFilePath: /plugins/plugin-aliyun/plugin/delete-expiring-cert/index.js

View File

@@ -96,6 +96,19 @@ input:
选择要部署证书的监听器
需要在监听器中选择证书中心,进行跨服务访问授权
order: 0
certType:
title: 证书部署类型
helper: 选择部署默认证书还是扩展证书
component:
name: a-select
options:
- label: 默认证书
value: default
- label: 扩展证书
value: extension
value: default
required: true
order: 0
output: {}
pluginType: deploy
type: builtIn

View File

@@ -0,0 +1,116 @@
showRunStrategy: false
default:
strategy:
runStrategy: 1
name: VolcengineDeployToTOS
title: 火山引擎-部署证书至TOS自定义域名
icon: svg:icon-volcengine
group: volcengine
desc: 仅限TOS自定义域名加速域名请选择火山引擎的CDN插件
input:
cert:
title: 域名证书
helper: 请选择前置任务输出的域名证书
component:
name: output-selector
from:
- ':cert:'
- VolcengineUploadToCertCenter
required: true
order: 0
certDomains:
title: 当前证书域名
component:
name: cert-domains-getter
mergeScript: |2-
return {
component:{
inputKey: ctx.compute(({form})=>{
return form.cert
}),
}
}
template: false
required: false
order: 0
accessId:
title: Access授权
helper: 火山引擎AccessKeyId、AccessKeySecret
component:
name: access-selector
type: volcengine
required: true
order: 0
region:
title: 地域
helper: TOS服务所在地域
component:
name: a-select
options:
- label: 华北2北京
value: cn-beijing
- label: 华东2上海
value: cn-shanghai
- label: 华南1广州
value: cn-guangzhou
- label: 中国香港
value: cn-hongkong
- label: 亚太东南(柔佛)
value: ap-southeast-1
- label: 亚太东南(雅加达)
value: ap-southeast-3
value: cn-beijing
required: true
order: 0
bucket:
title: Bucket
helper: 存储桶名称
component:
name: remote-auto-complete
vModel: value
type: plugin
action: onGetBucketList
search: false
pager: false
watches:
- accessId
- region
required: true
order: 0
domainName:
title: TOS自定义域名
component:
name: remote-select
vModel: value
mode: tags
type: plugin
action: onGetDomainList
search: false
pager: false
multi: true
watches:
- certDomains
- accessId
- certDomains
- accessId
- region
- bucket
required: true
mergeScript: |2-
return {
component:{
form: ctx.compute(({form})=>{
return form
})
},
}
helper: 你在火山引擎上配置的TOS自定义域名比如:example.com
order: 0
output: {}
pluginType: deploy
type: builtIn
scriptFilePath: /plugins/plugin-volcengine/plugins/plugin-deploy-to-tos.js

View File

@@ -6,8 +6,7 @@ name: VolcengineDeployToVOD
title: 火山引擎-部署证书至VOD
icon: svg:icon-volcengine
group: volcengine
desc: 部署至火山引擎视频点播(暂不可用)
deprecated: 暂时缺少部署ssl接口
desc: 部署至火山引擎视频点播
input:
cert:
title: 域名证书
@@ -44,12 +43,64 @@ input:
type: volcengine
required: true
order: 0
regionId:
title: 区域
helper: 选择火山引擎区域
component:
name: select
options:
- value: cn-north-1
label: 华北1北京
- value: ap-southeast-1
label: 东南亚1新加坡
default: cn-north-1
required: true
order: 0
spaceName:
title: 空间名称
component:
name: remote-select
vModel: value
mode: default
type: plugin
action: onGetSpaceList
search: false
pager: false
multi: false
watches:
- certDomains
- accessId
- accessId
- regionId
required: true
mergeScript: |2-
return {
component:{
form: ctx.compute(({form})=>{
return form
})
},
}
helper: 选择要部署证书的点播空间
order: 0
domainType:
title: 域名类型
helper: 选择域名类型
component:
name: a-select
vModel: value
options:
- value: play
label: 点播加速域名
- value: image
label: 封面加速域名
value: play
required: true
order: 0
domainList:
title: 点播域名
title: 域名
component:
name: remote-select
vModel: value
@@ -65,6 +116,7 @@ input:
- certDomains
- accessId
- spaceName
- domainType
required: true
mergeScript: |2-
@@ -77,7 +129,7 @@ input:
}
helper: |-
选择要部署证书的点播域名
选择要部署证书的域名
需要先在域名管理页面进行证书中心访问授权即点击去配置SSL证书
order: 0
output: {}

View File

@@ -1,6 +1,6 @@
{
"name": "@certd/ui-server",
"version": "1.39.5",
"version": "1.39.7",
"description": "fast-server base midway",
"private": true,
"type": "module",
@@ -50,20 +50,20 @@
"@aws-sdk/client-route-53": "^3.964.0",
"@aws-sdk/client-s3": "^3.964.0",
"@aws-sdk/client-sts": "^3.990.0",
"@certd/acme-client": "^1.39.5",
"@certd/basic": "^1.39.5",
"@certd/commercial-core": "^1.39.5",
"@certd/acme-client": "^1.39.7",
"@certd/basic": "^1.39.7",
"@certd/commercial-core": "^1.39.7",
"@certd/cv4pve-api-javascript": "^8.4.2",
"@certd/jdcloud": "^1.39.5",
"@certd/lib-huawei": "^1.39.5",
"@certd/lib-k8s": "^1.39.5",
"@certd/lib-server": "^1.39.5",
"@certd/midway-flyway-js": "^1.39.5",
"@certd/pipeline": "^1.39.5",
"@certd/plugin-cert": "^1.39.5",
"@certd/plugin-lib": "^1.39.5",
"@certd/plugin-plus": "^1.39.5",
"@certd/plus-core": "^1.39.5",
"@certd/jdcloud": "^1.39.7",
"@certd/lib-huawei": "^1.39.7",
"@certd/lib-k8s": "^1.39.7",
"@certd/lib-server": "^1.39.7",
"@certd/midway-flyway-js": "^1.39.7",
"@certd/pipeline": "^1.39.7",
"@certd/plugin-cert": "^1.39.7",
"@certd/plugin-lib": "^1.39.7",
"@certd/plugin-plus": "^1.39.7",
"@certd/plus-core": "^1.39.7",
"@google-cloud/publicca": "^1.3.0",
"@huaweicloud/huaweicloud-sdk-cdn": "^3.1.185",
"@huaweicloud/huaweicloud-sdk-core": "^3.1.185",
@@ -87,6 +87,7 @@
"@simplewebauthn/server": "^13.2.3",
"@ucloud-sdks/ucloud-sdk-js": "^0.2.4",
"@volcengine/openapi": "^1.28.1",
"@volcengine/tos-sdk": "^2.9.1",
"ali-oss": "^6.21.0",
"alipay-sdk": "^4.13.0",
"axios": "^1.9.0",

View File

@@ -20,7 +20,7 @@ import * as commercial from '@certd/commercial-core';
import * as upload from '@midwayjs/upload';
import { setLogger } from '@certd/acme-client';
import {HiddenMiddleware} from "./middleware/hidden.js";
import * as swagger from '@midwayjs/swagger';
// import * as swagger from '@midwayjs/swagger';
//@ts-ignore
// process.env.UV_THREADPOOL_SIZE = 2
process.on('uncaughtException', error => {
@@ -62,10 +62,10 @@ process.on('uncaughtException', error => {
upload,
libServer,
commercial,
{
component: swagger,
enabledEnvironment: ['local']
},
// {
// component: swagger,
// enabledEnvironment: ['local']
// },
{
component: info,
enabledEnvironment: ['local'],

View File

@@ -8,7 +8,7 @@ import {
SysSettingsService,
ValidateException
} from "@certd/lib-server";
import { CnameProvider, CnameRecord, IAccessService } from "@certd/pipeline";
import { CnameProvider, CnameRecord } from "@certd/pipeline";
import { createDnsProvider, DomainParser, IDnsProvider } from "@certd/plugin-cert";
import { Inject, Provide, Scope, ScopeEnum } from "@midwayjs/core";
import { InjectEntityModel } from "@midwayjs/typeorm";
@@ -252,7 +252,6 @@ export class CnameRecordService extends BaseService<CnameRecordEntity> {
}
await this.getByDomain(bean.domain, bean.userId,bean.projectId);
const taskService = this.taskServiceBuilder.create({ userId: bean.userId, projectId: bean.projectId });
const subDomainGetter = await taskService.getSubDomainsGetter();
const domainParser = new DomainParser(subDomainGetter);
@@ -290,10 +289,10 @@ export class CnameRecordService extends BaseService<CnameRecordEntity> {
});
}
const serviceGetter = this.taskServiceBuilder.create({ userId: bean.userId, projectId: bean.projectId });
const accessGetter:IAccessService = await serviceGetter.get("accessService");
const access = await accessGetter.getById(cnameProvider.accessId);
const context = { access, logger, http, utils, domainParser, serviceGetter };
const record = await this.getWithAccessByDomain(bean.domain, bean.userId,bean.projectId);
const access = record.cnameProvider.access
const context = { access, logger, http, utils, domainParser, serviceGetter:taskService };
const dnsProvider: IDnsProvider = await createDnsProvider({
dnsProviderType: cnameProvider.dnsProviderType,
context

View File

@@ -274,6 +274,9 @@ export class PipelineService extends BaseService<PipelineEntity> {
RunnableCollection.initPipelineRunnableType(pipeline);
pipeline.userId = bean.userId;
pipeline.projectId = bean.projectId;
if (bean.id) {
pipeline.id = bean.id;
}
let domains = [];
if (pipeline.stages) {
RunnableCollection.each(pipeline.stages, (runnable: any) => {
@@ -1074,6 +1077,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
if (!isPlus()) {
throw new NeedVIPException("此功能需要升级专业版");
}
//允许管理员修改userId=null
const query: any = {}
if (userId && userId > 0) {
query.userId = userId;
@@ -1126,6 +1130,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
if (!isPlus()) {
throw new NeedVIPException("此功能需要升级专业版");
}
//允许管理员修改userId=null
const query: any = {}
if (userId && userId > 0) {
query.userId = userId;
@@ -1164,9 +1169,9 @@ export class PipelineService extends BaseService<PipelineEntity> {
if (!isPlus()) {
throw new NeedVIPException("此功能需要升级专业版");
}
if (userId == null || ids.length === 0) {
return;
//允许userId为空为空则为管理员触发
if (ids.length === 0) {
throw new Error("参数错误 ids 不能为空");
}
const where: any = {
id: In(ids),

View File

@@ -0,0 +1,159 @@
import { IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from '@certd/pipeline';
import { AbstractPlusTaskPlugin } from "@certd/plugin-plus";
import dayjs from 'dayjs';
import { AliyunAccess } from '../../../plugin-lib/aliyun/access/index.js';
import { AliyunSslClient } from '../../../plugin-lib/aliyun/lib/index.js';
@IsTaskPlugin({
name: 'AliyunDeleteExpiringCert',
title: '阿里云-删除即将过期证书',
icon: 'ant-design:aliyun-outlined',
group: pluginGroups.aliyun.key,
desc: '仅删除未使用的证书',
default: {
strategy: {
runStrategy: RunStrategy.AlwaysRun,
},
},
needPlus: true,
})
export class AliyunDeleteExpiringCert extends AbstractPlusTaskPlugin {
@TaskInput({
title: 'Access提供者',
helper: 'access 授权',
component: {
name: 'access-selector',
type: 'aliyun',
},
required: true,
})
accessId!: string;
@TaskInput({
title: '地域',
helper: '阿里云CAS证书服务地域',
component: {
name: 'a-select',
options: [
{ value: 'cas.aliyuncs.com', label: '中国大陆' },
{ value: 'cas.ap-southeast-1.aliyuncs.com', label: '新加坡' },
],
},
required: true,
value: 'cas.aliyuncs.com',
})
endpoint!: string;
// @TaskInput({
// title: '关键字筛选',
// helper: '仅匹配证书名称、域名包含关键字的证书,可以不填',
// required: false,
// component: {
// name: 'a-input',
// },
// })
// searchKey!: string;
@TaskInput({
title: '最大删除数量',
helper: '单次运行最大删除数量',
value: 100,
component: {
name: 'a-input-number',
vModel: 'value',
},
required: true,
})
maxCount!: number;
@TaskInput({
title: '即将过期天数',
helper: '仅删除有效期小于此天数的证书,0表示完全过期时才删除',
value: 0,
component: {
name: 'a-input-number',
vModel: 'value',
},
required: true,
})
expiringDays!: number;
@TaskInput({
title: '检查超时时间',
helper: '检查删除任务结果超时时间,单位分钟',
value: 10,
component: {
name: 'a-input-number',
vModel: 'value',
},
required: true,
})
checkTimeout!: number;
async onInstance() {}
async execute(): Promise<void> {
const access = await this.getAccess<AliyunAccess>(this.accessId);
const sslClient = new AliyunSslClient({
access,
logger: this.logger,
endpoint: this.endpoint,
});
const params = {
ShowSize: 100,
CurrentPage: 1,
// Keyword: this.searchKey,
};
const certificates: any[] = [];
while(true){
const res = await sslClient.doRequest('ListCertificates', params, {
method: 'POST',
});
let list = res?.CertificateList;
if (!list || list.length === 0) {
break;
}
this.logger.info(`查询第${params.CurrentPage}页,每页${params.ShowSize}个证书,当前页共${list.length}个证书`);
const lastDay = dayjs().add(this.expiringDays, 'day');
list = list.filter((item: any) => {
const notAfter = item.NotAfter;
const usingProducts = item.UsingProductList;
return dayjs(notAfter).isBefore(lastDay) && (!usingProducts || usingProducts.length === 0);
});
for (const item of list) {
this.logger.info(`证书ID:${item.CertificateId}, 过期时间:${item.NotAfter},名称:${item.CertificateName},证书域名:${item.Domain}`);
certificates.push(item);
}
params.CurrentPage++;
}
this.logger.info(`即将过期的证书数量:${certificates.length}`);
if (certificates.length === 0) {
this.logger.info('没有即将过期的证书, 无需删除');
return;
}
this.logger.info(`开始删除证书,共${certificates.length}个证书`);
let successCount = 0;
let failedCount = 0;
for (const certificate of certificates) {
try {
const deleteRes = await sslClient.doRequest('DeleteUserCertificate', {
CertId: certificate.CertificateId,
}, { method: 'POST' });
this.logger.info(`删除证书成功证书ID:${certificate.CertificateId}, 名称:${certificate.CertificateName}, requestId:${deleteRes?.RequestId}`);
successCount++;
} catch (error: any) {
this.logger.error(`删除证书失败证书ID:${certificate.CertificateId}, 名称:${certificate.CertificateName}, 错误:${error.message}`);
failedCount++;
}
}
this.logger.info(`证书删除完成,成功:${successCount}, 失败:${failedCount}`);
}
}
new AliyunDeleteExpiringCert();

View File

@@ -13,4 +13,5 @@ export * from './deploy-to-vod/index.js';
export * from './deploy-to-apigateway/index.js';
export * from './deploy-to-apig/index.js';
export * from './deploy-to-ack/index.js';
export * from './deploy-to-all/index.js';
export * from './deploy-to-all/index.js';
export * from './delete-expiring-cert/index.js';

View File

@@ -5,3 +5,4 @@ export * from './plugin-deploy-to-alb.js'
export * from './plugin-deploy-to-live.js'
export * from './plugin-deploy-to-dcdn.js'
export * from './plugin-deploy-to-vod.js'
export * from './plugin-deploy-to-tos.js'

View File

@@ -3,6 +3,7 @@ import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from
import { CertApplyPluginNames, CertInfo } from "@certd/plugin-cert";
import { VolcengineAccess } from "../access.js";
import { VolcengineClient } from "../ve-client.js";
import dayjs from "dayjs";
@IsTaskPlugin({
name: "VolcengineDeployToALB",
@@ -32,6 +33,7 @@ export class VolcengineDeployToALB extends AbstractTaskPlugin {
certDomains!: string[];
@TaskInput({
title: "Access授权",
helper: "火山引擎AccessKeyId、AccessKeySecret",
@@ -126,6 +128,22 @@ export class VolcengineDeployToALB extends AbstractTaskPlugin {
listenerList!: string | string[];
@TaskInput({
title: "证书部署类型",
helper: "选择部署默认证书还是扩展证书",
component: {
name: "a-select",
options: [
{ label: "默认证书", value: "default" },
{ label: "扩展证书", value: "extension" }
]
},
value: "default",
required: true
})
certType!: string;
async onInstance() {
}
@@ -149,20 +167,101 @@ export class VolcengineDeployToALB extends AbstractTaskPlugin {
const service = await this.getAlbService();
for (const listener of this.listenerList) {
this.logger.info(`开始部署监听器${listener}证书`);
await service.request({
action: "ModifyListenerAttributes",
query: {
ListenerId: listener,
CertificateSource: "cert_center",
CertCenterCertificateId: certId
}
});
this.logger.info(`部署监听器${listener}证书成功`);
if (this.certType === "default") {
// 部署默认证书
const res = await service.request({
action: "ModifyListenerAttributes",
query: {
ListenerId: listener,
CertificateSource: "cert_center",
CertCenterCertificateId: certId
}
});
this.logger.info(`部署监听器${listener}默认证书成功res:${JSON.stringify(res)}`);
} else {
// 部署扩展证书
await this.deployExtensionCertificate(service, listener, certId as string);
}
await this.ctx.utils.sleep(5000);
}
this.logger.info("部署完成");
}
private async deployExtensionCertificate(service: any, listenerId: string, certId: string) {
// 获取监听器当前的扩展证书列表
const domainExtensions = await this.getListenerDomainExtensions(service, listenerId);
// 删除过期的扩展证书
try {
await this.deleteExpiredExtensions(service, listenerId, domainExtensions);
} catch (error) {
this.logger.error(`删除过期扩展证书失败:${error.message ||error}`);
}
// 新增扩展证书
const query: any = {
ListenerId: listenerId,
"DomainExtensions.1.Action": "create",
"DomainExtensions.1.CertificateSource": "cert_center",
"DomainExtensions.1.CertCenterCertificateId": certId
};
// 如果有证书域名信息,添加到扩展证书中
if (this.certDomains && this.certDomains.length > 0) {
query["DomainExtensions.1.Domain"] = this.certDomains[0];
}
await service.request({
action: "ModifyListenerAttributes",
query: query
});
this.logger.info(`部署监听器${listenerId}扩展证书成功`);
}
private async getListenerDomainExtensions(service: any, listenerId: string): Promise<any[]> {
const res = await service.request({
action: "DescribeListenerAttributes",
method: "GET",
query: {
ListenerId: listenerId
}
});
return res.Result.DomainExtensions || [];
}
private async deleteExpiredExtensions(service: any, listenerId: string, domainExtensions: any[]) {
const expiredExtensions = [];
for (const ext of domainExtensions) {
if (!await this.isCertificateExpired(ext)) {
expiredExtensions.push(ext);
}
}
if (expiredExtensions.length === 0) {
this.logger.info(`没有过期的扩展证书,跳过删除`);
return;
}
const query: any = {
ListenerId: listenerId
};
expiredExtensions.forEach((ext, index) => {
const idx = index + 1;
query[`DomainExtensions.${idx}.Action`] = "delete";
query[`DomainExtensions.${idx}.DomainExtensionId`] = ext.DomainExtensionId;
});
this.logger.info(`准备删除过期扩展证书,数量:${expiredExtensions.length}query:${JSON.stringify(query)}`);
await service.request({
action: "ModifyListenerAttributes",
query: query
});
this.logger.info(`删除${expiredExtensions.length}个过期扩展证书成功`);
await this.ctx.utils.sleep(5000);
}
private async getCertService(access: VolcengineAccess) {
const client = new VolcengineClient({
@@ -189,6 +288,54 @@ export class VolcengineDeployToALB extends AbstractTaskPlugin {
return service;
}
private async isCertificateExpired(extension: any): Promise<boolean> {
try {
let certificateId: string;
// 根据证书来源获取证书ID
if (extension.CertificateSource === "cert_center") {
certificateId = extension.CertCenterCertificateId;
} else if (extension.CertificateSource === "alb") {
this.logger.warn(`ALB证书不支持过期检查跳过`);
return false;
} else if (extension.CertificateSource === "pca_leaf") {
this.logger.warn(`PCA Leaf证书不支持过期检查跳过`);
return false;
} else {
this.logger.warn(`未知的证书来源: ${extension.CertificateSource},跳过`);
return false;
}
if (!certificateId) {
this.logger.warn(`证书ID为空跳过`);
return false;
}
// 获取证书服务
const access = await this.getAccess<VolcengineAccess>(this.accessId);
const certService = await this.getCertService(access);
// 获取证书详情
const certDetail = await certService.GetCertificateDetail(certificateId);
// 判断证书是否过期
if (certDetail.NotAfter) {
const expireTime = dayjs(certDetail.NotAfter);
const now = dayjs();
const isExpired = expireTime.isBefore(now);
if (isExpired) {
this.logger.info(`证书 ${certificateId} 已过期,过期时间: ${expireTime.toISOString()}`);
}
return isExpired;
}
return false;
} catch (error) {
this.logger.error(`检查证书是否过期失败: ${error.message || error}`);
return false;
}
}
async onGetListenerList(data: any) {
if (!this.accessId) {
throw new Error("请选择Access授权");

View File

@@ -100,7 +100,8 @@ export class VolcengineDeployToCDN extends AbstractTaskPlugin {
await service.UpdateCdnConfig({
Domain: domain,
HTTPS: {
CertInfo: { CertId: certId },
CertInfo: { CertId: certId as string },
Switch: true,
}
})
this.logger.info(`部署域名${domain}证书成功`);

View File

@@ -0,0 +1,199 @@
import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline";
import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from "@certd/plugin-lib";
import { CertApplyPluginNames, CertInfo } from "@certd/plugin-cert";
import { optionsUtils } from "@certd/basic";
import { VolcengineAccess } from "../access.js";
import { VolcengineClient } from "../ve-client.js";
@IsTaskPlugin({
name: 'VolcengineDeployToTOS',
title: '火山引擎-部署证书至TOS自定义域名',
icon: 'svg:icon-volcengine',
group: pluginGroups.volcengine.key,
desc: '仅限TOS自定义域名加速域名请选择火山引擎的CDN插件',
default: {
strategy: {
runStrategy: RunStrategy.SkipWhenSucceed,
},
},
})
export class VolcengineDeployToTOS extends AbstractTaskPlugin {
@TaskInput({
title: '域名证书',
helper: '请选择前置任务输出的域名证书',
component: {
name: 'output-selector',
from: [...CertApplyPluginNames, 'VolcengineUploadToCertCenter'],
},
required: true,
})
cert!: CertInfo | string;
@TaskInput(createCertDomainGetterInputDefine({ props: { required: false } }))
certDomains!: string[];
@TaskInput({
title: 'Access授权',
helper: '火山引擎AccessKeyId、AccessKeySecret',
component: {
name: 'access-selector',
type: 'volcengine',
},
required: true,
})
accessId!: string;
@TaskInput({
title: '地域',
helper: 'TOS服务所在地域',
component: {
name: 'a-select',
options:[
{ label: "华北2北京", value: "cn-beijing" },
{ label: "华东2上海", value: "cn-shanghai" },
{ label: "华南1广州", value: "cn-guangzhou" },
{ label: "中国香港", value: "cn-hongkong" },
{ label: "亚太东南(柔佛)", value: "ap-southeast-1" },
{ label: "亚太东南(雅加达)", value: "ap-southeast-3" },
]
},
value: 'cn-beijing',
required: true,
})
region:string = "cn-beijing"
@TaskInput({
title: 'Bucket',
helper: '存储桶名称',
component: {
name: 'remote-auto-complete',
vModel: 'value',
type: 'plugin',
action: 'onGetBucketList',
search: false,
pager: false,
watches: ['accessId', 'region']
},
required: true,
})
bucket!: string;
@TaskInput(
createRemoteSelectInputDefine({
title: 'TOS自定义域名',
helper: '你在火山引擎上配置的TOS自定义域名比如:example.com',
action: VolcengineDeployToTOS.prototype.onGetDomainList.name,
watches: ['certDomains', 'accessId', 'region', 'bucket'],
required: true,
})
)
domainName!: string | string[];
async onInstance() {}
async execute(): Promise<void> {
this.logger.info('开始部署证书到火山引擎TOS自定义域名');
const access = await this.getAccess<VolcengineAccess>(this.accessId);
this.logger.info(`bucket: ${this.bucket}, region: ${this.region}, domainName: ${this.domainName}`);
const client = new VolcengineClient({
logger: this.logger,
access,
http: this.http
});
const tosService = await client.getTOSService({ region: this.region });
if (!this.cert) {
throw new Error('你还未选择证书');
}
let certId = this.cert
if (typeof certId !== 'string') {
const certInfo = this.cert as CertInfo
this.logger.info(`开始上传证书`)
const certService = await client.getCertCenterService();
certId = await certService.ImportCertificate({
certName: this.appendTimeSuffix('certd'),
cert: certInfo
})
this.logger.info(`上传证书成功:${certId}`);
}else{
this.logger.info(`使用已有证书ID${certId}`);
}
for (const domain of this.domainName) {
this.logger.info(`开始部署域名${domain}证书`)
await tosService.putBucketCustomDomain({
bucket: this.bucket,
customDomainRule: {
Domain: domain,
CertId: certId as string
}
})
this.logger.info(`部署域名${domain}证书成功`);
await this.ctx.utils.sleep(1000)
}
this.logger.info('部署完成');
}
async onGetDomainList(data: any) {
if (!this.accessId || !this.bucket) {
throw new Error('请选择Access授权和Bucket');
}
const access = await this.getAccess<VolcengineAccess>(this.accessId);
const client = new VolcengineClient({
logger: this.logger,
access,
http: this.http
});
const tosService = await client.getTOSService({ region: this.region });
const res = await tosService.getBucketCustomDomain({
bucket: this.bucket
});
const list = res?.data?.CustomDomainRules || [];
if (!list || list.length === 0) {
throw new Error('找不到TOS自定义域名您可以手动输入');
}
const options = list.map((item: any) => {
return {
value: item.Domain,
label: item.Domain,
domain: item.Domain,
};
});
return optionsUtils.buildGroupOptions(options, this.certDomains);
}
async onGetBucketList(data: any) {
if (!this.accessId) {
throw new Error('请选择Access授权');
}
const access = await this.getAccess<VolcengineAccess>(this.accessId);
const client = new VolcengineClient({
logger: this.logger,
access,
http: this.http
});
const tosService = await client.getTOSService({ region: this.region });
const res = await tosService.listBuckets();
const buckets = res?.data?.Buckets || [];
return buckets.map((bucket: any) => ({
label: `${bucket.Name}<${bucket.Location}>`,
value: bucket.Name
}));
}
}
new VolcengineDeployToTOS();

View File

@@ -9,8 +9,7 @@ import { VolcengineClient } from "../ve-client.js";
title: "火山引擎-部署证书至VOD",
icon: "svg:icon-volcengine",
group: pluginGroups.volcengine.key,
desc: "部署至火山引擎视频点播(暂不可用)",
deprecated:"暂时缺少部署ssl接口",
desc: "部署至火山引擎视频点播",
default: {
strategy: {
runStrategy: RunStrategy.SkipWhenSucceed
@@ -45,27 +44,55 @@ export class VolcengineDeployToVOD extends AbstractTaskPlugin {
accessId!: string;
@TaskInput(
// createRemoteSelectInputDefine({
// title: "空间名称",
// helper: "选择要部署证书的监听器\n需要在监听器中选择证书中心进行跨服务访问授权",
// action: VolcengineDeployToVOD.prototype.onGetSpaceList.name,
// watches: ["certDomains", "accessId", "regionId"],
// required: true
// })
{
title: "空间名称",
required: true
}
)
spaceName!: string;
@TaskInput({
title: "区域",
helper: "选择火山引擎区域",
component: {
name: "select",
options: [
{ value: "cn-north-1", label: "华北1北京" },
{ value: "ap-southeast-1", label: "东南亚1新加坡" }
]
},
default: "cn-north-1",
required: true
})
regionId!: string;
@TaskInput(
createRemoteSelectInputDefine({
title: "点播域名",
helper: "选择要部署证书的点播域名\n需要先在域名管理页面进行证书中心访问授权即点击去配置SSL证书",
title: "空间名称",
helper: "选择要部署证书的点播空间",
action: VolcengineDeployToVOD.prototype.onGetSpaceList.name,
watches: ["accessId", "regionId"],
multi:false,
required: true
})
)
spaceName!: string;
@TaskInput({
title: "域名类型",
helper: "选择域名类型",
component: {
name: "a-select",
vModel: "value",
options: [
{ value: "play", label: "点播加速域名" },
{ value: "image", label: "封面加速域名" }
]
},
value: "play",
required: true
})
domainType!: string;
@TaskInput(
createRemoteSelectInputDefine({
title: "域名",
helper: "选择要部署证书的域名\n需要先在域名管理页面进行证书中心访问授权即点击去配置SSL证书",
action: VolcengineDeployToVOD.prototype.onGetDomainList.name,
watches: ["certDomains", "accessId", "spaceName"],
watches: ["certDomains", "accessId", "spaceName", "domainType"],
required: true
})
)
@@ -77,21 +104,36 @@ export class VolcengineDeployToVOD extends AbstractTaskPlugin {
async execute(): Promise<void> {
this.logger.info("开始部署证书到火山引擎VOD");
if (!this.spaceName) {
throw new Error("SpaceName不能为空");
}
const access = await this.getAccess<VolcengineAccess>(this.accessId);
let certId = await this.uploadOrGetCertId(access);
const service = await this.getVodService();
for (const item of this.domainList) {
this.logger.info(`开始部署点播域名${item}证书`);
const service = await this.getVodService({ version: "2023-07-01", region: this.regionId });
const domains = Array.isArray(this.domainList) ? this.domainList : [this.domainList];
for (const domain of domains) {
this.logger.info(`开始部署域名${domain}证书`);
await service.request({
action: "ModifyListenerAttributes",
query: {
ListenerId: item,
CertificateSource: "cert_center",
CertCenterCertificateId: certId
action: "UpdateDomainConfig",
method: "POST",
body: {
SpaceName: this.spaceName,
DomainType: this.domainType,
Domain: domain,
Config: {
HTTPS: {
Switch: true,
CertInfo: {
CertId: certId
}
}
}
}
});
this.logger.info(`部署点播域名${item}证书成功`);
this.logger.info(`部署域名${domain}证书成功`);
}
this.logger.info("部署完成");
@@ -126,7 +168,7 @@ export class VolcengineDeployToVOD extends AbstractTaskPlugin {
}
private async getVodService(req?: { version?: string }) {
private async getVodService(req?: { version?: string, region?: string }) {
const access = await this.getAccess<VolcengineAccess>(this.accessId);
const client = new VolcengineClient({
@@ -138,58 +180,61 @@ export class VolcengineDeployToVOD extends AbstractTaskPlugin {
return await client.getVodService(req);
}
// async onGetSpaceList(data: any) {
// if (!this.accessId) {
// throw new Error("请选择Access授权");
// }
// const service = await this.getVodService();
//
// const res = await service.request({
// action: "ListSpace",
// method: "GET",
// query: {
// PageSize: 100,
// },
// });
//
// const list = res.Result;
// if (!list || list.length === 0) {
// throw new Error("找不到空间,您可以手动填写");
// }
// return list.map((item: any) => {
// return {
// value: item.SpaceName,
// label: `${item.SpaceName}`
// };
// });
// }
async onGetSpaceList(data: any) {
if (!this.accessId) {
throw new Error("请选择Access授权");
}
const service = await this.getVodService({ version: "2021-01-01", region: this.regionId });
const res = await service.request({
action: "ListSpace",
body: {}
});
const list = res.Result;
if (!list || list.length === 0) {
throw new Error("找不到空间,您可以手动填写");
}
return list.map((item: any) => {
return {
value: item.SpaceName,
label: `${item.SpaceName} (${item.Region})`
};
});
}
async onGetDomainList(data: any) {
if (!this.accessId) {
throw new Error("请选择Access授权");
}
const service = await this.getVodService();
if (!this.spaceName) {
throw new Error("请先选择空间名称");
}
const service = await this.getVodService({ version: "2023-01-01", region: this.regionId });
const res = await service.request({
action: "ListDomain",
body: {
query: {
SpaceName: this.spaceName,
// Offset: 100
DomainType: this.domainType
}
});
const instances = res.Result?.PlayInstanceInfo?.ByteInstances;
if (!instances || instances.length === 0) {
throw new Error("找不到点播域名,您也可以手动输入点播域名");
throw new Error("找不到域名,您也可以手动输入域名");
}
const list = []
const list = [];
for (const item of instances) {
for (const domain of item.Domains) {
list.push({
value: item.Domain,
label: item.Domain,
domain: domain.Domain
});
if (item.Domains && item.Domains.length > 0) {
for (const domain of item.Domains) {
if (domain.Domain) {
list.push({
value: domain.Domain,
label: domain.Domain
});
}
}
}
}
return this.ctx.utils.options.buildGroupOptions(list, this.certDomains);

View File

@@ -42,6 +42,17 @@ export class VolcengineClient {
});
return res.Result.InstanceId || res.Result.RepeatId;
};
service.GetCertificateDetail = async (certificateId: string) => {
const res = await service.request({
action: "CertificateGetInstance",
method: "POST",
body: {
InstanceId: certificateId
}
});
return res.Result;
};
return service;
}
@@ -73,7 +84,7 @@ export class VolcengineClient {
return service;
}
async getVodService(opts?: { version?: string }) {
async getVodService(opts?: { version?: string, region?: string }) {
const CommonService = await this.getServiceCls();
const service = new CommonService({
@@ -82,6 +93,7 @@ export class VolcengineClient {
});
service.setAccessKeyId(this.opts.access.accessKeyId);
service.setSecretKey(this.opts.access.secretAccessKey);
service.setRegion(opts?.region || "cn-north-1");
return service;
}
@@ -113,6 +125,19 @@ export class VolcengineClient {
return service;
}
async getTOSService(opts: { region?: string }) {
const { TosClient } = await import("@volcengine/tos-sdk");
const client = new TosClient({
accessKeyId: this.opts.access.accessKeyId,
accessKeySecret: this.opts.access.secretAccessKey,
region: opts.region,
endpoint: `tos-${opts.region}.volces.com`
});
return client;
}
async getStsService() {
const CommonService = await this.getServiceCls();

194
pnpm-lock.yaml generated
View File

@@ -49,7 +49,7 @@ importers:
packages/core/acme-client:
dependencies:
'@certd/basic':
specifier: ^1.39.2
specifier: ^1.39.6
version: link:../basic
'@peculiar/x509':
specifier: ^1.11.0
@@ -213,10 +213,10 @@ importers:
packages/core/pipeline:
dependencies:
'@certd/basic':
specifier: ^1.39.2
specifier: ^1.39.6
version: link:../basic
'@certd/plus-core':
specifier: ^1.39.2
specifier: ^1.39.6
version: link:../../pro/plus-core
dayjs:
specifier: ^1.11.7
@@ -412,7 +412,7 @@ importers:
packages/libs/lib-k8s:
dependencies:
'@certd/basic':
specifier: ^1.39.2
specifier: ^1.39.6
version: link:../../core/basic
'@kubernetes/client-node':
specifier: 0.21.0
@@ -452,19 +452,19 @@ importers:
packages/libs/lib-server:
dependencies:
'@certd/acme-client':
specifier: ^1.39.2
specifier: ^1.39.6
version: link:../../core/acme-client
'@certd/basic':
specifier: ^1.39.2
specifier: ^1.39.6
version: link:../../core/basic
'@certd/pipeline':
specifier: ^1.39.2
specifier: ^1.39.6
version: link:../../core/pipeline
'@certd/plugin-lib':
specifier: ^1.39.2
specifier: ^1.39.6
version: link:../../plugins/plugin-lib
'@certd/plus-core':
specifier: ^1.39.2
specifier: ^1.39.6
version: link:../../pro/plus-core
'@midwayjs/cache':
specifier: 3.14.0
@@ -610,16 +610,16 @@ importers:
packages/plugins/plugin-cert:
dependencies:
'@certd/acme-client':
specifier: ^1.39.2
specifier: ^1.39.6
version: link:../../core/acme-client
'@certd/basic':
specifier: ^1.39.2
specifier: ^1.39.6
version: link:../../core/basic
'@certd/pipeline':
specifier: ^1.39.2
specifier: ^1.39.6
version: link:../../core/pipeline
'@certd/plugin-lib':
specifier: ^1.39.2
specifier: ^1.39.6
version: link:../plugin-lib
psl:
specifier: ^1.9.0
@@ -683,16 +683,16 @@ importers:
specifier: ^3.964.0
version: 3.964.0(aws-crt@1.26.2)
'@certd/acme-client':
specifier: ^1.39.2
specifier: ^1.39.6
version: link:../../core/acme-client
'@certd/basic':
specifier: ^1.39.2
specifier: ^1.39.6
version: link:../../core/basic
'@certd/pipeline':
specifier: ^1.39.2
specifier: ^1.39.6
version: link:../../core/pipeline
'@certd/plus-core':
specifier: ^1.39.2
specifier: ^1.39.6
version: link:../../pro/plus-core
'@kubernetes/client-node':
specifier: 0.21.0
@@ -783,16 +783,16 @@ importers:
packages/pro/commercial-core:
dependencies:
'@certd/basic':
specifier: ^1.39.2
specifier: ^1.39.6
version: link:../../core/basic
'@certd/lib-server':
specifier: ^1.39.2
specifier: ^1.39.6
version: link:../../libs/lib-server
'@certd/pipeline':
specifier: ^1.39.2
specifier: ^1.39.6
version: link:../../core/pipeline
'@certd/plus-core':
specifier: ^1.39.2
specifier: ^1.39.6
version: link:../plus-core
'@midwayjs/core':
specifier: 3.20.11
@@ -868,16 +868,16 @@ importers:
packages/pro/plugin-plus:
dependencies:
'@certd/basic':
specifier: ^1.39.2
specifier: ^1.39.6
version: link:../../core/basic
'@certd/pipeline':
specifier: ^1.39.2
specifier: ^1.39.6
version: link:../../core/pipeline
'@certd/plugin-lib':
specifier: ^1.39.2
specifier: ^1.39.6
version: link:../../plugins/plugin-lib
'@certd/plus-core':
specifier: ^1.39.2
specifier: ^1.39.6
version: link:../plus-core
crypto-js:
specifier: ^4.2.0
@@ -953,7 +953,7 @@ importers:
packages/pro/plus-core:
dependencies:
'@certd/basic':
specifier: ^1.39.2
specifier: ^1.39.6
version: link:../../core/basic
dayjs:
specifier: ^1.11.7
@@ -1249,10 +1249,10 @@ importers:
version: 0.1.3(zod@3.24.4)
devDependencies:
'@certd/lib-iframe':
specifier: ^1.39.2
specifier: ^1.39.6
version: link:../../libs/lib-iframe
'@certd/pipeline':
specifier: ^1.39.2
specifier: ^1.39.6
version: link:../../core/pipeline
'@rollup/plugin-commonjs':
specifier: ^25.0.7
@@ -1447,46 +1447,46 @@ importers:
specifier: ^3.990.0
version: 3.990.0(aws-crt@1.26.2)
'@certd/acme-client':
specifier: ^1.39.2
specifier: ^1.39.6
version: link:../../core/acme-client
'@certd/basic':
specifier: ^1.39.2
specifier: ^1.39.6
version: link:../../core/basic
'@certd/commercial-core':
specifier: ^1.39.2
specifier: ^1.39.6
version: link:../../pro/commercial-core
'@certd/cv4pve-api-javascript':
specifier: ^8.4.2
version: 8.4.2
'@certd/jdcloud':
specifier: ^1.39.2
specifier: ^1.39.6
version: link:../../libs/lib-jdcloud
'@certd/lib-huawei':
specifier: ^1.39.2
specifier: ^1.39.6
version: link:../../libs/lib-huawei
'@certd/lib-k8s':
specifier: ^1.39.2
specifier: ^1.39.6
version: link:../../libs/lib-k8s
'@certd/lib-server':
specifier: ^1.39.2
specifier: ^1.39.6
version: link:../../libs/lib-server
'@certd/midway-flyway-js':
specifier: ^1.39.2
specifier: ^1.39.6
version: link:../../libs/midway-flyway-js
'@certd/pipeline':
specifier: ^1.39.2
specifier: ^1.39.6
version: link:../../core/pipeline
'@certd/plugin-cert':
specifier: ^1.39.2
specifier: ^1.39.6
version: link:../../plugins/plugin-cert
'@certd/plugin-lib':
specifier: ^1.39.2
specifier: ^1.39.6
version: link:../../plugins/plugin-lib
'@certd/plugin-plus':
specifier: ^1.39.2
specifier: ^1.39.6
version: link:../../pro/plugin-plus
'@certd/plus-core':
specifier: ^1.39.2
specifier: ^1.39.6
version: link:../../pro/plus-core
'@google-cloud/publicca':
specifier: ^1.3.0
@@ -1557,6 +1557,9 @@ importers:
'@volcengine/openapi':
specifier: ^1.28.1
version: 1.30.1(buffer@6.0.3)
'@volcengine/tos-sdk':
specifier: ^2.9.1
version: 2.9.1
ali-oss:
specifier: ^6.21.0
version: 6.23.0
@@ -4874,6 +4877,9 @@ packages:
'@types/http-errors@2.0.4':
resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==}
'@types/http-proxy@1.17.17':
resolution: {integrity: sha512-ED6LB+Z1AVylNTu7hdzuBqOgMnvG/ld6wGCG8wFnAzKX5uyW2K3WD52v0gnLCTK/VLpXtKckgWuyScYK6cSPaw==}
'@types/istanbul-lib-coverage@2.0.6':
resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==}
@@ -5271,6 +5277,10 @@ packages:
resolution: {integrity: sha512-W8R6+7UIhx06s2kpsJ0KF80IKAiIad71HUKssonMChyI37h5oFnPf6zONcX2ikXc5M8xdOiKFRxoCO8ChEob0g==}
engines: {node: '>=12'}
'@volcengine/tos-sdk@2.9.1':
resolution: {integrity: sha512-hmrBzl7/LpJYezGWytPg6CZk5lvFgmDKUVZJLM3vwZgp3UKSZwgxFA7V0QmLnerPDRpLPAqh0bP8qUBSVHfmhA==}
engines: {node: '>=10'}
'@vue-macros/common@1.16.1':
resolution: {integrity: sha512-Pn/AWMTjoMYuquepLZP813BIcq8DTZiNCoaceuNlvaYuOTd8DqBZWc5u0uOMQZMInwME1mdSmmBAcTluiV9Jtg==}
engines: {node: '>=16.14.0'}
@@ -5858,6 +5868,9 @@ packages:
aws4@1.13.2:
resolution: {integrity: sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==}
axios-adapter-uniapp@0.1.4:
resolution: {integrity: sha512-4je5JcWGrrTjPEJXVXJZnOkv+BsnYn/fKbQmjxzdCGFyoQw1gq3tfQ4/WhLzy+Gi9cQJl3K8EH26G7U0BK3wcw==}
axios-mock-adapter@1.22.0:
resolution: {integrity: sha512-dmI0KbkyAhntUR05YY96qg2H6gg0XMl2+qTW0xmYg6Up+BFBAJYRLROMXRdDEL06/Wqwa0TJThAYvFtSFdRCZw==}
peerDependencies:
@@ -5866,6 +5879,9 @@ packages:
axios@0.21.4:
resolution: {integrity: sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==}
axios@0.27.2:
resolution: {integrity: sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==}
axios@1.9.0:
resolution: {integrity: sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==}
@@ -7469,6 +7485,9 @@ packages:
eventemitter3@2.0.3:
resolution: {integrity: sha512-jLN68Dx5kyFHaePoXWPsCGW5qdyZQtLYHkxkg02/Mz6g0kYpDx4FyP6XfArhQdlOC4b8Mv+EMxPo/8La7Tzghg==}
eventemitter3@4.0.7:
resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==}
eventemitter3@5.0.1:
resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==}
@@ -8117,6 +8136,19 @@ packages:
resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==}
engines: {node: '>= 14'}
http-proxy-middleware@2.0.9:
resolution: {integrity: sha512-c1IyJYLYppU574+YI7R4QyX2ystMtVXZwIdzazUIPIJsHuWNd+mho2j+bKoHftndicGj9yh+xjd+l0yj7VeT1Q==}
engines: {node: '>=12.0.0'}
peerDependencies:
'@types/express': ^4.17.13
peerDependenciesMeta:
'@types/express':
optional: true
http-proxy@1.18.1:
resolution: {integrity: sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==}
engines: {node: '>=8.0.0'}
http-signature@1.2.0:
resolution: {integrity: sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==}
engines: {node: '>=0.8', npm: '>=1.3.7'}
@@ -8420,6 +8452,10 @@ packages:
resolution: {integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==}
engines: {node: '>=8'}
is-plain-obj@3.0.0:
resolution: {integrity: sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==}
engines: {node: '>=10'}
is-plain-obj@4.1.0:
resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==}
engines: {node: '>=12'}
@@ -10990,6 +11026,9 @@ packages:
require-main-filename@2.0.0:
resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==}
requires-port@1.0.0:
resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==}
requizzle@0.2.4:
resolution: {integrity: sha512-JRrFk1D4OQ4SqovXOgdav+K8EAhSB/LJZqCz8tbX0KObcdeM15Ss59ozWMBWmmINMagCwmqn4ZNryUGpBsl6Jw==}
@@ -11848,6 +11887,9 @@ packages:
resolution: {integrity: sha512-6udB24Q737UD/SDsKAHI9FCRP7Bqc9D/MQUV02ORQg5iskjtLJlZJNdN4kKtcdtwCeWIwIHDGaUsTsCCAa8sFQ==}
engines: {node: '>=10'}
tos-crc64-js@0.0.1:
resolution: {integrity: sha512-l2Ndi9BaDH3gmAJ5VIS/1WeqFcucK41WCbw5dije24k2XtUCclYfvhntWIVHe+0S85QcED4vjqm3AO1izlQ30g==}
tough-cookie@2.5.0:
resolution: {integrity: sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==}
engines: {node: '>=0.8'}
@@ -17722,6 +17764,10 @@ snapshots:
'@types/http-errors@2.0.4': {}
'@types/http-proxy@1.17.17':
dependencies:
'@types/node': 20.17.47
'@types/istanbul-lib-coverage@2.0.6': {}
'@types/istanbul-lib-report@3.0.3':
@@ -17747,7 +17793,7 @@ snapshots:
'@types/keyv@3.1.4':
dependencies:
'@types/node': 18.19.100
'@types/node': 20.17.47
'@types/koa-compose@3.2.8':
dependencies:
@@ -17842,14 +17888,14 @@ snapshots:
'@types/responselike@1.0.3':
dependencies:
'@types/node': 18.19.100
'@types/node': 20.17.47
'@types/semver@7.7.0': {}
'@types/send@0.17.4':
dependencies:
'@types/mime': 1.3.5
'@types/node': 18.19.100
'@types/node': 20.17.47
'@types/serve-static@1.15.7':
dependencies:
@@ -18271,6 +18317,21 @@ snapshots:
- buffer
- supports-color
'@volcengine/tos-sdk@2.9.1':
dependencies:
axios: 0.21.4(debug@4.4.3)
axios-adapter-uniapp: 0.1.4(debug@4.4.3)
crypto-js: 4.2.0
debug: 4.4.3(supports-color@8.1.1)
http-proxy-middleware: 2.0.9(debug@4.4.3)
lodash: 4.17.21
qs: 6.14.0
tos-crc64-js: 0.0.1
type-fest: 1.4.0
transitivePeerDependencies:
- '@types/express'
- supports-color
'@vue-macros/common@1.16.1(vue@3.5.14(typescript@5.9.3))':
dependencies:
'@vue/compiler-sfc': 3.5.14
@@ -18982,6 +19043,12 @@ snapshots:
aws4@1.13.2: {}
axios-adapter-uniapp@0.1.4(debug@4.4.3):
dependencies:
axios: 0.27.2(debug@4.4.3)
transitivePeerDependencies:
- debug
axios-mock-adapter@1.22.0(axios@1.9.0):
dependencies:
axios: 1.9.0(debug@4.4.3)
@@ -18994,6 +19061,13 @@ snapshots:
transitivePeerDependencies:
- debug
axios@0.27.2(debug@4.4.3):
dependencies:
follow-redirects: 1.15.9(debug@4.4.3)
form-data: 4.0.2
transitivePeerDependencies:
- debug
axios@1.9.0(debug@4.4.3):
dependencies:
follow-redirects: 1.15.9(debug@4.4.3)
@@ -20780,13 +20854,13 @@ snapshots:
resolve: 1.22.10
semver: 6.3.1
eslint-plugin-prettier@3.4.1(eslint-config-prettier@8.10.0(eslint@8.57.0))(eslint@7.32.0)(prettier@2.8.8):
eslint-plugin-prettier@3.4.1(eslint-config-prettier@8.10.0(eslint@7.32.0))(eslint@7.32.0)(prettier@2.8.8):
dependencies:
eslint: 7.32.0
prettier: 2.8.8
prettier-linter-helpers: 1.0.0
optionalDependencies:
eslint-config-prettier: 8.10.0(eslint@8.57.0)
eslint-config-prettier: 8.10.0(eslint@7.32.0)
eslint-plugin-prettier@4.2.1(eslint-config-prettier@8.10.0(eslint@8.57.0))(eslint@8.57.0)(prettier@2.8.8):
dependencies:
@@ -20985,6 +21059,8 @@ snapshots:
eventemitter3@2.0.3: {}
eventemitter3@4.0.7: {}
eventemitter3@5.0.1: {}
events@3.3.0: {}
@@ -21746,6 +21822,24 @@ snapshots:
transitivePeerDependencies:
- supports-color
http-proxy-middleware@2.0.9(debug@4.4.3):
dependencies:
'@types/http-proxy': 1.17.17
http-proxy: 1.18.1(debug@4.4.3)
is-glob: 4.0.3
is-plain-obj: 3.0.0
micromatch: 4.0.8
transitivePeerDependencies:
- debug
http-proxy@1.18.1(debug@4.4.3):
dependencies:
eventemitter3: 4.0.7
follow-redirects: 1.15.9(debug@4.4.3)
requires-port: 1.0.0
transitivePeerDependencies:
- debug
http-signature@1.2.0:
dependencies:
assert-plus: 1.0.0
@@ -22017,6 +22111,8 @@ snapshots:
is-plain-obj@2.1.0: {}
is-plain-obj@3.0.0: {}
is-plain-obj@4.1.0: {}
is-plain-object@2.0.4:
@@ -23190,7 +23286,7 @@ snapshots:
eslint: 7.32.0
eslint-config-prettier: 8.10.0(eslint@7.32.0)
eslint-plugin-node: 11.1.0(eslint@7.32.0)
eslint-plugin-prettier: 3.4.1(eslint-config-prettier@8.10.0(eslint@8.57.0))(eslint@7.32.0)(prettier@2.8.8)
eslint-plugin-prettier: 3.4.1(eslint-config-prettier@8.10.0(eslint@7.32.0))(eslint@7.32.0)(prettier@2.8.8)
execa: 5.1.1
inquirer: 7.3.3
json5: 2.2.3
@@ -24825,6 +24921,8 @@ snapshots:
require-main-filename@2.0.0: {}
requires-port@1.0.0: {}
requizzle@0.2.4:
dependencies:
lodash: 4.17.21
@@ -25826,6 +25924,8 @@ snapshots:
'@tokenizer/token': 0.3.0
ieee754: 1.2.1
tos-crc64-js@0.0.1: {}
tough-cookie@2.5.0:
dependencies:
psl: 1.15.0

View File

@@ -1 +1 @@
01:13
00:07

View File

@@ -1 +1 @@
01:30
00:23