From 7a9eec88e8eddf40dba055c072b5b2b0f67c1407 Mon Sep 17 00:00:00 2001 From: xiaojunnuo Date: Fri, 10 Apr 2026 00:08:10 +0800 Subject: [PATCH] =?UTF-8?q?perf:=201panel=E6=94=AF=E6=8C=81=E5=85=88?= =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E8=AF=81=E4=B9=A6=E5=86=8D=E9=80=89=E6=8B=A9?= =?UTF-8?q?=E8=AF=81=E4=B9=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../plugin-lib/src/cert/cert-reader.ts | 3 + .../plugins/plugin-lib/src/cert/consts.ts | 2 +- packages/plugins/plugin-lib/src/cert/index.ts | 2 +- .../plugins/plugin-lib/src/common/util.ts | 5 + .../plugins/common/remote-select.vue | 8 +- .../src/components/plugins/common/types.ts | 5 + .../components/plugins/common/upload-cert.vue | 101 ++++++++++++++++++ .../service/getter/cert-info-getter.ts | 32 ++++++ .../service/getter/task-service-getter.ts | 10 ++ .../1panel/plugins/deploy-to-website.ts | 34 +++++- 10 files changed, 197 insertions(+), 5 deletions(-) create mode 100644 packages/ui/certd-client/src/components/plugins/common/types.ts create mode 100644 packages/ui/certd-client/src/components/plugins/common/upload-cert.vue create mode 100644 packages/ui/certd-server/src/modules/pipeline/service/getter/cert-info-getter.ts diff --git a/packages/plugins/plugin-lib/src/cert/cert-reader.ts b/packages/plugins/plugin-lib/src/cert/cert-reader.ts index 62132d5d4..cfbf88f2c 100644 --- a/packages/plugins/plugin-lib/src/cert/cert-reader.ts +++ b/packages/plugins/plugin-lib/src/cert/cert-reader.ts @@ -7,6 +7,9 @@ import { ILogger } from "@certd/basic"; import dayjs from "dayjs"; import { uniq } from "lodash-es"; +export interface ICertInfoGetter { + getByPipelineId: (pipelineId: number) => Promise; +} export type CertInfo = { crt: string; //fullchain证书 key: string; //私钥 diff --git a/packages/plugins/plugin-lib/src/cert/consts.ts b/packages/plugins/plugin-lib/src/cert/consts.ts index a9ded8ebb..8b5df7c4f 100644 --- a/packages/plugins/plugin-lib/src/cert/consts.ts +++ b/packages/plugins/plugin-lib/src/cert/consts.ts @@ -1,2 +1,2 @@ export const CertApplyPluginNames = [":cert:"]; -export const EVENT_CERT_APPLY_SUCCESS = "CertApply.success"; \ No newline at end of file +export const EVENT_CERT_APPLY_SUCCESS = "CertApply.success"; diff --git a/packages/plugins/plugin-lib/src/cert/index.ts b/packages/plugins/plugin-lib/src/cert/index.ts index 0eed8630f..0a545b59c 100644 --- a/packages/plugins/plugin-lib/src/cert/index.ts +++ b/packages/plugins/plugin-lib/src/cert/index.ts @@ -1,4 +1,4 @@ export * from "./convert.js"; export * from "./cert-reader.js"; export * from "./consts.js"; -export * from "./dns-provider/index.js"; \ No newline at end of file +export * from "./dns-provider/index.js"; diff --git a/packages/plugins/plugin-lib/src/common/util.ts b/packages/plugins/plugin-lib/src/common/util.ts index 12f22e09c..5705799f8 100644 --- a/packages/plugins/plugin-lib/src/common/util.ts +++ b/packages/plugins/plugin-lib/src/common/util.ts @@ -44,6 +44,10 @@ export function createRemoteSelectInputDefine(opts?: { component?: any; value?: any; pageSize?: number; + uploadCert?: { + title?: string; + columns?: Record; + }; }) { const title = opts?.title || "请选择"; const certDomainsInputKey = opts?.certDomainsInputKey || "certDomains"; @@ -74,6 +78,7 @@ export function createRemoteSelectInputDefine(opts?: { multi, pageSize: opts?.pageSize, watches: [certDomainsInputKey, accessIdInputKey, ...watches], + uploadCert: opts?.uploadCert, ...opts.component, }, value: opts.value, diff --git a/packages/ui/certd-client/src/components/plugins/common/remote-select.vue b/packages/ui/certd-client/src/components/plugins/common/remote-select.vue index ccf1a1c44..d4c0f1cc6 100644 --- a/packages/ui/certd-client/src/components/plugins/common/remote-select.vue +++ b/packages/ui/certd-client/src/components/plugins/common/remote-select.vue @@ -25,8 +25,9 @@ -
+
+
@@ -39,6 +40,8 @@ import { ComponentPropsType, doRequest } from "/@/components/plugins/lib"; import { defineComponent, inject, ref, useAttrs, watch, Ref } from "vue"; import { PluginDefine } from "@certd/pipeline"; import { getInputFromForm } from "./utils"; +import UploadCert from "./upload-cert.vue"; +import { UploadCertProps } from "./types"; defineOptions({ name: "RemoteSelect", @@ -65,9 +68,10 @@ const props = defineProps< pager?: boolean; multi?: boolean; pageSize?: number; + uploadCert?: UploadCertProps; } & ComponentPropsType >(); - +debugger; const emit = defineEmits<{ "update:value": any; }>(); diff --git a/packages/ui/certd-client/src/components/plugins/common/types.ts b/packages/ui/certd-client/src/components/plugins/common/types.ts new file mode 100644 index 000000000..969f0d632 --- /dev/null +++ b/packages/ui/certd-client/src/components/plugins/common/types.ts @@ -0,0 +1,5 @@ +export interface UploadCertProps { + title?: string; + columns?: Record; + button?: any; +} diff --git a/packages/ui/certd-client/src/components/plugins/common/upload-cert.vue b/packages/ui/certd-client/src/components/plugins/common/upload-cert.vue new file mode 100644 index 000000000..ac5ac806b --- /dev/null +++ b/packages/ui/certd-client/src/components/plugins/common/upload-cert.vue @@ -0,0 +1,101 @@ + + + diff --git a/packages/ui/certd-server/src/modules/pipeline/service/getter/cert-info-getter.ts b/packages/ui/certd-server/src/modules/pipeline/service/getter/cert-info-getter.ts new file mode 100644 index 000000000..462b1ee81 --- /dev/null +++ b/packages/ui/certd-server/src/modules/pipeline/service/getter/cert-info-getter.ts @@ -0,0 +1,32 @@ +import { CertInfo, CertReader, ICertInfoGetter } from '@certd/plugin-lib'; +import { CertInfoService } from '../../../monitor/index.js'; + +export class CertInfoGetter implements ICertInfoGetter { + userId: number; + projectId: number; + certInfoService: CertInfoService; + constructor(userId: number, projectId: number, certInfoService: CertInfoService) { + this.userId = userId; + this.projectId = projectId; + this.certInfoService = certInfoService; + } + async getByPipelineId(pipelineId: number): Promise { + if (!pipelineId) { + throw new Error(`流水线id不能为空`) + } + const query :any= { + pipelineId, + userId: this.userId, + } + if (this.projectId) { + query.projectId = this.projectId + } + const entity = await this.certInfoService.findOne({ + where:query + }) + if (!entity || !entity.certInfo) { + throw new Error(`流水线(${pipelineId})还未生成证书,请先运行一次流水线`) + } + return new CertReader(JSON.parse(entity.certInfo)).cert; + } +} diff --git a/packages/ui/certd-server/src/modules/pipeline/service/getter/task-service-getter.ts b/packages/ui/certd-server/src/modules/pipeline/service/getter/task-service-getter.ts index 12ef4e1d7..682c4dd2a 100644 --- a/packages/ui/certd-server/src/modules/pipeline/service/getter/task-service-getter.ts +++ b/packages/ui/certd-server/src/modules/pipeline/service/getter/task-service-getter.ts @@ -9,6 +9,9 @@ import { SubDomainsGetter } from "./sub-domain-getter.js"; import { DomainVerifierGetter } from "./domain-verifier-getter.js"; import { DomainService } from "../../../cert/service/domain-service.js"; import { SubDomainService } from "../sub-domain-service.js"; +import { CertInfoGetter } from "./cert-info-getter.js"; +import { CertInfoService } from "../../../monitor/index.js"; +import { ICertInfoGetter } from "@certd/plugin-lib"; const serviceNames = [ 'ocrService', @@ -34,6 +37,8 @@ export class TaskServiceGetter implements IServiceGetter{ return await this.getNotificationService() as T } else if (serviceName === 'domainVerifierGetter') { return await this.getDomainVerifierGetter() as T + } else if (serviceName === 'certInfoGetter') { + return await this.getCertInfoGetter() as T }else{ if(!serviceNames.includes(serviceName)){ throw new Error(`${serviceName} not in whitelist`) @@ -51,6 +56,11 @@ export class TaskServiceGetter implements IServiceGetter{ return new SubDomainsGetter(this.userId,this.projectId, subDomainsService,domainService) } + async getCertInfoGetter(): Promise { + const certInfoService:CertInfoService = await this.appCtx.getAsync("certInfoService") + return new CertInfoGetter(this.userId, this.projectId, certInfoService) + } + async getAccessService(): Promise { const accessService:AccessService = await this.appCtx.getAsync("accessService") return new AccessGetter(this.userId, this.projectId, accessService.getById.bind(accessService)); diff --git a/packages/ui/certd-server/src/plugins/plugin-plus/1panel/plugins/deploy-to-website.ts b/packages/ui/certd-server/src/plugins/plugin-plus/1panel/plugins/deploy-to-website.ts index 78d3c2822..6f9806eee 100644 --- a/packages/ui/certd-server/src/plugins/plugin-plus/1panel/plugins/deploy-to-website.ts +++ b/packages/ui/certd-server/src/plugins/plugin-plus/1panel/plugins/deploy-to-website.ts @@ -2,7 +2,7 @@ import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput import { CertApplyPluginNames, CertInfo } from "@certd/plugin-cert"; import { OnePanelAccess } from "../access.js"; -import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from "@certd/plugin-lib"; +import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine, ICertInfoGetter } from "@certd/plugin-lib"; import { OnePanelClient } from "../client.js"; @IsTaskPlugin({ @@ -66,6 +66,7 @@ export class OnePanelDeployToWebsitePlugin extends AbstractTaskPlugin { watches: ["accessId"], helper: "要更新的1Panel证书id,选择授权之后,从下拉框中选择\nIP需要加白名单,如果是同一台机器部署的,可以试试172.16.0.0/12", required: true, + uploadCert: {} }) ) sslIds!: string[]; @@ -213,5 +214,36 @@ export class OnePanelDeployToWebsitePlugin extends AbstractTaskPlugin { }); return this.ctx.utils.options.buildGroupOptions(list, this.certDomains); } + + async onUploadCert(data: { pipelineId: string, certName: string }) { + if (!this.access) { + throw new Error("请先选择1panel授权"); + } + const certInfoGetter = await this.ctx.serviceGetter.get("certInfoGetter") + const cert = await certInfoGetter.getByPipelineId(Number(data.pipelineId)); + + const client = new OnePanelClient({ + access: this.access, + http: this.http, + logger: this.logger, + utils: this.ctx.utils, + }); + + await client.doRequest({ + url: `/api/${this.access.apiVersion}/websites/ssl/upload`, + method: "post", + data: { + sslId: 0, + certificate: cert.crt, + certificatePath: "", + description: data.certName, + privateKey: cert.key, + privateKeyPath: "", + type: "paste", + }, + currentNode: this.currentNode, + }); + + } } new OnePanelDeployToWebsitePlugin();