diff --git a/packages/core/pipeline/src/decorator/utils.ts b/packages/core/pipeline/src/decorator/utils.ts index 38498845..9596bfb5 100644 --- a/packages/core/pipeline/src/decorator/utils.ts +++ b/packages/core/pipeline/src/decorator/utils.ts @@ -11,11 +11,13 @@ function attachProperty(target: any, propertyKey: string | symbol) { } function getClassProperties(target: any) { - //获取父类 + //获取父类, 向上追溯三层 const parent = Object.getPrototypeOf(target); + const pParent = Object.getPrototypeOf(parent); + const pParentMap = propertyMap[pParent] || {}; const parentMap = propertyMap[parent] || {}; const current = propertyMap[target] || {}; - return _.merge({}, parentMap, current); + return _.merge({}, pParentMap, parentMap, current); } function target(target: any, propertyKey?: string | symbol) { diff --git a/packages/libs/lib-server/src/basic/base-service.ts b/packages/libs/lib-server/src/basic/base-service.ts index 01e749c5..42cc9a99 100644 --- a/packages/libs/lib-server/src/basic/base-service.ts +++ b/packages/libs/lib-server/src/basic/base-service.ts @@ -30,7 +30,7 @@ export abstract class BaseService { async transaction(callback: (entityManager: EntityManager) => Promise) { const dataSource = this.dataSourceManager.getDataSource('default'); - await dataSource.transaction(callback as any); + return await dataSource.transaction(callback as any); } /** 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 04a21f00..36da600a 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 @@ -31,14 +31,14 @@ export abstract class CertApplyBaseConvertPlugin extends AbstractTaskPlugin { domains!: string[]; @TaskInput({ - title: "证书密码", + title: "证书加密密码", component: { name: "input-password", vModel: "value", }, required: false, order: 100, - helper: "PFX、jks格式证书是否加密\njks必须设置密码,不传则默认123456\npfx不传则为空密码", + helper: "转换成PFX、jks格式证书是否需要加密\njks必须设置密码,不传则默认123456\npfx不传则为空密码", }) pfxPassword!: string; 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 62b3c546..fa5be9a6 100644 --- a/packages/plugins/plugin-cert/src/plugin/cert-plugin/base.ts +++ b/packages/plugins/plugin-cert/src/plugin/cert-plugin/base.ts @@ -11,7 +11,6 @@ export async function emitCertApplySuccess(emitter: TaskEmitter, cert: CertReade } export abstract class CertApplyBasePlugin extends CertApplyBaseConvertPlugin { - @TaskInput({ title: "邮箱", component: { diff --git a/packages/ui/certd-client/src/components/file-input.vue b/packages/ui/certd-client/src/components/file-input.vue new file mode 100644 index 00000000..91e3edca --- /dev/null +++ b/packages/ui/certd-client/src/components/file-input.vue @@ -0,0 +1,27 @@ + + + diff --git a/packages/ui/certd-client/src/components/index.ts b/packages/ui/certd-client/src/components/index.ts index 9a075756..2954efe4 100644 --- a/packages/ui/certd-client/src/components/index.ts +++ b/packages/ui/certd-client/src/components/index.ts @@ -10,10 +10,12 @@ import Plugins from "./plugins/index"; import LoadingButton from "./loading-button.vue"; import IconSelect from "./icon-select.vue"; import ExpiresTimeText from "./expires-time-text.vue"; +import FileInput from "./file-input.vue"; export default { install(app: any) { app.component("PiContainer", PiContainer); app.component("TextEditable", TextEditable); + app.component("FileInput", FileInput); app.component("CronLight", CronLight); app.component("CronEditor", CronEditor); @@ -29,5 +31,5 @@ export default { app.component("ExpiresTimeText", ExpiresTimeText); app.use(vip); app.use(Plugins); - } + }, }; diff --git a/packages/ui/certd-client/src/views/certd/pipeline/api.plugin.ts b/packages/ui/certd-client/src/views/certd/pipeline/api.plugin.ts index 94127369..543d8677 100644 --- a/packages/ui/certd-client/src/views/certd/pipeline/api.plugin.ts +++ b/packages/ui/certd-client/src/views/certd/pipeline/api.plugin.ts @@ -6,8 +6,8 @@ const apiPrefix = "/pi/plugin"; const defaultInputDefine = { component: { name: "a-input", - vModel: "modelValue" - } + vModel: "modelValue", + }, }; function initPlugins(plugins: any) { @@ -35,7 +35,7 @@ export async function GetList(query: any) { const plugins = await request({ url: apiPrefix + "/list", method: "post", - params: query + params: query, }); initPlugins(plugins); return plugins; @@ -45,7 +45,7 @@ export async function GetGroups(query: any) { const groups = await request({ url: apiPrefix + "/groups", method: "post", - params: query + params: query, }); const plugins: any = []; for (const groupKey in groups) { @@ -60,8 +60,8 @@ export async function GetPluginDefine(type: string) { url: apiPrefix + "/getDefineByType", method: "post", data: { - type - } + type, + }, }); initPlugins([define]); return define; @@ -71,6 +71,6 @@ export async function GetPluginConfig(req: { id?: number; name: string; type: st return await request({ url: apiPrefix + "/config", method: "post", - data: req + data: req, }); } diff --git a/packages/ui/certd-client/src/views/certd/pipeline/cert-upload/api.ts b/packages/ui/certd-client/src/views/certd/pipeline/cert-upload/api.ts new file mode 100644 index 00000000..542359db --- /dev/null +++ b/packages/ui/certd-client/src/views/certd/pipeline/cert-upload/api.ts @@ -0,0 +1,10 @@ +import { request } from "/src/api/service"; + +const apiPrefix = "/monitor/cert"; +export async function UploadCert(body: { id?: number; cert: { crt: string; key: string }; pipeline?: any }) { + return await request({ + url: apiPrefix + "/upload", + method: "post", + data: body, + }); +} diff --git a/packages/ui/certd-client/src/views/certd/pipeline/cert-upload/use.tsx b/packages/ui/certd-client/src/views/certd/pipeline/cert-upload/use.tsx new file mode 100644 index 00000000..116a77cd --- /dev/null +++ b/packages/ui/certd-client/src/views/certd/pipeline/cert-upload/use.tsx @@ -0,0 +1,229 @@ +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 { 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 { useRouter } from "vue-router"; + +export function useCertUpload() { + const { openCrudFormDialog } = useFormWrapper(); + const router = useRouter(); + + 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") { + continue; + } + const inputDefine = cloneDeep(plugin.input[inputKey]); + useReference(inputDefine); + inputs[inputKey] = { + title: inputDefine.title, + form: { + ...inputDefine, + show: compute(ctx => { + const form = getFormData(); + if (!form) { + return false; + } + + let inputDefineShow = true; + if (inputDefine.show != null) { + const computeShow = inputDefine.show as any; + if (computeShow === false) { + inputDefineShow = false; + } else if (computeShow && computeShow.computeFn) { + inputDefineShow = computeShow.computeFn({ form }); + } + } + return inputDefineShow; + }), + }, + }; + } + return inputs; + } + function topRender({ form, key }: any) { + function onChange(e: any) { + const file = e.target.files[0]; + const size = file.size; + if (size > 100 * 1024) { + notification.error({ + message: "文件超过100k,请选择正确的证书文件", + }); + return; + } + const fileReader = new FileReader(); + fileReader.onload = function (e: any) { + const value = e.target.result; + set(form, key, value); + }; + fileReader.readAsText(file); // 以文本形式读取文件 + } + return ; + } + + async function openUploadCreateDialog() { + //检查是否流水线数量超出限制 + await checkPipelineLimit(); + + const wrapperRef = ref(); + function getFormData() { + if (!wrapperRef.value) { + return null; + } + return wrapperRef.value.getFormData(); + } + const inputs = await buildUploadCertPluginInputs(getFormData); + + function createCrudOptions() { + return { + crudOptions: { + columns: { + "cert.crt": { + title: "证书", + type: "textarea", + form: { + component: { + rows: 4, + placeholder: "-----BEGIN CERTIFICATE-----\n...\n...\n-----END CERTIFICATE-----", + }, + helper: "选择pem格式证书文件,或者粘贴到此", + rules: [{ required: true, message: "此项必填" }], + col: { span: 24 }, + order: -9999, + topRender, + }, + }, + "cert.key": { + title: "证书私钥", + type: "textarea", + form: { + component: { + rows: 4, + placeholder: "-----BEGIN PRIVATE KEY-----\n...\n...\n-----END PRIVATE KEY----- ", + }, + helper: "选择pem格式证书私钥文件,或者粘贴到此", + rules: [{ required: true, message: "此项必填" }], + col: { span: 24 }, + order: -9999, + topRender, + }, + }, + ...inputs, + notification: { + title: "失败通知", + type: "text", + form: { + value: 0, + component: { + name: NotificationSelector, + vModel: "modelValue", + on: { + selectedChange({ $event, form }: any) { + form.notificationTarget = $event; + }, + }, + }, + order: 101, + helper: "任务执行失败实时提醒", + }, + }, + }, + form: { + wrapper: { + title: "上传证书&创建部署流水线", + saveRemind: false, + }, + async doSubmit({ form }: any) { + const notifications = []; + if (form.notification != null) { + notifications.push({ + type: "custom", + when: ["error", "turnToSuccess", "success"], + notificationId: form.notification, + title: form.notificationTarget?.name || "自定义通知", + }); + } + + const req = { + id: form.id, + cert: form.cert, + pipeline: { + input: omit(form, ["id", "cert", "notification", "notificationTarget"]), + notifications, + }, + }; + const res = await api.UploadCert(req); + router.push({ + path: "/certd/pipeline/detail", + query: { id: res.pipelineId, editMode: "true" }, + }); + }, + }, + }, + }; + } + const { crudOptions } = createCrudOptions(); + const wrapper = await openCrudFormDialog({ crudOptions }); + wrapperRef.value = wrapper; + } + + async function openUpdateCertDialog(id: any) { + function createCrudOptions() { + return { + crudOptions: { + columns: { + "cert.crt": { + title: "证书", + type: "textarea", + form: { + component: { + rows: 4, + }, + rules: [{ required: true, message: "此项必填" }], + col: { span: 24 }, + }, + }, + "cert.key": { + title: "私钥", + type: "textarea", + form: { + component: { + rows: 4, + }, + rules: [{ required: true, message: "此项必填" }], + col: { span: 24 }, + }, + }, + }, + form: { + wrapper: { + title: "更新证书", + saveRemind: false, + }, + async doSubmit({ form }: any) { + const req = { + id: id, + cert: form.cert, + }; + return await api.UploadCert(form); + }, + }, + }, + }; + } + const { crudOptions } = createCrudOptions(); + await openCrudFormDialog({ crudOptions }); + } + + return { + openUploadCreateDialog, + openUpdateCertDialog, + }; +} diff --git a/packages/ui/certd-client/src/views/certd/pipeline/certd-form/crud.tsx b/packages/ui/certd-client/src/views/certd/pipeline/certd-form/crud.tsx index f1862539..e088bdd5 100644 --- a/packages/ui/certd-client/src/views/certd/pipeline/certd-form/crud.tsx +++ b/packages/ui/certd-client/src/views/certd/pipeline/certd-form/crud.tsx @@ -14,7 +14,7 @@ export default function (certPlugins: any[], formWrapperRef: any): CreateCrudOpt for (const plugin of certPlugins) { for (const inputKey in plugin.input) { if (inputs[inputKey]) { - inputs[inputKey].form.show = true; + // inputs[inputKey].form.show = true; continue; } const inputDefine = _.cloneDeep(plugin.input[inputKey]); diff --git a/packages/ui/certd-client/src/views/certd/pipeline/certd-form/dicts.ts b/packages/ui/certd-client/src/views/certd/pipeline/certd-form/dicts.ts index b29ada36..d135544b 100644 --- a/packages/ui/certd-client/src/views/certd/pipeline/certd-form/dicts.ts +++ b/packages/ui/certd-client/src/views/certd/pipeline/certd-form/dicts.ts @@ -4,11 +4,11 @@ export const Dicts = { sslProviderDict: dict({ data: [ { value: "letsencrypt", label: "Let‘s Encrypt" }, - { value: "zerossl", label: "ZeroSSL" } - ] + { value: "zerossl", label: "ZeroSSL" }, + ], }), challengeTypeDict: dict({ data: [{ value: "dns", label: "DNS校验" }] }), dnsProviderTypeDict: dict({ - url: "pi/dnsProvider/dnsProviderTypeDict" - }) + url: "pi/dnsProvider/dnsProviderTypeDict", + }), }; diff --git a/packages/ui/certd-client/src/views/certd/pipeline/certd-form/index.vue b/packages/ui/certd-client/src/views/certd/pipeline/certd-form/index.vue index 4057bf10..5ace5fc9 100644 --- a/packages/ui/certd-client/src/views/certd/pipeline/certd-form/index.vue +++ b/packages/ui/certd-client/src/views/certd/pipeline/certd-form/index.vue @@ -44,8 +44,8 @@ export default { const notificationApi = createNotificationApi(); await notificationApi.GetOrCreateDefault({ email: form.email }); } - } - } + }, + }, }) as any ); @@ -60,9 +60,9 @@ export default { return { formWrapperRef, open, - formWrapperOptions + formWrapperOptions, }; - } + }, }; diff --git a/packages/ui/certd-client/src/views/certd/pipeline/certd-form/use.ts b/packages/ui/certd-client/src/views/certd/pipeline/certd-form/use.ts new file mode 100644 index 00000000..ace5eace --- /dev/null +++ b/packages/ui/certd-client/src/views/certd/pipeline/certd-form/use.ts @@ -0,0 +1,126 @@ +import { checkPipelineLimit } from "/@/views/certd/pipeline/utils"; +import { omit } from "lodash-es"; +import * as api from "/@/views/certd/pipeline/api"; +import { message } from "ant-design-vue"; +import { nanoid } from "nanoid"; +import { useRouter } from "vue-router"; + +export function setRunnableIds(pipeline: any) { + const idMap: any = {}; + function createId(oldId: any) { + if (oldId == null) { + return nanoid(); + } + const newId = nanoid(); + idMap[oldId] = newId; + return newId; + } + if (pipeline.stages) { + for (const stage of pipeline.stages) { + stage.id = createId(stage.id); + if (stage.tasks) { + for (const task of stage.tasks) { + task.id = createId(task.id); + if (task.steps) { + for (const step of task.steps) { + step.id = createId(step.id); + } + } + } + } + } + } + + for (const trigger of pipeline.triggers) { + trigger.id = nanoid(); + } + for (const notification of pipeline.notifications) { + notification.id = nanoid(); + } + + let content = JSON.stringify(pipeline); + for (const key in idMap) { + content = content.replaceAll(key, idMap[key]); + } + return JSON.parse(content); +} + +export function useCertd(certdFormRef: any) { + const router = useRouter(); + async function openAddCertdPipelineDialog() { + //检查是否流水线数量超出限制 + await checkPipelineLimit(); + + certdFormRef.value.open(async ({ form }: any) => { + // 添加certd pipeline + const triggers = []; + if (form.triggerCron) { + triggers.push({ title: "定时触发", type: "timer", props: { cron: form.triggerCron } }); + } + const notifications = []; + if (form.notification != null) { + notifications.push({ + type: "custom", + when: ["error", "turnToSuccess", "success"], + notificationId: form.notification, + title: form.notificationTarget?.name || "自定义通知", + }); + } + const pluginInput = omit(form, ["triggerCron", "notification", "notificationTarget", "certApplyPlugin"]); + let pipeline = { + title: form.domains[0] + "证书自动化", + runnableType: "pipeline", + stages: [ + { + title: "证书申请阶段", + maxTaskCount: 1, + runnableType: "stage", + tasks: [ + { + title: "证书申请任务", + runnableType: "task", + steps: [ + { + title: "申请证书", + runnableType: "step", + input: { + renewDays: 35, + ...pluginInput, + }, + strategy: { + runStrategy: 0, // 正常执行 + }, + type: form.certApplyPlugin, + }, + ], + }, + ], + }, + ], + triggers, + notifications, + }; + pipeline = setRunnableIds(pipeline); + + /** + * // cert: 证书; backup: 备份; custom:自定义; + * type: string; + * // custom: 自定义; monitor: 监控; + * from: string; + */ + const id = await api.Save({ + title: pipeline.title, + content: JSON.stringify(pipeline), + keepHistoryCount: 30, + type: "cert", + from: "custom", + }); + message.success("创建成功,请添加证书部署任务"); + router.push({ path: "/certd/pipeline/detail", query: { id, editMode: "true" } }); + }); + } + + return { + openAddCertdPipelineDialog, + }; +} diff --git a/packages/ui/certd-client/src/views/certd/pipeline/crud.tsx b/packages/ui/certd-client/src/views/certd/pipeline/crud.tsx index a36f7b32..e0baa49e 100644 --- a/packages/ui/certd-client/src/views/certd/pipeline/crud.tsx +++ b/packages/ui/certd-client/src/views/certd/pipeline/crud.tsx @@ -4,62 +4,26 @@ import { computed, ref } from "vue"; import { useRouter } from "vue-router"; import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes, useUi } from "@fast-crud/fast-crud"; import { statusUtil } from "/@/views/certd/pipeline/pipeline/utils/util.status"; -import { nanoid } from "nanoid"; -import { message, Modal, notification } from "ant-design-vue"; +import { Modal, notification } from "ant-design-vue"; import { env } from "/@/utils/util.env"; import { useUserStore } from "/@/store/modules/user"; import dayjs from "dayjs"; import { useSettingStore } from "/@/store/modules/settings"; -import * as _ from "lodash-es"; +import { cloneDeep } from "lodash-es"; import { useModal } from "/@/use/use-modal"; import CertView from "./cert-view.vue"; import { eachStages } from "./utils"; -import { createNotificationApi as createNotificationApi } from "../notification/api"; -import { mySuiteApi } from "/@/views/certd/suite/mine/api"; +import { setRunnableIds, useCertd } from "/@/views/certd/pipeline/certd-form/use"; +import { useCertUpload } from "/@/views/certd/pipeline/cert-upload/use"; + export default function ({ crudExpose, context: { certdFormRef, groupDictRef, selectedRowKeys } }: CreateCrudOptionsProps): CreateCrudOptionsRet { const router = useRouter(); const { t } = useI18n(); const lastResRef = ref(); - function setRunnableIds(pipeline: any) { - const idMap: any = {}; - function createId(oldId: any) { - if (oldId == null) { - return nanoid(); - } - const newId = nanoid(); - idMap[oldId] = newId; - return newId; - } - if (pipeline.stages) { - for (const stage of pipeline.stages) { - stage.id = createId(stage.id); - if (stage.tasks) { - for (const task of stage.tasks) { - task.id = createId(task.id); - if (task.steps) { - for (const step of task.steps) { - step.id = createId(step.id); - } - } - } - } - } - } + const { openAddCertdPipelineDialog } = useCertd(certdFormRef); + const { openUploadCreateDialog } = useCertUpload(); - for (const trigger of pipeline.triggers) { - trigger.id = nanoid(); - } - for (const notification of pipeline.notifications) { - notification.id = nanoid(); - } - - let content = JSON.stringify(pipeline); - for (const key in idMap) { - content = content.replaceAll(key, idMap[key]); - } - return JSON.parse(content); - } const pageRequest = async (query: UserPageQuery): Promise => { return await api.GetList(query); }; @@ -96,90 +60,6 @@ export default function ({ crudExpose, context: { certdFormRef, groupDictRef, se return res; }; - const settingsStore = useSettingStore(); - async function addCertdPipeline() { - //检查是否流水线数量超出限制 - if (settingsStore.isComm && settingsStore.suiteSetting.enabled) { - //检查数量是否超限 - - const suiteDetail = await mySuiteApi.SuiteDetailGet(); - const max = suiteDetail.pipelineCount.max; - if (max != -1 && max <= suiteDetail.pipelineCount.used) { - notification.error({ - message: `对不起,您最多只能创建${max}条流水线,请购买或升级套餐`, - }); - return; - } - } - - certdFormRef.value.open(async ({ form }: any) => { - // 添加certd pipeline - const triggers = []; - if (form.triggerCron) { - triggers.push({ title: "定时触发", type: "timer", props: { cron: form.triggerCron } }); - } - const notifications = []; - if (form.notification != null) { - notifications.push({ - type: "custom", - when: ["error", "turnToSuccess", "success"], - notificationId: form.notification, - title: form.notificationTarget?.name || "自定义通知", - }); - } - let pipeline = { - title: form.domains[0] + "证书自动化", - runnableType: "pipeline", - stages: [ - { - title: "证书申请阶段", - maxTaskCount: 1, - runnableType: "stage", - tasks: [ - { - title: "证书申请任务", - runnableType: "task", - steps: [ - { - title: "申请证书", - runnableType: "step", - input: { - renewDays: 35, - ...form, - }, - strategy: { - runStrategy: 0, // 正常执行 - }, - type: form.certApplyPlugin, - }, - ], - }, - ], - }, - ], - triggers, - notifications, - }; - pipeline = setRunnableIds(pipeline); - - /** - * // cert: 证书; backup: 备份; custom:自定义; - * type: string; - * // custom: 自定义; monitor: 监控; - * from: string; - */ - const id = await api.Save({ - title: pipeline.title, - content: JSON.stringify(pipeline), - keepHistoryCount: 30, - type: "cert", - from: "custom", - }); - message.success("创建成功,请添加证书部署任务"); - router.push({ path: "/certd/pipeline/detail", query: { id, editMode: "true" } }); - }); - } - const model = useModal(); const viewCert = async (row: any) => { const cert = await api.GetCert(row.id); @@ -268,14 +148,25 @@ export default function ({ crudExpose, context: { certdFormRef, groupDictRef, se buttons: { add: { order: 5, + icon: "ion:ios-add-circle-outline", text: "自定义流水线", }, addCertd: { order: 1, text: "创建证书流水线", type: "primary", + icon: "ion:ios-add-circle-outline", click() { - addCertdPipeline(); + openAddCertdPipelineDialog(); + }, + }, + uploadCert: { + order: 2, + text: "上传证书部署", + type: "primary", + icon: "ion:cloud-upload-outline", + click() { + openUploadCreateDialog(); }, }, }, @@ -329,7 +220,7 @@ export default function ({ crudExpose, context: { certdFormRef, groupDictRef, se const { ui } = useUi(); // @ts-ignore let row = context[ui.tableColumn.row]; - row = _.cloneDeep(row); + row = cloneDeep(row); row.title = row.title + "_copy"; await crudExpose.openCopy({ row: row, diff --git a/packages/ui/certd-client/src/views/certd/pipeline/utils.ts b/packages/ui/certd-client/src/views/certd/pipeline/utils.ts index 6d0477f0..4422afee 100644 --- a/packages/ui/certd-client/src/views/certd/pipeline/utils.ts +++ b/packages/ui/certd-client/src/views/certd/pipeline/utils.ts @@ -1,10 +1,13 @@ 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"; export function eachStages(list: any[], exec: (item: any, runnableType: string) => void, runnableType: string = "stage") { if (!list || list.length <= 0) { return; } - forEach(list, (item) => { + forEach(list, item => { exec(item, runnableType); if (runnableType === "stage") { eachStages(item.tasks, exec, "task"); @@ -13,3 +16,19 @@ export function eachStages(list: any[], exec: (item: any, runnableType: string) } }); } + +export async function checkPipelineLimit() { + const settingsStore = useSettingStore(); + if (settingsStore.isComm && settingsStore.suiteSetting.enabled) { + //检查数量是否超限 + + const suiteDetail = await mySuiteApi.SuiteDetailGet(); + const max = suiteDetail.pipelineCount.max; + if (max != -1 && max <= suiteDetail.pipelineCount.used) { + notification.error({ + message: `对不起,您最多只能创建${max}条流水线,请购买或升级套餐`, + }); + throw new Error("流水线数量超限"); + } + } +} diff --git a/packages/ui/certd-server/src/controller/user/monitor/cert-info-controller.ts b/packages/ui/certd-server/src/controller/user/monitor/cert-info-controller.ts index 620b1268..86e55d98 100644 --- a/packages/ui/certd-server/src/controller/user/monitor/cert-info-controller.ts +++ b/packages/ui/certd-server/src/controller/user/monitor/cert-info-controller.ts @@ -121,6 +121,16 @@ export class CertInfoController extends CrudController { return this.ok(list); } + + + @Post('/getCert', { summary: Constants.per.authOnly }) + async getCert(@Query('id') id: number) { + await this.service.checkUserId(id, this.getUserId()); + const certInfoEntity = await this.service.info(id); + const certInfo = JSON.parse(certInfoEntity.certInfo); + return this.ok(certInfo); + } + @Post('/upload', { summary: Constants.per.authOnly }) async upload(@Body(ALL) body: {cert: CertInfo, pipeline: any, id?: number}) { if (body.id) { @@ -131,23 +141,16 @@ export class CertInfoController extends CrudController { userId: this.getUserId(), cert: body.cert, }); + return this.ok(); }else{ //添加 - await this.certUploadService.createUploadCertPipeline({ + const res = await this.certUploadService.createUploadCertPipeline({ userId: this.getUserId(), cert: body.cert, + pipeline: body.pipeline, }); - + return this.ok(res) } - return this.ok(); - } - - @Post('/getCert', { summary: Constants.per.authOnly }) - async getCert(@Query('id') id: number) { - await this.service.checkUserId(id, this.getUserId()); - const certInfoEntity = await this.service.info(id); - const certInfo = JSON.parse(certInfoEntity.certInfo); - return this.ok(certInfo); } } diff --git a/packages/ui/certd-server/src/modules/monitor/service/cert-upload-service.ts b/packages/ui/certd-server/src/modules/monitor/service/cert-upload-service.ts index f973abc8..4b242d7f 100644 --- a/packages/ui/certd-server/src/modules/monitor/service/cert-upload-service.ts +++ b/packages/ui/certd-server/src/modules/monitor/service/cert-upload-service.ts @@ -26,6 +26,10 @@ export type UpdateCertReq = { export type CreateUploadPipelineReq = { cert: CertInfo; userId: number; + pipeline?:{ + input?:any; + notifications?:any[] + } }; @Provide("CertUploadService") @@ -86,13 +90,16 @@ export class CertUploadService extends BaseService { }); const pipelineTitle = certReader.getAllDomains()[0] +"上传证书自动部署"; - const notifications = []; - notifications.push({ - type: "custom", - when: ["error", "turnToSuccess", "success"], - notificationId: 0, - title: "默认通知", - }); + 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", @@ -115,6 +122,7 @@ export class CertUploadService extends BaseService { input: { certInfoId: newCertInfo.id, domains: newCertInfo.domains.split(','), + ...body.pipeline?.input }, strategy: { runStrategy: 0, // 正常执行 @@ -144,7 +152,10 @@ export class CertUploadService extends BaseService { pipelineId: newPipeline.id }); - return newCertInfo.id + return { + id:newCertInfo.id, + pipelineId: newPipeline.id + } })