mirror of https://github.com/certd/certd
perf: EAB授权支持绑定邮箱,支持公共EAB设置
parent
e8b617b80c
commit
07043aff0c
|
@ -217,6 +217,8 @@ export class Executor {
|
||||||
const instance: ITaskPlugin = new plugin.target();
|
const instance: ITaskPlugin = new plugin.target();
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const define: PluginDefine = plugin.define;
|
const define: PluginDefine = plugin.define;
|
||||||
|
const pluginName = define.name;
|
||||||
|
const pluginConfig = await this.options.pluginConfigService.getPluginConfig(pluginName);
|
||||||
//从outputContext读取输入参数
|
//从outputContext读取输入参数
|
||||||
const input = cloneDeep(step.input);
|
const input = cloneDeep(step.input);
|
||||||
Decorator.inject(define.input, instance, input, (item, key) => {
|
Decorator.inject(define.input, instance, input, (item, key) => {
|
||||||
|
@ -238,6 +240,12 @@ export class Executor {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const sysInput = pluginConfig.sysSetting?.input || {};
|
||||||
|
//注入系统设置参数
|
||||||
|
for (const sysInputKey in sysInput) {
|
||||||
|
input[sysInputKey] = sysInput[sysInputKey];
|
||||||
|
}
|
||||||
|
|
||||||
const newInputHash = hashUtils.md5(JSON.stringify(input));
|
const newInputHash = hashUtils.md5(JSON.stringify(input));
|
||||||
step.status!.inputHash = newInputHash;
|
step.status!.inputHash = newInputHash;
|
||||||
//判断是否需要跳过
|
//判断是否需要跳过
|
||||||
|
|
|
@ -26,7 +26,10 @@ export type TaskOutputDefine = {
|
||||||
type?: string;
|
type?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TaskInputDefine = FormItemProps;
|
export type TaskInputDefine = {
|
||||||
|
required?: boolean;
|
||||||
|
isSys?: boolean;
|
||||||
|
} & FormItemProps;
|
||||||
|
|
||||||
export type PluginDefine = Registrable & {
|
export type PluginDefine = Registrable & {
|
||||||
default?: any;
|
default?: any;
|
||||||
|
|
|
@ -2,11 +2,11 @@ export type PluginConfig = {
|
||||||
name: string;
|
name: string;
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
sysSetting: {
|
sysSetting: {
|
||||||
[key: string]: any;
|
input: Record<string, any>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
//插件配置服务
|
//插件配置服务
|
||||||
export type IPluginConfigService = {
|
export type IPluginConfigService = {
|
||||||
getPluginConfig: (pluginName: string) => Promise<any>;
|
getPluginConfig: (pluginName: string) => Promise<PluginConfig>;
|
||||||
};
|
};
|
||||||
|
|
|
@ -167,7 +167,7 @@ export abstract class BaseService<T> {
|
||||||
index++;
|
index++;
|
||||||
});
|
});
|
||||||
if (index > 0) {
|
if (index > 0) {
|
||||||
qb.where(whereSql, query);
|
qb.andWhere(whereSql, query);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//自定义query
|
//自定义query
|
||||||
|
|
|
@ -26,6 +26,16 @@ export class EabAccess extends BaseAccess {
|
||||||
encrypt: true,
|
encrypt: true,
|
||||||
})
|
})
|
||||||
hmacKey = "";
|
hmacKey = "";
|
||||||
|
|
||||||
|
@AccessInput({
|
||||||
|
title: "email",
|
||||||
|
component: {
|
||||||
|
placeholder: "绑定一个邮箱",
|
||||||
|
},
|
||||||
|
helper: "Google EAB 申请证书绑定邮箱后,不能更换,否则会导致EAB失效",
|
||||||
|
required: false,
|
||||||
|
})
|
||||||
|
email = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
new EabAccess();
|
new EabAccess();
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { createDnsProvider, DnsProviderContext, IDnsProvider } from "../../dns-p
|
||||||
import { CertReader } from "./cert-reader.js";
|
import { CertReader } from "./cert-reader.js";
|
||||||
import { CertApplyBasePlugin } from "./base.js";
|
import { CertApplyBasePlugin } from "./base.js";
|
||||||
import { GoogleClient } from "../../libs/google.js";
|
import { GoogleClient } from "../../libs/google.js";
|
||||||
|
import { EabAccess } from "../../access";
|
||||||
|
|
||||||
export type { CertInfo };
|
export type { CertInfo };
|
||||||
export * from "./cert-reader.js";
|
export * from "./cert-reader.js";
|
||||||
|
@ -138,6 +139,13 @@ export class CertApplyPlugin extends CertApplyBasePlugin {
|
||||||
})
|
})
|
||||||
sslProvider!: SSLProvider;
|
sslProvider!: SSLProvider;
|
||||||
|
|
||||||
|
@TaskInput({
|
||||||
|
title: "Google公共EAB授权",
|
||||||
|
isSys: true,
|
||||||
|
show: false,
|
||||||
|
})
|
||||||
|
googleCommonEabAccessId!: number;
|
||||||
|
|
||||||
@TaskInput({
|
@TaskInput({
|
||||||
title: "EAB授权",
|
title: "EAB授权",
|
||||||
component: {
|
component: {
|
||||||
|
@ -151,7 +159,7 @@ export class CertApplyPlugin extends CertApplyBasePlugin {
|
||||||
mergeScript: `
|
mergeScript: `
|
||||||
return {
|
return {
|
||||||
show: ctx.compute(({form})=>{
|
show: ctx.compute(({form})=>{
|
||||||
return form.sslProvider === 'zerossl' || form.sslProvider === 'google'
|
return form.sslProvider === 'zerossl' || (form.sslProvider === 'google' && !form.googleCommonEabAccessId)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
|
@ -171,7 +179,7 @@ export class CertApplyPlugin extends CertApplyBasePlugin {
|
||||||
mergeScript: `
|
mergeScript: `
|
||||||
return {
|
return {
|
||||||
show: ctx.compute(({form})=>{
|
show: ctx.compute(({form})=>{
|
||||||
return form.sslProvider === 'google'
|
return form.sslProvider === 'google' && !form.googleCommonEabAccessId
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
|
@ -233,10 +241,12 @@ export class CertApplyPlugin extends CertApplyBasePlugin {
|
||||||
|
|
||||||
acme!: AcmeService;
|
acme!: AcmeService;
|
||||||
|
|
||||||
|
eab!: EabAccess;
|
||||||
async onInit() {
|
async onInit() {
|
||||||
let eab: any = null;
|
let eab: EabAccess = null;
|
||||||
|
|
||||||
if (this.sslProvider === "google") {
|
if (this.sslProvider === "google") {
|
||||||
|
const eabAccessId = this.eabAccessId || this.googleCommonEabAccessId;
|
||||||
if (this.googleAccessId) {
|
if (this.googleAccessId) {
|
||||||
this.logger.info("您正在使用google服务账号授权");
|
this.logger.info("您正在使用google服务账号授权");
|
||||||
const googleAccess = await this.ctx.accessService.getById(this.googleAccessId);
|
const googleAccess = await this.ctx.accessService.getById(this.googleAccessId);
|
||||||
|
@ -245,9 +255,9 @@ export class CertApplyPlugin extends CertApplyBasePlugin {
|
||||||
logger: this.logger,
|
logger: this.logger,
|
||||||
});
|
});
|
||||||
eab = await googleClient.getEab();
|
eab = await googleClient.getEab();
|
||||||
} else if (this.eabAccessId) {
|
} else if (eabAccessId) {
|
||||||
this.logger.info("您正在使用google EAB授权");
|
this.logger.info("您正在使用google EAB授权");
|
||||||
eab = await this.ctx.accessService.getById(this.eabAccessId);
|
eab = await this.ctx.accessService.getById(eabAccessId);
|
||||||
} else {
|
} else {
|
||||||
this.logger.error("google需要配置EAB授权或服务账号授权");
|
this.logger.error("google需要配置EAB授权或服务账号授权");
|
||||||
return;
|
return;
|
||||||
|
@ -260,7 +270,7 @@ export class CertApplyPlugin extends CertApplyBasePlugin {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this.eab = eab;
|
||||||
this.acme = new AcmeService({
|
this.acme = new AcmeService({
|
||||||
userContext: this.userContext,
|
userContext: this.userContext,
|
||||||
logger: this.logger,
|
logger: this.logger,
|
||||||
|
@ -276,7 +286,10 @@ export class CertApplyPlugin extends CertApplyBasePlugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
async doCertApply() {
|
async doCertApply() {
|
||||||
const email = this["email"];
|
let email = this.email;
|
||||||
|
if (this.eab && this.eab.email) {
|
||||||
|
email = this.eab.email;
|
||||||
|
}
|
||||||
const domains = this["domains"];
|
const domains = this["domains"];
|
||||||
|
|
||||||
const csrInfo = _.merge(
|
const csrInfo = _.merge(
|
||||||
|
|
|
@ -96,6 +96,20 @@ export const sysResources = [
|
||||||
permission: "sys:settings:view"
|
permission: "sys:settings:view"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: "证书插件配置",
|
||||||
|
name: "SysPluginConfig",
|
||||||
|
path: "/sys/plugin/config",
|
||||||
|
component: "/sys/plugin/config.vue",
|
||||||
|
meta: {
|
||||||
|
show: () => {
|
||||||
|
const settingStore = useSettingStore();
|
||||||
|
return settingStore.isComm;
|
||||||
|
},
|
||||||
|
icon: "ion:extension-puzzle-outline",
|
||||||
|
permission: "sys:settings:view"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: "账号绑定",
|
title: "账号绑定",
|
||||||
name: "AccountBind",
|
name: "AccountBind",
|
||||||
|
|
|
@ -222,3 +222,8 @@ h1, h2, h3, h4, h5, h6 {
|
||||||
/* right: 0; */
|
/* right: 0; */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.settings-form {
|
||||||
|
width: 800px;
|
||||||
|
margin: 20px;
|
||||||
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
import { getCommonColumnDefine } from "/@/views/certd/access/common";
|
import { getCommonColumnDefine } from "/@/views/certd/access/common";
|
||||||
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
|
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
|
||||||
|
|
||||||
export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
|
export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
|
||||||
const { crudBinding } = crudExpose;
|
const { crudBinding } = crudExpose;
|
||||||
const { props, ctx } = context;
|
const { props, ctx, api } = context;
|
||||||
const lastResRef = ref();
|
const lastResRef = ref();
|
||||||
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
|
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
|
||||||
return await context.api.GetList(query);
|
return await context.api.GetList(query);
|
||||||
|
@ -108,6 +108,33 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||||
width: 200
|
width: 200
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
from: {
|
||||||
|
title: "级别",
|
||||||
|
type: "dict-select",
|
||||||
|
dict: dict({
|
||||||
|
data: [
|
||||||
|
{ label: "系统", value: "sys" },
|
||||||
|
{ label: "用户", value: "user" }
|
||||||
|
]
|
||||||
|
}),
|
||||||
|
search: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
form: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
width: 100,
|
||||||
|
align: "center",
|
||||||
|
component: {
|
||||||
|
color: "auto"
|
||||||
|
},
|
||||||
|
order: 10
|
||||||
|
},
|
||||||
|
valueBuilder: ({ row, key, value }) => {
|
||||||
|
row[key] = row.userId > 0 ? "user" : "sys";
|
||||||
|
}
|
||||||
|
},
|
||||||
...commonColumnsDefine
|
...commonColumnsDefine
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
emits: ["update:modelValue"],
|
emits: ["update:modelValue"],
|
||||||
setup(props, ctx) {
|
setup(props, ctx) {
|
||||||
const api = createAccessApi(props.from === "sys" ? "/sys/access" : "/pi/access");
|
const api = createAccessApi(props.from);
|
||||||
const context: any = { props, ctx, api };
|
const context: any = { props, ctx, api };
|
||||||
const { crudBinding, crudRef, crudExpose } = useFs({ createCrudOptions, context });
|
const { crudBinding, crudRef, crudExpose } = useFs({ createCrudOptions, context });
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
<a-form-item-rest v-if="chooseForm.show">
|
<a-form-item-rest v-if="chooseForm.show">
|
||||||
<a-modal v-model:open="chooseForm.show" title="选择授权提供者" width="900px" @ok="chooseForm.ok">
|
<a-modal v-model:open="chooseForm.show" title="选择授权提供者" width="900px" @ok="chooseForm.ok">
|
||||||
<div style="height: 400px; position: relative">
|
<div style="height: 400px; position: relative">
|
||||||
<cert-access-modal v-model="selectedId" :type="type"></cert-access-modal>
|
<cert-access-modal v-model="selectedId" :type="type" :from="from"></cert-access-modal>
|
||||||
</div>
|
</div>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
</a-form-item-rest>
|
</a-form-item-rest>
|
||||||
|
@ -48,7 +48,7 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
emits: ["update:modelValue"],
|
emits: ["update:modelValue"],
|
||||||
setup(props, ctx) {
|
setup(props, ctx) {
|
||||||
const api = createAccessApi(props.from === "sys" ? "/sys/access" : "/pi/access");
|
const api = createAccessApi(props.from);
|
||||||
|
|
||||||
const target = ref({});
|
const target = ref({});
|
||||||
const selectedId = ref();
|
const selectedId = ref();
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { request } from "/src/api/service";
|
import { request } from "/src/api/service";
|
||||||
|
|
||||||
export function createAccessApi(apiPrefix = "/pi/access") {
|
export function createAccessApi(from = "user") {
|
||||||
|
const apiPrefix = from === "sys" ? "/sys/access" : "/pi/access";
|
||||||
return {
|
return {
|
||||||
async GetList(query: any) {
|
async GetList(query: any) {
|
||||||
return await request({
|
return await request({
|
||||||
|
|
|
@ -19,7 +19,7 @@ import { createAccessApi } from "/@/views/certd/access/api";
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "AccessManager",
|
name: "AccessManager",
|
||||||
setup() {
|
setup() {
|
||||||
const api = createAccessApi("/pi/access");
|
const api = createAccessApi("user");
|
||||||
const { crudBinding, crudRef, crudExpose } = useFs({ createCrudOptions, context: { api } });
|
const { crudBinding, crudRef, crudExpose } = useFs({ createCrudOptions, context: { api } });
|
||||||
|
|
||||||
// 页面打开后获取列表数据
|
// 页面打开后获取列表数据
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { request } from "/src/api/service";
|
import { request } from "/src/api/service";
|
||||||
import _ from "lodash-es";
|
import _ from "lodash-es";
|
||||||
|
import { PluginConfigBean, PluginSysSetting } from "/@/views/sys/plugin/api";
|
||||||
const apiPrefix = "/pi/plugin";
|
const apiPrefix = "/pi/plugin";
|
||||||
|
|
||||||
const defaultInputDefine = {
|
const defaultInputDefine = {
|
||||||
|
@ -54,3 +55,11 @@ export async function GetGroups(query: any) {
|
||||||
initPlugins(plugins);
|
initPlugins(plugins);
|
||||||
return groups;
|
return groups;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function GetPluginConfig(req: { id?: number; name: string; type: string }): Promise<PluginConfigBean> {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/config",
|
||||||
|
method: "post",
|
||||||
|
data: req
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { compute, CreateCrudOptionsRet, dict } from "@fast-crud/fast-crud";
|
import { compute, CreateCrudOptionsRet, dict } from "@fast-crud/fast-crud";
|
||||||
import { PluginGroup } from "@certd/pipeline";
|
import { PluginGroup } from "@certd/pipeline";
|
||||||
import { useReference } from "/@/use/use-refrence";
|
import { useReference } from "/@/use/use-refrence";
|
||||||
import _ from "lodash-es";
|
import _, { merge } from "lodash-es";
|
||||||
import { useUserStore } from "/@/store/modules/user";
|
import { useUserStore } from "/@/store/modules/user";
|
||||||
import { useSettingStore } from "/@/store/modules/settings";
|
import { useSettingStore } from "/@/store/modules/settings";
|
||||||
|
import * as api from "../api.plugin";
|
||||||
export default function (certPluginGroup: PluginGroup, formWrapperRef: any): CreateCrudOptionsRet {
|
export default function (certPluginGroup: PluginGroup, formWrapperRef: any): CreateCrudOptionsRet {
|
||||||
const inputs: any = {};
|
const inputs: any = {};
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
|
@ -46,7 +46,7 @@ export default function (certPluginGroup: PluginGroup, formWrapperRef: any): Cre
|
||||||
crudOptions: {
|
crudOptions: {
|
||||||
form: {
|
form: {
|
||||||
wrapper: {
|
wrapper: {
|
||||||
width: "1150px",
|
width: 1350,
|
||||||
saveRemind: false,
|
saveRemind: false,
|
||||||
title: "创建证书申请流水线"
|
title: "创建证书申请流水线"
|
||||||
}
|
}
|
||||||
|
@ -73,6 +73,19 @@ export default function (certPluginGroup: PluginGroup, formWrapperRef: any): Cre
|
||||||
</ul>
|
</ul>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
valueChange: {
|
||||||
|
handle: async ({ form, value }) => {
|
||||||
|
debugger;
|
||||||
|
const config = await api.GetPluginConfig({
|
||||||
|
name: value,
|
||||||
|
type: "builtIn"
|
||||||
|
});
|
||||||
|
if (config.sysSetting?.input) {
|
||||||
|
merge(form, config.sysSetting.input);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
immediate: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -116,7 +116,7 @@ import { useUserStore } from "/@/store/modules/user";
|
||||||
import { compute, useCompute } from "@fast-crud/fast-crud";
|
import { compute, useCompute } from "@fast-crud/fast-crud";
|
||||||
import { useReference } from "/@/use/use-refrence";
|
import { useReference } from "/@/use/use-refrence";
|
||||||
import { useSettingStore } from "/@/store/modules/settings";
|
import { useSettingStore } from "/@/store/modules/settings";
|
||||||
|
import * as pluginApi from "../../../api.plugin";
|
||||||
export default {
|
export default {
|
||||||
name: "PiStepForm",
|
name: "PiStepForm",
|
||||||
// eslint-disable-next-line vue/no-unused-components
|
// eslint-disable-next-line vue/no-unused-components
|
||||||
|
@ -163,7 +163,7 @@ export default {
|
||||||
console.log("currentStepTypeChanged:", currentStep.value);
|
console.log("currentStepTypeChanged:", currentStep.value);
|
||||||
};
|
};
|
||||||
|
|
||||||
const stepTypeSave = () => {
|
const stepTypeSave = async () => {
|
||||||
currentStep.value._isAdd = false;
|
currentStep.value._isAdd = false;
|
||||||
if (currentStep.value.type == null) {
|
if (currentStep.value.type == null) {
|
||||||
message.warn("请先选择类型");
|
message.warn("请先选择类型");
|
||||||
|
@ -171,7 +171,7 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 给step的input设置默认值
|
// 给step的input设置默认值
|
||||||
changeCurrentPlugin(currentStep.value);
|
await changeCurrentPlugin(currentStep.value);
|
||||||
|
|
||||||
//合并默认值
|
//合并默认值
|
||||||
_.merge(currentStep.value, { input: {}, strategy: { runStrategy: 0 } }, currentPlugin.value.default, currentStep.value);
|
_.merge(currentStep.value, { input: {}, strategy: { runStrategy: 0 } }, currentPlugin.value.default, currentStep.value);
|
||||||
|
@ -229,7 +229,7 @@ export default {
|
||||||
const currentPlugin = doComputed(() => {
|
const currentPlugin = doComputed(() => {
|
||||||
return currentPluginDefine.value;
|
return currentPluginDefine.value;
|
||||||
}, getContext);
|
}, getContext);
|
||||||
const changeCurrentPlugin = (step: any) => {
|
const changeCurrentPlugin = async (step: any) => {
|
||||||
const stepType = step.type;
|
const stepType = step.type;
|
||||||
step.type = stepType;
|
step.type = stepType;
|
||||||
step._isAdd = false;
|
step._isAdd = false;
|
||||||
|
@ -255,6 +255,14 @@ export default {
|
||||||
currentStep.value.input[key] = column.default ?? column.value;
|
currentStep.value.input[key] = column.default ?? column.value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//设置系统初始值
|
||||||
|
debugger;
|
||||||
|
const pluginSysConfig = await pluginApi.GetPluginConfig({ name: pluginDefine.name, type: "builtIn" });
|
||||||
|
if (pluginSysConfig.sysSetting?.input) {
|
||||||
|
for (const key in pluginSysConfig.sysSetting?.input) {
|
||||||
|
currentStep.value.input[key] = pluginSysConfig.sysSetting?.input[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
console.log("currentStepTypeChanged:", currentStep.value);
|
console.log("currentStepTypeChanged:", currentStep.value);
|
||||||
console.log("currentStepPlugin:", currentPlugin.value);
|
console.log("currentStepPlugin:", currentPlugin.value);
|
||||||
|
|
|
@ -20,7 +20,7 @@ export type PluginGroup = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export type PluginDefine = {
|
export type PluginDefine = {
|
||||||
key: string;
|
name: string;
|
||||||
title: string;
|
title: string;
|
||||||
desc?: string;
|
desc?: string;
|
||||||
input: {
|
input: {
|
||||||
|
|
|
@ -58,10 +58,43 @@ export async function DeleteBatch(ids: any[]) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function SetDisabled(bean: { id?: number; name?: string; type?: string; disabled: boolean }) {
|
export async function SetDisabled(data: { id?: number; name?: string; type?: string; disabled: boolean }) {
|
||||||
return await request({
|
return await request({
|
||||||
url: apiPrefix + "/setDisabled",
|
url: apiPrefix + "/setDisabled",
|
||||||
method: "post",
|
method: "post",
|
||||||
data: bean
|
data: data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export type PluginConfigBean = {
|
||||||
|
name: string;
|
||||||
|
disabled: boolean;
|
||||||
|
sysSetting: {
|
||||||
|
input?: Record<string, any>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export type CertApplyPluginSysInput = {
|
||||||
|
googleCommonEabAccessId: number;
|
||||||
|
};
|
||||||
|
export type PluginSysSetting<T> = {
|
||||||
|
input?: T;
|
||||||
|
};
|
||||||
|
export type CommPluginConfig = {
|
||||||
|
CertApply?: PluginSysSetting<CertApplyPluginSysInput>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function GetCommPluginConfigs(): Promise<CommPluginConfig> {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/getCommPluginConfigs",
|
||||||
|
method: "post"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function SaveCommPluginConfigs(data: CommPluginConfig): Promise<void> {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/saveCommPluginConfigs",
|
||||||
|
method: "post",
|
||||||
|
data
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
<template>
|
||||||
|
<fs-page class="page-plugin-config">
|
||||||
|
<template #header>
|
||||||
|
<div class="title">证书插件配置</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<div class="sys-plugin-config settings-form">
|
||||||
|
<a-form :model="formState" :label-col="{ span: 8 }" :wrapper-col="{ span: 16 }" autocomplete="off" @finish="onFinish" @finish-failed="onFinishFailed">
|
||||||
|
<a-form-item label="公共Google EAB授权" :name="['CertApply', 'input', 'googleCommonEabAccessId']">
|
||||||
|
<access-selector v-model:model-value="formState.CertApply.input.googleCommonEabAccessId" type="eab" from="sys"></access-selector>
|
||||||
|
<div class="helper">设置公共Google EAB授权给用户使用,避免用户自己去翻墙获取Google EAB授权</div>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item :wrapper-col="{ offset: 8, span: 16 }">
|
||||||
|
<a-button :loading="saveLoading" type="primary" html-type="submit">保存</a-button>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</div>
|
||||||
|
</fs-page>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import AccessSelector from "/@/views/certd/access/access-selector/index.vue";
|
||||||
|
import { reactive, ref } from "vue";
|
||||||
|
import { CommPluginConfig, GetCommPluginConfigs, SaveCommPluginConfigs } from "/@/views/sys/plugin/api";
|
||||||
|
import { merge } from "lodash-es";
|
||||||
|
import { notification } from "ant-design-vue";
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: "SysPluginConfig"
|
||||||
|
});
|
||||||
|
const formState = reactive<Partial<CommPluginConfig>>({
|
||||||
|
CertApply: {
|
||||||
|
input: {}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
async function loadForm() {
|
||||||
|
const res = await GetCommPluginConfigs();
|
||||||
|
merge(formState, res);
|
||||||
|
}
|
||||||
|
|
||||||
|
loadForm();
|
||||||
|
|
||||||
|
const saveLoading = ref(false);
|
||||||
|
const onFinish = async (form: any) => {
|
||||||
|
try {
|
||||||
|
saveLoading.value = true;
|
||||||
|
await SaveCommPluginConfigs(form);
|
||||||
|
notification.success({
|
||||||
|
message: "保存成功"
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
saveLoading.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onFinishFailed = (errorInfo: any) => {
|
||||||
|
console.log("Failed:", errorInfo);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style lang="less"></style>
|
|
@ -3,7 +3,7 @@
|
||||||
<template #header>
|
<template #header>
|
||||||
<div class="title">系统设置</div>
|
<div class="title">系统设置</div>
|
||||||
</template>
|
</template>
|
||||||
<div class="sys-settings-form">
|
<div class="sys-settings-form settings-form">
|
||||||
<a-form
|
<a-form
|
||||||
:model="formState"
|
:model="formState"
|
||||||
name="basic"
|
name="basic"
|
||||||
|
|
|
@ -8,7 +8,7 @@ CREATE TABLE "pi_plugin"
|
||||||
"group" varchar(100),
|
"group" varchar(100),
|
||||||
"version" varchar(100),
|
"version" varchar(100),
|
||||||
"setting" text,
|
"setting" text,
|
||||||
"sysSetting" text,
|
"sys_setting" text,
|
||||||
"content" text,
|
"content" text,
|
||||||
"type" varchar(100) NOT NULL,
|
"type" varchar(100) NOT NULL,
|
||||||
"disabled" boolean NOT NULL,
|
"disabled" boolean NOT NULL,
|
||||||
|
|
|
@ -24,7 +24,7 @@ export class CnameRecordController extends CrudController<CnameRecordService> {
|
||||||
|
|
||||||
const bq = qb => {
|
const bq = qb => {
|
||||||
if (domain) {
|
if (domain) {
|
||||||
qb.where('domain like :domain', { domain: `%${domain}%` });
|
qb.andWhere('domain like :domain', { domain: `%${domain}%` });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ export class AccessController extends CrudController<AccessService> {
|
||||||
body.query = body.query ?? {};
|
body.query = body.query ?? {};
|
||||||
delete body.query.userId;
|
delete body.query.userId;
|
||||||
const buildQuery = qb => {
|
const buildQuery = qb => {
|
||||||
qb.where('user_id = :userId', { userId: this.getUserId() });
|
qb.andWhere('user_id = :userId', { userId: this.getUserId() });
|
||||||
};
|
};
|
||||||
const res = await this.service.page({
|
const res = await this.service.page({
|
||||||
query: body.query,
|
query: body.query,
|
||||||
|
|
|
@ -51,7 +51,7 @@ export class HistoryController extends CrudController<HistoryService> {
|
||||||
const pipelines = await this.pipelineService.list({
|
const pipelines = await this.pipelineService.list({
|
||||||
query: pipelineQuery,
|
query: pipelineQuery,
|
||||||
buildQuery: qb => {
|
buildQuery: qb => {
|
||||||
qb.where('title like :title', { title: `%${pipelineTitle}%` });
|
qb.andWhere('title like :title', { title: `%${pipelineTitle}%` });
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
pipelineIds = pipelines.map(p => p.id);
|
pipelineIds = pipelines.map(p => p.id);
|
||||||
|
@ -59,7 +59,7 @@ export class HistoryController extends CrudController<HistoryService> {
|
||||||
|
|
||||||
const buildQuery = qb => {
|
const buildQuery = qb => {
|
||||||
if (pipelineIds) {
|
if (pipelineIds) {
|
||||||
qb.where({
|
qb.andWhere({
|
||||||
pipelineId: In(pipelineIds),
|
pipelineId: In(pipelineIds),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ export class PipelineController extends CrudController<PipelineService> {
|
||||||
|
|
||||||
const buildQuery = qb => {
|
const buildQuery = qb => {
|
||||||
if (title) {
|
if (title) {
|
||||||
qb.where('title like :title', { title: `%${title}%` });
|
qb.andWhere('title like :title', { title: `%${title}%` });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if (!body.sort || !body.sort?.prop) {
|
if (!body.sort || !body.sort?.prop) {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { ALL, Controller, Inject, Post, Provide, Query } from '@midwayjs/core';
|
import { ALL, Body, Controller, Inject, Post, Provide, Query } from '@midwayjs/core';
|
||||||
import { BaseController, Constants } from '@certd/lib-server';
|
import { BaseController, Constants } from '@certd/lib-server';
|
||||||
import { PluginService } from '../../modules/plugin/service/plugin-service.js';
|
import { PluginService } from '../../modules/plugin/service/plugin-service.js';
|
||||||
|
import { PluginConfigService } from '../../modules/plugin/service/plugin-config-service.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 插件
|
* 插件
|
||||||
|
@ -11,6 +12,9 @@ export class PluginController extends BaseController {
|
||||||
@Inject()
|
@Inject()
|
||||||
service: PluginService;
|
service: PluginService;
|
||||||
|
|
||||||
|
@Inject()
|
||||||
|
pluginConfigService: PluginConfigService;
|
||||||
|
|
||||||
@Post('/list', { summary: Constants.per.authOnly })
|
@Post('/list', { summary: Constants.per.authOnly })
|
||||||
async list(@Query(ALL) query: any) {
|
async list(@Query(ALL) query: any) {
|
||||||
query.userId = this.getUserId();
|
query.userId = this.getUserId();
|
||||||
|
@ -24,4 +28,10 @@ export class PluginController extends BaseController {
|
||||||
const group = await this.service.getEnabledBuildInGroup();
|
const group = await this.service.getEnabledBuildInGroup();
|
||||||
return this.ok(group);
|
return this.ok(group);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Post('/config', { summary: Constants.per.authOnly })
|
||||||
|
async config(@Body(ALL) body: { id?: number; name?: string; type: string }) {
|
||||||
|
const config = await this.pluginConfigService.getPluginConfig(body);
|
||||||
|
return this.ok(config);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ import { merge } from 'lodash-es';
|
||||||
import { CrudController } from '@certd/lib-server';
|
import { CrudController } from '@certd/lib-server';
|
||||||
import { PluginService } from '../../../modules/plugin/service/plugin-service.js';
|
import { PluginService } from '../../../modules/plugin/service/plugin-service.js';
|
||||||
import { checkComm } from '@certd/pipeline';
|
import { checkComm } from '@certd/pipeline';
|
||||||
|
import { CommPluginConfig, PluginConfigService } from '../../../modules/plugin/service/plugin-config-service.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 插件
|
* 插件
|
||||||
|
@ -13,6 +14,9 @@ export class PluginController extends CrudController<PluginService> {
|
||||||
@Inject()
|
@Inject()
|
||||||
service: PluginService;
|
service: PluginService;
|
||||||
|
|
||||||
|
@Inject()
|
||||||
|
pluginConfigService: PluginConfigService;
|
||||||
|
|
||||||
getService() {
|
getService() {
|
||||||
checkComm();
|
checkComm();
|
||||||
return this.service;
|
return this.service;
|
||||||
|
@ -65,4 +69,15 @@ export class PluginController extends CrudController<PluginService> {
|
||||||
await this.service.setDisabled(body);
|
await this.service.setDisabled(body);
|
||||||
return this.ok();
|
return this.ok();
|
||||||
}
|
}
|
||||||
|
@Post('/getCommPluginConfigs', { summary: 'sys:settings:edit' })
|
||||||
|
async getCommPluginConfigs() {
|
||||||
|
const res = await this.pluginConfigService.getCommPluginConfig();
|
||||||
|
return this.ok(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post('/saveCommPluginConfigs', { summary: 'sys:settings:edit' })
|
||||||
|
async saveCommPluginConfigs(@Body(ALL) body: CommPluginConfig) {
|
||||||
|
const res = await this.pluginConfigService.saveCommPluginConfig(body);
|
||||||
|
return this.ok(res);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { Config, Inject, Provide, Scope, ScopeEnum, sleep } from '@midwayjs/core';
|
import { Config, Inject, Provide, Scope, ScopeEnum, sleep } from '@midwayjs/core';
|
||||||
import { InjectEntityModel } from '@midwayjs/typeorm';
|
import { InjectEntityModel } from '@midwayjs/typeorm';
|
||||||
import { In, Repository } from 'typeorm';
|
import { In, Repository } from 'typeorm';
|
||||||
import { BaseService, PageReq } from '@certd/lib-server';
|
import { BaseService, NeedVIPException, PageReq } from '@certd/lib-server';
|
||||||
import { PipelineEntity } from '../entity/pipeline.js';
|
import { PipelineEntity } from '../entity/pipeline.js';
|
||||||
import { PipelineDetail } from '../entity/vo/pipeline-detail.js';
|
import { PipelineDetail } from '../entity/vo/pipeline-detail.js';
|
||||||
import { Executor, isPlus, Pipeline, ResultType, RunHistory, UserInfo } from '@certd/pipeline';
|
import { Executor, isPlus, logger, Pipeline, ResultType, RunHistory, UserInfo } from '@certd/pipeline';
|
||||||
import { AccessService } from './access-service.js';
|
import { AccessService } from './access-service.js';
|
||||||
import { DbStorage } from './db-storage.js';
|
import { DbStorage } from './db-storage.js';
|
||||||
import { StorageService } from './storage-service.js';
|
import { StorageService } from './storage-service.js';
|
||||||
|
@ -13,14 +13,12 @@ import { HistoryService } from './history-service.js';
|
||||||
import { HistoryEntity } from '../entity/history.js';
|
import { HistoryEntity } from '../entity/history.js';
|
||||||
import { HistoryLogEntity } from '../entity/history-log.js';
|
import { HistoryLogEntity } from '../entity/history-log.js';
|
||||||
import { HistoryLogService } from './history-log-service.js';
|
import { HistoryLogService } from './history-log-service.js';
|
||||||
import { logger } from '@certd/pipeline';
|
|
||||||
import { EmailService } from '../../basic/service/email-service.js';
|
import { EmailService } from '../../basic/service/email-service.js';
|
||||||
import { NeedVIPException } from '@certd/lib-server';
|
|
||||||
import { UserService } from '../../sys/authority/service/user-service.js';
|
import { UserService } from '../../sys/authority/service/user-service.js';
|
||||||
import { AccessGetter } from './access-getter.js';
|
import { AccessGetter } from './access-getter.js';
|
||||||
import { CnameRecordService } from '../../cname/service/cname-record-service.js';
|
import { CnameRecordService } from '../../cname/service/cname-record-service.js';
|
||||||
import { CnameProxyService } from './cname-proxy-service.js';
|
import { CnameProxyService } from './cname-proxy-service.js';
|
||||||
import { PluginConfigService } from './plugin-config-service.js';
|
import { PluginConfigGetter } from '../../plugin/service/plugin-config-getter.js';
|
||||||
|
|
||||||
const runningTasks: Map<string | number, Executor> = new Map();
|
const runningTasks: Map<string | number, Executor> = new Map();
|
||||||
const freeCount = 10;
|
const freeCount = 10;
|
||||||
|
@ -47,7 +45,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
||||||
historyLogService: HistoryLogService;
|
historyLogService: HistoryLogService;
|
||||||
|
|
||||||
@Inject()
|
@Inject()
|
||||||
pluginConfigService: PluginConfigService;
|
pluginConfigGetter: PluginConfigGetter;
|
||||||
|
|
||||||
@Inject()
|
@Inject()
|
||||||
userService: UserService;
|
userService: UserService;
|
||||||
|
@ -360,7 +358,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
||||||
onChanged,
|
onChanged,
|
||||||
accessService: accessGetter,
|
accessService: accessGetter,
|
||||||
cnameProxyService,
|
cnameProxyService,
|
||||||
pluginConfigService: this.pluginConfigService,
|
pluginConfigService: this.pluginConfigGetter,
|
||||||
storage: new DbStorage(userId, this.storageService),
|
storage: new DbStorage(userId, this.storageService),
|
||||||
emailService: this.emailService,
|
emailService: this.emailService,
|
||||||
fileRootDir: this.certdConfig.fileRootDir,
|
fileRootDir: this.certdConfig.fileRootDir,
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
import { Provide, Scope, ScopeEnum } from '@midwayjs/core';
|
|
||||||
import { IPluginConfigService } from '@certd/pipeline';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 授权
|
|
||||||
*/
|
|
||||||
@Provide()
|
|
||||||
@Scope(ScopeEnum.Singleton)
|
|
||||||
export class PluginConfigService implements IPluginConfigService {
|
|
||||||
getPluginConfig(pluginName: string) {
|
|
||||||
return Promise.resolve({});
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -23,7 +23,7 @@ export class PluginEntity {
|
||||||
@Column({ comment: '配置', length: 40960 })
|
@Column({ comment: '配置', length: 40960 })
|
||||||
setting: string;
|
setting: string;
|
||||||
|
|
||||||
@Column({ comment: '系统配置', length: 40960 })
|
@Column({ name: 'sys_setting', comment: '系统配置', length: 40960 })
|
||||||
sysSetting: string;
|
sysSetting: string;
|
||||||
|
|
||||||
@Column({ comment: '脚本', length: 40960 })
|
@Column({ comment: '脚本', length: 40960 })
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
import { Inject, Provide, Scope, ScopeEnum } from '@midwayjs/core';
|
||||||
|
import { IPluginConfigService, PluginConfig } from '@certd/pipeline';
|
||||||
|
import { PluginConfigService } from './plugin-config-service.js';
|
||||||
|
|
||||||
|
@Provide()
|
||||||
|
@Scope(ScopeEnum.Singleton)
|
||||||
|
export class PluginConfigGetter implements IPluginConfigService {
|
||||||
|
@Inject()
|
||||||
|
pluginConfigService: PluginConfigService;
|
||||||
|
|
||||||
|
async getPluginConfig(pluginName: string): Promise<PluginConfig> {
|
||||||
|
const res = await this.pluginConfigService.getPluginConfig({
|
||||||
|
name: pluginName,
|
||||||
|
type: 'builtIn',
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
name: res.name,
|
||||||
|
disabled: res.disabled,
|
||||||
|
sysSetting: res.sysSetting,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
import { Inject, Provide, Scope, ScopeEnum } from '@midwayjs/core';
|
||||||
|
import { PluginService } from './plugin-service.js';
|
||||||
|
|
||||||
|
export type PluginConfig = {
|
||||||
|
name: string;
|
||||||
|
disabled: boolean;
|
||||||
|
sysSetting: {
|
||||||
|
input?: Record<string, any>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export type CommPluginConfig = {
|
||||||
|
CertApply?: PluginConfig;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type PluginFindReq = {
|
||||||
|
id?: number;
|
||||||
|
name?: string;
|
||||||
|
type: string;
|
||||||
|
};
|
||||||
|
@Provide()
|
||||||
|
@Scope(ScopeEnum.Singleton)
|
||||||
|
export class PluginConfigService {
|
||||||
|
@Inject()
|
||||||
|
pluginService: PluginService;
|
||||||
|
|
||||||
|
async getCommPluginConfig() {
|
||||||
|
const configs: CommPluginConfig = {};
|
||||||
|
|
||||||
|
configs.CertApply = await this.getPluginConfig({
|
||||||
|
name: 'CertApply',
|
||||||
|
type: 'builtIn',
|
||||||
|
});
|
||||||
|
return configs;
|
||||||
|
}
|
||||||
|
|
||||||
|
async saveCommPluginConfig(body: CommPluginConfig) {
|
||||||
|
const certApplyConfig = body.CertApply;
|
||||||
|
const CertApply = await this.pluginService.getRepository().findOne({
|
||||||
|
where: { name: 'CertApply' },
|
||||||
|
});
|
||||||
|
if (!CertApply) {
|
||||||
|
await this.pluginService.add({
|
||||||
|
name: 'CertApply',
|
||||||
|
sysSetting: JSON.stringify(certApplyConfig),
|
||||||
|
type: 'builtIn',
|
||||||
|
disabled: false,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
await this.pluginService.getRepository().update({ name: 'CertApply' }, { sysSetting: JSON.stringify(certApplyConfig) });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async get(req: PluginFindReq) {
|
||||||
|
if (!req.name && !req.id) {
|
||||||
|
throw new Error('plugin s name or id is required');
|
||||||
|
}
|
||||||
|
return await this.pluginService.getRepository().findOne({
|
||||||
|
where: {
|
||||||
|
id: req.id,
|
||||||
|
name: req.name,
|
||||||
|
type: req.type,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async getPluginConfig(req: PluginFindReq) {
|
||||||
|
const plugin = await this.get(req);
|
||||||
|
let sysSetting: any = {};
|
||||||
|
if (plugin && plugin.sysSetting) {
|
||||||
|
sysSetting = JSON.parse(plugin.sysSetting);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
name: plugin.name,
|
||||||
|
disabled: plugin.disabled,
|
||||||
|
sysSetting,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue