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