mirror of https://github.com/certd/certd
refactor(core): 重构访问控制和插件实例化逻辑
- 修改访问控制和插件注册方式,使用异步函数统一实例化逻辑 - 更新相关组件和控制器以适应新的异步实例化方式 - 优化 DNS 提供商选择器,增加访问类型支持pull/370/head
parent
c4fb138ae8
commit
3d8a5196a0
|
@ -26,7 +26,9 @@ export function IsAccess(define: AccessDefine): ClassDecorator {
|
|||
target.define = define;
|
||||
accessRegistry.register(define.name, {
|
||||
define,
|
||||
target,
|
||||
target: async () => {
|
||||
return target;
|
||||
},
|
||||
});
|
||||
};
|
||||
}
|
||||
|
@ -39,13 +41,15 @@ export function AccessInput(input?: AccessInputDefine): PropertyDecorator {
|
|||
};
|
||||
}
|
||||
|
||||
export function newAccess(type: string, input: any, ctx?: AccessContext) {
|
||||
export async function newAccess(type: string, input: any, ctx?: AccessContext) {
|
||||
const register = accessRegistry.get(type);
|
||||
if (register == null) {
|
||||
throw new Error(`access ${type} not found`);
|
||||
}
|
||||
// @ts-ignore
|
||||
const access = new register.target();
|
||||
const accessCls = await register.target();
|
||||
// @ts-ignore
|
||||
const access = new accessCls();
|
||||
for (const key in input) {
|
||||
access[key] = input[key];
|
||||
}
|
||||
|
|
|
@ -281,13 +281,9 @@ export class Executor {
|
|||
let instance: ITaskPlugin = null;
|
||||
try {
|
||||
//@ts-ignore
|
||||
if (plugin.target.define) {
|
||||
//@ts-ignore
|
||||
instance = new plugin.target();
|
||||
} else {
|
||||
//@ts-ignore
|
||||
instance = await plugin.target();
|
||||
}
|
||||
const pluginCls = await plugin.target();
|
||||
//@ts-ignore
|
||||
instance = new pluginCls();
|
||||
} catch (e: any) {
|
||||
currentLogger.error(`实例化插件失败:${e.message}`);
|
||||
throw new Error(`实例化插件失败`, e);
|
||||
|
|
|
@ -26,7 +26,9 @@ export function IsNotification(define: NotificationDefine): ClassDecorator {
|
|||
target.define = define;
|
||||
notificationRegistry.register(define.name, {
|
||||
define,
|
||||
target,
|
||||
target: async () => {
|
||||
return target;
|
||||
},
|
||||
});
|
||||
};
|
||||
}
|
||||
|
@ -44,9 +46,10 @@ export async function newNotification(type: string, input: any, ctx: Notificatio
|
|||
if (register == null) {
|
||||
throw new Error(`notification ${type} not found`);
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
const plugin = new register.target();
|
||||
const pluginCls = await register.target();
|
||||
// @ts-ignore
|
||||
const plugin = new pluginCls();
|
||||
merge(plugin, input);
|
||||
if (!ctx) {
|
||||
throw new Error("ctx is required");
|
||||
|
|
|
@ -65,7 +65,9 @@ export function IsTaskPlugin(define: PluginDefine): ClassDecorator {
|
|||
|
||||
pluginRegistry.register(define.name, {
|
||||
define,
|
||||
target,
|
||||
target: async () => {
|
||||
return target;
|
||||
},
|
||||
});
|
||||
};
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ export type Registrable = {
|
|||
export type TargetGetter<T> = () => Promise<T>;
|
||||
export type RegistryItem<T> = {
|
||||
define: Registrable;
|
||||
target: T | TargetGetter<T>;
|
||||
target: TargetGetter<T>;
|
||||
};
|
||||
|
||||
export type OnRegisterContext<T> = {
|
||||
|
|
|
@ -140,7 +140,7 @@ export class AccessService extends BaseService<AccessEntity> {
|
|||
id: entity.id,
|
||||
...setting,
|
||||
};
|
||||
return newAccess(entity.type, input);
|
||||
return await newAccess(entity.type, input);
|
||||
}
|
||||
|
||||
async getById(id: any, userId: number): Promise<any> {
|
||||
|
|
|
@ -29,6 +29,7 @@ export type DomainVerifyPlanInput = {
|
|||
domain: string;
|
||||
type: "cname" | "dns" | "http";
|
||||
dnsProviderType?: string;
|
||||
dnsProviderAccessType?: string;
|
||||
dnsProviderAccessId?: number;
|
||||
cnameVerifyPlan?: Record<string, CnameRecordInput>;
|
||||
httpVerifyPlan?: Record<string, HttpRecordInput>;
|
||||
|
@ -99,7 +100,14 @@ HTTP文件验证:不支持泛域名,需要配置网站文件上传`,
|
|||
return {
|
||||
show: ctx.compute(({form})=>{
|
||||
return form.challengeType === 'dns'
|
||||
})
|
||||
}),
|
||||
component:{
|
||||
on:{
|
||||
selectedChange({form,$event}){
|
||||
form.dnsProviderAccessType = $event.accessType
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
required: true,
|
||||
|
@ -107,6 +115,8 @@ HTTP文件验证:不支持泛域名,需要配置网站文件上传`,
|
|||
})
|
||||
dnsProviderType!: string;
|
||||
|
||||
dnsProviderAccessType!: string;
|
||||
|
||||
@TaskInput({
|
||||
title: "DNS解析授权",
|
||||
component: {
|
||||
|
@ -117,7 +127,7 @@ HTTP文件验证:不支持泛域名,需要配置网站文件上传`,
|
|||
mergeScript: `return {
|
||||
component:{
|
||||
type: ctx.compute(({form})=>{
|
||||
return form.dnsProviderType
|
||||
return form.dnsProviderAccessType || form.dnsProviderType
|
||||
})
|
||||
},
|
||||
show: ctx.compute(({form})=>{
|
||||
|
|
|
@ -5,6 +5,6 @@ const apiPrefix = "/pi/dnsProvider";
|
|||
export async function GetList() {
|
||||
return await request({
|
||||
url: apiPrefix + "/list",
|
||||
method: "post"
|
||||
method: "post",
|
||||
});
|
||||
}
|
||||
|
|
|
@ -11,10 +11,10 @@ export default {
|
|||
props: {
|
||||
modelValue: {
|
||||
type: String,
|
||||
default: undefined
|
||||
}
|
||||
default: undefined,
|
||||
},
|
||||
},
|
||||
emits: ["update:modelValue"],
|
||||
emits: ["update:modelValue", "selected-change"],
|
||||
setup(props: any, ctx: any) {
|
||||
const options = ref<any[]>([]);
|
||||
|
||||
|
@ -25,24 +25,36 @@ export default {
|
|||
array.push({
|
||||
value: item.name,
|
||||
label: item.title,
|
||||
icon: item.icon
|
||||
icon: item.icon,
|
||||
accessType: item.accessType,
|
||||
});
|
||||
}
|
||||
options.value = array;
|
||||
// if (props.modelValue == null && options.value.length > 0) {
|
||||
// ctx.emit("update:modelValue", options.value[0].value);
|
||||
// }
|
||||
onSelectedChange(props.modelValue);
|
||||
}
|
||||
onCreate();
|
||||
|
||||
function onChanged(value: any) {
|
||||
ctx.emit("update:modelValue", value);
|
||||
onSelectedChange(value);
|
||||
}
|
||||
function onSelectedChange(value: any) {
|
||||
if (value) {
|
||||
const option = options.value.find(item => item.value == value);
|
||||
if (option) {
|
||||
ctx.emit("selected-change", option);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
options,
|
||||
onChanged
|
||||
onChanged,
|
||||
};
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ import { HttpRecord } from "/@/components/plugins/cert/domains-verify-plan-edito
|
|||
import { dict } from "@fast-crud/fast-crud";
|
||||
|
||||
defineOptions({
|
||||
name: "HttpVerifyPlan"
|
||||
name: "HttpVerifyPlan",
|
||||
});
|
||||
|
||||
const emit = defineEmits(["update:modelValue", "change"]);
|
||||
|
@ -53,12 +53,12 @@ watch(
|
|||
(value: any) => {
|
||||
if (value) {
|
||||
records.value = {
|
||||
...value
|
||||
...value,
|
||||
};
|
||||
}
|
||||
},
|
||||
{
|
||||
immediate: true
|
||||
immediate: true,
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -75,8 +75,8 @@ const uploaderTypeDict = dict({
|
|||
{ label: "阿里云OSS", value: "alioss" },
|
||||
{ label: "腾讯云COS", value: "tencentcos" },
|
||||
{ label: "七牛OSS", value: "qiniuoss" },
|
||||
{ label: "SSH(已废弃,请选择SFTP方式)", value: "ssh", disabled: true }
|
||||
]
|
||||
{ label: "SSH(已废弃,请选择SFTP方式)", value: "ssh", disabled: true },
|
||||
],
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
|
@ -32,14 +32,21 @@
|
|||
<div class="form-item">
|
||||
<span class="label">DNS类型:</span>
|
||||
<span class="input">
|
||||
<fs-dict-select v-model:value="item.dnsProviderType" size="small" :dict="dnsProviderTypeDict" placeholder="DNS提供商" @change="onPlanChanged"></fs-dict-select>
|
||||
<fs-dict-select
|
||||
v-model:value="item.dnsProviderType"
|
||||
size="small"
|
||||
:dict="dnsProviderTypeDict"
|
||||
placeholder="DNS提供商"
|
||||
@change="onPlanChanged"
|
||||
@selected-change="onDnsProviderChange(item, $event)"
|
||||
></fs-dict-select>
|
||||
</span>
|
||||
</div>
|
||||
<a-divider type="vertical" />
|
||||
<div class="form-item">
|
||||
<span class="label">DNS授权:</span>
|
||||
<span class="input">
|
||||
<access-selector v-model="item.dnsProviderAccessId" size="small" :type="item.dnsProviderType" placeholder="请选择" @change="onPlanChanged"></access-selector>
|
||||
<access-selector v-model="item.dnsProviderAccessId" size="small" :type="item.dnsProviderAccessType || item.dnsProviderType" placeholder="请选择" @change="onPlanChanged"></access-selector>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -101,6 +108,10 @@ const emit = defineEmits<{
|
|||
"update:modelValue": any;
|
||||
}>();
|
||||
|
||||
function onDnsProviderChange(item: any, option: any) {
|
||||
item.dnsProviderAccessType = option.accessType;
|
||||
}
|
||||
|
||||
const fullscreen = ref(false);
|
||||
function fullscreenExit() {
|
||||
if (fullscreen.value) {
|
||||
|
|
|
@ -12,6 +12,7 @@ export type DomainVerifyPlanInput = {
|
|||
domains: string[];
|
||||
type: "cname" | "dns" | "http";
|
||||
dnsProviderType?: string;
|
||||
dnsProviderAccessType?: string;
|
||||
dnsProviderAccessId?: number;
|
||||
cnameVerifyPlan?: Record<string, CnameRecord>;
|
||||
httpVerifyPlan?: Record<string, HttpRecord>;
|
||||
|
|
|
@ -27,6 +27,8 @@ export class DnsProviderController extends BaseController {
|
|||
dict.push({
|
||||
value: item.name,
|
||||
label: item.title,
|
||||
//@ts-ignore
|
||||
accessType: item.accessType,
|
||||
});
|
||||
}
|
||||
return this.ok(dict);
|
||||
|
|
|
@ -49,7 +49,7 @@ export class HandleController extends BaseController {
|
|||
}
|
||||
}
|
||||
|
||||
const access = newAccess(body.typeName, inputAccess);
|
||||
const access = await newAccess(body.typeName, inputAccess);
|
||||
|
||||
const res = await access.onRequest(body);
|
||||
|
||||
|
@ -76,7 +76,7 @@ export class HandleController extends BaseController {
|
|||
async pluginRequest(@Body(ALL) body: PluginRequestHandleReq) {
|
||||
const userId = this.getUserId();
|
||||
const pluginDefine = pluginRegistry.get(body.typeName);
|
||||
const pluginCls = pluginDefine.target;
|
||||
const pluginCls = await pluginDefine.target();
|
||||
if (pluginCls == null) {
|
||||
throw new Error(`plugin ${body.typeName} not found`);
|
||||
}
|
||||
|
|
|
@ -213,10 +213,9 @@ export class PluginService extends BaseService<PluginEntity> {
|
|||
// const script = await this.compile(plugin.content);
|
||||
const script = plugin.content
|
||||
const getPluginClass = new AsyncFunction(script);
|
||||
const pluginClass = await getPluginClass({ logger: logger });
|
||||
return new pluginClass();
|
||||
return await getPluginClass({ logger: logger });
|
||||
}catch (e) {
|
||||
logger.error("实例化插件失败:",e)
|
||||
logger.error("编译插件失败:",e)
|
||||
throw e
|
||||
}
|
||||
|
||||
|
@ -266,8 +265,8 @@ export class PluginService extends BaseService<PluginEntity> {
|
|||
|
||||
registry.register(item.name, {
|
||||
define: item,
|
||||
target: () => {
|
||||
return this.getPluginTarget(item.name);
|
||||
target: async () => {
|
||||
return await this.getPluginTarget(item.name);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue