mirror of
https://github.com/certd/certd.git
synced 2026-04-11 19:01:00 +08:00
Compare commits
9 Commits
v2-dev-plu
...
v1.36.18
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ea18a5ad15 | ||
|
|
4d0cd3f497 | ||
|
|
7dbdeaebe0 | ||
|
|
2085bcceb6 | ||
|
|
c09c962cb6 | ||
|
|
9108459ae4 | ||
|
|
992bac0b1f | ||
|
|
ebd6917a1d | ||
|
|
3e079e3b80 |
24
CHANGELOG.md
24
CHANGELOG.md
@@ -3,6 +3,30 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.36.18](https://github.com/certd/certd/compare/v1.36.17...v1.36.18) (2025-08-28)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 更新我爱云CDN域名地址,和部分目录结构 [@tyjsjxh](https://github.com/tyjsjxh) ([#514](https://github.com/certd/certd/issues/514)) ([78e7a81](https://github.com/certd/certd/commit/78e7a81638c2ee779f0ab6c3ba7e5c6f6e064151))
|
||||
* 修复cron选择组件星期显示错误的bug ([eb75e52](https://github.com/certd/certd/commit/eb75e52278f94a72643f7317e6740fb42666c68a))
|
||||
* 修复proxmox某些情况下执行卡住的bug ([ebd6917](https://github.com/certd/certd/commit/ebd6917a1d40ae4d94555c32b7e3c093d0599b94))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 部署到k8s支持自动创建secret ([c09c962](https://github.com/certd/certd/commit/c09c962cb676ca261610aa9f3e5105c9dae43f43))
|
||||
* 短信验证码支持腾讯云 ([9108459](https://github.com/certd/certd/commit/9108459ae42bcd95a59acba164a64e82e5f2cfe6))
|
||||
* 商业版支持自定义插件的参数配置 ([17f23f3](https://github.com/certd/certd/commit/17f23f37516af925d5049291d67d41e4271f81f8))
|
||||
* 腾讯云插件支持国际版 ([58e82d5](https://github.com/certd/certd/commit/58e82d5dbd4ebf089ef239578ef9b68454d17b30))
|
||||
* 腾讯云EO插件支持自动获取zoneid和域名列表 ([70fcdc9](https://github.com/certd/certd/commit/70fcdc9ebbfb7c883c0c8a2138f61a0776a9491b))
|
||||
* 支持部署到阿里云云原生API网关、AI网关 ([2ca20be](https://github.com/certd/certd/commit/2ca20be197720201fceabcce9d927f4dbc1cc872))
|
||||
* 支持部署到华为云obs ([9feb9d0](https://github.com/certd/certd/commit/9feb9d04b3c56ec95c06fcf4fd071eb0e88ffc6f))
|
||||
* 支持部署到dokploy ([7dbdeae](https://github.com/certd/certd/commit/7dbdeaebe0bfee7521a863fe5e6b4a712aec5876))
|
||||
* 支持删除宝塔证书夹中的过期证书 ([3575113](https://github.com/certd/certd/commit/3575113655be751d19f88c64491e98a89042d6a2))
|
||||
* 支持p7b证书格式 ([d9f4a57](https://github.com/certd/certd/commit/d9f4a5793d68a017a5d80ad5385cbda603c4e165))
|
||||
* lecdnv2支持api token ([e448934](https://github.com/certd/certd/commit/e4489343fee7754be07bcfc3323969dc3a30e90c))
|
||||
* openapi返回证书时挑选匹配范围最小的那一个;增加format参数,增加返回值p7b格式,增加detail返回 ([2085bcc](https://github.com/certd/certd/commit/2085bcceb61c3723c9bdfec4c4cc0917631ff5e5))
|
||||
* ssh 配置sudo免密提示 ([e1e7011](https://github.com/certd/certd/commit/e1e7011853ad0c5bd7b09c3690861d5aa34b2db4))
|
||||
|
||||
## [1.36.17](https://github.com/certd/certd/compare/v1.36.16...v1.36.17) (2025-08-17)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -9,5 +9,5 @@
|
||||
}
|
||||
},
|
||||
"npmClient": "pnpm",
|
||||
"version": "1.36.17"
|
||||
"version": "1.36.18"
|
||||
}
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.36.18](https://github.com/publishlab/node-acme-client/compare/v1.36.17...v1.36.18) (2025-08-28)
|
||||
|
||||
**Note:** Version bump only for package @certd/acme-client
|
||||
|
||||
## [1.36.17](https://github.com/publishlab/node-acme-client/compare/v1.36.16...v1.36.17) (2025-08-17)
|
||||
|
||||
**Note:** Version bump only for package @certd/acme-client
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"description": "Simple and unopinionated ACME client",
|
||||
"private": false,
|
||||
"author": "nmorsman",
|
||||
"version": "1.36.17",
|
||||
"version": "1.36.18",
|
||||
"type": "module",
|
||||
"module": "scr/index.js",
|
||||
"main": "src/index.js",
|
||||
@@ -18,7 +18,7 @@
|
||||
"types"
|
||||
],
|
||||
"dependencies": {
|
||||
"@certd/basic": "^1.36.17",
|
||||
"@certd/basic": "^1.36.18",
|
||||
"@peculiar/x509": "^1.11.0",
|
||||
"asn1js": "^3.0.5",
|
||||
"axios": "^1.7.2",
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.36.18](https://github.com/certd/certd/compare/v1.36.17...v1.36.18) (2025-08-28)
|
||||
|
||||
**Note:** Version bump only for package @certd/basic
|
||||
|
||||
## [1.36.17](https://github.com/certd/certd/compare/v1.36.16...v1.36.17) (2025-08-17)
|
||||
|
||||
**Note:** Version bump only for package @certd/basic
|
||||
|
||||
@@ -1 +1 @@
|
||||
23:53
|
||||
00:39
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/basic",
|
||||
"private": false,
|
||||
"version": "1.36.17",
|
||||
"version": "1.36.18",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.js",
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.36.18](https://github.com/certd/certd/compare/v1.36.17...v1.36.18) (2025-08-28)
|
||||
|
||||
**Note:** Version bump only for package @certd/pipeline
|
||||
|
||||
## [1.36.17](https://github.com/certd/certd/compare/v1.36.16...v1.36.17) (2025-08-17)
|
||||
|
||||
**Note:** Version bump only for package @certd/pipeline
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/pipeline",
|
||||
"private": false,
|
||||
"version": "1.36.17",
|
||||
"version": "1.36.18",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.js",
|
||||
@@ -17,8 +17,8 @@
|
||||
"pub": "npm publish"
|
||||
},
|
||||
"dependencies": {
|
||||
"@certd/basic": "^1.36.17",
|
||||
"@certd/plus-core": "^1.36.17",
|
||||
"@certd/basic": "^1.36.18",
|
||||
"@certd/plus-core": "^1.36.18",
|
||||
"dayjs": "^1.11.7",
|
||||
"lodash-es": "^4.17.21",
|
||||
"reflect-metadata": "^0.1.13"
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.36.18](https://github.com/certd/certd/compare/v1.36.17...v1.36.18) (2025-08-28)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-huawei
|
||||
|
||||
## [1.36.17](https://github.com/certd/certd/compare/v1.36.16...v1.36.17) (2025-08-17)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-huawei
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/lib-huawei",
|
||||
"private": false,
|
||||
"version": "1.36.17",
|
||||
"version": "1.36.18",
|
||||
"main": "./dist/bundle.js",
|
||||
"module": "./dist/bundle.js",
|
||||
"types": "./dist/d/index.d.ts",
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.36.18](https://github.com/certd/certd/compare/v1.36.17...v1.36.18) (2025-08-28)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-iframe
|
||||
|
||||
## [1.36.17](https://github.com/certd/certd/compare/v1.36.16...v1.36.17) (2025-08-17)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-iframe
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/lib-iframe",
|
||||
"private": false,
|
||||
"version": "1.36.17",
|
||||
"version": "1.36.18",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.js",
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.36.18](https://github.com/certd/certd/compare/v1.36.17...v1.36.18) (2025-08-28)
|
||||
|
||||
**Note:** Version bump only for package @certd/jdcloud
|
||||
|
||||
## [1.36.17](https://github.com/certd/certd/compare/v1.36.16...v1.36.17) (2025-08-17)
|
||||
|
||||
**Note:** Version bump only for package @certd/jdcloud
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@certd/jdcloud",
|
||||
"version": "1.36.17",
|
||||
"version": "1.36.18",
|
||||
"description": "jdcloud openApi sdk",
|
||||
"main": "./dist/bundle.js",
|
||||
"module": "./dist/bundle.js",
|
||||
|
||||
@@ -3,6 +3,12 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.36.18](https://github.com/certd/certd/compare/v1.36.17...v1.36.18) (2025-08-28)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 部署到k8s支持自动创建secret ([c09c962](https://github.com/certd/certd/commit/c09c962cb676ca261610aa9f3e5105c9dae43f43))
|
||||
|
||||
## [1.36.17](https://github.com/certd/certd/compare/v1.36.16...v1.36.17) (2025-08-17)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-k8s
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/lib-k8s",
|
||||
"private": false,
|
||||
"version": "1.36.17",
|
||||
"version": "1.36.18",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.js",
|
||||
@@ -17,7 +17,7 @@
|
||||
"pub": "npm publish"
|
||||
},
|
||||
"dependencies": {
|
||||
"@certd/basic": "^1.36.17",
|
||||
"@certd/basic": "^1.36.18",
|
||||
"@kubernetes/client-node": "0.21.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -90,7 +90,7 @@ export class K8sClient {
|
||||
async createSecret(opts: { namespace: string; body: V1Secret }) {
|
||||
const namespace = opts.namespace || "default";
|
||||
const created = await this.client.createNamespacedSecret(namespace, opts.body);
|
||||
this.logger.info("new secrets:", opts.body);
|
||||
this.logger.info("new secrets:", opts.body.metadata);
|
||||
return created.body;
|
||||
}
|
||||
|
||||
@@ -103,17 +103,33 @@ export class K8sClient {
|
||||
// return await this.client.replaceNamespacedSecret(secretName, namespace, opts.body);
|
||||
// }
|
||||
|
||||
async patchSecret(opts: { namespace: string; secretName: string; body: V1Secret }) {
|
||||
async patchSecret(opts: { namespace: string; secretName: string; body: V1Secret; createOnNotFound?: boolean }) {
|
||||
const namespace = opts.namespace || "default";
|
||||
const secretName = opts.secretName;
|
||||
if (secretName == null) {
|
||||
throw new Error("secretName 不能为空");
|
||||
}
|
||||
this.logger.info("patch secret:", secretName, namespace);
|
||||
const oldSecret = await this.client.readNamespacedSecret(secretName, namespace);
|
||||
let oldSecret: any = null;
|
||||
try {
|
||||
oldSecret = await this.client.readNamespacedSecret(secretName, namespace);
|
||||
} catch (e) {
|
||||
//@ts-ignore
|
||||
if (e.response?.body?.code === 404) {
|
||||
this.logger.warn(`secret ${secretName} 不存在`);
|
||||
if (opts.createOnNotFound) {
|
||||
//没有找到,则创建
|
||||
const res = await this.createSecret({ namespace, body: opts.body });
|
||||
this.logger.info(`secret ${secretName} 已创建`);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
|
||||
const newSecret = _.merge(oldSecret.body, opts.body);
|
||||
const res = await this.client.replaceNamespacedSecret(secretName, namespace, newSecret);
|
||||
this.logger.info("secret updated");
|
||||
this.logger.info(`secret ${secretName} 已更新`);
|
||||
return res.body;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.36.18](https://github.com/certd/certd/compare/v1.36.17...v1.36.18) (2025-08-28)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-server
|
||||
|
||||
## [1.36.17](https://github.com/certd/certd/compare/v1.36.16...v1.36.17) (2025-08-17)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-server
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@certd/lib-server",
|
||||
"version": "1.36.17",
|
||||
"version": "1.36.18",
|
||||
"description": "midway with flyway, sql upgrade way ",
|
||||
"private": false,
|
||||
"type": "module",
|
||||
@@ -27,10 +27,10 @@
|
||||
],
|
||||
"license": "AGPL",
|
||||
"dependencies": {
|
||||
"@certd/acme-client": "^1.36.17",
|
||||
"@certd/basic": "^1.36.17",
|
||||
"@certd/pipeline": "^1.36.17",
|
||||
"@certd/plus-core": "^1.36.17",
|
||||
"@certd/acme-client": "^1.36.18",
|
||||
"@certd/basic": "^1.36.18",
|
||||
"@certd/pipeline": "^1.36.18",
|
||||
"@certd/plus-core": "^1.36.18",
|
||||
"@midwayjs/cache": "~3.14.0",
|
||||
"@midwayjs/core": "~3.20.3",
|
||||
"@midwayjs/i18n": "~3.20.3",
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.36.18](https://github.com/certd/certd/compare/v1.36.17...v1.36.18) (2025-08-28)
|
||||
|
||||
**Note:** Version bump only for package @certd/midway-flyway-js
|
||||
|
||||
## [1.36.17](https://github.com/certd/certd/compare/v1.36.16...v1.36.17) (2025-08-17)
|
||||
|
||||
**Note:** Version bump only for package @certd/midway-flyway-js
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@certd/midway-flyway-js",
|
||||
"version": "1.36.17",
|
||||
"version": "1.36.18",
|
||||
"description": "midway with flyway, sql upgrade way ",
|
||||
"private": false,
|
||||
"type": "module",
|
||||
|
||||
@@ -3,6 +3,13 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.36.18](https://github.com/certd/certd/compare/v1.36.17...v1.36.18) (2025-08-28)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 支持p7b证书格式 ([d9f4a57](https://github.com/certd/certd/commit/d9f4a5793d68a017a5d80ad5385cbda603c4e165))
|
||||
* openapi返回证书时挑选匹配范围最小的那一个;增加format参数,增加返回值p7b格式,增加detail返回 ([2085bcc](https://github.com/certd/certd/commit/2085bcceb61c3723c9bdfec4c4cc0917631ff5e5))
|
||||
|
||||
## [1.36.17](https://github.com/certd/certd/compare/v1.36.16...v1.36.17) (2025-08-17)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/plugin-cert",
|
||||
"private": false,
|
||||
"version": "1.36.17",
|
||||
"version": "1.36.18",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -16,10 +16,10 @@
|
||||
"pub": "npm publish"
|
||||
},
|
||||
"dependencies": {
|
||||
"@certd/acme-client": "^1.36.17",
|
||||
"@certd/basic": "^1.36.17",
|
||||
"@certd/pipeline": "^1.36.17",
|
||||
"@certd/plugin-lib": "^1.36.17",
|
||||
"@certd/acme-client": "^1.36.18",
|
||||
"@certd/basic": "^1.36.18",
|
||||
"@certd/pipeline": "^1.36.18",
|
||||
"@certd/plugin-lib": "^1.36.18",
|
||||
"@google-cloud/publicca": "^1.3.0",
|
||||
"dayjs": "^1.11.7",
|
||||
"jszip": "^3.10.1",
|
||||
|
||||
@@ -21,6 +21,15 @@ export type CertReaderHandleContext = {
|
||||
};
|
||||
export type CertReaderHandle = (ctx: CertReaderHandleContext) => Promise<void>;
|
||||
export type HandleOpts = { logger: ILogger; handle: CertReaderHandle };
|
||||
|
||||
const formats = {
|
||||
pem: ["crt", "key", "ic"],
|
||||
one: ["one"],
|
||||
pfx: ["pfx"],
|
||||
der: ["der"],
|
||||
jks: ["jks"],
|
||||
p7b: ["p7b", "key"],
|
||||
};
|
||||
export class CertReader {
|
||||
cert: CertInfo;
|
||||
|
||||
@@ -74,8 +83,17 @@ export class CertReader {
|
||||
return arr[0] + endStr;
|
||||
}
|
||||
|
||||
toCertInfo(): CertInfo {
|
||||
return this.cert;
|
||||
toCertInfo(format?: string): CertInfo {
|
||||
if (!format) {
|
||||
return this.cert;
|
||||
}
|
||||
|
||||
const formatArr = formats[format];
|
||||
const res: any = {};
|
||||
formatArr.forEach((key: string) => {
|
||||
res[key] = this.cert[key];
|
||||
});
|
||||
return res;
|
||||
}
|
||||
|
||||
getCrtDetail(crt: string = this.cert.crt) {
|
||||
|
||||
@@ -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.36.18](https://github.com/certd/certd/compare/v1.36.17...v1.36.18) (2025-08-28)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 腾讯云插件支持国际版 ([58e82d5](https://github.com/certd/certd/commit/58e82d5dbd4ebf089ef239578ef9b68454d17b30))
|
||||
* 支持部署到阿里云云原生API网关、AI网关 ([2ca20be](https://github.com/certd/certd/commit/2ca20be197720201fceabcce9d927f4dbc1cc872))
|
||||
* ssh 配置sudo免密提示 ([e1e7011](https://github.com/certd/certd/commit/e1e7011853ad0c5bd7b09c3690861d5aa34b2db4))
|
||||
|
||||
## [1.36.17](https://github.com/certd/certd/compare/v1.36.16...v1.36.17) (2025-08-17)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/plugin-lib",
|
||||
"private": false,
|
||||
"version": "1.36.17",
|
||||
"version": "1.36.18",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -21,8 +21,8 @@
|
||||
"@alicloud/pop-core": "^1.7.10",
|
||||
"@alicloud/tea-util": "^1.4.10",
|
||||
"@aws-sdk/client-s3": "^3.787.0",
|
||||
"@certd/basic": "^1.36.17",
|
||||
"@certd/pipeline": "^1.36.17",
|
||||
"@certd/basic": "^1.36.18",
|
||||
"@certd/pipeline": "^1.36.18",
|
||||
"@kubernetes/client-node": "0.21.0",
|
||||
"ali-oss": "^6.22.0",
|
||||
"basic-ftp": "^5.0.5",
|
||||
|
||||
@@ -3,6 +3,19 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.36.18](https://github.com/certd/certd/compare/v1.36.17...v1.36.18) (2025-08-28)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 修复cron选择组件星期显示错误的bug ([eb75e52](https://github.com/certd/certd/commit/eb75e52278f94a72643f7317e6740fb42666c68a))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 短信验证码支持腾讯云 ([9108459](https://github.com/certd/certd/commit/9108459ae42bcd95a59acba164a64e82e5f2cfe6))
|
||||
* 商业版支持自定义插件的参数配置 ([17f23f3](https://github.com/certd/certd/commit/17f23f37516af925d5049291d67d41e4271f81f8))
|
||||
* 支持p7b证书格式 ([d9f4a57](https://github.com/certd/certd/commit/d9f4a5793d68a017a5d80ad5385cbda603c4e165))
|
||||
* openapi返回证书时挑选匹配范围最小的那一个;增加format参数,增加返回值p7b格式,增加detail返回 ([2085bcc](https://github.com/certd/certd/commit/2085bcceb61c3723c9bdfec4c4cc0917631ff5e5))
|
||||
|
||||
## [1.36.17](https://github.com/certd/certd/compare/v1.36.16...v1.36.17) (2025-08-17)
|
||||
|
||||
**Note:** Version bump only for package @certd/ui-client
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@certd/ui-client",
|
||||
"version": "1.36.17",
|
||||
"version": "1.36.18",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite --open",
|
||||
@@ -30,6 +30,7 @@
|
||||
"@ant-design/icons-vue": "^7.0.1",
|
||||
"@aws-sdk/client-s3": "^3.535.0",
|
||||
"@aws-sdk/s3-request-presigner": "^3.535.0",
|
||||
"@certd/vue-js-cron-light": "^4.0.14",
|
||||
"@ctrl/tinycolor": "^4.1.0",
|
||||
"@fast-crud/fast-crud": "^1.25.13",
|
||||
"@fast-crud/fast-extends": "^1.25.13",
|
||||
@@ -43,7 +44,6 @@
|
||||
"@tailwindcss/typography": "^0.5.16",
|
||||
"@tanstack/vue-store": "^0.7.0",
|
||||
"@vee-validate/zod": "^4.15.0",
|
||||
"@certd/vue-js-cron-light": "^4.0.14",
|
||||
"@vue/shared": "^3.5.13",
|
||||
"@vueuse/core": "^10.11.0",
|
||||
"ant-design-vue": "^4.2.6",
|
||||
@@ -103,8 +103,8 @@
|
||||
"zod-defaults": "^0.1.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@certd/lib-iframe": "^1.36.17",
|
||||
"@certd/pipeline": "^1.36.17",
|
||||
"@certd/lib-iframe": "^1.36.18",
|
||||
"@certd/pipeline": "^1.36.18",
|
||||
"@rollup/plugin-commonjs": "^25.0.7",
|
||||
"@rollup/plugin-node-resolve": "^15.2.3",
|
||||
"@types/chai": "^4.3.12",
|
||||
|
||||
@@ -587,6 +587,7 @@ export default {
|
||||
commFeature: "Commercial feature",
|
||||
smsProvider: "SMS provider",
|
||||
aliyunSms: "Aliyun SMS",
|
||||
tencentSms: "Tencent SMS",
|
||||
yfySms: "YFY SMS",
|
||||
smsTest: "SMS test",
|
||||
testMobilePlaceholder: "Enter test mobile number",
|
||||
|
||||
@@ -593,6 +593,7 @@ export default {
|
||||
commFeature: "商业版功能",
|
||||
smsProvider: "短信提供商",
|
||||
aliyunSms: "阿里云短信",
|
||||
tencentSms: "腾讯云短信",
|
||||
yfySms: "易发云短信",
|
||||
smsTest: "短信测试",
|
||||
testMobilePlaceholder: "输入测试手机号",
|
||||
|
||||
@@ -5,6 +5,7 @@ import { i18n } from "/src/locales/i18n";
|
||||
import { cloneDeep } from "lodash-es";
|
||||
interface PluginState {
|
||||
group?: PluginGroups;
|
||||
originGroup?: PluginGroups;
|
||||
}
|
||||
|
||||
export type PluginGroup = {
|
||||
@@ -55,7 +56,7 @@ export class PluginGroups {
|
||||
if (this.mergeSetting) {
|
||||
for (const plugin of groups[key].plugins) {
|
||||
if (plugin.sysSetting) {
|
||||
merge(plugin.input, plugin.sysSetting.metadata);
|
||||
merge(plugin.input, plugin.sysSetting.metadata?.input || {});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -166,6 +167,7 @@ export const usePluginStore = defineStore({
|
||||
},
|
||||
async clear() {
|
||||
this.group = null;
|
||||
this.originGroup = null
|
||||
},
|
||||
async getList(): Promise<PluginDefine[]> {
|
||||
await this.init();
|
||||
|
||||
@@ -119,7 +119,7 @@ export async function SaveCommPluginConfigs(data: CommPluginConfig): Promise<voi
|
||||
});
|
||||
}
|
||||
|
||||
export async function savePluginSetting(req: { id: number; metadata: any }): Promise<void> {
|
||||
export async function savePluginSetting(req: { name: string; sysSetting: any }): Promise<void> {
|
||||
return await request({
|
||||
url: apiPrefix + "/saveSetting",
|
||||
method: "post",
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<div class="origin-metadata w-100%">
|
||||
<div class="block-title">
|
||||
自定义插件参数配置
|
||||
<div class="helper">1111</div>
|
||||
<div class="helper">可以设置插件选项的配置,设置配置默认值、修改帮助说明、设置是否显示该字段等</div>
|
||||
</div>
|
||||
<div class="p-10">
|
||||
<div ref="formRef" class="config-form w-full" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
@@ -16,18 +16,18 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<template v-for="(item, key) in originInputs" :key="key">
|
||||
<template v-for="item in originInputs" :key="item.key">
|
||||
<template v-for="prop in editableKeys" :key="prop.key">
|
||||
<tr>
|
||||
<td v-if="prop.key === 'value'" class="border-t-2 p-5" rowspan="3" :class="{ 'border-t-2': prop.key === 'value' }">{{ item.title }}</td>
|
||||
<td class="border-t p-5" :class="{ 'border-t-2': prop.key === 'value' }">{{ prop.label }}</td>
|
||||
<td class="border-t p-5" :class="{ 'border-t-2': prop.key === 'value' }">
|
||||
<rollbackable :value="configForm[key][prop.key]" @set="configForm[key][prop.key] = item[prop.key] ?? null" @clear="delete configForm[key][prop.key]">
|
||||
<rollbackable :value="configForm[item.key][prop.key]" @set="prop.onSet(item)" @clear="delete configForm[item.key][prop.key]">
|
||||
<template #default>
|
||||
<fs-render :render-func="prop.defaultRender(key, item)"></fs-render>
|
||||
<fs-render :render-func="prop.defaultRender(item)"></fs-render>
|
||||
</template>
|
||||
<template #edit>
|
||||
<fs-render :render-func="prop.editRender(key, item)"></fs-render>
|
||||
<fs-render :render-func="prop.editRender(item)"></fs-render>
|
||||
</template>
|
||||
</rollbackable>
|
||||
</td>
|
||||
@@ -73,9 +73,7 @@ function getScope() {
|
||||
form: configForm,
|
||||
};
|
||||
}
|
||||
function getScopeFunc() {
|
||||
return getScope;
|
||||
}
|
||||
|
||||
function getForm() {
|
||||
return configForm;
|
||||
}
|
||||
@@ -84,43 +82,52 @@ const editableKeys = ref([
|
||||
{
|
||||
key: "value",
|
||||
label: "默认值",
|
||||
defaultRender(key: string, item: any) {
|
||||
onSet(item: any) {
|
||||
configForm[item.key]["value"] = item.value ?? null;
|
||||
},
|
||||
defaultRender(item: any) {
|
||||
return () => {
|
||||
return item["value"] ?? "";
|
||||
};
|
||||
},
|
||||
editRender(key: string, item: any) {
|
||||
editRender(item: any) {
|
||||
return () => {
|
||||
return <fs-component-render {...item.component} vModel:modelValue={configForm[key]["value"]} scope={getScope()} />;
|
||||
return <fs-component-render {...item.component} vModel:modelValue={configForm[item.key]["value"]} scope={getScope()} />;
|
||||
};
|
||||
},
|
||||
},
|
||||
{
|
||||
key: "show",
|
||||
label: "是否显示",
|
||||
defaultRender(key: string, item: any) {
|
||||
onSet(item: any) {
|
||||
configForm[item.key]["show"] = item.show ?? true;
|
||||
},
|
||||
defaultRender(item: any) {
|
||||
return () => {
|
||||
const value = item["show"];
|
||||
return value === false ? "不显示" : "显示";
|
||||
};
|
||||
},
|
||||
editRender(key: string, item: any) {
|
||||
editRender(item: any) {
|
||||
return () => {
|
||||
return <a-switch vModel:checked={configForm[key]["show"]} />;
|
||||
return <a-switch vModel:checked={configForm[item.key]["show"]} />;
|
||||
};
|
||||
},
|
||||
},
|
||||
{
|
||||
key: "helper",
|
||||
label: "帮助说明",
|
||||
defaultRender(key: string, item: any) {
|
||||
onSet(item: any) {
|
||||
configForm[item.key]["helper"] = item.helper ?? "";
|
||||
},
|
||||
defaultRender(item: any) {
|
||||
return () => {
|
||||
return <pre class={"helper"}>{item["helper"]}</pre>;
|
||||
};
|
||||
},
|
||||
editRender(key: string, item: any) {
|
||||
editRender(item: any) {
|
||||
return () => {
|
||||
return <a-textarea rows={5} vModel:value={configForm[key]["helper"]} />;
|
||||
return <a-textarea rows={5} vModel:value={configForm[item.key]["helper"]} />;
|
||||
};
|
||||
},
|
||||
},
|
||||
@@ -155,7 +162,7 @@ async function loadPluginSetting() {
|
||||
const setting = props.plugin.sysSetting;
|
||||
if (setting) {
|
||||
const settingJson = JSON.parse(setting);
|
||||
merge(configForm, settingJson.metadata);
|
||||
merge(configForm, settingJson.metadata?.input || {});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
import * as api from "/@/views/sys/plugin/api";
|
||||
import { useFormWrapper } from "@fast-crud/fast-crud";
|
||||
import { useI18n } from "/@/locales";
|
||||
import { Modal, notification } from "ant-design-vue";
|
||||
import { notification } from "ant-design-vue";
|
||||
import ConfigEditor from "./config-editor.vue";
|
||||
import { useModal } from "/@/use/use-modal";
|
||||
import { ref } from "vue";
|
||||
import { usePluginStore } from "/@/store/plugin";
|
||||
|
||||
export function usePluginConfig() {
|
||||
const { openCrudFormDialog } = useFormWrapper();
|
||||
const { t } = useI18n();
|
||||
|
||||
const modal = useModal();
|
||||
const pluginStore = usePluginStore();
|
||||
// @ts-ignore
|
||||
async function openConfigDialog({ row, crudExpose }) {
|
||||
const configEditorRef = ref();
|
||||
function createCrudOptions() {
|
||||
@@ -19,7 +21,7 @@ export function usePluginConfig() {
|
||||
form: {
|
||||
wrapper: {
|
||||
width: "80%",
|
||||
title: "插件元数据配置",
|
||||
title: "插件参数自定义",
|
||||
saveRemind: false,
|
||||
slots: {
|
||||
"form-body-top": () => {
|
||||
@@ -44,12 +46,16 @@ export function usePluginConfig() {
|
||||
newForm[key] = value;
|
||||
}
|
||||
}
|
||||
return await api.savePluginSetting({
|
||||
const res = await api.savePluginSetting({
|
||||
name: row.name,
|
||||
sysSetting: {
|
||||
metadata: newForm,
|
||||
metadata: {
|
||||
input: newForm,
|
||||
},
|
||||
},
|
||||
});
|
||||
await pluginStore.clear();
|
||||
return res;
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
<a-form-item :label="t('certd.smsProvider')" :name="['private', 'sms', 'type']">
|
||||
<a-select v-model:value="formState.private.sms.type" @change="smsTypeChange">
|
||||
<a-select-option value="aliyun">{{ t("certd.aliyunSms") }}</a-select-option>
|
||||
<a-select-option value="tencent">{{ t("certd.tencentSms") }}</a-select-option>
|
||||
<a-select-option value="yfysms">{{ t("certd.yfySms") }}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
|
||||
@@ -3,6 +3,28 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.36.18](https://github.com/certd/certd/compare/v1.36.17...v1.36.18) (2025-08-28)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 更新我爱云CDN域名地址,和部分目录结构 [@tyjsjxh](https://github.com/tyjsjxh) ([#514](https://github.com/certd/certd/issues/514)) ([78e7a81](https://github.com/certd/certd/commit/78e7a81638c2ee779f0ab6c3ba7e5c6f6e064151))
|
||||
* 修复proxmox某些情况下执行卡住的bug ([ebd6917](https://github.com/certd/certd/commit/ebd6917a1d40ae4d94555c32b7e3c093d0599b94))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 部署到k8s支持自动创建secret ([c09c962](https://github.com/certd/certd/commit/c09c962cb676ca261610aa9f3e5105c9dae43f43))
|
||||
* 短信验证码支持腾讯云 ([9108459](https://github.com/certd/certd/commit/9108459ae42bcd95a59acba164a64e82e5f2cfe6))
|
||||
* 商业版支持自定义插件的参数配置 ([17f23f3](https://github.com/certd/certd/commit/17f23f37516af925d5049291d67d41e4271f81f8))
|
||||
* 腾讯云插件支持国际版 ([58e82d5](https://github.com/certd/certd/commit/58e82d5dbd4ebf089ef239578ef9b68454d17b30))
|
||||
* 腾讯云EO插件支持自动获取zoneid和域名列表 ([70fcdc9](https://github.com/certd/certd/commit/70fcdc9ebbfb7c883c0c8a2138f61a0776a9491b))
|
||||
* 支持部署到阿里云云原生API网关、AI网关 ([2ca20be](https://github.com/certd/certd/commit/2ca20be197720201fceabcce9d927f4dbc1cc872))
|
||||
* 支持部署到华为云obs ([9feb9d0](https://github.com/certd/certd/commit/9feb9d04b3c56ec95c06fcf4fd071eb0e88ffc6f))
|
||||
* 支持部署到dokploy ([7dbdeae](https://github.com/certd/certd/commit/7dbdeaebe0bfee7521a863fe5e6b4a712aec5876))
|
||||
* 支持删除宝塔证书夹中的过期证书 ([3575113](https://github.com/certd/certd/commit/3575113655be751d19f88c64491e98a89042d6a2))
|
||||
* 支持p7b证书格式 ([d9f4a57](https://github.com/certd/certd/commit/d9f4a5793d68a017a5d80ad5385cbda603c4e165))
|
||||
* lecdnv2支持api token ([e448934](https://github.com/certd/certd/commit/e4489343fee7754be07bcfc3323969dc3a30e90c))
|
||||
* openapi返回证书时挑选匹配范围最小的那一个;增加format参数,增加返回值p7b格式,增加detail返回 ([2085bcc](https://github.com/certd/certd/commit/2085bcceb61c3723c9bdfec4c4cc0917631ff5e5))
|
||||
|
||||
## [1.36.17](https://github.com/certd/certd/compare/v1.36.16...v1.36.17) (2025-08-17)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@certd/ui-server",
|
||||
"version": "1.36.17",
|
||||
"version": "1.36.18",
|
||||
"description": "fast-server base midway",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
@@ -42,20 +42,20 @@
|
||||
"@aws-sdk/client-cloudfront": "^3.699.0",
|
||||
"@aws-sdk/client-iam": "^3.699.0",
|
||||
"@aws-sdk/client-s3": "^3.705.0",
|
||||
"@certd/acme-client": "^1.36.17",
|
||||
"@certd/basic": "^1.36.17",
|
||||
"@certd/commercial-core": "^1.36.17",
|
||||
"@certd/cv4pve-api-javascript": "^8.4.1",
|
||||
"@certd/jdcloud": "^1.36.17",
|
||||
"@certd/lib-huawei": "^1.36.17",
|
||||
"@certd/lib-k8s": "^1.36.17",
|
||||
"@certd/lib-server": "^1.36.17",
|
||||
"@certd/midway-flyway-js": "^1.36.17",
|
||||
"@certd/pipeline": "^1.36.17",
|
||||
"@certd/plugin-cert": "^1.36.17",
|
||||
"@certd/plugin-lib": "^1.36.17",
|
||||
"@certd/plugin-plus": "^1.36.17",
|
||||
"@certd/plus-core": "^1.36.17",
|
||||
"@certd/acme-client": "^1.36.18",
|
||||
"@certd/basic": "^1.36.18",
|
||||
"@certd/commercial-core": "^1.36.18",
|
||||
"@certd/cv4pve-api-javascript": "^8.4.2",
|
||||
"@certd/jdcloud": "^1.36.18",
|
||||
"@certd/lib-huawei": "^1.36.18",
|
||||
"@certd/lib-k8s": "^1.36.18",
|
||||
"@certd/lib-server": "^1.36.18",
|
||||
"@certd/midway-flyway-js": "^1.36.18",
|
||||
"@certd/pipeline": "^1.36.18",
|
||||
"@certd/plugin-cert": "^1.36.18",
|
||||
"@certd/plugin-lib": "^1.36.18",
|
||||
"@certd/plugin-plus": "^1.36.18",
|
||||
"@certd/plus-core": "^1.36.18",
|
||||
"@huaweicloud/huaweicloud-sdk-cdn": "^3.1.120",
|
||||
"@huaweicloud/huaweicloud-sdk-core": "^3.1.120",
|
||||
"@koa/cors": "^5.0.0",
|
||||
|
||||
@@ -10,6 +10,7 @@ export type CertGetReq = {
|
||||
domains?: string;
|
||||
certId: number;
|
||||
autoApply?:boolean;
|
||||
format?:string; //默认是所有,pem,der,p12,pfx,jks,one,p7b
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -38,6 +39,7 @@ export class OpenCertController extends BaseOpenController {
|
||||
domains: req.domains,
|
||||
certId: req.certId,
|
||||
autoApply: req.autoApply??false,
|
||||
format: req.format
|
||||
});
|
||||
return this.ok(res);
|
||||
}
|
||||
|
||||
@@ -164,7 +164,8 @@ export class SysSettingsController extends CrudController<SysSettingsService> {
|
||||
|
||||
@Post('/getSmsTypeDefine', { summary: 'sys:settings:view' })
|
||||
async getSmsTypeDefine(@Body('type') type: string) {
|
||||
return this.ok(SmsServiceFactory.getDefine(type));
|
||||
const define =await SmsServiceFactory.getDefine(type);
|
||||
return this.ok(define);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ export class CodeService {
|
||||
}
|
||||
const smsType = sysSettings.sms.type;
|
||||
const smsConfig = sysSettings.sms.config;
|
||||
const sender: ISmsService = SmsServiceFactory.createSmsService(smsType);
|
||||
const sender: ISmsService = await SmsServiceFactory.createSmsService(smsType);
|
||||
const accessGetter = new AccessSysGetter(this.accessService);
|
||||
sender.setCtx({
|
||||
accessService: accessGetter,
|
||||
|
||||
@@ -1,25 +1,28 @@
|
||||
import { AliyunSmsService } from './aliyun-sms.js';
|
||||
import { YfySmsService } from './yfy-sms.js';
|
||||
|
||||
export class SmsServiceFactory {
|
||||
static createSmsService(type: string) {
|
||||
const cls = this.GetClassByType(type);
|
||||
static async createSmsService(type: string) {
|
||||
const cls = await this.GetClassByType(type);
|
||||
return new cls();
|
||||
}
|
||||
|
||||
static GetClassByType(type: string) {
|
||||
static async GetClassByType(type: string) {
|
||||
switch (type) {
|
||||
case 'aliyun':
|
||||
const {AliyunSmsService} = await import("./aliyun-sms.js")
|
||||
return AliyunSmsService;
|
||||
case 'yfysms':
|
||||
const {YfySmsService} = await import("./yfy-sms.js")
|
||||
return YfySmsService;
|
||||
case 'tencent':
|
||||
const {TencentSmsService} = await import("./tencent-sms.js")
|
||||
return TencentSmsService;
|
||||
default:
|
||||
throw new Error('不支持的短信服务类型');
|
||||
}
|
||||
}
|
||||
|
||||
static getDefine(type: string) {
|
||||
const cls = this.GetClassByType(type);
|
||||
static async getDefine(type: string) {
|
||||
const cls = await this.GetClassByType(type);
|
||||
return cls.getDefine();
|
||||
}
|
||||
}
|
||||
|
||||
124
packages/ui/certd-server/src/modules/basic/sms/tencent-sms.ts
Normal file
124
packages/ui/certd-server/src/modules/basic/sms/tencent-sms.ts
Normal file
@@ -0,0 +1,124 @@
|
||||
import {ISmsService, PluginInputs, SmsPluginCtx} from './api.js';
|
||||
import {TencentAccess} from "@certd/plugin-lib";
|
||||
|
||||
export type TencentSmsConfig = {
|
||||
accessId: string;
|
||||
signName: string;
|
||||
codeTemplateId: string;
|
||||
appId: string;
|
||||
region: string;
|
||||
};
|
||||
|
||||
export class TencentSmsService implements ISmsService {
|
||||
static getDefine() {
|
||||
return {
|
||||
name: 'tencent',
|
||||
desc: '腾讯云短信服务',
|
||||
input: {
|
||||
accessId: {
|
||||
title: '腾讯云授权',
|
||||
component: {
|
||||
name: 'access-selector',
|
||||
type: 'tencent',
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
region: {
|
||||
title: '区域',
|
||||
value:"ap-beijing",
|
||||
component: {
|
||||
name: 'a-select',
|
||||
vModel: 'value',
|
||||
options:[
|
||||
{value:"ap-beijing",label:"华北地区(北京)"},
|
||||
{value:"ap-guangzhou",label:"华南地区(广州)"},
|
||||
{value:"ap-nanjing",label:"华东地区(南京)"},
|
||||
]
|
||||
},
|
||||
helper:"随便选一个",
|
||||
required: true,
|
||||
},
|
||||
signName: {
|
||||
title: '签名',
|
||||
component: {
|
||||
name: 'a-input',
|
||||
vModel: 'value',
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
appId: {
|
||||
title: '应用ID',
|
||||
component: {
|
||||
name: 'a-input',
|
||||
vModel: 'value',
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
codeTemplateId: {
|
||||
title: '验证码模板Id',
|
||||
component: {
|
||||
name: 'a-input',
|
||||
vModel: 'value',
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
} as PluginInputs<TencentSmsConfig>,
|
||||
};
|
||||
}
|
||||
|
||||
ctx: SmsPluginCtx<TencentSmsConfig>;
|
||||
|
||||
setCtx(ctx: any) {
|
||||
this.ctx = ctx;
|
||||
}
|
||||
|
||||
|
||||
async getClient() {
|
||||
const sdk = await import('tencentcloud-sdk-nodejs/tencentcloud/services/sms/v20210111/index.js');
|
||||
const client = sdk.v20210111.Client;
|
||||
const access = await this.ctx.accessService.getById<TencentAccess>(this.ctx.config.accessId);
|
||||
|
||||
|
||||
// const region = this.region;
|
||||
const clientConfig = {
|
||||
credential: {
|
||||
secretId: access.secretId,
|
||||
secretKey: access.secretKey,
|
||||
},
|
||||
region: this.ctx.config.region,
|
||||
profile: {
|
||||
httpProfile: {
|
||||
endpoint: `sms.${access.intlDomain()}tencentcloudapi.com`,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
return new client(clientConfig);
|
||||
}
|
||||
|
||||
async sendSmsCode(opts: { mobile: string; code: string; phoneCode: string }) {
|
||||
const { mobile, code, phoneCode } = opts;
|
||||
|
||||
const client = await this.getClient();
|
||||
const smsConfig = this.ctx.config;
|
||||
const params = {
|
||||
"PhoneNumberSet": [
|
||||
`+${phoneCode}${mobile}`
|
||||
],
|
||||
"SmsSdkAppId": smsConfig.appId,
|
||||
"TemplateId": smsConfig.codeTemplateId,
|
||||
"SignName": smsConfig.signName,
|
||||
"TemplateParamSet": [
|
||||
code
|
||||
]
|
||||
};
|
||||
const ret = await client.SendSms(params);
|
||||
this.checkRet(ret);
|
||||
}
|
||||
|
||||
checkRet(ret: any) {
|
||||
if (!ret || ret.Error) {
|
||||
throw new Error('执行失败:' + ret.Error.Code + ',' + ret.Error.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -27,7 +27,7 @@ export class CertInfoFacade {
|
||||
@Inject()
|
||||
userSettingsService : UserSettingsService
|
||||
|
||||
async getCertInfo(req: { domains?: string; certId?: number; userId: number,autoApply?:boolean }) {
|
||||
async getCertInfo(req: { domains?: string; certId?: number; userId: number,autoApply?:boolean,format?:string }) {
|
||||
const { domains, certId, userId } = req;
|
||||
if (certId) {
|
||||
return await this.certInfoService.getCertInfoById({ id: certId, userId });
|
||||
@@ -41,7 +41,7 @@ export class CertInfoFacade {
|
||||
const domainArr = domains.split(',');
|
||||
|
||||
const matchedList = await this.certInfoService.getMatchCertList({domains:domainArr,userId})
|
||||
let matched: CertInfoEntity = null
|
||||
|
||||
if (matchedList.length === 0 ) {
|
||||
if(req.autoApply === true){
|
||||
//自动申请,先创建自动申请流水线
|
||||
@@ -54,13 +54,7 @@ export class CertInfoFacade {
|
||||
});
|
||||
}
|
||||
}
|
||||
matched = null;
|
||||
for (const item of matchedList) {
|
||||
if (item.expiresTime>0 && item.expiresTime > new Date().getTime()) {
|
||||
matched = item;
|
||||
break
|
||||
}
|
||||
}
|
||||
let matched = this.getMinixMatched(matchedList);
|
||||
if (!matched) {
|
||||
if(req.autoApply === true){
|
||||
//如果没有找到有效期内的证书,则自动触发一次申请
|
||||
@@ -75,7 +69,38 @@ export class CertInfoFacade {
|
||||
}
|
||||
}
|
||||
|
||||
return await this.certInfoService.getCertInfoById({ id: matched.id, userId: userId });
|
||||
return await this.certInfoService.getCertInfoById({ id: matched.id, userId: userId,format:req.format });
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
public getMinixMatched(matchedList: CertInfoEntity[]) {
|
||||
let matched: CertInfoEntity = null;
|
||||
for (const item of matchedList) {
|
||||
if (item.expiresTime > 0 && item.expiresTime > new Date().getTime()) {
|
||||
if (matched) {
|
||||
//如果前面已经有match的值,判断范围是否比上一个小
|
||||
const currentStars = `-${item.domains}`.split("*");
|
||||
const matchedStars = `-${matched.domains}`.split("*");
|
||||
|
||||
const currentLength = item.domains.split(",");
|
||||
const matchedLength = matched.domains.split(",");
|
||||
if (currentStars.length < matchedStars.length) {
|
||||
//如果*的数量比上一个少,则替换为当前
|
||||
matched = item;
|
||||
} else if (currentStars.length == matchedStars.length) {
|
||||
//如果*的数量相同,则比较域名数量
|
||||
if (currentLength.length < matchedLength.length) {
|
||||
matched = item;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
matched = item;
|
||||
}
|
||||
}
|
||||
}
|
||||
return matched;
|
||||
}
|
||||
|
||||
async createAutoPipeline(req:{domains:string[],userId:number}){
|
||||
|
||||
@@ -113,7 +113,7 @@ export class CertInfoService extends BaseService<CertInfoEntity> {
|
||||
});
|
||||
}
|
||||
|
||||
async getCertInfoById(req: { id: number; userId: number }) {
|
||||
async getCertInfoById(req: { id: number; userId: number,format?:string }) {
|
||||
const entity = await this.info(req.id);
|
||||
if (!entity || entity.userId !== req.userId) {
|
||||
throw new CodeException(Constants.res.openCertNotFound);
|
||||
@@ -124,7 +124,14 @@ export class CertInfoService extends BaseService<CertInfoEntity> {
|
||||
}
|
||||
const certInfo = JSON.parse(entity.certInfo) as CertInfo;
|
||||
const certReader = new CertReader(certInfo);
|
||||
return certReader.toCertInfo();
|
||||
return {
|
||||
...certReader.toCertInfo(req.format),
|
||||
detail: {
|
||||
id: entity.id,
|
||||
domains: entity.domains.split(','),
|
||||
notAfter: certReader.expires,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
async updateCertByPipelineId(pipelineId: number, cert: CertInfo,file?:string,fromType = 'pipeline') {
|
||||
|
||||
@@ -33,3 +33,4 @@ export * from './plugin-wangsu/index.js'
|
||||
export * from './plugin-admin/index.js'
|
||||
export * from './plugin-ksyun/index.js'
|
||||
export * from './plugin-apisix/index.js'
|
||||
export * from './plugin-dokploy/index.js'
|
||||
|
||||
@@ -8,7 +8,7 @@ import {CertInfo, CertReader} from "@certd/plugin-cert";
|
||||
name: "apisix",
|
||||
title: "APISIX授权",
|
||||
desc: "",
|
||||
icon: "svg:icon-ksyun"
|
||||
icon: "svg:icon-lucky"
|
||||
})
|
||||
export class ApisixAccess extends BaseAccess {
|
||||
|
||||
@@ -93,7 +93,7 @@ export class ApisixAccess extends BaseAccess {
|
||||
headers,
|
||||
baseURL: this.endpoint,
|
||||
...req,
|
||||
logRes: true,
|
||||
logRes: false,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
107
packages/ui/certd-server/src/plugins/plugin-dokploy/access.ts
Normal file
107
packages/ui/certd-server/src/plugins/plugin-dokploy/access.ts
Normal file
@@ -0,0 +1,107 @@
|
||||
import { AccessInput, BaseAccess, IsAccess } from "@certd/pipeline";
|
||||
import { HttpRequestConfig } from "@certd/basic";
|
||||
import { CertInfo } from "@certd/plugin-cert";
|
||||
|
||||
/**
|
||||
*/
|
||||
@IsAccess({
|
||||
name: "dokploy",
|
||||
title: "Dokploy授权",
|
||||
desc: "",
|
||||
icon: "svg:icon-lucky"
|
||||
})
|
||||
export class DokployAccess extends BaseAccess {
|
||||
|
||||
@AccessInput({
|
||||
title: "Dokploy地址",
|
||||
component: {
|
||||
placeholder: "http://192.168.11.11:5480",
|
||||
},
|
||||
required: true,
|
||||
})
|
||||
endpoint = '';
|
||||
|
||||
@AccessInput({
|
||||
title: 'ApiKey',
|
||||
component: {
|
||||
placeholder: 'ApiKey',
|
||||
},
|
||||
// naAyXbZmxtsfrDfneOCeirbQNIICmBgfBiYXQwryPIUOdzPkXkfnaKjeAdbOQdwp
|
||||
//tlyvdNzojaFkNfGScALLmyuFHkHcYWaxoYjiDzWFHcnZAWdjOquMSqBwHLvGDGZK
|
||||
helper: "[settings-profile](https://app.dokploy.com/dashboard/settings/profile)中配置API Keys",
|
||||
required: true,
|
||||
encrypt: true,
|
||||
})
|
||||
apiKey = '';
|
||||
|
||||
|
||||
@AccessInput({
|
||||
title: "测试",
|
||||
component: {
|
||||
name: "api-test",
|
||||
action: "TestRequest"
|
||||
},
|
||||
helper: "点击测试接口是否正常"
|
||||
})
|
||||
testRequest = true;
|
||||
|
||||
async onTestRequest() {
|
||||
await this.getCertList();
|
||||
return "ok"
|
||||
}
|
||||
|
||||
async getCertList(){
|
||||
const req = {
|
||||
url :"/api/certificates.all",
|
||||
method: "get",
|
||||
}
|
||||
return await this.doRequest(req);
|
||||
}
|
||||
|
||||
async createCert(opts:{cert:CertInfo,serverId:string,name:string}){
|
||||
const req = {
|
||||
url :"/api/certificates.create",
|
||||
method: "post",
|
||||
data:{
|
||||
// certificateId:opts.certificateId,
|
||||
"name": opts.name,
|
||||
"certificateData": opts.cert.crt,
|
||||
"privateKey": opts.cert.key,
|
||||
"serverId": opts.serverId,
|
||||
autoRenew: false,
|
||||
organizationId : ""
|
||||
}
|
||||
}
|
||||
return await this.doRequest(req);
|
||||
}
|
||||
|
||||
|
||||
async removeCert (opts:{id:string}){
|
||||
const req = {
|
||||
url :"/api/certificates.remove",
|
||||
method: "post",
|
||||
data:{
|
||||
certificateId:opts.id,
|
||||
}
|
||||
}
|
||||
return await this.doRequest(req);
|
||||
}
|
||||
|
||||
async doRequest(req: HttpRequestConfig){
|
||||
const headers = {
|
||||
"x-api-key": this.apiKey,
|
||||
...req.headers
|
||||
};
|
||||
return await this.ctx.http.request({
|
||||
headers,
|
||||
baseURL: this.endpoint,
|
||||
...req,
|
||||
logRes: true,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
new DokployAccess();
|
||||
@@ -0,0 +1,2 @@
|
||||
export * from "./plugins/index.js";
|
||||
export * from "./access.js";
|
||||
@@ -0,0 +1 @@
|
||||
import "./plugin-refresh-cert.js"
|
||||
@@ -0,0 +1,117 @@
|
||||
import { AbstractTaskPlugin, IsTaskPlugin, PageSearch, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline";
|
||||
import {CertApplyPluginNames, CertInfo} from "@certd/plugin-cert";
|
||||
import {createCertDomainGetterInputDefine, createRemoteSelectInputDefine} from "@certd/plugin-lib";
|
||||
import {DokployAccess} from "../access.js";
|
||||
|
||||
@IsTaskPlugin({
|
||||
//命名规范,插件类型+功能(就是目录plugin-demo中的demo),大写字母开头,驼峰命名
|
||||
name: "DokployRefreshCert",
|
||||
title: "Dokploy-更新证书",
|
||||
desc: "自动更新Dokploy证书",
|
||||
icon: "svg:icon-lucky",
|
||||
//插件分组
|
||||
group: pluginGroups.panel.key,
|
||||
needPlus: true,
|
||||
default: {
|
||||
//默认值配置照抄即可
|
||||
strategy: {
|
||||
runStrategy: RunStrategy.SkipWhenSucceed
|
||||
}
|
||||
}
|
||||
})
|
||||
//类名规范,跟上面插件名称(name)一致
|
||||
export class DokployRefreshCert extends AbstractTaskPlugin {
|
||||
//证书选择,此项必须要有
|
||||
@TaskInput({
|
||||
title: "域名证书",
|
||||
helper: "请选择前置任务输出的域名证书",
|
||||
component: {
|
||||
name: "output-selector",
|
||||
from: [...CertApplyPluginNames]
|
||||
}
|
||||
// required: true, // 必填
|
||||
})
|
||||
cert!: CertInfo;
|
||||
|
||||
@TaskInput(createCertDomainGetterInputDefine({ props: { required: false } }))
|
||||
certDomains!: string[];
|
||||
|
||||
//授权选择框
|
||||
@TaskInput({
|
||||
title: "Dokploy授权",
|
||||
component: {
|
||||
name: "access-selector",
|
||||
type: "dokploy" //固定授权类型
|
||||
},
|
||||
required: true //必填
|
||||
})
|
||||
accessId!: string;
|
||||
//
|
||||
|
||||
@TaskInput(
|
||||
createRemoteSelectInputDefine({
|
||||
title: "证书名称",
|
||||
helper: "要更新的证书名称,如果这里没有,请先给手动绑定一次证书",
|
||||
action: DokployRefreshCert.prototype.onGetCertList.name,
|
||||
pager: false,
|
||||
search: false
|
||||
})
|
||||
)
|
||||
certList!: string[];
|
||||
|
||||
//插件实例化时执行的方法
|
||||
async onInstance() {
|
||||
}
|
||||
|
||||
//插件执行方法
|
||||
async execute(): Promise<void> {
|
||||
const access = await this.getAccess<DokployAccess>(this.accessId);
|
||||
|
||||
// await access.createCert({cert:this.cert})
|
||||
|
||||
const certList = await access.getCertList();
|
||||
|
||||
|
||||
for (const certId of this.certList) {
|
||||
this.logger.info(`----------- 开始更新证书:${certId}`);
|
||||
const [serverId,name] = certId.split("#");
|
||||
const founds = certList.filter((item: any) => item.name === name);
|
||||
if (founds){
|
||||
for (const found of founds) {
|
||||
await access.removeCert({id:found.certificateId})
|
||||
}
|
||||
}
|
||||
|
||||
await access.createCert({
|
||||
name,
|
||||
cert: this.cert,
|
||||
serverId: serverId,
|
||||
});
|
||||
this.logger.info(`----------- 更新证书${certId}成功`);
|
||||
}
|
||||
|
||||
this.logger.info("部署完成");
|
||||
}
|
||||
|
||||
async onGetCertList(data: PageSearch = {}) {
|
||||
const access = await this.getAccess<DokployAccess>(this.accessId);
|
||||
|
||||
const res = await access.getCertList()
|
||||
const list = res
|
||||
if (!list || list.length === 0) {
|
||||
throw new Error("没有找到证书,你可以直接手动输入id,如果id不存在将自动创建");
|
||||
}
|
||||
|
||||
const options = list.map((item: any) => {
|
||||
return {
|
||||
label: `${item.name}<${item.serverId}>`,
|
||||
value: `${item.serverId}#${item.name}`,
|
||||
domain: item.name
|
||||
};
|
||||
});
|
||||
return options;
|
||||
}
|
||||
}
|
||||
|
||||
//实例化一下,注册插件
|
||||
new DokployRefreshCert();
|
||||
@@ -61,10 +61,12 @@ export class ProxmoxAccess extends BaseAccess {
|
||||
|
||||
@AccessInput({
|
||||
title: '领域',
|
||||
value: "pam",
|
||||
component: {
|
||||
placeholder: 'realm',
|
||||
placeholder: 'pam、pve。默认值 pam',
|
||||
},
|
||||
required: true,
|
||||
helper:"pam 或 pve。默认值 pam",
|
||||
required: false,
|
||||
encrypt: false,
|
||||
})
|
||||
realm = '';
|
||||
|
||||
@@ -71,8 +71,14 @@ export class ProxmoxUploadCert extends AbstractPlusTaskPlugin {
|
||||
|
||||
for (const node of this.nodes) {
|
||||
this.logger.info(`开始上传证书到节点:${node}`);
|
||||
const res = await client.nodes.get(node).certificates.custom.uploadCustomCert(cert.crt, true, cert.key, true);
|
||||
this.logger.info(`上传结果:${JSON.stringify(res.response)}`);
|
||||
try{
|
||||
const res = await client.nodes.get(node).certificates.custom.uploadCustomCert(cert.crt, true, cert.key, true);
|
||||
this.logger.info(`上传结果:${JSON.stringify(res.response)}`);
|
||||
}catch (e) {
|
||||
this.logger.error(`执行失败:${e.message},请检查节点名称是否正确`);
|
||||
throw e
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
this.logger.info('部署成功');
|
||||
|
||||
@@ -34,20 +34,6 @@ export class DeployCertToTencentTKEIngressPlugin extends AbstractTaskPlugin {
|
||||
})
|
||||
ingressClass!: string;
|
||||
|
||||
/**
|
||||
* AccessProvider的key,或者一个包含access的具体的对象
|
||||
*/
|
||||
@TaskInput({
|
||||
title: "Access授权",
|
||||
helper: "access授权",
|
||||
component: {
|
||||
name: "access-selector",
|
||||
type: "tencent"
|
||||
},
|
||||
required: true
|
||||
})
|
||||
accessId!: string;
|
||||
|
||||
@TaskInput({
|
||||
title: "腾讯云证书id",
|
||||
helper: "请选择“上传证书到腾讯云”前置任务的输出",
|
||||
@@ -66,6 +52,7 @@ export class DeployCertToTencentTKEIngressPlugin extends AbstractTaskPlugin {
|
||||
})
|
||||
tencentCertId!: string;
|
||||
|
||||
|
||||
@TaskInput({
|
||||
title: "域名证书",
|
||||
helper: "请选择前置任务输出的域名证书",
|
||||
@@ -85,6 +72,24 @@ export class DeployCertToTencentTKEIngressPlugin extends AbstractTaskPlugin {
|
||||
cert!: any;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* AccessProvider的key,或者一个包含access的具体的对象
|
||||
*/
|
||||
@TaskInput({
|
||||
title: "Access授权",
|
||||
helper: "access授权",
|
||||
component: {
|
||||
name: "access-selector",
|
||||
type: "tencent"
|
||||
},
|
||||
required: true
|
||||
})
|
||||
accessId!: string;
|
||||
|
||||
|
||||
|
||||
@TaskInput({ title: "大区", value: "ap-guangzhou", required: true })
|
||||
region!: string;
|
||||
|
||||
@@ -147,6 +152,17 @@ export class DeployCertToTencentTKEIngressPlugin extends AbstractTaskPlugin {
|
||||
})
|
||||
skipTLSVerify!:boolean
|
||||
|
||||
@TaskInput({
|
||||
title: "Secret自动创建",
|
||||
helper: "如果Secret不存在,则创建",
|
||||
value: false,
|
||||
component: {
|
||||
name: "a-switch",
|
||||
vModel: "checked",
|
||||
},
|
||||
})
|
||||
createOnNotFound: boolean;
|
||||
|
||||
|
||||
// @TaskInput({ title: "集群内网ip", helper: "如果开启了外网的话,无需设置" })
|
||||
// clusterIp!: string;
|
||||
@@ -288,7 +304,7 @@ export class DeployCertToTencentTKEIngressPlugin extends AbstractTaskPlugin {
|
||||
secretNames = [secretName];
|
||||
}
|
||||
for (const secret of secretNames) {
|
||||
await k8sClient.patchSecret({ namespace, secretName: secret, body });
|
||||
await k8sClient.patchSecret({ namespace, secretName: secret, body , createOnNotFound: this.createOnNotFound});
|
||||
this.logger.info(`CertSecret已更新:${secret}`);
|
||||
}
|
||||
}
|
||||
|
||||
16
pnpm-lock.yaml
generated
16
pnpm-lock.yaml
generated
@@ -1492,8 +1492,8 @@ importers:
|
||||
specifier: ^1.36.17
|
||||
version: link:../../pro/commercial-core
|
||||
'@certd/cv4pve-api-javascript':
|
||||
specifier: ^8.4.1
|
||||
version: 8.4.1
|
||||
specifier: ^8.4.2
|
||||
version: 8.4.2
|
||||
'@certd/jdcloud':
|
||||
specifier: ^1.36.17
|
||||
version: link:../../libs/lib-jdcloud
|
||||
@@ -2766,8 +2766,8 @@ packages:
|
||||
'@better-scroll/zoom@2.5.1':
|
||||
resolution: {integrity: sha512-aGvFY5ooeZWS4RcxQLD+pGLpQHQxpPy0sMZV3yadcd2QK53PK9gS4Dp+BYfRv8lZ4/P2LoNEhr6Wq1DN6+uPlA==}
|
||||
|
||||
'@certd/cv4pve-api-javascript@8.4.1':
|
||||
resolution: {integrity: sha512-jxlRieJmCA0Z9LnwX6Ra6ZekRGJEu8o8RGYoKU0Jjkhc9jm6ChEbVyfE7Iw49/hlpA+2yaHdAXb46au/afCISg==}
|
||||
'@certd/cv4pve-api-javascript@8.4.2':
|
||||
resolution: {integrity: sha512-udGce7ewrVl4DmZvX+17PjsnqsdDIHEDatr8QP0AVrY2p+8JkaSPW4mXCKiLGf82C9K2+GXgT+qNIqgW7tfF9Q==}
|
||||
|
||||
'@certd/vue-js-cron-core@6.0.3':
|
||||
resolution: {integrity: sha512-kqzoAMhYz9j6FGNWEODRYtt4NpUEUwjpkU89z5WVg2tCtOcI5VhwyUGOd8AxiBCRfd6PtXvzuqw85PaOps9wrQ==}
|
||||
@@ -15448,7 +15448,7 @@ snapshots:
|
||||
dependencies:
|
||||
'@better-scroll/core': 2.5.1
|
||||
|
||||
'@certd/cv4pve-api-javascript@8.4.1':
|
||||
'@certd/cv4pve-api-javascript@8.4.2':
|
||||
dependencies:
|
||||
debug: 4.4.1(supports-color@8.1.1)
|
||||
transitivePeerDependencies:
|
||||
@@ -21535,13 +21535,13 @@ snapshots:
|
||||
resolve: 1.22.10
|
||||
semver: 6.3.1
|
||||
|
||||
eslint-plugin-prettier@3.4.1(eslint-config-prettier@8.10.0(eslint@7.32.0))(eslint@7.32.0)(prettier@2.8.8):
|
||||
eslint-plugin-prettier@3.4.1(eslint-config-prettier@8.10.0(eslint@8.57.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@7.32.0)
|
||||
eslint-config-prettier: 8.10.0(eslint@8.57.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:
|
||||
@@ -24249,7 +24249,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@7.32.0))(eslint@7.32.0)(prettier@2.8.8)
|
||||
eslint-plugin-prettier: 3.4.1(eslint-config-prettier@8.10.0(eslint@8.57.0))(eslint@7.32.0)(prettier@2.8.8)
|
||||
execa: 5.1.1
|
||||
inquirer: 7.3.3
|
||||
json5: 2.2.3
|
||||
|
||||
Reference in New Issue
Block a user