mirror of https://github.com/certd/certd
chore:
parent
656cb89fe8
commit
d558d50102
|
@ -1,5 +1,4 @@
|
||||||
import { CertInfo } from "../acme";
|
import { CertInfo } from "../acme";
|
||||||
|
|
||||||
export interface ICertApplyUploadService {
|
export interface ICertApplyUploadService {
|
||||||
getCertInfo: (opts: { certId: number; userId: number }) => Promise<any>;
|
getCertInfo: (opts: { certId: number; userId: number }) => Promise<any>;
|
||||||
updateCert: (opts: { certId: number; cert: CertInfo; userId: number }) => Promise<any>;
|
updateCert: (opts: { certId: number; cert: CertInfo; userId: number }) => Promise<any>;
|
||||||
|
|
|
@ -3,7 +3,6 @@ import type { CertInfo } from "../acme.js";
|
||||||
import { CertReader } from "../cert-reader.js";
|
import { CertReader } from "../cert-reader.js";
|
||||||
import { CertApplyBaseConvertPlugin } from "../base-convert.js";
|
import { CertApplyBaseConvertPlugin } from "../base-convert.js";
|
||||||
export * from "./d.js";
|
export * from "./d.js";
|
||||||
|
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import { ICertApplyUploadService } from "./d";
|
import { ICertApplyUploadService } from "./d";
|
||||||
export { CertReader };
|
export { CertReader };
|
||||||
|
@ -22,7 +21,7 @@ export type { CertInfo };
|
||||||
shortcut: {
|
shortcut: {
|
||||||
certUpdate: {
|
certUpdate: {
|
||||||
title: "更新证书",
|
title: "更新证书",
|
||||||
icon: "ph:upload",
|
icon: "ion:upload",
|
||||||
action: "onCertUpdate",
|
action: "onCertUpdate",
|
||||||
form: {
|
form: {
|
||||||
columns: {
|
columns: {
|
||||||
|
@ -65,20 +64,19 @@ export type { CertInfo };
|
||||||
})
|
})
|
||||||
export class CertApplyUploadPlugin extends CertApplyBaseConvertPlugin {
|
export class CertApplyUploadPlugin extends CertApplyBaseConvertPlugin {
|
||||||
@TaskInput({
|
@TaskInput({
|
||||||
title: "证书仓库ID",
|
title: "手动上传证书",
|
||||||
component: {
|
component: {
|
||||||
name: "cert-info-selector",
|
name: "cert-info-updater",
|
||||||
vModel: "modelValue",
|
vModel: "modelValue",
|
||||||
},
|
},
|
||||||
helper: "请不要随意修改",
|
helper: "手动上传证书",
|
||||||
order: -9999,
|
order: -9999,
|
||||||
required: true,
|
required: true,
|
||||||
mergeScript: `
|
mergeScript: `
|
||||||
return {
|
return {
|
||||||
component:{
|
component:{
|
||||||
on:{
|
on:{
|
||||||
selectedChange(scope){
|
updated(scope){
|
||||||
console.log(scope)
|
|
||||||
scope.form.input.domains = scope.$event?.domains
|
scope.form.input.domains = scope.$event?.domains
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -144,7 +142,7 @@ export class CertApplyUploadPlugin extends CertApplyBaseConvertPlugin {
|
||||||
async onCertUpdate(data: any) {
|
async onCertUpdate(data: any) {
|
||||||
const certApplyUploadService = await this.ctx.serviceGetter.get("CertApplyUploadService");
|
const certApplyUploadService = await this.ctx.serviceGetter.get("CertApplyUploadService");
|
||||||
|
|
||||||
await certApplyUploadService.updateCert({
|
const res = await certApplyUploadService.updateCert({
|
||||||
certId: this.certInfoId,
|
certId: this.certInfoId,
|
||||||
userId: this.ctx.user.id,
|
userId: this.ctx.user.id,
|
||||||
cert: {
|
cert: {
|
||||||
|
@ -152,6 +150,12 @@ export class CertApplyUploadPlugin extends CertApplyBaseConvertPlugin {
|
||||||
key: data.key,
|
key: data.key,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
input: {
|
||||||
|
domains: res.domains,
|
||||||
|
},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<AConfigProvider :locale="locale" :theme="tokenTheme">
|
<AConfigProvider :locale="locale" :theme="tokenTheme">
|
||||||
<contextHolder />
|
|
||||||
<fs-form-provider>
|
<fs-form-provider>
|
||||||
|
<contextHolder />
|
||||||
<router-view />
|
<router-view />
|
||||||
</fs-form-provider>
|
</fs-form-provider>
|
||||||
</AConfigProvider>
|
</AConfigProvider>
|
||||||
|
@ -21,7 +21,7 @@ import AConfigProvider from "ant-design-vue/es/config-provider";
|
||||||
import { Modal } from "ant-design-vue";
|
import { Modal } from "ant-design-vue";
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: "App"
|
name: "App",
|
||||||
});
|
});
|
||||||
const [modal, contextHolder] = Modal.useModal();
|
const [modal, contextHolder] = Modal.useModal();
|
||||||
provide("modal", modal);
|
provide("modal", modal);
|
||||||
|
@ -59,7 +59,7 @@ const tokenTheme = computed(() => {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
algorithm,
|
algorithm,
|
||||||
token: tokens
|
token: tokens,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
//其他初始化
|
//其他初始化
|
||||||
|
|
|
@ -5,7 +5,7 @@ import OutputSelector from "/@/components/plugins/common/output-selector/index.v
|
||||||
import DnsProviderSelector from "/@/components/plugins/cert/dns-provider-selector/index.vue";
|
import DnsProviderSelector from "/@/components/plugins/cert/dns-provider-selector/index.vue";
|
||||||
import DomainsVerifyPlanEditor from "/@/components/plugins/cert/domains-verify-plan-editor/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 AccessSelector from "/@/views/certd/access/access-selector/index.vue";
|
||||||
import CertInfoSelector from "/@/views/certd/monitor/cert/selector/index.vue";
|
import CertInfoUpdater from "/@/views/certd/monitor/cert/updater/index.vue";
|
||||||
import InputPassword from "./common/input-password.vue";
|
import InputPassword from "./common/input-password.vue";
|
||||||
import ApiTest from "./common/api-test.vue";
|
import ApiTest from "./common/api-test.vue";
|
||||||
export * from "./cert/index.js";
|
export * from "./cert/index.js";
|
||||||
|
@ -15,7 +15,7 @@ export default {
|
||||||
app.component("DnsProviderSelector", DnsProviderSelector);
|
app.component("DnsProviderSelector", DnsProviderSelector);
|
||||||
app.component("DomainsVerifyPlanEditor", DomainsVerifyPlanEditor);
|
app.component("DomainsVerifyPlanEditor", DomainsVerifyPlanEditor);
|
||||||
app.component("AccessSelector", AccessSelector);
|
app.component("AccessSelector", AccessSelector);
|
||||||
app.component("CertInfoSelector", CertInfoSelector);
|
app.component("CertInfoUpdater", CertInfoUpdater);
|
||||||
|
|
||||||
app.component("ApiTest", ApiTest);
|
app.component("ApiTest", ApiTest);
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ import { useRouter } from "vue-router";
|
||||||
import { useModal } from "/@/use/use-modal";
|
import { useModal } from "/@/use/use-modal";
|
||||||
import { notification } from "ant-design-vue";
|
import { notification } from "ant-design-vue";
|
||||||
import CertView from "/@/views/certd/pipeline/cert-view.vue";
|
import CertView from "/@/views/certd/pipeline/cert-view.vue";
|
||||||
|
import { useCertUpload } from "/@/views/certd/pipeline/cert-upload/use";
|
||||||
|
|
||||||
export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
|
export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
|
||||||
const api = certInfoApi;
|
const api = certInfoApi;
|
||||||
|
@ -51,69 +52,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
async function openUpload(id?: any) {
|
const { openUploadCreateDialog, openUpdateCertDialog } = useCertUpload();
|
||||||
function createCrudOptions() {
|
|
||||||
return {
|
|
||||||
crudOptions: {
|
|
||||||
request: {
|
|
||||||
// addRequest: async (form: any) => {
|
|
||||||
// return await api.Upload(form);
|
|
||||||
// },
|
|
||||||
// editRequest: async (form: any) => {
|
|
||||||
// return await api.Upload(form);
|
|
||||||
// }
|
|
||||||
},
|
|
||||||
columns: {
|
|
||||||
id: {
|
|
||||||
title: "ID",
|
|
||||||
type: "number",
|
|
||||||
form: {
|
|
||||||
show: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"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: "上传自定义证书",
|
|
||||||
},
|
|
||||||
async doSubmit({ form }: any) {
|
|
||||||
if (!id) {
|
|
||||||
delete form.id;
|
|
||||||
} else {
|
|
||||||
form.id = id;
|
|
||||||
}
|
|
||||||
return await api.Upload(form);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
const { crudOptions } = createCrudOptions();
|
|
||||||
const wrapperRef = await openCrudFormDialog({ crudOptions });
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
crudOptions: {
|
crudOptions: {
|
||||||
request: {
|
request: {
|
||||||
|
@ -145,7 +84,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||||
type: "primary",
|
type: "primary",
|
||||||
show: true,
|
show: true,
|
||||||
async click() {
|
async click() {
|
||||||
await openUpload();
|
await openUploadCreateDialog();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -179,7 +118,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||||
type: "link",
|
type: "link",
|
||||||
icon: "ph:upload",
|
icon: "ph:upload",
|
||||||
async click({ row }) {
|
async click({ row }) {
|
||||||
await openUpload(row.id);
|
await openUpdateCertDialog(row.id);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
remove: {
|
remove: {
|
||||||
|
|
|
@ -1,123 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="cert-info-selector w-full">
|
|
||||||
<div class="flex-o w-full">
|
|
||||||
<fs-table-select
|
|
||||||
ref="tableSelectRef"
|
|
||||||
class="flex-0"
|
|
||||||
:model-value="modelValue"
|
|
||||||
:dict="optionsDictRef"
|
|
||||||
:create-crud-options="createCrudOptions"
|
|
||||||
:crud-options-override="{
|
|
||||||
search: { show: false },
|
|
||||||
table: {
|
|
||||||
scroll: {
|
|
||||||
x: 540,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}"
|
|
||||||
:show-current="false"
|
|
||||||
:show-select="false"
|
|
||||||
:dialog="{ width: 960 }"
|
|
||||||
:destroy-on-close="false"
|
|
||||||
height="400px"
|
|
||||||
@update:model-value="onChange"
|
|
||||||
@dialog-closed="doRefresh"
|
|
||||||
@selected-change="onSelectedChange"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="tsx" setup>
|
|
||||||
import { inject, ref, Ref, watch } from "vue";
|
|
||||||
import { message } from "ant-design-vue";
|
|
||||||
import createCrudOptions from "../crud";
|
|
||||||
import { dict } from "@fast-crud/fast-crud";
|
|
||||||
import { certInfoApi } from "../api";
|
|
||||||
|
|
||||||
defineOptions({
|
|
||||||
name: "CertInfoSelector",
|
|
||||||
});
|
|
||||||
|
|
||||||
const props = defineProps<{
|
|
||||||
modelValue?: number | string;
|
|
||||||
type?: string;
|
|
||||||
placeholder?: string;
|
|
||||||
size?: string;
|
|
||||||
disabled?: boolean;
|
|
||||||
}>();
|
|
||||||
|
|
||||||
const onChange = async (value: number) => {
|
|
||||||
await emitValue(value);
|
|
||||||
};
|
|
||||||
|
|
||||||
const emit = defineEmits(["update:modelValue", "selectedChange", "change"]);
|
|
||||||
|
|
||||||
const tableSelectRef = ref();
|
|
||||||
|
|
||||||
const optionsDictRef = dict({
|
|
||||||
value: "id",
|
|
||||||
label: "domain",
|
|
||||||
getNodesByValues: async (values: any[]) => {
|
|
||||||
return await certInfoApi.GetOptionsByIds(values);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// async function openTableSelectDialog() {
|
|
||||||
// await tableSelectRef.value.open({});
|
|
||||||
// await tableSelectRef.value.crudExpose.openAdd({});
|
|
||||||
// }
|
|
||||||
|
|
||||||
const target: Ref<any> = ref({});
|
|
||||||
|
|
||||||
function clear() {
|
|
||||||
if (props.disabled) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
emitValue(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function emitValue(value: any) {
|
|
||||||
target.value = optionsDictRef.dataMap[value];
|
|
||||||
if (value !== 0 && pipeline?.value && target && pipeline.value.userId !== target.value.userId) {
|
|
||||||
message.error("对不起,您不能修改他人流水线的证书仓库ID");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
emit("change", value);
|
|
||||||
emit("update:modelValue", value);
|
|
||||||
}
|
|
||||||
|
|
||||||
function onSelectedChange(value: any) {
|
|
||||||
if (value && value.length > 0) {
|
|
||||||
emit("selectedChange", value[0]);
|
|
||||||
} else {
|
|
||||||
emit("selectedChange", null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// watch(
|
|
||||||
// () => {
|
|
||||||
// return props.modelValue;
|
|
||||||
// },
|
|
||||||
// async value => {
|
|
||||||
// await optionsDictRef.loadDict();
|
|
||||||
// target.value = optionsDictRef.dataMap[value];
|
|
||||||
// emit("selectedChange", target.value);
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// immediate: true,
|
|
||||||
// }
|
|
||||||
// );
|
|
||||||
|
|
||||||
//当不在pipeline中编辑时,可能为空
|
|
||||||
const pipeline = inject("pipeline", null);
|
|
||||||
|
|
||||||
async function doRefresh() {
|
|
||||||
await optionsDictRef.reloadDict();
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<style lang="less">
|
|
||||||
.cert-info-selector {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
<template>
|
||||||
|
<div class="cert-info-updater w-full flex items-center">
|
||||||
|
<div class="flex-o">
|
||||||
|
<fs-values-format :model-value="modelValue" :dict="certInfoDict" />
|
||||||
|
<fs-button v-if="modelValue" 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";
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: "CertInfoUpdater",
|
||||||
|
});
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
modelValue?: number | string;
|
||||||
|
type?: string;
|
||||||
|
placeholder?: string;
|
||||||
|
size?: string;
|
||||||
|
disabled?: boolean;
|
||||||
|
}>();
|
||||||
|
const emit = defineEmits(["updated"]);
|
||||||
|
|
||||||
|
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,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const { openUpdateCertDialog } = useCertUpload();
|
||||||
|
function onUpdated(res: any) {
|
||||||
|
emit("updated", res);
|
||||||
|
}
|
||||||
|
function onUploadClick() {
|
||||||
|
openUpdateCertDialog(props.modelValue, onUpdated);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="less">
|
||||||
|
.cert-info-selector {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -48,25 +48,6 @@ export function useCertUpload() {
|
||||||
}
|
}
|
||||||
return inputs;
|
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 <file-input class="mb-5" type="primary" text={"选择文件"} onChange={onChange} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function openUploadCreateDialog() {
|
async function openUploadCreateDialog() {
|
||||||
//检查是否流水线数量超出限制
|
//检查是否流水线数量超出限制
|
||||||
|
@ -87,32 +68,38 @@ export function useCertUpload() {
|
||||||
columns: {
|
columns: {
|
||||||
"cert.crt": {
|
"cert.crt": {
|
||||||
title: "证书",
|
title: "证书",
|
||||||
type: "textarea",
|
type: "text",
|
||||||
form: {
|
form: {
|
||||||
component: {
|
component: {
|
||||||
rows: 4,
|
name: "pem-input",
|
||||||
placeholder: "-----BEGIN CERTIFICATE-----\n...\n...\n-----END CERTIFICATE-----",
|
vModel: "modelValue",
|
||||||
|
textarea: {
|
||||||
|
rows: 4,
|
||||||
|
placeholder: "-----BEGIN CERTIFICATE-----\n...\n...\n-----END CERTIFICATE-----",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
helper: "选择pem格式证书文件,或者粘贴到此",
|
helper: "选择pem格式证书文件,或者粘贴到此",
|
||||||
rules: [{ required: true, message: "此项必填" }],
|
rules: [{ required: true, message: "此项必填" }],
|
||||||
col: { span: 24 },
|
col: { span: 24 },
|
||||||
order: -9999,
|
order: -9999,
|
||||||
topRender,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"cert.key": {
|
"cert.key": {
|
||||||
title: "证书私钥",
|
title: "证书私钥",
|
||||||
type: "textarea",
|
type: "text",
|
||||||
form: {
|
form: {
|
||||||
component: {
|
component: {
|
||||||
rows: 4,
|
name: "pem-input",
|
||||||
placeholder: "-----BEGIN PRIVATE KEY-----\n...\n...\n-----END PRIVATE KEY----- ",
|
vModel: "modelValue",
|
||||||
|
textarea: {
|
||||||
|
rows: 4,
|
||||||
|
placeholder: "-----BEGIN PRIVATE KEY-----\n...\n...\n-----END PRIVATE KEY----- ",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
helper: "选择pem格式证书私钥文件,或者粘贴到此",
|
helper: "选择pem格式证书私钥文件,或者粘贴到此",
|
||||||
rules: [{ required: true, message: "此项必填" }],
|
rules: [{ required: true, message: "此项必填" }],
|
||||||
col: { span: 24 },
|
col: { span: 24 },
|
||||||
order: -9999,
|
order: -9999,
|
||||||
topRender,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
...inputs,
|
...inputs,
|
||||||
|
@ -174,17 +161,22 @@ export function useCertUpload() {
|
||||||
wrapperRef.value = wrapper;
|
wrapperRef.value = wrapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function openUpdateCertDialog(id: any) {
|
async function openUpdateCertDialog(id: any, onSubmit?: any) {
|
||||||
function createCrudOptions() {
|
function createCrudOptions() {
|
||||||
return {
|
return {
|
||||||
crudOptions: {
|
crudOptions: {
|
||||||
columns: {
|
columns: {
|
||||||
"cert.crt": {
|
"cert.crt": {
|
||||||
title: "证书",
|
title: "证书",
|
||||||
type: "textarea",
|
type: "text",
|
||||||
form: {
|
form: {
|
||||||
component: {
|
component: {
|
||||||
rows: 4,
|
name: "pem-input",
|
||||||
|
vModel: "modelValue",
|
||||||
|
textarea: {
|
||||||
|
rows: 4,
|
||||||
|
placeholder: "-----BEGIN CERTIFICATE-----\n...\n...\n-----END CERTIFICATE-----",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
rules: [{ required: true, message: "此项必填" }],
|
rules: [{ required: true, message: "此项必填" }],
|
||||||
col: { span: 24 },
|
col: { span: 24 },
|
||||||
|
@ -195,7 +187,12 @@ export function useCertUpload() {
|
||||||
type: "textarea",
|
type: "textarea",
|
||||||
form: {
|
form: {
|
||||||
component: {
|
component: {
|
||||||
rows: 4,
|
name: "pem-input",
|
||||||
|
vModel: "modelValue",
|
||||||
|
textarea: {
|
||||||
|
rows: 4,
|
||||||
|
placeholder: "-----BEGIN PRIVATE KEY-----\n...\n...\n-----END PRIVATE KEY----- ",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
rules: [{ required: true, message: "此项必填" }],
|
rules: [{ required: true, message: "此项必填" }],
|
||||||
col: { span: 24 },
|
col: { span: 24 },
|
||||||
|
@ -212,7 +209,10 @@ export function useCertUpload() {
|
||||||
id: id,
|
id: id,
|
||||||
cert: form.cert,
|
cert: form.cert,
|
||||||
};
|
};
|
||||||
return await api.UploadCert(form);
|
const res = await api.UploadCert(req);
|
||||||
|
if (onSubmit) {
|
||||||
|
await onSubmit(res);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -7,10 +7,10 @@
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { doRequest } from "/@/components/plugins/lib";
|
import { doRequest } from "/@/components/plugins/lib";
|
||||||
import { ref, useAttrs } from "vue";
|
import { ref, useAttrs, inject } from "vue";
|
||||||
import { useFormWrapper } from "@fast-crud/fast-crud";
|
import { useFormWrapper } from "@fast-crud/fast-crud";
|
||||||
import { notification } from "ant-design-vue";
|
import { notification } from "ant-design-vue";
|
||||||
|
import { merge } from "lodash-es";
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: "TaskShortcut",
|
name: "TaskShortcut",
|
||||||
});
|
});
|
||||||
|
@ -32,7 +32,22 @@ async function openDialog() {
|
||||||
function createCrudOptions() {
|
function createCrudOptions() {
|
||||||
return {
|
return {
|
||||||
crudOptions: {
|
crudOptions: {
|
||||||
columns: props.form.columns,
|
columns: {
|
||||||
|
...props.form.columns,
|
||||||
|
immediateRun: {
|
||||||
|
title: "立即运行",
|
||||||
|
type: "switch",
|
||||||
|
span: 24,
|
||||||
|
form: {
|
||||||
|
value: true,
|
||||||
|
component: {
|
||||||
|
name: "a-switch",
|
||||||
|
vModel: "checked",
|
||||||
|
},
|
||||||
|
helper: "保存后是否立即触发运行流水线",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
form: {
|
form: {
|
||||||
wrapper: {
|
wrapper: {
|
||||||
title: props.title,
|
title: props.title,
|
||||||
|
@ -52,6 +67,7 @@ async function openDialog() {
|
||||||
await openCrudFormDialog({ crudOptions });
|
await openCrudFormDialog({ crudOptions });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getPipelineScope: any = inject("getPipelineScope");
|
||||||
const doPluginFormSubmit = async (formData: any) => {
|
const doPluginFormSubmit = async (formData: any) => {
|
||||||
if (loading.value) {
|
if (loading.value) {
|
||||||
return;
|
return;
|
||||||
|
@ -66,6 +82,27 @@ const doPluginFormSubmit = async (formData: any) => {
|
||||||
input: props.input,
|
input: props.input,
|
||||||
data: formData,
|
data: formData,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (res.input) {
|
||||||
|
const { save, findStep } = getPipelineScope();
|
||||||
|
const step = findStep(res.input);
|
||||||
|
if (step) {
|
||||||
|
// 数组覆盖合并
|
||||||
|
mergeWith(step.input, res.input, (objValue, srcValue) => {
|
||||||
|
if (isArray(objValue)) {
|
||||||
|
return srcValue;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
//保存,但不改变当前编辑状态
|
||||||
|
save(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (formData.immediateRun) {
|
||||||
|
const { run } = getPipelineScope();
|
||||||
|
run();
|
||||||
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
|
|
|
@ -647,31 +647,34 @@ export default defineComponent({
|
||||||
validateErrors.value[taskId] = errors;
|
validateErrors.value[taskId] = errors;
|
||||||
errors.push(error);
|
errors.push(error);
|
||||||
}
|
}
|
||||||
function doValidate() {
|
|
||||||
validateErrors.value = {};
|
|
||||||
|
|
||||||
const stepIds: string[] = [];
|
function eachSteps(pp: any, callback: any) {
|
||||||
//校验output id是否正确
|
if (pp.stages) {
|
||||||
const pp = pipeline.value;
|
for (const stage of pp.stages) {
|
||||||
function eachSteps(callback: any) {
|
if (stage.tasks) {
|
||||||
if (pp.stages) {
|
for (const task of stage.tasks) {
|
||||||
for (const stage of pp.stages) {
|
if (task.steps) {
|
||||||
if (stage.tasks) {
|
for (const step of task.steps) {
|
||||||
for (const task of stage.tasks) {
|
callback(step, task, stage);
|
||||||
if (task.steps) {
|
|
||||||
for (const step of task.steps) {
|
|
||||||
callback(step, task, stage);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function doValidate() {
|
||||||
|
validateErrors.value = {};
|
||||||
|
|
||||||
|
const stepIds: string[] = [];
|
||||||
|
//校验output id是否正确
|
||||||
|
const pp = pipeline.value;
|
||||||
|
|
||||||
//检查输出的stepid是否存在
|
//检查输出的stepid是否存在
|
||||||
let hasError = false;
|
let hasError = false;
|
||||||
let errorMessage = "";
|
let errorMessage = "";
|
||||||
eachSteps((step: any, task: any, stage: any) => {
|
eachSteps(pp, (step: any, task: any, stage: any) => {
|
||||||
stepIds.push(step.id);
|
stepIds.push(step.id);
|
||||||
if (step.input) {
|
if (step.input) {
|
||||||
for (const key in step.input) {
|
for (const key in step.input) {
|
||||||
|
@ -709,7 +712,7 @@ export default defineComponent({
|
||||||
function hasValidateError(taskId: string) {
|
function hasValidateError(taskId: string) {
|
||||||
return validateErrors.value[taskId] != null;
|
return validateErrors.value[taskId] != null;
|
||||||
}
|
}
|
||||||
const save = async () => {
|
const save = async (offEdit = true) => {
|
||||||
doValidate();
|
doValidate();
|
||||||
|
|
||||||
saveLoading.value = true;
|
saveLoading.value = true;
|
||||||
|
@ -728,7 +731,9 @@ export default defineComponent({
|
||||||
|
|
||||||
await props.options.doSave(pipeline.value);
|
await props.options.doSave(pipeline.value);
|
||||||
}
|
}
|
||||||
toggleEditMode(false);
|
if (offEdit) {
|
||||||
|
toggleEditMode(false);
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
saveLoading.value = false;
|
saveLoading.value = false;
|
||||||
}
|
}
|
||||||
|
@ -743,6 +748,17 @@ export default defineComponent({
|
||||||
toggleEditMode(false);
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
run,
|
run,
|
||||||
save,
|
save,
|
||||||
|
@ -750,6 +766,7 @@ export default defineComponent({
|
||||||
cancel,
|
cancel,
|
||||||
saveLoading,
|
saveLoading,
|
||||||
hasValidateError,
|
hasValidateError,
|
||||||
|
findStep,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -821,6 +838,17 @@ export default defineComponent({
|
||||||
const settingStore = useSettingStore();
|
const settingStore = useSettingStore();
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
|
|
||||||
|
const actions = useActions();
|
||||||
|
const trigger = useTrigger();
|
||||||
|
provide("getPipelineScope", () => {
|
||||||
|
return {
|
||||||
|
run: actions.run,
|
||||||
|
pipeline: pipeline,
|
||||||
|
save: actions.save,
|
||||||
|
findStep: actions.findStep,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
pipeline,
|
pipeline,
|
||||||
currentHistory,
|
currentHistory,
|
||||||
|
@ -830,8 +858,8 @@ export default defineComponent({
|
||||||
settingStore,
|
settingStore,
|
||||||
...useTaskRet,
|
...useTaskRet,
|
||||||
...useStageRet,
|
...useStageRet,
|
||||||
...useTrigger(),
|
...trigger,
|
||||||
...useActions(),
|
...actions,
|
||||||
...useHistory(),
|
...useHistory(),
|
||||||
...useNotification(),
|
...useNotification(),
|
||||||
...useScroll(),
|
...useScroll(),
|
||||||
|
|
|
@ -3,7 +3,6 @@ import { BaseService, CommonException } from "@certd/lib-server";
|
||||||
import { InjectEntityModel } from "@midwayjs/typeorm";
|
import { InjectEntityModel } from "@midwayjs/typeorm";
|
||||||
import { EntityManager, Repository } from "typeorm";
|
import { EntityManager, Repository } from "typeorm";
|
||||||
import { CertInfoEntity } from "../entity/cert-info.js";
|
import { CertInfoEntity } from "../entity/cert-info.js";
|
||||||
import { logger } from "@certd/basic";
|
|
||||||
import { CertInfo, CertReader } from "@certd/plugin-cert";
|
import { CertInfo, CertReader } from "@certd/plugin-cert";
|
||||||
import { PipelineService } from "../../pipeline/service/pipeline-service.js";
|
import { PipelineService } from "../../pipeline/service/pipeline-service.js";
|
||||||
import { CertInfoService } from "./cert-info-service.js";
|
import { CertInfoService } from "./cert-info-service.js";
|
||||||
|
@ -69,9 +68,12 @@ export class CertUploadService extends BaseService<CertInfoEntity> {
|
||||||
certReader: new CertReader(req.cert)
|
certReader: new CertReader(req.cert)
|
||||||
})
|
})
|
||||||
|
|
||||||
if (certInfoEntity.pipelineId) {
|
return {
|
||||||
logger.info( `触发流水线部署:${certInfoEntity.pipelineId}`)
|
id: certInfoEntity.id,
|
||||||
await this.pipelineService.trigger(certInfoEntity.pipelineId)
|
domains: certInfoEntity.domains.split(','),
|
||||||
|
pipelineId: certInfoEntity.pipelineId,
|
||||||
|
fromType: certInfoEntity.fromType,
|
||||||
|
updateTime: certInfoEntity.updateTime,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,7 +155,10 @@ export class CertUploadService extends BaseService<CertInfoEntity> {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id:newCertInfo.id,
|
id:newCertInfo.id,
|
||||||
pipelineId: newPipeline.id
|
pipelineId: newPipeline.id,
|
||||||
|
domains: newCertInfo.domains.split(','),
|
||||||
|
fromType: newCertInfo.fromType,
|
||||||
|
updateTime: newCertInfo.updateTime,
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
|
@ -9,7 +9,7 @@ export type DnslaRecord = {
|
||||||
// 这里通过IsDnsProvider注册一个dnsProvider
|
// 这里通过IsDnsProvider注册一个dnsProvider
|
||||||
@IsDnsProvider({
|
@IsDnsProvider({
|
||||||
name: 'dnsla',
|
name: 'dnsla',
|
||||||
title: 'dnsla',
|
title: 'dns.la',
|
||||||
desc: 'dns.la',
|
desc: 'dns.la',
|
||||||
icon: 'arcticons:dns-changer-3',
|
icon: 'arcticons:dns-changer-3',
|
||||||
// 这里是对应的 cloudflare的access类型名称
|
// 这里是对应的 cloudflare的access类型名称
|
||||||
|
@ -146,7 +146,7 @@ export class DnslaDnsProvider extends AbstractDnsProvider<DnslaRecord> {
|
||||||
type: 16,
|
type: 16,
|
||||||
host: fullRecord,
|
host: fullRecord,
|
||||||
data: value,
|
data: value,
|
||||||
ttl: 300,
|
ttl: 1,
|
||||||
});
|
});
|
||||||
|
|
||||||
return res.data;
|
return res.data;
|
||||||
|
|
Loading…
Reference in New Issue