diff --git a/packages/ui/certd-server/src/modules/pipeline/service/builtin-plugin-service.ts b/packages/ui/certd-server/src/modules/pipeline/service/builtin-plugin-service.ts index ca1e791dc..d04ec2a27 100644 --- a/packages/ui/certd-server/src/modules/pipeline/service/builtin-plugin-service.ts +++ b/packages/ui/certd-server/src/modules/pipeline/service/builtin-plugin-service.ts @@ -14,7 +14,7 @@ export class BuiltInPluginService { continue; } //@ts-ignore - if(Plugin.define?.type && Plugin.define?.type !== 'builtin'){ + if(Plugin.define?.type && Plugin.define?.type.toLowerCase() !== 'builtin'){ continue; } list.push({ ...Plugin.define, key }); diff --git a/packages/ui/certd-server/src/modules/plugin/service/plugin-service.ts b/packages/ui/certd-server/src/modules/plugin/service/plugin-service.ts index 5866c9952..4fd7da3f3 100644 --- a/packages/ui/certd-server/src/modules/plugin/service/plugin-service.ts +++ b/packages/ui/certd-server/src/modules/plugin/service/plugin-service.ts @@ -1,16 +1,16 @@ -import {Inject, Provide, Scope, ScopeEnum} from "@midwayjs/core"; -import {addonRegistry, BaseService, PageReq} from "@certd/lib-server"; -import {PluginEntity} from "../entity/plugin.js"; -import {InjectEntityModel} from "@midwayjs/typeorm"; -import {IsNull, Not, Repository} from "typeorm"; -import {isComm} from "@certd/plus-core"; -import {BuiltInPluginService} from "../../pipeline/service/builtin-plugin-service.js"; -import {merge} from "lodash-es"; -import {accessRegistry, notificationRegistry, pluginRegistry} from "@certd/pipeline"; -import {dnsProviderRegistry} from "@certd/plugin-cert"; -import {logger} from "@certd/basic"; +import { Inject, Provide, Scope, ScopeEnum } from "@midwayjs/core"; +import { addonRegistry, BaseService, PageReq } from "@certd/lib-server"; +import { PluginEntity } from "../entity/plugin.js"; +import { InjectEntityModel } from "@midwayjs/typeorm"; +import { IsNull, Not, Repository } from "typeorm"; +import { isComm } from "@certd/plus-core"; +import { BuiltInPluginService } from "../../pipeline/service/builtin-plugin-service.js"; +import { merge } from "lodash-es"; +import { accessRegistry, notificationRegistry, pluginRegistry } from "@certd/pipeline"; +import { dnsProviderRegistry } from "@certd/plugin-cert"; +import { logger } from "@certd/basic"; import yaml from "js-yaml"; -import {getDefaultAccessPlugin, getDefaultDeployPlugin, getDefaultDnsPlugin} from "./default-plugin.js"; +import { getDefaultAccessPlugin, getDefaultDeployPlugin, getDefaultDnsPlugin } from "./default-plugin.js"; import fs from "fs"; import path from "path"; @@ -19,8 +19,21 @@ export type PluginImportReq = { override?: boolean; }; + async function importer(modulePath: string) { + if (!modulePath) { + throw new Error("modules path 不能为空") + } + if (!modulePath.startsWith("/@/")) { + return await import(modulePath) + } + modulePath = modulePath.replace("/@/", "") + //替换@为相对地址 + modulePath = `../../../${modulePath}` + return await import(modulePath) +} + @Provide() -@Scope(ScopeEnum.Request, {allowDowngrade: true}) +@Scope(ScopeEnum.Request, { allowDowngrade: true }) export class PluginService extends BaseService { @InjectEntityModel(PluginEntity) repository: Repository; @@ -57,7 +70,7 @@ export class PluginService extends BaseService { }; } - async getEnabledBuildInGroup(opts?:{isSimple?:boolean,withSetting?:boolean}) { + async getEnabledBuildInGroup(opts?: { isSimple?: boolean, withSetting?: boolean }) { const groups = this.builtInPluginService.getGroups(); if (opts?.isSimple) { for (const key in groups) { @@ -75,17 +88,17 @@ export class PluginService extends BaseService { // 初始化设置 const settingPlugins = await this.repository.find({ - select:{ - id:true, - name:true, - sysSetting:true + select: { + id: true, + name: true, + sysSetting: true }, where: { - sysSetting : Not(IsNull()) + sysSetting: Not(IsNull()) } }) //合并插件配置 - const pluginSettingMap:any = {} + const pluginSettingMap: any = {} for (const item of settingPlugins) { if (!item.sysSetting) { continue; @@ -99,7 +112,7 @@ export class PluginService extends BaseService { } for (const item of group.plugins) { const pluginSetting = pluginSettingMap[item.name]; - if (pluginSetting){ + if (pluginSetting) { item.sysSetting = pluginSetting } } @@ -172,13 +185,13 @@ export class PluginService extends BaseService { } async setDisabled(opts: { id?: number; name?: string; type: string; disabled: boolean }) { - const {id, name, type, disabled} = opts; + const { id, name, type, disabled } = opts; if (!type) { throw new Error("参数错误: type 不能为空"); } if (id > 0) { //update - await this.repository.update({id}, {disabled}); + await this.repository.update({ id }, { disabled }); return; } @@ -214,7 +227,7 @@ export class PluginService extends BaseService { throw new Error(`插件${param.author}/${param.name}已存在`); } - if (param.type === "builtIn"){ + if (param.type === "builtIn") { return await super.add({ ...param, }); @@ -233,7 +246,7 @@ export class PluginService extends BaseService { throw new Error(`插件类型${param.pluginType}不支持`); } - const res= await super.add({ + const res = await super.add({ ...param, ...plugin }); @@ -242,18 +255,18 @@ export class PluginService extends BaseService { return res } - async registerById(id: any) { + async registerById(id: any) { const item = await this.info(id); if (!item) { return; } - if(item.type === "builtIn"){ + if (item.type === "builtIn") { return; } await this.registerPlugin(item); } - async unRegisterById(id: any){ + async unRegisterById(id: any) { const item = await this.info(id); if (!item) { return; @@ -262,19 +275,19 @@ export class PluginService extends BaseService { return; } let name = item.name; - if (item.author && !item.name.startsWith( `${item.author}/`)){ - name = `${item.author}/${item.name}` + if (item.author && !item.name.startsWith(`${item.author}/`)) { + name = `${item.author}/${item.name}` } - if (item.pluginType === "access"){ + if (item.pluginType === "access") { accessRegistry.unRegister(name) - }else if (item.pluginType === "deploy"){ + } else if (item.pluginType === "deploy") { pluginRegistry.unRegister(name) - }else if (item.pluginType === "dnsProvider"){ + } else if (item.pluginType === "dnsProvider") { dnsProviderRegistry.unRegister(name) - }else if (item.pluginType === "notification"){ + } else if (item.pluginType === "notification") { notificationRegistry.unRegister(name) - }else{ - logger.warn(`不支持的插件类型:${item.pluginType}`) + } else { + logger.warn(`不支持的插件类型:${item.pluginType}`) } } @@ -291,7 +304,7 @@ export class PluginService extends BaseService { } - const res= await super.update(param); + const res = await super.update(param); await this.registerById(param.id); return res @@ -300,14 +313,14 @@ export class PluginService extends BaseService { async compile(code: string) { const ts = await import("typescript"); return ts.transpileModule(code, { - compilerOptions: {module: ts.ModuleKind.ESNext} + compilerOptions: { module: ts.ModuleKind.ESNext } }).outputText; } private async getPluginClassFromFile(item: any) { const scriptFilePath = item.scriptFilePath; - const res = await import((`../../..${scriptFilePath}`)) + const res = await import((`../../..${scriptFilePath}`)) const classNames = Object.keys(res) return res[classNames[classNames.length - 1]] } @@ -336,8 +349,8 @@ export class PluginService extends BaseService { }).constructor; // const script = await this.compile(plugin.content); const script = plugin.content; - const getPluginClass = new AsyncFunction(script); - return await getPluginClass({logger: logger}); + const getPluginClass = new AsyncFunction("_ctx", script); + return await getPluginClass({ logger: logger, import: importer }); } catch (e) { logger.error("编译插件失败:", e); throw e; @@ -379,7 +392,7 @@ export class PluginService extends BaseService { } //排序 list = list.sort((a, b) => { - return (a.order??10) - (b.order ??10); + return (a.order ?? 10) - (b.order ?? 10); }); for (const item of list) { @@ -398,11 +411,11 @@ export class PluginService extends BaseService { delete item.metadata; delete item.content; delete item.extra; - if (item.author) { - item.name = item.author + "/" + item.name; + if (item.author) { + item.name = item.author + "/" + item.name; } let name = item.name - if(item.addonType){ + if (item.addonType) { name = item.addonType + ":" + name; } let registry = null; @@ -414,9 +427,9 @@ export class PluginService extends BaseService { registry = dnsProviderRegistry; } else if (item.pluginType === "notification") { registry = notificationRegistry; - }else if (item.pluginType === "addon") { + } else if (item.pluginType === "addon") { registry = addonRegistry; - } else { + } else { logger.warn(`插件${name}类型错误:${item.pluginType}`); return; } @@ -495,9 +508,9 @@ export class PluginService extends BaseService { if (!old) { //add - const {id} = await this.add(pluginEntity); + const { id } = await this.add(pluginEntity); pluginEntity.id = id; - } else{ + } else { if (!req.override) { throw new Error(`插件${loaded.author}/${loaded.name}已存在`); } @@ -511,8 +524,8 @@ export class PluginService extends BaseService { } - async deleteByIds(ids:any[]){ - await super.delete(ids); + async deleteByIds(ids: any[]) { + await super.delete(ids); for (const id of ids) { await this.unRegisterById(id) } diff --git a/packages/ui/certd-server/src/plugins/plugin-plus/maoyun/client.ts b/packages/ui/certd-server/src/plugins/plugin-plus/maoyun/client.ts deleted file mode 100644 index 0b94bb755..000000000 --- a/packages/ui/certd-server/src/plugins/plugin-plus/maoyun/client.ts +++ /dev/null @@ -1,98 +0,0 @@ -import { HttpClient, HttpRequestConfig, ILogger } from "@certd/basic"; -import { MaoyunAccess } from "./access.js"; - -export class MaoyunClient { - privateKeyPem = ""; - http: HttpClient; - logger: ILogger; - access: MaoyunAccess; - token: string; - - constructor(opts: { logger: ILogger; http: HttpClient; access: MaoyunAccess }) { - this.logger = opts.logger; - this.http = opts.http; - this.access = opts.access; - this.privateKeyPem = - "\n-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEAt83xKlUSU0i09/pwwQ0MQQ0v71IULdVGJ3AFo+anwLX1TRCp\nxmY5i+xmT9tshHqiPGN8qeg+lDaqA+iwmS6zqi+KlNmmKJc3kUx/h24MI3nff0xy\nz605ZfDgJhwBkJpTI6Sk4+OLX+lZxOiET0nOT7jrhKiFCKX8+0ZXjTJ1cmdifKaj\nqXmjD+XYZzBwA2fCr1kPq2xKvU097Ksu6QvM+La5X/tt+FJOuedmuqZmsb6YQ+6O\n6mJ0bcY0kFDGNkoeY6dEyeJAkIDJbda3n0I71KwRR2J0CSN3TF+w1hSQa7Hp1rXw\n+zQvR6p7O2VY8zQeZZKRKGl7OGdKW5F79iz2fQIDAQABAoIBAEN0BaRGciI0VY2H\n0CdY1X1uDIBke9lSIpvIhZlfxYJ4hFxS2CtiSo4qJGX8HbgElVNaI17rR0P3R6+F\njoG43OCA7/euZEcTL6ZYD5kw7q16RWYfNSc36A+cNXZm4sAhko9LFeQ4FmcNaQ9V\nUXEToe4p6+zUN3Y0DEJezzSXJvjjjodT5L03i2HCW+/xZIHi6oh1DuXdy7h1Ah8s\nSxN188HsX7/SoDHAxDqi/SSGyoYg/SvtOetPtrcZCfqoHfxkR+jQHNaOTq3vGmsu\np8KPtRBoFvSPMxSSHNLb4qbIFvlWRLNXfIhYnenTPtmCnnqogotZZ9CoCHL9dX5R\nt4q5L6ECgYEA5jYhqpRIhqSZOTJopGgy3LBy5T1PHDTfedTuSxnoywYWCuGNwgjI\nRgd94jcUuizO9euobxvDUTdOZ6LdK1NStfwOspb2NojvlE+9SfC8JDv7ZeRz8egB\nClrT6jtCUr80K1I0eF31ha0YMjgi7WZJvTMp53fqI0b1yQO2FaBNgWUCgYEAzGT6\nay+QlO2Fdt9mqeIJy9QiugItC7lk75fQMg5fa8A8wj9DO86o/2k4rKhl7SPg0H+R\nSJQoZGuS4M2f9muEHnLmVF8EzizuHZoR3HO4mie2adVf9NfAmkFsCluRAZKtQkNc\nt/VwlJEC6dChoZkU8Wzd0fSJKrdhjik2ayGXmzkCgYEAuie9s5UyzIXfTSwhCAkm\nT+TzE8Iu7Y0nxPnVM6+g2kNyoZvgqK23XUGDnuCRhzbiqGPGkQovN8Z0RUOiev1m\n3bgUHoAKWvECYrjURS1AxkAmuy8wPsYvyTLHOBpxOD5bLkjMGyVHe7AL59gTDktv\nh2oPEZibIamo6MJyhCxbYC0CgYAIZhnYL7MsO3phgRqR3oTyiDwJEq/RLIQWSFG4\nzNhk8BhPDxRvL7XIEQXQKndNwEyrpKJOri/euIDnlet9z7s1GRmX2/OxmS0LsFoN\nif/K7djUDn2L7RWwAQI0hsC1pNZTw7raoE5I/JB3FSifIFA4/3U5/GdqhvCOS+k9\ni7rUGQKBgQDPspapfGj2ozgWChJ2xMTGBhJhynM81w3j9w7MLvO/7/U43zYzKzyc\n7YJzApQOSwX/nLdquzi+UIbvuCB3npZVZl52S4f7BBcgLNQpdmcfWrAbDv5lySfn\n/KTN22Wxmhh20QgiNSxj+o+KIgdAgZCgWt7NrkZ5UX7Lo+ZfYU1xbg==\n-----END RSA PRIVATE KEY-----"; - } - - async sign(data: string) { - const { KJUR, KEYUTIL, hextob64 } = await import("jsrsasign"); - const privateKey = KEYUTIL.getKey(this.privateKeyPem); - // 创建签名实例 - const signature = new KJUR.crypto.Signature({ - alg: "SHA256withRSA", - }); - - // 初始化私钥 - signature.init(privateKey); - - // 更新待签名数据(假设原文是字符串) - signature.updateString(data); - - // 生成签名(默认返回十六进制字符串) - const hexSignature = signature.sign(); - - // 转换为 Base64(假设 Ix 是 Base64 编码) - return hextob64(hexSignature); - } - - async doRequest(req: HttpRequestConfig) { - const timestamp = Date.now(); - - let data = ""; - if (req.method.toLowerCase() === "get") { - // area_codes=&channel_type=0,1,2&domain_name=&https_status=&nonce=1747242446238&order=&page=1&page_size=10&status=×tamp=1747242446238 - let queryList = []; - for (const key in req.params) { - queryList.push(`${key}=${req.params[key]}`); - } - queryList.push(`nonce=${timestamp}`); - queryList.push(`timestamp=${timestamp}`); - //sort - queryList = queryList.sort(); - data = queryList.join("&"); - } else { - data = `body=${JSON.stringify(req.data || {})}&nonce=${timestamp}×tamp=${timestamp}`; - } - const sign = await this.sign(data); - const headers: any = { - sign: sign, - timestamp: timestamp, - nonce: timestamp, - }; - - if (this.token) { - headers.Token = this.token; - } - - const res = await this.http.request({ - ...req, - headers, - baseURL: "https://testaa.5678.jp", - }); - - if (!res.success && res.code !== 200) { - throw new Error(`请求失败:${res.msg}`); - } - return res.data; - } - - async login() { - const req = { - email: this.access.username, - password: this.access.password, - accountType: 1, - }; - const res = await this.doRequest({ - url: "/api/vcloud/v1/userApi/noAuth/login", - method: "post", - data: req, - logRes: false, - logParams: false, - }); - const { token } = res; - this.logger.info(`登录成功`); - this.token = token; - } -} diff --git a/packages/ui/certd-server/src/plugins/plugin-plus/maoyun/index.ts b/packages/ui/certd-server/src/plugins/plugin-plus/maoyun/index.ts index b9436b7da..9e832e961 100644 --- a/packages/ui/certd-server/src/plugins/plugin-plus/maoyun/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-plus/maoyun/index.ts @@ -1,4 +1,3 @@ // 隐藏 通过下载插件形式分发 // export * from "./plugins/index.js"; export * from "./access.js"; -export * from "./client.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-plus/maoyun/plugins/plugin-deploy-to-cdn.ts b/packages/ui/certd-server/src/plugins/plugin-plus/maoyun/plugins/plugin-deploy-to-cdn.ts index 20bf46a41..4039a710e 100644 --- a/packages/ui/certd-server/src/plugins/plugin-plus/maoyun/plugins/plugin-deploy-to-cdn.ts +++ b/packages/ui/certd-server/src/plugins/plugin-plus/maoyun/plugins/plugin-deploy-to-cdn.ts @@ -3,7 +3,7 @@ import { CertApplyPluginNames, CertInfo } from "@certd/plugin-cert"; import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from "@certd/plugin-lib"; import { AbstractPlusTaskPlugin } from "@certd/plugin-plus"; import { MaoyunAccess } from "../access.js"; -import { MaoyunClient } from "../client.js"; +import { MaoyunClient } from "@certd/plugin-plus"; @IsTaskPlugin({ //命名规范,插件类型+功能(就是目录plugin-demo中的demo),大写字母开头,驼峰命名 diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2d228e1a3..d599bc5d5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -885,6 +885,9 @@ importers: form-data: specifier: ^4.0.0 version: 4.0.2 + jsrsasign: + specifier: ^11.1.0 + version: 11.1.0 querystring: specifier: ^0.2.1 version: 0.2.1