perf: EAB授权支持绑定邮箱,支持公共EAB设置

pull/213/head
xiaojunnuo 2024-10-14 03:17:10 +08:00
parent e8b617b80c
commit 07043aff0c
32 changed files with 374 additions and 57 deletions

View File

@ -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;
//判断是否需要跳过 //判断是否需要跳过

View File

@ -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;

View File

@ -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>;
}; };

View File

@ -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

View File

@ -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();

View File

@ -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(

View File

@ -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",

View File

@ -222,3 +222,8 @@ h1, h2, h3, h4, h5, h6 {
/* right: 0; */ /* right: 0; */
} }
} }
.settings-form {
width: 800px;
margin: 20px;
}

View File

@ -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
} }
} }

View File

@ -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 });

View File

@ -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();

View File

@ -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({

View File

@ -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 } });
// //

View File

@ -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
});
}

View File

@ -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
} }
} }
}, },

View File

@ -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 {
} }
// stepinput // stepinput
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);

View File

@ -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: {

View File

@ -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
}); });
} }

View File

@ -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>

View File

@ -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"

View File

@ -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,

View File

@ -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}%` });
} }
}; };

View File

@ -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,

View File

@ -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),
}); });
} }

View File

@ -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) {

View File

@ -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);
}
} }

View File

@ -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);
}
} }

View File

@ -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,

View File

@ -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({});
}
}

View File

@ -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 })

View File

@ -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,
};
}
}

View File

@ -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,
};
}
}