diff --git a/packages/plugins/plugin-cert/src/plugin/cert-plugin/base-convert.ts b/packages/plugins/plugin-cert/src/plugin/cert-plugin/base-convert.ts index 36da600a..9301e144 100644 --- a/packages/plugins/plugin-cert/src/plugin/cert-plugin/base-convert.ts +++ b/packages/plugins/plugin-cert/src/plugin/cert-plugin/base-convert.ts @@ -4,6 +4,7 @@ import type { CertInfo } from "./acme.js"; import { CertReader } from "./cert-reader.js"; import JSZip from "jszip"; import { CertConverter } from "./convert.js"; +export const EVENT_CERT_APPLY_SUCCESS = "CertApply.success"; export abstract class CertApplyBaseConvertPlugin extends AbstractTaskPlugin { @TaskInput({ @@ -76,6 +77,16 @@ export abstract class CertApplyBaseConvertPlugin extends AbstractTaskPlugin { abstract onInit(): Promise; + //必须output之后执行 + async emitCertApplySuccess() { + const emitter = this.ctx.emitter; + const value = { + cert: this.cert, + file: this._result.files[0].path, + }; + await emitter.emit(EVENT_CERT_APPLY_SUCCESS, value); + } + async output(certReader: CertReader, isNew: boolean) { const cert: CertInfo = certReader.toCertInfo(); this.cert = cert; diff --git a/packages/plugins/plugin-cert/src/plugin/cert-plugin/base.ts b/packages/plugins/plugin-cert/src/plugin/cert-plugin/base.ts index fa5be9a6..46bf9efb 100644 --- a/packages/plugins/plugin-cert/src/plugin/cert-plugin/base.ts +++ b/packages/plugins/plugin-cert/src/plugin/cert-plugin/base.ts @@ -1,15 +1,9 @@ -import { NotificationBody, Step, TaskEmitter, TaskInput } from "@certd/pipeline"; +import { NotificationBody, Step, TaskInput } from "@certd/pipeline"; import dayjs from "dayjs"; import { CertReader } from "./cert-reader.js"; import { pick } from "lodash-es"; import { CertApplyBaseConvertPlugin } from "./base-convert.js"; -export const EVENT_CERT_APPLY_SUCCESS = "CertApply.success"; - -export async function emitCertApplySuccess(emitter: TaskEmitter, cert: CertReader) { - await emitter.emit(EVENT_CERT_APPLY_SUCCESS, cert); -} - export abstract class CertApplyBasePlugin extends CertApplyBaseConvertPlugin { @TaskInput({ title: "邮箱", @@ -75,7 +69,7 @@ export abstract class CertApplyBasePlugin extends CertApplyBaseConvertPlugin { if (cert != null) { await this.output(cert, true); - await emitCertApplySuccess(this.ctx.emitter, cert); + await this.emitCertApplySuccess(); //清空后续任务的状态,让后续任务能够重新执行 this.clearLastStatus(); diff --git a/packages/plugins/plugin-cert/src/plugin/cert-plugin/custom/d.ts b/packages/plugins/plugin-cert/src/plugin/cert-plugin/custom/d.ts deleted file mode 100644 index 619ff4a4..00000000 --- a/packages/plugins/plugin-cert/src/plugin/cert-plugin/custom/d.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { CertInfo } from "../acme"; -export interface ICertApplyUploadService { - getCertInfo: (opts: { certId: number; userId: number }) => Promise; - updateCert: (opts: { certId: number; cert: CertInfo; userId: number }) => Promise; -} diff --git a/packages/plugins/plugin-cert/src/plugin/cert-plugin/custom/index.ts b/packages/plugins/plugin-cert/src/plugin/cert-plugin/custom/index.ts index de57aa58..27566afb 100644 --- a/packages/plugins/plugin-cert/src/plugin/cert-plugin/custom/index.ts +++ b/packages/plugins/plugin-cert/src/plugin/cert-plugin/custom/index.ts @@ -2,9 +2,8 @@ import { IsTaskPlugin, pluginGroups, RunStrategy, Step, TaskInput, TaskOutput } import type { CertInfo } from "../acme.js"; import { CertReader } from "../cert-reader.js"; import { CertApplyBaseConvertPlugin } from "../base-convert.js"; -export * from "./d.js"; import dayjs from "dayjs"; -import { ICertApplyUploadService } from "./d"; + export { CertReader }; export type { CertInfo }; @IsTaskPlugin({ @@ -84,7 +83,7 @@ export class CertApplyUploadPlugin extends CertApplyBaseConvertPlugin { } `, }) - certInfoId!: string; + uploadCert!: CertInfo; @TaskOutput({ title: "证书MD5", @@ -100,14 +99,7 @@ export class CertApplyUploadPlugin extends CertApplyBaseConvertPlugin { async onInit(): Promise {} async getCertFromStore() { - const certApplyUploadService: ICertApplyUploadService = await this.ctx.serviceGetter.get("CertApplyUploadService"); - - const certInfo = await certApplyUploadService.getCertInfo({ - certId: Number(this.certInfoId), - userId: this.pipeline.userId, - }); - - const certReader = new CertReader(certInfo); + const certReader = new CertReader(this.uploadCert); if (!certReader.expires && certReader.expires < new Date().getTime()) { throw new Error("证书已过期,停止部署,请重新上传证书"); } @@ -121,39 +113,43 @@ export class CertApplyUploadPlugin extends CertApplyBaseConvertPlugin { const leftDays = dayjs(certReader.expires).diff(dayjs(), "day"); this.logger.info(`证书过期时间${dayjs(certReader.expires).format("YYYY-MM-DD HH:mm:ss")},剩余${leftDays}天`); - const lastCrtMd5 = this.lastStatus?.status?.output?.certMd5; - this.logger.info("证书MD5", crtMd5); - this.logger.info("上次证书MD5", lastCrtMd5); - if (lastCrtMd5 === crtMd5) { - this.logger.info("证书无变化,跳过"); - //输出证书MD5 - this.certMd5 = crtMd5; - await this.output(certReader, false); - return "skip"; + + if (!this.ctx.inputChanged) { + this.logger.info("输入参数无变化"); + const lastCrtMd5 = this.lastStatus?.status?.output?.certMd5; + this.logger.info("证书MD5", crtMd5); + this.logger.info("上次证书MD5", lastCrtMd5); + if (lastCrtMd5 === crtMd5) { + this.logger.info("证书无变化,跳过"); + //输出证书MD5 + this.certMd5 = crtMd5; + await this.output(certReader, false); + return "skip"; + } + this.logger.info("证书有变化,重新部署"); + } else { + this.logger.info("输入参数有变化,重新部署"); } - this.logger.info("证书有变化,重新部署"); + this.clearLastStatus(); //输出证书MD5 this.certMd5 = crtMd5; await this.output(certReader, true); + + //必须output之后执行 + await this.emitCertApplySuccess(); return; } async onCertUpdate(data: any) { - const certApplyUploadService = await this.ctx.serviceGetter.get("CertApplyUploadService"); - - const res = await certApplyUploadService.updateCert({ - certId: this.certInfoId, - userId: this.ctx.user.id, - cert: { - crt: data.crt, - key: data.key, - }, - }); - + const certReader = new CertReader(data); return { input: { - domains: res.domains, + uploadCert: { + crt: data.crt, + key: data.key, + }, + domains: certReader.getAllDomains(), }, }; } diff --git a/packages/plugins/plugin-cert/src/plugin/index.ts b/packages/plugins/plugin-cert/src/plugin/index.ts index 4cf3f4aa..f563084c 100644 --- a/packages/plugins/plugin-cert/src/plugin/index.ts +++ b/packages/plugins/plugin-cert/src/plugin/index.ts @@ -1,3 +1,5 @@ +export { EVENT_CERT_APPLY_SUCCESS } from "./cert-plugin/base-convert.js"; + export * from "./cert-plugin/index.js"; export * from "./cert-plugin/lego/index.js"; export * from "./cert-plugin/custom/index.js"; diff --git a/packages/ui/certd-client/package.json b/packages/ui/certd-client/package.json index 2006cf96..7e5713b0 100644 --- a/packages/ui/certd-client/package.json +++ b/packages/ui/certd-client/package.json @@ -67,6 +67,7 @@ "lucide-vue-next": "^0.477.0", "mitt": "^3.0.1", "nanoid": "^4.0.0", + "node-forge": "^1.3.1", "nprogress": "^0.2.0", "object-assign": "^4.1.1", "pinia": "2.1.7", diff --git a/packages/ui/certd-client/src/components/plugins/index.ts b/packages/ui/certd-client/src/components/plugins/index.ts index edb9db49..aba2ab19 100644 --- a/packages/ui/certd-client/src/components/plugins/index.ts +++ b/packages/ui/certd-client/src/components/plugins/index.ts @@ -5,8 +5,8 @@ import OutputSelector from "/@/components/plugins/common/output-selector/index.v import DnsProviderSelector from "/@/components/plugins/cert/dns-provider-selector/index.vue"; import DomainsVerifyPlanEditor from "/@/components/plugins/cert/domains-verify-plan-editor/index.vue"; import AccessSelector from "/@/views/certd/access/access-selector/index.vue"; -import CertInfoUpdater from "/@/views/certd/monitor/cert/updater/index.vue"; import InputPassword from "./common/input-password.vue"; +import CertInfoUpdater from "/@/views/certd/pipeline/cert-upload/index.vue"; import ApiTest from "./common/api-test.vue"; export * from "./cert/index.js"; export default { diff --git a/packages/ui/certd-client/src/views/certd/monitor/cert/crud.tsx b/packages/ui/certd-client/src/views/certd/monitor/cert/crud.tsx index 3ed9e672..65dc4f9c 100644 --- a/packages/ui/certd-client/src/views/certd/monitor/cert/crud.tsx +++ b/packages/ui/certd-client/src/views/certd/monitor/cert/crud.tsx @@ -109,24 +109,23 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat }, copy: { show: false }, edit: { show: false }, - upload: { - show: compute(({ row }) => { - return row.fromType === "upload"; - }), - order: 4, - title: "更新证书", - type: "link", - icon: "ion:upload", - async click({ row }) { - await openUpdateCertDialog({ - id: row.id, - }); - }, - }, remove: { order: 10, show: false, }, + download: { + order: 9, + title: "下载证书", + type: "link", + icon: "ant-design:download-outlined", + async click({ row }) { + if (!row.certFile) { + notification.error({ message: "证书还未生成,请先运行流水线" }); + return; + } + window.open("/api/monitor/cert/download?id=" + row.id); + }, + }, }, }, columns: { diff --git a/packages/ui/certd-client/src/views/certd/monitor/cert/index.vue b/packages/ui/certd-client/src/views/certd/monitor/cert/index.vue index 7a4a9e34..ad696cb4 100644 --- a/packages/ui/certd-client/src/views/certd/monitor/cert/index.vue +++ b/packages/ui/certd-client/src/views/certd/monitor/cert/index.vue @@ -3,7 +3,7 @@ @@ -11,12 +11,12 @@