mirror of https://github.com/certd/certd
				
				
				
			perf: 手动上传证书部署流水线
							parent
							
								
									fedf90ea78
								
							
						
					
					
						commit
						fbb66f3c43
					
				| 
						 | 
				
			
			@ -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<void>;
 | 
			
		||||
 | 
			
		||||
  //必须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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +0,0 @@
 | 
			
		|||
import { CertInfo } from "../acme";
 | 
			
		||||
export interface ICertApplyUploadService {
 | 
			
		||||
  getCertInfo: (opts: { certId: number; userId: number }) => Promise<any>;
 | 
			
		||||
  updateCert: (opts: { certId: number; cert: CertInfo; userId: number }) => Promise<any>;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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<void> {}
 | 
			
		||||
 | 
			
		||||
  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,6 +113,9 @@ 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}天`);
 | 
			
		||||
 | 
			
		||||
    if (!this.ctx.inputChanged) {
 | 
			
		||||
      this.logger.info("输入参数无变化");
 | 
			
		||||
      const lastCrtMd5 = this.lastStatus?.status?.output?.certMd5;
 | 
			
		||||
      this.logger.info("证书MD5", crtMd5);
 | 
			
		||||
      this.logger.info("上次证书MD5", lastCrtMd5);
 | 
			
		||||
| 
						 | 
				
			
			@ -132,28 +127,29 @@ export class CertApplyUploadPlugin extends CertApplyBaseConvertPlugin {
 | 
			
		|||
        return "skip";
 | 
			
		||||
      }
 | 
			
		||||
      this.logger.info("证书有变化,重新部署");
 | 
			
		||||
    } else {
 | 
			
		||||
      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: {
 | 
			
		||||
    const certReader = new CertReader(data);
 | 
			
		||||
    return {
 | 
			
		||||
      input: {
 | 
			
		||||
        uploadCert: {
 | 
			
		||||
          crt: data.crt,
 | 
			
		||||
          key: data.key,
 | 
			
		||||
        },
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
      input: {
 | 
			
		||||
        domains: res.domains,
 | 
			
		||||
        domains: certReader.getAllDomains(),
 | 
			
		||||
      },
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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";
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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: {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
    <template #header>
 | 
			
		||||
      <div class="title">
 | 
			
		||||
        证书仓库
 | 
			
		||||
        <span class="sub">从流水线生成的证书,后续将支持手动上传证书并部署</span>
 | 
			
		||||
        <span class="sub">从流水线生成的证书</span>
 | 
			
		||||
      </div>
 | 
			
		||||
    </template>
 | 
			
		||||
    <fs-crud ref="crudRef" v-bind="crudBinding"> </fs-crud>
 | 
			
		||||
| 
						 | 
				
			
			@ -11,12 +11,12 @@
 | 
			
		|||
</template>
 | 
			
		||||
 | 
			
		||||
<script lang="ts" setup>
 | 
			
		||||
import { defineComponent, onActivated, onMounted } from "vue";
 | 
			
		||||
import { onActivated, onMounted } from "vue";
 | 
			
		||||
import { useFs } from "@fast-crud/fast-crud";
 | 
			
		||||
import createCrudOptions from "./crud";
 | 
			
		||||
import { createApi } from "./api";
 | 
			
		||||
 | 
			
		||||
defineOptions({
 | 
			
		||||
  name: "CertStore"
 | 
			
		||||
  name: "CertStore",
 | 
			
		||||
});
 | 
			
		||||
const { crudBinding, crudRef, crudExpose } = useFs({ createCrudOptions, context: {} });
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,7 +8,7 @@ export async function GetList(query: any) {
 | 
			
		|||
  return await request({
 | 
			
		||||
    url: apiPrefix + "/page",
 | 
			
		||||
    method: "post",
 | 
			
		||||
    data: query
 | 
			
		||||
    data: query,
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -16,7 +16,7 @@ export async function AddObj(obj: any) {
 | 
			
		|||
  return await request({
 | 
			
		||||
    url: apiPrefix + "/add",
 | 
			
		||||
    method: "post",
 | 
			
		||||
    data: obj
 | 
			
		||||
    data: obj,
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -24,7 +24,7 @@ export async function UpdateObj(obj: any) {
 | 
			
		|||
  return await request({
 | 
			
		||||
    url: apiPrefix + "/update",
 | 
			
		||||
    method: "post",
 | 
			
		||||
    data: obj
 | 
			
		||||
    data: obj,
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -32,7 +32,7 @@ export async function DelObj(id: any) {
 | 
			
		|||
  return await request({
 | 
			
		||||
    url: apiPrefix + "/delete",
 | 
			
		||||
    method: "post",
 | 
			
		||||
    params: { id }
 | 
			
		||||
    params: { id },
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -40,7 +40,7 @@ export async function GetObj(id: any) {
 | 
			
		|||
  return await request({
 | 
			
		||||
    url: apiPrefix + "/info",
 | 
			
		||||
    method: "post",
 | 
			
		||||
    params: { id }
 | 
			
		||||
    params: { id },
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -48,7 +48,7 @@ export async function GetDetail(id: any) {
 | 
			
		|||
  return await request({
 | 
			
		||||
    url: apiPrefix + "/detail",
 | 
			
		||||
    method: "post",
 | 
			
		||||
    params: { id }
 | 
			
		||||
    params: { id },
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -56,7 +56,7 @@ export async function Save(pipelineEntity: any) {
 | 
			
		|||
  return await request({
 | 
			
		||||
    url: apiPrefix + "/save",
 | 
			
		||||
    method: "post",
 | 
			
		||||
    data: pipelineEntity
 | 
			
		||||
    data: pipelineEntity,
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -64,7 +64,7 @@ export async function Trigger(id: any, stepId?: string) {
 | 
			
		|||
  return await request({
 | 
			
		||||
    url: apiPrefix + "/trigger",
 | 
			
		||||
    method: "post",
 | 
			
		||||
    params: { id, stepId }
 | 
			
		||||
    params: { id, stepId },
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -72,7 +72,7 @@ export async function Cancel(historyId: any) {
 | 
			
		|||
  return await request({
 | 
			
		||||
    url: apiPrefix + "/cancel",
 | 
			
		||||
    method: "post",
 | 
			
		||||
    params: { historyId }
 | 
			
		||||
    params: { historyId },
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -80,7 +80,7 @@ export async function BatchUpdateGroup(pipelineIds: number[], groupId: number):
 | 
			
		|||
  return await request({
 | 
			
		||||
    url: apiPrefix + "/batchUpdateGroup",
 | 
			
		||||
    method: "post",
 | 
			
		||||
    data: { ids: pipelineIds, groupId }
 | 
			
		||||
    data: { ids: pipelineIds, groupId },
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -88,7 +88,7 @@ export async function BatchDelete(pipelineIds: number[]): Promise<CertInfo> {
 | 
			
		|||
  return await request({
 | 
			
		||||
    url: apiPrefix + "/batchDelete",
 | 
			
		||||
    method: "post",
 | 
			
		||||
    data: { ids: pipelineIds }
 | 
			
		||||
    data: { ids: pipelineIds },
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -96,14 +96,14 @@ export async function GetFiles(pipelineId: number) {
 | 
			
		|||
  return await request({
 | 
			
		||||
    url: historyApiPrefix + "/files",
 | 
			
		||||
    method: "post",
 | 
			
		||||
    params: { pipelineId }
 | 
			
		||||
    params: { pipelineId },
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export async function GetCount() {
 | 
			
		||||
  return await request({
 | 
			
		||||
    url: apiPrefix + "/count",
 | 
			
		||||
    method: "post"
 | 
			
		||||
    method: "post",
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -119,6 +119,6 @@ export async function GetCert(pipelineId: number): Promise<CertInfo> {
 | 
			
		|||
  return await request({
 | 
			
		||||
    url: certApiPrefix + "/get",
 | 
			
		||||
    method: "post",
 | 
			
		||||
    params: { id: pipelineId }
 | 
			
		||||
    params: { id: pipelineId },
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,24 +1,23 @@
 | 
			
		|||
<template>
 | 
			
		||||
  <div class="cert-info-updater w-full flex items-center">
 | 
			
		||||
    <div class="flex-o">
 | 
			
		||||
      <fs-values-format :model-value="modelValue" :dict="certInfoDict" />
 | 
			
		||||
      <a-tag>{{ domain }}</a-tag>
 | 
			
		||||
      <fs-button type="primary" size="small" class="ml-1" icon="ion:upload" text="更新证书" @click="onUploadClick" />
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script lang="tsx" setup>
 | 
			
		||||
import { inject } from "vue";
 | 
			
		||||
import { dict } from "@fast-crud/fast-crud";
 | 
			
		||||
import { certInfoApi } from "../api";
 | 
			
		||||
import { useCertUpload } from "/@/views/certd/pipeline/cert-upload/use";
 | 
			
		||||
import { computed, inject } from "vue";
 | 
			
		||||
import { useCertUpload } from "./use";
 | 
			
		||||
import { getAllDomainsFromCrt } from "/@/views/certd/pipeline/utils";
 | 
			
		||||
 | 
			
		||||
defineOptions({
 | 
			
		||||
  name: "CertInfoUpdater",
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const props = defineProps<{
 | 
			
		||||
  modelValue?: number | string;
 | 
			
		||||
  modelValue?: { crt: string; key: string };
 | 
			
		||||
  type?: string;
 | 
			
		||||
  placeholder?: string;
 | 
			
		||||
  size?: string;
 | 
			
		||||
| 
						 | 
				
			
			@ -26,33 +25,28 @@ const props = defineProps<{
 | 
			
		|||
}>();
 | 
			
		||||
const emit = defineEmits(["updated", "update:modelValue"]);
 | 
			
		||||
 | 
			
		||||
const certInfoDict = dict({
 | 
			
		||||
  value: "id",
 | 
			
		||||
  label: "domain",
 | 
			
		||||
  getNodesByValues: async (values: any[]) => {
 | 
			
		||||
    const res = await certInfoApi.GetOptionsByIds(values);
 | 
			
		||||
    if (res.length > 0) {
 | 
			
		||||
      emit("updated", {
 | 
			
		||||
        domains: res[0].domains,
 | 
			
		||||
      });
 | 
			
		||||
const { openUpdateCertDialog } = useCertUpload();
 | 
			
		||||
 | 
			
		||||
const domain = computed(() => {
 | 
			
		||||
  if (!props.modelValue?.crt) {
 | 
			
		||||
    return "";
 | 
			
		||||
  }
 | 
			
		||||
    return res;
 | 
			
		||||
  },
 | 
			
		||||
  const domains = getAllDomainsFromCrt(props.modelValue?.crt);
 | 
			
		||||
 | 
			
		||||
  return domains[0];
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const { openUpdateCertDialog } = useCertUpload();
 | 
			
		||||
function onUpdated(res: any) {
 | 
			
		||||
  if (!props.modelValue) {
 | 
			
		||||
    emit("update:modelValue", res.id);
 | 
			
		||||
  }
 | 
			
		||||
  emit("updated", res);
 | 
			
		||||
function onUpdated(res: { uploadCert: any }) {
 | 
			
		||||
  debugger;
 | 
			
		||||
  emit("update:modelValue", res.uploadCert);
 | 
			
		||||
  const domains = getAllDomainsFromCrt(res.uploadCert.crt);
 | 
			
		||||
  emit("updated", { domains });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const pipeline: any = inject("pipeline");
 | 
			
		||||
function onUploadClick() {
 | 
			
		||||
  debugger;
 | 
			
		||||
  openUpdateCertDialog({
 | 
			
		||||
    id: props.modelValue,
 | 
			
		||||
    pipelineId: pipeline.id,
 | 
			
		||||
    onSubmit: onUpdated,
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,23 +1,62 @@
 | 
			
		|||
import { compute, useFormWrapper } from "@fast-crud/fast-crud";
 | 
			
		||||
import NotificationSelector from "/@/views/certd/notification/notification-selector/index.vue";
 | 
			
		||||
import * as api from "./api";
 | 
			
		||||
import { omit, cloneDeep, set } from "lodash-es";
 | 
			
		||||
import { cloneDeep, omit } from "lodash-es";
 | 
			
		||||
import { useReference } from "/@/use/use-refrence";
 | 
			
		||||
import { ref } from "vue";
 | 
			
		||||
import * as pluginApi from "../api.plugin";
 | 
			
		||||
import { checkPipelineLimit } from "/@/views/certd/pipeline/utils";
 | 
			
		||||
import { notification } from "ant-design-vue";
 | 
			
		||||
import * as api from "../api";
 | 
			
		||||
import { checkPipelineLimit, getAllDomainsFromCrt } from "/@/views/certd/pipeline/utils";
 | 
			
		||||
import { useRouter } from "vue-router";
 | 
			
		||||
import { nanoid } from "nanoid";
 | 
			
		||||
 | 
			
		||||
export function useCertUpload() {
 | 
			
		||||
  const { openCrudFormDialog } = useFormWrapper();
 | 
			
		||||
  const router = useRouter();
 | 
			
		||||
 | 
			
		||||
  const certInputs = {
 | 
			
		||||
    "uploadCert.crt": {
 | 
			
		||||
      title: "证书",
 | 
			
		||||
      type: "text",
 | 
			
		||||
      form: {
 | 
			
		||||
        component: {
 | 
			
		||||
          name: "pem-input",
 | 
			
		||||
          vModel: "modelValue",
 | 
			
		||||
          textarea: {
 | 
			
		||||
            rows: 4,
 | 
			
		||||
            placeholder: "-----BEGIN CERTIFICATE-----\n...\n...\n-----END CERTIFICATE-----",
 | 
			
		||||
          },
 | 
			
		||||
        },
 | 
			
		||||
        helper: "选择pem格式证书文件,或者粘贴到此",
 | 
			
		||||
        rules: [{ required: true, message: "此项必填" }],
 | 
			
		||||
        col: { span: 24 },
 | 
			
		||||
        order: -9999,
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
    "uploadCert.key": {
 | 
			
		||||
      title: "证书私钥",
 | 
			
		||||
      type: "text",
 | 
			
		||||
      form: {
 | 
			
		||||
        component: {
 | 
			
		||||
          name: "pem-input",
 | 
			
		||||
          vModel: "modelValue",
 | 
			
		||||
          textarea: {
 | 
			
		||||
            rows: 4,
 | 
			
		||||
            placeholder: "-----BEGIN PRIVATE KEY-----\n...\n...\n-----END PRIVATE KEY----- ",
 | 
			
		||||
          },
 | 
			
		||||
        },
 | 
			
		||||
        helper: "选择pem格式证书私钥文件,或者粘贴到此",
 | 
			
		||||
        rules: [{ required: true, message: "此项必填" }],
 | 
			
		||||
        col: { span: 24 },
 | 
			
		||||
        order: -9999,
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  async function buildUploadCertPluginInputs(getFormData: any) {
 | 
			
		||||
    const plugin: any = await pluginApi.GetPluginDefine("CertApplyUpload");
 | 
			
		||||
    const inputs: any = {};
 | 
			
		||||
    for (const inputKey in plugin.input) {
 | 
			
		||||
      if (inputKey === "certInfoId" || inputKey === "domains") {
 | 
			
		||||
      if (inputKey === "uploadCert" || inputKey === "domains") {
 | 
			
		||||
        continue;
 | 
			
		||||
      }
 | 
			
		||||
      const inputDefine = cloneDeep(plugin.input[inputKey]);
 | 
			
		||||
| 
						 | 
				
			
			@ -66,42 +105,7 @@ export function useCertUpload() {
 | 
			
		|||
      return {
 | 
			
		||||
        crudOptions: {
 | 
			
		||||
          columns: {
 | 
			
		||||
            "cert.crt": {
 | 
			
		||||
              title: "证书",
 | 
			
		||||
              type: "text",
 | 
			
		||||
              form: {
 | 
			
		||||
                component: {
 | 
			
		||||
                  name: "pem-input",
 | 
			
		||||
                  vModel: "modelValue",
 | 
			
		||||
                  textarea: {
 | 
			
		||||
                    rows: 4,
 | 
			
		||||
                    placeholder: "-----BEGIN CERTIFICATE-----\n...\n...\n-----END CERTIFICATE-----",
 | 
			
		||||
                  },
 | 
			
		||||
                },
 | 
			
		||||
                helper: "选择pem格式证书文件,或者粘贴到此",
 | 
			
		||||
                rules: [{ required: true, message: "此项必填" }],
 | 
			
		||||
                col: { span: 24 },
 | 
			
		||||
                order: -9999,
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
            "cert.key": {
 | 
			
		||||
              title: "证书私钥",
 | 
			
		||||
              type: "text",
 | 
			
		||||
              form: {
 | 
			
		||||
                component: {
 | 
			
		||||
                  name: "pem-input",
 | 
			
		||||
                  vModel: "modelValue",
 | 
			
		||||
                  textarea: {
 | 
			
		||||
                    rows: 4,
 | 
			
		||||
                    placeholder: "-----BEGIN PRIVATE KEY-----\n...\n...\n-----END PRIVATE KEY----- ",
 | 
			
		||||
                  },
 | 
			
		||||
                },
 | 
			
		||||
                helper: "选择pem格式证书私钥文件,或者粘贴到此",
 | 
			
		||||
                rules: [{ required: true, message: "此项必填" }],
 | 
			
		||||
                col: { span: 24 },
 | 
			
		||||
                order: -9999,
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
            ...cloneDeep(certInputs),
 | 
			
		||||
            ...inputs,
 | 
			
		||||
            notification: {
 | 
			
		||||
              title: "失败通知",
 | 
			
		||||
| 
						 | 
				
			
			@ -128,6 +132,9 @@ export function useCertUpload() {
 | 
			
		|||
              saveRemind: false,
 | 
			
		||||
            },
 | 
			
		||||
            async doSubmit({ form }: any) {
 | 
			
		||||
              const cert = form.uploadCert;
 | 
			
		||||
              const domains = getAllDomainsFromCrt(cert.crt);
 | 
			
		||||
 | 
			
		||||
              const notifications = [];
 | 
			
		||||
              if (form.notification != null) {
 | 
			
		||||
                notifications.push({
 | 
			
		||||
| 
						 | 
				
			
			@ -138,18 +145,54 @@ export function useCertUpload() {
 | 
			
		|||
                });
 | 
			
		||||
              }
 | 
			
		||||
 | 
			
		||||
              const req = {
 | 
			
		||||
                id: form.id,
 | 
			
		||||
                cert: form.cert,
 | 
			
		||||
                pipeline: {
 | 
			
		||||
                  input: omit(form, ["id", "cert", "notification", "notificationTarget"]),
 | 
			
		||||
                  notifications,
 | 
			
		||||
              const pipelineTitle = domains[0] + "上传证书部署";
 | 
			
		||||
              const input = omit(form, ["id", "cert", "notification", "notificationTarget"]);
 | 
			
		||||
              const pipeline = {
 | 
			
		||||
                title: pipelineTitle,
 | 
			
		||||
                runnableType: "pipeline",
 | 
			
		||||
                stages: [
 | 
			
		||||
                  {
 | 
			
		||||
                    id: nanoid(10),
 | 
			
		||||
                    title: "上传证书解析阶段",
 | 
			
		||||
                    maxTaskCount: 1,
 | 
			
		||||
                    runnableType: "stage",
 | 
			
		||||
                    tasks: [
 | 
			
		||||
                      {
 | 
			
		||||
                        id: nanoid(10),
 | 
			
		||||
                        title: "上传证书解析转换",
 | 
			
		||||
                        runnableType: "task",
 | 
			
		||||
                        steps: [
 | 
			
		||||
                          {
 | 
			
		||||
                            id: nanoid(10),
 | 
			
		||||
                            title: "上传证书解析转换",
 | 
			
		||||
                            runnableType: "step",
 | 
			
		||||
                            input: {
 | 
			
		||||
                              cert: cert,
 | 
			
		||||
                              domains: domains,
 | 
			
		||||
                              ...input,
 | 
			
		||||
                            },
 | 
			
		||||
                            strategy: {
 | 
			
		||||
                              runStrategy: 0, // 正常执行
 | 
			
		||||
                            },
 | 
			
		||||
                            type: "CertApplyUpload",
 | 
			
		||||
                          },
 | 
			
		||||
                        ],
 | 
			
		||||
                      },
 | 
			
		||||
                    ],
 | 
			
		||||
                  },
 | 
			
		||||
                ],
 | 
			
		||||
                notifications,
 | 
			
		||||
              };
 | 
			
		||||
              const res = await api.UploadCert(req);
 | 
			
		||||
 | 
			
		||||
              const id = await api.Save({
 | 
			
		||||
                title: pipeline.title,
 | 
			
		||||
                content: JSON.stringify(pipeline),
 | 
			
		||||
                keepHistoryCount: 30,
 | 
			
		||||
                type: "cert_upload",
 | 
			
		||||
              });
 | 
			
		||||
              router.push({
 | 
			
		||||
                path: "/certd/pipeline/detail",
 | 
			
		||||
                query: { id: res.pipelineId, editMode: "true" },
 | 
			
		||||
                query: { id: id, editMode: "true" },
 | 
			
		||||
              });
 | 
			
		||||
            },
 | 
			
		||||
          },
 | 
			
		||||
| 
						 | 
				
			
			@ -161,61 +204,22 @@ export function useCertUpload() {
 | 
			
		|||
    wrapperRef.value = wrapper;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async function openUpdateCertDialog(opts: { id?: any; onSubmit?: any; pipelineId?: any }) {
 | 
			
		||||
  async function openUpdateCertDialog(opts: { onSubmit?: any }) {
 | 
			
		||||
    function createCrudOptions() {
 | 
			
		||||
      return {
 | 
			
		||||
        crudOptions: {
 | 
			
		||||
          columns: {
 | 
			
		||||
            "cert.crt": {
 | 
			
		||||
              title: "证书",
 | 
			
		||||
              type: "text",
 | 
			
		||||
              form: {
 | 
			
		||||
                component: {
 | 
			
		||||
                  name: "pem-input",
 | 
			
		||||
                  vModel: "modelValue",
 | 
			
		||||
                  textarea: {
 | 
			
		||||
                    rows: 4,
 | 
			
		||||
                    placeholder: "-----BEGIN CERTIFICATE-----\n...\n...\n-----END CERTIFICATE-----",
 | 
			
		||||
                  },
 | 
			
		||||
                },
 | 
			
		||||
                rules: [{ required: true, message: "此项必填" }],
 | 
			
		||||
                col: { span: 24 },
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
            "cert.key": {
 | 
			
		||||
              title: "私钥",
 | 
			
		||||
              type: "textarea",
 | 
			
		||||
              form: {
 | 
			
		||||
                component: {
 | 
			
		||||
                  name: "pem-input",
 | 
			
		||||
                  vModel: "modelValue",
 | 
			
		||||
                  textarea: {
 | 
			
		||||
                    rows: 4,
 | 
			
		||||
                    placeholder: "-----BEGIN PRIVATE KEY-----\n...\n...\n-----END PRIVATE KEY----- ",
 | 
			
		||||
                  },
 | 
			
		||||
                },
 | 
			
		||||
                rules: [{ required: true, message: "此项必填" }],
 | 
			
		||||
                col: { span: 24 },
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
            ...cloneDeep(certInputs),
 | 
			
		||||
          },
 | 
			
		||||
          form: {
 | 
			
		||||
            wrapper: {
 | 
			
		||||
              title: "更新证书",
 | 
			
		||||
              title: "手动上传证书",
 | 
			
		||||
              saveRemind: false,
 | 
			
		||||
            },
 | 
			
		||||
            async afterSubmit() {
 | 
			
		||||
              notification.success({ message: "更新成功" });
 | 
			
		||||
            },
 | 
			
		||||
            async afterSubmit() {},
 | 
			
		||||
            async doSubmit({ form }: any) {
 | 
			
		||||
              const req = {
 | 
			
		||||
                id: opts.id,
 | 
			
		||||
                pipelineId: opts.pipelineId,
 | 
			
		||||
                cert: form.cert,
 | 
			
		||||
              };
 | 
			
		||||
              const res = await api.UploadCert(req);
 | 
			
		||||
              if (opts.onSubmit) {
 | 
			
		||||
                await opts.onSubmit(res);
 | 
			
		||||
                await opts.onSubmit(form);
 | 
			
		||||
              }
 | 
			
		||||
            },
 | 
			
		||||
          },
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
import { checkPipelineLimit } from "/@/views/certd/pipeline/utils";
 | 
			
		||||
import { checkPipelineLimit, readCertDetail } from "/@/views/certd/pipeline/utils";
 | 
			
		||||
import { omit } from "lodash-es";
 | 
			
		||||
import * as api from "/@/views/certd/pipeline/api";
 | 
			
		||||
import { message } from "ant-design-vue";
 | 
			
		||||
| 
						 | 
				
			
			@ -52,6 +52,7 @@ export function useCertd(certdFormRef: any) {
 | 
			
		|||
    await checkPipelineLimit();
 | 
			
		||||
 | 
			
		||||
    certdFormRef.value.open(async ({ form }: any) => {
 | 
			
		||||
      const certDetail = readCertDetail(form.cert.crt);
 | 
			
		||||
      // 添加certd pipeline
 | 
			
		||||
      const triggers = [];
 | 
			
		||||
      if (form.triggerCron) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,6 +22,7 @@ const props = defineProps<{
 | 
			
		|||
  form: any;
 | 
			
		||||
  input: any;
 | 
			
		||||
  pluginName: string;
 | 
			
		||||
  stepId: string;
 | 
			
		||||
}>();
 | 
			
		||||
 | 
			
		||||
const attrs = useAttrs();
 | 
			
		||||
| 
						 | 
				
			
			@ -85,7 +86,7 @@ const doPluginFormSubmit = async (formData: any) => {
 | 
			
		|||
 | 
			
		||||
    if (res.input) {
 | 
			
		||||
      const { save, findStep } = getPipelineScope();
 | 
			
		||||
      const step = findStep(res.input);
 | 
			
		||||
      const step = findStep(props.stepId);
 | 
			
		||||
      if (step) {
 | 
			
		||||
        // 数组覆盖合并
 | 
			
		||||
        mergeWith(step.input, res.input, (objValue, srcValue) => {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -41,6 +41,7 @@ async function init() {
 | 
			
		|||
          ...shortcut,
 | 
			
		||||
          pluginName: stepType,
 | 
			
		||||
          input: step.input,
 | 
			
		||||
          stepId: step.id,
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -104,7 +104,7 @@
 | 
			
		|||
                              </template>
 | 
			
		||||
                              <span class="flex-o w-100">
 | 
			
		||||
                                <span class="ellipsis flex-1 task-title" :class="{ 'in-edit': editMode, deleted: task.disabled }">{{ task.title }}</span>
 | 
			
		||||
                                <pi-status-show :status="task.status?.result"></pi-status-show>
 | 
			
		||||
                                <pi-status-show v-if="!editMode" :status="task.status?.result"></pi-status-show>
 | 
			
		||||
                              </span>
 | 
			
		||||
                            </a-popover>
 | 
			
		||||
                          </a-button>
 | 
			
		||||
| 
						 | 
				
			
			@ -273,6 +273,7 @@ import { FsIcon } from "@fast-crud/fast-crud";
 | 
			
		|||
import { useSettingStore } from "/@/store/modules/settings";
 | 
			
		||||
import { useUserStore } from "/@/store/modules/user";
 | 
			
		||||
import TaskShortcuts from "./component/shortcut/task-shortcuts.vue";
 | 
			
		||||
import { eachSteps, findStep } from "../utils";
 | 
			
		||||
export default defineComponent({
 | 
			
		||||
  name: "PipelineEdit",
 | 
			
		||||
  // eslint-disable-next-line vue/no-unused-components
 | 
			
		||||
| 
						 | 
				
			
			@ -648,22 +649,6 @@ export default defineComponent({
 | 
			
		|||
        errors.push(error);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      function eachSteps(pp: any, callback: any) {
 | 
			
		||||
        if (pp.stages) {
 | 
			
		||||
          for (const stage of pp.stages) {
 | 
			
		||||
            if (stage.tasks) {
 | 
			
		||||
              for (const task of stage.tasks) {
 | 
			
		||||
                if (task.steps) {
 | 
			
		||||
                  for (const step of task.steps) {
 | 
			
		||||
                    callback(step, task, stage);
 | 
			
		||||
                  }
 | 
			
		||||
                }
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      function doValidate() {
 | 
			
		||||
        validateErrors.value = {};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -748,15 +733,8 @@ export default defineComponent({
 | 
			
		|||
        toggleEditMode(false);
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      function findStep(id: string) {
 | 
			
		||||
        let found = null;
 | 
			
		||||
        const pp = pipeline.value;
 | 
			
		||||
        eachSteps(pp, (step: any, task: any, stage: any) => {
 | 
			
		||||
          if (step.id === id) {
 | 
			
		||||
            found = step;
 | 
			
		||||
          }
 | 
			
		||||
        });
 | 
			
		||||
        return found;
 | 
			
		||||
      function fundStepFromPipeline(id: string) {
 | 
			
		||||
        return findStep(pipeline.value, id);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return {
 | 
			
		||||
| 
						 | 
				
			
			@ -766,7 +744,7 @@ export default defineComponent({
 | 
			
		|||
        cancel,
 | 
			
		||||
        saveLoading,
 | 
			
		||||
        hasValidateError,
 | 
			
		||||
        findStep,
 | 
			
		||||
        findStep: fundStepFromPipeline,
 | 
			
		||||
      };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,7 +2,8 @@ import { forEach } from "lodash-es";
 | 
			
		|||
import { mySuiteApi } from "/@/views/certd/suite/mine/api";
 | 
			
		||||
import { notification } from "ant-design-vue";
 | 
			
		||||
import { useSettingStore } from "/@/store/modules/settings";
 | 
			
		||||
 | 
			
		||||
//@ts-ignore
 | 
			
		||||
import forge from "node-forge";
 | 
			
		||||
export function eachStages(list: any[], exec: (item: any, runnableType: string) => void, runnableType: string = "stage") {
 | 
			
		||||
  if (!list || list.length <= 0) {
 | 
			
		||||
    return;
 | 
			
		||||
| 
						 | 
				
			
			@ -17,6 +18,42 @@ export function eachStages(list: any[], exec: (item: any, runnableType: string)
 | 
			
		|||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function eachSteps(pipeline: any, callback: any) {
 | 
			
		||||
  const pp = pipeline;
 | 
			
		||||
  if (pp.stages) {
 | 
			
		||||
    for (const stage of pp.stages) {
 | 
			
		||||
      if (stage.tasks) {
 | 
			
		||||
        for (const task of stage.tasks) {
 | 
			
		||||
          if (task.steps) {
 | 
			
		||||
            for (const step of task.steps) {
 | 
			
		||||
              callback(step, task, stage);
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function findStep(pipeline: any, id: string) {
 | 
			
		||||
  const pp = pipeline;
 | 
			
		||||
  if (pp.stages) {
 | 
			
		||||
    for (const stage of pp.stages) {
 | 
			
		||||
      if (stage.tasks) {
 | 
			
		||||
        for (const task of stage.tasks) {
 | 
			
		||||
          if (task.steps) {
 | 
			
		||||
            for (const step of task.steps) {
 | 
			
		||||
              if (step.id === id) {
 | 
			
		||||
                return step;
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export async function checkPipelineLimit() {
 | 
			
		||||
  const settingsStore = useSettingStore();
 | 
			
		||||
  if (settingsStore.isComm && settingsStore.suiteSetting.enabled) {
 | 
			
		||||
| 
						 | 
				
			
			@ -32,3 +69,34 @@ export async function checkPipelineLimit() {
 | 
			
		|||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function readCertDetail(crt: string) {
 | 
			
		||||
  const detail = forge.pki.certificateFromPem(crt);
 | 
			
		||||
  const expires = detail.notAfter;
 | 
			
		||||
  return { detail, expires };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function getAllDomainsFromCrt(crt: string) {
 | 
			
		||||
  const { detail } = readCertDetail(crt);
 | 
			
		||||
  const domains = [];
 | 
			
		||||
 | 
			
		||||
  // 1. 提取SAN中的DNS名称
 | 
			
		||||
  const sanExtension = detail.extensions.find((ext: any) => ext.name === "subjectAltName");
 | 
			
		||||
  if (sanExtension) {
 | 
			
		||||
    sanExtension.altNames.forEach((altName: any) => {
 | 
			
		||||
      if (altName.type === 2) {
 | 
			
		||||
        // type=2 表示DNS名称
 | 
			
		||||
        domains.push(altName.value);
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // 2. 如果没有SAN,回退到CN(通用名称)
 | 
			
		||||
  if (domains.length === 0) {
 | 
			
		||||
    const cnAttr = detail.subject.attributes.find((attr: any) => attr.name === "commonName");
 | 
			
		||||
    if (cnAttr) {
 | 
			
		||||
      domains.push(cnAttr.value);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return domains;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,11 +1,11 @@
 | 
			
		|||
import { ALL, Body, Controller, Inject, Post, Provide, Query } from '@midwayjs/core';
 | 
			
		||||
import { Constants, CrudController } from '@certd/lib-server';
 | 
			
		||||
import { AuthService } from '../../../modules/sys/authority/service/auth-service.js';
 | 
			
		||||
import { CertInfoService } from '../../../modules/monitor/index.js';
 | 
			
		||||
import { PipelineService } from '../../../modules/pipeline/service/pipeline-service.js';
 | 
			
		||||
import { ALL, Body, Controller, Get, Inject, Post, Provide, Query } from "@midwayjs/core";
 | 
			
		||||
import { CommonException, Constants, CrudController } from "@certd/lib-server";
 | 
			
		||||
import { AuthService } from "../../../modules/sys/authority/service/auth-service.js";
 | 
			
		||||
import { CertInfoService } from "../../../modules/monitor/index.js";
 | 
			
		||||
import { PipelineService } from "../../../modules/pipeline/service/pipeline-service.js";
 | 
			
		||||
import { SelectQueryBuilder } from "typeorm";
 | 
			
		||||
import { CertUploadService } from "../../../modules/monitor/service/cert-upload-service.js";
 | 
			
		||||
import { CertInfo } from "@certd/plugin-cert";
 | 
			
		||||
import { logger } from "@certd/basic";
 | 
			
		||||
import fs from "fs";
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			@ -17,8 +17,6 @@ export class CertInfoController extends CrudController<CertInfoService> {
 | 
			
		|||
  @Inject()
 | 
			
		||||
  authService: AuthService;
 | 
			
		||||
  @Inject()
 | 
			
		||||
  certUploadService: CertUploadService;
 | 
			
		||||
  @Inject()
 | 
			
		||||
  pipelineService: PipelineService;
 | 
			
		||||
 | 
			
		||||
  getService(): CertInfoService {
 | 
			
		||||
| 
						 | 
				
			
			@ -131,26 +129,28 @@ export class CertInfoController extends CrudController<CertInfoService> {
 | 
			
		|||
    return this.ok(certInfo);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Post('/upload', { summary: Constants.per.authOnly })
 | 
			
		||||
  async upload(@Body(ALL) body: {cert: CertInfo, pipeline: any, id?: number}) {
 | 
			
		||||
    if (body.id) {
 | 
			
		||||
      //修改
 | 
			
		||||
      await this.service.checkUserId(body.id, this.getUserId());
 | 
			
		||||
      await this.certUploadService.updateCert({
 | 
			
		||||
        id: body.id,
 | 
			
		||||
        userId: this.getUserId(),
 | 
			
		||||
        cert: body.cert,
 | 
			
		||||
      });
 | 
			
		||||
      return this.ok();
 | 
			
		||||
    }else{
 | 
			
		||||
      //添加
 | 
			
		||||
     const res =  await this.certUploadService.createUploadCertPipeline({
 | 
			
		||||
        userId: this.getUserId(),
 | 
			
		||||
        cert: body.cert,
 | 
			
		||||
        pipeline: body.pipeline,
 | 
			
		||||
      });
 | 
			
		||||
      return this.ok(res)
 | 
			
		||||
  @Get('/download', { summary: Constants.per.authOnly })
 | 
			
		||||
  async download(@Query('id') id: number) {
 | 
			
		||||
    const certInfo = await this.service.info(id)
 | 
			
		||||
    if (certInfo == null) {
 | 
			
		||||
      throw new CommonException('file not found');
 | 
			
		||||
    }
 | 
			
		||||
    if (certInfo.userId !== this.getUserId()) {
 | 
			
		||||
      throw new CommonException('file not found');
 | 
			
		||||
    }
 | 
			
		||||
    // koa send file
 | 
			
		||||
    // 下载文件的名称
 | 
			
		||||
    // const filename = file.filename;
 | 
			
		||||
    // 要下载的文件的完整路径
 | 
			
		||||
    const path = certInfo.certFile;
 | 
			
		||||
    if (!path) {
 | 
			
		||||
      throw new CommonException('file not found');
 | 
			
		||||
    }
 | 
			
		||||
    logger.info(`download:${path}`);
 | 
			
		||||
    // 以流的形式下载文件
 | 
			
		||||
    this.ctx.attachment(path);
 | 
			
		||||
    this.ctx.set('Content-Type', 'application/octet-stream');
 | 
			
		||||
 | 
			
		||||
    return fs.createReadStream(path);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,7 +13,6 @@ import {
 | 
			
		|||
import {EmailService} from '../../../modules/basic/service/email-service.js';
 | 
			
		||||
import {http, HttpRequestConfig, logger, mergeUtils, utils} from '@certd/basic';
 | 
			
		||||
import {NotificationService} from '../../../modules/pipeline/service/notification-service.js';
 | 
			
		||||
import {CertApplyUploadService} from "../../../modules/pipeline/service/cert-apply-upload-service.js";
 | 
			
		||||
 | 
			
		||||
@Provide()
 | 
			
		||||
@Controller('/api/pi/handle')
 | 
			
		||||
| 
						 | 
				
			
			@ -24,8 +23,6 @@ export class HandleController extends BaseController {
 | 
			
		|||
  @Inject()
 | 
			
		||||
  emailService: EmailService;
 | 
			
		||||
 | 
			
		||||
  @Inject()
 | 
			
		||||
  certApplyUploadService: CertApplyUploadService;
 | 
			
		||||
 | 
			
		||||
  @Inject()
 | 
			
		||||
  notificationService: NotificationService;
 | 
			
		||||
| 
						 | 
				
			
			@ -97,7 +94,6 @@ export class HandleController extends BaseController {
 | 
			
		|||
    };
 | 
			
		||||
 | 
			
		||||
    const serviceContainer:any = {
 | 
			
		||||
      CertApplyUploadService:this.certApplyUploadService
 | 
			
		||||
    }
 | 
			
		||||
    const serviceGetter =  {
 | 
			
		||||
      get:(name: string) => {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,8 +1,8 @@
 | 
			
		|||
import { Autoload, Init, Inject, Scope, ScopeEnum } from '@midwayjs/core';
 | 
			
		||||
import { CertInfoService } from '../monitor/index.js';
 | 
			
		||||
import { pipelineEmitter } from '@certd/pipeline';
 | 
			
		||||
import { CertReader, EVENT_CERT_APPLY_SUCCESS } from '@certd/plugin-cert';
 | 
			
		||||
import { PipelineEvent } from '@certd/pipeline/dist/service/emit.js';
 | 
			
		||||
import { Autoload, Init, Inject, Scope, ScopeEnum } from "@midwayjs/core";
 | 
			
		||||
import { CertInfoService } from "../monitor/index.js";
 | 
			
		||||
import { pipelineEmitter } from "@certd/pipeline";
 | 
			
		||||
import { CertInfo, EVENT_CERT_APPLY_SUCCESS } from "@certd/plugin-cert";
 | 
			
		||||
import { PipelineEvent } from "@certd/pipeline/dist/service/emit.js";
 | 
			
		||||
 | 
			
		||||
@Autoload()
 | 
			
		||||
@Scope(ScopeEnum.Request, { allowDowngrade: true })
 | 
			
		||||
| 
						 | 
				
			
			@ -15,8 +15,8 @@ export class AutoEPipelineEmitterRegister {
 | 
			
		|||
    await this.onCertApplySuccess();
 | 
			
		||||
  }
 | 
			
		||||
  async onCertApplySuccess() {
 | 
			
		||||
    pipelineEmitter.on(EVENT_CERT_APPLY_SUCCESS, async (event: PipelineEvent<CertReader>) => {
 | 
			
		||||
      await this.certInfoService.updateCertByPipelineId(event.pipeline.id, event.event);
 | 
			
		||||
    pipelineEmitter.on(EVENT_CERT_APPLY_SUCCESS, async (event: PipelineEvent<{cert:CertInfo,file:string}>) => {
 | 
			
		||||
      await this.certInfoService.updateCertByPipelineId(event.pipeline.id, event.event.cert, event.event.file);
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,6 +11,7 @@ export type UploadCertReq = {
 | 
			
		|||
  certReader: CertReader;
 | 
			
		||||
  fromType?: string;
 | 
			
		||||
  userId?: number;
 | 
			
		||||
  file?:any
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -38,7 +39,7 @@ export class CertInfoService extends BaseService<CertInfoEntity> {
 | 
			
		|||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async updateDomains(pipelineId: number, userId: number, domains: string[]) {
 | 
			
		||||
  async updateDomains(pipelineId: number, userId: number, domains: string[],fromType?:string) {
 | 
			
		||||
    const found = await this.repository.findOne({
 | 
			
		||||
      where: {
 | 
			
		||||
        pipelineId,
 | 
			
		||||
| 
						 | 
				
			
			@ -53,6 +54,7 @@ export class CertInfoService extends BaseService<CertInfoEntity> {
 | 
			
		|||
      //create
 | 
			
		||||
      bean.pipelineId = pipelineId;
 | 
			
		||||
      bean.userId = userId;
 | 
			
		||||
      bean.fromType = fromType
 | 
			
		||||
      if (!domains || domains.length === 0) {
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
| 
						 | 
				
			
			@ -133,7 +135,7 @@ export class CertInfoService extends BaseService<CertInfoEntity> {
 | 
			
		|||
    return certReader.toCertInfo();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async updateCertByPipelineId(pipelineId: number, certReader: CertReader, fromType = 'pipeline') {
 | 
			
		||||
  async updateCertByPipelineId(pipelineId: number, cert: CertInfo,file?:string,fromType = 'pipeline') {
 | 
			
		||||
    const found = await this.repository.findOne({
 | 
			
		||||
      where: {
 | 
			
		||||
        pipelineId,
 | 
			
		||||
| 
						 | 
				
			
			@ -141,8 +143,9 @@ export class CertInfoService extends BaseService<CertInfoEntity> {
 | 
			
		|||
    });
 | 
			
		||||
    const bean = await this.updateCert({
 | 
			
		||||
      id: found?.id,
 | 
			
		||||
      certReader,
 | 
			
		||||
      certReader: new CertReader(cert),
 | 
			
		||||
      fromType,
 | 
			
		||||
      file
 | 
			
		||||
    });
 | 
			
		||||
    return bean;
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -165,6 +168,9 @@ export class CertInfoService extends BaseService<CertInfoEntity> {
 | 
			
		|||
    bean.expiresTime = certReader.expires;
 | 
			
		||||
    bean.certProvider = certReader.detail.issuer.commonName;
 | 
			
		||||
    bean.userId = userId
 | 
			
		||||
    if(req.file){
 | 
			
		||||
      bean.certFile = req.file
 | 
			
		||||
    }
 | 
			
		||||
    await this.addOrUpdate(bean);
 | 
			
		||||
    return bean;
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,203 +0,0 @@
 | 
			
		|||
import { Inject, Provide, Scope, ScopeEnum } from "@midwayjs/core";
 | 
			
		||||
import { BaseService, CommonException } from "@certd/lib-server";
 | 
			
		||||
import { InjectEntityModel } from "@midwayjs/typeorm";
 | 
			
		||||
import { EntityManager, Repository } from "typeorm";
 | 
			
		||||
import { CertInfoEntity } from "../entity/cert-info.js";
 | 
			
		||||
import { CertInfo, CertReader } from "@certd/plugin-cert";
 | 
			
		||||
import { PipelineService } from "../../pipeline/service/pipeline-service.js";
 | 
			
		||||
import { CertInfoService } from "./cert-info-service.js";
 | 
			
		||||
import { PipelineEntity } from "../../pipeline/entity/pipeline.js";
 | 
			
		||||
import { nanoid } from "nanoid";
 | 
			
		||||
 | 
			
		||||
export type UploadCertReq = {
 | 
			
		||||
  id?: number;
 | 
			
		||||
  certReader: CertReader;
 | 
			
		||||
  fromType?: string;
 | 
			
		||||
  userId?: number;
 | 
			
		||||
  pipelineId?: number;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export type UpdateCertReq = {
 | 
			
		||||
  id: number;
 | 
			
		||||
  cert: CertInfo;
 | 
			
		||||
  userId?: number;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export type CreateUploadPipelineReq = {
 | 
			
		||||
  cert: CertInfo;
 | 
			
		||||
  userId: number;
 | 
			
		||||
  pipelineId?: number;
 | 
			
		||||
  pipeline?:{
 | 
			
		||||
    input?:any;
 | 
			
		||||
    notifications?:any[]
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@Provide("CertUploadService")
 | 
			
		||||
@Scope(ScopeEnum.Request, { allowDowngrade: true })
 | 
			
		||||
export class CertUploadService extends BaseService<CertInfoEntity> {
 | 
			
		||||
  @InjectEntityModel(CertInfoEntity)
 | 
			
		||||
  repository: Repository<CertInfoEntity>;
 | 
			
		||||
 | 
			
		||||
  @Inject()
 | 
			
		||||
  pipelineService: PipelineService;
 | 
			
		||||
  @Inject()
 | 
			
		||||
  certInfoService: CertInfoService;
 | 
			
		||||
 | 
			
		||||
  //@ts-ignore
 | 
			
		||||
  getRepository() {
 | 
			
		||||
    return this.repository;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * 更新证书,触发流水线
 | 
			
		||||
   * @param req
 | 
			
		||||
   */
 | 
			
		||||
  async updateCert(req: UpdateCertReq) {
 | 
			
		||||
 | 
			
		||||
    const certInfoEntity = await this.certInfoService.info(req.id);
 | 
			
		||||
    if (!certInfoEntity) {
 | 
			
		||||
      throw new CommonException("cert not found");
 | 
			
		||||
    }
 | 
			
		||||
    if(certInfoEntity.fromType !== 'upload') {
 | 
			
		||||
      throw new CommonException("cert can't be custom upload");
 | 
			
		||||
    }
 | 
			
		||||
    await this.uploadCert(this.repository.manager,{
 | 
			
		||||
      id: req.id,
 | 
			
		||||
      fromType: 'upload',
 | 
			
		||||
      userId: req.userId,
 | 
			
		||||
      certReader: new CertReader(req.cert)
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
      id: certInfoEntity.id,
 | 
			
		||||
      domains: certInfoEntity.domains.split(','),
 | 
			
		||||
      pipelineId: certInfoEntity.pipelineId,
 | 
			
		||||
      fromType: certInfoEntity.fromType,
 | 
			
		||||
      updateTime: certInfoEntity.updateTime,
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async createUploadCertPipeline(body:CreateUploadPipelineReq) {
 | 
			
		||||
    const {  userId, cert  } = body;
 | 
			
		||||
 | 
			
		||||
    if (!cert) {
 | 
			
		||||
      throw new CommonException("cert can't be empty");
 | 
			
		||||
    }
 | 
			
		||||
    const certReader =  new CertReader(cert)
 | 
			
		||||
    return await this.transaction(async (tx:EntityManager)=>{
 | 
			
		||||
      let pipelineId = body.pipelineId;
 | 
			
		||||
      const newCertInfo = await this.uploadCert(tx,{
 | 
			
		||||
        certReader: certReader,
 | 
			
		||||
        fromType: 'upload',
 | 
			
		||||
        userId,
 | 
			
		||||
        pipelineId
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      if(!pipelineId){
 | 
			
		||||
        const pipelineTitle = certReader.getAllDomains()[0] +"上传证书自动部署";
 | 
			
		||||
        const notifications = body.pipeline?.notifications ||[];
 | 
			
		||||
        if(notifications.length === 0){
 | 
			
		||||
          notifications.push({
 | 
			
		||||
            type: "custom",
 | 
			
		||||
            when: ["error", "turnToSuccess", "success"],
 | 
			
		||||
            notificationId: 0,
 | 
			
		||||
            title: "默认通知",
 | 
			
		||||
          });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let pipeline = {
 | 
			
		||||
          title: pipelineTitle,
 | 
			
		||||
          runnableType: "pipeline",
 | 
			
		||||
          stages: [
 | 
			
		||||
            {
 | 
			
		||||
              id: nanoid(10),
 | 
			
		||||
              title: "上传证书解析阶段",
 | 
			
		||||
              maxTaskCount: 1,
 | 
			
		||||
              runnableType: "stage",
 | 
			
		||||
              tasks: [
 | 
			
		||||
                {
 | 
			
		||||
                  id: nanoid(10),
 | 
			
		||||
                  title: "上传证书解析转换",
 | 
			
		||||
                  runnableType: "task",
 | 
			
		||||
                  steps: [
 | 
			
		||||
                    {
 | 
			
		||||
                      id: nanoid(10),
 | 
			
		||||
                      title: "上传证书解析转换",
 | 
			
		||||
                      runnableType: "step",
 | 
			
		||||
                      input: {
 | 
			
		||||
                        certInfoId: newCertInfo.id,
 | 
			
		||||
                        domains: newCertInfo.domains.split(','),
 | 
			
		||||
                        ...body.pipeline?.input
 | 
			
		||||
                      },
 | 
			
		||||
                      strategy: {
 | 
			
		||||
                        runStrategy: 0, // 正常执行
 | 
			
		||||
                      },
 | 
			
		||||
                      type: "CertApplyUpload",
 | 
			
		||||
                    },
 | 
			
		||||
                  ],
 | 
			
		||||
                },
 | 
			
		||||
              ],
 | 
			
		||||
            },
 | 
			
		||||
          ],
 | 
			
		||||
          triggers:[],
 | 
			
		||||
          notifications,
 | 
			
		||||
        }
 | 
			
		||||
        const newPipeline = await tx.getRepository(PipelineEntity).save({
 | 
			
		||||
          userId,
 | 
			
		||||
          title: pipelineTitle,
 | 
			
		||||
          type:"cert_upload",
 | 
			
		||||
          content: JSON.stringify(pipeline),
 | 
			
		||||
          keepHistory:20,
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
        newCertInfo.pipelineId = newPipeline.id;
 | 
			
		||||
        await tx.getRepository(CertInfoEntity).save({
 | 
			
		||||
          id: newCertInfo.id,
 | 
			
		||||
          pipelineId: newPipeline.id
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        pipelineId = newPipeline.id;
 | 
			
		||||
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return {
 | 
			
		||||
        id:newCertInfo.id,
 | 
			
		||||
        pipelineId: pipelineId,
 | 
			
		||||
        domains: newCertInfo.domains.split(','),
 | 
			
		||||
        fromType: newCertInfo.fromType,
 | 
			
		||||
        updateTime: newCertInfo.updateTime,
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private async uploadCert(tx:EntityManager,req: UploadCertReq) {
 | 
			
		||||
    const bean = new CertInfoEntity();
 | 
			
		||||
    const { id, fromType,userId, certReader } = req;
 | 
			
		||||
    if (id) {
 | 
			
		||||
      bean.id = id;
 | 
			
		||||
    } else {
 | 
			
		||||
      bean.fromType = fromType;
 | 
			
		||||
      bean.userId = userId
 | 
			
		||||
    }
 | 
			
		||||
    const certInfo = certReader.toCertInfo();
 | 
			
		||||
    bean.certInfo = JSON.stringify(certInfo);
 | 
			
		||||
    bean.applyTime = new Date().getTime();
 | 
			
		||||
    const domains = certReader.detail.domains.altNames;
 | 
			
		||||
    bean.domains = domains.join(',');
 | 
			
		||||
    bean.domain = domains[0];
 | 
			
		||||
    bean.domainCount = domains.length;
 | 
			
		||||
    bean.expiresTime = certReader.expires;
 | 
			
		||||
    bean.certProvider = certReader.detail.issuer.commonName;
 | 
			
		||||
    if (req.pipelineId){
 | 
			
		||||
      bean.pipelineId = req.pipelineId;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    await tx.getRepository(CertInfoEntity).save(bean);
 | 
			
		||||
    return bean;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,28 +0,0 @@
 | 
			
		|||
import {ICertApplyUploadService} from "@certd/plugin-cert";
 | 
			
		||||
import {IMidwayContext, Inject, Provide} from "@midwayjs/core";
 | 
			
		||||
import {CertInfoService} from "../../monitor/index.js";
 | 
			
		||||
import {CertUploadService} from "../../monitor/service/cert-upload-service.js";
 | 
			
		||||
 | 
			
		||||
@Provide("CertApplyUploadService")
 | 
			
		||||
export class CertApplyUploadService implements ICertApplyUploadService {
 | 
			
		||||
  @Inject()
 | 
			
		||||
  ctx : IMidwayContext
 | 
			
		||||
 | 
			
		||||
  async getCertInfo(opts: { certId: number; userId: number; })  {
 | 
			
		||||
    const certInfoService = this.ctx.getApp().getApplicationContext().get<CertInfoService>("CertInfoService")
 | 
			
		||||
    const { certId, userId } = opts;
 | 
			
		||||
    return await certInfoService.getCertInfo({
 | 
			
		||||
      certId,
 | 
			
		||||
      userId: Number(userId),
 | 
			
		||||
    });
 | 
			
		||||
  };
 | 
			
		||||
  async updateCert(opts: { certId: any; userId: any; cert: any; }){
 | 
			
		||||
    const certUploadService =  this.ctx.getApp().getApplicationContext().get<CertUploadService>("CertUploadService")
 | 
			
		||||
    return await certUploadService.updateCert({
 | 
			
		||||
      id:opts.certId,
 | 
			
		||||
      userId:opts.userId,
 | 
			
		||||
      cert:opts.cert
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -36,7 +36,6 @@ import { NotificationService } from "./notification-service.js";
 | 
			
		|||
import { NotificationGetter } from "./notification-getter.js";
 | 
			
		||||
import { UserSuiteEntity, UserSuiteService } from "@certd/commercial-core";
 | 
			
		||||
import { CertInfoService } from "../../monitor/service/cert-info-service.js";
 | 
			
		||||
import {CertApplyUploadService} from "./cert-apply-upload-service.js";
 | 
			
		||||
 | 
			
		||||
const runningTasks: Map<string | number, Executor> = new Map();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -93,8 +92,6 @@ export class PipelineService extends BaseService<PipelineEntity> {
 | 
			
		|||
  @Inject()
 | 
			
		||||
  certInfoService: CertInfoService;
 | 
			
		||||
 | 
			
		||||
  @Inject()
 | 
			
		||||
  certApplyUploadService: CertApplyUploadService;
 | 
			
		||||
  //@ts-ignore
 | 
			
		||||
  getRepository() {
 | 
			
		||||
    return this.repository;
 | 
			
		||||
| 
						 | 
				
			
			@ -196,10 +193,11 @@ export class PipelineService extends BaseService<PipelineEntity> {
 | 
			
		|||
    await this.registerTriggerById(bean.id);
 | 
			
		||||
 | 
			
		||||
    //保存域名信息到certInfo表
 | 
			
		||||
    if(bean.from !== 'cert_upload'){
 | 
			
		||||
      await this.certInfoService.updateDomains(pipeline.id, pipeline.userId || bean.userId, domains);
 | 
			
		||||
    let fromType = 'pipeline';
 | 
			
		||||
    if(bean.type === 'cert_upload') {
 | 
			
		||||
      fromType = 'upload';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    await this.certInfoService.updateDomains(pipeline.id, pipeline.userId || bean.userId, domains,fromType);
 | 
			
		||||
    return bean;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -483,9 +481,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
 | 
			
		|||
      const siteInfo = await this.sysSettingsService.getSetting<SysSiteInfo>(SysSiteInfo);
 | 
			
		||||
      sysInfo.title = siteInfo.title;
 | 
			
		||||
    }
 | 
			
		||||
    const serviceContainer = {
 | 
			
		||||
      CertApplyUploadService: this.certApplyUploadService
 | 
			
		||||
    }
 | 
			
		||||
    const serviceContainer = {}
 | 
			
		||||
    const serviceGetter = {
 | 
			
		||||
      get:(name: string) => {
 | 
			
		||||
        return serviceContainer[name]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1072,6 +1072,9 @@ importers:
 | 
			
		|||
      cropperjs:
 | 
			
		||||
        specifier: ^1.6.1
 | 
			
		||||
        version: 1.6.2
 | 
			
		||||
      crypto-js:
 | 
			
		||||
        specifier: ^4.2.0
 | 
			
		||||
        version: 4.2.0
 | 
			
		||||
      cssnano:
 | 
			
		||||
        specifier: ^7.0.6
 | 
			
		||||
        version: 7.0.6(postcss@8.5.3)
 | 
			
		||||
| 
						 | 
				
			
			@ -1102,6 +1105,9 @@ importers:
 | 
			
		|||
      nanoid:
 | 
			
		||||
        specifier: ^4.0.0
 | 
			
		||||
        version: 4.0.2
 | 
			
		||||
      node-forge:
 | 
			
		||||
        specifier: ^1.3.1
 | 
			
		||||
        version: 1.3.1
 | 
			
		||||
      nprogress:
 | 
			
		||||
        specifier: ^0.2.0
 | 
			
		||||
        version: 0.2.0
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue