From 7dbdeaebe0bfee7521a863fe5e6b4a712aec5876 Mon Sep 17 00:00:00 2001 From: xiaojunnuo Date: Fri, 29 Aug 2025 00:38:45 +0800 Subject: [PATCH] =?UTF-8?q?perf:=20=E6=94=AF=E6=8C=81=E9=83=A8=E7=BD=B2?= =?UTF-8?q?=E5=88=B0dokploy?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/ui/certd-server/src/plugins/index.ts | 1 + .../src/plugins/plugin-apisix/access.ts | 4 +- .../src/plugins/plugin-dokploy/access.ts | 107 ++++++++++++++++ .../src/plugins/plugin-dokploy/index.ts | 2 + .../plugins/plugin-dokploy/plugins/index.ts | 1 + .../plugins/plugin-refresh-cert.ts | 117 ++++++++++++++++++ 6 files changed, 230 insertions(+), 2 deletions(-) create mode 100644 packages/ui/certd-server/src/plugins/plugin-dokploy/access.ts create mode 100644 packages/ui/certd-server/src/plugins/plugin-dokploy/index.ts create mode 100644 packages/ui/certd-server/src/plugins/plugin-dokploy/plugins/index.ts create mode 100644 packages/ui/certd-server/src/plugins/plugin-dokploy/plugins/plugin-refresh-cert.ts diff --git a/packages/ui/certd-server/src/plugins/index.ts b/packages/ui/certd-server/src/plugins/index.ts index 15ca8925..8157b61d 100644 --- a/packages/ui/certd-server/src/plugins/index.ts +++ b/packages/ui/certd-server/src/plugins/index.ts @@ -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' diff --git a/packages/ui/certd-server/src/plugins/plugin-apisix/access.ts b/packages/ui/certd-server/src/plugins/plugin-apisix/access.ts index 3b917706..e2e15737 100644 --- a/packages/ui/certd-server/src/plugins/plugin-apisix/access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-apisix/access.ts @@ -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, }); } diff --git a/packages/ui/certd-server/src/plugins/plugin-dokploy/access.ts b/packages/ui/certd-server/src/plugins/plugin-dokploy/access.ts new file mode 100644 index 00000000..cdc8fafb --- /dev/null +++ b/packages/ui/certd-server/src/plugins/plugin-dokploy/access.ts @@ -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(); diff --git a/packages/ui/certd-server/src/plugins/plugin-dokploy/index.ts b/packages/ui/certd-server/src/plugins/plugin-dokploy/index.ts new file mode 100644 index 00000000..02dc3945 --- /dev/null +++ b/packages/ui/certd-server/src/plugins/plugin-dokploy/index.ts @@ -0,0 +1,2 @@ +export * from "./plugins/index.js"; +export * from "./access.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-dokploy/plugins/index.ts b/packages/ui/certd-server/src/plugins/plugin-dokploy/plugins/index.ts new file mode 100644 index 00000000..705339de --- /dev/null +++ b/packages/ui/certd-server/src/plugins/plugin-dokploy/plugins/index.ts @@ -0,0 +1 @@ +import "./plugin-refresh-cert.js" diff --git a/packages/ui/certd-server/src/plugins/plugin-dokploy/plugins/plugin-refresh-cert.ts b/packages/ui/certd-server/src/plugins/plugin-dokploy/plugins/plugin-refresh-cert.ts new file mode 100644 index 00000000..1e97beb6 --- /dev/null +++ b/packages/ui/certd-server/src/plugins/plugin-dokploy/plugins/plugin-refresh-cert.ts @@ -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 { + const access = await this.getAccess(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(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();