diff --git a/packages/ui/certd-client/src/locales/langs/en-US/certd/mine.ts b/packages/ui/certd-client/src/locales/langs/en-US/certd/mine.ts index a66719dc0..31afc672d 100644 --- a/packages/ui/certd-client/src/locales/langs/en-US/certd/mine.ts +++ b/packages/ui/certd-client/src/locales/langs/en-US/certd/mine.ts @@ -13,14 +13,14 @@ export default { inputVerifyCode: "Please enter the verification code", myInfo: "My Information", user: { - greeting: "Hello", - profile: "Account Info", - logout: "Logout", - setting: { - grantSetting: "Grant Settings", - saveSuccess: "Save Success", - allowAdminViewCerts: "Allow Admin view and download Certs", - allowAdminViewCertsHelper: "Allow admin view and download all certificates", - }, - }, + greeting: "Hello", + profile: "Account Info", + logout: "Logout", + setting: { + grantSetting: "Grant Settings", + saveSuccess: "Save Success", + allowAdminViewCerts: "Allow Admin view and download Certs", + allowAdminViewCertsHelper: "Allow admin view and download all certificates", + }, + }, }; diff --git a/packages/ui/certd-server/app.js b/packages/ui/certd-server/app.js index 060add6d9..23173f248 100644 --- a/packages/ui/certd-server/app.js +++ b/packages/ui/certd-server/app.js @@ -1,8 +1,8 @@ // 获取框架 -const WebFramework = require('@midwayjs/koa').Framework; -const { Bootstrap } = require('@midwayjs/bootstrap'); +const WebFramework = require("@midwayjs/koa").Framework; +const { Bootstrap } = require("@midwayjs/bootstrap"); -const DirectoryFileDetector = require('@midwayjs/core').DirectoryFileDetector; +const DirectoryFileDetector = require("@midwayjs/core").DirectoryFileDetector; const baseDir = process.cwd(); const customFileDetector = new DirectoryFileDetector({ @@ -12,7 +12,7 @@ const customFileDetector = new DirectoryFileDetector({ module.exports = async () => { // 加载框架并执行 await Bootstrap.configure({ - ignore: ["**/plugins/**","/plugins/","plugins","dist/plugins","/dist/plugins","dist\\plugins","dist/plugins"], + ignore: ["**/plugins/**", "/plugins/", "plugins", "dist/plugins", "/dist/plugins", "dist\\plugins", "dist/plugins"], moduleDetector: customFileDetector, }).run(); // 获取依赖注入容器 diff --git a/packages/ui/certd-server/before-build.js b/packages/ui/certd-server/before-build.js index 4632200ff..dde8c87b0 100644 --- a/packages/ui/certd-server/before-build.js +++ b/packages/ui/certd-server/before-build.js @@ -1,22 +1,22 @@ -import fs from 'fs'; +import fs from "fs"; //瘦身 -const filePath = './node_modules/typeorm/platform/PlatformTools.js'; +const filePath = "./node_modules/typeorm/platform/PlatformTools.js"; const find = `const cli_highlight_1 = require("cli-highlight");`; -const rep = 'const cli_highlight_1 ={highlight: (str) => { return str }};'; +const rep = "const cli_highlight_1 ={highlight: (str) => { return str }};"; // 在 filePath 找到 find那一行 用 rep 替换 function slimming(filePath, find, rep) { - fs.readFile(filePath, 'utf8', function (err, data) { + fs.readFile(filePath, "utf8", function (err, data) { if (err) { return console.log(err); } var result = data.replace(find, rep); - fs.writeFile(filePath, result, 'utf8', function (err) { + fs.writeFile(filePath, result, "utf8", function (err) { if (err) return console.log(err); }); }); } slimming(filePath, find, rep); -slimming("./tsconfig.json",`"sourceMap": true,`, `"sourceMap": false,`) -slimming("./tsconfig.json",`"inlineSourceMap": true,`, `"inlineSourceMap": false,`) +slimming("./tsconfig.json", `"sourceMap": true,`, `"sourceMap": false,`); +slimming("./tsconfig.json", `"inlineSourceMap": true,`, `"inlineSourceMap": false,`); diff --git a/packages/ui/certd-server/bootstrap.js b/packages/ui/certd-server/bootstrap.js index 6abeb8f23..6cdd899aa 100644 --- a/packages/ui/certd-server/bootstrap.js +++ b/packages/ui/certd-server/bootstrap.js @@ -1,4 +1,4 @@ -import { Bootstrap } from '@midwayjs/bootstrap'; +import { Bootstrap } from "@midwayjs/bootstrap"; await Bootstrap.configure({ - ignore: ["**/plugins/**","/plugins/","plugins","dist/plugins","/dist/plugins","dist\\plugins"] - }).run(); + ignore: ["**/plugins/**", "/plugins/", "plugins", "dist/plugins", "/dist/plugins", "dist\\plugins"], +}).run(); diff --git a/packages/ui/certd-server/db/transform.js b/packages/ui/certd-server/db/transform.js index 4e6aa799a..606529c9d 100644 --- a/packages/ui/certd-server/db/transform.js +++ b/packages/ui/certd-server/db/transform.js @@ -1,4 +1,4 @@ -import fs from 'fs'; +import fs from "fs"; /** * ## sqlite与postgres不同点 * 1. @@ -27,56 +27,55 @@ import fs from 'fs'; */ function transformPG() { // 读取文件列表 - const sqliteFiles = fs.readdirSync('./migration/'); - const pgFiles = fs.readdirSync('./migration-pg/'); + const sqliteFiles = fs.readdirSync("./migration/"); + const pgFiles = fs.readdirSync("./migration-pg/"); //找出pg里面没有的文件 const notFiles = sqliteFiles.filter(file => !pgFiles.includes(file)); for (const notFile of notFiles) { //开始转换 - const sqliteSql = fs.readFileSync(`./migration/${notFile}`, 'utf-8'); - let pgSql = sqliteSql.replaceAll(/AUTOINCREMENT/g, 'GENERATED BY DEFAULT AS IDENTITY'); - pgSql = pgSql.replaceAll(/datetime/g, 'timestamp'); - pgSql = pgSql.replaceAll(/boolean DEFAULT \(0\)/g, 'boolean DEFAULT (false)'); - pgSql = pgSql.replaceAll(/boolean DEFAULT \(1\)/g, 'boolean DEFAULT (true)'); - pgSql = pgSql.replaceAll(/boolean.*NOT NULL DEFAULT \(0\)/g, 'boolean NOT NULL DEFAULT (false)'); - pgSql = pgSql.replaceAll(/boolean.*NOT NULL DEFAULT \(1\)/g, 'boolean NOT NULL DEFAULT (true)'); - pgSql = pgSql.replaceAll(/integer/g, 'bigint'); - pgSql = pgSql.replaceAll(/INTEGER/g, 'bigint'); - pgSql = pgSql.replaceAll(/last_insert_rowid\(\)/g, 'LASTVAL()'); + const sqliteSql = fs.readFileSync(`./migration/${notFile}`, "utf-8"); + let pgSql = sqliteSql.replaceAll(/AUTOINCREMENT/g, "GENERATED BY DEFAULT AS IDENTITY"); + pgSql = pgSql.replaceAll(/datetime/g, "timestamp"); + pgSql = pgSql.replaceAll(/boolean DEFAULT \(0\)/g, "boolean DEFAULT (false)"); + pgSql = pgSql.replaceAll(/boolean DEFAULT \(1\)/g, "boolean DEFAULT (true)"); + pgSql = pgSql.replaceAll(/boolean.*NOT NULL DEFAULT \(0\)/g, "boolean NOT NULL DEFAULT (false)"); + pgSql = pgSql.replaceAll(/boolean.*NOT NULL DEFAULT \(1\)/g, "boolean NOT NULL DEFAULT (true)"); + pgSql = pgSql.replaceAll(/integer/g, "bigint"); + pgSql = pgSql.replaceAll(/INTEGER/g, "bigint"); + pgSql = pgSql.replaceAll(/last_insert_rowid\(\)/g, "LASTVAL()"); fs.writeFileSync(`./migration-pg/${notFile}`, pgSql); } if (notFiles.length > 0) { - console.log('sqlite->pg 转换完成'); + console.log("sqlite->pg 转换完成"); - throw new Error('sqlite->pg 转换完成,有更新,需要测试pg'); + throw new Error("sqlite->pg 转换完成,有更新,需要测试pg"); } else { - console.log('sql无需更新'); + console.log("sql无需更新"); } } function transformMysql() { // 读取文件列表 - const sqliteFiles = fs.readdirSync('./migration/'); - const pgFiles = fs.readdirSync('./migration-mysql/'); + const sqliteFiles = fs.readdirSync("./migration/"); + const pgFiles = fs.readdirSync("./migration-mysql/"); //找出pg里面没有的文件 const notFiles = sqliteFiles.filter(file => !pgFiles.includes(file)); for (const notFile of notFiles) { //开始转换 - const sqliteSql = fs.readFileSync(`./migration/${notFile}`, 'utf-8'); - let pgSql = sqliteSql.replaceAll(/AUTOINCREMENT/g, 'AUTO_INCREMENT'); - pgSql = pgSql.replaceAll(/datetime/g, 'timestamp'); + const sqliteSql = fs.readFileSync(`./migration/${notFile}`, "utf-8"); + let pgSql = sqliteSql.replaceAll(/AUTOINCREMENT/g, "AUTO_INCREMENT"); + pgSql = pgSql.replaceAll(/datetime/g, "timestamp"); //DEFAULT (xxx) 替换成 DEFAULT xxx - pgSql = pgSql.replaceAll(/DEFAULT \(([^)]*)\)/g, 'DEFAULT $1'); - pgSql = pgSql.replaceAll(/integer/g, 'bigint'); - pgSql = pgSql.replaceAll(/INTEGER/g, 'bigint'); - pgSql = pgSql.replaceAll(/last_insert_rowid\(\)/g, 'LAST_INSERT_ID()'); + pgSql = pgSql.replaceAll(/DEFAULT \(([^)]*)\)/g, "DEFAULT $1"); + pgSql = pgSql.replaceAll(/integer/g, "bigint"); + pgSql = pgSql.replaceAll(/INTEGER/g, "bigint"); + pgSql = pgSql.replaceAll(/last_insert_rowid\(\)/g, "LAST_INSERT_ID()"); //text 改成longtext - pgSql = pgSql.replaceAll(/text/g, 'longtext'); + pgSql = pgSql.replaceAll(/text/g, "longtext"); //双引号 替换成反引号 - pgSql = pgSql.replaceAll(/"/g, '`'); + pgSql = pgSql.replaceAll(/"/g, "`"); - //提取所有的 create table 的表格name const tableNames = pgSql.match(/CREATE TABLE `([^`]*)`/g); if (tableNames && tableNames.length > 0) { @@ -88,21 +87,19 @@ CREATE TABLE `cd_audit_log` */ //提取表名 const tableName = item.match(/`([^`]*)`/)[1]; - pgSql += `\nALTER TABLE \`${tableName}\` ENGINE = InnoDB;` + pgSql += `\nALTER TABLE \`${tableName}\` ENGINE = InnoDB;`; } } - - fs.writeFileSync(`./migration-mysql/${notFile}`, pgSql); } if (notFiles.length > 0) { - console.log('sqlite->mysql 转换完成'); + console.log("sqlite->mysql 转换完成"); - throw new Error('sqlite->mysql 转换完成,有更新,需要测试mysql'); + throw new Error("sqlite->mysql 转换完成,有更新,需要测试mysql"); } else { - console.log('sql无需更新'); + console.log("sql无需更新"); } } diff --git a/packages/ui/certd-server/export-plugin-yaml.js b/packages/ui/certd-server/export-plugin-yaml.js index eeca20c7a..9b1f38254 100644 --- a/packages/ui/certd-server/export-plugin-yaml.js +++ b/packages/ui/certd-server/export-plugin-yaml.js @@ -4,17 +4,16 @@ import path, { join } from "path"; import fs from "fs"; import { pathToFileURL } from "node:url"; import * as yaml from "js-yaml"; -import { AbstractTaskPlugin, BaseAccess, BaseNotification} from "@certd/pipeline"; -import { BaseAddon} from "@certd/lib-server"; +import { AbstractTaskPlugin, BaseAccess, BaseNotification } from "@certd/pipeline"; +import { BaseAddon } from "@certd/lib-server"; import { dnsProviderRegistry } from "@certd/plugin-cert"; -import { pluginRegistry ,accessRegistry,notificationRegistry,pluginGroups} from "@certd/pipeline"; +import { pluginRegistry, accessRegistry, notificationRegistry, pluginGroups } from "@certd/pipeline"; function scanDir(dir) { const files = fs.readdirSync(dir); const result = []; // 扫描目录及子目录 for (const file of files) { - const filePath = join(dir, file); const stat = fs.statSync(filePath); if (stat.isDirectory()) { @@ -26,111 +25,110 @@ function scanDir(dir) { result.push(filePath); } } - return result + return result; } export default async function loadModules(dir) { const files = scanDir(dir); - const modules = {} + const modules = {}; for (const file of files) { - if(file === "dist/plugins/index.js" || file === "dist\\plugins\\index.js"){ - continue + if (file === "dist/plugins/index.js" || file === "dist\\plugins\\index.js") { + continue; } - const content = fs.readFileSync(file, 'utf8') - if(content.includes(" abstract ")){ - continue + const content = fs.readFileSync(file, "utf8"); + if (content.includes(" abstract ")) { + continue; } - const lines = content.split('\n') - let allExport = true + const lines = content.split("\n"); + let allExport = true; for (let line of lines) { - line = line.trim() + line = line.trim(); if (!line || line.startsWith("//")) { - continue + continue; } - if(!line.startsWith("export ")){ - allExport = false - break + if (!line.startsWith("export ")) { + allExport = false; + break; } } if (allExport) { - continue + continue; } try { // 转换为 file:// URL(Windows 必需) - const moduleUrl = pathToFileURL(file).href - const module = await import(moduleUrl) + const moduleUrl = pathToFileURL(file).href; + const module = await import(moduleUrl); // 如果模块有默认导出,优先使用 - modules[file] = module.default || module + modules[file] = module.default || module; } catch (err) { - console.error(`加载模块 ${file} 失败:`, err) + console.error(`加载模块 ${file} 失败:`, err); } } return modules; } -function isPrototypeOf(value,cls){ - return cls.prototype.isPrototypeOf(value.prototype) +function isPrototypeOf(value, cls) { + return cls.prototype.isPrototypeOf(value.prototype); } -async function genMetadata(){ - const modules = await loadModules('./dist/plugins'); +async function genMetadata() { + const modules = await loadModules("./dist/plugins"); fs.rmSync("./metadata", { recursive: true }); fs.mkdirSync("./metadata", { recursive: true }); for (const key in modules) { - const module = modules[key] - const entry = Object.entries(module) - if (entry.length >1) { - console.log(`[warning] 文件 ${key} 导出了 ${entry.length} 个对象: ${entry.map(([name, value]) => name).join(", ")}`) + const module = modules[key]; + const entry = Object.entries(module); + if (entry.length > 1) { + console.log(`[warning] 文件 ${key} 导出了 ${entry.length} 个对象: ${entry.map(([name, value]) => name).join(", ")}`); } for (const [name, value] of entry) { //如果有define属性 - if(value.define){ + if (value.define) { //那么就是插件 - let location = key.substring(4) - location = location.substring(0, location.length - 3) - location = location.replaceAll("\\","/") - location += ".js" - location = `${location}` // 从modules/plugin/plugin-service 加载 ../../plugins目录下的文件 + let location = key.substring(4); + location = location.substring(0, location.length - 3); + location = location.replaceAll("\\", "/"); + location += ".js"; + location = `${location}`; // 从modules/plugin/plugin-service 加载 ../../plugins目录下的文件 const pluginDefine = { - ...value.define + ...value.define, + }; + let subType = ""; + if (pluginDefine.accessType) { + pluginDefine.pluginType = "dnsProvider"; + } else if (isPrototypeOf(value, AbstractTaskPlugin)) { + pluginDefine.pluginType = "deploy"; + } else if (isPrototypeOf(value, BaseNotification)) { + pluginDefine.pluginType = "notification"; + } else if (isPrototypeOf(value, BaseAccess)) { + pluginDefine.pluginType = "access"; + } else if (isPrototypeOf(value, BaseAddon)) { + pluginDefine.pluginType = "addon"; + subType = "_" + pluginDefine.addonType; + } else { + console.log(`[warning] 未知的插件类型:${pluginDefine.name}`); } - let subType = "" - if(pluginDefine.accessType){ - pluginDefine.pluginType = "dnsProvider" - }else if(isPrototypeOf(value,AbstractTaskPlugin)){ - pluginDefine.pluginType = "deploy" - }else if(isPrototypeOf(value,BaseNotification)){ - pluginDefine.pluginType = "notification" - }else if(isPrototypeOf(value,BaseAccess)){ - pluginDefine.pluginType = "access" - }else if(isPrototypeOf(value,BaseAddon)){ - pluginDefine.pluginType = "addon" - subType = "_"+pluginDefine.addonType - }else{ - console.log(`[warning] 未知的插件类型:${pluginDefine.name}`) - } - pluginDefine.type = "builtIn" - - const filePath = path.join(`./metadata/${pluginDefine.pluginType}${subType}_${pluginDefine.name}.yaml`) + pluginDefine.type = "builtIn"; - pluginDefine.scriptFilePath = location - console.log(location) - const data = yaml.dump(pluginDefine) - fs.writeFileSync(filePath,data ,'utf8') + const filePath = path.join(`./metadata/${pluginDefine.pluginType}${subType}_${pluginDefine.name}.yaml`); + + pluginDefine.scriptFilePath = location; + console.log(location); + const data = yaml.dump(pluginDefine); + fs.writeFileSync(filePath, data, "utf8"); } } } } - async function genPluginMd() { const plugins = { access: [], deploy: [], dnsProvider: [], - notification: [] + notification: [], }; plugins.access = accessRegistry.getDefineList(); @@ -138,24 +136,23 @@ async function genPluginMd() { plugins.dnsProvider = dnsProviderRegistry.getDefineList(); plugins.notification = notificationRegistry.getDefineList(); - -// function genMd(list) { -// let mdContent = ` -// -// -// -// -// -// -// `; -// let i = 0; -// for (const x of list) { -// i++ -// mdContent += ``; -// } -// mdContent += `
序号名称说明
${i}. ${x.title} ${x.desc||''}
`; -// return mdContent; -// } + // function genMd(list) { + // let mdContent = ` + // + // + // + // + // + // + // `; + // let i = 0; + // for (const x of list) { + // i++ + // mdContent += ``; + // } + // mdContent += `
序号名称说明
${i}. ${x.title} ${x.desc||''}
`; + // return mdContent; + // } // function genMd(list) { // let mdContent = ``; @@ -174,14 +171,14 @@ async function genPluginMd() { `; let i = 0; for (const x of list) { - i++ - const desc = x.desc||'' - mdContent += `| ${i}.| **${x.title}** | ${desc.replaceAll("\n"," ")} | \n`; + i++; + const desc = x.desc || ""; + mdContent += `| ${i}.| **${x.title}** | ${desc.replaceAll("\n", " ")} | \n`; } return mdContent; } - function addTableStyle(){ + function addTableStyle() { return ` - ` + `; } let mdContent = ""; mdContent = "# 授权列表\n"; mdContent += genMd(plugins.access); - mdContent += addTableStyle() + mdContent += addTableStyle(); fs.writeFileSync("../../../docs/guide/plugins/access.md", mdContent); mdContent = "# DNS提供商\n"; mdContent += genMd(plugins.dnsProvider); - mdContent += addTableStyle() + mdContent += addTableStyle(); fs.writeFileSync("../../../docs/guide/plugins/dns-provider.md", mdContent); - mdContent = "# 通知插件\n"; mdContent += genMd(plugins.notification); - mdContent += addTableStyle() + mdContent += addTableStyle(); fs.writeFileSync("../../../docs/guide/plugins/notification.md", mdContent); - mdContent = "# 任务插件\n"; - mdContent += `共 \`${plugins.deploy.length}\` 款任务插件 \n` - let index =0 + mdContent += `共 \`${plugins.deploy.length}\` 款任务插件 \n`; + let index = 0; for (const key in pluginGroups) { - index++ + index++; const group = pluginGroups[key]; mdContent += `## ${index}. ${group.title}\n`; mdContent += genMd(group.plugins); } - mdContent += addTableStyle() + mdContent += addTableStyle(); fs.writeFileSync("../../../docs/guide/plugins/deploy.md", mdContent); - } - - // import why from 'why-is-node-running' // setTimeout(() => why(), 100); // 延迟打印原因 -async function main(){ - await genMetadata() - console.log("genMetadata success") +async function main() { + await genMetadata(); + console.log("genMetadata success"); // 获取args genmd - const args = process.argv.slice(2) - if(!args.includes("docoff")){ - await genPluginMd() - console.log("genPluginMd success") + const args = process.argv.slice(2); + if (!args.includes("docoff")) { + await genPluginMd(); + console.log("genPluginMd success"); } - process.exit() + process.exit(); } - -main() - +main(); diff --git a/packages/ui/certd-server/jest.config.js b/packages/ui/certd-server/jest.config.js index c5bd388a7..b118c449c 100644 --- a/packages/ui/certd-server/jest.config.js +++ b/packages/ui/certd-server/jest.config.js @@ -1,6 +1,6 @@ module.exports = { - preset: 'ts-jest', - testEnvironment: 'node', - testPathIgnorePatterns: ['/test/fixtures'], - coveragePathIgnorePatterns: ['/test/'], -}; \ No newline at end of file + preset: "ts-jest", + testEnvironment: "node", + testPathIgnorePatterns: ["/test/fixtures"], + coveragePathIgnorePatterns: ["/test/"], +}; diff --git a/packages/ui/certd-server/src/config/config.default.ts b/packages/ui/certd-server/src/config/config.default.ts index c75db5614..192a42b3c 100644 --- a/packages/ui/certd-server/src/config/config.default.ts +++ b/packages/ui/certd-server/src/config/config.default.ts @@ -1,32 +1,32 @@ -import { MidwayConfig } from '@midwayjs/core'; +import { MidwayConfig } from "@midwayjs/core"; // import { join } from 'path'; // import { dirname } from 'node:path'; // import { fileURLToPath } from 'node:url'; // // const __filename = fileURLToPath(import.meta.url); // const __dirname = dirname(fileURLToPath(import.meta.url)); -import { FlywayHistory, setFlywayLogger } from '@certd/midway-flyway-js'; -import { UserEntity } from '../modules/sys/authority/entity/user.js'; -import { PipelineEntity } from '../modules/pipeline/entity/pipeline.js'; +import { FlywayHistory, setFlywayLogger } from "@certd/midway-flyway-js"; +import { UserEntity } from "../modules/sys/authority/entity/user.js"; +import { PipelineEntity } from "../modules/pipeline/entity/pipeline.js"; //import { logger } from '../utils/logger'; // load .env file in process.cwd -import { loadDotEnv, mergeConfig } from './loader.js'; -import { libServerEntities } from '@certd/lib-server'; -import { commercialEntities } from '@certd/commercial-core'; -import { tmpdir } from 'node:os'; -import { DefaultUploadFileMimeType, uploadWhiteList } from '@midwayjs/upload'; -import path from 'path'; -import { logger } from '@certd/basic'; +import { loadDotEnv, mergeConfig } from "./loader.js"; +import { libServerEntities } from "@certd/lib-server"; +import { commercialEntities } from "@certd/commercial-core"; +import { tmpdir } from "node:os"; +import { DefaultUploadFileMimeType, uploadWhiteList } from "@midwayjs/upload"; +import path from "path"; +import { logger } from "@certd/basic"; -const env = process.env.NODE_ENV || 'development'; +const env = process.env.NODE_ENV || "development"; const development = { midwayLogger: { default: { - dir: './logs', + dir: "./logs", }, // ... }, - keys: 'certd', + keys: "certd", koa: { hostname: "::", port: 7001, @@ -34,8 +34,8 @@ const development = { https: { enabled: true, port: 7002, - key: './data/ssl/cert.key', - cert: './data/ssl/cert.crt', + key: "./data/ssl/cert.key", + cert: "./data/ssl/cert.crt", }, staticFile: { usePrecompiledGzip: true, @@ -44,11 +44,11 @@ const development = { gzip: true, dirs: { default: { - prefix: '/', - dir: 'public', + prefix: "/", + dir: "public", alias: { - '/': '/index.html', - '\\': '/index.html', + "/": "/index.html", + "\\": "/index.html", }, maxFiles: 200, }, @@ -77,14 +77,14 @@ const development = { /** * 单数据库实例 */ - type: 'better-sqlite3', - database: './data/db.sqlite', + type: "better-sqlite3", + database: "./data/db.sqlite", synchronize: false, // 如果第一次使用,不存在表,有同步的需求可以写 true logging: false, highlightSql: false, // 配置实体模型 或者 entities: '/entity', - entities: ['**/modules/**/entity/*.js', ...libServerEntities, ...commercialEntities, PipelineEntity, FlywayHistory, UserEntity], + entities: ["**/modules/**/entity/*.js", ...libServerEntities, ...commercialEntities, PipelineEntity, FlywayHistory, UserEntity], }, }, }, @@ -92,7 +92,7 @@ const development = { * 自动升级数据库脚本 */ flyway: { - scriptDir: './db/migration', + scriptDir: "./db/migration", }, auth: { @@ -101,24 +101,24 @@ const development = { }, }, certd: { - fileRootDir: './data/files', + fileRootDir: "./data/files", }, system: { resetAdminPasswd: false, }, plus: { - serverBaseUrls: ['http://127.0.0.1:11007'], + serverBaseUrls: ["http://127.0.0.1:11007"], }, upload: { // mode: UploadMode, 默认为file,即上传到服务器临时目录,可以配置为 stream - mode: 'file', + mode: "file", // fileSize: string, 最大上传文件大小,默认为 10mb - fileSize: '10mb', + fileSize: "10mb", whitelist: uploadWhiteList, //文件扩展名白名单 mimeTypeWhiteList: DefaultUploadFileMimeType, //文件MIME类型白名单 // whitelist: uploadWhiteList.filter(ext => ext !== '.pdf'), // tmpdir: string,上传的文件临时存储路径 - tmpdir: path.join(tmpdir(), 'certd-upload-files'), + tmpdir: path.join(tmpdir(), "certd-upload-files"), // cleanTimeout: number,上传的文件在临时目录中多久之后自动删除,默认为 5 分钟 cleanTimeout: 5 * 60 * 1000, // base64: boolean,设置原始body是否是base64格式,默认为false,一般用于腾讯云的兼容 @@ -128,113 +128,113 @@ const development = { }, agent: { enabled: false, - contactText: '', - contactLink: '', + contactText: "", + contactLink: "", }, swagger: { isGenerateTagForController: false, routerFilter: (url: string) => { - return url.startsWith('/api/sys'); + return url.startsWith("/api/sys"); }, tags: [ { - name: 'addon', - description: '插件管理' + name: "addon", + description: "插件管理", }, { - name: 'basic-group', - description: '基础分组管理' + name: "basic-group", + description: "基础分组管理", }, { - name: 'basic-user', - description: '基础用户管理' + name: "basic-user", + description: "基础用户管理", }, { - name: 'cert', - description: '证书管理' + name: "cert", + description: "证书管理", }, { - name: 'pipeline-cname', - description: 'CNAME配置管理' + name: "pipeline-cname", + description: "CNAME配置管理", }, { - name: 'dashboard', - description: '仪表板统计' + name: "dashboard", + description: "仪表板统计", }, { - name: 'enterprise-project', - description: '企业项目管理' + name: "enterprise-project", + description: "企业项目管理", }, { - name: 'enterprise-project-member', - description: '企业项目成员管理' + name: "enterprise-project-member", + description: "企业项目成员管理", }, { - name: 'mine', - description: '个人中心' + name: "mine", + description: "个人中心", }, { - name: 'monitor', - description: '监控管理' + name: "monitor", + description: "监控管理", }, { - name: 'open', - description: '开放API KEY管理' + name: "open", + description: "开放API KEY管理", }, { - name: 'pipeline-access', - description: '流水线授权配置' + name: "pipeline-access", + description: "流水线授权配置", }, { - name: 'pipeline-cert', - description: '流水线证书' + name: "pipeline-cert", + description: "流水线证书", }, { - name: 'pipeline-dns-provider', - description: '流水线DNS提供商' + name: "pipeline-dns-provider", + description: "流水线DNS提供商", }, { - name: 'pipeline-handle', - description: '插件请求处理' + name: "pipeline-handle", + description: "插件请求处理", }, { - name: 'pipeline-history', - description: '流水线执行历史' + name: "pipeline-history", + description: "流水线执行历史", }, { - name: 'pipeline-notification', - description: '流水线通知配置' + name: "pipeline-notification", + description: "流水线通知配置", }, { - name: 'pipeline-plugin', - description: '流水线插件' + name: "pipeline-plugin", + description: "流水线插件", }, { - name: 'pipeline-subdomain', - description: '流水线子域名' + name: "pipeline-subdomain", + description: "流水线子域名", }, { - name: 'pipeline-template', - description: '流水线模版' + name: "pipeline-template", + description: "流水线模版", }, { - name: 'pipeline-group', - description: '流水线分组' + name: "pipeline-group", + description: "流水线分组", }, { - name: 'pipeline', - description: '流水线管理' + name: "pipeline", + description: "流水线管理", }, { - name: 'openapi', - description: '开放API' + name: "openapi", + description: "开放API", }, - ] - } + ], + }, } as MidwayConfig; loadDotEnv(); -mergeConfig(development, 'development'); +mergeConfig(development, "development"); mergeConfig(development, env); diff --git a/packages/ui/certd-server/src/config/loader.ts b/packages/ui/certd-server/src/config/loader.ts index 97052b09b..915b1f7a4 100644 --- a/packages/ui/certd-server/src/config/loader.ts +++ b/packages/ui/certd-server/src/config/loader.ts @@ -1,25 +1,25 @@ -import path from 'path'; -import * as _ from 'lodash-es'; -import yaml from 'js-yaml'; -import fs from 'fs'; -import { logger } from '@certd/basic'; +import path from "path"; +import * as _ from "lodash-es"; +import yaml from "js-yaml"; +import fs from "fs"; +import { logger } from "@certd/basic"; function parseEnv(defaultConfig: any) { const config = {}; for (const key in process.env) { let keyName = key; - if (!keyName.startsWith('certd_')) { + if (!keyName.startsWith("certd_")) { continue; } - keyName = keyName.replace('certd_', ''); - const configKey = keyName.replaceAll('_', '.'); + keyName = keyName.replace("certd_", ""); + const configKey = keyName.replaceAll("_", "."); const oldValue = _.get(defaultConfig, configKey); let value: any = process.env[key]; - if (typeof oldValue === 'boolean') { - value = value === 'true'; + if (typeof oldValue === "boolean") { + value = value === "true"; } else if (Number.isInteger(oldValue)) { value = parseInt(value, 10); - } else if (typeof oldValue === 'number') { + } else if (typeof oldValue === "number") { value = parseFloat(value); } _.set(config, configKey, value); @@ -27,12 +27,12 @@ function parseEnv(defaultConfig: any) { return config; } -export function load(config, env = '') { +export function load(config, env = "") { // Get document, or throw exception on error - logger.info('load config', env); + logger.info("load config", env); const yamlPath = path.join(process.cwd(), `.env.${env}.yaml`); if (fs.existsSync(yamlPath)) { - const doc = yaml.load(fs.readFileSync(yamlPath, 'utf8')); + const doc = yaml.load(fs.readFileSync(yamlPath, "utf8")); return _.merge(doc, parseEnv(config)); } return parseEnv(config); @@ -40,7 +40,7 @@ export function load(config, env = '') { export function mergeConfig(config: any, envType: string) { _.merge(config, load(config, envType)); - const keys = _.get(config, 'auth.jwt.secret'); + const keys = _.get(config, "auth.jwt.secret"); if (keys) { config.keys = keys; } @@ -48,9 +48,9 @@ export function mergeConfig(config: any, envType: string) { } export function loadDotEnv() { - const envStr = fs.readFileSync('.env').toString(); - envStr.split('\n').forEach(line => { - const [key, value] = line.trim().split('='); + const envStr = fs.readFileSync(".env").toString(); + envStr.split("\n").forEach(line => { + const [key, value] = line.trim().split("="); const oldValue = process.env[key]; if (!oldValue) { process.env[key] = value; diff --git a/packages/ui/certd-server/src/configuration-cache.ts b/packages/ui/certd-server/src/configuration-cache.ts index 7788bd7a8..e447213ad 100644 --- a/packages/ui/certd-server/src/configuration-cache.ts +++ b/packages/ui/certd-server/src/configuration-cache.ts @@ -1,5 +1,5 @@ export function shouldSetDefaultNoCache(path: string, cacheControl?: string) { - if(path === '/' || path === '/index.html' ){ + if (path === "/" || path === "/index.html") { //首页不管怎样都不要缓存 return true; } @@ -7,5 +7,5 @@ export function shouldSetDefaultNoCache(path: string, cacheControl?: string) { return false; } // api也不要缓存,如果他本身有设置缓存除外 - return path.startsWith('/api'); + return path.startsWith("/api"); } diff --git a/packages/ui/certd-server/src/configuration.test.ts b/packages/ui/certd-server/src/configuration.test.ts index cc9147e33..40785ca41 100644 --- a/packages/ui/certd-server/src/configuration.test.ts +++ b/packages/ui/certd-server/src/configuration.test.ts @@ -14,8 +14,8 @@ describe("shouldSetDefaultNoCache", () => { it("keeps explicit cache headers from file responses", () => { assert.equal(shouldSetDefaultNoCache("/", "public,max-age=259200"), true); - assert.equal(shouldSetDefaultNoCache("/index.html", "public,max-age=259200"), true); - assert.equal(shouldSetDefaultNoCache("/api/basic/file/download", "public,max-age=259200"), false); + assert.equal(shouldSetDefaultNoCache("/index.html", "public,max-age=259200"), true); + assert.equal(shouldSetDefaultNoCache("/api/basic/file/download", "public,max-age=259200"), false); }); it("ignores non-html and non-api paths", () => { diff --git a/packages/ui/certd-server/src/configuration.ts b/packages/ui/certd-server/src/configuration.ts index 86fd259eb..8eaaef70c 100644 --- a/packages/ui/certd-server/src/configuration.ts +++ b/packages/ui/certd-server/src/configuration.ts @@ -1,33 +1,33 @@ -import { App, Configuration } from '@midwayjs/core'; -import * as koa from '@midwayjs/koa'; -import { IMidwayKoaContext, NextFunction } from '@midwayjs/koa'; -import * as orm from '@midwayjs/typeorm'; -import * as cache from '@midwayjs/cache'; -import * as validate from '@midwayjs/validate'; -import * as info from '@midwayjs/info'; -import * as staticFile from '@midwayjs/static-file'; -import * as cron from './modules/cron/index.js'; -import * as flyway from '@certd/midway-flyway-js'; -import cors from '@koa/cors'; -import { GlobalExceptionMiddleware } from './middleware/global-exception.js'; -import { PreviewMiddleware } from './middleware/preview.js'; -import { AuthorityMiddleware } from './middleware/authority.js'; -import { logger } from '@certd/basic'; -import { ResetPasswdMiddleware } from './middleware/reset-passwd/middleware.js'; -import DefaultConfig from './config/config.default.js'; -import * as libServer from '@certd/lib-server'; -import * as commercial from '@certd/commercial-core'; -import * as upload from '@midwayjs/upload'; -import { setLogger } from '@certd/acme-client'; -import {HiddenMiddleware} from "./middleware/hidden.js"; -import { shouldSetDefaultNoCache } from './configuration-cache.js'; +import { App, Configuration } from "@midwayjs/core"; +import * as koa from "@midwayjs/koa"; +import { IMidwayKoaContext, NextFunction } from "@midwayjs/koa"; +import * as orm from "@midwayjs/typeorm"; +import * as cache from "@midwayjs/cache"; +import * as validate from "@midwayjs/validate"; +import * as info from "@midwayjs/info"; +import * as staticFile from "@midwayjs/static-file"; +import * as cron from "./modules/cron/index.js"; +import * as flyway from "@certd/midway-flyway-js"; +import cors from "@koa/cors"; +import { GlobalExceptionMiddleware } from "./middleware/global-exception.js"; +import { PreviewMiddleware } from "./middleware/preview.js"; +import { AuthorityMiddleware } from "./middleware/authority.js"; +import { logger } from "@certd/basic"; +import { ResetPasswdMiddleware } from "./middleware/reset-passwd/middleware.js"; +import DefaultConfig from "./config/config.default.js"; +import * as libServer from "@certd/lib-server"; +import * as commercial from "@certd/commercial-core"; +import * as upload from "@midwayjs/upload"; +import { setLogger } from "@certd/acme-client"; +import { HiddenMiddleware } from "./middleware/hidden.js"; +import { shouldSetDefaultNoCache } from "./configuration-cache.js"; // import * as swagger from '@midwayjs/swagger'; //@ts-ignore // process.env.UV_THREADPOOL_SIZE = 2 -process.on('uncaughtException', error => { - console.error('未捕获的异常:', error); +process.on("uncaughtException", error => { + console.error("未捕获的异常:", error); // 在这里可以添加日志记录、发送错误通知等操作 - if(error?.message?.includes('address family not supported')){ + if (error?.message?.includes("address family not supported")) { logger.error("您的服务器不支持监听IPV6格式的地址(::),请配置环境变量: certd_koa_hostname=0.0.0.0"); } }); @@ -48,9 +48,7 @@ process.on('uncaughtException', error => { @Configuration({ detectorOptions: { - ignore: [ - '**/plugins/**' - ] + ignore: ["**/plugins/**"], }, imports: [ koa, @@ -69,7 +67,7 @@ process.on('uncaughtException', error => { // }, { component: info, - enabledEnvironment: ['local'], + enabledEnvironment: ["local"], }, ], importConfigs: [ @@ -79,13 +77,12 @@ process.on('uncaughtException', error => { ], }) export class MainConfiguration { - @App('koa') + @App("koa") app: koa.Application; async onReady() { // 设置flyway logger - // add middleware // this.app.useMiddleware([ReportMiddleware]); // add filter @@ -93,7 +90,7 @@ export class MainConfiguration { //跨域 this.app.use( cors({ - origin: '*', + origin: "*", }) ); // @@ -126,8 +123,8 @@ export class MainConfiguration { await next(); const path = ctx.path; // 如果是首页则强制设置为不缓存 - if (shouldSetDefaultNoCache(path, ctx.response.get('Cache-Control')) ) { - ctx.response.set('Cache-Control', 'public,max-age=0'); + if (shouldSetDefaultNoCache(path, ctx.response.get("Cache-Control"))) { + ctx.response.set("Cache-Control", "public,max-age=0"); } }); @@ -136,6 +133,6 @@ export class MainConfiguration { logger.info(text); }); - logger.info('当前环境:', this.app.getEnv()); // prod + logger.info("当前环境:", this.app.getEnv()); // prod } } diff --git a/packages/ui/certd-server/src/controller/basic/app-controller.ts b/packages/ui/certd-server/src/controller/basic/app-controller.ts index cf8aaf93a..6b79ecea4 100644 --- a/packages/ui/certd-server/src/controller/basic/app-controller.ts +++ b/packages/ui/certd-server/src/controller/basic/app-controller.ts @@ -1,29 +1,29 @@ -import {Body, Controller, Get, Inject, Post, Provide} from '@midwayjs/core'; -import { BaseController, Constants, FileService, SysSettingsService, SysSiteInfo } from '@certd/lib-server'; -import { http, logger } from '@certd/basic'; -import { isComm } from '@certd/plus-core'; +import { Body, Controller, Get, Inject, Post, Provide } from "@midwayjs/core"; +import { BaseController, Constants, FileService, SysSettingsService, SysSiteInfo } from "@certd/lib-server"; +import { http, logger } from "@certd/basic"; +import { isComm } from "@certd/plus-core"; export function normalizeReleaseVersion(release: { tag_name?: string; name?: string }) { - const version = release?.tag_name || release?.name || ''; - return version.replace(/^v/i, ''); + const version = release?.tag_name || release?.name || ""; + return version.replace(/^v/i, ""); } /** */ @Provide() -@Controller('/api/app/') +@Controller("/api/app/") export class AppController extends BaseController { @Inject() sysSettingsService: SysSettingsService; @Inject() fileService: FileService; - @Get('/latest', { description: Constants.per.authOnly }) + @Get("/latest", { description: Constants.per.authOnly }) async latest(): Promise { try { const res = await http.request({ - url: 'https://api.atomgit.com/api/v5/repos/certd/certd/releases/latest', - method: 'get', + url: "https://api.atomgit.com/api/v5/repos/certd/certd/releases/latest", + method: "get", logRes: false, timeout: 5000, }); @@ -31,30 +31,30 @@ export class AppController extends BaseController { return this.ok(latest); } catch (e: any) { logger.error(e); - return this.ok(''); + return this.ok(""); } } - @Get('/favicon', { description: Constants.per.guest }) + @Get("/favicon", { description: Constants.per.guest }) public async getFavicon() { if (isComm()) { const siteInfo = await this.sysSettingsService.getSetting(SysSiteInfo); const favicon = siteInfo.logo; if (favicon) { - const redirect = '/api/basic/file/download?key=' + favicon; + const redirect = "/api/basic/file/download?key=" + favicon; this.ctx.response.redirect(redirect); - this.ctx.response.set('Cache-Control', 'public,max-age=25920'); + this.ctx.response.set("Cache-Control", "public,max-age=25920"); return; } } - const redirect = '/static/images/logo/logo.svg'; + const redirect = "/static/images/logo/logo.svg"; this.ctx.response.redirect(redirect); - this.ctx.response.set('Cache-Control', 'public,max-age=25920'); + this.ctx.response.set("Cache-Control", "public,max-age=25920"); } - @Post('/webhook', { description: Constants.per.guest }) - public async webhook( @Body() body: any) { - logger.info('webhook', JSON.stringify(body)) - return this.ok("success") + @Post("/webhook", { description: Constants.per.guest }) + public async webhook(@Body() body: any) { + logger.info("webhook", JSON.stringify(body)); + return this.ok("success"); } } diff --git a/packages/ui/certd-server/src/controller/basic/code-controller.ts b/packages/ui/certd-server/src/controller/basic/code-controller.ts index 6ac3ade59..8025cf3c2 100644 --- a/packages/ui/certd-server/src/controller/basic/code-controller.ts +++ b/packages/ui/certd-server/src/controller/basic/code-controller.ts @@ -32,12 +32,12 @@ export class EmailCodeReq { } // 找回密码的验证码有效期 -const FORGOT_PASSWORD_CODE_DURATION = 3 +const FORGOT_PASSWORD_CODE_DURATION = 3; /** */ @Provide() -@Controller('/api/basic/code') +@Controller("/api/basic/code") export class BasicController extends BaseController { @Inject() codeService: CodeService; @@ -53,13 +53,13 @@ export class BasicController extends BaseController { @Inject() addonGetterService: AddonGetterService; - @Post('/captcha/get', { description: Constants.per.guest }) - async getCaptcha(@Query("captchaAddonId") captchaAddonId:number) { - const form = await this.captchaService.getCaptcha(captchaAddonId) - return this.ok(form); + @Post("/captcha/get", { description: Constants.per.guest }) + async getCaptcha(@Query("captchaAddonId") captchaAddonId: number) { + const form = await this.captchaService.getCaptcha(captchaAddonId); + return this.ok(form); } - @Post('/sendSmsCode', { description: Constants.per.guest }) + @Post("/sendSmsCode", { description: Constants.per.guest }) public async sendSmsCode( @Body(ALL) body: SmsCodeReq, @@ -70,17 +70,17 @@ export class BasicController extends BaseController { verificationCodeLength: undefined, duration: undefined, }; - if(body?.verificationType === 'forgotPassword') { + if (body?.verificationType === "forgotPassword") { opts.duration = FORGOT_PASSWORD_CODE_DURATION; // opts.verificationCodeLength = 6; //部分厂商这里会设置参数长度这里就不改了 } - await this.codeService.checkCaptcha(body.captcha,{remoteIp}); + await this.codeService.checkCaptcha(body.captcha, { remoteIp }); await this.codeService.sendSmsCode(body.phoneCode, body.mobile, opts); return this.ok(null); } - @Post('/sendEmailCode', { description: Constants.per.guest }) + @Post("/sendEmailCode", { description: Constants.per.guest }) public async sendEmailCode( @Body(ALL) body: EmailCodeReq, @@ -91,20 +91,18 @@ export class BasicController extends BaseController { verificationCodeLength: undefined, duration: undefined, }; - - if(body?.verificationType === 'forgotPassword') { + + if (body?.verificationType === "forgotPassword") { opts.duration = FORGOT_PASSWORD_CODE_DURATION; opts.verificationCodeLength = 6; - }else{ + } else { opts.duration = 10; opts.verificationCodeLength = 6; } - - await this.codeService.checkCaptcha(body.captcha,{remoteIp}); + await this.codeService.checkCaptcha(body.captcha, { remoteIp }); await this.codeService.sendEmailCode(body.email, opts); // 设置缓存内容 return this.ok(null); } - } diff --git a/packages/ui/certd-server/src/controller/basic/file-controller.ts b/packages/ui/certd-server/src/controller/basic/file-controller.ts index 47ffe94fd..566824964 100644 --- a/packages/ui/certd-server/src/controller/basic/file-controller.ts +++ b/packages/ui/certd-server/src/controller/basic/file-controller.ts @@ -1,16 +1,16 @@ -import { Controller, Fields, Files, Get, Inject, Post, Provide, Query } from '@midwayjs/core'; -import { BaseController, Constants, FileService, PermissionException, UploadFileItem, uploadTmpFileCacheKey } from '@certd/lib-server'; -import send from 'koa-send'; -import { nanoid } from 'nanoid'; -import { cache } from '@certd/basic'; -import { UploadFileInfo } from '@midwayjs/upload'; -import { AuthService } from '../../modules/sys/authority/service/auth-service.js'; +import { Controller, Fields, Files, Get, Inject, Post, Provide, Query } from "@midwayjs/core"; +import { BaseController, Constants, FileService, PermissionException, UploadFileItem, uploadTmpFileCacheKey } from "@certd/lib-server"; +import send from "koa-send"; +import { nanoid } from "nanoid"; +import { cache } from "@certd/basic"; +import { UploadFileInfo } from "@midwayjs/upload"; +import { AuthService } from "../../modules/sys/authority/service/auth-service.js"; -const imageExtSet = new Set(['.apng', '.avif', '.bmp', '.gif', '.ico', '.jpeg', '.jpg', '.png', '.svg', '.webp']); +const imageExtSet = new Set([".apng", ".avif", ".bmp", ".gif", ".ico", ".jpeg", ".jpg", ".png", ".svg", ".webp"]); const imageCacheSeconds = 3 * 24 * 60 * 60; export function isImageFile(filePath: string) { - return imageExtSet.has(filePath.substring(filePath.lastIndexOf('.')).toLowerCase()); + return imageExtSet.has(filePath.substring(filePath.lastIndexOf(".")).toLowerCase()); } export function getImageDownloadOptions(filePath: string) { @@ -20,7 +20,7 @@ export function getImageDownloadOptions(filePath: string) { return { maxage: imageCacheSeconds * 1000, setHeaders(res: any) { - res.setHeader('Cache-Control', `public,max-age=${imageCacheSeconds}`); + res.setHeader("Cache-Control", `public,max-age=${imageCacheSeconds}`); }, }; } @@ -28,7 +28,7 @@ export function getImageDownloadOptions(filePath: string) { /** */ @Provide() -@Controller('/api/basic/file') +@Controller("/api/basic/file") export class FileController extends BaseController { @Inject() fileService: FileService; @@ -36,9 +36,9 @@ export class FileController extends BaseController { @Inject() authService: AuthService; - @Post('/upload', { description: Constants.per.authOnly }) - async upload(@Files() files: UploadFileInfo[], @Fields() fields: any, @Query('autoSave') autoSave: string) { - console.log('files', files, fields); + @Post("/upload", { description: Constants.per.authOnly }) + async upload(@Files() files: UploadFileInfo[], @Fields() fields: any, @Query("autoSave") autoSave: string) { + console.log("files", files, fields); const cacheKey = uploadTmpFileCacheKey + nanoid(); const file = files[0]; cache.set( @@ -51,8 +51,8 @@ export class FileController extends BaseController { ttl: 1000 * 60 * 60, } ); - if (autoSave === 'true') { - const key = await this.fileService.saveFile(this.getUserId(), cacheKey, 'public'); + if (autoSave === "true") { + const key = await this.fileService.saveFile(this.getUserId(), cacheKey, "public"); return this.ok({ key, url: `/api/basic/file/download?key=${encodeURIComponent(key)}`, @@ -63,8 +63,8 @@ export class FileController extends BaseController { }); } - @Get('/download', { description: Constants.per.guestOptionalAuth }) - async download(@Query('key') key: string) { + @Get("/download", { description: Constants.per.guestOptionalAuth }) + async download(@Query("key") key: string) { const filePath = this.getDownloadFilePath(key); const sendOptions = getImageDownloadOptions(filePath); if (!sendOptions) { @@ -74,7 +74,7 @@ export class FileController extends BaseController { } private getDownloadFilePath(key: string) { - const isPrivateFile = !key.startsWith('/public'); + const isPrivateFile = !key.startsWith("/public"); const userId = isPrivateFile ? this.getUserId() : null; try { return this.fileService.getFile(key, userId); diff --git a/packages/ui/certd-server/src/controller/basic/health-controller.ts b/packages/ui/certd-server/src/controller/basic/health-controller.ts index 11aabee79..4b290c81b 100644 --- a/packages/ui/certd-server/src/controller/basic/health-controller.ts +++ b/packages/ui/certd-server/src/controller/basic/health-controller.ts @@ -1,21 +1,18 @@ -import {Controller, Get, Provide} from '@midwayjs/core'; -import {BaseController, Constants} from '@certd/lib-server'; +import { Controller, Get, Provide } from "@midwayjs/core"; +import { BaseController, Constants } from "@certd/lib-server"; /** */ @Provide() -@Controller('/health') +@Controller("/health") export class HealthController extends BaseController { - - - @Get('/liveliness', { description: Constants.per.guest }) + @Get("/liveliness", { description: Constants.per.guest }) async liveliness(): Promise { - return this.ok('ok') + return this.ok("ok"); } - @Get('/readiness', { description: Constants.per.guest }) + @Get("/readiness", { description: Constants.per.guest }) async readiness(): Promise { - return this.ok('ok') + return this.ok("ok"); } - } diff --git a/packages/ui/certd-server/src/controller/basic/home-controller.ts b/packages/ui/certd-server/src/controller/basic/home-controller.ts index 99f619264..02786a540 100644 --- a/packages/ui/certd-server/src/controller/basic/home-controller.ts +++ b/packages/ui/certd-server/src/controller/basic/home-controller.ts @@ -1,15 +1,15 @@ -import { Controller, Get, Inject, MidwayEnvironmentService, Provide } from '@midwayjs/core'; -import { logger } from '@certd/basic'; -import { Constants } from '@certd/lib-server'; +import { Controller, Get, Inject, MidwayEnvironmentService, Provide } from "@midwayjs/core"; +import { logger } from "@certd/basic"; +import { Constants } from "@certd/lib-server"; @Provide() -@Controller('/home') +@Controller("/home") export class HomeController { @Inject() environmentService: MidwayEnvironmentService; - @Get('/', { description: Constants.per.guest }) + @Get("/", { description: Constants.per.guest }) async home(): Promise { - logger.info('当前环境:', this.environmentService.getCurrentEnvironment()); // prod - return 'Hello Midwayjs!'; + logger.info("当前环境:", this.environmentService.getCurrentEnvironment()); // prod + return "Hello Midwayjs!"; } } diff --git a/packages/ui/certd-server/src/controller/basic/login/forgot-password-controller.ts b/packages/ui/certd-server/src/controller/basic/login/forgot-password-controller.ts index 8ad6f42de..25b3c520d 100644 --- a/packages/ui/certd-server/src/controller/basic/login/forgot-password-controller.ts +++ b/packages/ui/certd-server/src/controller/basic/login/forgot-password-controller.ts @@ -1,13 +1,13 @@ -import { ALL, Body, Controller, Inject, Post, Provide } from '@midwayjs/core'; +import { ALL, Body, Controller, Inject, Post, Provide } from "@midwayjs/core"; import { BaseController, CommonException, Constants, SysSettingsService } from "@certd/lib-server"; -import { CodeService } from '../../../modules/basic/service/code-service.js'; -import { UserService } from '../../../modules/sys/authority/service/user-service.js'; +import { CodeService } from "../../../modules/basic/service/code-service.js"; +import { UserService } from "../../../modules/sys/authority/service/user-service.js"; import { LoginService } from "../../../modules/login/service/login-service.js"; /** */ @Provide() -@Controller('/api') +@Controller("/api") export class ForgotPasswordController extends BaseController { @Inject() loginService: LoginService; @@ -19,29 +19,29 @@ export class ForgotPasswordController extends BaseController { @Inject() sysSettingsService: SysSettingsService; - @Post('/forgotPassword', { description: Constants.per.guest }) + @Post("/forgotPassword", { description: Constants.per.guest }) public async forgotPassword( @Body(ALL) - body: any, + body: any ) { const sysSettings = await this.sysSettingsService.getPublicSettings(); - if(!sysSettings.selfServicePasswordRetrievalEnabled) { - throw new CommonException('暂未开启自助找回'); + if (!sysSettings.selfServicePasswordRetrievalEnabled) { + throw new CommonException("暂未开启自助找回"); } // 找回密码的验证码允许错误次数 const maxErrorCount = 5; - if(body.type === 'email') { + if (body.type === "email") { this.codeService.checkEmailCode({ - verificationType: 'forgotPassword', + verificationType: "forgotPassword", email: body.input, validateCode: body.validateCode, maxErrorCount: maxErrorCount, throwError: true, }); - } else if(body.type === 'mobile') { + } else if (body.type === "mobile") { await this.codeService.checkSmsCode({ - verificationType: 'forgotPassword', + verificationType: "forgotPassword", mobile: body.input, phoneCode: body.phoneCode, smsCode: body.validateCode, @@ -49,10 +49,10 @@ export class ForgotPasswordController extends BaseController { throwError: true, }); } else { - throw new CommonException('暂不支持的找回类型,请联系管理员找回'); + throw new CommonException("暂不支持的找回类型,请联系管理员找回"); } const username = await this.userService.forgotPassword(body); - username && this.loginService.clearCacheOnSuccess(username) + username && this.loginService.clearCacheOnSuccess(username); return this.ok(); } } diff --git a/packages/ui/certd-server/src/controller/basic/login/login-controller.ts b/packages/ui/certd-server/src/controller/basic/login/login-controller.ts index db5969b8f..a80eeb036 100644 --- a/packages/ui/certd-server/src/controller/basic/login/login-controller.ts +++ b/packages/ui/certd-server/src/controller/basic/login/login-controller.ts @@ -9,7 +9,7 @@ import { PasskeyService } from "../../../modules/login/service/passkey-service.j /** */ @Provide() -@Controller('/api/') +@Controller("/api/") export class LoginController extends BaseController { @Inject() loginService: LoginService; @@ -24,20 +24,19 @@ export class LoginController extends BaseController { @Inject() captchaService: CaptchaService; - @Inject() + @Inject() passkeyService: PasskeyService; - - @Post('/login', { description: Constants.per.guest }) + @Post("/login", { description: Constants.per.guest }) public async login( @Body(ALL) body: any, @RequestIP() remoteIp: string ) { - const settings = await this.sysSettingsService.getPublicSettings() + const settings = await this.sysSettingsService.getPublicSettings(); if (settings.captchaEnabled === true) { - await this.captchaService.doValidate({form:body.captcha,must:false,captchaAddonId:settings.captchaAddonId,req:{remoteIp}}) + await this.captchaService.doValidate({ form: body.captcha, must: false, captchaAddonId: settings.captchaAddonId, req: { remoteIp } }); } const token = await this.loginService.loginByPassword(body); this.writeTokenCookie(token); @@ -48,14 +47,14 @@ export class LoginController extends BaseController { // this.loginService.writeTokenCookie(this.ctx,token); } - @Post('/loginBySms', { description: Constants.per.guest }) + @Post("/loginBySms", { description: Constants.per.guest }) public async loginBySms( @Body(ALL) body: any ) { const settings = await this.sysSettingsService.getSetting(SysPublicSettings); if (settings.smsLoginEnabled !== true) { - throw new Error('当前站点禁止短信验证码登录'); + throw new Error("当前站点禁止短信验证码登录"); } checkComm(); @@ -72,12 +71,11 @@ export class LoginController extends BaseController { return this.ok(token); } - @Post('/loginByTwoFactor', { description: Constants.per.guest }) + @Post("/loginByTwoFactor", { description: Constants.per.guest }) public async loginByTwoFactor( @Body(ALL) body: any ) { - const token = await this.loginService.loginByTwoFactor({ loginId: body.loginId, verifyCode: body.verifyCode, @@ -87,19 +85,14 @@ export class LoginController extends BaseController { return this.ok(token); } - - - - @Post('/passkey/generateAuthentication', { description: Constants.per.guest }) + @Post("/passkey/generateAuthentication", { description: Constants.per.guest }) public async generateAuthentication() { - const options = await this.passkeyService.generateAuthenticationOptions( - this.ctx - ); + const options = await this.passkeyService.generateAuthenticationOptions(this.ctx); return this.ok(options); } - @Post('/loginByPasskey', { description: Constants.per.guest }) + @Post("/loginByPasskey", { description: Constants.per.guest }) public async loginByPasskey( @Body(ALL) body: any @@ -107,19 +100,22 @@ export class LoginController extends BaseController { const credential = body.credential; const challenge = body.challenge; - const token = await this.loginService.loginByPasskey({ - credential, - challenge, - }, this.ctx); + const token = await this.loginService.loginByPasskey( + { + credential, + challenge, + }, + this.ctx + ); // this.writeTokenCookie(token); return this.ok(token); } - @Post('/logout', { description: Constants.per.authOnly }) + @Post("/logout", { description: Constants.per.authOnly }) public logout() { this.ctx.cookies.set("certd_token", "", { - maxAge: 0 + maxAge: 0, }); return this.ok(); } diff --git a/packages/ui/certd-server/src/controller/basic/login/oauth-controller.ts b/packages/ui/certd-server/src/controller/basic/login/oauth-controller.ts index f312a1847..0882fedec 100644 --- a/packages/ui/certd-server/src/controller/basic/login/oauth-controller.ts +++ b/packages/ui/certd-server/src/controller/basic/login/oauth-controller.ts @@ -32,9 +32,8 @@ function getOauthBoundType(type: string, subtype?: string) { /** */ @Provide() -@Controller('/api/oauth') +@Controller("/api/oauth") export class ConnectController extends BaseController { - @Inject() addonGetterService: AddonGetterService; @Inject() @@ -52,10 +51,8 @@ export class ConnectController extends BaseController { @Inject() addonService: AddonService; - - private async getOauthProvider(type: string) { - const publicSettings = await this.sysSettingsService.getPublicSettings() + const publicSettings = await this.sysSettingsService.getPublicSettings(); if (!publicSettings?.oauthEnabled) { throw new Error("OAuth功能未启用"); } @@ -64,7 +61,7 @@ export class ConnectController extends BaseController { throw new Error(`未配置该OAuth类型:${type}`); } - const addon = await this.addonGetterService.getAddonById(setting.addonId, true, 0,null); + const addon = await this.addonGetterService.getAddonById(setting.addonId, true, 0, null); if (!addon) { throw new Error("初始化OAuth插件失败"); } @@ -74,19 +71,18 @@ export class ConnectController extends BaseController { }; } - @Post('/login', { description: Constants.per.guest }) - public async login(@Body(ALL) body: { type: string, subtype?: string, forType?:string ,from?:string }) { - + @Post("/login", { description: Constants.per.guest }) + public async login(@Body(ALL) body: { type: string; subtype?: string; forType?: string; from?: string }) { const oauthProvider = await this.getOauthProvider(body.type); const installInfo = await this.sysSettingsService.getSetting(SysInstallInfo); const bindUrl = installInfo?.bindUrl || ""; //构造登录url const redirectUrl = `${bindUrl}api/oauth/callback/${body.type}`; - let stateObj = { - forType: body.forType || 'login', - } - const state = utils.hash.base64(JSON.stringify(stateObj)) + const stateObj = { + forType: body.forType || "login", + }; + const state = utils.hash.base64(JSON.stringify(stateObj)); const { loginUrl, ticketValue } = await oauthProvider.addon.buildLoginUrl({ redirectUri: redirectUrl, forType: body.forType, @@ -94,25 +90,23 @@ export class ConnectController extends BaseController { subtype: body.subtype, state, }); - + const ticket = this.codeService.setValidationValue({ ...ticketValue, state, subtype: body.subtype, - }) + }); this.ctx.cookies.set("oauth_ticket", ticket, { httpOnly: true, // secure: true, // sameSite: "strict", - }) + }); return this.ok({ loginUrl, ticket }); } - - @Get('/callback/:type', { description: Constants.per.guest }) - public async callback(@Param('type') type: string, @Query() query: Record) { - - checkPlus() + @Get("/callback/:type", { description: Constants.per.guest }) + public async callback(@Param("type") type: string, @Query() query: Record) { + checkPlus(); //处理登录回调 const oauthProvider = await this.getOauthProvider(type); @@ -133,13 +127,13 @@ export class ConnectController extends BaseController { const installInfo = await this.sysSettingsService.getSetting(SysInstallInfo); const bindUrl = installInfo?.bindUrl || ""; - const currentUrl = `${bindUrl}api/oauth/callback/${type}?${request.querystring}` + const currentUrl = `${bindUrl}api/oauth/callback/${type}?${request.querystring}`; try { const tokenRes = await oauthProvider.addon.onCallback({ code: query.code, state: query.state, ticketValue, - currentURL: new URL(currentUrl) + currentURL: new URL(currentUrl), }); const userInfo = tokenRes.userInfo; @@ -149,7 +143,7 @@ export class ConnectController extends BaseController { userInfo, }); - let state = {forType:""} + let state = { forType: "" }; if (query.state) { state = JSON.parse(utils.hash.base64Decode(query.state)); } @@ -160,12 +154,11 @@ export class ConnectController extends BaseController { logger.error(err); this.ctx.redirect(`${bindUrl}#/oauth/callback/${type}?error=${err.error_description || err.message}`); } - } - @Post('/getLogoutUrl', { description: Constants.per.guest }) + @Post("/getLogoutUrl", { description: Constants.per.guest }) public async logout(@Body(ALL) body: any) { - checkPlus() + checkPlus(); const oauthProvider = await this.getOauthProvider(body.type); const { logoutUrl } = await oauthProvider.addon.buildLogoutUrl({ ...body, @@ -173,10 +166,9 @@ export class ConnectController extends BaseController { return this.ok({ logoutUrl }); } - - @Post('/token', { description: Constants.per.guest }) - public async token(@Body(ALL) body: { validationCode: string, type: string }) { - checkPlus() + @Post("/token", { description: Constants.per.guest }) + public async token(@Body(ALL) body: { validationCode: string; type: string }) { + checkPlus(); const validationValue = await this.codeService.getValidationValue(body.validationCode); if (!validationValue) { throw new Error("校验码错误"); @@ -191,7 +183,6 @@ export class ConnectController extends BaseController { const loginRes = await this.loginService.loginByOpenId({ openId, type }); if (loginRes == null) { - return this.ok({ bindRequired: true, validationCode: body.validationCode, @@ -207,24 +198,22 @@ export class ConnectController extends BaseController { // this.loginService.writeTokenCookie(this.ctx,token); } - - @Post('/autoRegister', { description: Constants.per.guest }) - public async autoRegister(@Body(ALL) body: { validationCode: string, type: string }) { - + @Post("/autoRegister", { description: Constants.per.guest }) + public async autoRegister(@Body(ALL) body: { validationCode: string; type: string }) { const validationValue = this.codeService.getValidationValue(body.validationCode); if (!validationValue) { throw new Error("第三方认证授权已过期"); } const userInfo = validationValue.userInfo; const oauthType = validationValue.type; - let newUser = new UserEntity() + let newUser = new UserEntity(); newUser.username = `${userInfo.nickName}_${simpleNanoId(6)}_${oauthType}`; newUser.avatar = userInfo.avatar; newUser.nickName = userInfo.nickName || simpleNanoId(6); newUser.email = userInfo.email || ""; - newUser = await this.userService.register("username", newUser, async (txManager) => { - const oauthBound: OauthBoundEntity = new OauthBoundEntity() + newUser = await this.userService.register("username", newUser, async txManager => { + const oauthBound: OauthBoundEntity = new OauthBoundEntity(); oauthBound.userId = newUser.id; oauthBound.type = oauthType; oauthBound.openId = userInfo.openId; @@ -236,8 +225,7 @@ export class ConnectController extends BaseController { return this.ok(loginRes); } - - @Post('/bind', { description: Constants.per.loginOnly }) + @Post("/bind", { description: Constants.per.loginOnly }) public async bind(@Body(ALL) body: any) { //需要已登录 const userId = this.getUserId(); @@ -256,7 +244,7 @@ export class ConnectController extends BaseController { return this.ok(1); } - @Post('/unbind', { description: Constants.per.loginOnly }) + @Post("/unbind", { description: Constants.per.loginOnly }) public async unbind(@Body(ALL) body: any) { //需要已登录 const userId = this.getUserId(); @@ -267,20 +255,19 @@ export class ConnectController extends BaseController { return this.ok(1); } - @Post('/bounds', { description: Constants.per.loginOnly }) + @Post("/bounds", { description: Constants.per.loginOnly }) public async bounds(@Body(ALL) body: any) { //需要已登录 const userId = this.getUserId(); const bounds = await this.oauthBoundService.find({ - where :{ + where: { userId, - } + }, }); return this.ok(bounds); } - - @Post('/providers', { description: Constants.per.guest }) + @Post("/providers", { description: Constants.per.guest }) public async providers() { const defineList = addonRegistry.getDefineList("oauth"); @@ -289,27 +276,27 @@ export class ConnectController extends BaseController { const list = []; for (const item of defineList) { - const type = item.name + const type = item.name; const conf = oauthProviders[type]; - const provider:any = { + const provider: any = { ...item, - } - delete provider.input + }; + delete provider.input; if (conf && conf.addonId) { const addonEntity = await this.addonService.info(conf.addonId); if (addonEntity) { provider.addonId = conf.addonId; provider.addonTitle = addonEntity.name; - const addon = await this.addonGetterService.getAddonById(conf.addonId,true,0,null) as IOauthProvider & { icon?: string; types?: OauthProviderType[] }; - const {logoutUrl} = await addon.buildLogoutUrl({}); - if (logoutUrl){ + const addon = (await this.addonGetterService.getAddonById(conf.addonId, true, 0, null)) as IOauthProvider & { icon?: string; types?: OauthProviderType[] }; + const { logoutUrl } = await addon.buildLogoutUrl({}); + if (logoutUrl) { provider.logoutUrl = logoutUrl; } - if(addon.icon){ + if (addon.icon) { provider.icon = addon.icon; } - if(addon.types?.length){ + if (addon.types?.length) { provider.types = addon.types; } } diff --git a/packages/ui/certd-server/src/controller/basic/login/register-controller.ts b/packages/ui/certd-server/src/controller/basic/login/register-controller.ts index 063c55dbb..586f9c308 100644 --- a/packages/ui/certd-server/src/controller/basic/login/register-controller.ts +++ b/packages/ui/certd-server/src/controller/basic/login/register-controller.ts @@ -1,9 +1,9 @@ -import { ALL, Body, Controller, Inject, Post, Provide, RequestIP } from '@midwayjs/core'; -import { BaseController, Constants, SysSettingsService } from '@certd/lib-server'; -import { RegisterType, UserService } from '../../../modules/sys/authority/service/user-service.js'; -import { CodeService } from '../../../modules/basic/service/code-service.js'; -import { checkComm, checkPlus } from '@certd/plus-core'; -import { InviteService } from '@certd/commercial-core'; +import { ALL, Body, Controller, Inject, Post, Provide, RequestIP } from "@midwayjs/core"; +import { BaseController, Constants, SysSettingsService } from "@certd/lib-server"; +import { RegisterType, UserService } from "../../../modules/sys/authority/service/user-service.js"; +import { CodeService } from "../../../modules/basic/service/code-service.js"; +import { checkComm, checkPlus } from "@certd/plus-core"; +import { InviteService } from "@certd/commercial-core"; export type RegisterReq = { type: RegisterType; @@ -14,14 +14,14 @@ export type RegisterReq = { phoneCode?: string; validateCode: string; - captcha:any; + captcha: any; inviteCode?: string; }; /** */ @Provide() -@Controller('/api/') +@Controller("/api/") export class RegisterController extends BaseController { @Inject() userService: UserService; @@ -34,7 +34,7 @@ export class RegisterController extends BaseController { @Inject() inviteService: InviteService; - @Post('/register', { description: Constants.per.guest }) + @Post("/register", { description: Constants.per.guest }) public async register( @Body(ALL) body: RegisterReq, @@ -42,22 +42,22 @@ export class RegisterController extends BaseController { ) { const sysPublicSettings = await this.sysSettingsService.getPublicSettings(); if (sysPublicSettings.registerEnabled === false) { - throw new Error('当前站点已禁止自助注册功能'); + throw new Error("当前站点已禁止自助注册功能"); } - if (body.username && ["admin","certd"].includes(body.username) ) { - throw new Error('用户名不能为保留字'); + if (body.username && ["admin", "certd"].includes(body.username)) { + throw new Error("用户名不能为保留字"); } - if (body.type === 'username') { + if (body.type === "username") { if (sysPublicSettings.usernameRegisterEnabled === false) { - throw new Error('当前站点已禁止用户名注册功能'); + throw new Error("当前站点已禁止用户名注册功能"); } if (!body.username) { - throw new Error('用户名不能为空'); + throw new Error("用户名不能为空"); } - await this.codeService.checkCaptcha(body.captcha,{remoteIp}); + await this.codeService.checkCaptcha(body.captcha, { remoteIp }); const registerUser = { username: body.username, password: body.password, @@ -66,9 +66,9 @@ export class RegisterController extends BaseController { await this.inviteService.bindInvitee({ manager: txManager }, { inviteeUserId: registerUser.id, inviteCode: body.inviteCode }); }); return this.ok(newUser); - } else if (body.type === 'mobile') { + } else if (body.type === "mobile") { if (sysPublicSettings.mobileRegisterEnabled === false) { - throw new Error('当前站点已禁止手机号注册功能'); + throw new Error("当前站点已禁止手机号注册功能"); } checkComm(); //验证短信验证码 @@ -88,9 +88,9 @@ export class RegisterController extends BaseController { await this.inviteService.bindInvitee({ manager: txManager }, { inviteeUserId: registerUser.id, inviteCode: body.inviteCode }); }); return this.ok(newUser); - } else if (body.type === 'email') { + } else if (body.type === "email") { if (sysPublicSettings.emailRegisterEnabled === false) { - throw new Error('当前站点已禁止Email注册功能'); + throw new Error("当前站点已禁止Email注册功能"); } checkPlus(); this.codeService.checkEmailCode({ diff --git a/packages/ui/certd-server/src/controller/basic/root-controller.ts b/packages/ui/certd-server/src/controller/basic/root-controller.ts index cda4f3806..200a73114 100644 --- a/packages/ui/certd-server/src/controller/basic/root-controller.ts +++ b/packages/ui/certd-server/src/controller/basic/root-controller.ts @@ -1,18 +1,18 @@ -import { Controller, Get, Inject, Provide } from '@midwayjs/core'; -import { Constants, SysSettingsService } from '@certd/lib-server'; +import { Controller, Get, Inject, Provide } from "@midwayjs/core"; +import { Constants, SysSettingsService } from "@certd/lib-server"; @Provide() -@Controller('/') +@Controller("/") export class HomeController { @Inject() sysSettingsService: SysSettingsService; - @Get('/robots.txt', { description: Constants.per.guest }) + @Get("/robots.txt", { description: Constants.per.guest }) async robots(): Promise { const publicSettings = await this.sysSettingsService.getPublicSettings(); if (!publicSettings.robots) { - return 'User-agent: *\nDisallow: /'; + return "User-agent: *\nDisallow: /"; } else { - return 'User-agent: *\nAllow: /'; + return "User-agent: *\nAllow: /"; } } } diff --git a/packages/ui/certd-server/src/controller/basic/settings-controller.ts b/packages/ui/certd-server/src/controller/basic/settings-controller.ts index 3984919ce..ebee0ecb4 100644 --- a/packages/ui/certd-server/src/controller/basic/settings-controller.ts +++ b/packages/ui/certd-server/src/controller/basic/settings-controller.ts @@ -1,15 +1,5 @@ import { Config, Controller, Get, Inject, Provide } from "@midwayjs/core"; -import { - BaseController, - Constants, - SysHeaderMenus, - SysInstallInfo, - SysPublicSettings, - SysSettingsService, - SysSiteEnv, - SysSiteInfo, - SysSuiteSetting -} from "@certd/lib-server"; +import { BaseController, Constants, SysHeaderMenus, SysInstallInfo, SysPublicSettings, SysSettingsService, SysSiteEnv, SysSiteInfo, SysSuiteSetting } from "@certd/lib-server"; import { AppKey, getPlusInfo, isComm } from "@certd/plus-core"; import { SysInviteCommissionSetting } from "@certd/commercial-core"; import { cloneDeep } from "lodash-es"; @@ -54,7 +44,7 @@ export class BasicSettingsController extends BaseController { } const setting = await this.sysSettingsService.getSetting(SysSuiteSetting); return { - enabled: setting.enabled + enabled: setting.enabled, }; } @@ -72,7 +62,7 @@ export class BasicSettingsController extends BaseController { public async getSiteEnv() { const env: SysSiteEnv = { - agent: this.agentConfig + agent: this.agentConfig, }; return env; } @@ -87,10 +77,9 @@ export class BasicSettingsController extends BaseController { @Get("/productInfo", { description: Constants.per.guest }) async getProductInfo() { const info = await http.request({ - url: "https://app.handfree.work/certd/info.json" + url: "https://app.handfree.work/certd/info.json", }); return this.ok(info); - } @Get("/all", { description: Constants.per.guest }) @@ -118,7 +107,7 @@ export class BasicSettingsController extends BaseController { inviteSetting, app: { time: new Date().getTime(), - version + version, }, }); } diff --git a/packages/ui/certd-server/src/controller/basic/unhidden-controller.ts b/packages/ui/certd-server/src/controller/basic/unhidden-controller.ts index dae436072..2ebdd9126 100644 --- a/packages/ui/certd-server/src/controller/basic/unhidden-controller.ts +++ b/packages/ui/certd-server/src/controller/basic/unhidden-controller.ts @@ -1,8 +1,8 @@ -import {Body, Controller, Get, Inject, Post, Provide} from '@midwayjs/core'; -import {Constants, NotFoundException, ParamException, SysInstallInfo, SysSettingsService} from '@certd/lib-server'; -import {utils} from "@certd/basic"; -import {hiddenStatus, SafeService} from "../../modules/sys/settings/safe-service.js"; -import {IMidwayKoaContext} from "@midwayjs/koa"; +import { Body, Controller, Get, Inject, Post, Provide } from "@midwayjs/core"; +import { Constants, NotFoundException, ParamException, SysInstallInfo, SysSettingsService } from "@certd/lib-server"; +import { utils } from "@certd/basic"; +import { hiddenStatus, SafeService } from "../../modules/sys/settings/safe-service.js"; +import { IMidwayKoaContext } from "@midwayjs/koa"; const unhiddenHtml = ` @@ -19,48 +19,47 @@ const unhiddenHtml = ` -` +`; @Provide() -@Controller('/api/unhidden') +@Controller("/api/unhidden") export class UnhiddenController { - @Inject() - ctx: IMidwayKoaContext; - @Inject() - safeService: SafeService; - @Inject() - sysSettingsService: SysSettingsService; + @Inject() + ctx: IMidwayKoaContext; + @Inject() + safeService: SafeService; + @Inject() + sysSettingsService: SysSettingsService; - - @Post('/:randomPath', {description: Constants.per.guest}) - async randomPath(@Body("password") password: any) { - await this.checkUnhiddenPath() - const hiddenSetting = await this.safeService.getHiddenSetting() - if (utils.hash.md5(password) === hiddenSetting.openPassword) { - //解锁 - hiddenStatus.isHidden = false; - const setting = await this.sysSettingsService.getSetting(SysInstallInfo) - const bindUrl = setting.bindUrl - //解锁成功,跳转回首页,redirect - this.ctx.response.redirect(bindUrl || "/"); - return - } else { - //密码错误 - throw new ParamException('解锁密码错误'); - } + @Post("/:randomPath", { description: Constants.per.guest }) + async randomPath(@Body("password") password: any) { + await this.checkUnhiddenPath(); + const hiddenSetting = await this.safeService.getHiddenSetting(); + if (utils.hash.md5(password) === hiddenSetting.openPassword) { + //解锁 + hiddenStatus.isHidden = false; + const setting = await this.sysSettingsService.getSetting(SysInstallInfo); + const bindUrl = setting.bindUrl; + //解锁成功,跳转回首页,redirect + this.ctx.response.redirect(bindUrl || "/"); + return; + } else { + //密码错误 + throw new ParamException("解锁密码错误"); } + } - @Get('/:randomPath', {description: Constants.per.guest}) - async unhiddenGet() { - await this.checkUnhiddenPath() - this.ctx.response.body = unhiddenHtml - } + @Get("/:randomPath", { description: Constants.per.guest }) + async unhiddenGet() { + await this.checkUnhiddenPath(); + this.ctx.response.body = unhiddenHtml; + } - async checkUnhiddenPath() { - const hiddenSetting = await this.safeService.getHiddenSetting() - if (this.ctx.path != `/api/unhidden/${hiddenSetting.openPath}`) { - this.ctx.res.statusCode = 404 - throw new NotFoundException("Page not found") - } + async checkUnhiddenPath() { + const hiddenSetting = await this.safeService.getHiddenSetting(); + if (this.ctx.path != `/api/unhidden/${hiddenSetting.openPath}`) { + this.ctx.res.statusCode = 404; + throw new NotFoundException("Page not found"); } + } } diff --git a/packages/ui/certd-server/src/controller/basic/webhook-controller.ts b/packages/ui/certd-server/src/controller/basic/webhook-controller.ts index cd5825afb..4fabe22d2 100644 --- a/packages/ui/certd-server/src/controller/basic/webhook-controller.ts +++ b/packages/ui/certd-server/src/controller/basic/webhook-controller.ts @@ -1,18 +1,18 @@ -import { BaseController, Constants } from '@certd/lib-server'; -import { Controller, Get, Inject, Param, Post, Provide } from '@midwayjs/core'; -import { PipelineService } from '../../modules/pipeline/service/pipeline-service.js'; +import { BaseController, Constants } from "@certd/lib-server"; +import { Controller, Get, Inject, Param, Post, Provide } from "@midwayjs/core"; +import { PipelineService } from "../../modules/pipeline/service/pipeline-service.js"; /** */ @Provide() -@Controller('/api/webhook/') +@Controller("/api/webhook/") export class WebhookController extends BaseController { @Inject() pipelineService: PipelineService; - @Get('/:webhookKey', { description: Constants.per.guest }) - @Post('/:webhookKey', { description: Constants.per.guest }) - async webhook(@Param('webhookKey') webhookKey: string): Promise { + @Get("/:webhookKey", { description: Constants.per.guest }) + @Post("/:webhookKey", { description: Constants.per.guest }) + async webhook(@Param("webhookKey") webhookKey: string): Promise { await this.pipelineService.triggerByWebhook(webhookKey); return this.ok({}); } diff --git a/packages/ui/certd-server/src/controller/openapi/base-open-controller.ts b/packages/ui/certd-server/src/controller/openapi/base-open-controller.ts index ad141256e..c4ee88292 100644 --- a/packages/ui/certd-server/src/controller/openapi/base-open-controller.ts +++ b/packages/ui/certd-server/src/controller/openapi/base-open-controller.ts @@ -1,12 +1,12 @@ -import { BaseController, Encryptor } from '@certd/lib-server'; -import { OpenKey } from '../../modules/open/service/open-key-service.js'; +import { BaseController, Encryptor } from "@certd/lib-server"; +import { OpenKey } from "../../modules/open/service/open-key-service.js"; export class BaseOpenController extends BaseController { ok(res: any) { const openKey: OpenKey = this.ctx.openKey; if (openKey.encrypt) { const data = JSON.stringify(res); - const encryptor = new Encryptor(openKey.keySecret, 'hex'); + const encryptor = new Encryptor(openKey.keySecret, "hex"); const encrypted = encryptor.encrypt(data); return this.ok(encrypted); } diff --git a/packages/ui/certd-server/src/controller/openapi/v1/cert-controller.ts b/packages/ui/certd-server/src/controller/openapi/v1/cert-controller.ts index a7d265194..b66318af9 100644 --- a/packages/ui/certd-server/src/controller/openapi/v1/cert-controller.ts +++ b/packages/ui/certd-server/src/controller/openapi/v1/cert-controller.ts @@ -10,39 +10,39 @@ import { ApiTags } from "@midwayjs/swagger"; export type CertGetReq = { domains?: string; certId: number; - autoApply?:boolean; - format?:string; //默认是所有,pem,der,p12,pfx,jks,one,p7b + autoApply?: boolean; + format?: string; //默认是所有,pem,der,p12,pfx,jks,one,p7b }; /** */ @Provide() -@Controller('/api/v1/cert') -@ApiTags(['openapi']) +@Controller("/api/v1/cert") +@ApiTags(["openapi"]) export class OpenCertController extends BaseOpenController { @Inject() certInfoFacade: CertInfoFacade; @Inject() encryptService: EncryptService; - @Get('/get', { description: Constants.per.open, summary: "根据域名或ID获取证书,支持自动申请" }) - @Post('/get', { description: Constants.per.open, summary: "根据域名或ID获取证书,支持自动申请" }) + @Get("/get", { description: Constants.per.open, summary: "根据域名或ID获取证书,支持自动申请" }) + @Post("/get", { description: Constants.per.open, summary: "根据域名或ID获取证书,支持自动申请" }) async get(@Body(ALL) bean: CertGetReq, @Query(ALL) query: CertGetReq) { const openKey: OpenKey = this.ctx.openKey; const userId = openKey.userId; - - if (userId==null) { + + if (userId == null) { throw new CodeException(Constants.res.openKeyError); } const projectId = openKey.projectId; - const req = merge({}, bean, query) + const req = merge({}, bean, query); const res: CertInfo = await this.certInfoFacade.getCertInfo({ userId, domains: req.domains, certId: req.certId, - autoApply: req.autoApply??false, + autoApply: req.autoApply ?? false, format: req.format, projectId, }); diff --git a/packages/ui/certd-server/src/controller/sys/access/access-controller.ts b/packages/ui/certd-server/src/controller/sys/access/access-controller.ts index ee0184ef6..d45b7b8e4 100644 --- a/packages/ui/certd-server/src/controller/sys/access/access-controller.ts +++ b/packages/ui/certd-server/src/controller/sys/access/access-controller.ts @@ -6,7 +6,7 @@ import { AccessController } from "../../user/pipeline/access-controller.js"; * 授权 */ @Provide() -@Controller('/api/sys/access') +@Controller("/api/sys/access") export class SysAccessController extends AccessController { @Inject() service2: AccessService; @@ -15,10 +15,11 @@ export class SysAccessController extends AccessController { return this.service2; } - async getProjectUserId(permission:string){ + async getProjectUserId(permission: string) { return { - projectId:null,userId:0 - } + projectId: null, + userId: 0, + }; } getUserId() { @@ -26,58 +27,58 @@ export class SysAccessController extends AccessController { return 0; } - @Post('/page', { description: 'sys:settings:view' }) + @Post("/page", { description: "sys:settings:view" }) async page(@Body(ALL) body: any) { return await super.page(body); } - @Post('/list', { description: 'sys:settings:view' }) + @Post("/list", { description: "sys:settings:view" }) async list(@Body(ALL) body: any) { return await super.list(body); } - @Post('/add', { description: 'sys:settings:edit' }) + @Post("/add", { description: "sys:settings:edit" }) async add(@Body(ALL) bean: any) { return await super.add(bean); } - @Post('/update', { description: 'sys:settings:edit' }) + @Post("/update", { description: "sys:settings:edit" }) async update(@Body(ALL) bean: any) { return await super.update(bean); } - @Post('/info', { description: 'sys:settings:view' }) - async info(@Query('id') id: number) { + @Post("/info", { description: "sys:settings:view" }) + async info(@Query("id") id: number) { return await super.info(id); } - @Post('/delete', { description: 'sys:settings:edit' }) - async delete(@Query('id') id: number) { + @Post("/delete", { description: "sys:settings:edit" }) + async delete(@Query("id") id: number) { return await super.delete(id); } - @Post('/define', { description: 'sys:settings:view' }) - async define(@Query('type') type: string) { + @Post("/define", { description: "sys:settings:view" }) + async define(@Query("type") type: string) { return await super.define(type); } - @Post('/getSecretPlain', { description: 'sys:settings:view' }) + @Post("/getSecretPlain", { description: "sys:settings:view" }) async getSecretPlain(@Body(ALL) body: { id: number; key: string }) { const value = await this.service.getById(body.id, 0); return this.ok(value[body.key]); } - @Post('/accessTypeDict', { description: 'sys:settings:view' }) + @Post("/accessTypeDict", { description: "sys:settings:view" }) async getAccessTypeDict() { return await super.getAccessTypeDict(); } - @Post('/simpleInfo', { description: 'sys:settings:view' }) - async simpleInfo(@Query('id') id: number) { + @Post("/simpleInfo", { description: "sys:settings:view" }) + async simpleInfo(@Query("id") id: number) { return await super.simpleInfo(id); } - @Post('/getDictByIds', { description: 'sys:settings:view' }) - async getDictByIds(@Body('ids') ids: number[]) { - return await super.getDictByIds(ids); - } + @Post("/getDictByIds", { description: "sys:settings:view" }) + async getDictByIds(@Body("ids") ids: number[]) { + return await super.getDictByIds(ids); + } } diff --git a/packages/ui/certd-server/src/controller/sys/account/account-controller.ts b/packages/ui/certd-server/src/controller/sys/account/account-controller.ts index 77dcf6c50..229c6bdf2 100644 --- a/packages/ui/certd-server/src/controller/sys/account/account-controller.ts +++ b/packages/ui/certd-server/src/controller/sys/account/account-controller.ts @@ -1,5 +1,5 @@ -import { ALL, Body, Controller, Inject, Post, Provide } from '@midwayjs/core'; -import { BaseController, PlusService, SysInstallInfo, SysSettingsService } from '@certd/lib-server'; +import { ALL, Body, Controller, Inject, Post, Provide } from "@midwayjs/core"; +import { BaseController, PlusService, SysInstallInfo, SysSettingsService } from "@certd/lib-server"; export type PreBindUserReq = { userId: number; @@ -10,7 +10,7 @@ export type BindUserReq = { /** */ @Provide() -@Controller('/api/sys/account') +@Controller("/api/sys/account") export class BasicController extends BaseController { @Inject() plusService: PlusService; @@ -18,7 +18,7 @@ export class BasicController extends BaseController { @Inject() sysSettingsService: SysSettingsService; - @Post('/preBindUser', { description: 'sys:settings:edit' }) + @Post("/preBindUser", { description: "sys:settings:edit" }) public async preBindUser(@Body(ALL) body: PreBindUserReq) { // 设置缓存内容 if (body.userId == null || body.userId <= 0) { @@ -28,7 +28,7 @@ export class BasicController extends BaseController { return this.ok({}); } - @Post('/bindUser', { description: 'sys:settings:edit' }) + @Post("/bindUser", { description: "sys:settings:edit" }) public async bindUser(@Body(ALL) body: BindUserReq) { if (body.userId == null || body.userId <= 0) { throw new Error("用户ID不能为空"); @@ -39,7 +39,7 @@ export class BasicController extends BaseController { return this.ok({}); } - @Post('/unbindUser', { description: 'sys:settings:edit' }) + @Post("/unbindUser", { description: "sys:settings:edit" }) public async unbindUser() { const installInfo: SysInstallInfo = await this.sysSettingsService.getSetting(SysInstallInfo); installInfo.bindUserId = null; @@ -47,7 +47,7 @@ export class BasicController extends BaseController { return this.ok({}); } - @Post('/updateLicense', { description: 'sys:settings:edit' }) + @Post("/updateLicense", { description: "sys:settings:edit" }) public async updateLicense(@Body(ALL) body: { license: string }) { await this.plusService.updateLicense(body.license); return this.ok(true); diff --git a/packages/ui/certd-server/src/controller/sys/addon/addon-controller.ts b/packages/ui/certd-server/src/controller/sys/addon/addon-controller.ts index 229a9ee95..9c33e6a2c 100644 --- a/packages/ui/certd-server/src/controller/sys/addon/addon-controller.ts +++ b/packages/ui/certd-server/src/controller/sys/addon/addon-controller.ts @@ -3,7 +3,7 @@ import { AddonRequestHandleReq, AddonService, Constants } from "@certd/lib-serve import { AddonController } from "../../user/addon/addon-controller.js"; @Provide() -@Controller('/api/sys/addon') +@Controller("/api/sys/addon") export class SysAddonController extends AddonController { @Inject() service2: AddonService; @@ -12,77 +12,77 @@ export class SysAddonController extends AddonController { return this.service2; } - async getProjectUserId(permission:string){ + async getProjectUserId(permission: string) { return { - projectId:null,userId:0 //0为系统级别 - } + projectId: null, + userId: 0, //0为系统级别 + }; } getUserId() { // checkComm(); return 0; } - @Post('/page', { description: 'sys:settings:view' }) + @Post("/page", { description: "sys:settings:view" }) async page(@Body(ALL) body: any) { return await super.page(body); } - @Post('/list', { description: 'sys:settings:view' }) + @Post("/list", { description: "sys:settings:view" }) async list(@Body(ALL) body: any) { return await super.list(body); } - @Post('/add', { description: 'sys:settings:edit' }) + @Post("/add", { description: "sys:settings:edit" }) async add(@Body(ALL) bean: any) { return await super.add(bean); } - @Post('/update', { description: 'sys:settings:edit' }) + @Post("/update", { description: "sys:settings:edit" }) async update(@Body(ALL) bean: any) { return await super.update(bean); } - @Post('/info', { description: 'sys:settings:view' }) - async info(@Query('id') id: number) { + @Post("/info", { description: "sys:settings:view" }) + async info(@Query("id") id: number) { return await super.info(id); } - @Post('/delete', { description: 'sys:settings:edit' }) - async delete(@Query('id') id: number) { + @Post("/delete", { description: "sys:settings:edit" }) + async delete(@Query("id") id: number) { return await super.delete(id); } - @Post('/define', { description: Constants.per.authOnly }) - async define(@Query('type') type: string,@Query('addonType') addonType: string) { - return await super.define(type,addonType); + @Post("/define", { description: Constants.per.authOnly }) + async define(@Query("type") type: string, @Query("addonType") addonType: string) { + return await super.define(type, addonType); } - @Post('/getTypeDict', { description: Constants.per.authOnly }) - async getTypeDict(@Query('addonType') addonType: string) { + @Post("/getTypeDict", { description: Constants.per.authOnly }) + async getTypeDict(@Query("addonType") addonType: string) { return await super.getTypeDict(addonType); } - @Post('/simpleInfo', { description: Constants.per.authOnly }) - async simpleInfo(@Query('addonType') addonType: string,@Query('id') id: number) { - return await super.simpleInfo(addonType,id); + @Post("/simpleInfo", { description: Constants.per.authOnly }) + async simpleInfo(@Query("addonType") addonType: string, @Query("id") id: number) { + return await super.simpleInfo(addonType, id); } - @Post('/getDefaultId', { description: Constants.per.authOnly }) - async getDefaultId(@Query('addonType') addonType: string) { - return await super.getDefaultId(addonType); + @Post("/getDefaultId", { description: Constants.per.authOnly }) + async getDefaultId(@Query("addonType") addonType: string) { + return await super.getDefaultId(addonType); } - @Post('/setDefault', { description: Constants.per.authOnly }) - async setDefault(@Query('addonType') addonType: string,@Query('id') id: number) { - return await super.setDefault(addonType,id); + @Post("/setDefault", { description: Constants.per.authOnly }) + async setDefault(@Query("addonType") addonType: string, @Query("id") id: number) { + return await super.setDefault(addonType, id); } - - @Post('/options', { description: Constants.per.authOnly }) - async options(@Query('addonType') addonType: string) { + @Post("/options", { description: Constants.per.authOnly }) + async options(@Query("addonType") addonType: string) { return await super.options(addonType); } - @Post('/handle', { description: Constants.per.authOnly }) + @Post("/handle", { description: Constants.per.authOnly }) async handle(@Body(ALL) body: AddonRequestHandleReq) { - return await super.handle(body); + return await super.handle(body); } } diff --git a/packages/ui/certd-server/src/controller/sys/authority/permission-controller.ts b/packages/ui/certd-server/src/controller/sys/authority/permission-controller.ts index ba09a6a38..d0277a198 100644 --- a/packages/ui/certd-server/src/controller/sys/authority/permission-controller.ts +++ b/packages/ui/certd-server/src/controller/sys/authority/permission-controller.ts @@ -1,12 +1,12 @@ -import { ALL, Body, Controller, Inject, Post, Provide, Query } from '@midwayjs/core'; -import { CrudController } from '@certd/lib-server'; -import { PermissionService } from '../../../modules/sys/authority/service/permission-service.js'; +import { ALL, Body, Controller, Inject, Post, Provide, Query } from "@midwayjs/core"; +import { CrudController } from "@certd/lib-server"; +import { PermissionService } from "../../../modules/sys/authority/service/permission-service.js"; /** * 权限资源 */ @Provide() -@Controller('/api/sys/authority/permission') +@Controller("/api/sys/authority/permission") export class PermissionController extends CrudController { @Inject() service: PermissionService; @@ -15,7 +15,7 @@ export class PermissionController extends CrudController { return this.service; } - @Post('/page', { description: 'sys:auth:per:view' }) + @Post("/page", { description: "sys:auth:per:view" }) async page( @Body(ALL) body @@ -23,7 +23,7 @@ export class PermissionController extends CrudController { return await super.page(body); } - @Post('/add', { description: 'sys:auth:per:add' }) + @Post("/add", { description: "sys:auth:per:add" }) async add( @Body(ALL) bean @@ -31,22 +31,22 @@ export class PermissionController extends CrudController { return await super.add(bean); } - @Post('/update', { description: 'sys:auth:per:edit' }) + @Post("/update", { description: "sys:auth:per:edit" }) async update( @Body(ALL) bean ) { return await super.update(bean); } - @Post('/delete', { description: 'sys:auth:per:remove' }) + @Post("/delete", { description: "sys:auth:per:remove" }) async delete( - @Query('id') + @Query("id") id: number ) { return await super.delete(id); } - @Post('/tree', { description: 'sys:auth:per:view' }) + @Post("/tree", { description: "sys:auth:per:view" }) async tree() { const tree = await this.service.tree({}); return this.ok(tree); diff --git a/packages/ui/certd-server/src/controller/sys/authority/role-controller.ts b/packages/ui/certd-server/src/controller/sys/authority/role-controller.ts index e76943f33..03df65471 100644 --- a/packages/ui/certd-server/src/controller/sys/authority/role-controller.ts +++ b/packages/ui/certd-server/src/controller/sys/authority/role-controller.ts @@ -1,12 +1,12 @@ -import { ALL, Body, Controller, Inject, Post, Provide, Query } from '@midwayjs/core'; -import { CrudController } from '@certd/lib-server'; -import { RoleService } from '../../../modules/sys/authority/service/role-service.js'; +import { ALL, Body, Controller, Inject, Post, Provide, Query } from "@midwayjs/core"; +import { CrudController } from "@certd/lib-server"; +import { RoleService } from "../../../modules/sys/authority/service/role-service.js"; /** * 系统用户 */ @Provide() -@Controller('/api/sys/authority/role') +@Controller("/api/sys/authority/role") export class RoleController extends CrudController { @Inject() service: RoleService; @@ -15,7 +15,7 @@ export class RoleController extends CrudController { return this.service; } - @Post('/page', { description: 'sys:auth:role:view' }) + @Post("/page", { description: "sys:auth:role:view" }) async page( @Body(ALL) body @@ -23,13 +23,13 @@ export class RoleController extends CrudController { return await super.page(body); } - @Post('/list', { description: 'sys:auth:role:view' }) + @Post("/list", { description: "sys:auth:role:view" }) async list() { const ret = await this.service.find({}); return this.ok(ret); } - @Post('/add', { description: 'sys:auth:role:add' }) + @Post("/add", { description: "sys:auth:role:add" }) async add( @Body(ALL) bean @@ -37,36 +37,36 @@ export class RoleController extends CrudController { return await super.add(bean); } - @Post('/update', { description: 'sys:auth:role:edit' }) + @Post("/update", { description: "sys:auth:role:edit" }) async update( @Body(ALL) bean ) { return await super.update(bean); } - @Post('/delete', { description: 'sys:auth:role:remove' }) + @Post("/delete", { description: "sys:auth:role:remove" }) async delete( - @Query('id') + @Query("id") id: number ) { if (id === 1) { - throw new Error('不能删除默认的管理员角色'); + throw new Error("不能删除默认的管理员角色"); } return await super.delete(id); } - @Post('/getPermissionTree', { description: 'sys:auth:role:view' }) + @Post("/getPermissionTree", { description: "sys:auth:role:view" }) async getPermissionTree( - @Query('id') + @Query("id") id: number ) { const ret = await this.service.getPermissionTreeByRoleId(id); return this.ok(ret); } - @Post('/getPermissionIds', { description: 'sys:auth:role:view' }) + @Post("/getPermissionIds", { description: "sys:auth:role:view" }) async getPermissionIds( - @Query('id') + @Query("id") id: number ) { const ret = await this.service.getPermissionIdsByRoleId(id); @@ -78,8 +78,8 @@ export class RoleController extends CrudController { * @param roleId * @param permissionIds */ - @Post('/authz', { description: 'sys:auth:role:edit' }) - async authz(@Body('roleId') roleId, @Body('permissionIds') permissionIds) { + @Post("/authz", { description: "sys:auth:role:edit" }) + async authz(@Body("roleId") roleId, @Body("permissionIds") permissionIds) { await this.service.authz(roleId, permissionIds); return this.ok(null); } diff --git a/packages/ui/certd-server/src/controller/sys/authority/user-controller.ts b/packages/ui/certd-server/src/controller/sys/authority/user-controller.ts index 1faf30334..19d317de5 100644 --- a/packages/ui/certd-server/src/controller/sys/authority/user-controller.ts +++ b/packages/ui/certd-server/src/controller/sys/authority/user-controller.ts @@ -1,17 +1,17 @@ -import {Provide, Controller, Post, Inject, Body, Query, ALL} from '@midwayjs/core'; -import {UserService} from '../../../modules/sys/authority/service/user-service.js'; -import {CrudController} from '@certd/lib-server'; -import {RoleService} from '../../../modules/sys/authority/service/role-service.js'; -import {PermissionService} from '../../../modules/sys/authority/service/permission-service.js'; -import {Constants} from '@certd/lib-server'; -import {In} from 'typeorm'; -import {LoginService} from "../../../modules/login/service/login-service.js"; +import { Provide, Controller, Post, Inject, Body, Query, ALL } from "@midwayjs/core"; +import { UserService } from "../../../modules/sys/authority/service/user-service.js"; +import { CrudController } from "@certd/lib-server"; +import { RoleService } from "../../../modules/sys/authority/service/role-service.js"; +import { PermissionService } from "../../../modules/sys/authority/service/permission-service.js"; +import { Constants } from "@certd/lib-server"; +import { In } from "typeorm"; +import { LoginService } from "../../../modules/login/service/login-service.js"; /** * 系统用户 */ @Provide() -@Controller('/api/sys/authority/user') +@Controller("/api/sys/authority/user") export class UserController extends CrudController { @Inject() service: UserService; @@ -28,8 +28,8 @@ export class UserController extends CrudController { return this.service; } - @Post('/getSimpleUserByIds', {description: 'sys:auth:user:view'}) - async getSimpleUserByIds(@Body('ids') ids: number[]) { + @Post("/getSimpleUserByIds", { description: "sys:auth:user:view" }) + async getSimpleUserByIds(@Body("ids") ids: number[]) { const users = await this.service.find({ select: { id: true, @@ -46,8 +46,7 @@ export class UserController extends CrudController { return this.ok(users); } - - @Post('/getSimpleUsers', {description: 'sys:auth:user:view'}) + @Post("/getSimpleUsers", { description: "sys:auth:user:view" }) async getSimpleUsers() { const users = await this.service.find({ select: { @@ -61,10 +60,10 @@ export class UserController extends CrudController { return this.ok(users); } - @Post('/page', {description: 'sys:auth:user:view'}) + @Post("/page", { description: "sys:auth:user:view" }) async page( @Body(ALL) - body + body ) { const ret = await super.page(body); @@ -93,32 +92,32 @@ export class UserController extends CrudController { return ret; } - @Post('/add', {description: 'sys:auth:user:add'}) + @Post("/add", { description: "sys:auth:user:add" }) async add( @Body(ALL) - bean + bean ) { return await super.add(bean); } - @Post('/update', {description: 'sys:auth:user:edit'}) + @Post("/update", { description: "sys:auth:user:edit" }) async update( @Body(ALL) - bean + bean ) { return await super.update(bean); } - @Post('/delete', {description: 'sys:auth:user:remove'}) + @Post("/delete", { description: "sys:auth:user:remove" }) async delete( - @Query('id') - id: number + @Query("id") + id: number ) { if (id === 1) { - throw new Error('不能删除默认的管理员角色'); + throw new Error("不能删除默认的管理员角色"); } if (id === 3) { - throw new Error('不能删除默认的普通用户角色'); + throw new Error("不能删除默认的普通用户角色"); } return await super.delete(id); } @@ -126,12 +125,12 @@ export class UserController extends CrudController { /** * 解除登录锁定 */ - @Post('/unlockBlock', {description: "sys:auth:user:edit"}) - public async unlockBlock(@Body('id') id: number) { - const info = await this.service.info(id, ['password']); - this.loginService.clearCacheOnSuccess(info.username) + @Post("/unlockBlock", { description: "sys:auth:user:edit" }) + public async unlockBlock(@Body("id") id: number) { + const info = await this.service.info(id, ["password"]); + this.loginService.clearCacheOnSuccess(info.username); if (info.mobile) { - this.loginService.clearCacheOnSuccess(info.mobile) + this.loginService.clearCacheOnSuccess(info.mobile); } return this.ok(info); } @@ -139,17 +138,17 @@ export class UserController extends CrudController { /** * 当前登录用户的个人信息 */ - @Post('/mine', {description: Constants.per.authOnly}) + @Post("/mine", { description: Constants.per.authOnly }) public async mine() { const id = this.getUserId(); - const info = await this.service.info(id, ['password']); + const info = await this.service.info(id, ["password"]); return this.ok(info); } /** * 当前登录用户的权限列表 */ - @Post('/permissions', {description: Constants.per.authOnly}) + @Post("/permissions", { description: Constants.per.authOnly }) public async permissions() { const id = this.getUserId(); const permissions = await this.service.getUserPermissions(id); @@ -159,15 +158,11 @@ export class UserController extends CrudController { /** * 当前登录用户的权限树形列表 */ - @Post('/permissionTree', {description: Constants.per.authOnly}) + @Post("/permissionTree", { description: Constants.per.authOnly }) public async permissionTree() { const id = this.getUserId(); const permissions = await this.service.getUserPermissions(id); const tree = this.permissionService.buildTree(permissions); return this.ok(tree); } - - - - } diff --git a/packages/ui/certd-server/src/controller/sys/cname/cname-provider-controller.ts b/packages/ui/certd-server/src/controller/sys/cname/cname-provider-controller.ts index 9ba057cb9..47e341f25 100644 --- a/packages/ui/certd-server/src/controller/sys/cname/cname-provider-controller.ts +++ b/packages/ui/certd-server/src/controller/sys/cname/cname-provider-controller.ts @@ -1,13 +1,13 @@ -import { ALL, Body, Controller, Inject, Post, Provide, Query } from '@midwayjs/core'; -import { CrudController } from '@certd/lib-server'; -import { merge } from 'lodash-es'; -import { CnameProviderService } from '../../../modules/cname/service/cname-provider-service.js'; +import { ALL, Body, Controller, Inject, Post, Provide, Query } from "@midwayjs/core"; +import { CrudController } from "@certd/lib-server"; +import { merge } from "lodash-es"; +import { CnameProviderService } from "../../../modules/cname/service/cname-provider-service.js"; /** * 授权 */ @Provide() -@Controller('/api/sys/cname/provider') +@Controller("/api/sys/cname/provider") export class CnameRecordController extends CrudController { @Inject() service: CnameProviderService; @@ -16,18 +16,18 @@ export class CnameRecordController extends CrudController return this.service; } - @Post('/page', { description: 'sys:settings:view' }) + @Post("/page", { description: "sys:settings:view" }) async page(@Body(ALL) body: any) { body.query = body.query ?? {}; return await super.page(body); } - @Post('/list', { description: 'sys:settings:view' }) + @Post("/list", { description: "sys:settings:view" }) async list(@Body(ALL) body: any) { return super.list(body); } - @Post('/add', { description: 'sys:settings:edit' }) + @Post("/add", { description: "sys:settings:edit" }) async add(@Body(ALL) bean: any) { const def: any = { isDefault: false, @@ -38,36 +38,36 @@ export class CnameRecordController extends CrudController return super.add(bean); } - @Post('/update', { description: 'sys:settings:edit' }) + @Post("/update", { description: "sys:settings:edit" }) async update(@Body(ALL) bean: any) { bean.userId = this.getUserId(); return super.update(bean); } - @Post('/info', { description: 'sys:settings:view' }) - async info(@Query('id') id: number) { + @Post("/info", { description: "sys:settings:view" }) + async info(@Query("id") id: number) { return super.info(id); } - @Post('/delete', { description: 'sys:settings:edit' }) - async delete(@Query('id') id: number) { + @Post("/delete", { description: "sys:settings:edit" }) + async delete(@Query("id") id: number) { return super.delete(id); } - @Post('/deleteByIds', { description: 'sys:settings:edit' }) - async deleteByIds(@Body('ids') ids: number[]) { + @Post("/deleteByIds", { description: "sys:settings:edit" }) + async deleteByIds(@Body("ids") ids: number[]) { const res = await this.service.delete(ids); return this.ok(res); } - @Post('/setDefault', { description: 'sys:settings:edit' }) - async setDefault(@Body('id') id: number) { + @Post("/setDefault", { description: "sys:settings:edit" }) + async setDefault(@Body("id") id: number) { await this.service.setDefault(id); return this.ok(); } - @Post('/setDisabled', { description: 'sys:settings:edit' }) - async setDisabled(@Body('id') id: number, @Body('disabled') disabled: boolean) { + @Post("/setDisabled", { description: "sys:settings:edit" }) + async setDisabled(@Body("id") id: number, @Body("disabled") disabled: boolean) { await this.service.setDisabled(id, disabled); return this.ok(); } diff --git a/packages/ui/certd-server/src/controller/sys/console/statistic-controller.ts b/packages/ui/certd-server/src/controller/sys/console/statistic-controller.ts index cedc9fac9..55b5ab535 100644 --- a/packages/ui/certd-server/src/controller/sys/console/statistic-controller.ts +++ b/packages/ui/certd-server/src/controller/sys/console/statistic-controller.ts @@ -1,9 +1,9 @@ -import { Controller, Inject, Post, Provide } from '@midwayjs/core'; -import { BaseController } from '@certd/lib-server'; -import { UserService } from '../../../modules/sys/authority/service/user-service.js'; -import { RoleService } from '../../../modules/sys/authority/service/role-service.js'; -import { PipelineService } from '../../../modules/pipeline/service/pipeline-service.js'; -import { HistoryService } from '../../../modules/pipeline/service/history-service.js'; +import { Controller, Inject, Post, Provide } from "@midwayjs/core"; +import { BaseController } from "@certd/lib-server"; +import { UserService } from "../../../modules/sys/authority/service/user-service.js"; +import { RoleService } from "../../../modules/sys/authority/service/role-service.js"; +import { PipelineService } from "../../../modules/pipeline/service/pipeline-service.js"; +import { HistoryService } from "../../../modules/pipeline/service/history-service.js"; export type ChartItem = { name: string; @@ -19,7 +19,7 @@ export type SysStatisticCount = { /** */ @Provide() -@Controller('/api/sys/statistic/') +@Controller("/api/sys/statistic/") export class SysStatisticController extends BaseController { @Inject() userService: UserService; @@ -31,7 +31,7 @@ export class SysStatisticController extends BaseController { @Inject() historyService: HistoryService; - @Post('/count', { description: 'sys:settings:view' }) + @Post("/count", { description: "sys:settings:view" }) public async count() { const userCount = await this.userService.count(); const userRegisterCountPerDay = await this.userService.registerCountPerDay({ days: 7 }); diff --git a/packages/ui/certd-server/src/controller/sys/enterprise/project-controller.ts b/packages/ui/certd-server/src/controller/sys/enterprise/project-controller.ts index a37cb2ba6..e2b1d5c81 100644 --- a/packages/ui/certd-server/src/controller/sys/enterprise/project-controller.ts +++ b/packages/ui/certd-server/src/controller/sys/enterprise/project-controller.ts @@ -40,7 +40,7 @@ export class SysProjectController extends CrudController { bean.userId = this.getUserId(); return super.add({ ...bean, - userId:-1, //企业用户id固定为-1 + userId: -1, //企业用户id固定为-1 adminId: bean.userId, }); } diff --git a/packages/ui/certd-server/src/controller/sys/enterprise/project-member-controller.ts b/packages/ui/certd-server/src/controller/sys/enterprise/project-member-controller.ts index 345698559..8998ce5ee 100644 --- a/packages/ui/certd-server/src/controller/sys/enterprise/project-member-controller.ts +++ b/packages/ui/certd-server/src/controller/sys/enterprise/project-member-controller.ts @@ -55,12 +55,12 @@ export class SysProjectMemberController extends CrudController { @Inject() service: PluginService; @@ -23,18 +19,18 @@ export class PluginController extends CrudController { return this.service; } - @Post('/page', { description: 'sys:settings:view' }) + @Post("/page", { description: "sys:settings:view" }) async page(@Body(ALL) body: any) { body.query = body.query ?? {}; return await super.page(body); } - @Post('/list', { description: 'sys:settings:view' }) + @Post("/list", { description: "sys:settings:view" }) async list(@Body(ALL) body: any) { return super.list(body); } - @Post('/add', { description: 'sys:settings:edit' }) + @Post("/add", { description: "sys:settings:edit" }) async add(@Body(ALL) bean: any) { const def: any = { isDefault: false, @@ -44,69 +40,68 @@ export class PluginController extends CrudController { return super.add(bean); } - @Post('/update', { description: 'sys:settings:edit' }) + @Post("/update", { description: "sys:settings:edit" }) async update(@Body(ALL) bean: any) { - const res = await super.update(bean); - return res + return res; } - @Post('/info', { description: 'sys:settings:view' }) - async info(@Query('id') id: number) { + @Post("/info", { description: "sys:settings:view" }) + async info(@Query("id") id: number) { return super.info(id); } - @Post('/delete', { description: 'sys:settings:edit' }) - async delete(@Query('id') id: number) { + @Post("/delete", { description: "sys:settings:edit" }) + async delete(@Query("id") id: number) { const res = await this.service.deleteByIds([id]); return this.ok(res); } - @Post('/deleteByIds', { description: 'sys:settings:edit' }) - async deleteByIds(@Body('ids') ids: number[]) { + @Post("/deleteByIds", { description: "sys:settings:edit" }) + async deleteByIds(@Body("ids") ids: number[]) { const res = await this.service.deleteByIds(ids); return this.ok(res); } - @Post('/setDisabled', { description: 'sys:settings:edit' }) + @Post("/setDisabled", { description: "sys:settings:edit" }) async setDisabled(@Body(ALL) body: { id: number; name: string; type: string; disabled: boolean }) { await this.service.setDisabled(body); return this.ok(); } - @Post('/getCommPluginConfigs', { description: 'sys:settings:view' }) + @Post("/getCommPluginConfigs", { description: "sys:settings:view" }) async getCommPluginConfigs() { const res = await this.pluginConfigService.getCommPluginConfig(); return this.ok(res); } - @Post('/saveCommPluginConfigs', { description: 'sys:settings:edit' }) + @Post("/saveCommPluginConfigs", { description: "sys:settings:edit" }) async saveCommPluginConfigs(@Body(ALL) body: CommPluginConfig) { const res = await this.pluginConfigService.saveCommPluginConfig(body); return this.ok(res); } - @Post('/getPluginByName', { description: 'sys:settings:view' }) - async getPluginByName(@Body('name') name: string) { + @Post("/getPluginByName", { description: "sys:settings:view" }) + async getPluginByName(@Body("name") name: string) { const res = await this.pluginConfigService.getPluginConfig({ name: name, - type: 'builtIn' + type: "builtIn", }); return this.ok(res); } - @Post('/saveSetting', { description: 'sys:settings:edit' }) + @Post("/saveSetting", { description: "sys:settings:edit" }) async saveSetting(@Body(ALL) body: PluginConfig) { const res = await this.pluginConfigService.savePluginConfig(body); return this.ok(res); } - @Post('/import', { description: 'sys:settings:edit' }) + @Post("/import", { description: "sys:settings:edit" }) async import(@Body(ALL) body: PluginImportReq) { const res = await this.service.importPlugin(body); return this.ok(res); } - @Post('/export', { description: 'sys:settings:edit' }) - async export(@Body('id') id: number) { + @Post("/export", { description: "sys:settings:edit" }) + async export(@Body("id") id: number) { const res = await this.service.exportPlugin(id); return this.ok(res); } diff --git a/packages/ui/certd-server/src/controller/sys/plus/plus-controller.ts b/packages/ui/certd-server/src/controller/sys/plus/plus-controller.ts index adb1b8390..d7b7c04f1 100644 --- a/packages/ui/certd-server/src/controller/sys/plus/plus-controller.ts +++ b/packages/ui/certd-server/src/controller/sys/plus/plus-controller.ts @@ -1,11 +1,11 @@ -import { ALL, Body, Controller, Inject, Post, Provide } from '@midwayjs/core'; -import { BaseController, PlusService, SysInstallInfo, SysSettingsService } from '@certd/lib-server'; -import { logger } from '@certd/basic'; +import { ALL, Body, Controller, Inject, Post, Provide } from "@midwayjs/core"; +import { BaseController, PlusService, SysInstallInfo, SysSettingsService } from "@certd/lib-server"; +import { logger } from "@certd/basic"; /** */ @Provide() -@Controller('/api/sys/plus') +@Controller("/api/sys/plus") export class SysPlusController extends BaseController { @Inject() sysSettingsService: SysSettingsService; @@ -13,7 +13,7 @@ export class SysPlusController extends BaseController { @Inject() plusService: PlusService; - @Post('/active', { description: 'sys:settings:edit' }) + @Post("/active", { description: "sys:settings:edit" }) async active(@Body(ALL) body) { const { code, inviteCode } = body; @@ -21,33 +21,32 @@ export class SysPlusController extends BaseController { return this.ok(true); } - @Post('/bindUrl', { description: 'sys:settings:edit' }) - async bindUrl(@Body(ALL) body: { url: string ,url2?:string }) { - const { url,url2 } = body; + @Post("/bindUrl", { description: "sys:settings:edit" }) + async bindUrl(@Body(ALL) body: { url: string; url2?: string }) { + const { url, url2 } = body; await this.plusService.register(); const installInfo: SysInstallInfo = await this.sysSettingsService.getSetting(SysInstallInfo); - await this.plusService.bindUrl(url,url2); + await this.plusService.bindUrl(url, url2); installInfo.bindUrl = url; installInfo.bindUrl2 = url2; await this.sysSettingsService.saveSetting(installInfo); //重新验证vip - try{ + try { await this.plusService.verify(); - }catch(e){ + } catch (e) { logger.error(`验证配置失败:${e}`); } - return this.ok(true); } - @Post('/getVipTrial', { description: 'sys:settings:edit' }) - async getVipTrial(@Body("vipType") vipType?:string) { + @Post("/getVipTrial", { description: "sys:settings:edit" }) + async getVipTrial(@Body("vipType") vipType?: string) { const res = await this.plusService.getVipTrial(vipType); return this.ok(res); } - @Post('/getTodayVipOrderCount', { description: 'sys:settings:edit' }) + @Post("/getTodayVipOrderCount", { description: "sys:settings:edit" }) async getTodayVipOrderCount() { const res = await this.plusService.getTodayOrderCount(); return this.ok(res); diff --git a/packages/ui/certd-server/src/controller/sys/settings/sys-safe-settings-controller.ts b/packages/ui/certd-server/src/controller/sys/settings/sys-safe-settings-controller.ts index 30053ec07..52cc53537 100644 --- a/packages/ui/certd-server/src/controller/sys/settings/sys-safe-settings-controller.ts +++ b/packages/ui/certd-server/src/controller/sys/settings/sys-safe-settings-controller.ts @@ -3,21 +3,18 @@ import { BaseController, SysSafeSetting } from "@certd/lib-server"; import { cloneDeep } from "lodash-es"; import { SafeService } from "../../../modules/sys/settings/safe-service.js"; - /** */ @Provide() -@Controller('/api/sys/settings/safe') +@Controller("/api/sys/settings/safe") export class SysSettingsController extends BaseController { @Inject() safeService: SafeService; - - @Post("/get", { description: "sys:settings:view" }) async safeGet() { - const res = await this.safeService.getSafeSetting() - const clone:SysSafeSetting = cloneDeep(res); + const res = await this.safeService.getSafeSetting(); + const clone: SysSafeSetting = cloneDeep(res); delete clone.hidden?.openPassword; return this.ok(clone); } diff --git a/packages/ui/certd-server/src/controller/sys/settings/sys-settings-controller.ts b/packages/ui/certd-server/src/controller/sys/settings/sys-settings-controller.ts index bc2c254aa..19092fcb4 100644 --- a/packages/ui/certd-server/src/controller/sys/settings/sys-settings-controller.ts +++ b/packages/ui/certd-server/src/controller/sys/settings/sys-settings-controller.ts @@ -1,14 +1,5 @@ import { ALL, Body, Controller, Inject, Post, Provide, Query, RequestIP } from "@midwayjs/core"; -import { - addonRegistry, - AddonService, - CrudController, - SysPrivateSettings, - SysPublicSettings, - SysSafeSetting, - SysSettingsEntity, - SysSettingsService -} from "@certd/lib-server"; +import { addonRegistry, AddonService, CrudController, SysPrivateSettings, SysPublicSettings, SysSafeSetting, SysSettingsEntity, SysSettingsService } from "@certd/lib-server"; import { cloneDeep, merge } from "lodash-es"; import { PipelineService } from "../../../modules/pipeline/service/pipeline-service.js"; import { UserSettingsService } from "../../../modules/mine/service/user-settings-service.js"; @@ -17,11 +8,10 @@ import { http, logger, utils } from "@certd/basic"; import { CodeService } from "../../../modules/basic/service/code-service.js"; import { SmsServiceFactory } from "../../../modules/basic/sms/factory.js"; - /** */ @Provide() -@Controller('/api/sys/settings') +@Controller("/api/sys/settings") export class SysSettingsController extends CrudController { @Inject() service: SysSettingsService; @@ -31,84 +21,84 @@ export class SysSettingsController extends CrudController { pipelineService: PipelineService; @Inject() codeService: CodeService; - @Inject() + @Inject() addonService: AddonService; getService() { return this.service; } - @Post('/page', { description: 'sys:settings:view' }) + @Post("/page", { description: "sys:settings:view" }) async page(@Body(ALL) body) { return super.page(body); } - @Post('/list', { description: 'sys:settings:view' }) + @Post("/list", { description: "sys:settings:view" }) async list(@Body(ALL) body) { return super.list(body); } - @Post('/add', { description: 'sys:settings:edit' }) + @Post("/add", { description: "sys:settings:edit" }) async add(@Body(ALL) bean) { return super.add(bean); } - @Post('/update', { description: 'sys:settings:edit' }) + @Post("/update", { description: "sys:settings:edit" }) async update(@Body(ALL) bean) { await this.service.checkUserId(bean.id, this.getUserId()); return super.update(bean); } - @Post('/info', { description: 'sys:settings:view' }) - async info(@Query('id') id: number) { + @Post("/info", { description: "sys:settings:view" }) + async info(@Query("id") id: number) { await this.service.checkUserId(id, this.getUserId()); return super.info(id); } - @Post('/delete', { description: 'sys:settings:edit' }) - async delete(@Query('id') id: number) { + @Post("/delete", { description: "sys:settings:edit" }) + async delete(@Query("id") id: number) { await this.service.checkUserId(id, this.getUserId()); return super.delete(id); } - @Post('/save', { description: 'sys:settings:edit' }) + @Post("/save", { description: "sys:settings:edit" }) async save(@Body(ALL) bean: SysSettingsEntity) { await this.service.save(bean); return this.ok({}); } - @Post('/get', { description: 'sys:settings:view' }) - async get(@Query('key') key: string) { + @Post("/get", { description: "sys:settings:view" }) + async get(@Query("key") key: string) { const entity = await this.service.getByKey(key); return this.ok(entity); } // savePublicSettings - @Post('/getEmailSettings', { description: 'sys:settings:view' }) + @Post("/getEmailSettings", { description: "sys:settings:view" }) async getEmailSettings(@Body(ALL) body) { const conf = await getEmailSettings(this.service, this.userSettingsService); return this.ok(conf); } - @Post('/getEmailTemplates', { description: 'sys:settings:view' }) + @Post("/getEmailTemplates", { description: "sys:settings:view" }) async getEmailTemplates(@Body(ALL) body) { const conf = await getEmailSettings(this.service, this.userSettingsService); - const templates = conf.templates || {} + const templates = conf.templates || {}; - const emailTemplateProviders = await this.addonService.getDefineList("emailTemplate") + const emailTemplateProviders = await this.addonService.getDefineList("emailTemplate"); - const proviers = [] + const proviers = []; for (const item of emailTemplateProviders) { - const templateConf = templates[item.name] || {} + const templateConf = templates[item.name] || {}; proviers.push({ name: item.name, title: item.title, - addonId : templateConf.addonId, - }) + addonId: templateConf.addonId, + }); } return this.ok(proviers); } - @Post('/saveEmailSettings', { description: 'sys:settings:edit' }) + @Post("/saveEmailSettings", { description: "sys:settings:edit" }) async saveEmailSettings(@Body(ALL) body) { const conf = await getEmailSettings(this.service, this.userSettingsService); merge(conf, body); @@ -116,7 +106,7 @@ export class SysSettingsController extends CrudController { return this.ok(conf); } - @Post('/getSysSettings', { description: 'sys:settings:view' }) + @Post("/getSysSettings", { description: "sys:settings:view" }) async getSysSettings() { const publicSettings = await this.service.getPublicSettings(); let privateSettings = await this.service.getPrivateSettings(); @@ -125,7 +115,7 @@ export class SysSettingsController extends CrudController { } // savePublicSettings - @Post('/saveSysSettings', { description: 'sys:settings:edit' }) + @Post("/saveSysSettings", { description: "sys:settings:edit" }) async saveSysSettings(@Body(ALL) body: { public: SysPublicSettings; private: SysPrivateSettings }) { const publicSettings = await this.service.getPublicSettings(); const privateSettings = await this.service.getPrivateSettings(); @@ -136,21 +126,21 @@ export class SysSettingsController extends CrudController { return this.ok({}); } - @Post('/stopOtherUserTimer', { description: 'sys:settings:edit' }) + @Post("/stopOtherUserTimer", { description: "sys:settings:edit" }) async stopOtherUserTimer(@Body(ALL) body) { await this.pipelineService.stopOtherUserPipeline(1); return this.ok({}); } - @Post('/testProxy', { description: 'sys:settings:edit' }) + @Post("/testProxy", { description: "sys:settings:edit" }) async testProxy(@Body(ALL) body) { - const google = 'https://www.google.com/'; - const baidu = 'https://www.baidu.com/'; + const google = "https://www.google.com/"; + const baidu = "https://www.baidu.com/"; let googleRes = false; try { await http.request({ url: google, - method: 'GET', + method: "GET", timeout: 5000, logRes: false, logParams: false, @@ -158,13 +148,13 @@ export class SysSettingsController extends CrudController { googleRes = true; } catch (e) { googleRes = e.message; - logger.info('test google error:', e); + logger.info("test google error:", e); } let baiduRes = false; try { await http.request({ url: baidu, - method: 'GET', + method: "GET", timeout: 5000, logRes: false, logParams: false, @@ -172,7 +162,7 @@ export class SysSettingsController extends CrudController { baiduRes = true; } catch (e) { baiduRes = e.message; - logger.info('test baidu error:', e); + logger.info("test baidu error:", e); } return this.ok({ google: googleRes, @@ -180,51 +170,48 @@ export class SysSettingsController extends CrudController { }); } - @Post('/testSms', { description: 'sys:settings:edit' }) + @Post("/testSms", { description: "sys:settings:edit" }) async testSms(@Body(ALL) body) { - await this.codeService.sendSmsCode(body.phoneCode, body.mobile ); + await this.codeService.sendSmsCode(body.phoneCode, body.mobile); return this.ok({}); } - @Post('/getSmsTypeDefine', { description: 'sys:settings:view' }) - async getSmsTypeDefine(@Body('type') type: string) { - const define =await SmsServiceFactory.getDefine(type); + @Post("/getSmsTypeDefine", { description: "sys:settings:view" }) + async getSmsTypeDefine(@Body("type") type: string) { + const define = await SmsServiceFactory.getDefine(type); return this.ok(define); } - - @Post("/safe/get", { description: "sys:settings:view" }) async safeGet() { const res = await this.service.getSetting(SysSafeSetting); - const clone:SysSafeSetting = cloneDeep(res); + const clone: SysSafeSetting = cloneDeep(res); delete clone.hidden?.openPassword; return this.ok(clone); } @Post("/safe/save", { description: "sys:settings:edit" }) async safeSave(@Body(ALL) body: any) { - if(body.hidden.openPassword){ + if (body.hidden.openPassword) { body.hidden.openPassword = utils.hash.md5(body.hidden.openPassword); } - const blankSetting = new SysSafeSetting() + const blankSetting = new SysSafeSetting(); const setting = await this.service.getSetting(SysSafeSetting); - const newSetting = merge(blankSetting,cloneDeep(setting), body); - if(newSetting.hidden?.enabled && !newSetting.hidden?.openPassword){ - throw new Error("首次设置需要填写解锁密码") + const newSetting = merge(blankSetting, cloneDeep(setting), body); + if (newSetting.hidden?.enabled && !newSetting.hidden?.openPassword) { + throw new Error("首次设置需要填写解锁密码"); } await this.service.saveSetting(blankSetting); return this.ok({}); } - @Post("/captchaTest", { description: "sys:settings:edit" }) - async captchaTest(@Body(ALL) body: any,@RequestIP() remoteIp: string) { - await this.codeService.checkCaptcha(body,{remoteIp}); + async captchaTest(@Body(ALL) body: any, @RequestIP() remoteIp: string) { + await this.codeService.checkCaptcha(body, { remoteIp }); return this.ok({}); } - @Post('/oauth/providers', { description: 'sys:settings:view' }) + @Post("/oauth/providers", { description: "sys:settings:view" }) async oauthProviders() { const list = await addonRegistry.getDefineList("oauth"); return this.ok(list); diff --git a/packages/ui/certd-server/src/controller/user/addon/addon-controller.ts b/packages/ui/certd-server/src/controller/user/addon/addon-controller.ts index 86bc84914..b7f310bff 100644 --- a/packages/ui/certd-server/src/controller/user/addon/addon-controller.ts +++ b/packages/ui/certd-server/src/controller/user/addon/addon-controller.ts @@ -1,13 +1,5 @@ import { ALL, Body, Controller, Inject, Post, Provide, Query } from "@midwayjs/core"; -import { - AddonDefine, - AddonRequestHandleReq, - AddonService, - Constants, - CrudController, - newAddon, - ValidateException -} from "@certd/lib-server"; +import { AddonDefine, AddonRequestHandleReq, AddonService, Constants, CrudController, newAddon, ValidateException } from "@certd/lib-server"; import { AuthService } from "../../../modules/sys/authority/service/auth-service.js"; import { checkPlus } from "@certd/plus-core"; import { http, logger, utils } from "@certd/basic"; @@ -19,14 +11,14 @@ import { ApiTags } from "@midwayjs/swagger"; */ @Provide() @Controller("/api/addon") -@ApiTags(['addon']) +@ApiTags(["addon"]) export class AddonController extends CrudController { @Inject() service: AddonService; @Inject() authService: AuthService; @Inject() - taskServiceBuilder:TaskServiceBuilder + taskServiceBuilder: TaskServiceBuilder; getService(): AddonService { return this.service; @@ -34,7 +26,7 @@ export class AddonController extends CrudController { @Post("/page", { description: Constants.per.authOnly, summary: "查询Addon分页列表" }) async page(@Body(ALL) body) { - const {projectId,userId} = await this.getProjectUserIdRead(); + const { projectId, userId } = await this.getProjectUserIdRead(); body.query = body.query ?? {}; delete body.query.userId; body.query.projectId = projectId; @@ -45,14 +37,14 @@ export class AddonController extends CrudController { query: body.query, page: body.page, sort: body.sort, - buildQuery + buildQuery, }); return this.ok(res); } @Post("/list", { description: Constants.per.authOnly, summary: "查询Addon列表" }) async list(@Body(ALL) body) { - const {projectId,userId} = await this.getProjectUserIdRead(); + const { projectId, userId } = await this.getProjectUserIdRead(); body.query = body.query ?? {}; body.query.userId = userId; body.query.projectId = projectId; @@ -61,7 +53,7 @@ export class AddonController extends CrudController { @Post("/add", { description: Constants.per.authOnly, summary: "添加Addon" }) async add(@Body(ALL) bean) { - const {userId,projectId} = await this.getProjectUserIdRead(); + const { userId, projectId } = await this.getProjectUserIdRead(); bean.userId = userId; bean.projectId = projectId; const type = bean.type; @@ -129,7 +121,7 @@ export class AddonController extends CrudController { value: item.name, label: item.title, needPlus: item.needPlus ?? false, - icon: item.icon + icon: item.icon, }); } dict = dict.sort(a => { @@ -142,43 +134,42 @@ export class AddonController extends CrudController { async simpleInfo(@Query("addonType") addonType: string, @Query("id") id: number) { if (id === 0) { //获取默认 - const {projectId,userId} = await this.getProjectUserIdRead(); - const res = await this.service.getDefault(userId, addonType,projectId); + const { projectId, userId } = await this.getProjectUserIdRead(); + const res = await this.service.getDefault(userId, addonType, projectId); if (!res) { throw new ValidateException("默认Addon配置不存在"); } const simple = await this.service.getSimpleInfo(res.id); return this.ok(simple); } - await this.checkOwner(this.getService(), id, "read",true); + await this.checkOwner(this.getService(), id, "read", true); const res = await this.service.getSimpleInfo(id); return this.ok(res); } @Post("/getDefaultId", { description: Constants.per.authOnly, summary: "查询Addon插件默认配置ID" }) async getDefaultId(@Query("addonType") addonType: string) { - const {projectId,userId} = await this.getProjectUserIdRead(); - const res = await this.service.getDefault(userId, addonType,projectId); + const { projectId, userId } = await this.getProjectUserIdRead(); + const res = await this.service.getDefault(userId, addonType, projectId); return this.ok(res?.id); } @Post("/setDefault", { description: Constants.per.authOnly, summary: "设置Addon插件默认配置" }) async setDefault(@Query("addonType") addonType: string, @Query("id") id: number) { - const {projectId,userId} = await this.checkOwner(this.getService(), id, "write",true); - const res = await this.service.setDefault(id, userId, addonType,projectId); + const { projectId, userId } = await this.checkOwner(this.getService(), id, "write", true); + const res = await this.service.setDefault(id, userId, addonType, projectId); return this.ok(res); } - @Post("/options", { description: Constants.per.authOnly, summary: "查询Addon插件配置字典" }) async options(@Query("addonType") addonType: string) { - const {projectId,userId} = await this.getProjectUserIdRead(); + const { projectId, userId } = await this.getProjectUserIdRead(); const res = await this.service.list({ query: { userId, addonType, - projectId - } + projectId, + }, }); for (const item of res) { delete item.setting; @@ -186,25 +177,24 @@ export class AddonController extends CrudController { return this.ok(res); } - @Post("/handle", { description: Constants.per.authOnly, summary: "Addon插件处理请求" }) async handle(@Body(ALL) body: AddonRequestHandleReq) { let inputAddon = body.input.addon; if (body.input.id > 0) { - await this.checkOwner(this.getService(), body.input.id, "write",true); + await this.checkOwner(this.getService(), body.input.id, "write", true); const oldEntity = await this.service.info(body.input.id); if (oldEntity) { inputAddon = JSON.parse(oldEntity.setting); } } - const {projectId,userId} = await this.getProjectUserIdRead(); - const serviceGetter = this.taskServiceBuilder.create({ userId,projectId }); + const { projectId, userId } = await this.getProjectUserIdRead(); + const serviceGetter = this.taskServiceBuilder.create({ userId, projectId }); const ctx = { http: http, logger: logger, utils: utils, - serviceGetter + serviceGetter, }; const addon = await newAddon(body.addonType, body.typeName, inputAddon, ctx); const res = await addon.onRequest(body); diff --git a/packages/ui/certd-server/src/controller/user/basic/group-controller.ts b/packages/ui/certd-server/src/controller/user/basic/group-controller.ts index 937408ffd..ed38e427b 100644 --- a/packages/ui/certd-server/src/controller/user/basic/group-controller.ts +++ b/packages/ui/certd-server/src/controller/user/basic/group-controller.ts @@ -1,15 +1,15 @@ -import { ALL, Body, Controller, Inject, Post, Provide, Query } from '@midwayjs/core'; -import { Constants, CrudController } from '@certd/lib-server'; -import { AuthService } from '../../../modules/sys/authority/service/auth-service.js'; -import { GroupService } from '../../../modules/basic/service/group-service.js'; -import { ApiTags } from '@midwayjs/swagger'; +import { ALL, Body, Controller, Inject, Post, Provide, Query } from "@midwayjs/core"; +import { Constants, CrudController } from "@certd/lib-server"; +import { AuthService } from "../../../modules/sys/authority/service/auth-service.js"; +import { GroupService } from "../../../modules/basic/service/group-service.js"; +import { ApiTags } from "@midwayjs/swagger"; /** * 通知 */ @Provide() -@Controller('/api/basic/group') -@ApiTags(['basic-group']) +@Controller("/api/basic/group") +@ApiTags(["basic-group"]) export class GroupController extends CrudController { @Inject() service: GroupService; @@ -20,14 +20,14 @@ export class GroupController extends CrudController { return this.service; } - @Post('/page', { description: Constants.per.authOnly, summary: "查询分组分页列表" }) + @Post("/page", { description: Constants.per.authOnly, summary: "查询分组分页列表" }) async page(@Body(ALL) body: any) { - const {projectId,userId} = await this.getProjectUserIdRead(); + const { projectId, userId } = await this.getProjectUserIdRead(); body.query = body.query ?? {}; body.query.projectId = projectId; delete body.query.userId; const buildQuery = qb => { - qb.andWhere('user_id = :userId', { userId }); + qb.andWhere("user_id = :userId", { userId }); }; const res = await this.service.page({ query: body.query, @@ -38,45 +38,45 @@ export class GroupController extends CrudController { return this.ok(res); } - @Post('/list', { description: Constants.per.authOnly, summary: "查询分组列表" }) + @Post("/list", { description: Constants.per.authOnly, summary: "查询分组列表" }) async list(@Body(ALL) body: any) { - const {projectId,userId} = await this.getProjectUserIdRead(); + const { projectId, userId } = await this.getProjectUserIdRead(); body.query = body.query ?? {}; body.query.projectId = projectId; body.query.userId = userId; return await super.list(body); } - @Post('/add', { description: Constants.per.authOnly, summary: "添加分组" }) + @Post("/add", { description: Constants.per.authOnly, summary: "添加分组" }) async add(@Body(ALL) bean: any) { - const {projectId,userId} = await this.getProjectUserIdRead(); + const { projectId, userId } = await this.getProjectUserIdRead(); bean.projectId = projectId; bean.userId = userId; return await super.add(bean); } - @Post('/update', { description: Constants.per.authOnly, summary: "更新分组" }) + @Post("/update", { description: Constants.per.authOnly, summary: "更新分组" }) async update(@Body(ALL) bean) { await this.checkOwner(this.getService(), bean.id, "write"); delete bean.userId; delete bean.projectId; return await super.update(bean); } - @Post('/info', { description: Constants.per.authOnly, summary: "查询分组详情" }) - async info(@Query('id') id: number) { + @Post("/info", { description: Constants.per.authOnly, summary: "查询分组详情" }) + async info(@Query("id") id: number) { await this.checkOwner(this.getService(), id, "read"); return await super.info(id); } - @Post('/delete', { description: Constants.per.authOnly, summary: "删除分组" }) - async delete(@Query('id') id: number) { + @Post("/delete", { description: Constants.per.authOnly, summary: "删除分组" }) + async delete(@Query("id") id: number) { await this.checkOwner(this.getService(), id, "write"); return await super.delete(id); } - @Post('/all', { description: Constants.per.authOnly, summary: "查询所有分组" }) - async all(@Query('type') type: string) { - const {projectId,userId} = await this.getProjectUserIdRead(); + @Post("/all", { description: Constants.per.authOnly, summary: "查询所有分组" }) + async all(@Query("type") type: string) { + const { projectId, userId } = await this.getProjectUserIdRead(); const list: any = await this.service.find({ where: { projectId, diff --git a/packages/ui/certd-server/src/controller/user/basic/user-controller.ts b/packages/ui/certd-server/src/controller/user/basic/user-controller.ts index 64f9d07ab..601b61152 100644 --- a/packages/ui/certd-server/src/controller/user/basic/user-controller.ts +++ b/packages/ui/certd-server/src/controller/user/basic/user-controller.ts @@ -1,34 +1,34 @@ -import { Constants, isEnterprise } from '@certd/lib-server'; -import { Body, Controller, Inject, Post, Provide } from '@midwayjs/core'; -import { In } from 'typeorm'; -import { AuthService } from '../../../modules/sys/authority/service/auth-service.js'; -import { UserService } from '../../../modules/sys/authority/service/user-service.js'; -import { BasicController } from '../../basic/code-controller.js'; -import { RoleService } from '../../../modules/sys/authority/service/role-service.js'; -import { ApiTags } from '@midwayjs/swagger'; +import { Constants, isEnterprise } from "@certd/lib-server"; +import { Body, Controller, Inject, Post, Provide } from "@midwayjs/core"; +import { In } from "typeorm"; +import { AuthService } from "../../../modules/sys/authority/service/auth-service.js"; +import { UserService } from "../../../modules/sys/authority/service/user-service.js"; +import { BasicController } from "../../basic/code-controller.js"; +import { RoleService } from "../../../modules/sys/authority/service/role-service.js"; +import { ApiTags } from "@midwayjs/swagger"; /** * 通知 */ @Provide() -@Controller('/api/basic/user') -@ApiTags(['basic-user']) +@Controller("/api/basic/user") +@ApiTags(["basic-user"]) export class BasicUserController extends BasicController { @Inject() service: UserService; @Inject() authService: AuthService; - @Inject() + @Inject() roleService: RoleService; getService(): UserService { return this.service; } - @Post('/getSimpleUserByIds', { description: Constants.per.authOnly, summary: "根据ID列表获取用户简单信息" }) - async getSimpleUserByIds(@Body('ids') ids: number[]) { - if(!isEnterprise()){ - throw new Error('非企业模式不能获取用户信息'); + @Post("/getSimpleUserByIds", { description: Constants.per.authOnly, summary: "根据ID列表获取用户简单信息" }) + async getSimpleUserByIds(@Body("ids") ids: number[]) { + if (!isEnterprise()) { + throw new Error("非企业模式不能获取用户信息"); } const users = await this.service.find({ select: { @@ -45,10 +45,10 @@ export class BasicUserController extends BasicController { return this.ok(users); } - @Post('/getSimpleUsers', {description: Constants.per.authOnly, summary: "获取所有用户简单信息"}) + @Post("/getSimpleUsers", { description: Constants.per.authOnly, summary: "获取所有用户简单信息" }) async getSimpleUsers() { - if(!isEnterprise()){ - throw new Error('非企业模式不能获取所有用户信息'); + if (!isEnterprise()) { + throw new Error("非企业模式不能获取所有用户信息"); } const users = await this.service.find({ select: { @@ -62,7 +62,7 @@ export class BasicUserController extends BasicController { return this.ok(users); } - @Post('/getSimpleRoles', {description: Constants.per.authOnly, summary: "获取所有角色简单信息"}) + @Post("/getSimpleRoles", { description: Constants.per.authOnly, summary: "获取所有角色简单信息" }) async getSimpleRoles() { const roles = await this.roleService.find({ select: { @@ -72,5 +72,4 @@ export class BasicUserController extends BasicController { }); return this.ok(roles); } - } diff --git a/packages/ui/certd-server/src/controller/user/cert/domain-controller.ts b/packages/ui/certd-server/src/controller/user/cert/domain-controller.ts index 4f3091040..6644b56fd 100644 --- a/packages/ui/certd-server/src/controller/user/cert/domain-controller.ts +++ b/packages/ui/certd-server/src/controller/user/cert/domain-controller.ts @@ -1,16 +1,16 @@ -import { ALL, Body, Controller, Inject, Post, Provide, Query } from '@midwayjs/core'; -import { Constants, CrudController } from '@certd/lib-server'; +import { ALL, Body, Controller, Inject, Post, Provide, Query } from "@midwayjs/core"; +import { Constants, CrudController } from "@certd/lib-server"; import { DomainService } from "../../../modules/cert/service/domain-service.js"; -import { checkPlus } from '@certd/plus-core'; -import { ApiTags } from '@midwayjs/swagger'; -import { parseDomainByPsl } from '@certd/plugin-lib'; +import { checkPlus } from "@certd/plus-core"; +import { ApiTags } from "@midwayjs/swagger"; +import { parseDomainByPsl } from "@certd/plugin-lib"; /** * 授权 */ @Provide() -@Controller('/api/cert/domain') -@ApiTags(['cert']) +@Controller("/api/cert/domain") +@ApiTags(["cert"]) export class DomainController extends CrudController { @Inject() service: DomainService; @@ -19,7 +19,7 @@ export class DomainController extends CrudController { return this.service; } - @Post('/page', { description: Constants.per.authOnly, summary: "查询域名分页列表" }) + @Post("/page", { description: Constants.per.authOnly, summary: "查询域名分页列表" }) async page(@Body(ALL) body: any) { const { projectId, userId } = await this.getProjectUserIdRead(); body.query = body.query ?? {}; @@ -30,7 +30,7 @@ export class DomainController extends CrudController { const bq = qb => { if (domain) { - qb.andWhere('domain like :domain', { domain: `%${domain}%` }); + qb.andWhere("domain like :domain", { domain: `%${domain}%` }); } }; @@ -43,7 +43,7 @@ export class DomainController extends CrudController { return this.ok(pageRet); } - @Post('/list', { description: Constants.per.authOnly, summary: "查询域名列表" }) + @Post("/list", { description: Constants.per.authOnly, summary: "查询域名列表" }) async list(@Body(ALL) body: any) { const { projectId, userId } = await this.getProjectUserIdRead(); body.query = body.query ?? {}; @@ -53,7 +53,7 @@ export class DomainController extends CrudController { return this.ok(list); } - @Post('/add', { description: Constants.per.authOnly, summary: "添加域名" }) + @Post("/add", { description: Constants.per.authOnly, summary: "添加域名" }) async add(@Body(ALL) bean: any) { const { projectId, userId } = await this.getProjectUserIdRead(); bean.projectId = projectId; @@ -61,7 +61,7 @@ export class DomainController extends CrudController { return super.add(bean); } - @Post('/update', { description: Constants.per.authOnly, summary: "更新域名" }) + @Post("/update", { description: Constants.per.authOnly, summary: "更新域名" }) async update(@Body(ALL) bean: any) { await this.checkOwner(this.getService(), bean.id, "write"); delete bean.userId; @@ -69,19 +69,19 @@ export class DomainController extends CrudController { return super.update(bean); } - @Post('/info', { description: Constants.per.authOnly, summary: "查询域名详情" }) - async info(@Query('id') id: number) { + @Post("/info", { description: Constants.per.authOnly, summary: "查询域名详情" }) + async info(@Query("id") id: number) { await this.checkOwner(this.getService(), id, "read"); return super.info(id); } - @Post('/delete', { description: Constants.per.authOnly, summary: "删除域名" }) - async delete(@Query('id') id: number) { + @Post("/delete", { description: Constants.per.authOnly, summary: "删除域名" }) + async delete(@Query("id") id: number) { await this.checkOwner(this.getService(), id, "write"); return super.delete(id); } - @Post('/deleteByIds', { description: Constants.per.authOnly, summary: "批量删除域名" }) + @Post("/deleteByIds", { description: Constants.per.authOnly, summary: "批量删除域名" }) async deleteByIds(@Body(ALL) body: any) { const { projectId, userId } = await this.getProjectUserIdRead(); await this.service.delete(body.ids, { @@ -91,8 +91,7 @@ export class DomainController extends CrudController { return this.ok(); } - - @Post('/import/start', { description: Constants.per.authOnly, summary: "开始域名导入任务" }) + @Post("/import/start", { description: Constants.per.authOnly, summary: "开始域名导入任务" }) async importStart(@Body(ALL) body: any) { checkPlus(); const { projectId, userId } = await this.getProjectUserIdRead(); @@ -101,24 +100,23 @@ export class DomainController extends CrudController { key, userId: userId, projectId: projectId, - } + }; await this.service.startDomainImportTask(req); return this.ok(); } - @Post('/import/status', { description: Constants.per.authOnly, summary: "查询域名导入任务状态" }) + @Post("/import/status", { description: Constants.per.authOnly, summary: "查询域名导入任务状态" }) async importStatus() { const { projectId, userId } = await this.getProjectUserIdRead(); const req = { userId: userId, projectId: projectId, - } + }; const task = await this.service.getDomainImportTaskStatus(req); return this.ok(task); } - - @Post('/import/delete', { description: Constants.per.authOnly, summary: "删除域名导入任务" }) + @Post("/import/delete", { description: Constants.per.authOnly, summary: "删除域名导入任务" }) async importDelete(@Body(ALL) body: any) { const { projectId, userId } = await this.getProjectUserIdRead(); const { key } = body; @@ -126,12 +124,12 @@ export class DomainController extends CrudController { userId: userId, projectId: projectId, key, - } + }; await this.service.deleteDomainImportTask(req); return this.ok(); } - @Post('/import/save', { description: Constants.per.authOnly, summary: "保存域名导入任务" }) + @Post("/import/save", { description: Constants.per.authOnly, summary: "保存域名导入任务" }) async importSave(@Body(ALL) body: any) { checkPlus(); const { projectId, userId } = await this.getProjectUserIdRead(); @@ -139,61 +137,59 @@ export class DomainController extends CrudController { const req = { userId: userId, projectId: projectId, - dnsProviderType, dnsProviderAccessId, key - } + dnsProviderType, + dnsProviderAccessId, + key, + }; const item = await this.service.saveDomainImportTask(req); return this.ok(item); } - - @Post('/sync/expiration/start', { description: Constants.per.authOnly, summary: "开始同步域名过期时间任务" }) + @Post("/sync/expiration/start", { description: Constants.per.authOnly, summary: "开始同步域名过期时间任务" }) async syncExpirationStart(@Body(ALL) body: any) { const { projectId, userId } = await this.getProjectUserIdRead(); await this.service.startSyncExpirationTask({ userId: userId, projectId: projectId, - }) + }); return this.ok(); } - @Post('/sync/expiration/status', { description: Constants.per.authOnly, summary: "查询同步域名过期时间任务状态" }) + @Post("/sync/expiration/status", { description: Constants.per.authOnly, summary: "查询同步域名过期时间任务状态" }) async syncExpirationStatus(@Body(ALL) body: any) { const { projectId, userId } = await this.getProjectUserIdRead(); const status = await this.service.getSyncExpirationTaskStatus({ userId: userId, projectId: projectId, - }) + }); return this.ok(status); } - - - @Post('/setting/save', { description: Constants.per.authOnly, summary: "保存域名监控设置" }) + @Post("/setting/save", { description: Constants.per.authOnly, summary: "保存域名监控设置" }) async settingSave(@Body(ALL) body: any) { const { projectId, userId } = await this.getProjectUserIdWrite(); await this.service.monitorSettingSave({ userId: userId, projectId: projectId, - setting: {...body}, - }) + setting: { ...body }, + }); return this.ok(); } - @Post('/setting/get', { description: Constants.per.authOnly, summary: "查询域名监控设置" }) + @Post("/setting/get", { description: Constants.per.authOnly, summary: "查询域名监控设置" }) async settingGet() { const { projectId, userId } = await this.getProjectUserIdRead(); const setting = await this.service.monitorSettingGet({ userId: userId, projectId: projectId, - }) + }); return this.ok(setting); } - @Post('/isSubdomain', { description: Constants.per.authOnly, summary: "判断是否为子域名" }) + @Post("/isSubdomain", { description: Constants.per.authOnly, summary: "判断是否为子域名" }) async isSubdomain(@Body(ALL) body: any) { const { domain } = body; - const parsed = parseDomainByPsl(domain) - const mainDomain = parsed.domain || '' + const parsed = parseDomainByPsl(domain); + const mainDomain = parsed.domain || ""; return this.ok(mainDomain !== domain); } - } diff --git a/packages/ui/certd-server/src/controller/user/cname/cname-provider-controller.ts b/packages/ui/certd-server/src/controller/user/cname/cname-provider-controller.ts index d05d440ce..9ee687ea5 100644 --- a/packages/ui/certd-server/src/controller/user/cname/cname-provider-controller.ts +++ b/packages/ui/certd-server/src/controller/user/cname/cname-provider-controller.ts @@ -1,15 +1,15 @@ -import { ALL, Body, Controller, Inject, Post, Provide } from '@midwayjs/core'; -import { BaseController, Constants } from '@certd/lib-server'; -import { CnameRecordService } from '../../../modules/cname/service/cname-record-service.js'; -import { CnameProviderService } from '../../../modules/cname/service/cname-provider-service.js'; -import { ApiTags } from '@midwayjs/swagger'; +import { ALL, Body, Controller, Inject, Post, Provide } from "@midwayjs/core"; +import { BaseController, Constants } from "@certd/lib-server"; +import { CnameRecordService } from "../../../modules/cname/service/cname-record-service.js"; +import { CnameProviderService } from "../../../modules/cname/service/cname-provider-service.js"; +import { ApiTags } from "@midwayjs/swagger"; /** * 授权 */ @Provide() -@Controller('/api/cname/provider') -@ApiTags(['pipeline-cname']) +@Controller("/api/cname/provider") +@ApiTags(["pipeline-cname"]) export class CnameProviderController extends BaseController { @Inject() service: CnameRecordService; @@ -20,7 +20,7 @@ export class CnameProviderController extends BaseController { return this.service; } - @Post('/list', { description: Constants.per.authOnly, summary: "查询CNAME提供商列表" }) + @Post("/list", { description: Constants.per.authOnly, summary: "查询CNAME提供商列表" }) async list(@Body(ALL) body: any) { const res = await this.providerService.list({}); return this.ok(res); diff --git a/packages/ui/certd-server/src/controller/user/cname/cname-record-controller.ts b/packages/ui/certd-server/src/controller/user/cname/cname-record-controller.ts index d2c3a43d9..cc0879b67 100644 --- a/packages/ui/certd-server/src/controller/user/cname/cname-record-controller.ts +++ b/packages/ui/certd-server/src/controller/user/cname/cname-record-controller.ts @@ -1,14 +1,14 @@ -import { ALL, Body, Controller, Inject, Post, Provide, Query } from '@midwayjs/core'; -import { Constants, CrudController } from '@certd/lib-server'; -import { CnameRecordService } from '../../../modules/cname/service/cname-record-service.js'; -import { ApiTags } from '@midwayjs/swagger'; +import { ALL, Body, Controller, Inject, Post, Provide, Query } from "@midwayjs/core"; +import { Constants, CrudController } from "@certd/lib-server"; +import { CnameRecordService } from "../../../modules/cname/service/cname-record-service.js"; +import { ApiTags } from "@midwayjs/swagger"; /** * 授权 */ @Provide() -@Controller('/api/cname/record') -@ApiTags(['pipeline-cname']) +@Controller("/api/cname/record") +@ApiTags(["pipeline-cname"]) export class CnameRecordController extends CrudController { @Inject() service: CnameRecordService; @@ -17,9 +17,9 @@ export class CnameRecordController extends CrudController { return this.service; } - @Post('/page', { description: Constants.per.authOnly, summary: "查询CNAME记录分页列表" }) + @Post("/page", { description: Constants.per.authOnly, summary: "查询CNAME记录分页列表" }) async page(@Body(ALL) body: any) { - const {userId,projectId} = await this.getProjectUserIdRead(); + const { userId, projectId } = await this.getProjectUserIdRead(); body.query = body.query ?? {}; body.query.userId = userId; body.query.projectId = projectId; @@ -28,7 +28,7 @@ export class CnameRecordController extends CrudController { const bq = qb => { if (domain) { - qb.andWhere('domain like :domain', { domain: `%${domain}%` }); + qb.andWhere("domain like :domain", { domain: `%${domain}%` }); } }; @@ -41,9 +41,9 @@ export class CnameRecordController extends CrudController { return this.ok(pageRet); } - @Post('/list', { description: Constants.per.authOnly, summary: "查询CNAME记录列表" }) + @Post("/list", { description: Constants.per.authOnly, summary: "查询CNAME记录列表" }) async list(@Body(ALL) body: any) { - const {userId,projectId} = await this.getProjectUserIdRead(); + const { userId, projectId } = await this.getProjectUserIdRead(); body.query = body.query ?? {}; body.query.userId = userId; body.query.projectId = projectId; @@ -51,15 +51,15 @@ export class CnameRecordController extends CrudController { return this.ok(list); } - @Post('/add', { description: Constants.per.authOnly, summary: "添加CNAME记录" }) + @Post("/add", { description: Constants.per.authOnly, summary: "添加CNAME记录" }) async add(@Body(ALL) bean: any) { - const {userId,projectId} = await this.getProjectUserIdWrite(); + const { userId, projectId } = await this.getProjectUserIdWrite(); bean.userId = userId; bean.projectId = projectId; return super.add(bean); } - @Post('/update', { description: Constants.per.authOnly, summary: "更新CNAME记录" }) + @Post("/update", { description: Constants.per.authOnly, summary: "更新CNAME记录" }) async update(@Body(ALL) bean: any) { await this.checkOwner(this.getService(), bean.id, "write"); delete bean.userId; @@ -67,50 +67,50 @@ export class CnameRecordController extends CrudController { return super.update(bean); } - @Post('/info', { description: Constants.per.authOnly, summary: "查询CNAME记录详情" }) - async info(@Query('id') id: number) { + @Post("/info", { description: Constants.per.authOnly, summary: "查询CNAME记录详情" }) + async info(@Query("id") id: number) { await this.checkOwner(this.getService(), id, "read"); return super.info(id); } - @Post('/delete', { description: Constants.per.authOnly, summary: "删除CNAME记录" }) - async delete(@Query('id') id: number) { + @Post("/delete", { description: Constants.per.authOnly, summary: "删除CNAME记录" }) + async delete(@Query("id") id: number) { await this.checkOwner(this.getService(), id, "write"); return super.delete(id); } - @Post('/deleteByIds', { description: Constants.per.authOnly, summary: "批量删除CNAME记录" }) + @Post("/deleteByIds", { description: Constants.per.authOnly, summary: "批量删除CNAME记录" }) async deleteByIds(@Body(ALL) body: any) { - const {userId,projectId} = await this.getProjectUserIdWrite(); + const { userId, projectId } = await this.getProjectUserIdWrite(); await this.service.delete(body.ids, { userId, projectId, }); return this.ok(); } - @Post('/getByDomain', { description: Constants.per.authOnly, summary: "根据域名获取CNAME记录" }) + @Post("/getByDomain", { description: Constants.per.authOnly, summary: "根据域名获取CNAME记录" }) async getByDomain(@Body(ALL) body: { domain: string; createOnNotFound: boolean }) { - const {userId,projectId} = await this.getProjectUserIdRead(); - const res = await this.service.getByDomain(body.domain, userId,projectId, body.createOnNotFound); + const { userId, projectId } = await this.getProjectUserIdRead(); + const res = await this.service.getByDomain(body.domain, userId, projectId, body.createOnNotFound); return this.ok(res); } - @Post('/verify', { description: Constants.per.authOnly, summary: "验证CNAME记录" }) + @Post("/verify", { description: Constants.per.authOnly, summary: "验证CNAME记录" }) async verify(@Body(ALL) body: { id: number }) { await this.checkOwner(this.getService(), body.id, "read"); const res = await this.service.verify(body.id); return this.ok(res); } - @Post('/resetStatus', { description: Constants.per.authOnly, summary: "重置CNAME记录状态" }) + @Post("/resetStatus", { description: Constants.per.authOnly, summary: "重置CNAME记录状态" }) async resetStatus(@Body(ALL) body: { id: number }) { await this.checkOwner(this.getService(), body.id, "read"); const res = await this.service.resetStatus(body.id); return this.ok(res); } - @Post('/import', { description: Constants.per.authOnly, summary: "导入CNAME记录" }) + @Post("/import", { description: Constants.per.authOnly, summary: "导入CNAME记录" }) async import(@Body(ALL) body: { domainList: string; cnameProviderId: any }) { - const {userId,projectId} = await this.getProjectUserIdWrite(); + const { userId, projectId } = await this.getProjectUserIdWrite(); const res = await this.service.doImport({ userId, projectId, @@ -119,5 +119,4 @@ export class CnameRecordController extends CrudController { }); return this.ok(res); } - } diff --git a/packages/ui/certd-server/src/controller/user/dashboard/statistic-controller.ts b/packages/ui/certd-server/src/controller/user/dashboard/statistic-controller.ts index 5f1f15b53..f0775e9a5 100644 --- a/packages/ui/certd-server/src/controller/user/dashboard/statistic-controller.ts +++ b/packages/ui/certd-server/src/controller/user/dashboard/statistic-controller.ts @@ -1,11 +1,11 @@ -import { Controller, Inject, Post, Provide } from '@midwayjs/core'; -import { BaseController, Constants } from '@certd/lib-server'; -import { UserService } from '../../../modules/sys/authority/service/user-service.js'; -import { RoleService } from '../../../modules/sys/authority/service/role-service.js'; -import { PipelineService } from '../../../modules/pipeline/service/pipeline-service.js'; -import { HistoryService } from '../../../modules/pipeline/service/history-service.js'; -import { CertInfoService } from '../../../modules/monitor/index.js'; -import { ApiTags } from '@midwayjs/swagger'; +import { Controller, Inject, Post, Provide } from "@midwayjs/core"; +import { BaseController, Constants } from "@certd/lib-server"; +import { UserService } from "../../../modules/sys/authority/service/user-service.js"; +import { RoleService } from "../../../modules/sys/authority/service/role-service.js"; +import { PipelineService } from "../../../modules/pipeline/service/pipeline-service.js"; +import { HistoryService } from "../../../modules/pipeline/service/history-service.js"; +import { CertInfoService } from "../../../modules/monitor/index.js"; +import { ApiTags } from "@midwayjs/swagger"; export type ChartItem = { name: string; @@ -30,8 +30,8 @@ export type UserStatisticCount = { /** */ @Provide() -@Controller('/api/statistic/') -@ApiTags(['dashboard']) +@Controller("/api/statistic/") +@ApiTags(["dashboard"]) export class StatisticController extends BaseController { @Inject() userService: UserService; @@ -46,17 +46,17 @@ export class StatisticController extends BaseController { @Inject() certInfoService: CertInfoService; - @Post('/count', { description: Constants.per.authOnly, summary: "查询仪表盘统计数据" }) + @Post("/count", { description: Constants.per.authOnly, summary: "查询仪表盘统计数据" }) public async count() { - const {userId,projectId} = await this.getProjectUserIdRead(); - const pipelineCount = await this.pipelineService.count({ userId,projectId }); - const pipelineStatusCount = await this.pipelineService.statusCount({ userId,projectId }); - const pipelineEnableCount = await this.pipelineService.enableCount({ userId,projectId }); + const { userId, projectId } = await this.getProjectUserIdRead(); + const pipelineCount = await this.pipelineService.count({ userId, projectId }); + const pipelineStatusCount = await this.pipelineService.statusCount({ userId, projectId }); + const pipelineEnableCount = await this.pipelineService.enableCount({ userId, projectId }); - const historyCount = await this.historyService.countPerDay({ userId,projectId, days: 7 }); - const expiringList = await this.pipelineService.latestExpiringList({ userId,projectId, count: 5 }); + const historyCount = await this.historyService.countPerDay({ userId, projectId, days: 7 }); + const expiringList = await this.pipelineService.latestExpiringList({ userId, projectId, count: 5 }); - const certCount = await this.certInfoService.count({ userId,projectId }); + const certCount = await this.certInfoService.count({ userId, projectId }); const count: UserStatisticCount = { pipelineCount, diff --git a/packages/ui/certd-server/src/controller/user/enterprise/project-controller.ts b/packages/ui/certd-server/src/controller/user/enterprise/project-controller.ts index db377c15a..a02fa4273 100644 --- a/packages/ui/certd-server/src/controller/user/enterprise/project-controller.ts +++ b/packages/ui/certd-server/src/controller/user/enterprise/project-controller.ts @@ -1,22 +1,22 @@ -import { BaseController, Constants } from '@certd/lib-server'; -import { ALL, Body, Controller, Inject, Post, Provide } from '@midwayjs/core'; -import { AuthService } from '../../../modules/sys/authority/service/auth-service.js'; -import { ProjectService } from '../../../modules/sys/enterprise/service/project-service.js'; -import { ProjectMemberService } from '../../../modules/sys/enterprise/service/project-member-service.js'; -import { ApiTags } from '@midwayjs/swagger'; +import { BaseController, Constants } from "@certd/lib-server"; +import { ALL, Body, Controller, Inject, Post, Provide } from "@midwayjs/core"; +import { AuthService } from "../../../modules/sys/authority/service/auth-service.js"; +import { ProjectService } from "../../../modules/sys/enterprise/service/project-service.js"; +import { ProjectMemberService } from "../../../modules/sys/enterprise/service/project-member-service.js"; +import { ApiTags } from "@midwayjs/swagger"; /** */ @Provide() -@Controller('/api/enterprise/project') -@ApiTags(['enterprise-project']) +@Controller("/api/enterprise/project") +@ApiTags(["enterprise-project"]) export class UserProjectController extends BaseController { @Inject() service: ProjectService; @Inject() projectMemberService: ProjectMemberService; - + @Inject() authService: AuthService; @@ -24,54 +24,52 @@ export class UserProjectController extends BaseController { return this.service; } - /** - * @param body - * @returns + /** + * @param body + * @returns */ - @Post('/detail', { description: Constants.per.authOnly, summary: "查询项目详情" }) + @Post("/detail", { description: Constants.per.authOnly, summary: "查询项目详情" }) async detail(@Body(ALL) body: any) { - const {projectId} = await this.getProjectUserIdRead(); - const res = await this.service.getDetail(projectId,this.getUserId()); + const { projectId } = await this.getProjectUserIdRead(); + const res = await this.service.getDetail(projectId, this.getUserId()); return this.ok(res); } - /** * 我的项目 - * @param body - * @returns + * @param body + * @returns */ - @Post('/list', { description: Constants.per.authOnly, summary: "查询我的项目列表" }) + @Post("/list", { description: Constants.per.authOnly, summary: "查询我的项目列表" }) async list(@Body(ALL) body: any) { - const userId= this.getUserId(); + const userId = this.getUserId(); const res = await this.service.getUserProjects(userId); return this.ok(res); } - /** - * + * * @param body 所有项目 - * @returns + * @returns */ - @Post('/all', { description: Constants.per.authOnly, summary: "查询所有项目" }) + @Post("/all", { description: Constants.per.authOnly, summary: "查询所有项目" }) async all(@Body(ALL) body: any) { - const userId= this.getUserId(); + const userId = this.getUserId(); const res = await this.service.getAllWithStatus(userId); return this.ok(res); } - @Post('/applyJoin', { description: Constants.per.authOnly, summary: "申请加入项目" }) + @Post("/applyJoin", { description: Constants.per.authOnly, summary: "申请加入项目" }) async applyJoin(@Body(ALL) body: any) { - const userId= this.getUserId(); + const userId = this.getUserId(); const res = await this.service.applyJoin({ userId, projectId: body.projectId }); return this.ok(res); } - @Post('/updateMember', { description: Constants.per.authOnly, summary: "更新项目成员" }) + @Post("/updateMember", { description: Constants.per.authOnly, summary: "更新项目成员" }) async updateMember(@Body(ALL) body: any) { - const {projectId} = await this.getProjectUserIdAdmin(); - const {status,permission,userId} = body; + const { projectId } = await this.getProjectUserIdAdmin(); + const { status, permission, userId } = body; const member = await this.projectMemberService.findOne({ where: { projectId, @@ -79,7 +77,7 @@ export class UserProjectController extends BaseController { }, }); if (!member) { - throw new Error('成员不存在'); + throw new Error("成员不存在"); } const res = await this.projectMemberService.update({ id: member.id, @@ -89,17 +87,17 @@ export class UserProjectController extends BaseController { return this.ok(res); } - @Post('/approveJoin', { description: Constants.per.authOnly, summary: "审批加入项目申请" }) + @Post("/approveJoin", { description: Constants.per.authOnly, summary: "审批加入项目申请" }) async approveJoin(@Body(ALL) body: any) { - const {projectId} = await this.getProjectUserIdAdmin(); - const {status,permission,userId} = body; - const res = await this.service.approveJoin({ userId, projectId: projectId,status,permission }); + const { projectId } = await this.getProjectUserIdAdmin(); + const { status, permission, userId } = body; + const res = await this.service.approveJoin({ userId, projectId: projectId, status, permission }); return this.ok(res); } - @Post('/delete', { description: Constants.per.authOnly, summary: "删除项目成员" }) + @Post("/delete", { description: Constants.per.authOnly, summary: "删除项目成员" }) async delete(@Body(ALL) body: any) { - const {projectId} = await this.getProjectUserIdAdmin(); + const { projectId } = await this.getProjectUserIdAdmin(); await this.projectMemberService.deleteWhere({ projectId, userId: this.getUserId(), @@ -107,15 +105,14 @@ export class UserProjectController extends BaseController { return this.ok(); } - @Post('/leave', { description: Constants.per.authOnly, summary: "离开项目" }) + @Post("/leave", { description: Constants.per.authOnly, summary: "离开项目" }) async leave(@Body(ALL) body: any) { - const {projectId} = body - const userId = this.getUserId(); + const { projectId } = body; + const userId = this.getUserId(); await this.projectMemberService.deleteWhere({ projectId, userId, }); return this.ok(); } - } diff --git a/packages/ui/certd-server/src/controller/user/enterprise/project-member-controller.ts b/packages/ui/certd-server/src/controller/user/enterprise/project-member-controller.ts index 3d492feda..870ab64b6 100644 --- a/packages/ui/certd-server/src/controller/user/enterprise/project-member-controller.ts +++ b/packages/ui/certd-server/src/controller/user/enterprise/project-member-controller.ts @@ -1,4 +1,4 @@ -import { CrudController, SysSettingsService,Constants } from "@certd/lib-server"; +import { CrudController, SysSettingsService, Constants } from "@certd/lib-server"; import { ALL, Body, Controller, Inject, Post, Provide, Query } from "@midwayjs/core"; import { ProjectMemberEntity } from "../../../modules/sys/enterprise/entity/project-member.js"; import { ProjectMemberService } from "../../../modules/sys/enterprise/service/project-member-service.js"; @@ -9,7 +9,7 @@ import { ApiTags } from "@midwayjs/swagger"; */ @Provide() @Controller("/api/enterprise/projectMember") -@ApiTags(['enterprise-project-member']) +@ApiTags(["enterprise-project-member"]) export class ProjectMemberController extends CrudController { @Inject() service: ProjectMemberService; @@ -26,7 +26,7 @@ export class ProjectMemberController extends CrudController @Post("/page", { description: Constants.per.authOnly, summary: "查询项目成员分页列表" }) async page(@Body(ALL) body: any) { - const {projectId} = await this.getProjectUserIdRead(); + const { projectId } = await this.getProjectUserIdRead(); body.query = body.query ?? {}; body.query.projectId = projectId; return await super.page(body); @@ -34,7 +34,7 @@ export class ProjectMemberController extends CrudController @Post("/list", { description: Constants.per.authOnly, summary: "查询项目成员列表" }) async list(@Body(ALL) body: any) { - const {projectId} = await this.getProjectUserIdRead(); + const { projectId } = await this.getProjectUserIdRead(); body.query = body.query ?? {}; body.query.projectId = projectId; return super.list(body); @@ -56,12 +56,12 @@ export class ProjectMemberController extends CrudController return super.add(bean); } - @Post("/update", { description: Constants.per.authOnly, summary: "更新项目成员" }) + @Post("/update", { description: Constants.per.authOnly, summary: "更新项目成员" }) async update(@Body(ALL) bean: any) { if (!bean.id) { throw new Error("id is required"); } - const projectId = await this.service.getProjectId(bean.id) + const projectId = await this.service.getProjectId(bean.id); await this.projectService.checkAdminPermission({ userId: this.getUserId(), projectId: projectId, @@ -77,13 +77,13 @@ export class ProjectMemberController extends CrudController @Post("/info", { description: Constants.per.authOnly, summary: "查询项目成员详情" }) async info(@Query("id") id: number) { - if (!id) { + if (!id) { throw new Error("id is required"); } - const projectId = await this.service.getProjectId(id) + const projectId = await this.service.getProjectId(id); await this.projectService.checkReadPermission({ userId: this.getUserId(), - projectId:projectId, + projectId: projectId, }); return super.info(id); } @@ -93,10 +93,10 @@ export class ProjectMemberController extends CrudController if (!id) { throw new Error("id is required"); } - const projectId = await this.service.getProjectId(id) + const projectId = await this.service.getProjectId(id); await this.projectService.checkAdminPermission({ userId: this.getUserId(), - projectId:projectId, + projectId: projectId, }); return super.delete(id); } @@ -107,14 +107,14 @@ export class ProjectMemberController extends CrudController if (!id) { throw new Error("id is required"); } - const projectId = await this.service.getProjectId(id) + const projectId = await this.service.getProjectId(id); await this.projectService.checkAdminPermission({ userId: this.getUserId(), - projectId:projectId, + projectId: projectId, }); await this.service.delete(id as any); } - + return this.ok({}); } } diff --git a/packages/ui/certd-server/src/controller/user/enterprise/transfer-controller.ts b/packages/ui/certd-server/src/controller/user/enterprise/transfer-controller.ts index b1821dace..55bccd27f 100644 --- a/packages/ui/certd-server/src/controller/user/enterprise/transfer-controller.ts +++ b/packages/ui/certd-server/src/controller/user/enterprise/transfer-controller.ts @@ -1,44 +1,43 @@ -import { BaseController, Constants } from '@certd/lib-server'; -import { Controller, Inject, Post, Provide } from '@midwayjs/core'; -import { TransferService } from '../../../modules/sys/enterprise/service/transfer-service.js'; -import { ApiTags } from '@midwayjs/swagger'; +import { BaseController, Constants } from "@certd/lib-server"; +import { Controller, Inject, Post, Provide } from "@midwayjs/core"; +import { TransferService } from "../../../modules/sys/enterprise/service/transfer-service.js"; +import { ApiTags } from "@midwayjs/swagger"; /** */ @Provide() -@Controller('/api/enterprise/transfer') -@ApiTags(['enterprise-project']) +@Controller("/api/enterprise/transfer") +@ApiTags(["enterprise-project"]) export class TransferController extends BaseController { @Inject() service: TransferService; - getService(): TransferService { return this.service; } - /** - * 我自己的资源 - * @param body - * @returns + /** + * 我自己的资源 + * @param body + * @returns */ - @Post('/selfResources', { description: Constants.per.authOnly, summary: "查询我自己的资源" }) + @Post("/selfResources", { description: Constants.per.authOnly, summary: "查询我自己的资源" }) async selfResources() { const userId = this.getUserId(); const res = await this.service.getUserResources(userId); return this.ok(res); } - /** - * 迁移项目 - * @param body - * @returns + /** + * 迁移项目 + * @param body + * @returns */ - @Post('/doTransfer', { description: Constants.per.authOnly, summary: "迁移项目资源" }) + @Post("/doTransfer", { description: Constants.per.authOnly, summary: "迁移项目资源" }) async doTransfer() { - const {projectId} = await this.getProjectUserIdRead(); - const userId = this.getUserId(); - await this.service.transferAll(userId,projectId); + const { projectId } = await this.getProjectUserIdRead(); + const userId = this.getUserId(); + await this.service.transferAll(userId, projectId); return this.ok(); } } diff --git a/packages/ui/certd-server/src/controller/user/mine/email-controller.ts b/packages/ui/certd-server/src/controller/user/mine/email-controller.ts index bd2db95a1..552186a57 100644 --- a/packages/ui/certd-server/src/controller/user/mine/email-controller.ts +++ b/packages/ui/certd-server/src/controller/user/mine/email-controller.ts @@ -1,41 +1,41 @@ -import { Body, Controller, Inject, Post, Provide } from '@midwayjs/core'; -import { BaseController } from '@certd/lib-server'; -import { Constants } from '@certd/lib-server'; -import { EmailService } from '../../../modules/basic/service/email-service.js'; -import { ApiTags } from '@midwayjs/swagger'; +import { Body, Controller, Inject, Post, Provide } from "@midwayjs/core"; +import { BaseController } from "@certd/lib-server"; +import { Constants } from "@certd/lib-server"; +import { EmailService } from "../../../modules/basic/service/email-service.js"; +import { ApiTags } from "@midwayjs/swagger"; /** */ @Provide() -@Controller('/api/mine/email') -@ApiTags(['mine']) +@Controller("/api/mine/email") +@ApiTags(["mine"]) export class EmailController extends BaseController { @Inject() emailService: EmailService; - @Post('/test', { description: Constants.per.authOnly, summary: "测试邮件发送" }) - public async test(@Body('receiver') receiver) { + @Post("/test", { description: Constants.per.authOnly, summary: "测试邮件发送" }) + public async test(@Body("receiver") receiver) { const userId = super.getUserId(); await this.emailService.test(userId, receiver); return this.ok({}); } - @Post('/list', { description: Constants.per.authOnly, summary: "查询邮件列表" }) + @Post("/list", { description: Constants.per.authOnly, summary: "查询邮件列表" }) public async list() { const userId = super.getUserId(); const res = await this.emailService.list(userId); return this.ok(res); } - @Post('/add', { description: Constants.per.authOnly, summary: "添加邮件" }) - public async add(@Body('email') email) { + @Post("/add", { description: Constants.per.authOnly, summary: "添加邮件" }) + public async add(@Body("email") email) { const userId = super.getUserId(); await this.emailService.add(userId, email); return this.ok({}); } - @Post('/delete', { description: Constants.per.authOnly, summary: "删除邮件" }) - public async delete(@Body('email') email) { + @Post("/delete", { description: Constants.per.authOnly, summary: "删除邮件" }) + public async delete(@Body("email") email) { const userId = super.getUserId(); await this.emailService.delete(userId, email); return this.ok({}); diff --git a/packages/ui/certd-server/src/controller/user/mine/passkey-controller.ts b/packages/ui/certd-server/src/controller/user/mine/passkey-controller.ts index 9ac72bc2c..854636413 100644 --- a/packages/ui/certd-server/src/controller/user/mine/passkey-controller.ts +++ b/packages/ui/certd-server/src/controller/user/mine/passkey-controller.ts @@ -5,8 +5,8 @@ import { UserService } from "../../../modules/sys/authority/service/user-service import { ApiTags } from "@midwayjs/swagger"; @Provide() -@Controller('/api/mine/passkey') -@ApiTags(['mine']) +@Controller("/api/mine/passkey") +@ApiTags(["mine"]) export class MinePasskeyController extends BaseController { @Inject() passkeyService: PasskeyService; @@ -14,56 +14,43 @@ export class MinePasskeyController extends BaseController { @Inject() userService: UserService; - @Post('/generateRegistration', { description: Constants.per.authOnly, summary: "生成Passkey注册选项" }) + @Post("/generateRegistration", { description: Constants.per.authOnly, summary: "生成Passkey注册选项" }) public async generateRegistration( @Body(ALL) body: any, @RequestIP() remoteIp: string ) { - const userId = this.getUserId() + const userId = this.getUserId(); const user = await this.userService.info(userId); - + if (!user) { - throw new Error('用户不存在'); + throw new Error("用户不存在"); } - const options = await this.passkeyService.generateRegistrationOptions( - userId, - user.username, - remoteIp, - this.ctx - ); + const options = await this.passkeyService.generateRegistrationOptions(userId, user.username, remoteIp, this.ctx); return this.ok({ ...options, }); } - @Post('/verifyRegistration', { description: Constants.per.authOnly, summary: "验证Passkey注册" }) + @Post("/verifyRegistration", { description: Constants.per.authOnly, summary: "验证Passkey注册" }) public async verifyRegistration( @Body(ALL) body: any ) { - const userId = this.getUserId() + const userId = this.getUserId(); const response = body.response; const challenge = body.challenge; const deviceName = body.deviceName; - const result = await this.passkeyService.registerPasskey( - userId, - response, - challenge, - deviceName, - this.ctx - ); + const result = await this.passkeyService.registerPasskey(userId, response, challenge, deviceName, this.ctx); return this.ok(result); } - - - @Post('/register', { description: Constants.per.authOnly, summary: "注册Passkey" }) + @Post("/register", { description: Constants.per.authOnly, summary: "注册Passkey" }) public async registerPasskey( @Body(ALL) body: any @@ -73,30 +60,23 @@ export class MinePasskeyController extends BaseController { const deviceName = body.deviceName; const challenge = body.challenge; - const result = await this.passkeyService.registerPasskey( - userId, - response, - challenge, - deviceName, - this.ctx - ); + const result = await this.passkeyService.registerPasskey(userId, response, challenge, deviceName, this.ctx); return this.ok(result); } - - @Post('/list', { description: Constants.per.authOnly, summary: "查询Passkey列表" }) + @Post("/list", { description: Constants.per.authOnly, summary: "查询Passkey列表" }) public async getPasskeys() { const userId = this.getUserId(); const passkeys = await this.passkeyService.find({ - select: ['id', 'deviceName', 'registeredAt', 'transports', 'passkeyId' ,'updateTime'], + select: ["id", "deviceName", "registeredAt", "transports", "passkeyId", "updateTime"], where: { userId }, - order: { registeredAt: 'DESC' }, + order: { registeredAt: "DESC" }, }); return this.ok(passkeys); } - @Post('/unbind', { description: Constants.per.authOnly, summary: "解绑Passkey" }) + @Post("/unbind", { description: Constants.per.authOnly, summary: "解绑Passkey" }) public async unbindPasskey(@Body(ALL) body: any) { const userId = this.getUserId(); const passkeyId = body.id; @@ -106,11 +86,10 @@ export class MinePasskeyController extends BaseController { }); if (!passkey) { - throw new Error('Passkey不存在'); + throw new Error("Passkey不存在"); } await this.passkeyService.delete([passkey.id]); return this.ok({}); } - } diff --git a/packages/ui/certd-server/src/controller/user/mine/setting-two-factor-controller.ts b/packages/ui/certd-server/src/controller/user/mine/setting-two-factor-controller.ts index 8b84483f1..cab7a7280 100644 --- a/packages/ui/certd-server/src/controller/user/mine/setting-two-factor-controller.ts +++ b/packages/ui/certd-server/src/controller/user/mine/setting-two-factor-controller.ts @@ -4,14 +4,14 @@ import { UserSettingsService } from "../../../modules/mine/service/user-settings import { UserTwoFactorSetting } from "../../../modules/mine/service/models.js"; import { merge } from "lodash-es"; import { TwoFactorService } from "../../../modules/mine/service/two-factor-service.js"; -import {isPlus} from "@certd/plus-core"; +import { isPlus } from "@certd/plus-core"; import { ApiTags } from "@midwayjs/swagger"; /** */ @Provide() @Controller("/api/user/settings/twoFactor") -@ApiTags(['mine']) +@ApiTags(["mine"]) export class UserTwoFactorSettingController extends BaseController { @Inject() service: UserSettingsService; @@ -19,50 +19,48 @@ export class UserTwoFactorSettingController extends BaseController { @Inject() twoFactorService: TwoFactorService; - - @Post("/get", { description: Constants.per.authOnly, summary: "获取双因子认证设置" }) async get() { const userId = this.getUserId(); - const setting = await this.service.getSetting(userId,null, UserTwoFactorSetting); + const setting = await this.service.getSetting(userId, null, UserTwoFactorSetting); return this.ok(setting); } @Post("/save", { description: Constants.per.authOnly, summary: "保存双因子认证设置" }) async save(@Body(ALL) bean: any) { if (!isPlus()) { - throw new Error('本功能需要开通Certd专业版') + throw new Error("本功能需要开通Certd专业版"); } const userId = this.getUserId(); const setting = new UserTwoFactorSetting(); merge(setting, bean); // 禁用时清除 - if(!setting.authenticator.enabled){ - setting.authenticator.secret = null; - setting.authenticator.verified = false; + if (!setting.authenticator.enabled) { + setting.authenticator.secret = null; + setting.authenticator.verified = false; } - await this.service.saveSetting(userId,null, setting); + await this.service.saveSetting(userId, null, setting); return this.ok({}); } @Post("/authenticator/qrcode", { description: Constants.per.authOnly, summary: "获取验证器二维码" }) async authenticatorQrcode() { const userId = this.getUserId(); - const {qrcode,link,secret} = await this.twoFactorService.getAuthenticatorQrCode(userId); - return this.ok({qrcode,link,secret}); + const { qrcode, link, secret } = await this.twoFactorService.getAuthenticatorQrCode(userId); + return this.ok({ qrcode, link, secret }); } @Post("/authenticator/save", { description: Constants.per.authOnly, summary: "保存验证器设置" }) async authenticatorSave(@Body(ALL) bean: any) { if (!isPlus()) { - throw new Error('本功能需要开通Certd专业版') + throw new Error("本功能需要开通Certd专业版"); } const userId = this.getUserId(); await this.twoFactorService.saveAuthenticator({ - userId, - verifyCode: bean.verifyCode, + userId, + verifyCode: bean.verifyCode, }); return this.ok(); } @@ -73,5 +71,4 @@ export class UserTwoFactorSettingController extends BaseController { await this.twoFactorService.offAuthenticator(userId); return this.ok(); } - } diff --git a/packages/ui/certd-server/src/controller/user/mine/user-settings-controller.ts b/packages/ui/certd-server/src/controller/user/mine/user-settings-controller.ts index cd4cf11c9..1eb45bccf 100644 --- a/packages/ui/certd-server/src/controller/user/mine/user-settings-controller.ts +++ b/packages/ui/certd-server/src/controller/user/mine/user-settings-controller.ts @@ -10,8 +10,8 @@ import { ApiTags } from "@midwayjs/swagger"; /** */ @Provide() -@Controller('/api/user/settings') -@ApiTags(['mine']) +@Controller("/api/user/settings") +@ApiTags(["mine"]) export class UserSettingsController extends CrudController { @Inject() service: UserSettingsService; @@ -20,54 +20,54 @@ export class UserSettingsController extends CrudController return this.service; } - @Post('/page', { description: Constants.per.authOnly, summary: "查询用户设置分页列表" }) + @Post("/page", { description: Constants.per.authOnly, summary: "查询用户设置分页列表" }) async page(@Body(ALL) body) { body.query = body.query ?? {}; body.query.userId = this.getUserId(); return super.page(body); } - @Post('/list', { description: Constants.per.authOnly, summary: "查询用户设置列表" }) + @Post("/list", { description: Constants.per.authOnly, summary: "查询用户设置列表" }) async list(@Body(ALL) body) { body.query = body.query ?? {}; body.query.userId = this.getUserId(); return super.list(body); } - @Post('/add', { description: Constants.per.authOnly, summary: "添加用户设置" }) + @Post("/add", { description: Constants.per.authOnly, summary: "添加用户设置" }) async add(@Body(ALL) bean) { bean.userId = this.getUserId(); return super.add(bean); } - @Post('/update', { description: Constants.per.authOnly, summary: "更新用户设置" }) + @Post("/update", { description: Constants.per.authOnly, summary: "更新用户设置" }) async update(@Body(ALL) bean) { await this.service.checkUserId(bean.id, this.getUserId()); delete bean.userId; return super.update(bean); } - @Post('/info', { description: Constants.per.authOnly, summary: "查询用户设置详情" }) - async info(@Query('id') id: number) { + @Post("/info", { description: Constants.per.authOnly, summary: "查询用户设置详情" }) + async info(@Query("id") id: number) { await this.service.checkUserId(id, this.getUserId()); return super.info(id); } - @Post('/delete', { description: Constants.per.authOnly, summary: "删除用户设置" }) - async delete(@Query('id') id: number) { + @Post("/delete", { description: Constants.per.authOnly, summary: "删除用户设置" }) + async delete(@Query("id") id: number) { await this.service.checkUserId(id, this.getUserId()); return super.delete(id); } - @Post('/save', { description: Constants.per.authOnly, summary: "保存用户设置" }) + @Post("/save", { description: Constants.per.authOnly, summary: "保存用户设置" }) async save(@Body(ALL) bean: UserSettingsEntity) { bean.userId = this.getUserId(); await this.service.save(bean); return this.ok({}); } - @Post('/get', { description: Constants.per.authOnly, summary: "获取用户设置" }) - async get(@Query('key') key: string) { - const {projectId,userId} = await this.getProjectUserIdRead(); + @Post("/get", { description: Constants.per.authOnly, summary: "获取用户设置" }) + async get(@Query("key") key: string) { + const { projectId, userId } = await this.getProjectUserIdRead(); const entity = await this.service.getByKey(key, userId, projectId); return this.ok(entity); } @@ -81,14 +81,13 @@ export class UserSettingsController extends CrudController @Post("/grant/save", { description: Constants.per.authOnly, summary: "保存授权设置" }) async grantSettingsSave(@Body(ALL) bean: UserGrantSetting) { if (!isPlus()) { - throw new Error('本功能需要开通Certd专业版') + throw new Error("本功能需要开通Certd专业版"); } const userId = this.getUserId(); const setting = new UserGrantSetting(); merge(setting, bean); - await this.service.saveSetting(userId,null, setting); + await this.service.saveSetting(userId, null, setting); return this.ok({}); } - } diff --git a/packages/ui/certd-server/src/controller/user/monitor/cert-info-controller.ts b/packages/ui/certd-server/src/controller/user/monitor/cert-info-controller.ts index 42ecb85f7..9c536694a 100644 --- a/packages/ui/certd-server/src/controller/user/monitor/cert-info-controller.ts +++ b/packages/ui/certd-server/src/controller/user/monitor/cert-info-controller.ts @@ -13,8 +13,8 @@ import { CertReader } from "@certd/plugin-lib"; /** */ @Provide() -@Controller('/api/monitor/cert') -@ApiTags(['cert']) +@Controller("/api/monitor/cert") +@ApiTags(["cert"]) export class CertInfoController extends CrudController { @Inject() service: CertInfoService; @@ -30,12 +30,12 @@ export class CertInfoController extends CrudController { return this.service; } - @Post('/page', { description: Constants.per.authOnly, summary: "查询证书分页列表" }) + @Post("/page", { description: Constants.per.authOnly, summary: "查询证书分页列表" }) async page(@Body(ALL) body: any) { body.query = body.query ?? {}; - const { projectId, userId } = await this.getProjectUserIdRead() - body.query.projectId = projectId + const { projectId, userId } = await this.getProjectUserIdRead(); + body.query.projectId = projectId; body.query.userId = userId; const domains = body.query?.domains; delete body.query.domains; @@ -49,21 +49,21 @@ export class CertInfoController extends CrudController { query: body.query, page: body.page, sort: body.sort, - buildQuery: (bq) => { + buildQuery: bq => { if (domains) { - bq.andWhere('domains like :domains', { domains: `%${domains}%` }); + bq.andWhere("domains like :domains", { domains: `%${domains}%` }); } if (expiresLeft) { - const willExpire = dayjs().add(DEFAULT_WILL_EXPIRE_DAYS, 'day').valueOf(); + const willExpire = dayjs().add(DEFAULT_WILL_EXPIRE_DAYS, "day").valueOf(); if (expiresLeft === "expired") { - bq.andWhere('expires_time < :now', { now: Date.now() }); + bq.andWhere("expires_time < :now", { now: Date.now() }); } else if (expiresLeft === "expiring") { - bq.andWhere('expires_time <= :willExpire and expires_time > :now', { willExpire, now: Date.now() }); + bq.andWhere("expires_time <= :willExpire and expires_time > :now", { willExpire, now: Date.now() }); } else if (expiresLeft === "noExpired") { - bq.andWhere('expires_time > :willExpire', { willExpire }); + bq.andWhere("expires_time > :willExpire", { willExpire }); } } - } + }, }); const records = res.records; @@ -79,71 +79,70 @@ export class CertInfoController extends CrudController { return this.ok(res); } - @Post('/list', { description: Constants.per.authOnly, summary: "查询证书列表" }) + @Post("/list", { description: Constants.per.authOnly, summary: "查询证书列表" }) async list(@Body(ALL) body: any) { body.query = body.query ?? {}; - const { projectId, userId } = await this.getProjectUserIdRead() - body.query.projectId = projectId + const { projectId, userId } = await this.getProjectUserIdRead(); + body.query.projectId = projectId; body.query.userId = userId; return await super.list(body); } - - @Post('/getOptionsByIds', { description: Constants.per.authOnly, summary: "根据ID列表获取证书选项" }) - async getOptionsByIds(@Body(ALL) body: {ids:any[]}) { - const { projectId, userId } = await this.getProjectUserIdRead() + @Post("/getOptionsByIds", { description: Constants.per.authOnly, summary: "根据ID列表获取证书选项" }) + async getOptionsByIds(@Body(ALL) body: { ids: any[] }) { + const { projectId, userId } = await this.getProjectUserIdRead(); const list = await this.service.list({ - query:{ + query: { projectId, userId, }, buildQuery: (bq: SelectQueryBuilder) => { - bq.andWhere('id in (:...ids)', { ids: body.ids }); - } - }) + bq.andWhere("id in (:...ids)", { ids: body.ids }); + }, + }); - const safeList =list.map((item:any) => { - const domainsArr = item.domains? item.domains.split(',') : []; + const safeList = list.map((item: any) => { + const domainsArr = item.domains ? item.domains.split(",") : []; return { id: item.id, domain: item.domain, - domains:domainsArr, + domains: domainsArr, userId: item.userId, - } - }) + }; + }); return this.ok(safeList); } - @Post('/add', { description: Constants.per.authOnly, summary: "添加证书" }) + @Post("/add", { description: Constants.per.authOnly, summary: "添加证书" }) async add(@Body(ALL) bean: any) { - const { projectId, userId } = await this.getProjectUserIdWrite() - bean.projectId = projectId + const { projectId, userId } = await this.getProjectUserIdWrite(); + bean.projectId = projectId; bean.userId = userId; return await super.add(bean); } - @Post('/update', { description: Constants.per.authOnly, summary: "更新证书" }) + @Post("/update", { description: Constants.per.authOnly, summary: "更新证书" }) async update(@Body(ALL) bean) { - await this.checkOwner(this.service,bean.id,"write"); + await this.checkOwner(this.service, bean.id, "write"); delete bean.userId; delete bean.projectId; return await super.update(bean); } - @Post('/info', { description: Constants.per.authOnly, summary: "查询证书详情" }) - async info(@Query('id') id: number) { - await this.checkOwner(this.service,id,"read"); + @Post("/info", { description: Constants.per.authOnly, summary: "查询证书详情" }) + async info(@Query("id") id: number) { + await this.checkOwner(this.service, id, "read"); return await super.info(id); } - @Post('/delete', { description: Constants.per.authOnly, summary: "删除证书" }) - async delete(@Query('id') id: number) { - await this.checkOwner(this.service,id,"write"); + @Post("/delete", { description: Constants.per.authOnly, summary: "删除证书" }) + async delete(@Query("id") id: number) { + await this.checkOwner(this.service, id, "write"); return await super.delete(id); } - @Post('/all', { description: Constants.per.authOnly, summary: "查询所有证书" }) + @Post("/all", { description: Constants.per.authOnly, summary: "查询所有证书" }) async all() { - const { projectId, userId } = await this.getProjectUserIdRead() + const { projectId, userId } = await this.getProjectUserIdRead(); const list: any = await this.service.find({ where: { projectId, @@ -153,32 +152,30 @@ export class CertInfoController extends CrudController { return this.ok(list); } - - - @Post('/getCert', { description: Constants.per.authOnly, summary: "获取证书信息" }) - async getCert(@Query('id') id: number) { - await this.checkOwner(this.getService(),id,"read"); + @Post("/getCert", { description: Constants.per.authOnly, summary: "获取证书信息" }) + async getCert(@Query("id") id: number) { + await this.checkOwner(this.getService(), id, "read"); const certInfoEntity = await this.service.info(id); const certInfo = JSON.parse(certInfoEntity.certInfo); if (certInfo?.crt) { const certReader = new CertReader(certInfo); - certInfo.detail = certReader.detail + certInfo.detail = certReader.detail; } return this.ok(certInfo); } - @Get('/download', { description: Constants.per.authOnly, summary: "下载证书文件" }) - async download(@Query('id') id: number) { - const {userId,projectId} =await this.checkOwner(this.getService(),id,"read"); - const certInfo = await this.getService().info(id) + @Get("/download", { description: Constants.per.authOnly, summary: "下载证书文件" }) + async download(@Query("id") id: number) { + const { userId, projectId } = await this.checkOwner(this.getService(), id, "read"); + const certInfo = await this.getService().info(id); if (certInfo == null) { - throw new CommonException('file not found'); + throw new CommonException("file not found"); } if (certInfo.userId !== userId) { - throw new CommonException('file not found'); + throw new CommonException("file not found"); } if (projectId && certInfo.projectId !== projectId) { - throw new CommonException('file not found'); + throw new CommonException("file not found"); } // koa send file // 下载文件的名称 @@ -186,12 +183,12 @@ export class CertInfoController extends CrudController { // 要下载的文件的完整路径 const path = certInfo.certFile; if (!path) { - throw new CommonException('file not found'); + throw new CommonException("file not found"); } logger.info(`download:${path}`); // 以流的形式下载文件 this.ctx.attachment(path); - this.ctx.set('Content-Type', 'application/octet-stream'); + this.ctx.set("Content-Type", "application/octet-stream"); return fs.createReadStream(path); } diff --git a/packages/ui/certd-server/src/controller/user/monitor/job-history-controller.ts b/packages/ui/certd-server/src/controller/user/monitor/job-history-controller.ts index e06727c71..698d2b75e 100644 --- a/packages/ui/certd-server/src/controller/user/monitor/job-history-controller.ts +++ b/packages/ui/certd-server/src/controller/user/monitor/job-history-controller.ts @@ -8,8 +8,8 @@ import { AuthService } from "../../../modules/sys/authority/service/auth-service /** */ @Provide() -@Controller('/api/monitor/job-history') -@ApiTags(['monitor']) +@Controller("/api/monitor/job-history") +@ApiTags(["monitor"]) export class JobHistoryController extends CrudController { @Inject() service: JobHistoryService; @@ -22,12 +22,12 @@ export class JobHistoryController extends CrudController { return this.service; } - @Post('/page', { description: Constants.per.authOnly, summary: "查询监控运行历史分页列表" }) + @Post("/page", { description: Constants.per.authOnly, summary: "查询监控运行历史分页列表" }) async page(@Body(ALL) body: any) { - const { projectId, userId } = await this.getProjectUserIdRead() + const { projectId, userId } = await this.getProjectUserIdRead(); body.query = body.query ?? {}; body.query.userId = userId; - body.query.projectId = projectId + body.query.projectId = projectId; const res = await this.service.page({ query: body.query, page: body.page, @@ -36,30 +36,30 @@ export class JobHistoryController extends CrudController { return this.ok(res); } - @Post('/list', { description: Constants.per.authOnly, summary: "查询监控运行历史列表" }) + @Post("/list", { description: Constants.per.authOnly, summary: "查询监控运行历史列表" }) async list(@Body(ALL) body: any) { body.query = body.query ?? {}; - const { projectId, userId } = await this.getProjectUserIdRead() + const { projectId, userId } = await this.getProjectUserIdRead(); body.query.userId = userId; - body.query.projectId = projectId + body.query.projectId = projectId; return await super.list(body); } - @Post('/info', { description: Constants.per.authOnly, summary: "查询监控运行历史详情" }) - async info(@Query('id') id: number) { - await this.checkOwner(this.service,id,"read"); + @Post("/info", { description: Constants.per.authOnly, summary: "查询监控运行历史详情" }) + async info(@Query("id") id: number) { + await this.checkOwner(this.service, id, "read"); return await super.info(id); } - @Post('/delete', { description: Constants.per.authOnly, summary: "删除监控运行历史" }) - async delete(@Query('id') id: number) { - await this.checkOwner(this.service,id,"write"); + @Post("/delete", { description: Constants.per.authOnly, summary: "删除监控运行历史" }) + async delete(@Query("id") id: number) { + await this.checkOwner(this.service, id, "write"); return await super.delete(id); } - @Post('/batchDelete', { description: Constants.per.authOnly, summary: "批量删除监控运行历史" }) - async batchDelete(@Body('ids') ids: number[]) { - const { projectId, userId } = await this.getProjectUserIdWrite() - await this.service.batchDelete(ids,userId,projectId); + @Post("/batchDelete", { description: Constants.per.authOnly, summary: "批量删除监控运行历史" }) + async batchDelete(@Body("ids") ids: number[]) { + const { projectId, userId } = await this.getProjectUserIdWrite(); + await this.service.batchDelete(ids, userId, projectId); return this.ok(); } } diff --git a/packages/ui/certd-server/src/controller/user/monitor/site-info-controller.ts b/packages/ui/certd-server/src/controller/user/monitor/site-info-controller.ts index 7cdbf0c79..8ae3292cc 100644 --- a/packages/ui/certd-server/src/controller/user/monitor/site-info-controller.ts +++ b/packages/ui/certd-server/src/controller/user/monitor/site-info-controller.ts @@ -4,15 +4,15 @@ import { AuthService } from "../../../modules/sys/authority/service/auth-service import { SiteInfoService } from "../../../modules/monitor/service/site-info-service.js"; import { UserSiteMonitorSetting } from "../../../modules/mine/service/models.js"; import { merge } from "lodash-es"; -import {SiteIpService} from "../../../modules/monitor/service/site-ip-service.js"; +import { SiteIpService } from "../../../modules/monitor/service/site-ip-service.js"; import { utils } from "@certd/basic"; import { ApiTags } from "@midwayjs/swagger"; /** */ @Provide() -@Controller('/api/monitor/site') -@ApiTags(['monitor']) +@Controller("/api/monitor/site") +@ApiTags(["monitor"]) export class SiteInfoController extends CrudController { @Inject() service: SiteInfoService; @@ -25,11 +25,11 @@ export class SiteInfoController extends CrudController { return this.service; } - @Post('/page', { description: Constants.per.authOnly, summary: "查询站点监控分页列表" }) + @Post("/page", { description: Constants.per.authOnly, summary: "查询站点监控分页列表" }) async page(@Body(ALL) body: any) { body.query = body.query ?? {}; - const { projectId, userId } = await this.getProjectUserIdRead() - body.query.projectId = projectId + const { projectId, userId } = await this.getProjectUserIdRead(); + body.query.projectId = projectId; body.query.userId = userId; const certDomains = body.query.certDomains; const domain = body.query.domain; @@ -41,34 +41,34 @@ export class SiteInfoController extends CrudController { query: body.query, page: body.page, sort: body.sort, - buildQuery: (bq) => { + buildQuery: bq => { if (domain) { - bq.andWhere('domain like :domain', { domain: `%${domain}%` }); + bq.andWhere("domain like :domain", { domain: `%${domain}%` }); } if (certDomains) { - bq.andWhere('cert_domains like :cert_domains', { cert_domains: `%${certDomains}%` }); + bq.andWhere("cert_domains like :cert_domains", { cert_domains: `%${certDomains}%` }); } if (name) { - bq.andWhere('name like :name', { name: `%${name}%` }); + bq.andWhere("name like :name", { name: `%${name}%` }); } - } + }, }); return this.ok(res); } - @Post('/list', { description: Constants.per.authOnly, summary: "查询站点监控列表" }) + @Post("/list", { description: Constants.per.authOnly, summary: "查询站点监控列表" }) async list(@Body(ALL) body: any) { body.query = body.query ?? {}; - const { projectId, userId } = await this.getProjectUserIdRead() - body.query.projectId = projectId + const { projectId, userId } = await this.getProjectUserIdRead(); + body.query.projectId = projectId; body.query.userId = userId; return await super.list(body); } - @Post('/add', { description: Constants.per.authOnly, summary: "添加站点监控" }) + @Post("/add", { description: Constants.per.authOnly, summary: "添加站点监控" }) async add(@Body(ALL) bean: any) { - const { projectId, userId } = await this.getProjectUserIdWrite() - bean.projectId = projectId + const { projectId, userId } = await this.getProjectUserIdWrite(); + bean.projectId = projectId; bean.userId = userId; const res = await this.service.add(bean); const entity = await this.service.info(res.id); @@ -78,9 +78,9 @@ export class SiteInfoController extends CrudController { return this.ok(res); } - @Post('/update', { description: Constants.per.authOnly, summary: "更新站点监控" }) + @Post("/update", { description: Constants.per.authOnly, summary: "更新站点监控" }) async update(@Body(ALL) bean) { - await this.checkOwner(this.service,bean.id,"write"); + await this.checkOwner(this.service, bean.id, "write"); delete bean.userId; delete bean.projectId; await this.service.update(bean); @@ -90,89 +90,86 @@ export class SiteInfoController extends CrudController { } return this.ok(); } - @Post('/info', { description: Constants.per.authOnly, summary: "查询站点监控详情" }) - async info(@Query('id') id: number) { - await this.checkOwner(this.service,id,"read"); + @Post("/info", { description: Constants.per.authOnly, summary: "查询站点监控详情" }) + async info(@Query("id") id: number) { + await this.checkOwner(this.service, id, "read"); return await super.info(id); } - @Post('/delete', { description: Constants.per.authOnly, summary: "删除站点监控" }) - async delete(@Query('id') id: number) { - await this.checkOwner(this.service,id,"write"); + @Post("/delete", { description: Constants.per.authOnly, summary: "删除站点监控" }) + async delete(@Query("id") id: number) { + await this.checkOwner(this.service, id, "write"); return await super.delete(id); } - - @Post('/batchDelete', { description: Constants.per.authOnly, summary: "批量删除站点监控" }) + @Post("/batchDelete", { description: Constants.per.authOnly, summary: "批量删除站点监控" }) async batchDelete(@Body(ALL) body: any) { - const { projectId, userId } = await this.getProjectUserIdWrite() - await this.service.batchDelete(body.ids,userId,projectId); + const { projectId, userId } = await this.getProjectUserIdWrite(); + await this.service.batchDelete(body.ids, userId, projectId); return this.ok(); } - @Post('/check', { description: Constants.per.authOnly, summary: "检查站点监控" }) - async check(@Body('id') id: number) { - await this.checkOwner(this.service,id,"read"); + @Post("/check", { description: Constants.per.authOnly, summary: "检查站点监控" }) + async check(@Body("id") id: number) { + await this.checkOwner(this.service, id, "read"); await this.service.check(id, true, 0); await utils.sleep(1000); return this.ok(); } - @Post('/checkAll', { description: Constants.per.authOnly, summary: "检查所有站点监控" }) + @Post("/checkAll", { description: Constants.per.authOnly, summary: "检查所有站点监控" }) async checkAll() { - const { projectId, userId } = await this.getProjectUserIdWrite() - this.service.triggerJobOnce(userId,projectId); + const { projectId, userId } = await this.getProjectUserIdWrite(); + this.service.triggerJobOnce(userId, projectId); return this.ok(); } - @Post('/import', { description: Constants.per.authOnly, summary: "导入站点监控" }) + @Post("/import", { description: Constants.per.authOnly, summary: "导入站点监控" }) async doImport(@Body(ALL) body: any) { - const { projectId, userId } = await this.getProjectUserIdWrite() + const { projectId, userId } = await this.getProjectUserIdWrite(); await this.service.doImport({ - text:body.text, - groupId:body.groupId, + text: body.text, + groupId: body.groupId, userId, - projectId - }) - return this.ok(); - } - - - @Post('/ipCheckChange', { description: Constants.per.authOnly, summary: "修改IP检查设置" }) - async ipCheckChange(@Body(ALL) bean: any) { - await this.checkOwner(this.service,bean.id,"read"); - await this.service.ipCheckChange({ - id: bean.id, - ipCheck: bean.ipCheck + projectId, }); return this.ok(); } - @Post('/disabledChange', { description: Constants.per.authOnly, summary: "修改禁用状态" }) + @Post("/ipCheckChange", { description: Constants.per.authOnly, summary: "修改IP检查设置" }) + async ipCheckChange(@Body(ALL) bean: any) { + await this.checkOwner(this.service, bean.id, "read"); + await this.service.ipCheckChange({ + id: bean.id, + ipCheck: bean.ipCheck, + }); + return this.ok(); + } + + @Post("/disabledChange", { description: Constants.per.authOnly, summary: "修改禁用状态" }) async disabledChange(@Body(ALL) bean: any) { - await this.checkOwner(this.service,bean.id,"write"); + await this.checkOwner(this.service, bean.id, "write"); await this.service.disabledChange({ id: bean.id, - disabled: bean.disabled + disabled: bean.disabled, }); return this.ok(); } @Post("/setting/get", { description: Constants.per.authOnly, summary: "获取站点监控设置" }) async get() { - const { userId, projectId } = await this.getProjectUserIdRead() - const setting = await this.service.getSetting(userId, projectId) + const { userId, projectId } = await this.getProjectUserIdRead(); + const setting = await this.service.getSetting(userId, projectId); return this.ok(setting); } @Post("/setting/save", { description: Constants.per.authOnly, summary: "保存站点监控设置" }) async save(@Body(ALL) bean: any) { - const { userId, projectId} = await this.getProjectUserIdWrite() + const { userId, projectId } = await this.getProjectUserIdWrite(); const setting = new UserSiteMonitorSetting(); merge(setting, bean); - await this.service.saveSetting(userId, projectId,setting); + await this.service.saveSetting(userId, projectId, setting); return this.ok({}); } - } diff --git a/packages/ui/certd-server/src/controller/user/monitor/site-ip-controller.ts b/packages/ui/certd-server/src/controller/user/monitor/site-ip-controller.ts index 36bb86d20..0a39bae98 100644 --- a/packages/ui/certd-server/src/controller/user/monitor/site-ip-controller.ts +++ b/packages/ui/certd-server/src/controller/user/monitor/site-ip-controller.ts @@ -8,8 +8,8 @@ import { ApiTags } from "@midwayjs/swagger"; /** */ @Provide() -@Controller('/api/monitor/site/ip') -@ApiTags(['monitor']) +@Controller("/api/monitor/site/ip") +@ApiTags(["monitor"]) export class SiteInfoController extends CrudController { @Inject() service: SiteIpService; @@ -22,12 +22,12 @@ export class SiteInfoController extends CrudController { return this.service; } - @Post('/page', { description: Constants.per.authOnly, summary: "查询站点IP分页列表" }) + @Post("/page", { description: Constants.per.authOnly, summary: "查询站点IP分页列表" }) async page(@Body(ALL) body: any) { - const { projectId, userId } = await this.getProjectUserIdRead() + const { projectId, userId } = await this.getProjectUserIdRead(); body.query = body.query ?? {}; body.query.userId = userId; - body.query.projectId = projectId + body.query.projectId = projectId; const res = await this.service.page({ query: body.query, page: body.page, @@ -36,98 +36,94 @@ export class SiteInfoController extends CrudController { return this.ok(res); } - @Post('/list', { description: Constants.per.authOnly, summary: "查询站点IP列表" }) + @Post("/list", { description: Constants.per.authOnly, summary: "查询站点IP列表" }) async list(@Body(ALL) body: any) { body.query = body.query ?? {}; - const { projectId, userId } = await this.getProjectUserIdRead() + const { projectId, userId } = await this.getProjectUserIdRead(); body.query.userId = userId; - body.query.projectId = projectId + body.query.projectId = projectId; return await super.list(body); } - @Post('/add', { description: Constants.per.authOnly, summary: "添加站点IP" }) + @Post("/add", { description: Constants.per.authOnly, summary: "添加站点IP" }) async add(@Body(ALL) bean: any) { - const { projectId, userId } = await this.getProjectUserIdWrite() + const { projectId, userId } = await this.getProjectUserIdWrite(); bean.userId = userId; - bean.projectId = projectId - bean.from = "manual" + bean.projectId = projectId; + bean.from = "manual"; const res = await this.service.add(bean); const siteEntity = await this.siteInfoService.info(bean.siteId); - if(!siteEntity.disabled){ - const {domain, httpsPort} = siteEntity; - this.service.check(res.id,domain, httpsPort); + if (!siteEntity.disabled) { + const { domain, httpsPort } = siteEntity; + this.service.check(res.id, domain, httpsPort); } return this.ok(res); } - @Post('/update', { description: Constants.per.authOnly, summary: "更新站点IP" }) + @Post("/update", { description: Constants.per.authOnly, summary: "更新站点IP" }) async update(@Body(ALL) bean) { - await this.checkOwner(this.service,bean.id,"write"); + await this.checkOwner(this.service, bean.id, "write"); delete bean.userId; delete bean.projectId; await this.service.update(bean); const siteEntity = await this.siteInfoService.info(bean.siteId); - if(!siteEntity.disabled){ - const {domain, httpsPort} = siteEntity; - this.service.check(siteEntity.id,domain, httpsPort); + if (!siteEntity.disabled) { + const { domain, httpsPort } = siteEntity; + this.service.check(siteEntity.id, domain, httpsPort); } return this.ok(); } - @Post('/info', { description: Constants.per.authOnly, summary: "查询站点IP详情" }) - async info(@Query('id') id: number) { - await this.checkOwner(this.service,id,"read"); + @Post("/info", { description: Constants.per.authOnly, summary: "查询站点IP详情" }) + async info(@Query("id") id: number) { + await this.checkOwner(this.service, id, "read"); return await super.info(id); } - @Post('/delete', { description: Constants.per.authOnly, summary: "删除站点IP" }) - async delete(@Query('id') id: number) { - await this.checkOwner(this.service,id,"write"); + @Post("/delete", { description: Constants.per.authOnly, summary: "删除站点IP" }) + async delete(@Query("id") id: number) { + await this.checkOwner(this.service, id, "write"); const entity = await this.service.info(id); const res = await super.delete(id); - await this.service.updateIpCount(entity.siteId) - return res + await this.service.updateIpCount(entity.siteId); + return res; } - - - @Post('/check', { description: Constants.per.authOnly, summary: "检查站点IP" }) - async check(@Body('id') id: number) { - await this.checkOwner(this.service,id,"read"); + @Post("/check", { description: Constants.per.authOnly, summary: "检查站点IP" }) + async check(@Body("id") id: number) { + await this.checkOwner(this.service, id, "read"); const entity = await this.service.info(id); const siteEntity = await this.siteInfoService.info(entity.siteId); const domain = siteEntity.domain; const port = siteEntity.httpsPort; - this.service.check(id,domain,port); + this.service.check(id, domain, port); return this.ok(); } - @Post('/checkAll', { description: Constants.per.authOnly, summary: "检查所有站点IP" }) - async checkAll(@Body('siteId') siteId: number) { - await this.getProjectUserIdRead() + @Post("/checkAll", { description: Constants.per.authOnly, summary: "检查所有站点IP" }) + async checkAll(@Body("siteId") siteId: number) { + await this.getProjectUserIdRead(); const siteEntity = await this.siteInfoService.info(siteId); await this.service.syncAndCheck(siteEntity); return this.ok(); } - @Post('/sync', { description: Constants.per.authOnly, summary: "同步站点IP" }) - async sync(@Body('siteId') siteId: number) { - await this.getProjectUserIdWrite() - const entity = await this.siteInfoService.info(siteId) + @Post("/sync", { description: Constants.per.authOnly, summary: "同步站点IP" }) + async sync(@Body("siteId") siteId: number) { + await this.getProjectUserIdWrite(); + const entity = await this.siteInfoService.info(siteId); await this.service.sync(entity); return this.ok(); } - @Post('/import', { description: Constants.per.authOnly, summary: "导入站点IP" }) + @Post("/import", { description: Constants.per.authOnly, summary: "导入站点IP" }) async doImport(@Body(ALL) body: any) { - const { userId, projectId } = await this.getProjectUserIdWrite() + const { userId, projectId } = await this.getProjectUserIdWrite(); await this.service.doImport({ - text:body.text, + text: body.text, userId, - siteId:body.siteId, - projectId - }) + siteId: body.siteId, + projectId, + }); return this.ok(); } - - } diff --git a/packages/ui/certd-server/src/controller/user/open/open-key-controller.ts b/packages/ui/certd-server/src/controller/user/open/open-key-controller.ts index 7fbde2fa5..a1787f85e 100644 --- a/packages/ui/certd-server/src/controller/user/open/open-key-controller.ts +++ b/packages/ui/certd-server/src/controller/user/open/open-key-controller.ts @@ -1,14 +1,14 @@ -import { ALL, Body, Controller, Inject, Post, Provide, Query } from '@midwayjs/core'; -import { Constants, CrudController } from '@certd/lib-server'; -import { AuthService } from '../../../modules/sys/authority/service/auth-service.js'; -import { OpenKeyService } from '../../../modules/open/service/open-key-service.js'; -import { ApiTags } from '@midwayjs/swagger'; +import { ALL, Body, Controller, Inject, Post, Provide, Query } from "@midwayjs/core"; +import { Constants, CrudController } from "@certd/lib-server"; +import { AuthService } from "../../../modules/sys/authority/service/auth-service.js"; +import { OpenKeyService } from "../../../modules/open/service/open-key-service.js"; +import { ApiTags } from "@midwayjs/swagger"; /** */ @Provide() -@Controller('/api/open/key') -@ApiTags(['open']) +@Controller("/api/open/key") +@ApiTags(["open"]) export class OpenKeyController extends CrudController { @Inject() service: OpenKeyService; @@ -19,9 +19,9 @@ export class OpenKeyController extends CrudController { return this.service; } - @Post('/page', { description: Constants.per.authOnly, summary: "查询开放API密钥分页列表" }) + @Post("/page", { description: Constants.per.authOnly, summary: "查询开放API密钥分页列表" }) async page(@Body(ALL) body: any) { - const {projectId,userId} = await this.getProjectUserIdRead(); + const { projectId, userId } = await this.getProjectUserIdRead(); body.query = body.query ?? {}; body.query.projectId = projectId; body.query.userId = userId; @@ -36,13 +36,13 @@ export class OpenKeyController extends CrudController { private keySecretDesensitization(list: any[]) { for (const item of list) { - item.keySecret = item.keySecret?.substring(0, 4) + '*********************************' + item.keySecret?.substring(item.keySecret.length - 4); + item.keySecret = item.keySecret?.substring(0, 4) + "*********************************" + item.keySecret?.substring(item.keySecret.length - 4); } } - @Post('/list', { description: Constants.per.authOnly, summary: "查询开放API密钥列表" }) + @Post("/list", { description: Constants.per.authOnly, summary: "查询开放API密钥列表" }) async list(@Body(ALL) body: any) { - const {projectId,userId} = await this.getProjectUserIdRead(); + const { projectId, userId } = await this.getProjectUserIdRead(); body.query = body.query ?? {}; body.query.projectId = projectId; body.query.userId = userId; @@ -51,16 +51,16 @@ export class OpenKeyController extends CrudController { return this.ok(res); } - @Post('/add', { description: Constants.per.authOnly, summary: "添加开放API密钥" }) + @Post("/add", { description: Constants.per.authOnly, summary: "添加开放API密钥" }) async add(@Body(ALL) body: any) { - const {projectId,userId} = await this.getProjectUserIdRead(); + const { projectId, userId } = await this.getProjectUserIdRead(); body.projectId = projectId; body.userId = userId; const res = await this.service.add(body); return this.ok(res); } - @Post('/update', { description: Constants.per.authOnly, summary: "更新开放API密钥" }) + @Post("/update", { description: Constants.per.authOnly, summary: "更新开放API密钥" }) async update(@Body(ALL) bean) { await this.checkOwner(this.getService(), bean.id, "write"); delete bean.userId; @@ -68,8 +68,8 @@ export class OpenKeyController extends CrudController { await this.service.update(bean); return this.ok(); } - @Post('/info', { description: Constants.per.authOnly, summary: "查询开放API密钥详情" }) - async info(@Query('id') id: number) { + @Post("/info", { description: Constants.per.authOnly, summary: "查询开放API密钥详情" }) + async info(@Query("id") id: number) { const info = await this.checkPermission(id); return this.ok(info); } @@ -77,32 +77,31 @@ export class OpenKeyController extends CrudController { private async checkPermission(id: number) { const info = await this.service.info(id); if (!info) { - throw new Error('密钥不存在'); + throw new Error("密钥不存在"); } - if (info.scope === 'user'){ - await this.checkOwner(this.getService(), id, "write");; - }else{ + if (info.scope === "user") { + await this.checkOwner(this.getService(), id, "write"); + } else { await this.checkOwner(this.getService(), id, "read"); } - return info + return info; } - - @Post('/delete', { description: Constants.per.authOnly, summary: "删除开放API密钥" }) - async delete(@Query('id') id: number) { + @Post("/delete", { description: Constants.per.authOnly, summary: "删除开放API密钥" }) + async delete(@Query("id") id: number) { await this.checkOwner(this.getService(), id, "write"); return await super.delete(id); } - @Post('/getApiToken', { description: Constants.per.authOnly, summary: "获取API测试令牌" }) - async getApiToken(@Body('id') id: number) { + @Post("/getApiToken", { description: Constants.per.authOnly, summary: "获取API测试令牌" }) + async getApiToken(@Body("id") id: number) { await this.checkPermission(id); const token = await this.service.getApiToken(id); return this.ok(token); } - @Post('/getSecret', { description: Constants.per.authOnly, summary: "获取密钥" }) - async getSecret(@Body('id') id: number) { + @Post("/getSecret", { description: Constants.per.authOnly, summary: "获取密钥" }) + async getSecret(@Body("id") id: number) { const info = await this.checkPermission(id); return this.ok(info.keySecret); } diff --git a/packages/ui/certd-server/src/controller/user/pipeline/access-controller.ts b/packages/ui/certd-server/src/controller/user/pipeline/access-controller.ts index 270f2bbb5..181edd230 100644 --- a/packages/ui/certd-server/src/controller/user/pipeline/access-controller.ts +++ b/packages/ui/certd-server/src/controller/user/pipeline/access-controller.ts @@ -1,16 +1,16 @@ -import { ALL, Body, Controller, Inject, Post, Provide, Query } from '@midwayjs/core'; -import { Constants, CrudController } from '@certd/lib-server'; -import { AccessService } from '@certd/lib-server'; -import { AuthService } from '../../../modules/sys/authority/service/auth-service.js'; -import { AccessDefine } from '@certd/pipeline'; -import { ApiTags } from '@midwayjs/swagger'; +import { ALL, Body, Controller, Inject, Post, Provide, Query } from "@midwayjs/core"; +import { Constants, CrudController } from "@certd/lib-server"; +import { AccessService } from "@certd/lib-server"; +import { AuthService } from "../../../modules/sys/authority/service/auth-service.js"; +import { AccessDefine } from "@certd/pipeline"; +import { ApiTags } from "@midwayjs/swagger"; /** * 授权 */ @Provide() -@ApiTags(['pipeline-access']) -@Controller('/api/pi/access') +@ApiTags(["pipeline-access"]) +@Controller("/api/pi/access") export class AccessController extends CrudController { @Inject() service: AccessService; @@ -21,18 +21,18 @@ export class AccessController extends CrudController { return this.service; } - @Post('/page', { description: Constants.per.authOnly, summary: "查询授权配置分页列表" }) + @Post("/page", { description: Constants.per.authOnly, summary: "查询授权配置分页列表" }) async page(@Body(ALL) body) { - const { projectId, userId } = await this.getProjectUserIdRead() + const { projectId, userId } = await this.getProjectUserIdRead(); body.query = body.query ?? {}; delete body.query.userId; body.query.userId = userId; body.query.projectId = projectId; - let name = body.query?.name; + const name = body.query?.name; delete body.query.name; const buildQuery = qb => { if (name) { - qb.andWhere('name like :name', { name: `%${name.trim()}%` }); + qb.andWhere("name like :name", { name: `%${name.trim()}%` }); } }; const res = await this.service.page({ @@ -44,60 +44,60 @@ export class AccessController extends CrudController { return this.ok(res); } - @Post('/list', { description: Constants.per.authOnly, summary: "查询授权配置列表" }) + @Post("/list", { description: Constants.per.authOnly, summary: "查询授权配置列表" }) async list(@Body(ALL) body) { - const { projectId, userId } = await this.getProjectUserIdRead() + const { projectId, userId } = await this.getProjectUserIdRead(); body.query = body.query ?? {}; body.query.userId = userId; body.query.projectId = projectId; return super.list(body); } - @Post('/add', { description: Constants.per.authOnly, summary: "添加授权配置" }) + @Post("/add", { description: Constants.per.authOnly, summary: "添加授权配置" }) async add(@Body(ALL) bean) { - const { projectId, userId } = await this.getProjectUserIdWrite() + const { projectId, userId } = await this.getProjectUserIdWrite(); bean.userId = userId; bean.projectId = projectId; return super.add(bean); } - @Post('/update', { description: Constants.per.authOnly, summary: "更新授权配置" }) + @Post("/update", { description: Constants.per.authOnly, summary: "更新授权配置" }) async update(@Body(ALL) bean) { await this.checkOwner(this.getService(), bean.id, "write"); delete bean.userId; delete bean.projectId; return super.update(bean); } - @Post('/info', { description: Constants.per.authOnly, summary: "查询授权配置详情" }) - async info(@Query('id') id: number) { + @Post("/info", { description: Constants.per.authOnly, summary: "查询授权配置详情" }) + async info(@Query("id") id: number) { await this.checkOwner(this.getService(), id, "read"); return super.info(id); } - @Post('/delete', { description: Constants.per.authOnly, summary: "删除授权配置" }) - async delete(@Query('id') id: number) { + @Post("/delete", { description: Constants.per.authOnly, summary: "删除授权配置" }) + async delete(@Query("id") id: number) { await this.checkOwner(this.getService(), id, "write"); return super.delete(id); } - @Post('/define', { description: Constants.per.authOnly, summary: "查询授权插件定义" }) - async define(@Query('type') type: string) { + @Post("/define", { description: Constants.per.authOnly, summary: "查询授权插件定义" }) + async define(@Query("type") type: string) { const access = this.service.getDefineByType(type); return this.ok(access); } - @Post('/getSecretPlain', { description: Constants.per.authOnly, summary: "获取授权配置明文密钥" }) + @Post("/getSecretPlain", { description: Constants.per.authOnly, summary: "获取授权配置明文密钥" }) async getSecretPlain(@Body(ALL) body: { id: number; key: string }) { - const {userId, projectId} = await this.checkOwner(this.getService(), body.id, "read"); - const value = await this.service.getById(body.id, userId, projectId); + const { userId, projectId } = await this.checkOwner(this.getService(), body.id, "read"); + const value = await this.service.getById(body.id, userId, projectId); return this.ok(value[body.key]); } - @Post('/accessTypeDict', { description: Constants.per.authOnly, summary: "查询授权类型字典" }) + @Post("/accessTypeDict", { description: Constants.per.authOnly, summary: "查询授权类型字典" }) async getAccessTypeDict() { let list: AccessDefine[] = this.service.getDefineList(); - list = list.sort((a,b) => { - return (a.order??10) - (b.order??10); + list = list.sort((a, b) => { + return (a.order ?? 10) - (b.order ?? 10); }); const dict = []; for (const item of list) { @@ -110,17 +110,17 @@ export class AccessController extends CrudController { return this.ok(dict); } - @Post('/simpleInfo', { description: Constants.per.authOnly, summary: "查询授权配置简单信息" }) - async simpleInfo(@Query('id') id: number) { + @Post("/simpleInfo", { description: Constants.per.authOnly, summary: "查询授权配置简单信息" }) + async simpleInfo(@Query("id") id: number) { // await this.authService.checkUserIdButAllowAdmin(this.ctx, this.service, id); // await this.checkOwner(this.getService(), id, "read",true); const res = await this.service.getSimpleInfo(id); return this.ok(res); } - @Post('/getDictByIds', { description: Constants.per.authOnly, summary: "根据ID列表获取授权配置字典" }) - async getDictByIds(@Body('ids') ids: number[]) { - const { userId, projectId } = await this.getProjectUserIdRead() + @Post("/getDictByIds", { description: Constants.per.authOnly, summary: "根据ID列表获取授权配置字典" }) + async getDictByIds(@Body("ids") ids: number[]) { + const { userId, projectId } = await this.getProjectUserIdRead(); const res = await this.service.getSimpleByIds(ids, userId, projectId); return this.ok(res); } diff --git a/packages/ui/certd-server/src/controller/user/pipeline/cert-controller.ts b/packages/ui/certd-server/src/controller/user/pipeline/cert-controller.ts index 4d6031c3e..21718b760 100644 --- a/packages/ui/certd-server/src/controller/user/pipeline/cert-controller.ts +++ b/packages/ui/certd-server/src/controller/user/pipeline/cert-controller.ts @@ -1,64 +1,60 @@ -import { Body, Controller, Inject, Post, Provide, Query } from '@midwayjs/core'; -import { PipelineService } from '../../../modules/pipeline/service/pipeline-service.js'; -import { BaseController, Constants, PermissionException } from '@certd/lib-server'; -import { StorageService } from '../../../modules/pipeline/service/storage-service.js'; +import { Body, Controller, Inject, Post, Provide, Query } from "@midwayjs/core"; +import { PipelineService } from "../../../modules/pipeline/service/pipeline-service.js"; +import { BaseController, Constants, PermissionException } from "@certd/lib-server"; +import { StorageService } from "../../../modules/pipeline/service/storage-service.js"; import { CertReader } from "@certd/plugin-cert"; -import { UserSettingsService } from '../../../modules/mine/service/user-settings-service.js'; -import { UserGrantSetting } from '../../../modules/mine/service/models.js'; -import { ApiTags } from '@midwayjs/swagger'; +import { UserSettingsService } from "../../../modules/mine/service/user-settings-service.js"; +import { UserGrantSetting } from "../../../modules/mine/service/models.js"; +import { ApiTags } from "@midwayjs/swagger"; @Provide() -@Controller('/api/pi/cert') -@ApiTags(['pipeline-cert']) +@Controller("/api/pi/cert") +@ApiTags(["pipeline-cert"]) export class CertController extends BaseController { @Inject() pipelineService: PipelineService; @Inject() storeService: StorageService; - @Inject() userSettingsService: UserSettingsService; - - @Post('/get', { description: Constants.per.authOnly, summary: "获取证书" }) - async getCert(@Query('id') id: number) { - - const {userId} = await this.getProjectUserIdRead() + @Post("/get", { description: Constants.per.authOnly, summary: "获取证书" }) + async getCert(@Query("id") id: number) { + const { userId } = await this.getProjectUserIdRead(); const pipleinUserId = await this.pipelineService.getPipelineUserId(id); if (pipleinUserId !== userId) { // 如果是管理员,检查用户是否有授权管理员查看 - const isAdmin = await this.isAdmin() + const isAdmin = await this.isAdmin(); if (!isAdmin) { throw new PermissionException(); } // 是否允许管理员查看 - const setting = await this.userSettingsService.getSetting(pipleinUserId,null, UserGrantSetting, false); + const setting = await this.userSettingsService.getSetting(pipleinUserId, null, UserGrantSetting, false); if (setting?.allowAdminViewCerts !== true) { //不允许管理员查看 throw new PermissionException("该流水线的用户还未授权管理员查看证书,请先让用户在”设置->授权委托“中打开开关"); } } const privateVars = await this.storeService.getPipelinePrivateVars(id); - + const certInfo = privateVars.cert; if (certInfo?.crt) { const certReader = new CertReader(certInfo); - certInfo.detail = certReader.detail + certInfo.detail = certReader.detail; } return this.ok(certInfo); } - - @Post('/readCertDetail', { description: Constants.per.authOnly, summary: "读取证书详情" }) - async readCertDetail(@Body('crt') crt: string) { + @Post("/readCertDetail", { description: Constants.per.authOnly, summary: "读取证书详情" }) + async readCertDetail(@Body("crt") crt: string) { if (!crt) { - throw new Error('crt is required'); + throw new Error("crt is required"); } - const certDetail = CertReader.readCertDetail(crt) + const certDetail = CertReader.readCertDetail(crt); return this.ok(certDetail); } } diff --git a/packages/ui/certd-server/src/controller/user/pipeline/dns-provider-controller.ts b/packages/ui/certd-server/src/controller/user/pipeline/dns-provider-controller.ts index ff04c20bf..42974408a 100644 --- a/packages/ui/certd-server/src/controller/user/pipeline/dns-provider-controller.ts +++ b/packages/ui/certd-server/src/controller/user/pipeline/dns-provider-controller.ts @@ -1,26 +1,26 @@ -import { ALL, Controller, Inject, Post, Provide, Query } from '@midwayjs/core'; -import { DnsProviderService } from '../../../modules/pipeline/service/dns-provider-service.js'; -import { BaseController } from '@certd/lib-server'; -import { Constants } from '@certd/lib-server'; -import { ApiTags } from '@midwayjs/swagger'; +import { ALL, Controller, Inject, Post, Provide, Query } from "@midwayjs/core"; +import { DnsProviderService } from "../../../modules/pipeline/service/dns-provider-service.js"; +import { BaseController } from "@certd/lib-server"; +import { Constants } from "@certd/lib-server"; +import { ApiTags } from "@midwayjs/swagger"; /** * 插件 */ @Provide() -@Controller('/api/pi/dnsProvider') -@ApiTags(['pipeline-dns-provider']) +@Controller("/api/pi/dnsProvider") +@ApiTags(["pipeline-dns-provider"]) export class DnsProviderController extends BaseController { @Inject() service: DnsProviderService; - @Post('/list', { description: Constants.per.authOnly, summary: "查询DNS提供商列表" }) + @Post("/list", { description: Constants.per.authOnly, summary: "查询DNS提供商列表" }) async list(@Query(ALL) query: any) { const list = this.service.getList(); return this.ok(list); } - @Post('/dnsProviderTypeDict', { description: Constants.per.authOnly, summary: "查询DNS提供商类型字典" }) + @Post("/dnsProviderTypeDict", { description: Constants.per.authOnly, summary: "查询DNS提供商类型字典" }) async getDnsProviderTypeDict() { const list = this.service.getList(); const dict = []; diff --git a/packages/ui/certd-server/src/controller/user/pipeline/handle-controller.ts b/packages/ui/certd-server/src/controller/user/pipeline/handle-controller.ts index e6393cd62..11409bf40 100644 --- a/packages/ui/certd-server/src/controller/user/pipeline/handle-controller.ts +++ b/packages/ui/certd-server/src/controller/user/pipeline/handle-controller.ts @@ -1,27 +1,17 @@ -import {ALL, Body, Controller, Inject, Post, Provide} from '@midwayjs/core'; -import {AccessGetter, AccessService, BaseController, Constants} from '@certd/lib-server'; -import { - AccessRequestHandleReq, - IAccessService, - ITaskPlugin, - newAccess, - newNotification, - NotificationRequestHandleReq, - pluginRegistry, - PluginRequestHandleReq, - TaskInstanceContext, -} from '@certd/pipeline'; -import {EmailService} from '../../../modules/basic/service/email-service.js'; -import {http, HttpRequestConfig, logger, mergeUtils, utils} from '@certd/basic'; -import {NotificationService} from '../../../modules/pipeline/service/notification-service.js'; -import {TaskServiceBuilder} from "../../../modules/pipeline/service/getter/task-service-getter.js"; -import { cloneDeep } from 'lodash-es'; -import { ApiTags } from '@midwayjs/swagger'; -import { AuthService } from '../../../modules/sys/authority/service/auth-service.js'; +import { ALL, Body, Controller, Inject, Post, Provide } from "@midwayjs/core"; +import { AccessGetter, AccessService, BaseController, Constants } from "@certd/lib-server"; +import { AccessRequestHandleReq, IAccessService, ITaskPlugin, newAccess, newNotification, NotificationRequestHandleReq, pluginRegistry, PluginRequestHandleReq, TaskInstanceContext } from "@certd/pipeline"; +import { EmailService } from "../../../modules/basic/service/email-service.js"; +import { http, HttpRequestConfig, logger, mergeUtils, utils } from "@certd/basic"; +import { NotificationService } from "../../../modules/pipeline/service/notification-service.js"; +import { TaskServiceBuilder } from "../../../modules/pipeline/service/getter/task-service-getter.js"; +import { cloneDeep } from "lodash-es"; +import { ApiTags } from "@midwayjs/swagger"; +import { AuthService } from "../../../modules/sys/authority/service/auth-service.js"; @Provide() -@Controller('/api/pi/handle') -@ApiTags(['pipeline-handle']) +@Controller("/api/pi/handle") +@ApiTags(["pipeline-handle"]) export class HandleController extends BaseController { @Inject() accessService: AccessService; @@ -38,28 +28,28 @@ export class HandleController extends BaseController { @Inject() notificationService: NotificationService; - @Post('/access', { description: Constants.per.authOnly, summary: "处理授权请求" }) + @Post("/access", { description: Constants.per.authOnly, summary: "处理授权请求" }) async accessRequest(@Body(ALL) body: AccessRequestHandleReq) { - let {projectId,userId} = await this.getProjectUserIdRead() - if (body.fromType === 'sys') { + let { projectId, userId } = await this.getProjectUserIdRead(); + if (body.fromType === "sys") { //系统级别的请求 const pass = await this.authService.checkPermission(this.ctx, "sys:settings:view"); if (!pass) { - throw new Error('权限不足'); + throw new Error("权限不足"); } - projectId = null - userId = 0 + projectId = null; + userId = 0; } - + let inputAccess = body.input; if (body.record.id > 0) { const oldEntity = await this.accessService.info(body.record.id); if (oldEntity) { if (oldEntity.userId !== userId && oldEntity.userId !== this.getUserId()) { - throw new Error('您没有权限使用该授权'); + throw new Error("您没有权限使用该授权"); } if (oldEntity.projectId && oldEntity.projectId !== projectId) { - throw new Error('您没有权限使用该授权(projectId不匹配)'); + throw new Error("您没有权限使用该授权(projectId不匹配)"); } const param: any = { type: body.typeName, @@ -69,8 +59,8 @@ export class HandleController extends BaseController { inputAccess = this.accessService.decryptAccessEntity(param); } } - const accessGetter = new AccessGetter(userId,projectId, this.accessService.getById.bind(this.accessService)); - const access = await newAccess(body.typeName, inputAccess,accessGetter); + const accessGetter = new AccessGetter(userId, projectId, this.accessService.getById.bind(this.accessService)); + const access = await newAccess(body.typeName, inputAccess, accessGetter); // mergeUtils.merge(access, body.input); const res = await access.onRequest(body); @@ -78,7 +68,7 @@ export class HandleController extends BaseController { return this.ok(res); } - @Post('/notification', { description: Constants.per.authOnly, summary: "处理通知请求" }) + @Post("/notification", { description: Constants.per.authOnly, summary: "处理通知请求" }) async notificationRequest(@Body(ALL) body: NotificationRequestHandleReq) { const input = body.input; @@ -94,9 +84,9 @@ export class HandleController extends BaseController { return this.ok(res); } - @Post('/plugin', { description: Constants.per.authOnly, summary: "处理插件请求" }) + @Post("/plugin", { description: Constants.per.authOnly, summary: "处理插件请求" }) async pluginRequest(@Body(ALL) body: PluginRequestHandleReq) { - const {projectId,userId} = await this.getProjectUserIdRead() + const { projectId, userId } = await this.getProjectUserIdRead(); const pluginDefine = pluginRegistry.get(body.typeName); const pluginCls = await pluginDefine.target(); if (pluginCls == null) { @@ -117,14 +107,14 @@ export class HandleController extends BaseController { }); }; - const taskServiceGetter = this.taskServiceBuilder.create({userId,projectId}) + const taskServiceGetter = this.taskServiceBuilder.create({ userId, projectId }); - const accessGetter = await taskServiceGetter.get("accessService") + const accessGetter = await taskServiceGetter.get("accessService"); //@ts-ignore const taskCtx: TaskInstanceContext = { pipeline: undefined, step: undefined, - define: cloneDeep( pluginDefine.define), + define: cloneDeep(pluginDefine.define), lastStatus: undefined, http, download, @@ -136,7 +126,7 @@ export class HandleController extends BaseController { userContext: undefined, fileStore: undefined, signal: undefined, - user: {id:userId,role:"user"}, + user: { id: userId, role: "user" }, projectId, // pipelineContext: this.pipelineContext, // userContext: this.contextFactory.getContext('user', this.options.userId), @@ -147,7 +137,7 @@ export class HandleController extends BaseController { // }), // signal: this.abort.signal, utils, - serviceGetter:taskServiceGetter + serviceGetter: taskServiceGetter, }; instance.setCtx(taskCtx); mergeUtils.merge(plugin, body.input); diff --git a/packages/ui/certd-server/src/controller/user/pipeline/history-controller.ts b/packages/ui/certd-server/src/controller/user/pipeline/history-controller.ts index a30ee78ce..6dc716cf1 100644 --- a/packages/ui/certd-server/src/controller/user/pipeline/history-controller.ts +++ b/packages/ui/certd-server/src/controller/user/pipeline/history-controller.ts @@ -18,8 +18,8 @@ import { ApiTags } from "@midwayjs/swagger"; * 证书 */ @Provide() -@Controller('/api/pi/history') -@ApiTags(['pipeline-history']) +@Controller("/api/pi/history") +@ApiTags(["pipeline-history"]) export class HistoryController extends CrudController { @Inject() service: HistoryService; @@ -41,10 +41,10 @@ export class HistoryController extends CrudController { return this.service; } - @Post('/page', { description: Constants.per.authOnly, summary: "查询流水线执行历史分页列表" }) + @Post("/page", { description: Constants.per.authOnly, summary: "查询流水线执行历史分页列表" }) async page(@Body(ALL) body: any) { - const { projectId, userId } = await this.getProjectUserIdRead() - body.query.projectId = projectId + const { projectId, userId } = await this.getProjectUserIdRead(); + body.query.projectId = projectId; const isAdmin = await this.authService.isAdmin(this.ctx); const publicSettings = await this.sysSettingsService.getPublicSettings(); @@ -64,7 +64,7 @@ export class HistoryController extends CrudController { const pipelines = await this.pipelineService.list({ query: pipelineQuery, buildQuery: qb => { - qb.andWhere('title like :title', { title: `%${pipelineTitle}%` }); + qb.andWhere("title like :title", { title: `%${pipelineTitle}%` }); }, }); pipelineIds = pipelines.map(p => p.id); @@ -88,14 +88,14 @@ export class HistoryController extends CrudController { return this.ok(res); } - @Post('/list', { description: Constants.per.authOnly, summary: "查询流水线执行历史列表" }) + @Post("/list", { description: Constants.per.authOnly, summary: "查询流水线执行历史列表" }) async list(@Body(ALL) body) { - const { projectId, userId } = await this.getProjectUserIdRead() - if (!body){ - body = {} + const { projectId, userId } = await this.getProjectUserIdRead(); + if (!body) { + body = {}; } - if (projectId){ - body.projectId = projectId + if (projectId) { + body.projectId = projectId; } const isAdmin = this.authService.isAdmin(this.ctx); @@ -111,7 +111,7 @@ export class HistoryController extends CrudController { }; const withDetail = body.withDetail; delete body.withDetail; - let select: any = null + let select: any = null; if (!withDetail) { select = { pipeline: true, // 后面这里改成false @@ -129,9 +129,9 @@ export class HistoryController extends CrudController { } const listRet = await this.getService().list({ query: body, - sort: { prop: 'id', asc: false }, + sort: { prop: "id", asc: false }, buildQuery, - select + select, }); for (const item of listRet) { @@ -144,92 +144,92 @@ export class HistoryController extends CrudController { //@ts-ignore item.version = json.version; - item.status = json.status.result + item.status = json.status.result; delete item.pipeline; } return this.ok(listRet); } - @Post('/add', { description: Constants.per.authOnly, summary: "添加流水线执行历史" }) + @Post("/add", { description: Constants.per.authOnly, summary: "添加流水线执行历史" }) async add(@Body(ALL) bean: PipelineEntity) { - const { projectId, userId } = await this.getProjectUserIdRead() - bean.projectId = projectId + const { projectId, userId } = await this.getProjectUserIdRead(); + bean.projectId = projectId; bean.userId = userId; return super.add(bean); } - @Post('/update', { description: Constants.per.authOnly, summary: "更新流水线执行历史" }) + @Post("/update", { description: Constants.per.authOnly, summary: "更新流水线执行历史" }) async update(@Body(ALL) bean) { - await this.checkOwner(this.getService(), bean.id,"write",true); + await this.checkOwner(this.getService(), bean.id, "write", true); delete bean.userId; delete bean.projectId; return super.update(bean); } - @Post('/save', { description: Constants.per.authOnly, summary: "保存流水线执行历史" }) + @Post("/save", { description: Constants.per.authOnly, summary: "保存流水线执行历史" }) async save(@Body(ALL) bean: HistoryEntity) { - const { projectId,userId } = await this.getProjectUserIdWrite() + const { projectId, userId } = await this.getProjectUserIdWrite(); bean.userId = userId; bean.projectId = projectId; if (bean.id > 0) { //修改 delete bean.projectId; delete bean.userId; - await this.checkOwner(this.getService(), bean.id,"write",true); + await this.checkOwner(this.getService(), bean.id, "write", true); } - + await this.service.save(bean); return this.ok(bean.id); } - @Post('/saveLog', { description: Constants.per.authOnly, summary: "保存流水线执行日志" }) + @Post("/saveLog", { description: Constants.per.authOnly, summary: "保存流水线执行日志" }) async saveLog(@Body(ALL) bean: HistoryLogEntity) { - const { projectId,userId } = await this.getProjectUserIdWrite() + const { projectId, userId } = await this.getProjectUserIdWrite(); bean.projectId = projectId; bean.userId = userId; if (bean.id > 0) { //修改 delete bean.projectId; delete bean.userId; - await this.checkOwner(this.logService, bean.id,"write",true); + await this.checkOwner(this.logService, bean.id, "write", true); } await this.logService.save(bean); return this.ok(bean.id); } - @Post('/delete', { description: Constants.per.authOnly, summary: "删除流水线执行历史" }) - async delete(@Query('id') id: number) { - await this.checkOwner(this.getService(), id,"write",true); + @Post("/delete", { description: Constants.per.authOnly, summary: "删除流水线执行历史" }) + async delete(@Query("id") id: number) { + await this.checkOwner(this.getService(), id, "write", true); await super.delete(id); return this.ok(); } - @Post('/deleteByIds', { description: Constants.per.authOnly, summary: "批量删除流水线执行历史" }) + @Post("/deleteByIds", { description: Constants.per.authOnly, summary: "批量删除流水线执行历史" }) async deleteByIds(@Body(ALL) body: any) { - let {userId} = await this.checkOwner(this.getService(), body.ids,"write",true); + let { userId } = await this.checkOwner(this.getService(), body.ids, "write", true); const isAdmin = await this.authService.isAdmin(this.ctx); userId = isAdmin ? null : userId; await this.getService().deleteByIds(body.ids, userId); return this.ok(); } - @Post('/detail', { description: Constants.per.authOnly, summary: "查询流水线执行历史详情" }) - async detail(@Query('id') id: number) { - await this.checkOwner(this.getService(), id,"read",true); + @Post("/detail", { description: Constants.per.authOnly, summary: "查询流水线执行历史详情" }) + async detail(@Query("id") id: number) { + await this.checkOwner(this.getService(), id, "read", true); const detail = await this.service.detail(id); return this.ok(detail); } - @Post('/logs', { description: Constants.per.authOnly, summary: "查询流水线执行日志" }) - async logs(@Query('id') id: number) { - await this.checkOwner(this.logService, id,"read",true); + @Post("/logs", { description: Constants.per.authOnly, summary: "查询流水线执行日志" }) + async logs(@Query("id") id: number) { + await this.checkOwner(this.logService, id, "read", true); const logInfo = await this.logService.info(id); return this.ok(logInfo); } - @Post('/files', { description: Constants.per.authOnly, summary: "查询流水线执行文件" }) - async files(@Query('pipelineId') pipelineId: number, @Query('historyId') historyId: number) { + @Post("/files", { description: Constants.per.authOnly, summary: "查询流水线执行文件" }) + async files(@Query("pipelineId") pipelineId: number, @Query("historyId") historyId: number) { const files = await this.getFiles(historyId, pipelineId); return this.ok(files); } @@ -243,24 +243,24 @@ export class HistoryController extends CrudController { history = await this.service.getLastHistory(pipelineId); } if (history == null) { - throw new CommonException('流水线还未运行过'); + throw new CommonException("流水线还未运行过"); } - const {projectId} = await this.getProjectUserIdRead() + const { projectId } = await this.getProjectUserIdRead(); if (projectId) { //enterprise模式 - if(history.projectId !== projectId){ - throw new PermissionException("您没有权限下载该流水线证书,请先加入该项目:"+history.projectId); + if (history.projectId !== projectId) { + throw new PermissionException("您没有权限下载该流水线证书,请先加入该项目:" + history.projectId); } //有权限下载 - }else if (history.userId !== this.getUserId()) { + } else if (history.userId !== this.getUserId()) { // 如果是管理员,检查用户是否有授权管理员查看 - const isAdmin = await this.isAdmin() + const isAdmin = await this.isAdmin(); if (!isAdmin) { throw new PermissionException(); } // 是否允许管理员查看 const setting = await this.userSettingsService.getSetting(history.userId, null, UserGrantSetting, false); - if (setting?.allowAdminViewCerts!==true) { + if (setting?.allowAdminViewCerts !== true) { //不允许管理员查看 throw new PermissionException("该流水线的用户还未授权管理员下载证书,请先让用户在”设置->授权委托“中打开开关"); } @@ -269,12 +269,12 @@ export class HistoryController extends CrudController { return await this.service.getFiles(history); } - @Get('/download', { description: Constants.per.authOnly, summary: "下载流水线执行文件" }) - async download(@Query('pipelineId') pipelineId: number, @Query('historyId') historyId: number, @Query('fileId') fileId: string) { + @Get("/download", { description: Constants.per.authOnly, summary: "下载流水线执行文件" }) + async download(@Query("pipelineId") pipelineId: number, @Query("historyId") historyId: number, @Query("fileId") fileId: string) { const files = await this.getFiles(historyId, pipelineId); const file = files.find(f => f.id === fileId); if (file == null) { - throw new CommonException('file not found'); + throw new CommonException("file not found"); } // koa send file // 下载文件的名称 @@ -284,7 +284,7 @@ export class HistoryController extends CrudController { logger.info(`download:${path}`); // 以流的形式下载文件 this.ctx.attachment(path); - this.ctx.set('Content-Type', 'application/octet-stream'); + this.ctx.set("Content-Type", "application/octet-stream"); return fs.createReadStream(path); } diff --git a/packages/ui/certd-server/src/controller/user/pipeline/notification-controller.ts b/packages/ui/certd-server/src/controller/user/pipeline/notification-controller.ts index f00c3c769..06aca817e 100644 --- a/packages/ui/certd-server/src/controller/user/pipeline/notification-controller.ts +++ b/packages/ui/certd-server/src/controller/user/pipeline/notification-controller.ts @@ -1,17 +1,17 @@ -import { ALL, Body, Controller, Inject, Post, Provide, Query } from '@midwayjs/core'; -import { Constants, CrudController, ValidateException } from '@certd/lib-server'; -import { NotificationService } from '../../../modules/pipeline/service/notification-service.js'; -import { AuthService } from '../../../modules/sys/authority/service/auth-service.js'; -import { NotificationDefine } from '@certd/pipeline'; -import { checkPlus } from '@certd/plus-core'; -import { ApiTags } from '@midwayjs/swagger'; +import { ALL, Body, Controller, Inject, Post, Provide, Query } from "@midwayjs/core"; +import { Constants, CrudController, ValidateException } from "@certd/lib-server"; +import { NotificationService } from "../../../modules/pipeline/service/notification-service.js"; +import { AuthService } from "../../../modules/sys/authority/service/auth-service.js"; +import { NotificationDefine } from "@certd/pipeline"; +import { checkPlus } from "@certd/plus-core"; +import { ApiTags } from "@midwayjs/swagger"; /** * 通知 */ @Provide() -@Controller('/api/pi/notification') -@ApiTags(['pipeline-notification']) +@Controller("/api/pi/notification") +@ApiTags(["pipeline-notification"]) export class NotificationController extends CrudController { @Inject() service: NotificationService; @@ -22,14 +22,14 @@ export class NotificationController extends CrudController return this.service; } - @Post('/page', { description: Constants.per.authOnly, summary: "查询通知配置分页列表" }) + @Post("/page", { description: Constants.per.authOnly, summary: "查询通知配置分页列表" }) async page(@Body(ALL) body) { - const {projectId,userId} = await this.getProjectUserIdRead(); + const { projectId, userId } = await this.getProjectUserIdRead(); body.query = body.query ?? {}; delete body.query.userId; body.query.projectId = projectId; const buildQuery = qb => { - qb.andWhere('user_id = :userId', { userId: userId}); + qb.andWhere("user_id = :userId", { userId: userId }); }; const res = await this.service.page({ query: body.query, @@ -40,24 +40,24 @@ export class NotificationController extends CrudController return this.ok(res); } - @Post('/list', { description: Constants.per.authOnly, summary: "查询通知配置列表" }) + @Post("/list", { description: Constants.per.authOnly, summary: "查询通知配置列表" }) async list(@Body(ALL) body) { - const {projectId,userId} = await this.getProjectUserIdRead(); + const { projectId, userId } = await this.getProjectUserIdRead(); body.query = body.query ?? {}; body.query.userId = userId; body.query.projectId = projectId; return super.list(body); } - @Post('/add', { description: Constants.per.authOnly, summary: "添加通知配置" }) + @Post("/add", { description: Constants.per.authOnly, summary: "添加通知配置" }) async add(@Body(ALL) bean) { - const {projectId,userId} = await this.getProjectUserIdRead(); + const { projectId, userId } = await this.getProjectUserIdRead(); bean.userId = userId; bean.projectId = projectId; const type = bean.type; const define: NotificationDefine = this.service.getDefineByType(type); if (!define) { - throw new ValidateException('通知类型不存在'); + throw new ValidateException("通知类型不存在"); } if (define.needPlus) { checkPlus(); @@ -65,18 +65,18 @@ export class NotificationController extends CrudController return super.add(bean); } - @Post('/update', { description: Constants.per.authOnly, summary: "更新通知配置" }) + @Post("/update", { description: Constants.per.authOnly, summary: "更新通知配置" }) async update(@Body(ALL) bean) { - await this.checkOwner(this.getService(), bean.id,"write"); + await this.checkOwner(this.getService(), bean.id, "write"); const old = await this.service.info(bean.id); if (!old) { - throw new ValidateException('通知配置不存在'); + throw new ValidateException("通知配置不存在"); } if (old.type !== bean.type) { const type = bean.type; const define: NotificationDefine = this.service.getDefineByType(type); if (!define) { - throw new ValidateException('通知类型不存在'); + throw new ValidateException("通知类型不存在"); } if (define.needPlus) { checkPlus(); @@ -86,25 +86,25 @@ export class NotificationController extends CrudController delete bean.projectId; return super.update(bean); } - @Post('/info', { description: Constants.per.authOnly, summary: "查询通知配置详情" }) - async info(@Query('id') id: number) { - await this.checkOwner(this.getService(), id,"read"); + @Post("/info", { description: Constants.per.authOnly, summary: "查询通知配置详情" }) + async info(@Query("id") id: number) { + await this.checkOwner(this.getService(), id, "read"); return super.info(id); } - @Post('/delete', { description: Constants.per.authOnly, summary: "删除通知配置" }) - async delete(@Query('id') id: number) { - await this.checkOwner(this.getService(), id,"write"); + @Post("/delete", { description: Constants.per.authOnly, summary: "删除通知配置" }) + async delete(@Query("id") id: number) { + await this.checkOwner(this.getService(), id, "write"); return super.delete(id); } - @Post('/define', { description: Constants.per.authOnly, summary: "查询通知插件定义" }) - async define(@Query('type') type: string) { + @Post("/define", { description: Constants.per.authOnly, summary: "查询通知插件定义" }) + async define(@Query("type") type: string) { const notification = this.service.getDefineByType(type); return this.ok(notification); } - @Post('/getTypeDict', { description: Constants.per.authOnly, summary: "查询通知类型字典" }) + @Post("/getTypeDict", { description: Constants.per.authOnly, summary: "查询通知类型字典" }) async getTypeDict() { const list: any = this.service.getDefineList(); let dict = []; @@ -125,48 +125,48 @@ export class NotificationController extends CrudController return this.ok(dict); } - @Post('/simpleInfo', { description: Constants.per.authOnly, summary: "查询通知配置简单信息" }) - async simpleInfo(@Query('id') id: number) { - const {projectId,userId} = await this.getProjectUserIdRead(); + @Post("/simpleInfo", { description: Constants.per.authOnly, summary: "查询通知配置简单信息" }) + async simpleInfo(@Query("id") id: number) { + const { projectId, userId } = await this.getProjectUserIdRead(); if (id === 0) { //获取默认 - const res = await this.service.getDefault(userId,projectId); + const res = await this.service.getDefault(userId, projectId); if (!res) { - throw new ValidateException('默认通知配置不存在'); + throw new ValidateException("默认通知配置不存在"); } const simple = await this.service.getSimpleInfo(res.id); return this.ok(simple); } - await this.checkOwner(this.getService(), id,"read",true); + await this.checkOwner(this.getService(), id, "read", true); const res = await this.service.getSimpleInfo(id); return this.ok(res); } - @Post('/getDefaultId', { description: Constants.per.authOnly, summary: "查询默认通知配置ID" }) + @Post("/getDefaultId", { description: Constants.per.authOnly, summary: "查询默认通知配置ID" }) async getDefaultId() { - const {projectId,userId} = await this.getProjectUserIdRead(); - const res = await this.service.getDefault(userId,projectId); + const { projectId, userId } = await this.getProjectUserIdRead(); + const res = await this.service.getDefault(userId, projectId); return this.ok(res?.id); } - @Post('/setDefault', { description: Constants.per.authOnly, summary: "设置默认通知配置" }) - async setDefault(@Query('id') id: number) { - const {projectId,userId} = await this.getProjectUserIdRead(); - await this.checkOwner(this.getService(), id,"write"); - const res = await this.service.setDefault(id, userId,projectId); + @Post("/setDefault", { description: Constants.per.authOnly, summary: "设置默认通知配置" }) + async setDefault(@Query("id") id: number) { + const { projectId, userId } = await this.getProjectUserIdRead(); + await this.checkOwner(this.getService(), id, "write"); + const res = await this.service.setDefault(id, userId, projectId); return this.ok(res); } - @Post('/getOrCreateDefault', { description: Constants.per.authOnly, summary: "获取或创建默认通知配置" }) - async getOrCreateDefault(@Body('email') email: string) { - const {projectId,userId} = await this.getProjectUserIdRead(); - const res = await this.service.getOrCreateDefault(email, userId,projectId); + @Post("/getOrCreateDefault", { description: Constants.per.authOnly, summary: "获取或创建默认通知配置" }) + async getOrCreateDefault(@Body("email") email: string) { + const { projectId, userId } = await this.getProjectUserIdRead(); + const res = await this.service.getOrCreateDefault(email, userId, projectId); return this.ok(res); } - @Post('/options', { description: Constants.per.authOnly, summary: "查询通知配置选项" }) + @Post("/options", { description: Constants.per.authOnly, summary: "查询通知配置选项" }) async options() { - const {projectId,userId} = await this.getProjectUserIdRead(); + const { projectId, userId } = await this.getProjectUserIdRead(); const res = await this.service.list({ query: { userId: userId, diff --git a/packages/ui/certd-server/src/controller/user/pipeline/pipeline-controller.ts b/packages/ui/certd-server/src/controller/user/pipeline/pipeline-controller.ts index 732a8996c..59f519362 100644 --- a/packages/ui/certd-server/src/controller/user/pipeline/pipeline-controller.ts +++ b/packages/ui/certd-server/src/controller/user/pipeline/pipeline-controller.ts @@ -1,13 +1,12 @@ -import { Constants, CrudController, SysSettingsService } from '@certd/lib-server'; -import { isPlus } from '@certd/plus-core'; -import { ALL, Body, Controller, Inject, Post, Provide, Query } from '@midwayjs/core'; -import { ApiProperty, ApiTags } from '@midwayjs/swagger'; -import { SiteInfoService } from '../../../modules/monitor/index.js'; -import { HistoryService } from '../../../modules/pipeline/service/history-service.js'; -import { PipelineService } from '../../../modules/pipeline/service/pipeline-service.js'; -import { AuthService } from '../../../modules/sys/authority/service/auth-service.js'; -import { PipelineEntity } from '../../../modules/pipeline/entity/pipeline.js'; - +import { Constants, CrudController, SysSettingsService } from "@certd/lib-server"; +import { isPlus } from "@certd/plus-core"; +import { ALL, Body, Controller, Inject, Post, Provide, Query } from "@midwayjs/core"; +import { ApiProperty, ApiTags } from "@midwayjs/swagger"; +import { SiteInfoService } from "../../../modules/monitor/index.js"; +import { HistoryService } from "../../../modules/pipeline/service/history-service.js"; +import { PipelineService } from "../../../modules/pipeline/service/pipeline-service.js"; +import { AuthService } from "../../../modules/sys/authority/service/auth-service.js"; +import { PipelineEntity } from "../../../modules/pipeline/entity/pipeline.js"; const pipelineExample = ` // 流水线配置示例,实际传送时要去掉注释 @@ -67,50 +66,50 @@ const pipelineExample = ` "notificationId": 0, // 通知ID, 0为使用默认通知 } ], -}` +}`; export class PipelineSaveDTO { - @ApiProperty({ description: 'Id,修改时必传' }) - id: number; - userId: number; - @ApiProperty({ description: '标题' }) - title: string; - @ApiProperty({ description: '流水线详细配置,json格式的字符串', example: pipelineExample }) - content: string; + @ApiProperty({ description: "Id,修改时必传" }) + id: number; + userId: number; + @ApiProperty({ description: "标题" }) + title: string; + @ApiProperty({ description: "流水线详细配置,json格式的字符串", example: pipelineExample }) + content: string; - @ApiProperty({ description: '保留历史版本数量' }) - keepHistoryCount: number; - @ApiProperty({ description: '分组ID' }) - groupId: number; - @ApiProperty({ description: '备注' }) - remark: string; - @ApiProperty({ description: '状态' }) - status: string; - @ApiProperty({ description: '是否禁用' }) - disabled: boolean; - @ApiProperty({ description: '类型' }) - type: string; - webhookKey: string; - @ApiProperty({ description: '来源' }) - from: string; - @ApiProperty({ description: '排序' }) - order: number; - @ApiProperty({ description: '项目ID' }) - projectId: number; - @ApiProperty({ description: '流水线有效期,单位秒' }) - validTime: number; - @ApiProperty({ description: '是否增加证书监控' }) - addToMonitorEnabled: boolean - @ApiProperty({ description: '增加证书监控的域名,逗号分隔' }) - addToMonitorDomains: string + @ApiProperty({ description: "保留历史版本数量" }) + keepHistoryCount: number; + @ApiProperty({ description: "分组ID" }) + groupId: number; + @ApiProperty({ description: "备注" }) + remark: string; + @ApiProperty({ description: "状态" }) + status: string; + @ApiProperty({ description: "是否禁用" }) + disabled: boolean; + @ApiProperty({ description: "类型" }) + type: string; + webhookKey: string; + @ApiProperty({ description: "来源" }) + from: string; + @ApiProperty({ description: "排序" }) + order: number; + @ApiProperty({ description: "项目ID" }) + projectId: number; + @ApiProperty({ description: "流水线有效期,单位秒" }) + validTime: number; + @ApiProperty({ description: "是否增加证书监控" }) + addToMonitorEnabled: boolean; + @ApiProperty({ description: "增加证书监控的域名,逗号分隔" }) + addToMonitorDomains: string; } /** * 证书 */ @Provide() -@ApiTags(['pipeline']) -@Controller('/api/pi/pipeline') +@ApiTags(["pipeline"]) +@Controller("/api/pi/pipeline") export class PipelineController extends CrudController { @Inject() service: PipelineService; @@ -124,19 +123,18 @@ export class PipelineController extends CrudController { @Inject() siteInfoService: SiteInfoService; - getService() { return this.service; } - @Post('/page', { description: Constants.per.authOnly, summary: "查询流水线分页列表" }) + @Post("/page", { description: Constants.per.authOnly, summary: "查询流水线分页列表" }) async page(@Body(ALL) body) { const isAdmin = await this.authService.isAdmin(this.ctx); const publicSettings = await this.sysSettingsService.getPublicSettings(); - const { projectId, userId } = await this.getProjectUserIdRead() - body.query.projectId = projectId - let onlyOther = false + const { projectId, userId } = await this.getProjectUserIdRead(); + body.query.projectId = projectId; + let onlyOther = false; if (isAdmin) { if (publicSettings.managerOtherUserPipeline) { //管理员管理 其他用户 @@ -157,14 +155,14 @@ export class PipelineController extends CrudController { const buildQuery = qb => { if (title) { - qb.andWhere('(title like :title or content like :content)', { title: `%${title}%`, content: `%${title}%` }); + qb.andWhere("(title like :title or content like :content)", { title: `%${title}%`, content: `%${title}%` }); } if (onlyOther) { - qb.andWhere('user_id != :userId', { userId: this.getUserId() }); + qb.andWhere("user_id != :userId", { userId: this.getUserId() }); } }; if (!body.sort || !body.sort?.prop) { - body.sort = { prop: 'order', asc: false }; + body.sort = { prop: "order", asc: false }; } const pageRet = await this.getService().page({ @@ -176,31 +174,30 @@ export class PipelineController extends CrudController { return this.ok(pageRet); } - @Post('/getSimpleByIds', { description: Constants.per.authOnly, summary: "根据ID列表获取流水线简单信息" }) + @Post("/getSimpleByIds", { description: Constants.per.authOnly, summary: "根据ID列表获取流水线简单信息" }) async getSimpleById(@Body(ALL) body) { - const { projectId, userId } = await this.getProjectUserIdRead() + const { projectId, userId } = await this.getProjectUserIdRead(); const ret = await this.getService().getSimplePipelines(body.ids, userId, projectId); return this.ok(ret); } - - @Post('/add', { description: Constants.per.authOnly }) + @Post("/add", { description: Constants.per.authOnly }) async add(@Body(ALL) bean: PipelineEntity) { return await this.save(bean as any); } - @Post('/update', { description: Constants.per.authOnly }) - async update(@Body(ALL) bean:PipelineEntity) { - await this.checkOwner(this.getService(), bean.id,"write",true); - await this.service.update(bean as any); - return this.ok({}); + @Post("/update", { description: Constants.per.authOnly }) + async update(@Body(ALL) bean: PipelineEntity) { + await this.checkOwner(this.getService(), bean.id, "write", true); + await this.service.update(bean as any); + return this.ok({}); } - @Post('/save', { description: Constants.per.authOnly, summary: '新增/更新流水线' }) + @Post("/save", { description: Constants.per.authOnly, summary: "新增/更新流水线" }) async save(@Body() bean: PipelineSaveDTO) { - const { userId ,projectId} = await this.getProjectUserIdWrite() + const { userId, projectId } = await this.getProjectUserIdWrite(); if (bean.id > 0) { - const {userId,projectId} = await this.checkOwner(this.getService(), bean.id,"write",true); + const { userId, projectId } = await this.checkOwner(this.getService(), bean.id, "write", true); bean.userId = userId; bean.projectId = projectId; } else { @@ -210,7 +207,7 @@ export class PipelineController extends CrudController { if (!this.isAdmin()) { // 非管理员用户 不允许设置流水线有效期 - delete bean.validTime + delete bean.validTime; } const { version } = await this.service.save(bean as any); @@ -229,63 +226,62 @@ export class PipelineController extends CrudController { return this.ok({ id: bean.id, version: version }); } - @Post('/delete', { description: Constants.per.authOnly, summary: "删除流水线" }) - async delete(@Query('id') id: number) { - await this.checkOwner(this.getService(), id,"write",true); + @Post("/delete", { description: Constants.per.authOnly, summary: "删除流水线" }) + async delete(@Query("id") id: number) { + await this.checkOwner(this.getService(), id, "write", true); await this.service.delete(id); return this.ok({}); } - @Post('/disabled', { description: Constants.per.authOnly, summary: "禁用流水线" }) + @Post("/disabled", { description: Constants.per.authOnly, summary: "禁用流水线" }) async disabled(@Body(ALL) bean) { - await this.checkOwner(this.getService(), bean.id,"write",true); + await this.checkOwner(this.getService(), bean.id, "write", true); delete bean.userId; delete bean.projectId; await this.service.disabled(bean.id, bean.disabled); return this.ok({}); } - @Post('/detail', { description: Constants.per.authOnly, summary: "查询流水线详情" }) - async detail(@Query('id') id: number) { - await this.checkOwner(this.getService(), id,"read",true); + @Post("/detail", { description: Constants.per.authOnly, summary: "查询流水线详情" }) + async detail(@Query("id") id: number) { + await this.checkOwner(this.getService(), id, "read", true); const detail = await this.service.detail(id); return this.ok(detail); } - @Post('/trigger', { description: Constants.per.authOnly, summary: "触发流水线执行" }) - async trigger(@Query('id') id: number, @Query('stepId') stepId?: string) { - await this.checkOwner(this.getService(), id,"write",true); + @Post("/trigger", { description: Constants.per.authOnly, summary: "触发流水线执行" }) + async trigger(@Query("id") id: number, @Query("stepId") stepId?: string) { + await this.checkOwner(this.getService(), id, "write", true); await this.service.trigger(id, stepId, true); return this.ok({}); } - @Post('/cancel', { description: Constants.per.authOnly, summary: "取消流水线执行" }) - async cancel(@Query('historyId') historyId: number) { - await this.checkOwner(this.historyService, historyId,"write",true); + @Post("/cancel", { description: Constants.per.authOnly, summary: "取消流水线执行" }) + async cancel(@Query("historyId") historyId: number) { + await this.checkOwner(this.historyService, historyId, "write", true); await this.service.cancel(historyId); return this.ok({}); } - @Post('/count', { description: Constants.per.authOnly, summary: "查询流水线数量" }) + @Post("/count", { description: Constants.per.authOnly, summary: "查询流水线数量" }) async count() { - const { userId } = await this.getProjectUserIdRead() + const { userId } = await this.getProjectUserIdRead(); const count = await this.service.count({ userId: userId }); return this.ok({ count }); } - - private async checkPermissionCall(callback:any){ - let { projectId ,userId} = await this.getProjectUserIdWrite() - if(projectId){ - return await callback({userId,projectId}); + private async checkPermissionCall(callback: any) { + let { projectId, userId } = await this.getProjectUserIdWrite(); + if (projectId) { + return await callback({ userId, projectId }); } const isAdmin = await this.authService.isAdmin(this.ctx); userId = isAdmin ? undefined : userId; - return await callback({userId}); + return await callback({ userId }); } - @Post('/batchDelete', { description: Constants.per.authOnly, summary: "批量删除流水线" }) - async batchDelete(@Body('ids') ids: number[]) { + @Post("/batchDelete", { description: Constants.per.authOnly, summary: "批量删除流水线" }) + async batchDelete(@Body("ids") ids: number[]) { // let { projectId ,userId} = await this.getProjectUserIdWrite() // if(projectId){ // await this.service.batchDelete(ids, null,projectId); @@ -295,16 +291,14 @@ export class PipelineController extends CrudController { // userId = isAdmin ? undefined : userId; // await this.service.batchDelete(ids, userId); // return this.ok({}); - await this.checkPermissionCall(async ({userId,projectId})=>{ - await this.service.batchDelete(ids, userId,projectId); - }) - return this.ok({}) + await this.checkPermissionCall(async ({ userId, projectId }) => { + await this.service.batchDelete(ids, userId, projectId); + }); + return this.ok({}); } - - - @Post('/batchUpdateGroup', { description: Constants.per.authOnly, summary: "批量更新流水线分组" }) - async batchUpdateGroup(@Body('ids') ids: number[], @Body('groupId') groupId: number) { + @Post("/batchUpdateGroup", { description: Constants.per.authOnly, summary: "批量更新流水线分组" }) + async batchUpdateGroup(@Body("ids") ids: number[], @Body("groupId") groupId: number) { // let { projectId ,userId} = await this.getProjectUserIdWrite() // if(projectId){ // await this.service.batchUpdateGroup(ids, groupId, null,projectId); @@ -314,15 +308,14 @@ export class PipelineController extends CrudController { // const isAdmin = await this.authService.isAdmin(this.ctx); // userId = isAdmin ? undefined : this.getUserId(); // await this.service.batchUpdateGroup(ids, groupId, userId); - await this.checkPermissionCall(async ({userId,projectId})=>{ - await this.service.batchUpdateGroup(ids, groupId, userId,projectId); - }) + await this.checkPermissionCall(async ({ userId, projectId }) => { + await this.service.batchUpdateGroup(ids, groupId, userId, projectId); + }); return this.ok({}); } - - @Post('/batchUpdateTrigger', { description: Constants.per.authOnly, summary: "批量更新流水线触发器" }) - async batchUpdateTrigger(@Body('ids') ids: number[], @Body('trigger') trigger: any) { + @Post("/batchUpdateTrigger", { description: Constants.per.authOnly, summary: "批量更新流水线触发器" }) + async batchUpdateTrigger(@Body("ids") ids: number[], @Body("trigger") trigger: any) { // let { projectId ,userId} = await this.getProjectUserIdWrite() // if(projectId){ // await this.service.batchUpdateTrigger(ids, trigger, null,projectId); @@ -332,54 +325,53 @@ export class PipelineController extends CrudController { // const isAdmin = await this.authService.isAdmin(this.ctx); // userId = isAdmin ? undefined : this.getUserId(); // await this.service.batchUpdateTrigger(ids, trigger, userId); - await this.checkPermissionCall(async ({userId,projectId})=>{ - await this.service.batchUpdateTrigger(ids, trigger, userId,projectId); - }) + await this.checkPermissionCall(async ({ userId, projectId }) => { + await this.service.batchUpdateTrigger(ids, trigger, userId, projectId); + }); return this.ok({}); } - @Post('/batchUpdateNotification', { description: Constants.per.authOnly, summary: "批量更新流水线通知" }) - async batchUpdateNotification(@Body('ids') ids: number[], @Body('notification') notification: any) { + @Post("/batchUpdateNotification", { description: Constants.per.authOnly, summary: "批量更新流水线通知" }) + async batchUpdateNotification(@Body("ids") ids: number[], @Body("notification") notification: any) { // const isAdmin = await this.authService.isAdmin(this.ctx); // const userId = isAdmin ? undefined : this.getUserId(); // await this.service.batchUpdateNotifications(ids, notification, userId); - await this.checkPermissionCall(async ({userId,projectId})=>{ - await this.service.batchUpdateNotifications(ids, notification, userId,projectId); - }) + await this.checkPermissionCall(async ({ userId, projectId }) => { + await this.service.batchUpdateNotifications(ids, notification, userId, projectId); + }); return this.ok({}); } - @Post('/batchUpdateCertApplyOptions', { description: Constants.per.authOnly, summary: "批量更新证书申请任务配置" }) - async batchUpdateCertApplyOptions(@Body('ids') ids: number[], @Body('options') options: any) { - await this.checkPermissionCall(async ({userId,projectId})=>{ - await this.service.batchUpdateCertApplyOptions(ids, options, userId,projectId); - }) + @Post("/batchUpdateCertApplyOptions", { description: Constants.per.authOnly, summary: "批量更新证书申请任务配置" }) + async batchUpdateCertApplyOptions(@Body("ids") ids: number[], @Body("options") options: any) { + await this.checkPermissionCall(async ({ userId, projectId }) => { + await this.service.batchUpdateCertApplyOptions(ids, options, userId, projectId); + }); return this.ok({}); } - @Post('/batchRerun', { description: Constants.per.authOnly, summary: "批量重新运行流水线" }) - async batchRerun(@Body('ids') ids: number[], @Body('force') force: boolean) { - await this.checkPermissionCall(async ({userId,projectId})=>{ - await this.service.batchRerun(ids, force,userId,projectId); - }) + @Post("/batchRerun", { description: Constants.per.authOnly, summary: "批量重新运行流水线" }) + async batchRerun(@Body("ids") ids: number[], @Body("force") force: boolean) { + await this.checkPermissionCall(async ({ userId, projectId }) => { + await this.service.batchRerun(ids, force, userId, projectId); + }); return this.ok({}); } - @Post('/batchTransfer', { description: Constants.per.authOnly, summary: "批量迁移流水线" }) - async batchTransfer(@Body('ids') ids: number[], @Body('toProjectId') toProjectId: number) { - await this.checkPermissionCall(async ({})=>{ + @Post("/batchTransfer", { description: Constants.per.authOnly, summary: "批量迁移流水线" }) + async batchTransfer(@Body("ids") ids: number[], @Body("toProjectId") toProjectId: number) { + await this.checkPermissionCall(async ({}) => { await this.service.batchTransfer(ids, toProjectId); - }) + }); return this.ok({}); } - @Post('/refreshWebhookKey', { description: Constants.per.authOnly, summary: "刷新Webhook密钥" }) - async refreshWebhookKey(@Body('id') id: number) { - await this.checkOwner(this.getService(), id,"write",true); + @Post("/refreshWebhookKey", { description: Constants.per.authOnly, summary: "刷新Webhook密钥" }) + async refreshWebhookKey(@Body("id") id: number) { + await this.checkOwner(this.getService(), id, "write", true); const res = await this.service.refreshWebhookKey(id); return this.ok({ webhookKey: res, }); } - } diff --git a/packages/ui/certd-server/src/controller/user/pipeline/pipeline-group-controller.ts b/packages/ui/certd-server/src/controller/user/pipeline/pipeline-group-controller.ts index 498e3b6b6..624e672a3 100644 --- a/packages/ui/certd-server/src/controller/user/pipeline/pipeline-group-controller.ts +++ b/packages/ui/certd-server/src/controller/user/pipeline/pipeline-group-controller.ts @@ -1,15 +1,15 @@ -import { ALL, Body, Controller, Inject, Post, Provide, Query } from '@midwayjs/core'; -import { Constants, CrudController } from '@certd/lib-server'; -import { AuthService } from '../../../modules/sys/authority/service/auth-service.js'; -import { PipelineGroupService } from '../../../modules/pipeline/service/pipeline-group-service.js'; -import { ApiTags } from '@midwayjs/swagger'; +import { ALL, Body, Controller, Inject, Post, Provide, Query } from "@midwayjs/core"; +import { Constants, CrudController } from "@certd/lib-server"; +import { AuthService } from "../../../modules/sys/authority/service/auth-service.js"; +import { PipelineGroupService } from "../../../modules/pipeline/service/pipeline-group-service.js"; +import { ApiTags } from "@midwayjs/swagger"; /** * 通知 */ @Provide() -@Controller('/api/pi/pipeline/group') -@ApiTags(['pipeline-group']) +@Controller("/api/pi/pipeline/group") +@ApiTags(["pipeline-group"]) export class PipelineGroupController extends CrudController { @Inject() service: PipelineGroupService; @@ -20,14 +20,14 @@ export class PipelineGroupController extends CrudController { - qb.andWhere('user_id = :userId', { userId: userId }); + qb.andWhere("user_id = :userId", { userId: userId }); }; const res = await this.service.page({ query: body.query, @@ -38,45 +38,45 @@ export class PipelineGroupController extends CrudController { @Inject() service: SubDomainService; @@ -22,25 +22,24 @@ export class SubDomainController extends CrudController { return this.service; } - @Post('/parseDomain', { description: Constants.per.authOnly, summary: "解析域名" }) - async parseDomain(@Body("fullDomain") fullDomain:string) { - const {projectId,userId} = await this.getProjectUserIdRead(); + @Post("/parseDomain", { description: Constants.per.authOnly, summary: "解析域名" }) + async parseDomain(@Body("fullDomain") fullDomain: string) { + const { projectId, userId } = await this.getProjectUserIdRead(); const taskService = this.taskServiceBuilder.create({ userId: userId, projectId: projectId }); const subDomainGetter = await taskService.getSubDomainsGetter(); - const domainParser = new DomainParser(subDomainGetter) - const domain = await domainParser.parse(fullDomain) + const domainParser = new DomainParser(subDomainGetter); + const domain = await domainParser.parse(fullDomain); return this.ok(domain); } - - @Post('/page', { description: Constants.per.authOnly, summary: "查询子域名分页列表" }) + @Post("/page", { description: Constants.per.authOnly, summary: "查询子域名分页列表" }) async page(@Body(ALL) body) { - const {userId,projectId} = await this.getProjectUserIdRead(); + const { userId, projectId } = await this.getProjectUserIdRead(); body.query = body.query ?? {}; delete body.query.userId; body.query.projectId = projectId; const buildQuery = qb => { - qb.andWhere('user_id = :userId', { userId: userId }); + qb.andWhere("user_id = :userId", { userId: userId }); }; const res = await this.service.page({ query: body.query, @@ -51,45 +50,45 @@ export class SubDomainController extends CrudController { return this.ok(res); } - @Post('/list', { description: Constants.per.authOnly, summary: "查询子域名列表" }) + @Post("/list", { description: Constants.per.authOnly, summary: "查询子域名列表" }) async list(@Body(ALL) body) { - const {userId,projectId} = await this.getProjectUserIdRead(); + const { userId, projectId } = await this.getProjectUserIdRead(); body.query = body.query ?? {}; body.query.userId = userId; body.query.projectId = projectId; return super.list(body); } - @Post('/add', { description: Constants.per.authOnly, summary: "添加子域名" }) + @Post("/add", { description: Constants.per.authOnly, summary: "添加子域名" }) async add(@Body(ALL) bean) { - const {userId,projectId} = await this.getProjectUserIdRead(); + const { userId, projectId } = await this.getProjectUserIdRead(); bean.userId = userId; bean.projectId = projectId; return super.add(bean); } - @Post('/update', { description: Constants.per.authOnly, summary: "更新子域名" }) + @Post("/update", { description: Constants.per.authOnly, summary: "更新子域名" }) async update(@Body(ALL) bean) { await this.checkOwner(this.getService(), bean.id, "write"); delete bean.userId; delete bean.projectId; return super.update(bean); } - @Post('/info', { description: Constants.per.authOnly, summary: "查询子域名详情" }) - async info(@Query('id') id: number) { + @Post("/info", { description: Constants.per.authOnly, summary: "查询子域名详情" }) + async info(@Query("id") id: number) { await this.checkOwner(this.getService(), id, "read"); return super.info(id); } - @Post('/delete', { description: Constants.per.authOnly, summary: "删除子域名" }) - async delete(@Query('id') id: number) { + @Post("/delete", { description: Constants.per.authOnly, summary: "删除子域名" }) + async delete(@Query("id") id: number) { await this.checkOwner(this.getService(), id, "write"); return super.delete(id); } - @Post('/batchDelete', { description: Constants.per.authOnly, summary: "批量删除子域名" }) - async batchDelete(@Body('ids') ids: number[]) { - const {userId,projectId} = await this.getProjectUserIdWrite(); + @Post("/batchDelete", { description: Constants.per.authOnly, summary: "批量删除子域名" }) + async batchDelete(@Body("ids") ids: number[]) { + const { userId, projectId } = await this.getProjectUserIdWrite(); await this.service.batchDelete(ids, userId, projectId); return this.ok({}); } diff --git a/packages/ui/certd-server/src/controller/user/pipeline/template-controller.ts b/packages/ui/certd-server/src/controller/user/pipeline/template-controller.ts index ac3ed6679..f45a79f87 100644 --- a/packages/ui/certd-server/src/controller/user/pipeline/template-controller.ts +++ b/packages/ui/certd-server/src/controller/user/pipeline/template-controller.ts @@ -1,15 +1,15 @@ -import {ALL, Body, Controller, Inject, Post, Provide, Query} from '@midwayjs/core'; -import {Constants, CrudController} from '@certd/lib-server'; -import { TemplateService } from '../../../modules/pipeline/service/template-service.js'; -import { checkPlus } from '@certd/plus-core'; -import { ApiTags } from '@midwayjs/swagger'; +import { ALL, Body, Controller, Inject, Post, Provide, Query } from "@midwayjs/core"; +import { Constants, CrudController } from "@certd/lib-server"; +import { TemplateService } from "../../../modules/pipeline/service/template-service.js"; +import { checkPlus } from "@certd/plus-core"; +import { ApiTags } from "@midwayjs/swagger"; /** * 流水线模版 */ @Provide() -@Controller('/api/pi/template') -@ApiTags(['pipeline-template']) +@Controller("/api/pi/template") +@ApiTags(["pipeline-template"]) export class TemplateController extends CrudController { @Inject() service: TemplateService; @@ -18,17 +18,15 @@ export class TemplateController extends CrudController { return this.service; } - - @Post('/page', { description: Constants.per.authOnly, summary: "查询流水线模版分页列表" }) + @Post("/page", { description: Constants.per.authOnly, summary: "查询流水线模版分页列表" }) async page(@Body(ALL) body) { - body.query = body.query ?? {}; delete body.query.userId; - const { projectId, userId } = await this.getProjectUserIdRead() - body.query.projectId = projectId - + const { projectId, userId } = await this.getProjectUserIdRead(); + body.query.projectId = projectId; + const buildQuery = qb => { - qb.andWhere('user_id = :userId', { userId: userId }); + qb.andWhere("user_id = :userId", { userId: userId }); }; const res = await this.service.page({ query: body.query, @@ -39,63 +37,63 @@ export class TemplateController extends CrudController { return this.ok(res); } - @Post('/list', { description: Constants.per.authOnly, summary: "查询流水线模版列表" }) + @Post("/list", { description: Constants.per.authOnly, summary: "查询流水线模版列表" }) async list(@Body(ALL) body) { body.query = body.query ?? {}; - const { projectId, userId } = await this.getProjectUserIdRead() - body.query.projectId = projectId - body.query.userId = userId + const { projectId, userId } = await this.getProjectUserIdRead(); + body.query.projectId = projectId; + body.query.userId = userId; return super.list(body); } - @Post('/add', { description: Constants.per.authOnly, summary: "添加流水线模版" }) + @Post("/add", { description: Constants.per.authOnly, summary: "添加流水线模版" }) async add(@Body(ALL) bean) { - const { projectId, userId } = await this.getProjectUserIdRead() + const { projectId, userId } = await this.getProjectUserIdRead(); bean.userId = userId; - bean.projectId = projectId - checkPlus() + bean.projectId = projectId; + checkPlus(); return super.add(bean); } - @Post('/update', { description: Constants.per.authOnly, summary: "更新流水线模版" }) + @Post("/update", { description: Constants.per.authOnly, summary: "更新流水线模版" }) async update(@Body(ALL) bean) { await this.checkOwner(this.service, bean.id, "write"); delete bean.userId; delete bean.projectId; return super.update(bean); } - @Post('/info', { description: Constants.per.authOnly, summary: "查询流水线模版详情" }) - async info(@Query('id') id: number) { - await this.checkOwner(this.service, id, "read"); + @Post("/info", { description: Constants.per.authOnly, summary: "查询流水线模版详情" }) + async info(@Query("id") id: number) { + await this.checkOwner(this.service, id, "read"); return super.info(id); } - @Post('/delete', { description: Constants.per.authOnly, summary: "删除流水线模版" }) - async delete(@Query('id') id: number) { - const { userId ,projectId } = await this.getProjectUserIdWrite() - await this.service.batchDelete([id], userId,projectId); + @Post("/delete", { description: Constants.per.authOnly, summary: "删除流水线模版" }) + async delete(@Query("id") id: number) { + const { userId, projectId } = await this.getProjectUserIdWrite(); + await this.service.batchDelete([id], userId, projectId); return this.ok({}); } - @Post('/batchDelete', { description: Constants.per.authOnly, summary: "批量删除流水线模版" }) - async batchDelete(@Body('ids') ids: number[]) { - const { userId ,projectId } = await this.getProjectUserIdWrite() - await this.service.batchDelete(ids, userId,projectId); + @Post("/batchDelete", { description: Constants.per.authOnly, summary: "批量删除流水线模版" }) + async batchDelete(@Body("ids") ids: number[]) { + const { userId, projectId } = await this.getProjectUserIdWrite(); + await this.service.batchDelete(ids, userId, projectId); return this.ok({}); } - @Post('/detail', { description: Constants.per.authOnly, summary: "查询流水线模版详情" }) - async detail(@Query('id') id: number) { - const { userId ,projectId } = await this.getProjectUserIdRead() - const detail = await this.service.detail(id, userId,projectId); + @Post("/detail", { description: Constants.per.authOnly, summary: "查询流水线模版详情" }) + async detail(@Query("id") id: number) { + const { userId, projectId } = await this.getProjectUserIdRead(); + const detail = await this.service.detail(id, userId, projectId); return this.ok(detail); } - @Post('/createPipelineByTemplate', { description: Constants.per.authOnly, summary: "根据模版创建流水线" }) + @Post("/createPipelineByTemplate", { description: Constants.per.authOnly, summary: "根据模版创建流水线" }) async createPipelineByTemplate(@Body(ALL) body: any) { - const { userId ,projectId } = await this.getProjectUserIdWrite() + const { userId, projectId } = await this.getProjectUserIdWrite(); body.userId = userId; - body.projectId = projectId - checkPlus() + body.projectId = projectId; + checkPlus(); const res = await this.service.createPipelineByTemplate(body); return this.ok(res); } diff --git a/packages/ui/certd-server/src/filter/default.filter.ts b/packages/ui/certd-server/src/filter/default.filter.ts index 24c8af200..ab5ba1a12 100644 --- a/packages/ui/certd-server/src/filter/default.filter.ts +++ b/packages/ui/certd-server/src/filter/default.filter.ts @@ -1,5 +1,5 @@ -import { Catch } from '@midwayjs/core'; -import { Context } from '@midwayjs/koa'; +import { Catch } from "@midwayjs/core"; +import { Context } from "@midwayjs/koa"; @Catch() export class DefaultErrorFilter { diff --git a/packages/ui/certd-server/src/filter/notfound.filter.ts b/packages/ui/certd-server/src/filter/notfound.filter.ts index e3b7fa924..0b1c28235 100644 --- a/packages/ui/certd-server/src/filter/notfound.filter.ts +++ b/packages/ui/certd-server/src/filter/notfound.filter.ts @@ -1,10 +1,10 @@ -import { Catch, httpError, MidwayHttpError } from '@midwayjs/core'; -import { Context } from '@midwayjs/koa'; +import { Catch, httpError, MidwayHttpError } from "@midwayjs/core"; +import { Context } from "@midwayjs/koa"; @Catch(httpError.NotFoundError) export class NotFoundFilter { async catch(err: MidwayHttpError, ctx: Context) { // 404 错误会到这里 - ctx.redirect('/404.html'); + ctx.redirect("/404.html"); } } diff --git a/packages/ui/certd-server/src/middleware/authority.ts b/packages/ui/certd-server/src/middleware/authority.ts index 78d189487..5b14888f5 100644 --- a/packages/ui/certd-server/src/middleware/authority.ts +++ b/packages/ui/certd-server/src/middleware/authority.ts @@ -1,11 +1,11 @@ -import { Init, Inject, MidwayWebRouterService, Provide, Scope, ScopeEnum } from '@midwayjs/core'; -import { IMidwayKoaContext, IWebMiddleware, NextFunction } from '@midwayjs/koa'; -import jwt from 'jsonwebtoken'; -import { Constants, SysPrivateSettings, SysSettingsService } from '@certd/lib-server'; -import { logger } from '@certd/basic'; -import { AuthService } from '../modules/sys/authority/service/auth-service.js'; -import { OpenKeyService } from '../modules/open/service/open-key-service.js'; -import { RoleService } from '../modules/sys/authority/service/role-service.js'; +import { Init, Inject, MidwayWebRouterService, Provide, Scope, ScopeEnum } from "@midwayjs/core"; +import { IMidwayKoaContext, IWebMiddleware, NextFunction } from "@midwayjs/koa"; +import jwt from "jsonwebtoken"; +import { Constants, SysPrivateSettings, SysSettingsService } from "@certd/lib-server"; +import { logger } from "@certd/basic"; +import { AuthService } from "../modules/sys/authority/service/auth-service.js"; +import { OpenKeyService } from "../modules/open/service/open-key-service.js"; +import { RoleService } from "../modules/sys/authority/service/role-service.js"; /** * 权限校验 @@ -40,11 +40,11 @@ export class AuthorityMiddleware implements IWebMiddleware { await next(); return; } - let permission = routeInfo.description || ''; - permission = permission.trim().split(' ')[0]; - if (permission == null || permission === '') { + let permission = routeInfo.description || ""; + permission = permission.trim().split(" ")[0]; + if (permission == null || permission === "") { ctx.status = 500; - ctx.body = Constants.res.serverError('该路由未配置权限控制:' + ctx.path); + ctx.body = Constants.res.serverError("该路由未配置权限控制:" + ctx.path); return; } if (permission === Constants.per.guest) { @@ -58,7 +58,7 @@ export class AuthorityMiddleware implements IWebMiddleware { try { ctx.user = jwt.verify(token, this.secret); } catch (err) { - logger.error('token verify error: ', err); + logger.error("token verify error: ", err); return this.notAuth(ctx); } } else { @@ -74,8 +74,8 @@ export class AuthorityMiddleware implements IWebMiddleware { if (permission === Constants.per.open) { await next(); return; - } else if (openKey.scope === 'open') { - return this.notAuth(ctx, 'open key scope error,need user scope'); + } else if (openKey.scope === "open") { + return this.notAuth(ctx, "open key scope error,need user scope"); } } @@ -90,7 +90,7 @@ export class AuthorityMiddleware implements IWebMiddleware { const pass = await this.authService.checkPermission(ctx, permission); if (!pass) { - logger.info('not permission: ', ctx.req.url); + logger.info("not permission: ", ctx.req.url); ctx.status = 200; ctx.body = Constants.res.permission; return; @@ -104,49 +104,49 @@ export class AuthorityMiddleware implements IWebMiddleware { ctx.body = Constants.res.auth; if (message) { // @ts-ignore - ctx.body.message =message; + ctx.body.message = message; } return; } private getTokenFromRequest(ctx: IMidwayKoaContext) { - let token = ctx.get('Authorization') || ''; - token = token.replace('Bearer ', '').trim(); + let token = ctx.get("Authorization") || ""; + token = token.replace("Bearer ", "").trim(); if (token) { return token; } const cookie = ctx.headers.cookie; if (cookie) { - const items = cookie.split(';'); + const items = cookie.split(";"); for (const item of items) { - if (!item || !item.trim()) { + if (!item || !item.trim()) { continue; } - const [key, value] = item.split('='); - if (key.trim() === 'certd_token') { + const [key, value] = item.split("="); + if (key.trim() === "certd_token") { return value.trim(); } } } - return (ctx.query.token as string) || ''; + return (ctx.query.token as string) || ""; } async doOpenHandler(ctx: IMidwayKoaContext) { //开放接口 - const openKey = ctx.get('x-certd-token') || ''; + const openKey = ctx.get("x-certd-token") || ""; if (!openKey) { return null; } //校验 openKey const openKeyRes = await this.openKeyService.verifyOpenKey(openKey); - let roles = [1] + let roles = [1]; if (!openKeyRes.projectId || openKeyRes.projectId <= 0) { roles = await this.roleService.getRoleIdsByUserId(openKeyRes.userId); } - ctx.user = { id: openKeyRes.userId, roles ,projectId:openKeyRes.projectId}; + ctx.user = { id: openKeyRes.userId, roles, projectId: openKeyRes.projectId }; ctx.openKey = openKeyRes; return openKeyRes; } diff --git a/packages/ui/certd-server/src/middleware/global-exception.ts b/packages/ui/certd-server/src/middleware/global-exception.ts index 277a6ed36..8bb4a24f8 100644 --- a/packages/ui/certd-server/src/middleware/global-exception.ts +++ b/packages/ui/certd-server/src/middleware/global-exception.ts @@ -1,6 +1,6 @@ -import { Provide } from '@midwayjs/core'; -import { IMidwayKoaContext, IWebMiddleware, NextFunction } from '@midwayjs/koa'; -import { logger } from '@certd/basic'; +import { Provide } from "@midwayjs/core"; +import { IMidwayKoaContext, IWebMiddleware, NextFunction } from "@midwayjs/koa"; +import { logger } from "@certd/basic"; import { Result, TextException } from "@certd/lib-server"; @Provide() @@ -9,20 +9,20 @@ export class GlobalExceptionMiddleware implements IWebMiddleware { return async (ctx: IMidwayKoaContext, next: NextFunction) => { const { url } = ctx; const startTime = Date.now(); - logger.info('请求开始:', url); + logger.info("请求开始:", url); try { await next(); - logger.info('请求完成:', url, Date.now() - startTime + 'ms'); + logger.info("请求完成:", url, Date.now() - startTime + "ms"); } catch (err) { - if(err instanceof TextException){ - delete err.stack + if (err instanceof TextException) { + delete err.stack; } - logger.error('请求异常:', url, Date.now() - startTime + 'ms', err); + logger.error("请求异常:", url, Date.now() - startTime + "ms", err); ctx.status = 200; - if (err.code == null || typeof err.code !== 'number') { + if (err.code == null || typeof err.code !== "number") { err.code = 1; } - ctx.body = Result.error(err.code, err.message,err.data); + ctx.body = Result.error(err.code, err.message, err.data); } }; } diff --git a/packages/ui/certd-server/src/middleware/hidden.ts b/packages/ui/certd-server/src/middleware/hidden.ts index 7e135f7c4..f05837d7f 100644 --- a/packages/ui/certd-server/src/middleware/hidden.ts +++ b/packages/ui/certd-server/src/middleware/hidden.ts @@ -1,8 +1,7 @@ -import {Inject, Provide} from '@midwayjs/core'; -import {IMidwayKoaContext, IWebMiddleware, NextFunction} from '@midwayjs/koa'; -import {hiddenStatus, SafeService} from "../modules/sys/settings/safe-service.js"; -import {SiteOffException} from "@certd/lib-server"; - +import { Inject, Provide } from "@midwayjs/core"; +import { IMidwayKoaContext, IWebMiddleware, NextFunction } from "@midwayjs/koa"; +import { hiddenStatus, SafeService } from "../modules/sys/settings/safe-service.js"; +import { SiteOffException } from "@certd/lib-server"; /** * 隐藏环境 @@ -14,41 +13,40 @@ export class HiddenMiddleware implements IWebMiddleware { resolve() { return async (ctx: IMidwayKoaContext, next: NextFunction) => { - async function pass() { - hiddenStatus.updateRequestTime() + hiddenStatus.updateRequestTime(); await next(); } const hiddenSetting = await this.hiddenService.getHiddenSetting(); if (!hiddenSetting || !hiddenSetting?.enabled) { //未开启站点隐藏,直接通过 - return await pass() + return await pass(); } const req = ctx.request; - if (hiddenSetting.hiddenOpenApi === false && req.url.startsWith(`/api/v1/`) ) { + if (hiddenSetting.hiddenOpenApi === false && req.url.startsWith(`/api/v1/`)) { //不隐藏开放接口 await next(); - return + return; } //判断当前是否是隐藏状态 if (!hiddenStatus.isHidden) { - return await pass() + return await pass(); } //判断是否有解锁文件,如果有就返回true并删除文件 if (hiddenStatus.hasUnHiddenFile()) { //临时修改为未隐藏 hiddenStatus.isHidden = false; - return await pass() + return await pass(); } if (req.url === `/api/unhidden/${hiddenSetting.openPath}`) { return await pass(); } - throw new SiteOffException('此站点已关闭'); - } + throw new SiteOffException("此站点已关闭"); + }; } } diff --git a/packages/ui/certd-server/src/middleware/preview.ts b/packages/ui/certd-server/src/middleware/preview.ts index 847ba9005..1ec5d790c 100644 --- a/packages/ui/certd-server/src/middleware/preview.ts +++ b/packages/ui/certd-server/src/middleware/preview.ts @@ -1,13 +1,13 @@ -import { Config, Provide } from '@midwayjs/core'; -import { IMidwayKoaContext, NextFunction, IWebMiddleware } from '@midwayjs/koa'; -import { PreviewException } from '@certd/lib-server'; +import { Config, Provide } from "@midwayjs/core"; +import { IMidwayKoaContext, NextFunction, IWebMiddleware } from "@midwayjs/koa"; +import { PreviewException } from "@certd/lib-server"; /** * 预览模式 */ @Provide() export class PreviewMiddleware implements IWebMiddleware { - @Config('preview.enabled') + @Config("preview.enabled") private preview: boolean; resolve() { @@ -24,16 +24,16 @@ export class PreviewMiddleware implements IWebMiddleware { if (id == null && roleId != null) { id = roleId; } - if (id != null && typeof id === 'string') { + if (id != null && typeof id === "string") { id = parseInt(id); } - if (url.indexOf('?') !== -1) { - url = url.substring(0, url.indexOf('?')); + if (url.indexOf("?") !== -1) { + url = url.substring(0, url.indexOf("?")); } - const isModify = url.endsWith('update') || url.endsWith('delete') || url.endsWith('authz'); + const isModify = url.endsWith("update") || url.endsWith("delete") || url.endsWith("authz"); const isPreviewId = id < 1000; if (this.preview && isModify && isPreviewId) { - throw new PreviewException('对不起,预览环境不允许修改此数据,如需体验请添加新数据'); + throw new PreviewException("对不起,预览环境不允许修改此数据,如需体验请添加新数据"); } await next(); return; diff --git a/packages/ui/certd-server/src/middleware/reset-passwd/middleware.ts b/packages/ui/certd-server/src/middleware/reset-passwd/middleware.ts index 4da108996..f53c29cc5 100644 --- a/packages/ui/certd-server/src/middleware/reset-passwd/middleware.ts +++ b/packages/ui/certd-server/src/middleware/reset-passwd/middleware.ts @@ -1,8 +1,8 @@ import { CommonException, SysSettingsService } from "@certd/lib-server"; -import { Autoload, Config, Init, Inject, Provide, Scope, ScopeEnum } from '@midwayjs/core'; -import { IMidwayKoaContext, IWebMiddleware, NextFunction } from '@midwayjs/koa'; +import { Autoload, Config, Init, Inject, Provide, Scope, ScopeEnum } from "@midwayjs/core"; +import { IMidwayKoaContext, IWebMiddleware, NextFunction } from "@midwayjs/koa"; import { UserSettingsService } from "../../modules/mine/service/user-settings-service.js"; -import { UserService } from '../../modules/sys/authority/service/user-service.js'; +import { UserService } from "../../modules/sys/authority/service/user-service.js"; /** * 重置密码模式 @@ -19,19 +19,17 @@ export class ResetPasswdMiddleware implements IWebMiddleware { @Inject() sysSettingsService: SysSettingsService; - @Config('system.resetAdminPasswd') + @Config("system.resetAdminPasswd") private resetAdminPasswd: boolean; resolve() { return async (ctx: IMidwayKoaContext, next: NextFunction) => { if (this.resetAdminPasswd === true) { - throw new CommonException('1号管理员密码已修改为123456,当前为重置密码模式,无法响应请求,请关闭重置密码模式恢复正常服务'); + throw new CommonException("1号管理员密码已修改为123456,当前为重置密码模式,无法响应请求,请关闭重置密码模式恢复正常服务"); } await next(); }; } @Init() - async init() { - - } + async init() {} } diff --git a/packages/ui/certd-server/src/modules/auto/auto-a-register.ts b/packages/ui/certd-server/src/modules/auto/auto-a-register.ts index 2df4846ac..315822905 100644 --- a/packages/ui/certd-server/src/modules/auto/auto-a-register.ts +++ b/packages/ui/certd-server/src/modules/auto/auto-a-register.ts @@ -9,7 +9,8 @@ import { AutoPrint } from "./auto-print.js"; @Autoload() @Scope(ScopeEnum.Request, { allowDowngrade: true }) -export class AutoARegister { //这个A是必须,让他排在第一个 进行init,否则会被其他init模块抢先注册导致报错 +export class AutoARegister { + //这个A是必须,让他排在第一个 进行init,否则会被其他init模块抢先注册导致报错 @Inject() autoInitSite: AutoInitSite; diff --git a/packages/ui/certd-server/src/modules/auto/auto-cron.ts b/packages/ui/certd-server/src/modules/auto/auto-cron.ts index 879479b7b..a037b2538 100644 --- a/packages/ui/certd-server/src/modules/auto/auto-cron.ts +++ b/packages/ui/certd-server/src/modules/auto/auto-cron.ts @@ -1,18 +1,18 @@ -import { logger } from '@certd/basic'; -import { SysSettingsService, SysSiteInfo } from '@certd/lib-server'; +import { logger } from "@certd/basic"; +import { SysSettingsService, SysSiteInfo } from "@certd/lib-server"; import { getPlusInfo, isPlus } from "@certd/plus-core"; -import { Config, Inject, Provide, Scope, ScopeEnum } from '@midwayjs/core'; +import { Config, Inject, Provide, Scope, ScopeEnum } from "@midwayjs/core"; import dayjs from "dayjs"; import { Between } from "typeorm"; -import { DomainService } from '../cert/service/domain-service.js'; -import { Cron } from '../cron/cron.js'; +import { DomainService } from "../cert/service/domain-service.js"; +import { Cron } from "../cron/cron.js"; import { UserSiteMonitorSetting } from "../mine/service/models.js"; import { UserSettingsService } from "../mine/service/user-settings-service.js"; -import { SiteInfoService } from '../monitor/index.js'; +import { SiteInfoService } from "../monitor/index.js"; import { NotificationService } from "../pipeline/service/notification-service.js"; -import { PipelineService } from '../pipeline/service/pipeline-service.js'; +import { PipelineService } from "../pipeline/service/pipeline-service.js"; import { UserService } from "../sys/authority/service/user-service.js"; -import { ProjectService } from '../sys/enterprise/service/project-service.js'; +import { ProjectService } from "../sys/enterprise/service/project-service.js"; @Provide() @Scope(ScopeEnum.Request, { allowDowngrade: true }) @@ -20,13 +20,13 @@ export class AutoCron { @Inject() pipelineService: PipelineService; - @Config('cron.onlyAdminUser') + @Config("cron.onlyAdminUser") private onlyAdminUser: boolean; - @Config('cron.immediateTriggerOnce') + @Config("cron.immediateTriggerOnce") private immediateTriggerOnce = false; - @Config('cron.immediateTriggerSiteMonitor') + @Config("cron.immediateTriggerSiteMonitor") private immediateTriggerSiteMonitor = false; @Inject() @@ -51,12 +51,10 @@ export class AutoCron { @Inject() projectService: ProjectService; - - async init() { - logger.info('加载定时trigger开始'); + logger.info("加载定时trigger开始"); await this.pipelineService.onStartup(this.immediateTriggerOnce, this.onlyAdminUser); - logger.info('加载定时trigger完成'); + logger.info("加载定时trigger完成"); // // const meta = getClassMetadata(CLASS_KEY, this.echoPlugin); // console.log('meta', meta); @@ -64,183 +62,180 @@ export class AutoCron { // console.log('metas', metas); await this.registerSiteMonitorCron(); - await this.registerPlusExpireCheckCron(); await this.registerUserExpireCheckCron(); await this.registerDomainExpireCheckCron(); - } async registerSiteMonitorCron() { //先注册公共job - logger.info(`注册公共站点证书检查定时任务`) - const randomMinute = Math.floor(Math.random() * 60) + logger.info(`注册公共站点证书检查定时任务`); + const randomMinute = Math.floor(Math.random() * 60); this.cron.register({ - name: 'siteMonitor', + name: "siteMonitor", cron: `0 ${randomMinute} 0 * * *`, - job:async ()=>{ - logger.info(`开始公共站点证书检查任务`) - await this.siteInfoService.triggerCommonJob() - logger.info(`公共站点证书检查任务完成`) + job: async () => { + logger.info(`开始公共站点证书检查任务`); + await this.siteInfoService.triggerCommonJob(); + logger.info(`公共站点证书检查任务完成`); }, }); - logger.info(`注册公共站点证书检查定时任务完成`) - - + logger.info(`注册公共站点证书检查定时任务完成`); //注册用户独立的检查时间 - logger.info(`注册用户独立站点证书检查定时任务`) + logger.info(`注册用户独立站点证书检查定时任务`); const monitorSettingList = await this.userSettingsService.list({ - query:{ + query: { key: UserSiteMonitorSetting.__key__, - } - }) + }, + }); for (const item of monitorSettingList) { - const setting = item.setting ? JSON.parse(item.setting):{} - if(!setting?.cron){ - continue + const setting = item.setting ? JSON.parse(item.setting) : {}; + if (!setting?.cron) { + continue; } - await this.siteInfoService.registerSiteMonitorJob(item.userId,item.projectId) + await this.siteInfoService.registerSiteMonitorJob(item.userId, item.projectId); } - logger.info(`注册用户独立站点证书检查定时任务完成`) + logger.info(`注册用户独立站点证书检查定时任务完成`); if (this.immediateTriggerSiteMonitor) { - logger.info(`立即触发一次公共站点证书检查任务`) - await this.siteInfoService.triggerCommonJob() + logger.info(`立即触发一次公共站点证书检查任务`); + await this.siteInfoService.triggerCommonJob(); } } - registerPlusExpireCheckCron(){ + registerPlusExpireCheckCron() { // 添加plus即将到期检查任务 this.cron.register({ - name: 'plus-expire-check', + name: "plus-expire-check", cron: `0 10 9 * * *`, // 一天只能检查一次,否则会重复发送通知 job: async () => { - const plusInfo = getPlusInfo() - if (!plusInfo.originVipType || plusInfo.originVipType==="free" ) { - return + const plusInfo = getPlusInfo(); + if (!plusInfo.originVipType || plusInfo.originVipType === "free") { + return; } - let label ="专业版" - if( plusInfo.originVipType === 'comm'){ - label = "商业版" + let label = "专业版"; + if (plusInfo.originVipType === "comm") { + label = "商业版"; } - const siteInfo = await this.sysSettingsService.getSetting(SysSiteInfo) + const siteInfo = await this.sysSettingsService.getSetting(SysSiteInfo); - const appTitle = siteInfo.title || "certd" - const expiresDate = dayjs(plusInfo.expireTime).format("YYYY-MM-DD") + const appTitle = siteInfo.title || "certd"; + const expiresDate = dayjs(plusInfo.expireTime).format("YYYY-MM-DD"); // plusInfo.expireTime= dayjs("2025-06-10").valueOf() - let expiresDays =Math.floor((plusInfo.expireTime - new Date().getTime())/ 1000 / 60 / 60 / 24) - let title = "" - let content ="" - if(expiresDays === 20 ||expiresDays === 10 || expiresDays === 3 || expiresDays === 1 || expiresDays === 0){ - title = `vip(${label})即将到期` - content = `您的${appTitle} vip (${label})剩余${expiresDays}天(${expiresDate})到期,请及时续期,以免影响业务` - }else if (expiresDays === -1 || expiresDays === -3 || expiresDays === -7) { - title = `vip(${label})已过期` - content = `您的${appTitle} vip (${label})已过期${Math.abs(expiresDays)}天(${expiresDate}),请尽快续期,以免影响业务` + const expiresDays = Math.floor((plusInfo.expireTime - new Date().getTime()) / 1000 / 60 / 60 / 24); + let title = ""; + let content = ""; + if (expiresDays === 20 || expiresDays === 10 || expiresDays === 3 || expiresDays === 1 || expiresDays === 0) { + title = `vip(${label})即将到期`; + content = `您的${appTitle} vip (${label})剩余${expiresDays}天(${expiresDate})到期,请及时续期,以免影响业务`; + } else if (expiresDays === -1 || expiresDays === -3 || expiresDays === -7) { + title = `vip(${label})已过期`; + content = `您的${appTitle} vip (${label})已过期${Math.abs(expiresDays)}天(${expiresDate}),请尽快续期,以免影响业务`; } - if(title){ - logger.warn(title) - logger.warn(content) + if (title) { + logger.warn(title); + logger.warn(content); const url = await this.notificationService.getBindUrl(""); - const adminUsers = await this.userService.getAdmins() + const adminUsers = await this.userService.getAdmins(); for (const adminUser of adminUsers) { - logger.info(`发送vip到期通知给管理员:${adminUser.username}`) - await this.notificationService.send({ - useDefault: true, - logger: logger, - body:{ - title, - content, - errorMessage:title, - url, - notificationType: "vipExpireRemind", - } - },adminUser.id) + logger.info(`发送vip到期通知给管理员:${adminUser.username}`); + await this.notificationService.send( + { + useDefault: true, + logger: logger, + body: { + title, + content, + errorMessage: title, + url, + notificationType: "vipExpireRemind", + }, + }, + adminUser.id + ); } - } - - } - }) + }, + }); } - registerUserExpireCheckCron() { // 添加plus即将到期检查任务 this.cron.register({ - name: 'user-expire-check', + name: "user-expire-check", cron: `0 20 9 * * *`, // 一天只能检查一次,否则会重复发送通知 job: async () => { - const getExpiresDaysUsers = async (days: number) => { - const targetDate = dayjs().add(days, 'day') - const startTime = targetDate.startOf('day').valueOf() - const endTime = targetDate.endOf('day').valueOf() + const targetDate = dayjs().add(days, "day"); + const startTime = targetDate.startOf("day").valueOf(); + const endTime = targetDate.endOf("day").valueOf(); return await this.userService.find({ where: { validTime: Between(startTime, endTime), - status: 1 - } - }) - } + status: 1, + }, + }); + }; const notifyExpiresDaysUsers = async (days: number) => { - const list = await getExpiresDaysUsers(days) + const list = await getExpiresDaysUsers(days); if (list.length === 0) { - return + return; } - let title = `账号即将到期` - let content = `您的账号剩余${days}天到期,请及时续期,以免影响业务` + let title = `账号即将到期`; + let content = `您的账号剩余${days}天到期,请及时续期,以免影响业务`; if (days <= 0) { - title = `账号已过期` - content = `您的账号已过期${Math.abs(days)}天,请尽快续期,以免影响业务` + title = `账号已过期`; + content = `您的账号已过期${Math.abs(days)}天,请尽快续期,以免影响业务`; } const url = await this.notificationService.getBindUrl(""); for (const user of list) { - logger.info(`发送到期通知给用户:${user.username}`) - await this.notificationService.send({ - useDefault: true, - logger: logger, - body: { - title, - content, - errorMessage: title, - url, - notificationType: "userExpireRemind", - } - }, user.id) + logger.info(`发送到期通知给用户:${user.username}`); + await this.notificationService.send( + { + useDefault: true, + logger: logger, + body: { + title, + content, + errorMessage: title, + url, + notificationType: "userExpireRemind", + }, + }, + user.id + ); } - } + }; - await notifyExpiresDaysUsers(7) - await notifyExpiresDaysUsers(3) - await notifyExpiresDaysUsers(1) - await notifyExpiresDaysUsers(0) - await notifyExpiresDaysUsers(-1) - await notifyExpiresDaysUsers(-3) - } - }) + await notifyExpiresDaysUsers(7); + await notifyExpiresDaysUsers(3); + await notifyExpiresDaysUsers(1); + await notifyExpiresDaysUsers(0); + await notifyExpiresDaysUsers(-1); + await notifyExpiresDaysUsers(-3); + }, + }); } - - registerDomainExpireCheckCron(){ - if (!isPlus()){ - return + registerDomainExpireCheckCron() { + if (!isPlus()) { + return; } // 添加域名即将到期同步任务 - const randomWeek = Math.floor(Math.random() * 7) + 1 - const randomHour = Math.floor(Math.random() * 24) - const randomMinute = Math.floor(Math.random() * 60) - logger.info(`注册域名注册过期时间同步任务,每周${randomWeek} ${randomHour}:${randomMinute}检查一次`) + const randomWeek = Math.floor(Math.random() * 7) + 1; + const randomHour = Math.floor(Math.random() * 24); + const randomMinute = Math.floor(Math.random() * 60); + logger.info(`注册域名注册过期时间同步任务,每周${randomWeek} ${randomHour}:${randomMinute}检查一次`); this.cron.register({ - name: 'domain-expire-check', + name: "domain-expire-check", cron: `0 ${randomMinute} ${randomHour} ? * ${randomWeek}`, // 每周随机一天检查一次 job: async () => { - await this.domainService.startSyncExpirationTask({}) - } - }) + await this.domainService.startSyncExpirationTask({}); + }, + }); } } diff --git a/packages/ui/certd-server/src/modules/auto/auto-init-site.ts b/packages/ui/certd-server/src/modules/auto/auto-init-site.ts index 88d4c43d6..ef6410ba6 100644 --- a/packages/ui/certd-server/src/modules/auto/auto-init-site.ts +++ b/packages/ui/certd-server/src/modules/auto/auto-init-site.ts @@ -1,9 +1,9 @@ -import { logger } from '@certd/basic'; -import { EncryptService, PlusService, SysInstallInfo, SysPrivateSettings, SysSettingsService } from '@certd/lib-server'; -import { Config, Inject, Provide, Scope, ScopeEnum } from '@midwayjs/core'; -import crypto from 'crypto'; -import { nanoid } from 'nanoid'; -import { UserService } from '../sys/authority/service/user-service.js'; +import { logger } from "@certd/basic"; +import { EncryptService, PlusService, SysInstallInfo, SysPrivateSettings, SysSettingsService } from "@certd/lib-server"; +import { Config, Inject, Provide, Scope, ScopeEnum } from "@midwayjs/core"; +import crypto from "crypto"; +import { nanoid } from "nanoid"; +import { UserService } from "../sys/authority/service/user-service.js"; import { SafeService } from "../sys/settings/safe-service.js"; @Provide() @@ -12,7 +12,7 @@ export class AutoInitSite { @Inject() userService: UserService; - @Config('typeorm.dataSource.default.type') + @Config("typeorm.dataSource.default.type") dbType: string; @Inject() @@ -24,10 +24,9 @@ export class AutoInitSite { @Inject() encryptService: EncryptService; - async init() { - logger.info('初始化站点开始'); + logger.info("初始化站点开始"); await this.startOptimizeDb(); //安装信息 const installInfo: SysInstallInfo = await this.sysSettingsService.getSetting(SysInstallInfo); @@ -45,7 +44,7 @@ export class AutoInitSite { if (!privateInfo.encryptSecret) { const secretKey = crypto.randomBytes(32); - privateInfo.encryptSecret = secretKey.toString('base64'); + privateInfo.encryptSecret = secretKey.toString("base64"); await this.sysSettingsService.saveSetting(privateInfo); } @@ -61,32 +60,32 @@ export class AutoInitSite { try { await this.plusService.verify(); } catch (e) { - logger.error('授权许可验证失败', e); + logger.error("授权许可验证失败", e); } - + //加载设置 await this.sysSettingsService.reloadSettings(); //加载站点隐藏配置 - await this.safeService.reloadHiddenStatus(true) - logger.info('初始化站点完成'); + await this.safeService.reloadHiddenStatus(true); + logger.info("初始化站点完成"); } async startOptimizeDb() { //优化数据库 //检查当前数据库类型为sqlite - if (this.dbType === 'better-sqlite3') { - const res = await this.userService.repository.query('PRAGMA auto_vacuum;'); + if (this.dbType === "better-sqlite3") { + const res = await this.userService.repository.query("PRAGMA auto_vacuum;"); if (!(res && res.length > 0 && res[0].auto_vacuum > 0)) { //未开启自动优化 - await this.userService.repository.query('PRAGMA auto_vacuum = INCREMENTAL;'); - logger.info('sqlite数据库自动优化已开启'); + await this.userService.repository.query("PRAGMA auto_vacuum = INCREMENTAL;"); + logger.info("sqlite数据库自动优化已开启"); } const optimizeDb = async () => { - logger.info('sqlite数据库空间优化开始'); - await this.userService.repository.query('VACUUM'); - logger.info('sqlite数据库空间优化完成'); + logger.info("sqlite数据库空间优化开始"); + await this.userService.repository.query("VACUUM"); + logger.info("sqlite数据库空间优化完成"); }; await optimizeDb(); setInterval(optimizeDb, 1000 * 60 * 60 * 24); diff --git a/packages/ui/certd-server/src/modules/auto/auto-load-plugins.ts b/packages/ui/certd-server/src/modules/auto/auto-load-plugins.ts index 2526c622c..7ea7b0bb1 100644 --- a/packages/ui/certd-server/src/modules/auto/auto-load-plugins.ts +++ b/packages/ui/certd-server/src/modules/auto/auto-load-plugins.ts @@ -9,28 +9,26 @@ export class AutoLoadPlugins { @Inject() pluginService: PluginService; - async init() { logger.info(`加载插件开始,加载模式:${process.env.certd_plugin_loadmode}`); if (process.env.certd_plugin_loadmode === "metadata") { - await this.pluginService.registerFromLocal("./metadata") - }else{ + await this.pluginService.registerFromLocal("./metadata"); + } else { // await import("../../plugins/index.js") const fs = await import("fs"); const list = fs.readdirSync("./dist/plugins"); console.log("list", list); for (const file of list) { - if (!file.includes(".")){ + if (!file.includes(".")) { logger.info(`加载插件文件:${file}`); await import(`../../plugins/${file}/index.js`); } } } // await import("../../plugins/index.js") - await this.pluginService.registerFromDb() + await this.pluginService.registerFromDb(); await registerPaymentProviders(); logger.info(`加载插件完成,加载模式:${process.env.certd_plugin_loadmode}`); - } } diff --git a/packages/ui/certd-server/src/modules/auto/auto-mitter-register.ts b/packages/ui/certd-server/src/modules/auto/auto-mitter-register.ts index 1b87f004a..06dc88805 100644 --- a/packages/ui/certd-server/src/modules/auto/auto-mitter-register.ts +++ b/packages/ui/certd-server/src/modules/auto/auto-mitter-register.ts @@ -1,6 +1,6 @@ -import { logger, utils } from '@certd/basic'; -import { UserSuiteService } from '@certd/commercial-core'; -import { Inject, Provide, Scope, ScopeEnum } from '@midwayjs/core'; +import { logger, utils } from "@certd/basic"; +import { UserSuiteService } from "@certd/commercial-core"; +import { Inject, Provide, Scope, ScopeEnum } from "@midwayjs/core"; @Provide() @Scope(ScopeEnum.Request, { allowDowngrade: true }) @@ -12,8 +12,8 @@ export class AutoMitterRegister { await this.registerOnNewUser(); } async registerOnNewUser() { - utils.mitter.on('register', async (req: { userId: number }) => { - logger.info('register event', req.userId); + utils.mitter.on("register", async (req: { userId: number }) => { + logger.info("register event", req.userId); await this.userSuiteService.presentGiftSuite(req.userId); }); } diff --git a/packages/ui/certd-server/src/modules/auto/auto-print.ts b/packages/ui/certd-server/src/modules/auto/auto-print.ts index 79a9cda17..7138ac8a3 100644 --- a/packages/ui/certd-server/src/modules/auto/auto-print.ts +++ b/packages/ui/certd-server/src/modules/auto/auto-print.ts @@ -1,15 +1,15 @@ -import { App, Config, Inject, Provide, Scope, ScopeEnum } from '@midwayjs/core'; -import { getPlusInfo, isPlus } from '@certd/plus-core'; -import { isDev, logger } from '@certd/basic'; +import { App, Config, Inject, Provide, Scope, ScopeEnum } from "@midwayjs/core"; +import { getPlusInfo, isPlus } from "@certd/plus-core"; +import { isDev, logger } from "@certd/basic"; -import { SysInstallInfo, SysSettingsService } from '@certd/lib-server'; -import { getVersion } from '../../utils/version.js'; -import dayjs from 'dayjs'; -import { Application } from '@midwayjs/koa'; -import { httpsServer, HttpsServerOptions } from './https/server.js'; -import { UserService } from '../sys/authority/service/user-service.js'; -import { UserSettingsService } from '../mine/service/user-settings-service.js'; -import { startProxyServer } from './proxy/server.js'; +import { SysInstallInfo, SysSettingsService } from "@certd/lib-server"; +import { getVersion } from "../../utils/version.js"; +import dayjs from "dayjs"; +import { Application } from "@midwayjs/koa"; +import { httpsServer, HttpsServerOptions } from "./https/server.js"; +import { UserService } from "../sys/authority/service/user-service.js"; +import { UserSettingsService } from "../mine/service/user-settings-service.js"; +import { startProxyServer } from "./proxy/server.js"; @Provide() @Scope(ScopeEnum.Request, { allowDowngrade: true }) @@ -20,18 +20,18 @@ export class AutoPrint { @App() app: Application; - @Config('https') + @Config("https") httpsConfig: HttpsServerOptions; - @Config('koa') + @Config("koa") koaConfig: any; @Inject() userService: UserService; - + @Inject() userSettingsService: UserSettingsService; - @Config('system.resetAdminPasswd') + @Config("system.resetAdminPasswd") private resetAdminPasswd: boolean; async init() { @@ -43,31 +43,31 @@ export class AutoPrint { this.startHeapLog(); } const installInfo: SysInstallInfo = await this.sysSettingsService.getSetting(SysInstallInfo); - logger.info('========================================='); - logger.info('当前站点ID:', installInfo.siteId); + logger.info("========================================="); + logger.info("当前站点ID:", installInfo.siteId); const version = await getVersion(); logger.info(`当前版本:${version}`); const plusInfo = getPlusInfo(); if (isPlus()) { - logger.info(`授权信息:${plusInfo.vipType},${plusInfo.expireTime === -1 ? '永久' : dayjs(plusInfo.expireTime).format('YYYY-MM-DD')}`); + logger.info(`授权信息:${plusInfo.vipType},${plusInfo.expireTime === -1 ? "永久" : dayjs(plusInfo.expireTime).format("YYYY-MM-DD")}`); } - logger.info('Certd已启动'); - logger.info('========================================='); + logger.info("Certd已启动"); + logger.info("========================================="); await this.resetPasswd(); } - async resetPasswd(){ + async resetPasswd() { if (this.resetAdminPasswd === true) { - logger.info('开始重置1号管理员用户的密码'); - const newPasswd = '123456'; + logger.info("开始重置1号管理员用户的密码"); + const newPasswd = "123456"; await this.userService.resetPassword(1, newPasswd); await this.userService.updateStatus(1, 1); await this.userSettingsService.deleteWhere({ userId: 1, - key:"user.two.factor" - }) - const publicSettings = await this.sysSettingsService.getPublicSettings() - publicSettings.captchaEnabled = false + key: "user.two.factor", + }); + const publicSettings = await this.sysSettingsService.getPublicSettings(); + publicSettings.captchaEnabled = false; await this.sysSettingsService.savePublicSettings(publicSettings); const user = await this.userService.info(1); @@ -77,7 +77,7 @@ export class AutoPrint { startHeapLog() { function format(bytes: any) { - return (bytes / 1024 / 1024).toFixed(2) + ' MB'; + return (bytes / 1024 / 1024).toFixed(2) + " MB"; } function printHeapLog() { const mu = process.memoryUsage(); @@ -89,7 +89,7 @@ export class AutoPrint { startHttpsServer() { if (!this.httpsConfig.enabled) { - logger.info('Https server is not enabled'); + logger.info("Https server is not enabled"); return; } httpsServer.start({ @@ -100,6 +100,6 @@ export class AutoPrint { } startProxyServer() { - startProxyServer({port: 7003}); + startProxyServer({ port: 7003 }); } } diff --git a/packages/ui/certd-server/src/modules/auto/fix/cert-info-wildcard-domain-count-fix.ts b/packages/ui/certd-server/src/modules/auto/fix/cert-info-wildcard-domain-count-fix.ts index 88faba7e1..20a3f6d09 100644 --- a/packages/ui/certd-server/src/modules/auto/fix/cert-info-wildcard-domain-count-fix.ts +++ b/packages/ui/certd-server/src/modules/auto/fix/cert-info-wildcard-domain-count-fix.ts @@ -38,10 +38,10 @@ export class CertInfoWildcardDomainCountFix { if (fixedCount > 0) { logger.info(`已修复证书泛域名数量历史数据,数量=${fixedCount}`); } - return true + return true; } catch (e: any) { logger.error("修复证书泛域名数量历史数据失败", e); } - return false + return false; } } diff --git a/packages/ui/certd-server/src/modules/auto/fix/common-eab-to-acme-account-fix.ts b/packages/ui/certd-server/src/modules/auto/fix/common-eab-to-acme-account-fix.ts index cfb28402f..f93c2e1b4 100644 --- a/packages/ui/certd-server/src/modules/auto/fix/common-eab-to-acme-account-fix.ts +++ b/packages/ui/certd-server/src/modules/auto/fix/common-eab-to-acme-account-fix.ts @@ -63,7 +63,6 @@ export class CommonEabToAcmeAccountFix { @Inject() storageService: StorageService; - async init() { try { const certApplyConfig = await this.pluginConfigService.getPluginConfig({ diff --git a/packages/ui/certd-server/src/modules/auto/fix/google-common-eab-account-key-fix.ts b/packages/ui/certd-server/src/modules/auto/fix/google-common-eab-account-key-fix.ts index 946dc32e1..f567c80f9 100644 --- a/packages/ui/certd-server/src/modules/auto/fix/google-common-eab-account-key-fix.ts +++ b/packages/ui/certd-server/src/modules/auto/fix/google-common-eab-account-key-fix.ts @@ -56,12 +56,12 @@ export class GoogleCommonEabAccountKeyFix { }); const googleCommonEabAccessId = certApplyConfig?.sysSetting?.input?.googleCommonEabAccessId; if (!googleCommonEabAccessId) { - return true; + return true; } const eabAccess = await this.accessService.getAccessById(googleCommonEabAccessId, false); if (eabAccess.accountKey) { - return true; + return true; } if (!eabAccess.kid) { logger.info("公共Google EAB授权缺少KID,跳过历史ACME账号私钥修复"); @@ -82,7 +82,7 @@ export class GoogleCommonEabAccountKeyFix { } catch (e: any) { logger.error("修复公共Google EAB授权ACME账号私钥失败", e); } - return false + return false; } async getLegacyGoogleAccountConfig(email?: string) { diff --git a/packages/ui/certd-server/src/modules/auto/fix/legacy-acme-account-access-fix.ts b/packages/ui/certd-server/src/modules/auto/fix/legacy-acme-account-access-fix.ts index 9145c9433..6dc33b772 100644 --- a/packages/ui/certd-server/src/modules/auto/fix/legacy-acme-account-access-fix.ts +++ b/packages/ui/certd-server/src/modules/auto/fix/legacy-acme-account-access-fix.ts @@ -74,7 +74,6 @@ export class LegacyAcmeAccountAccessFix { @Inject() accessService: AccessService; - async init() { try { const repository = this.storageService.getRepository(); diff --git a/packages/ui/certd-server/src/modules/auto/fix/oauth-subtype-bound-type-fix.ts b/packages/ui/certd-server/src/modules/auto/fix/oauth-subtype-bound-type-fix.ts index cb70e4eab..118f22a0b 100644 --- a/packages/ui/certd-server/src/modules/auto/fix/oauth-subtype-bound-type-fix.ts +++ b/packages/ui/certd-server/src/modules/auto/fix/oauth-subtype-bound-type-fix.ts @@ -41,7 +41,7 @@ export class OauthSubtypeBoundTypeFix { await this.convertLegacyAddonLoginTypeToArray(addonEntity, legacyLoginType, manager); } }); - return true + return true; } catch (e: any) { logger.error("修复OAuth subtype绑定历史数据失败", e); } diff --git a/packages/ui/certd-server/src/modules/auto/fix/suite-content-wildcard-domain-count-fix.ts b/packages/ui/certd-server/src/modules/auto/fix/suite-content-wildcard-domain-count-fix.ts index 889530e51..f0c37fe93 100644 --- a/packages/ui/certd-server/src/modules/auto/fix/suite-content-wildcard-domain-count-fix.ts +++ b/packages/ui/certd-server/src/modules/auto/fix/suite-content-wildcard-domain-count-fix.ts @@ -14,7 +14,6 @@ export function fixSuiteContentWildcardDomainCount(contentValue?: string) { return JSON.stringify(content); } - @Provide() @Scope(ScopeEnum.Request, { allowDowngrade: true }) export class SuiteContentWildcardDomainCountFix { @@ -33,11 +32,11 @@ export class SuiteContentWildcardDomainCountFix { if (fixedCount > 0) { logger.info(`已修复套餐最大泛域名数量历史数据,数量=${fixedCount}`); } - return true + return true; } catch (e: any) { logger.error("修复套餐最大泛域名数量历史数据失败", e); } - return false + return false; } private async fixSuiteContentWildcardDomainCountByTable(entityManager: any, tableName: string) { diff --git a/packages/ui/certd-server/src/modules/auto/https/self-certificate.ts b/packages/ui/certd-server/src/modules/auto/https/self-certificate.ts index 490679bdd..9bf79855c 100644 --- a/packages/ui/certd-server/src/modules/auto/https/self-certificate.ts +++ b/packages/ui/certd-server/src/modules/auto/https/self-certificate.ts @@ -1,8 +1,8 @@ -import { logger } from '@certd/basic'; -import fs from 'fs'; +import { logger } from "@certd/basic"; +import fs from "fs"; // @ts-ignore -import forge from 'node-forge'; -import path from 'path'; +import forge from "node-forge"; +import path from "path"; export function createSelfCertificate(opts: { crtPath: string; keyPath: string }) { // 生成密钥对 @@ -11,14 +11,14 @@ export function createSelfCertificate(opts: { crtPath: string; keyPath: string } // 创建自签名证书 const cert = forge.pki.createCertificate(); cert.publicKey = keypair.publicKey; - cert.serialNumber = '01'; + cert.serialNumber = "01"; cert.validFrom = new Date(Date.now() - 1000 * 60 * 60 * 24).toISOString(); // 1天前 cert.validTo = new Date(Date.now() + 1000 * 60 * 60 * 24 * 365 * 10).toISOString(); // 10年后 // 创建主题 const attrs = [ { - name: 'commonName', - value: 'self-certificate.certd', // 或者你的域名 + name: "commonName", + value: "self-certificate.certd", // 或者你的域名 }, ]; cert.setSubject(attrs); @@ -30,7 +30,7 @@ export function createSelfCertificate(opts: { crtPath: string; keyPath: string } const pemKey = forge.pki.privateKeyToPem(keypair.privateKey); // 写入文件 - logger.info('生成自签名证书成功'); + logger.info("生成自签名证书成功"); logger.info(`自签证书保存路径: ${opts.crtPath}`); logger.info(`自签私钥保存路径: ${opts.keyPath}`); const crtDir = path.dirname(opts.crtPath); diff --git a/packages/ui/certd-server/src/modules/auto/https/server.ts b/packages/ui/certd-server/src/modules/auto/https/server.ts index 8e995bca5..5675dbce0 100644 --- a/packages/ui/certd-server/src/modules/auto/https/server.ts +++ b/packages/ui/certd-server/src/modules/auto/https/server.ts @@ -1,8 +1,8 @@ -import https from 'node:https'; -import fs from 'fs'; -import { Application } from '@midwayjs/koa'; -import { createSelfCertificate } from './self-certificate.js'; -import {logger, safePromise} from '@certd/basic'; +import https from "node:https"; +import fs from "fs"; +import { Application } from "@midwayjs/koa"; +import { createSelfCertificate } from "./self-certificate.js"; +import { logger, safePromise } from "@certd/basic"; export type HttpsServerOptions = { enabled: boolean; @@ -33,24 +33,24 @@ export class HttpsServer { start(opts: HttpsServerOptions) { if (!opts) { - logger.error('https配置不能为空'); + logger.error("https配置不能为空"); return; } this.opts = opts; - logger.info('========================================='); + logger.info("========================================="); if (!opts.key || !opts.cert) { - logger.error('证书路径未配置,无法启动https服务,请先配置:koa.https.key和koa.https.cert'); + logger.error("证书路径未配置,无法启动https服务,请先配置:koa.https.key和koa.https.cert"); return; } if (!fs.existsSync(opts.key) || !fs.existsSync(opts.cert)) { - logger.info('证书文件不存在,将生成自签名证书'); + logger.info("证书文件不存在,将生成自签名证书"); createSelfCertificate({ crtPath: opts.cert, keyPath: opts.key, }); } - logger.info('准备启动https服务'); + logger.info("准备启动https服务"); const httpServer = https.createServer( { cert: fs.readFileSync(opts.cert), @@ -59,7 +59,7 @@ export class HttpsServer { opts.app.callback() ); this.server = httpServer; - let hostname = opts.hostname || '::'; + let hostname = opts.hostname || "::"; // A function that runs in the context of the http server // and reports what type of server listens on which port function listeningReporter() { @@ -71,19 +71,18 @@ export class HttpsServer { httpServer.listen(opts.port, hostname, listeningReporter); return httpServer; } catch (e) { - if ( e.message?.includes("address family not supported")) { - hostname = "0.0.0.0" + if (e.message?.includes("address family not supported")) { + hostname = "0.0.0.0"; logger.error(`${e.message},尝试监听${hostname}`, e); - try{ + try { httpServer.listen(opts.port, hostname, listeningReporter); return httpServer; - }catch (e) { - logger.error('启动https服务失败', e); + } catch (e) { + logger.error("启动https服务失败", e); } - }else{ - logger.error('启动https服务失败', e); + } else { + logger.error("启动https服务失败", e); } - } } } diff --git a/packages/ui/certd-server/src/modules/auto/proxy/server.ts b/packages/ui/certd-server/src/modules/auto/proxy/server.ts index ac78e47a5..7a2042ac4 100644 --- a/packages/ui/certd-server/src/modules/auto/proxy/server.ts +++ b/packages/ui/certd-server/src/modules/auto/proxy/server.ts @@ -1,13 +1,12 @@ // proxy-server.js -import http from 'http'; -import https from 'https'; -import url from 'url'; -import net from 'net'; -import { logger } from '@certd/basic'; +import http from "http"; +import https from "https"; +import url from "url"; +import net from "net"; +import { logger } from "@certd/basic"; - -export function startProxyServer(opts:{port:number}) { - const {port} = opts; +export function startProxyServer(opts: { port: number }) { + const { port } = opts; // 创建 HTTP 代理服务器 const proxyServer = http.createServer((clientReq, clientRes) => { @@ -17,31 +16,31 @@ export function startProxyServer(opts:{port:number}) { const parsedUrl = url.parse(clientReq.url); const options = { hostname: parsedUrl.hostname, - port: parsedUrl.port || (parsedUrl.protocol === 'https:' ? 443 : 80), + port: parsedUrl.port || (parsedUrl.protocol === "https:" ? 443 : 80), path: parsedUrl.path, method: clientReq.method, - headers: clientReq.headers + headers: clientReq.headers, }; // 根据协议选择不同的模块 - const protocol = parsedUrl.protocol === 'https:' ? https : http; + const protocol = parsedUrl.protocol === "https:" ? https : http; // 移除可能会引起问题的 headers - delete options.headers['proxy-connection']; - delete options.headers['connection']; - delete options.headers['keep-alive']; + delete options.headers["proxy-connection"]; + delete options.headers["connection"]; + delete options.headers["keep-alive"]; // 创建到目标服务器的请求 - const proxyReq = protocol.request(options, (proxyRes) => { + const proxyReq = protocol.request(options, proxyRes => { // 将目标服务器的响应返回给客户端 clientRes.writeHead(proxyRes.statusCode, proxyRes.headers); proxyRes.pipe(clientRes); }); - proxyReq.on('error', (err) => { - logger.error('[proxy] 代理请求错误:', err); + proxyReq.on("error", err => { + logger.error("[proxy] 代理请求错误:", err); clientRes.writeHead(500); - clientRes.end('代理服务器错误'); + clientRes.end("代理服务器错误"); }); // 将客户端请求体转发到目标服务器 @@ -49,18 +48,16 @@ export function startProxyServer(opts:{port:number}) { }); // 处理 CONNECT 方法(HTTPS 代理) - proxyServer.on('connect', (req, clientSocket, head) => { + proxyServer.on("connect", (req, clientSocket, head) => { logger.log(`[proxy] HTTPS 连接请求: ${req.url}`); - const [hostname, port] = req.url.split(':'); + const [hostname, port] = req.url.split(":"); const portNum = parseInt(port) || 443; // 连接到目标服务器 const serverSocket = net.connect(portNum, hostname, () => { // 告诉客户端连接已建立 - clientSocket.write('HTTP/1.1 200 Connection Established\r\n' + - 'Proxy-agent: Node.js-Proxy\r\n' + - '\r\n'); + clientSocket.write("HTTP/1.1 200 Connection Established\r\n" + "Proxy-agent: Node.js-Proxy\r\n" + "\r\n"); // 建立双向数据流 serverSocket.write(head); @@ -68,25 +65,25 @@ export function startProxyServer(opts:{port:number}) { clientSocket.pipe(serverSocket); }); - serverSocket.on('error', (err) => { - logger.error('[proxy] HTTPS 代理错误:', err); + serverSocket.on("error", err => { + logger.error("[proxy] HTTPS 代理错误:", err); clientSocket.end(); }); - clientSocket.on('error', (err) => { - logger.error('[proxy] 客户端 socket 错误:', err); + clientSocket.on("error", err => { + logger.error("[proxy] 客户端 socket 错误:", err); serverSocket.end(); }); }); // 监听端口 proxyServer.listen(port, () => { - logger.info(`[proxy] 正向代理服务器运行在 http://0.0.0.0:${port}`); + logger.info(`[proxy] 正向代理服务器运行在 http://0.0.0.0:${port}`); }); proxyServer.close(() => { - logger.info('[proxy] 正向代理服务器已关闭'); + logger.info("[proxy] 正向代理服务器已关闭"); }); - return proxyServer -} \ No newline at end of file + return proxyServer; +} diff --git a/packages/ui/certd-server/src/modules/basic/entity/group.ts b/packages/ui/certd-server/src/modules/basic/entity/group.ts index ae6d920a1..f3a8e9d02 100644 --- a/packages/ui/certd-server/src/modules/basic/entity/group.ts +++ b/packages/ui/certd-server/src/modules/basic/entity/group.ts @@ -1,41 +1,41 @@ -import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; +import { Column, Entity, PrimaryGeneratedColumn } from "typeorm"; -export const GROUP_TYPE_SITE = 'site'; +export const GROUP_TYPE_SITE = "site"; -@Entity('cd_group') +@Entity("cd_group") export class GroupEntity { @PrimaryGeneratedColumn() id: number; - @Column({ name: 'user_id', comment: '用户id' }) + @Column({ name: "user_id", comment: "用户id" }) userId: number; - @Column({ name: 'name', comment: '分组名称' }) + @Column({ name: "name", comment: "分组名称" }) name: string; - @Column({ name: 'icon', comment: '图标' }) + @Column({ name: "icon", comment: "图标" }) icon: string; - @Column({ name: 'favorite', comment: '收藏' }) + @Column({ name: "favorite", comment: "收藏" }) favorite: boolean; - @Column({ name: 'type', comment: '类型', length: 512 }) + @Column({ name: "type", comment: "类型", length: 512 }) type: string; - @Column({ name: 'project_id', comment: '项目Id' }) + @Column({ name: "project_id", comment: "项目Id" }) projectId: number; @Column({ - name: 'create_time', - comment: '创建时间', - default: () => 'CURRENT_TIMESTAMP', + name: "create_time", + comment: "创建时间", + default: () => "CURRENT_TIMESTAMP", }) createTime: Date; @Column({ - name: 'update_time', - comment: '修改时间', - default: () => 'CURRENT_TIMESTAMP', + name: "update_time", + comment: "修改时间", + default: () => "CURRENT_TIMESTAMP", }) updateTime: Date; } diff --git a/packages/ui/certd-server/src/modules/basic/service/captcha-service.ts b/packages/ui/certd-server/src/modules/basic/service/captcha-service.ts index 930980838..b77bdfc4a 100644 --- a/packages/ui/certd-server/src/modules/basic/service/captcha-service.ts +++ b/packages/ui/certd-server/src/modules/basic/service/captcha-service.ts @@ -12,15 +12,14 @@ export class CaptchaService { @Inject() addonGetterService: AddonGetterService; - async getCaptcha(captchaAddonId?: number) { if (!captchaAddonId) { const settings = await this.sysSettingsService.getPublicSettings(); captchaAddonId = settings.captchaAddonId ?? 0; } - const addon: ICaptchaAddon = await this.addonGetterService.getAddonById(captchaAddonId, true, 0,null, { + const addon: ICaptchaAddon = await this.addonGetterService.getAddonById(captchaAddonId, true, 0, null, { type: "captcha", - name: "image" + name: "image", }); if (!addon) { throw new Error("验证码插件还未配置"); @@ -28,8 +27,7 @@ export class CaptchaService { return await addon.getCaptcha(); } - - async doValidate(opts: { form: any, must?: boolean, captchaAddonId?: number,req:CaptchaRequest }) { + async doValidate(opts: { form: any; must?: boolean; captchaAddonId?: number; req: CaptchaRequest }) { if (!opts.captchaAddonId) { const settings = await this.sysSettingsService.getPublicSettings(); opts.captchaAddonId = settings.captchaAddonId ?? 0; @@ -46,13 +44,11 @@ export class CaptchaService { if (!opts.form) { throw new Error("请输入验证码"); } - const res = await addon.onValidate(opts.form,opts.req); + const res = await addon.onValidate(opts.form, opts.req); if (!res) { throw new Error("验证码错误"); } return true; - } - } diff --git a/packages/ui/certd-server/src/modules/basic/service/code-service.ts b/packages/ui/certd-server/src/modules/basic/service/code-service.ts index 740602bc7..22956d582 100644 --- a/packages/ui/certd-server/src/modules/basic/service/code-service.ts +++ b/packages/ui/certd-server/src/modules/basic/service/code-service.ts @@ -1,11 +1,11 @@ -import { cache, isDev, randomNumber, simpleNanoId } from '@certd/basic'; -import { AccessService, AccessSysGetter, CodeErrorException, SysSettingsService } from '@certd/lib-server'; -import { Inject, Provide, Scope, ScopeEnum } from '@midwayjs/core'; -import { ISmsService } from '../sms/api.js'; -import { SmsServiceFactory } from '../sms/factory.js'; +import { cache, isDev, randomNumber, simpleNanoId } from "@certd/basic"; +import { AccessService, AccessSysGetter, CodeErrorException, SysSettingsService } from "@certd/lib-server"; +import { Inject, Provide, Scope, ScopeEnum } from "@midwayjs/core"; +import { ISmsService } from "../sms/api.js"; +import { SmsServiceFactory } from "../sms/factory.js"; import { CaptchaService } from "./captcha-service.js"; -import { EmailService } from './email-service.js'; -import { CaptchaRequest } from '../../../plugins/plugin-captcha/api.js'; +import { EmailService } from "./email-service.js"; +import { CaptchaRequest } from "../../../plugins/plugin-captcha/api.js"; // {data: '', text: 'abcd'} /** @@ -24,32 +24,30 @@ export class CodeService { @Inject() captchaService: CaptchaService; - - - async checkCaptcha(body:any,req:CaptchaRequest) { - return await this.captchaService.doValidate({form:body,req}); + async checkCaptcha(body: any, req: CaptchaRequest) { + return await this.captchaService.doValidate({ form: body, req }); } /** */ async sendSmsCode( - phoneCode = '86', + phoneCode = "86", mobile: string, opts?: { - duration?: number, - verificationType?: string, - verificationCodeLength?: number, - }, + duration?: number; + verificationType?: string; + verificationCodeLength?: number; + } ) { if (!mobile) { - throw new Error('手机号不能为空'); + throw new Error("手机号不能为空"); } - const verificationCodeLength = Math.floor(Math.max(Math.min(opts?.verificationCodeLength || 4, 8), 4)); + const verificationCodeLength = Math.floor(Math.max(Math.min(opts?.verificationCodeLength || 4, 8), 4)); const duration = Math.floor(Math.max(Math.min(opts?.duration || 5, 15), 1)); const sysSettings = await this.sysSettingsService.getPrivateSettings(); if (!sysSettings.sms?.config?.accessId) { - throw new Error('当前站点还未配置短信'); + throw new Error("当前站点还未配置短信"); } const smsType = sysSettings.sms.type; const smsConfig = sysSettings.sms.config; @@ -66,7 +64,7 @@ export class CodeService { phoneCode, }); - const key = this.buildSmsCodeKey(phoneCode, mobile, opts?.verificationType); + const key = this.buildSmsCodeKey(phoneCode, mobile, opts?.verificationType); cache.set(key, smsCode, { ttl: duration * 60 * 1000, //5分钟 }); @@ -81,38 +79,38 @@ export class CodeService { async sendEmailCode( email: string, opts?: { - duration?: number, - verificationType?: string, - verificationCodeLength?: number, - }, + duration?: number; + verificationType?: string; + verificationCodeLength?: number; + } ) { if (!email) { - throw new Error('Email不能为空'); + throw new Error("Email不能为空"); } - - const verificationCodeLength = Math.floor(Math.max(Math.min(opts?.verificationCodeLength || 4, 8), 4)); + const verificationCodeLength = Math.floor(Math.max(Math.min(opts?.verificationCodeLength || 4, 8), 4)); const duration = Math.floor(Math.max(Math.min(opts?.duration || 5, 15), 1)); const code = randomNumber(verificationCodeLength); - + const templateData = { - code, duration, + code, + duration, title: "验证码", - content:`您的验证码是${code},请勿泄露`, - notificationType: "registerCode" - } - if (opts?.verificationType === 'forgotPassword') { - templateData.title = '找回密码'; - templateData.notificationType = "forgotPassword" + content: `您的验证码是${code},请勿泄露`, + notificationType: "registerCode", + }; + if (opts?.verificationType === "forgotPassword") { + templateData.title = "找回密码"; + templateData.notificationType = "forgotPassword"; } await this.emailService.sendByTemplate({ - type: templateData.notificationType, - data: templateData, - receivers: [email], + type: templateData.notificationType, + data: templateData, + receivers: [email], }); - const key = this.buildEmailCodeKey(email,opts?.verificationType); + const key = this.buildEmailCodeKey(email, opts?.verificationType); cache.set(key, code, { ttl: duration * 60 * 1000, //5分钟 }); @@ -122,44 +120,43 @@ export class CodeService { /** * checkSms */ - async checkSmsCode(opts: { mobile: string; phoneCode: string; smsCode: string; verificationType?: string; throwError: boolean; maxErrorCount?: number }) { + async checkSmsCode(opts: { mobile: string; phoneCode: string; smsCode: string; verificationType?: string; throwError: boolean; maxErrorCount?: number }) { const key = this.buildSmsCodeKey(opts.phoneCode, opts.mobile, opts.verificationType); - return this.checkValidateCode("sms",key, opts.smsCode, opts.throwError, opts.maxErrorCount); - + return this.checkValidateCode("sms", key, opts.smsCode, opts.throwError, opts.maxErrorCount); } buildSmsCodeKey(phoneCode: string, mobile: string, verificationType?: string) { - return ['sms', verificationType, phoneCode, mobile].filter(item => !!item).join(':'); + return ["sms", verificationType, phoneCode, mobile].filter(item => !!item).join(":"); } buildEmailCodeKey(email: string, verificationType?: string) { - return ['email', verificationType, email].filter(item => !!item).join(':'); + return ["email", verificationType, email].filter(item => !!item).join(":"); } - checkValidateCode(type:string,key: string, userCode: string, throwError = true, maxErrorCount = 3) { + checkValidateCode(type: string, key: string, userCode: string, throwError = true, maxErrorCount = 3) { // 记录异常次数key - if (isDev() && userCode==="1234567") { + if (isDev() && userCode === "1234567") { return true; } - const err_num_key = key + ':err_num'; + const err_num_key = key + ":err_num"; //验证邮件验证码 const code = cache.get(key); if (code == null || code !== userCode) { let maxRetryCount = false; if (!!code && maxErrorCount > 0) { - const err_num = cache.get(err_num_key) || 0 - if(err_num >= maxErrorCount - 1) { + const err_num = cache.get(err_num_key) || 0; + if (err_num >= maxErrorCount - 1) { maxRetryCount = true; cache.delete(key); cache.delete(err_num_key); } else { cache.set(err_num_key, err_num + 1, { - ttl: 30 * 60 * 1000 + ttl: 30 * 60 * 1000, }); } } if (throwError) { - const label = type ==='sms' ? '手机' : '邮箱'; - throw new CodeErrorException(!maxRetryCount ? `${label}验证码错误`: `${label}验证码错误请获取新的验证码`); + const label = type === "sms" ? "手机" : "邮箱"; + throw new CodeErrorException(!maxRetryCount ? `${label}验证码错误` : `${label}验证码错误请获取新的验证码`); } return false; } @@ -169,8 +166,8 @@ export class CodeService { } checkEmailCode(opts: { validateCode: string; email: string; verificationType?: string; throwError: boolean; maxErrorCount?: number }) { - const key = this.buildEmailCodeKey(opts.email, opts.verificationType); - return this.checkValidateCode('email',key, opts.validateCode, opts.throwError, opts.maxErrorCount); + const key = this.buildEmailCodeKey(opts.email, opts.verificationType); + return this.checkValidateCode("email", key, opts.validateCode, opts.throwError, opts.maxErrorCount); } compile(templateString: string) { @@ -183,11 +180,10 @@ export class CodeService { ); } - - buildValidationValueKey(code:string) { + buildValidationValueKey(code: string) { return `validationValue:${code}`; } - setValidationValue(value:any) { + setValidationValue(value: any) { const randomCode = simpleNanoId(12); const key = this.buildValidationValueKey(randomCode); cache.set(key, value, { @@ -195,7 +191,7 @@ export class CodeService { }); return randomCode; } - getValidationValue(code:string) { + getValidationValue(code: string) { return cache.get(this.buildValidationValueKey(code)); } } diff --git a/packages/ui/certd-server/src/modules/basic/service/email-service.ts b/packages/ui/certd-server/src/modules/basic/service/email-service.ts index 428bb26ef..9013d8a3c 100644 --- a/packages/ui/certd-server/src/modules/basic/service/email-service.ts +++ b/packages/ui/certd-server/src/modules/basic/service/email-service.ts @@ -1,18 +1,18 @@ -import { Inject, Provide, Scope, ScopeEnum } from '@midwayjs/core'; -import type { EmailSend, EmailSendByTemplateReq } from '@certd/pipeline'; -import { IEmailService } from '@certd/pipeline'; +import { Inject, Provide, Scope, ScopeEnum } from "@midwayjs/core"; +import type { EmailSend, EmailSendByTemplateReq } from "@certd/pipeline"; +import { IEmailService } from "@certd/pipeline"; -import { logger } from '@certd/basic'; -import { isComm, isPlus } from '@certd/plus-core'; +import { logger } from "@certd/basic"; +import { isComm, isPlus } from "@certd/plus-core"; -import nodemailer from 'nodemailer'; -import { SendMailOptions } from 'nodemailer'; -import { UserSettingsService } from '../../mine/service/user-settings-service.js'; -import { AddonService, PlusService, SysEmailConf, SysInstallInfo, SysSettingsService, SysSiteInfo } from '@certd/lib-server'; -import { getEmailSettings } from '../../sys/settings/fix.js'; +import nodemailer from "nodemailer"; +import { SendMailOptions } from "nodemailer"; +import { UserSettingsService } from "../../mine/service/user-settings-service.js"; +import { AddonService, PlusService, SysEmailConf, SysInstallInfo, SysSettingsService, SysSiteInfo } from "@certd/lib-server"; +import { getEmailSettings } from "../../sys/settings/fix.js"; import { UserEmailSetting } from "../../mine/service/models.js"; -import { AddonGetterService } from '../../pipeline/service/addon-getter-service.js'; -import { EmailContent, ITemplateProvider } from '../../../plugins/plugin-template/api.js'; +import { AddonGetterService } from "../../pipeline/service/addon-getter-service.js"; +import { EmailContent, ITemplateProvider } from "../../../plugins/plugin-template/api.js"; export type EmailConfig = { host: string; @@ -43,12 +43,11 @@ export class EmailService implements IEmailService { @Inject() addonGetterService: AddonGetterService; @Inject() - addonService: AddonService - + addonService: AddonService; async sendByPlus(email: EmailSend) { if (!isPlus()) { - throw new Error('plus not enabled'); + throw new Error("plus not enabled"); } /** @@ -63,13 +62,13 @@ export class EmailService implements IEmailService { /** */ async send(email: EmailSend) { - logger.info('sendEmail', email); + logger.info("sendEmail", email); if (!email.receivers || email.receivers.length === 0) { - throw new Error('收件人不能为空'); + throw new Error("收件人不能为空"); } - let sysTitle = 'Certd'; + let sysTitle = "Certd"; if (isComm()) { const siteInfo = await this.sysSettingsService.getSetting(SysSiteInfo); if (siteInfo) { @@ -79,11 +78,10 @@ export class EmailService implements IEmailService { let subject = email.subject; if (!subject) { - logger.error(new Error('邮件标题不能为空')); + logger.error(new Error("邮件标题不能为空")); subject = `邮件标题为空,请联系管理员排查`; } - if (!subject.includes(`【${sysTitle}】`)) { subject = `【${sysTitle}】${subject}`; } @@ -96,27 +94,25 @@ export class EmailService implements IEmailService { //自动使用plus发邮件 return await this.sendByPlus(email); } - throw new Error('邮件服务器还未设置'); + throw new Error("邮件服务器还未设置"); } - - if (emailConf.usePlus && isPlus()) { return await this.sendByPlus(email); } await this.sendByCustom(emailConf, email, sysTitle); - logger.info('sendEmail complete: ', email); + logger.info("sendEmail complete: ", email); } private async sendByCustom(emailConfig: EmailConfig, email: EmailSend, sysTitle: string) { const transporter = nodemailer.createTransport(emailConfig); let from = `${sysTitle} <${emailConfig.sender}>`; - if (emailConfig.sender.includes('<')) { + if (emailConfig.sender.includes("<")) { from = emailConfig.sender; } const mailOptions = { from: from, - to: email.receivers.join(', '), // list of receivers + to: email.receivers.join(", "), // list of receivers subject: email.subject, text: email.content, html: email.html, @@ -129,8 +125,8 @@ export class EmailService implements IEmailService { await this.sendByTemplate({ type: "common", data: { - title: '测试邮件,from certd', - content: '测试邮件,from certd', + title: "测试邮件,from certd", + content: "测试邮件,from certd", url: await this.getTestEmailUrl(), }, receivers: [receiver], @@ -147,41 +143,41 @@ export class EmailService implements IEmailService { } async list(userId: any) { - const userEmailSetting = await this.settingsService.getSetting(userId,null, UserEmailSetting) + const userEmailSetting = await this.settingsService.getSetting(userId, null, UserEmailSetting); return userEmailSetting.list; } async delete(userId: any, email: string) { - const userEmailSetting = await this.settingsService.getSetting(userId, null, UserEmailSetting) + const userEmailSetting = await this.settingsService.getSetting(userId, null, UserEmailSetting); userEmailSetting.list = userEmailSetting.list.filter(item => item !== email); - await this.settingsService.saveSetting(userId, null, userEmailSetting) + await this.settingsService.saveSetting(userId, null, userEmailSetting); } async add(userId: any, email: string) { - const userEmailSetting = await this.settingsService.getSetting(userId, null, UserEmailSetting) + const userEmailSetting = await this.settingsService.getSetting(userId, null, UserEmailSetting); //如果已存在 if (userEmailSetting.list.includes(email)) { - return + return; } - userEmailSetting.list.unshift(email) - await this.settingsService.saveSetting(userId, null, userEmailSetting) + userEmailSetting.list.unshift(email); + await this.settingsService.saveSetting(userId, null, userEmailSetting); } async sendByTemplate(req: EmailSendByTemplateReq) { - let content = null + let content = null; const emailConf = await this.sysSettingsService.getSetting(SysEmailConf); - const template = emailConf?.templates?.[req.type] - if (isPlus() && template && template.addonId) { - const addon: ITemplateProvider = await this.addonGetterService.getAddonById(template.addonId, true, 0,null) + const template = emailConf?.templates?.[req.type]; + if (isPlus() && template && template.addonId) { + const addon: ITemplateProvider = await this.addonGetterService.getAddonById(template.addonId, true, 0, null); if (addon) { - content = await addon.buildContent({ data: req.data }) + content = await addon.buildContent({ data: req.data }); } } - if (isPlus() && !content ) { + if (isPlus() && !content) { //看看有没有通用模版 if (emailConf?.templates?.common && emailConf?.templates?.common.addonId) { - const addon: ITemplateProvider = await this.addonGetterService.getAddonById(emailConf.templates.common.addonId, true, 0,null) + const addon: ITemplateProvider = await this.addonGetterService.getAddonById(emailConf.templates.common.addonId, true, 0, null); if (addon) { - content = await addon.buildContent({ data: req.data }) + content = await addon.buildContent({ data: req.data }); } } } @@ -189,21 +185,21 @@ export class EmailService implements IEmailService { // 没有找到模版,使用默认模版 if (!content) { try { - const addon: ITemplateProvider = await this.addonGetterService.getBlank("emailTemplate", req.type) - content = await addon.buildDefaultContent({ data: req.data }) + const addon: ITemplateProvider = await this.addonGetterService.getBlank("emailTemplate", req.type); + content = await addon.buildDefaultContent({ data: req.data }); } catch (e) { // 对应的通知类型模版可能没有注册或者开发 } } if (!content) { - const addon: ITemplateProvider = await this.addonGetterService.getBlank("emailTemplate", "common") - content = await addon.buildDefaultContent({ data: req.data }) + const addon: ITemplateProvider = await this.addonGetterService.getBlank("emailTemplate", "common"); + content = await addon.buildDefaultContent({ data: req.data }); } return await this.send({ ...content, receivers: req.receivers, attachments: req.attachments, - }) + }); } } diff --git a/packages/ui/certd-server/src/modules/basic/service/group-service.ts b/packages/ui/certd-server/src/modules/basic/service/group-service.ts index 64fdf7558..eb2ca12a0 100644 --- a/packages/ui/certd-server/src/modules/basic/service/group-service.ts +++ b/packages/ui/certd-server/src/modules/basic/service/group-service.ts @@ -1,9 +1,9 @@ -import { Provide, Scope, ScopeEnum } from '@midwayjs/core'; -import { BaseService } from '@certd/lib-server'; -import { InjectEntityModel } from '@midwayjs/typeorm'; -import { Repository } from 'typeorm'; -import { merge } from 'lodash-es'; -import { GroupEntity } from '../entity/group.js'; +import { Provide, Scope, ScopeEnum } from "@midwayjs/core"; +import { BaseService } from "@certd/lib-server"; +import { InjectEntityModel } from "@midwayjs/typeorm"; +import { Repository } from "typeorm"; +import { merge } from "lodash-es"; +import { GroupEntity } from "../entity/group.js"; @Provide() @Scope(ScopeEnum.Request, { allowDowngrade: true }) @@ -18,7 +18,7 @@ export class GroupService extends BaseService { async add(bean: any) { if (!bean.type) { - throw new Error('type is required'); + throw new Error("type is required"); } bean = merge( { diff --git a/packages/ui/certd-server/src/modules/basic/service/task-executor.ts b/packages/ui/certd-server/src/modules/basic/service/task-executor.ts index 809596b30..085dc2485 100644 --- a/packages/ui/certd-server/src/modules/basic/service/task-executor.ts +++ b/packages/ui/certd-server/src/modules/basic/service/task-executor.ts @@ -1,50 +1,50 @@ -import { logger } from "@certd/basic" +import { logger } from "@certd/basic"; export class BackTaskExecutor { - tasks: Record> = {} + tasks: Record> = {}; start(task: BackTask) { - const type = task.type || 'default' + const type = task.type || "default"; if (!this.tasks[type]) { - this.tasks[type] = {} + this.tasks[type] = {}; } - const oldTask = this.tasks[type][task.key] - if (oldTask ){ + const oldTask = this.tasks[type][task.key]; + if (oldTask) { if (oldTask.status === "running") { - throw new Error(`任务 ${task.title} 正在运行中`) + throw new Error(`任务 ${task.title} 正在运行中`); } this.clear(type, task.key); } - this.tasks[type][task.key] = task + this.tasks[type][task.key] = task; this.run(task); } get(type: string, key: string) { if (!this.tasks[type]) { - this.tasks[type] = {} + this.tasks[type] = {}; } - return this.tasks[type][key] + return this.tasks[type][key]; } removeIsEnd(type: string, key: string) { - const task = this.tasks[type]?.[key] + const task = this.tasks[type]?.[key]; if (task && task.status !== "running") { this.clear(type, key); } } clear(type: string, key: string) { - const task = this.tasks[type]?.[key] + const task = this.tasks[type]?.[key]; if (task) { task.clearTimeout(); - delete this.tasks[type][key] + delete this.tasks[type][key]; } } private async run(task: BackTask) { - const type = task.type || 'default' + const type = task.type || "default"; if (task.status === "running") { - throw new Error(`任务 ${type}—${task.key} 正在运行中`) + throw new Error(`任务 ${type}—${task.key} 正在运行中`); } task.startTime = Date.now(); task.clearTimeout(); @@ -54,84 +54,78 @@ export class BackTaskExecutor { } catch (e) { logger.error(`任务 ${task.title}[${type}-${task.key}] 执行失败`, e.message); task.status = "failed"; - task.addError(e.message) + task.addError(e.message); } finally { task.endTime = Date.now(); task.status = "done"; - task.setTimeoutId(setTimeout(() => { - this.clear(type, task.key); - }, 24 * 60 * 60 * 1000)); + task.setTimeoutId( + setTimeout(() => { + this.clear(type, task.key); + }, 24 * 60 * 60 * 1000) + ); delete task.run; } } - - - } export class BackTask { type: string; key: string; title: string; - total: number = 0; - current: number = 0; - skip: number = 0; + total = 0; + current = 0; + skip = 0; startTime: number; endTime: number; - status: string = "pending"; + status = "pending"; errors?: string[] = []; private _timeoutId?: NodeJS.Timeout; - - private _run: (task: BackTask) => Promise; - constructor(opts: { - type: string, - key: string, title: string, run: (task: BackTask) => Promise - }) { - const { key, title, run, type } = opts - this.type = type + constructor(opts: { type: string; key: string; title: string; run: (task: BackTask) => Promise }) { + const { key, title, run, type } = opts; + this.type = type; this.key = key; this.title = title; this._run = run; - Object.defineProperty(this, '_run', { + Object.defineProperty(this, "_run", { enumerable: false, - value: this._run - }) - Object.defineProperty(this, '_timeoutId', { - enumerable: false, - value: null - }) - - Object.defineProperty(this, 'progress', { - get: ()=> { - return this.getProgress() - }, - enumerable: true, // 关键:设置为可枚举 - configurable: true + value: this._run, }); - Object.defineProperty(this, 'successCount', { - get: ()=> { - return this.getSuccessCount() + Object.defineProperty(this, "_timeoutId", { + enumerable: false, + value: null, + }); + + Object.defineProperty(this, "progress", { + get: () => { + return this.getProgress(); }, - enumerable: true, // 关键:设置为可枚举 - configurable: true - }) - Object.defineProperty(this, 'errorCount', { - get: ()=> { - return this.getErrorCount() + enumerable: true, // 关键:设置为可枚举 + configurable: true, + }); + Object.defineProperty(this, "successCount", { + get: () => { + return this.getSuccessCount(); }, - enumerable: true, // 关键:设置为可枚举 - configurable: true - }) - Object.defineProperty(this, 'skipCount', { - get: ()=> { - return this.getSkipCount() + enumerable: true, // 关键:设置为可枚举 + configurable: true, + }); + Object.defineProperty(this, "errorCount", { + get: () => { + return this.getErrorCount(); }, - enumerable: true, // 关键:设置为可枚举 - configurable: true - }) + enumerable: true, // 关键:设置为可枚举 + configurable: true, + }); + Object.defineProperty(this, "skipCount", { + get: () => { + return this.getSkipCount(); + }, + enumerable: true, // 关键:设置为可枚举 + configurable: true, + }); } async run(task: BackTask) { @@ -145,7 +139,6 @@ export class BackTask { } } - setTimeoutId(timeoutId: NodeJS.Timeout) { this.clearTimeout(); this._timeoutId = timeoutId; @@ -155,34 +148,33 @@ export class BackTask { this.total = total; } incrementCurrent() { - this.current++ + this.current++; } addError(error: string) { - logger.error(error) - this.errors.push(error) + logger.error(error); + this.errors.push(error); } getErrorCount() { - return this.errors.length + return this.errors.length; } getSkipCount() { - return this.skip + return this.skip; } getSuccessCount() { - return this.current - this.errors.length + return this.current - this.errors.length; } getProgress() { - return (this.current * 1.0 / this.total * 100.0); + return ((this.current * 1.0) / this.total) * 100.0; } - incrementSkip() { - this.skip++ + this.skip++; } } -export const taskExecutor = new BackTaskExecutor(); \ No newline at end of file +export const taskExecutor = new BackTaskExecutor(); diff --git a/packages/ui/certd-server/src/modules/basic/sms/aliyun-sms.ts b/packages/ui/certd-server/src/modules/basic/sms/aliyun-sms.ts index 5ab712df5..f9b69df79 100644 --- a/packages/ui/certd-server/src/modules/basic/sms/aliyun-sms.ts +++ b/packages/ui/certd-server/src/modules/basic/sms/aliyun-sms.ts @@ -1,6 +1,6 @@ -import { logger } from '@certd/basic'; -import { ISmsService, PluginInputs, SmsPluginCtx } from './api.js'; -import { AliyunAccess, AliyunClient } from '../../../plugins/plugin-lib/aliyun/index.js'; +import { logger } from "@certd/basic"; +import { ISmsService, PluginInputs, SmsPluginCtx } from "./api.js"; +import { AliyunAccess, AliyunClient } from "../../../plugins/plugin-lib/aliyun/index.js"; export type AliyunSmsConfig = { accessId: string; @@ -11,30 +11,30 @@ export type AliyunSmsConfig = { export class AliyunSmsService implements ISmsService { static getDefine() { return { - name: 'aliyun', - desc: '阿里云短信服务', + name: "aliyun", + desc: "阿里云短信服务", input: { accessId: { - title: '阿里云授权', + title: "阿里云授权", component: { - name: 'access-selector', - type: 'aliyun', + name: "access-selector", + type: "aliyun", }, required: true, }, signName: { - title: '签名', + title: "签名", component: { - name: 'a-input', - vModel: 'value', + name: "a-input", + vModel: "value", }, required: true, }, codeTemplateId: { - title: '验证码模板Id', + title: "验证码模板Id", component: { - name: 'a-input', - vModel: 'value', + name: "a-input", + vModel: "value", }, required: true, }, @@ -55,8 +55,8 @@ export class AliyunSmsService implements ISmsService { await aliyunClinet.init({ accessKeyId: access.accessKeyId, accessKeySecret: access.accessKeySecret, - endpoint: 'https://dysmsapi.aliyuncs.com', - apiVersion: '2017-05-25', + endpoint: "https://dysmsapi.aliyuncs.com", + apiVersion: "2017-05-25", }); const smsConfig = this.ctx.config; const phoneNumber = phoneCode + mobile; @@ -67,6 +67,6 @@ export class AliyunSmsService implements ISmsService { TemplateParam: `{"code":"${code}"}`, }; - await aliyunClinet.request('SendSms', params); + await aliyunClinet.request("SendSms", params); } } diff --git a/packages/ui/certd-server/src/modules/basic/sms/api.ts b/packages/ui/certd-server/src/modules/basic/sms/api.ts index 8ff37f007..ad5c363ee 100644 --- a/packages/ui/certd-server/src/modules/basic/sms/api.ts +++ b/packages/ui/certd-server/src/modules/basic/sms/api.ts @@ -1,4 +1,4 @@ -import { FormItemProps, IAccessService } from '@certd/pipeline'; +import { FormItemProps, IAccessService } from "@certd/pipeline"; export interface ISmsService { sendSmsCode(opts: { mobile: string; code: string; phoneCode: string }): Promise; diff --git a/packages/ui/certd-server/src/modules/basic/sms/factory.ts b/packages/ui/certd-server/src/modules/basic/sms/factory.ts index 74566e54b..a9dbc97e7 100644 --- a/packages/ui/certd-server/src/modules/basic/sms/factory.ts +++ b/packages/ui/certd-server/src/modules/basic/sms/factory.ts @@ -1,4 +1,3 @@ - export class SmsServiceFactory { static async createSmsService(type: string) { const cls = await this.GetClassByType(type); @@ -7,17 +6,17 @@ export class SmsServiceFactory { static async GetClassByType(type: string) { switch (type) { - case 'aliyun': - const {AliyunSmsService} = await import("./aliyun-sms.js") + case "aliyun": + const { AliyunSmsService } = await import("./aliyun-sms.js"); return AliyunSmsService; - case 'yfysms': - const {YfySmsService} = await import("./yfy-sms.js") + case "yfysms": + const { YfySmsService } = await import("./yfy-sms.js"); return YfySmsService; - case 'tencent': - const {TencentSmsService} = await import("./tencent-sms.js") + case "tencent": + const { TencentSmsService } = await import("./tencent-sms.js"); return TencentSmsService; default: - throw new Error('不支持的短信服务类型'); + throw new Error("不支持的短信服务类型"); } } diff --git a/packages/ui/certd-server/src/modules/basic/sms/tencent-sms.ts b/packages/ui/certd-server/src/modules/basic/sms/tencent-sms.ts index 2c5b31a61..c5968e523 100644 --- a/packages/ui/certd-server/src/modules/basic/sms/tencent-sms.ts +++ b/packages/ui/certd-server/src/modules/basic/sms/tencent-sms.ts @@ -1,5 +1,5 @@ -import { TencentAccess } from '../../../plugins/plugin-lib/tencent/access.js'; -import {ISmsService, PluginInputs, SmsPluginCtx} from './api.js'; +import { TencentAccess } from "../../../plugins/plugin-lib/tencent/access.js"; +import { ISmsService, PluginInputs, SmsPluginCtx } from "./api.js"; export type TencentSmsConfig = { accessId: string; @@ -12,53 +12,53 @@ export type TencentSmsConfig = { export class TencentSmsService implements ISmsService { static getDefine() { return { - name: 'tencent', - desc: '腾讯云短信服务', + name: "tencent", + desc: "腾讯云短信服务", input: { accessId: { - title: '腾讯云授权', + title: "腾讯云授权", component: { - name: 'access-selector', - type: 'tencent', + name: "access-selector", + type: "tencent", }, required: true, }, region: { - title: '区域', - value:"ap-beijing", + title: "区域", + value: "ap-beijing", component: { - name: 'a-select', - vModel: 'value', - options:[ - {value:"ap-beijing",label:"华北地区(北京)"}, - {value:"ap-guangzhou",label:"华南地区(广州)"}, - {value:"ap-nanjing",label:"华东地区(南京)"}, - ] + name: "a-select", + vModel: "value", + options: [ + { value: "ap-beijing", label: "华北地区(北京)" }, + { value: "ap-guangzhou", label: "华南地区(广州)" }, + { value: "ap-nanjing", label: "华东地区(南京)" }, + ], }, - helper:"随便选一个", + helper: "随便选一个", required: true, }, signName: { - title: '签名', + title: "签名", component: { - name: 'a-input', - vModel: 'value', + name: "a-input", + vModel: "value", }, required: true, }, appId: { - title: '应用ID', + title: "应用ID", component: { - name: 'a-input', - vModel: 'value', + name: "a-input", + vModel: "value", }, required: true, }, codeTemplateId: { - title: '验证码模板Id', + title: "验证码模板Id", component: { - name: 'a-input', - vModel: 'value', + name: "a-input", + vModel: "value", }, required: true, }, @@ -72,13 +72,11 @@ export class TencentSmsService implements ISmsService { this.ctx = ctx; } - async getClient() { - const sdk = await import('tencentcloud-sdk-nodejs/tencentcloud/services/sms/v20210111/index.js'); + const sdk = await import("tencentcloud-sdk-nodejs/tencentcloud/services/sms/v20210111/index.js"); const client = sdk.v20210111.Client; const access = await this.ctx.accessService.getById(this.ctx.config.accessId); - // const region = this.region; const clientConfig = { credential: { @@ -102,15 +100,11 @@ export class TencentSmsService implements ISmsService { const client = await this.getClient(); const smsConfig = this.ctx.config; const params = { - "PhoneNumberSet": [ - `+${phoneCode}${mobile}` - ], - "SmsSdkAppId": smsConfig.appId, - "TemplateId": smsConfig.codeTemplateId, - "SignName": smsConfig.signName, - "TemplateParamSet": [ - code - ] + PhoneNumberSet: [`+${phoneCode}${mobile}`], + SmsSdkAppId: smsConfig.appId, + TemplateId: smsConfig.codeTemplateId, + SignName: smsConfig.signName, + TemplateParamSet: [code], }; const ret = await client.SendSms(params); this.checkRet(ret); @@ -118,7 +112,7 @@ export class TencentSmsService implements ISmsService { checkRet(ret: any) { if (!ret || ret.Error) { - throw new Error('执行失败:' + ret.Error.Code + ',' + ret.Error.Message); + throw new Error("执行失败:" + ret.Error.Code + "," + ret.Error.Message); } } } diff --git a/packages/ui/certd-server/src/modules/basic/sms/yfy-sms.ts b/packages/ui/certd-server/src/modules/basic/sms/yfy-sms.ts index 743468271..3aaf1b7ee 100644 --- a/packages/ui/certd-server/src/modules/basic/sms/yfy-sms.ts +++ b/packages/ui/certd-server/src/modules/basic/sms/yfy-sms.ts @@ -1,6 +1,6 @@ -import { http, utils } from '@certd/basic'; -import { ISmsService, PluginInputs, SmsPluginCtx } from './api.js'; -import { YfySmsAccess } from '../../../plugins/plugin-plus/yidun/access-sms.js'; +import { http, utils } from "@certd/basic"; +import { ISmsService, PluginInputs, SmsPluginCtx } from "./api.js"; +import { YfySmsAccess } from "../../../plugins/plugin-plus/yidun/access-sms.js"; export type YfySmsConfig = { accessId: string; @@ -10,22 +10,22 @@ export type YfySmsConfig = { export class YfySmsService implements ISmsService { static getDefine() { return { - name: 'yfysms', - desc: '易发云短信', + name: "yfysms", + desc: "易发云短信", input: { accessId: { - title: '易发云短信授权', + title: "易发云短信授权", component: { - name: 'access-selector', - type: 'yfysms', + name: "access-selector", + type: "yfysms", }, required: true, }, signName: { - title: '签名', + title: "签名", component: { - name: 'a-input', - vModel: 'value', + name: "a-input", + vModel: "value", }, required: true, }, @@ -44,10 +44,10 @@ export class YfySmsService implements ISmsService { const access = await this.ctx.accessService.getById(this.ctx.config.accessId); const res = await http.request({ - url: 'http://sms.yfyidc.cn/sms/', - method: 'post', + url: "http://sms.yfyidc.cn/sms/", + method: "post", headers: { - 'Content-Type': 'application/x-www-form-urlencoded', + "Content-Type": "application/x-www-form-urlencoded", }, data: { /** @@ -75,40 +75,40 @@ export class YfySmsService implements ISmsService { * 9 用户已封禁 * 10 未实名认证 */ - let message = ''; + let message = ""; switch (res) { case 1: - message = '余额不足'; + message = "余额不足"; break; case 2: - message = '用户不存在'; + message = "用户不存在"; break; case 3: - message = 'KEY错误'; + message = "KEY错误"; break; case 4: - message = '发送失败'; + message = "发送失败"; break; case 5: - message = '签名不存在'; + message = "签名不存在"; break; case 6: - message = '签名审核未通过'; + message = "签名审核未通过"; break; case 7: - message = '当前发信短信已达到上限'; + message = "当前发信短信已达到上限"; break; case 8: - message = '有违规词'; + message = "有违规词"; break; case 9: - message = '用户已封禁'; + message = "用户已封禁"; break; case 10: - message = '未实名认证'; + message = "未实名认证"; break; default: - message = '未知错误'; + message = "未知错误"; } throw new Error(`发送短信失败:${message}`); } diff --git a/packages/ui/certd-server/src/modules/cert/entity/domain.ts b/packages/ui/certd-server/src/modules/cert/entity/domain.ts index 1b0a07aa5..33ef8c657 100644 --- a/packages/ui/certd-server/src/modules/cert/entity/domain.ts +++ b/packages/ui/certd-server/src/modules/cert/entity/domain.ts @@ -1,62 +1,61 @@ -import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; +import { Column, Entity, PrimaryGeneratedColumn } from "typeorm"; /** * 域名管理 */ -@Entity('cd_domain') +@Entity("cd_domain") export class DomainEntity { @PrimaryGeneratedColumn() id: number; - @Column({ comment: '用户ID', name: 'user_id' }) + @Column({ comment: "用户ID", name: "user_id" }) userId: number; - @Column({ comment: '主域名', length: 100 }) + @Column({ comment: "主域名", length: 100 }) domain: string; - @Column({ comment: '校验类型', name: 'challenge_type', length: 50 }) - challengeType : string; + @Column({ comment: "校验类型", name: "challenge_type", length: 50 }) + challengeType: string; - @Column({ comment: 'DNS提供商', name: 'dns_provider_type', length: 50 }) + @Column({ comment: "DNS提供商", name: "dns_provider_type", length: 50 }) dnsProviderType: string; - @Column({ comment: 'DNS提供商授权', name: 'dns_provider_access' }) + @Column({ comment: "DNS提供商授权", name: "dns_provider_access" }) dnsProviderAccess: number; - @Column({ comment: '是否禁用', name: 'disabled' }) + @Column({ comment: "是否禁用", name: "disabled" }) disabled: boolean; - @Column({ comment: '注册时间', name: 'registration_date' }) + @Column({ comment: "注册时间", name: "registration_date" }) registrationDate: number; - @Column({ comment: '过期时间', name: 'expiration_date' }) + @Column({ comment: "过期时间", name: "expiration_date" }) expirationDate: number; - @Column({ comment: '来源', name: 'from_type', length: 50 }) + @Column({ comment: "来源", name: "from_type", length: 50 }) fromType: string; - - @Column({ comment: 'http上传类型', name: 'http_uploader_type', length: 50 }) + @Column({ comment: "http上传类型", name: "http_uploader_type", length: 50 }) httpUploaderType: string; - @Column({ comment: 'http上传授权', name: 'http_uploader_access' }) + @Column({ comment: "http上传授权", name: "http_uploader_access" }) httpUploaderAccess: number; - @Column({ comment: 'http上传根目录', name: 'http_upload_root_dir', length: 512 }) + @Column({ comment: "http上传根目录", name: "http_upload_root_dir", length: 512 }) httpUploadRootDir: string; - @Column({ name: 'project_id', comment: '项目Id' }) + @Column({ name: "project_id", comment: "项目Id" }) projectId: number; @Column({ - comment: '创建时间', - name: 'create_time', - default: () => 'CURRENT_TIMESTAMP', + comment: "创建时间", + name: "create_time", + default: () => "CURRENT_TIMESTAMP", }) createTime: Date; @Column({ - comment: '修改时间', - name: 'update_time', - default: () => 'CURRENT_TIMESTAMP', + comment: "修改时间", + name: "update_time", + default: () => "CURRENT_TIMESTAMP", }) updateTime: Date; } diff --git a/packages/ui/certd-server/src/modules/cert/service/domain-service.ts b/packages/ui/certd-server/src/modules/cert/service/domain-service.ts index 64af711a4..cb5a863f5 100644 --- a/packages/ui/certd-server/src/modules/cert/service/domain-service.ts +++ b/packages/ui/certd-server/src/modules/cert/service/domain-service.ts @@ -1,24 +1,24 @@ -import { http, logger, utils } from '@certd/basic'; -import { AccessService, BaseService, isEnterprise } from '@certd/lib-server'; -import { doPageTurn, Pager, PageRes } from '@certd/pipeline'; +import { http, logger, utils } from "@certd/basic"; +import { AccessService, BaseService, isEnterprise } from "@certd/lib-server"; +import { doPageTurn, Pager, PageRes } from "@certd/pipeline"; import { DomainVerifiers } from "@certd/plugin-cert"; import { createDnsProvider, dnsProviderRegistry, DomainParser } from "@certd/plugin-lib"; -import { Inject, Provide, Scope, ScopeEnum } from '@midwayjs/core'; -import { InjectEntityModel } from '@midwayjs/typeorm'; -import dayjs from 'dayjs'; -import { merge } from 'lodash-es'; -import { In, LessThan, Not, Repository } from 'typeorm'; -import { BackTask, taskExecutor } from '../../basic/service/task-executor.js'; +import { Inject, Provide, Scope, ScopeEnum } from "@midwayjs/core"; +import { InjectEntityModel } from "@midwayjs/typeorm"; +import dayjs from "dayjs"; +import { merge } from "lodash-es"; +import { In, LessThan, Not, Repository } from "typeorm"; +import { BackTask, taskExecutor } from "../../basic/service/task-executor.js"; import { CnameRecordEntity } from "../../cname/entity/cname-record.js"; -import { CnameRecordService } from '../../cname/service/cname-record-service.js'; -import { Cron } from '../../cron/cron.js'; -import { UserDomainImportSetting, UserDomainMonitorSetting } from '../../mine/service/models.js'; -import { UserSettingsService } from '../../mine/service/user-settings-service.js'; -import { JobHistoryService } from '../../monitor/service/job-history-service.js'; -import { TaskServiceBuilder } from '../../pipeline/service/getter/task-service-getter.js'; +import { CnameRecordService } from "../../cname/service/cname-record-service.js"; +import { Cron } from "../../cron/cron.js"; +import { UserDomainImportSetting, UserDomainMonitorSetting } from "../../mine/service/models.js"; +import { UserSettingsService } from "../../mine/service/user-settings-service.js"; +import { JobHistoryService } from "../../monitor/service/job-history-service.js"; +import { TaskServiceBuilder } from "../../pipeline/service/getter/task-service-getter.js"; import { SubDomainService } from "../../pipeline/service/sub-domain-service.js"; -import { DomainEntity } from '../entity/domain.js'; -import { TldClient } from './tld-client.js'; +import { DomainEntity } from "../entity/domain.js"; +import { TldClient } from "./tld-client.js"; export interface SyncFromProviderReq { userId: number; @@ -27,12 +27,10 @@ export interface SyncFromProviderReq { dnsProviderAccessId: number; } +const DOMAIN_IMPORT_TASK_TYPE = "domainImportTask"; +const DOMAIN_EXPIRE_TASK_TYPE = "domainExpirationSyncTask"; -const DOMAIN_IMPORT_TASK_TYPE = 'domainImportTask' -const DOMAIN_EXPIRE_TASK_TYPE = 'domainExpirationSyncTask' - -const DOMAIN_EXPIRE_CHECK_TYPE = 'domainExpirationCheck' - +const DOMAIN_EXPIRE_CHECK_TYPE = "domainExpirationCheck"; /** * @@ -63,8 +61,6 @@ export class DomainService extends BaseService { @Inject() cron: Cron; - - //@ts-ignore getRepository() { return this.repository; @@ -72,50 +68,48 @@ export class DomainService extends BaseService { async add(param) { if (param.userId == null) { - throw new Error('userId 不能为空'); + throw new Error("userId 不能为空"); } if (!param.domain) { - throw new Error('domain 不能为空'); + throw new Error("domain 不能为空"); } const old = await this.repository.findOne({ where: { domain: param.domain, - userId: param.userId - } + userId: param.userId, + }, }); if (old) { throw new Error(`域名(${param.domain})不能重复`); } if (!param.fromType) { - param.fromType = 'manual' + param.fromType = "manual"; } return await super.add(param); } async update(param) { if (!param.id) { - throw new Error('id 不能为空'); + throw new Error("id 不能为空"); } - const old = await this.info(param.id) + const old = await this.info(param.id); if (!old) { - throw new Error('domain记录不存在'); + throw new Error("domain记录不存在"); } const same = await this.repository.findOne({ where: { domain: param.domain, userId: old.userId, - id: Not(param.id) - } + id: Not(param.id), + }, }); if (same) { throw new Error(`域名(${param.domain})不能重复`); } - delete param.userId + delete param.userId; return await super.update(param); - - } /** @@ -124,23 +118,22 @@ export class DomainService extends BaseService { * @param domains //去除* 且去重之后的域名列表 */ async getDomainVerifiers(userId: number, projectId: number, domains: string[]): Promise { - - const mainDomainMap: Record = {} + const mainDomainMap: Record = {}; const taskService = this.taskServiceBuilder.create({ userId: userId, projectId: projectId }); const subDomainGetter = await taskService.getSubDomainsGetter(); - const domainParser = new DomainParser(subDomainGetter) + const domainParser = new DomainParser(subDomainGetter); - const mainDomains = [] + const mainDomains = []; for (const domain of domains) { const mainDomain = await domainParser.parse(domain); mainDomainMap[domain] = mainDomain; - mainDomains.push(mainDomain) + mainDomains.push(mainDomain); } //匹配DNS记录 - let allDomains = [...domains, ...mainDomains] + let allDomains = [...domains, ...mainDomains]; //去重 - allDomains = [...new Set(allDomains)] + allDomains = [...new Set(allDomains)]; //从 domain 表中获取配置 const domainRecords = await this.find({ @@ -149,19 +142,22 @@ export class DomainService extends BaseService { userId, projectId, disabled: false, - } - }) + }, + }); - const dnsMap = domainRecords.filter(item => item.challengeType === 'dns').reduce((pre, item) => { - pre[item.domain] = item - return pre - }, {}) - - const httpMap = domainRecords.filter(item => item.challengeType === 'http').reduce((pre, item) => { - pre[item.domain] = item - return pre - }, {}) + const dnsMap = domainRecords + .filter(item => item.challengeType === "dns") + .reduce((pre, item) => { + pre[item.domain] = item; + return pre; + }, {}); + const httpMap = domainRecords + .filter(item => item.challengeType === "http") + .reduce((pre, item) => { + pre[item.domain] = item; + return pre; + }, {}); //从cname record表中获取配置 const cnameRecords = await this.cnameRecordService.find({ @@ -170,91 +166,95 @@ export class DomainService extends BaseService { userId, projectId, status: "valid", - } - }) + }, + }); const cnameMap = cnameRecords.reduce((pre, item) => { - pre[item.domain] = item - return pre - }, {}) + pre[item.domain] = item; + return pre; + }, {}); //构建域名验证计划 - const domainVerifiers: DomainVerifiers = {} + const domainVerifiers: DomainVerifiers = {}; for (const domain of domains) { - const mainDomain = mainDomainMap[domain] + const mainDomain = mainDomainMap[domain]; - const dnsRecord = dnsMap[mainDomain] + const dnsRecord = dnsMap[mainDomain]; if (dnsRecord) { domainVerifiers[domain] = { domain, mainDomain, - type: 'dns', + type: "dns", dns: { dnsProviderType: dnsRecord.dnsProviderType, - dnsProviderAccessId: dnsRecord.dnsProviderAccess - } - } - continue + dnsProviderAccessId: dnsRecord.dnsProviderAccess, + }, + }; + continue; } - const cnameRecord: CnameRecordEntity = cnameMap[domain] + const cnameRecord: CnameRecordEntity = cnameMap[domain]; if (cnameRecord) { domainVerifiers[domain] = { domain, mainDomain, - type: 'cname', + type: "cname", cname: { domain: cnameRecord.domain, hostRecord: cnameRecord.hostRecord, - recordValue: cnameRecord.recordValue - } - } - continue + recordValue: cnameRecord.recordValue, + }, + }; + continue; } - const httpRecord = httpMap[domain] + const httpRecord = httpMap[domain]; if (httpRecord) { domainVerifiers[domain] = { domain, mainDomain, - type: 'http', + type: "http", http: { httpUploaderType: httpRecord.httpUploaderType, httpUploaderAccess: httpRecord.httpUploaderAccess, - httpUploadRootDir: httpRecord.httpUploadRootDir - } - } - continue + httpUploadRootDir: httpRecord.httpUploadRootDir, + }, + }; + continue; } - domainVerifiers[domain] = null + domainVerifiers[domain] = null; } return domainVerifiers; } + async startDomainImportTask(req: { userId: number; projectId: number; key: string }) { + const key = req.key; + const setting = await this.userSettingService.getSetting(req.userId, req.projectId, UserDomainImportSetting); - async startDomainImportTask(req: { userId: number, projectId: number, key: string }) { - const key = req.key - const setting = await this.userSettingService.getSetting(req.userId, req.projectId, UserDomainImportSetting) - - const item = setting.domainImportList.find(item => item.key === key) + const item = setting.domainImportList.find(item => item.key === key); if (!item) { - throw new Error(`域名导入任务配置(${key})还未注册`) + throw new Error(`域名导入任务配置(${key})还未注册`); } - const { dnsProviderType, dnsProviderAccessId, title } = item + const { dnsProviderType, dnsProviderAccessId, title } = item; - taskExecutor.start(new BackTask({ - type: DOMAIN_IMPORT_TASK_TYPE, - key, - title: title, - run: async (task: BackTask) => { - await this._syncFromProvider({ - userId: req.userId, - projectId: req.projectId, - dnsProviderType, - dnsProviderAccessId, - }, task) - }, - })) + taskExecutor.start( + new BackTask({ + type: DOMAIN_IMPORT_TASK_TYPE, + key, + title: title, + run: async (task: BackTask) => { + await this._syncFromProvider( + { + userId: req.userId, + projectId: req.projectId, + dnsProviderType, + dnsProviderAccessId, + }, + task + ); + }, + }) + ); } private async _syncFromProvider(req: SyncFromProviderReq, task: BackTask) { @@ -262,28 +262,28 @@ export class DomainService extends BaseService { const serviceGetter = this.taskServiceBuilder.create({ userId, projectId }); const subDomainGetter = await serviceGetter.getSubDomainsGetter(); - const domainParser = new DomainParser(subDomainGetter) + const domainParser = new DomainParser(subDomainGetter); const access = await this.accessService.getById(dnsProviderAccessId, userId, projectId); const context = { access, logger, http, utils, domainParser, serviceGetter }; // 翻页查询dns的记录 - const dnsProvider = await createDnsProvider({ dnsProviderType, context }) + const dnsProvider = await createDnsProvider({ dnsProviderType, context }); const pager = new Pager({ pageNo: 1, pageSize: 100, - }) - const challengeType = "dns" + }); + const challengeType = "dns"; const getPage = async (pager: Pager) => { - return await dnsProvider.getDomainListPage(pager) - } + return await dnsProvider.getDomainListPage(pager); + }; const itemHandle = async (domainRecord: any) => { - task.incrementCurrent() - let domain = domainRecord.domain + task.incrementCurrent(); + let domain = domainRecord.domain; if (domain.endsWith(".")) { - domain = domain.slice(0, -1) + domain = domain.slice(0, -1); } const old = await this.findOne({ @@ -291,8 +291,8 @@ export class DomainService extends BaseService { domain, userId, projectId, - } - }) + }, + }); if (old) { // if (old.fromType !== 'auto') { // //如果是手动的,跳过更新校验配置 @@ -300,17 +300,17 @@ export class DomainService extends BaseService { // } if (old) { //如果old存在,直接跳过 - task.incrementSkip() - return + task.incrementSkip(); + return; } const updateObj: any = { id: old.id, dnsProviderType, dnsProviderAccess: dnsProviderAccessId, challengeType, - } + }; //更新 - await super.update(updateObj) + await super.update(updateObj); } else { //添加 await this.add({ @@ -321,81 +321,80 @@ export class DomainService extends BaseService { dnsProviderAccess: dnsProviderAccessId, challengeType, disabled: false, - fromType: 'manual', - }) - logger.info(`导入域名${domain}到用户${userId}`) + fromType: "manual", + }); + logger.info(`导入域名${domain}到用户${userId}`); } - } + }; const batchHandle = async (pageRes: PageRes) => { - task.setTotal(pageRes.total || 0) - } - await doPageTurn({ pager, getPage, itemHandle, batchHandle }) - const key = `user_${userId || 0}` - logger.info(`从域名提供商${dnsProviderType}导入域名完成(${key}),共导入${task.total}个域名,跳过${task.getSkipCount()}个域名,成功${task.getSuccessCount()}个域名,失败${task.getErrorCount()}个域名`) + task.setTotal(pageRes.total || 0); + }; + await doPageTurn({ pager, getPage, itemHandle, batchHandle }); + const key = `user_${userId || 0}`; + logger.info(`从域名提供商${dnsProviderType}导入域名完成(${key}),共导入${task.total}个域名,跳过${task.getSkipCount()}个域名,成功${task.getSuccessCount()}个域名,失败${task.getErrorCount()}个域名`); } - async getDomainImportTaskStatus(req: { userId?: number, projectId?: number }) { - const userId = req.userId || 0 - const projectId = req.projectId + async getDomainImportTaskStatus(req: { userId?: number; projectId?: number }) { + const userId = req.userId || 0; + const projectId = req.projectId; - const setting = await this.userSettingService.getSetting(userId, projectId, UserDomainImportSetting) - const list = setting?.domainImportList || [] + const setting = await this.userSettingService.getSetting(userId, projectId, UserDomainImportSetting); + const list = setting?.domainImportList || []; - const taskList: any = [] + const taskList: any = []; for (const item of list) { - const { key } = item + const { key } = item; - const task = taskExecutor.get(DOMAIN_IMPORT_TASK_TYPE, key) + const task = taskExecutor.get(DOMAIN_IMPORT_TASK_TYPE, key); taskList.push({ ...item, task: task, - }) + }); } - return taskList + return taskList; } - async getProviderTitle(req: { userId?: number, projectId?: number, dnsProviderType: string, dnsProviderAccessId: number }) { - const userId = req.userId || 0 - const projectId = req.projectId - const { dnsProviderType, dnsProviderAccessId } = req - const dnsProviderDefine = dnsProviderRegistry.getDefine(dnsProviderType) + async getProviderTitle(req: { userId?: number; projectId?: number; dnsProviderType: string; dnsProviderAccessId: number }) { + const userId = req.userId || 0; + const projectId = req.projectId; + const { dnsProviderType, dnsProviderAccessId } = req; + const dnsProviderDefine = dnsProviderRegistry.getDefine(dnsProviderType); if (!dnsProviderDefine) { - throw new Error(`该域名提供商(${dnsProviderType})不存在,请检查是否已被注册`) + throw new Error(`该域名提供商(${dnsProviderType})不存在,请检查是否已被注册`); } - const access = await this.accessService.getSimpleInfo(dnsProviderAccessId) + const access = await this.accessService.getSimpleInfo(dnsProviderAccessId); if (!access || access.userId !== userId) { - throw new Error(`该授权(${dnsProviderAccessId})不存在,请检查是否已被删除`) + throw new Error(`该授权(${dnsProviderAccessId})不存在,请检查是否已被删除`); } if (projectId && access.projectId !== projectId) { - throw new Error(`该授权(${dnsProviderAccessId})不存在,请检查是否已被删除`) + throw new Error(`该授权(${dnsProviderAccessId})不存在,请检查是否已被删除`); } return { - title: `${dnsProviderDefine.title}_${access.name || ''}`, + title: `${dnsProviderDefine.title}_${access.name || ""}`, //@ts-ignore - icon: dnsProviderDefine.icon || '', - } + icon: dnsProviderDefine.icon || "", + }; } - async addDomainImportTask(req: { userId?: number, projectId?: number, dnsProviderType: string, dnsProviderAccessId: number, index?: number }) { - const userId = req.userId || 0 - const projectId = req.projectId - const { dnsProviderType, dnsProviderAccessId, index = 0 } = req - const key = `user_${userId}_${dnsProviderType}_${dnsProviderAccessId}` + async addDomainImportTask(req: { userId?: number; projectId?: number; dnsProviderType: string; dnsProviderAccessId: number; index?: number }) { + const userId = req.userId || 0; + const projectId = req.projectId; + const { dnsProviderType, dnsProviderAccessId, index = 0 } = req; + const key = `user_${userId}_${dnsProviderType}_${dnsProviderAccessId}`; - const { title, icon } = await this.getProviderTitle(req) + const { title, icon } = await this.getProviderTitle(req); - - const setting = await this.userSettingService.getSetting(userId, projectId, UserDomainImportSetting) - setting.domainImportList = setting.domainImportList || [] + const setting = await this.userSettingService.getSetting(userId, projectId, UserDomainImportSetting); + setting.domainImportList = setting.domainImportList || []; if (setting.domainImportList.find(item => item.key === key)) { - throw new Error(`该域名导入任务${key}已存在`) + throw new Error(`该域名导入任务${key}已存在`); } - const access = await this.accessService.getAccessById(dnsProviderAccessId, true, userId, projectId) + const access = await this.accessService.getAccessById(dnsProviderAccessId, true, userId, projectId); if (!access) { - throw new Error(`该授权(${dnsProviderAccessId})不存在,请检查是否已被删除`) + throw new Error(`该授权(${dnsProviderAccessId})不存在,请检查是否已被删除`); } const item = { @@ -403,100 +402,98 @@ export class DomainService extends BaseService { dnsProviderAccessId, key, title, - icon: icon || '', - } - setting.domainImportList.splice(index, 0, item) - await this.userSettingService.saveSetting(userId, projectId, setting) + icon: icon || "", + }; + setting.domainImportList.splice(index, 0, item); + await this.userSettingService.saveSetting(userId, projectId, setting); - return item + return item; } - async deleteDomainImportTask(req: { userId?: number, projectId?: number, key: string }) { - const userId = req.userId || 0 - const { key } = req + async deleteDomainImportTask(req: { userId?: number; projectId?: number; key: string }) { + const userId = req.userId || 0; + const { key } = req; - const projectId = req.projectId - const setting = await this.userSettingService.getSetting(userId, projectId, UserDomainImportSetting) - setting.domainImportList = setting.domainImportList || [] - const index = setting.domainImportList.findIndex(item => item.key === key) + const projectId = req.projectId; + const setting = await this.userSettingService.getSetting(userId, projectId, UserDomainImportSetting); + setting.domainImportList = setting.domainImportList || []; + const index = setting.domainImportList.findIndex(item => item.key === key); if (index === -1) { - throw new Error(`该域名导入任务${key}不存在`) + throw new Error(`该域名导入任务${key}不存在`); } - setting.domainImportList.splice(index, 1) - taskExecutor.clear(DOMAIN_IMPORT_TASK_TYPE, key) - await this.userSettingService.saveSetting(userId, projectId, setting) + setting.domainImportList.splice(index, 1); + taskExecutor.clear(DOMAIN_IMPORT_TASK_TYPE, key); + await this.userSettingService.saveSetting(userId, projectId, setting); } - async saveDomainImportTask(req: { userId?: number, projectId?: number, dnsProviderType: string, dnsProviderAccessId: number, key?: string }) { - const userId = req.userId || 0 - const projectId = req.projectId - const { dnsProviderType, dnsProviderAccessId, key } = req - const setting = await this.userSettingService.getSetting(userId, projectId, UserDomainImportSetting) - setting.domainImportList = setting.domainImportList || [] + async saveDomainImportTask(req: { userId?: number; projectId?: number; dnsProviderType: string; dnsProviderAccessId: number; key?: string }) { + const userId = req.userId || 0; + const projectId = req.projectId; + const { dnsProviderType, dnsProviderAccessId, key } = req; + const setting = await this.userSettingService.getSetting(userId, projectId, UserDomainImportSetting); + setting.domainImportList = setting.domainImportList || []; - let index = 0 + let index = 0; if (key) { - index = setting.domainImportList.findIndex(item => item.key === key) + index = setting.domainImportList.findIndex(item => item.key === key); if (index === -1) { - throw new Error(`该域名导入任务${key}不存在`) + throw new Error(`该域名导入任务${key}不存在`); } - await this.deleteDomainImportTask({ userId, projectId, key }) + await this.deleteDomainImportTask({ userId, projectId, key }); } - return await this.addDomainImportTask({ userId, projectId, dnsProviderType, dnsProviderAccessId, index }) + return await this.addDomainImportTask({ userId, projectId, dnsProviderType, dnsProviderAccessId, index }); } - - - - async getSyncExpirationTaskStatus(req: { userId?: number, projectId?: number }) { - const userId = req.userId ?? 'all' - const projectId = req.projectId - let key = `user_${userId}` + async getSyncExpirationTaskStatus(req: { userId?: number; projectId?: number }) { + const userId = req.userId ?? "all"; + const projectId = req.projectId; + let key = `user_${userId}`; if (projectId != null) { - key += `_${projectId}` + key += `_${projectId}`; } - const task = taskExecutor.get(DOMAIN_EXPIRE_TASK_TYPE, key) - return task + const task = taskExecutor.get(DOMAIN_EXPIRE_TASK_TYPE, key); + return task; } - async startSyncExpirationTask(req: { userId?: number, projectId?: number }) { - const userId = req.userId - const projectId = req.projectId - let key = `user_${userId ?? 'all'}` + async startSyncExpirationTask(req: { userId?: number; projectId?: number }) { + const userId = req.userId; + const projectId = req.projectId; + let key = `user_${userId ?? "all"}`; if (projectId != null) { - key += `_${projectId}` + key += `_${projectId}`; } - taskExecutor.start(new BackTask({ - type: DOMAIN_EXPIRE_TASK_TYPE, - key, - title: `同步注册域名过期时间(${key}))`, - run: async (task: BackTask) => { - await this._syncDomainsExpirationDate({ userId, projectId, task }) - if (userId != null) { - await this.startCheckDomainExpiration({ userId, projectId }) - } - } - })) + taskExecutor.start( + new BackTask({ + type: DOMAIN_EXPIRE_TASK_TYPE, + key, + title: `同步注册域名过期时间(${key}))`, + run: async (task: BackTask) => { + await this._syncDomainsExpirationDate({ userId, projectId, task }); + if (userId != null) { + await this.startCheckDomainExpiration({ userId, projectId }); + } + }, + }) + ); } - private async _syncDomainsExpirationDate(req: { userId?: number, projectId?: number, task: BackTask }) { - + private async _syncDomainsExpirationDate(req: { userId?: number; projectId?: number; task: BackTask }) { //同步所有域名的过期时间 const pager = new Pager({ pageNo: 1, pageSize: 100, - }) + }); const tldClient = new TldClient(); const query: any = { challengeType: "dns", - } + }; if (req.userId != null) { - query.userId = req.userId + query.userId = req.userId; } if (req.projectId != null) { - query.projectId = req.projectId + query.projectId = req.projectId; } const getDomainPage = async (pager: Pager) => { const pageRes = await this.page({ @@ -507,62 +504,61 @@ export class DomainService extends BaseService { page: { offset: pager.getOffset(), limit: pager.pageSize, - } - }) - req.task.total = pageRes.total + }, + }); + req.task.total = pageRes.total; return { list: pageRes.records, total: pageRes.total, - } - } + }; + }; const itemHandle = async (item: any) => { - req.task.incrementCurrent() + req.task.incrementCurrent(); try { - const res = await tldClient.getDomainExpirationDate(item.domain) - const { expirationDate, registrationDate } = res + const res = await tldClient.getDomainExpirationDate(item.domain); + const { expirationDate, registrationDate } = res; if (!expirationDate) { - req.task.addError(`【${item.domain}】获取域名${item.domain}过期时间失败`) - return + req.task.addError(`【${item.domain}】获取域名${item.domain}过期时间失败`); + return; } - logger.info(`【${item.domain}】更新域名过期时间:${dayjs(expirationDate).format('YYYY-MM-DD')}`) + logger.info(`【${item.domain}】更新域名过期时间:${dayjs(expirationDate).format("YYYY-MM-DD")}`); const updateObj: any = { id: item.id, expirationDate: expirationDate, registrationDate: registrationDate, - } + }; //更新 - await super.update(updateObj) + await super.update(updateObj); } catch (error) { - const errorMsg = `【${item.domain}】${error.message ?? error}` - req.task.addError(errorMsg) - logger.error(errorMsg) + const errorMsg = `【${item.domain}】${error.message ?? error}`; + req.task.addError(errorMsg); + logger.error(errorMsg); } finally { - await utils.sleep(1000) + await utils.sleep(1000); } - } + }; - await doPageTurn({ pager, getPage: getDomainPage, itemHandle: itemHandle }) - const key = `user_${req.userId || 'all'}` - const log = `同步用户(${key})注册域名过期时间完成(${req.task.getSuccessCount()}个成功,${req.task.getErrorCount()}个失败)` - logger.info(log) + await doPageTurn({ pager, getPage: getDomainPage, itemHandle: itemHandle }); + const key = `user_${req.userId || "all"}`; + const log = `同步用户(${key})注册域名过期时间完成(${req.task.getSuccessCount()}个成功,${req.task.getErrorCount()}个失败)`; + logger.info(log); } - - public async startCheckDomainExpiration(req: { userId?: number, projectId?: number }) { - const { userId, projectId } = req + public async startCheckDomainExpiration(req: { userId?: number; projectId?: number }) { + const { userId, projectId } = req; if (userId == null) { - throw new Error('userId is required'); + throw new Error("userId is required"); } if (projectId && !isEnterprise()) { - logger.warn(`当前未开启企业模式,跳过检查项目(${projectId})的域名过期时间`) - return + logger.warn(`当前未开启企业模式,跳过检查项目(${projectId})的域名过期时间`); + return; } - const setting = await this.monitorSettingGet({ userId, projectId }) + const setting = await this.monitorSettingGet({ userId, projectId }); if (!setting || !setting.enabled) { - return + return; } const jobHistory: any = { @@ -572,46 +568,46 @@ export class DomainService extends BaseService { title: `检查注册域名过期时间`, startAt: dayjs().valueOf(), result: "start", - } - await this.jobHistoryService.add(jobHistory) + }; + await this.jobHistoryService.add(jobHistory); - const expireDays = setting.willExpireDays || 30 - const ltTime = dayjs().add(expireDays, 'day').valueOf() + const expireDays = setting.willExpireDays || 30; + const ltTime = dayjs().add(expireDays, "day").valueOf(); const total = await this.repository.count({ - where:{ + where: { userId, projectId, disabled: false, - } - }) + }, + }); //开始检查域名过期时间 const list = await this.repository.find({ where: { userId, projectId, disabled: false, - expirationDate: LessThan(ltTime) - } - }) + expirationDate: LessThan(ltTime), + }, + }); - const now = dayjs().valueOf() - let willExpireDomains = [] - let hasExpireDomains = [] + const now = dayjs().valueOf(); + const willExpireDomains = []; + const hasExpireDomains = []; for (const item of list) { - const { expirationDate } = item - const leftDays = dayjs(expirationDate).diff(dayjs(), 'day') + const { expirationDate } = item; + const leftDays = dayjs(expirationDate).diff(dayjs(), "day"); //@ts-ignore - item.leftDays = leftDays + item.leftDays = leftDays; if (expirationDate < now) { - hasExpireDomains.push(item) + hasExpireDomains.push(item); } else { - willExpireDomains.push(item) + willExpireDomains.push(item); } } - const title = `域名过期检查:即将过期 ${willExpireDomains.length} 个域名,已过期 ${hasExpireDomains.length} 个域名,共 ${total} 个域名` + const title = `域名过期检查:即将过期 ${willExpireDomains.length} 个域名,已过期 ${hasExpireDomains.length} 个域名,共 ${total} 个域名`; try { await this.jobHistoryService.update({ @@ -619,30 +615,29 @@ export class DomainService extends BaseService { content: title, result: "done", endAt: dayjs().valueOf(), - }) - + }); } catch (error) { - logger.error(`更新域名过期检查任务状态失败:${error.message ?? error}`) + logger.error(`更新域名过期检查任务状态失败:${error.message ?? error}`); } if (list.length == 0) { //没有过期域名 不发通知 - return + return; } //发送通知 - const willExpireDomainsStr = willExpireDomains.map(item => `${item.domain} (剩余${item.leftDays}天)`).join('\n ') - const hasExpireDomainsStr = hasExpireDomains.map(item => `${item.domain} (已过期${item.leftDays}天)`).join('\n ') + const willExpireDomainsStr = willExpireDomains.map(item => `${item.domain} (剩余${item.leftDays}天)`).join("\n "); + const hasExpireDomainsStr = hasExpireDomains.map(item => `${item.domain} (已过期${item.leftDays}天)`).join("\n "); const content = `您有域名即将过期,请尽快续费 即将过期域名: ${willExpireDomains.length} 个 (有效期<${expireDays}天) ${willExpireDomainsStr} 已过期域名: ${hasExpireDomains.length} 个 - ${hasExpireDomainsStr}` + ${hasExpireDomainsStr}`; const taskService = this.taskServiceBuilder.create({ userId: userId, projectId: projectId }); - const notificationService = await taskService.getNotificationService() + const notificationService = await taskService.getNotificationService(); const url = await notificationService.getBindUrl("#/certd/cert/domain"); await notificationService.send({ id: setting.notificationId, @@ -656,39 +651,37 @@ export class DomainService extends BaseService { notificationType: DOMAIN_EXPIRE_CHECK_TYPE, willExpireDomains, hasExpireDomains, - } - }) - + }, + }); } - - public async monitorSettingGet(req: { userId?: number, projectId?: number }) { - const { userId, projectId } = req - const setting = await this.userSettingService.getSetting(userId, projectId, UserDomainMonitorSetting) - return setting || {} + public async monitorSettingGet(req: { userId?: number; projectId?: number }) { + const { userId, projectId } = req; + const setting = await this.userSettingService.getSetting(userId, projectId, UserDomainMonitorSetting); + return setting || {}; } - public async monitorSettingSave(req: { userId?: number, projectId?: number, setting?: any }) { - const { userId, projectId, setting } = req - const bean: UserDomainMonitorSetting = new UserDomainMonitorSetting() - merge(bean, setting) - await this.userSettingService.saveSetting(userId, projectId, bean) - await this.registerMonitorCron({ userId, projectId }) + public async monitorSettingSave(req: { userId?: number; projectId?: number; setting?: any }) { + const { userId, projectId, setting } = req; + const bean: UserDomainMonitorSetting = new UserDomainMonitorSetting(); + merge(bean, setting); + await this.userSettingService.saveSetting(userId, projectId, bean); + await this.registerMonitorCron({ userId, projectId }); } - public async registerMonitorCron(req: { userId?: number, projectId?: number }) { - const { userId, projectId } = req - const setting = await this.monitorSettingGet(req) - const key = `${DOMAIN_EXPIRE_CHECK_TYPE}:${userId}_${projectId || ''}` - this.cron.remove(key) + public async registerMonitorCron(req: { userId?: number; projectId?: number }) { + const { userId, projectId } = req; + const setting = await this.monitorSettingGet(req); + const key = `${DOMAIN_EXPIRE_CHECK_TYPE}:${userId}_${projectId || ""}`; + this.cron.remove(key); if (setting.enabled) { this.cron.register({ cron: setting.cron, name: key, job: async () => { - await this.startCheckDomainExpiration({ userId, projectId }) + await this.startCheckDomainExpiration({ userId, projectId }); }, - }) + }); } } } diff --git a/packages/ui/certd-server/src/modules/cert/service/tld-client.ts b/packages/ui/certd-server/src/modules/cert/service/tld-client.ts index ee277ac7b..e9d0b06dd 100644 --- a/packages/ui/certd-server/src/modules/cert/service/tld-client.ts +++ b/packages/ui/certd-server/src/modules/cert/service/tld-client.ts @@ -73,7 +73,7 @@ export class TldClient { method: "GET", }); - let res: DomainInfo = {}; + const res: DomainInfo = {}; const events = rdap.events || []; for (const item of events) { if (item.eventAction === "expiration") { @@ -96,7 +96,7 @@ export class TldClient { timeout: 5000, }); - let res: DomainInfo = {}; + const res: DomainInfo = {}; /** * { "Domain Status": [ diff --git a/packages/ui/certd-server/src/modules/cname/entity/cname-provider.ts b/packages/ui/certd-server/src/modules/cname/entity/cname-provider.ts index 956ef8f16..6ae3782e4 100644 --- a/packages/ui/certd-server/src/modules/cname/entity/cname-provider.ts +++ b/packages/ui/certd-server/src/modules/cname/entity/cname-provider.ts @@ -1,39 +1,39 @@ -import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; +import { Column, Entity, PrimaryGeneratedColumn } from "typeorm"; /** * cname配置 */ -@Entity('cd_cname_provider') +@Entity("cd_cname_provider") export class CnameProviderEntity { @PrimaryGeneratedColumn() id: number; - @Column({ comment: 'userId', name: 'user_id' }) + @Column({ comment: "userId", name: "user_id" }) userId: number; - @Column({ comment: '域名', length: 100 }) + @Column({ comment: "域名", length: 100 }) domain: string; - @Column({ comment: '子域名托管', length: 100, nullable: true }) + @Column({ comment: "子域名托管", length: 100, nullable: true }) subdomain: string; - @Column({ comment: 'DNS提供商类型', name: 'dns_provider_type', length: 20 }) + @Column({ comment: "DNS提供商类型", name: "dns_provider_type", length: 20 }) dnsProviderType: string; - @Column({ comment: 'DNS授权Id', name: 'access_id' }) + @Column({ comment: "DNS授权Id", name: "access_id" }) accessId: number; - @Column({ comment: '是否默认', name: 'is_default' }) + @Column({ comment: "是否默认", name: "is_default" }) isDefault: boolean; - @Column({ comment: '是否禁用', name: 'disabled' }) + @Column({ comment: "是否禁用", name: "disabled" }) disabled: boolean; - @Column({ comment: '备注', length: 200 }) + @Column({ comment: "备注", length: 200 }) remark: string; @Column({ - comment: '创建时间', - name: 'create_time', - default: () => 'CURRENT_TIMESTAMP', + comment: "创建时间", + name: "create_time", + default: () => "CURRENT_TIMESTAMP", }) createTime: Date; @Column({ - comment: '修改时间', - name: 'update_time', - default: () => 'CURRENT_TIMESTAMP', + comment: "修改时间", + name: "update_time", + default: () => "CURRENT_TIMESTAMP", }) updateTime: Date; diff --git a/packages/ui/certd-server/src/modules/cname/entity/cname-record.ts b/packages/ui/certd-server/src/modules/cname/entity/cname-record.ts index a1494d464..7b20ca169 100644 --- a/packages/ui/certd-server/src/modules/cname/entity/cname-record.ts +++ b/packages/ui/certd-server/src/modules/cname/entity/cname-record.ts @@ -1,49 +1,49 @@ -import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; -export type CnameRecordStatusType = 'cname' | 'validating' | 'valid' | 'error' | 'timeout'; +import { Column, Entity, PrimaryGeneratedColumn } from "typeorm"; +export type CnameRecordStatusType = "cname" | "validating" | "valid" | "error" | "timeout"; /** * cname record配置 */ -@Entity('cd_cname_record') +@Entity("cd_cname_record") export class CnameRecordEntity { @PrimaryGeneratedColumn() id: number; - @Column({ comment: '用户ID', name: 'user_id' }) + @Column({ comment: "用户ID", name: "user_id" }) userId: number; - @Column({ comment: '证书申请域名', length: 100 }) + @Column({ comment: "证书申请域名", length: 100 }) domain: string; - @Column({ comment: '主域名', name: 'main_domain', length: 100 }) - mainDomain:string; + @Column({ comment: "主域名", name: "main_domain", length: 100 }) + mainDomain: string; - @Column({ comment: '主机记录', name: 'host_record', length: 100 }) + @Column({ comment: "主机记录", name: "host_record", length: 100 }) hostRecord: string; - @Column({ comment: '记录值', name: 'record_value', length: 200 }) + @Column({ comment: "记录值", name: "record_value", length: 200 }) recordValue: string; - @Column({ comment: 'CNAME提供者', name: 'cname_provider_id' }) + @Column({ comment: "CNAME提供者", name: "cname_provider_id" }) cnameProviderId: number; - @Column({ comment: '验证状态', length: 20 }) + @Column({ comment: "验证状态", length: 20 }) status: string; - @Column({ comment: '错误信息' }) - error: string + @Column({ comment: "错误信息" }) + error: string; - @Column({ name: 'project_id', comment: '项目Id' }) + @Column({ name: "project_id", comment: "项目Id" }) projectId: number; @Column({ - comment: '创建时间', - name: 'create_time', - default: () => 'CURRENT_TIMESTAMP', + comment: "创建时间", + name: "create_time", + default: () => "CURRENT_TIMESTAMP", }) createTime: Date; @Column({ - comment: '修改时间', - name: 'update_time', - default: () => 'CURRENT_TIMESTAMP', + comment: "修改时间", + name: "update_time", + default: () => "CURRENT_TIMESTAMP", }) updateTime: Date; } diff --git a/packages/ui/certd-server/src/modules/cname/service/cname-provider-service.ts b/packages/ui/certd-server/src/modules/cname/service/cname-provider-service.ts index ca452079a..ac52c1192 100644 --- a/packages/ui/certd-server/src/modules/cname/service/cname-provider-service.ts +++ b/packages/ui/certd-server/src/modules/cname/service/cname-provider-service.ts @@ -1,9 +1,9 @@ -import { Inject, Provide, Scope, ScopeEnum } from '@midwayjs/core'; -import { InjectEntityModel } from '@midwayjs/typeorm'; -import { Repository } from 'typeorm'; -import { BaseService, ListReq, SysPrivateSettings, SysSettingsService, ValidateException } from '@certd/lib-server'; -import { CnameProviderEntity } from '../entity/cname-provider.js'; -import { CommonProviders } from './common-provider.js'; +import { Inject, Provide, Scope, ScopeEnum } from "@midwayjs/core"; +import { InjectEntityModel } from "@midwayjs/typeorm"; +import { Repository } from "typeorm"; +import { BaseService, ListReq, SysPrivateSettings, SysSettingsService, ValidateException } from "@certd/lib-server"; +import { CnameProviderEntity } from "../entity/cname-provider.js"; +import { CommonProviders } from "./common-provider.js"; /** * 授权 @@ -63,7 +63,7 @@ export class CnameProviderService extends BaseService { for (const id of ids) { const info = await this.info(id); if (info.isDefault) { - throw new ValidateException('默认的CNAME服务不能删除,请先修改为非默认值'); + throw new ValidateException("默认的CNAME服务不能删除,请先修改为非默认值"); } } await super.delete(ids); @@ -85,7 +85,7 @@ export class CnameProviderService extends BaseService { if (def) { return def; } - const founds = await this.repository.find({ take: 1, order: { createTime: 'DESC' }, where: { disabled: false } }); + const founds = await this.repository.find({ take: 1, order: { createTime: "DESC" }, where: { disabled: false } }); if (founds && founds.length > 0) { return founds[0]; } @@ -127,5 +127,4 @@ export class CnameProviderService extends BaseService { } return await super.info(id, infoIgnoreProperty); } - } diff --git a/packages/ui/certd-server/src/modules/cname/service/cname-record-service.ts b/packages/ui/certd-server/src/modules/cname/service/cname-record-service.ts index a71281da8..30f2f7e1a 100644 --- a/packages/ui/certd-server/src/modules/cname/service/cname-record-service.ts +++ b/packages/ui/certd-server/src/modules/cname/service/cname-record-service.ts @@ -1,13 +1,6 @@ import { createChallengeFn, getAuthoritativeDnsResolver } from "@certd/acme-client"; import { cache, http, isDev, logger, utils } from "@certd/basic"; -import { - AccessService, - BaseService, - PlusService, - SysInstallInfo, - SysSettingsService, - ValidateException -} from "@certd/lib-server"; +import { AccessService, BaseService, PlusService, SysInstallInfo, SysSettingsService, ValidateException } from "@certd/lib-server"; import { CnameProvider, CnameRecord } from "@certd/pipeline"; import { createDnsProvider, DomainParser, IDnsProvider } from "@certd/plugin-cert"; import { Inject, Provide, Scope, ScopeEnum } from "@midwayjs/core"; @@ -58,7 +51,6 @@ export class CnameRecordService extends BaseService { @Inject() taskServiceBuilder: TaskServiceBuilder; - //@ts-ignore getRepository() { return this.repository; @@ -135,7 +127,7 @@ export class CnameRecordService extends BaseService { throw new ValidateException("id不能为空"); } //hostRecord包含所有权校验信息,不允许用户修改hostRecord - delete param.hostRecord + delete param.hostRecord; const old = await this.info(param.id); if (!old) { @@ -164,32 +156,32 @@ export class CnameRecordService extends BaseService { // // 3. 检查原域名是否有cname记录 // } - async getWithAccessByDomain(domain: string, userId: number,projectId?:number) { - const record: CnameRecord = await this.getByDomain(domain, userId,projectId); + async getWithAccessByDomain(domain: string, userId: number, projectId?: number) { + const record: CnameRecord = await this.getByDomain(domain, userId, projectId); if (record.cnameProvider.id > 0) { //自定义cname服务 record.cnameProvider.access = await this.accessService.getAccessById(record.cnameProvider.accessId, false); } else { record.commonDnsProvider = new CommonDnsProvider({ config: record.cnameProvider, - plusService: this.plusService + plusService: this.plusService, }); } return record; } - async getByDomain(domain: string, userId: number,projectId?:number, createOnNotFound = true) { + async getByDomain(domain: string, userId: number, projectId?: number, createOnNotFound = true) { if (!domain) { throw new ValidateException("domain不能为空"); } if (userId == null) { throw new ValidateException("userId不能为空"); } - let record = await this.getRepository().findOne({ where: { domain, userId,projectId } }); + let record = await this.getRepository().findOne({ where: { domain, userId, projectId } }); if (record == null) { if (createOnNotFound) { - record = await this.add({ domain, userId,projectId }); + record = await this.add({ domain, userId, projectId }); } else { throw new ValidateException(`找不到${domain}的CNAME记录`); } @@ -205,8 +197,8 @@ export class CnameRecordService extends BaseService { return { ...record, cnameProvider: { - ...provider - } as CnameProvider + ...provider, + } as CnameProvider, } as CnameRecord; } @@ -222,17 +214,16 @@ export class CnameRecordService extends BaseService { if (domainPrefix) { const prefixStr = domainPrefix + "."; record.mainDomain = record.domain.substring(prefixStr.length); - }else{ + } else { record.mainDomain = record.domain; } if (update) { await this.update({ id: record.id, - mainDomain: record.mainDomain + mainDomain: record.mainDomain, }); } - } } @@ -241,8 +232,7 @@ export class CnameRecordService extends BaseService { * @param id */ async verify(id: number) { - - const {walkTxtRecord} = createChallengeFn({logger}); + const { walkTxtRecord } = createChallengeFn({ logger }); const bean = await this.info(id); if (!bean) { throw new ValidateException(`CnameRecord:${id} 不存在`); @@ -251,7 +241,7 @@ export class CnameRecordService extends BaseService { return true; } - await this.getByDomain(bean.domain, bean.userId,bean.projectId); + await this.getByDomain(bean.domain, bean.userId, bean.projectId); const taskService = this.taskServiceBuilder.create({ userId: bean.userId, projectId: bean.projectId }); const subDomainGetter = await taskService.getSubDomainsGetter(); const domainParser = new DomainParser(subDomainGetter); @@ -263,7 +253,7 @@ export class CnameRecordService extends BaseService { value = { validating: false, pass: false, - startTime: new Date().getTime() + startTime: new Date().getTime(), }; } let ttl = 5 * 60 * 1000; @@ -285,17 +275,17 @@ export class CnameRecordService extends BaseService { //公共CNAME return new CommonDnsProvider({ config: cnameProvider, - plusService: this.plusService + plusService: this.plusService, }); } - const record = await this.getWithAccessByDomain(bean.domain, bean.userId,bean.projectId); + const record = await this.getWithAccessByDomain(bean.domain, bean.userId, bean.projectId); - const access = record.cnameProvider.access - const context = { access, logger, http, utils, domainParser, serviceGetter:taskService }; + const access = record.cnameProvider.access; + const context = { access, logger, http, utils, domainParser, serviceGetter: taskService }; const dnsProvider: IDnsProvider = await createDnsProvider({ dnsProviderType: cnameProvider.dnsProviderType, - context + context, }); return dnsProvider; }; @@ -309,7 +299,7 @@ export class CnameRecordService extends BaseService { } await dnsProvider.removeRecord({ recordReq: value.recordReq, - recordRes: value.recordRes + recordRes: value.recordRes, }); logger.info("删除CNAME的校验DNS记录成功"); } catch (e) { @@ -329,7 +319,6 @@ export class CnameRecordService extends BaseService { return false; } - const originDomain = await domainParser.parse(bean.domain); const fullDomain = `${bean.hostRecord}.${originDomain}`; @@ -366,7 +355,7 @@ export class CnameRecordService extends BaseService { } cache.set(cacheKey, value, { - ttl: ttl + ttl: ttl, }); const domain = await domainParser.parse(bean.recordValue); @@ -377,7 +366,7 @@ export class CnameRecordService extends BaseService { fullRecord: fullRecord, hostRecord: hostRecord, type: "TXT", - value: testRecordValue + value: testRecordValue, }; const dnsProvider = await buildDnsProvider(); @@ -418,8 +407,6 @@ export class CnameRecordService extends BaseService { } async checkRepeatAcmeChallengeRecords(acmeRecordDomain: string, targetCnameDomain: string) { - - let dnsResolver = null; try { dnsResolver = await getAuthoritativeDnsResolver(acmeRecordDomain); @@ -443,7 +430,6 @@ export class CnameRecordService extends BaseService { throw new Error(`${acmeRecordDomain}存在多个CNAME记录,请删除多余的CNAME记录:${cnameRecord}`); } } - } // 确保权威服务器里面没有纯粹的TXT记录 @@ -465,7 +451,7 @@ export class CnameRecordService extends BaseService { return; } - const {walkTxtRecord} = createChallengeFn({logger}); + const { walkTxtRecord } = createChallengeFn({ logger }); if (cnameRecords.length > 0) { // 从cname记录中获取txt记录 @@ -479,7 +465,6 @@ export class CnameRecordService extends BaseService { } } } - } async resetStatus(id: number) { @@ -489,27 +474,32 @@ export class CnameRecordService extends BaseService { await this.getRepository().update(id, { status: "cname", mainDomain: "" }); } - async doImport(req:{ userId: number; projectId: number; domainList: string; cnameProviderId: any }) { - const {userId,projectId,cnameProviderId,domainList} = req; - const domains = domainList.split("\n").map(item => item.trim()).filter(item => item.length > 0); + async doImport(req: { userId: number; projectId: number; domainList: string; cnameProviderId: any }) { + const { userId, projectId, cnameProviderId, domainList } = req; + const domains = domainList + .split("\n") + .map(item => item.trim()) + .filter(item => item.length > 0); if (domains.length === 0) { throw new ValidateException("域名列表不能为空"); } if (!req.cnameProviderId) { throw new ValidateException("CNAME服务提供商不能为空"); } - - taskExecutor.start(new BackTask({ - type:"cnameImport", - key: "user_"+userId, - title: "导入CNAME记录", - run: async (task) => { - await this._import({ userId,projectId, domains, cnameProviderId },task); - } - })); + + taskExecutor.start( + new BackTask({ + type: "cnameImport", + key: "user_" + userId, + title: "导入CNAME记录", + run: async task => { + await this._import({ userId, projectId, domains, cnameProviderId }, task); + }, + }) + ); } - async _import(req :{ userId: number; projectId: number; domains: string[]; cnameProviderId: any },task:BackTask) { + async _import(req: { userId: number; projectId: number; domains: string[]; cnameProviderId: any }, task: BackTask) { const userId = req.userId; for (const domain of req.domains) { const old = await this.getRepository().findOne({ @@ -523,17 +513,16 @@ export class CnameRecordService extends BaseService { logger.warn(`域名${domain}已存在,跳过`); } //开始导入 - try{ - await this.add({ - userId, - domain: domain, - projectId: req.projectId, - cnameProviderId: req.cnameProviderId, - }); - }catch(e){ + try { + await this.add({ + userId, + domain: domain, + projectId: req.projectId, + cnameProviderId: req.cnameProviderId, + }); + } catch (e) { logger.error(`导入域名${domain}失败:${e.message}`); } } - } } diff --git a/packages/ui/certd-server/src/modules/cname/service/common-provider.ts b/packages/ui/certd-server/src/modules/cname/service/common-provider.ts index ef9642c4b..d3cb9db95 100644 --- a/packages/ui/certd-server/src/modules/cname/service/common-provider.ts +++ b/packages/ui/certd-server/src/modules/cname/service/common-provider.ts @@ -1,7 +1,7 @@ -import {CreateRecordOptions, DnsProviderContext, DomainRecord, IDnsProvider, RemoveRecordOptions} from '@certd/plugin-cert'; -import {PlusService} from '@certd/lib-server'; -import punycode from 'punycode.js' -import { Pager, PageRes } from '@certd/pipeline'; +import { CreateRecordOptions, DnsProviderContext, DomainRecord, IDnsProvider, RemoveRecordOptions } from "@certd/plugin-cert"; +import { PlusService } from "@certd/lib-server"; +import punycode from "punycode.js"; +import { Pager, PageRes } from "@certd/pipeline"; export type CommonCnameProvider = { id: number; domain: string; @@ -10,8 +10,8 @@ export type CommonCnameProvider = { export const CommonProviders = [ { id: -1, - domain: 'cname.certd.com.cn', - title: '公共CNAME服务', + domain: "cname.certd.com.cn", + title: "公共CNAME服务", }, ]; @@ -25,7 +25,7 @@ export class CommonDnsProvider implements IDnsProvider { this.plusService = opts.plusService; } getDomainListPage(pager: Pager): Promise> { - throw new Error('公共CNAME服务不支持获取域名列表'); + throw new Error("公共CNAME服务不支持获取域名列表"); } /** @@ -44,24 +44,22 @@ export class CommonDnsProvider implements IDnsProvider { return punycode.decode(domain); } - usePunyCode(): boolean { - return false + return false; } - async onInstance() { - } + async onInstance() {} async createRecord(options: CreateRecordOptions) { if (!this.config.domain.endsWith(options.domain)) { - throw new Error('cname服务域名不匹配'); + throw new Error("cname服务域名不匹配"); } await this.plusService.register(); const res = await this.plusService.requestWithToken({ - url: '/activation/certd/cname/recordCreate', - method: 'post', + url: "/activation/certd/cname/recordCreate", + method: "post", data: { subjectId: await this.plusService.getSubjectId(), domain: options.domain, @@ -75,8 +73,8 @@ export class CommonDnsProvider implements IDnsProvider { async removeRecord(options: RemoveRecordOptions) { const res = await this.plusService.requestWithToken({ - url: '/activation/certd/cname/recordRemove', - method: 'post', + url: "/activation/certd/cname/recordRemove", + method: "post", data: { subjectId: await this.plusService.getSubjectId(), domain: options.recordReq.domain, diff --git a/packages/ui/certd-server/src/modules/cron/configuration.ts b/packages/ui/certd-server/src/modules/cron/configuration.ts index 4aae93062..d6ca701be 100644 --- a/packages/ui/certd-server/src/modules/cron/configuration.ts +++ b/packages/ui/certd-server/src/modules/cron/configuration.ts @@ -1,10 +1,10 @@ -import { logger } from '@certd/basic'; -import { Config, Configuration, IMidwayContainer } from '@midwayjs/core'; -import { Cron } from './cron.js'; +import { logger } from "@certd/basic"; +import { Config, Configuration, IMidwayContainer } from "@midwayjs/core"; +import { Cron } from "./cron.js"; // ... (see below) ... @Configuration({ - namespace: 'cron', + namespace: "cron", //importConfigs: [join(__dirname, './config')], }) export class CronConfiguration { @@ -12,13 +12,13 @@ export class CronConfiguration { config; cron: Cron; async onReady(container: IMidwayContainer) { - logger.info('cron start'); + logger.info("cron start"); this.cron = new Cron({ logger: logger, ...this.config, }); - container.registerObject('cron', this.cron); + container.registerObject("cron", this.cron); this.cron.start(); - logger.info('cron started'); + logger.info("cron started"); } } diff --git a/packages/ui/certd-server/src/modules/cron/cron.ts b/packages/ui/certd-server/src/modules/cron/cron.ts index 303a02644..0bdff7c12 100644 --- a/packages/ui/certd-server/src/modules/cron/cron.ts +++ b/packages/ui/certd-server/src/modules/cron/cron.ts @@ -1,5 +1,5 @@ -import parser from 'cron-parser'; -import { ILogger, logger } from '@certd/basic'; +import parser from "cron-parser"; +import { ILogger, logger } from "@certd/basic"; export type CronTaskReq = { /** @@ -57,7 +57,7 @@ export class Cron { } start() { - this.logger.info('[cron] start'); + this.logger.info("[cron] start"); this.queue.forEach(task => { task.genNextTime(); }); @@ -85,11 +85,11 @@ export class Cron { } this.logger.info(`[cron] register cron : [${req.name}] ,${req.cron}`); - this.remove(req.name) + this.remove(req.name); const task = new CronTask(req, this.logger); this.queue.push(task); - this.logger.info('当前定时任务数量:', this.getTaskSize()); + this.logger.info("当前定时任务数量:", this.getTaskSize()); } remove(taskName: string) { @@ -99,7 +99,7 @@ export class Cron { this.queue[index].stop(); this.queue.splice(index, 1); } - this.logger.info('当前定时任务数量:', this.getTaskSize()); + this.logger.info("当前定时任务数量:", this.getTaskSize()); } getTaskSize() { diff --git a/packages/ui/certd-server/src/modules/cron/index.ts b/packages/ui/certd-server/src/modules/cron/index.ts index 7bdf862ae..1e348f598 100644 --- a/packages/ui/certd-server/src/modules/cron/index.ts +++ b/packages/ui/certd-server/src/modules/cron/index.ts @@ -1,5 +1,5 @@ // src/index.ts -export { CronConfiguration as Configuration } from './configuration.js'; +export { CronConfiguration as Configuration } from "./configuration.js"; // export * from './controller/user'; // export * from './controller/api'; // export * from './service/user'; diff --git a/packages/ui/certd-server/src/modules/db/index.ts b/packages/ui/certd-server/src/modules/db/index.ts index d1306b186..db292a4e3 100644 --- a/packages/ui/certd-server/src/modules/db/index.ts +++ b/packages/ui/certd-server/src/modules/db/index.ts @@ -1,14 +1,14 @@ -import { SqliteAdapter } from './sqlite.js'; -import { PostgresqlAdapter } from './postgresql.js'; -import { Config, Init, Provide, Scope, ScopeEnum } from '@midwayjs/core'; -import { SqlAdapter } from './d.js'; -import { MysqlAdapter } from './mysql.js'; +import { SqliteAdapter } from "./sqlite.js"; +import { PostgresqlAdapter } from "./postgresql.js"; +import { Config, Init, Provide, Scope, ScopeEnum } from "@midwayjs/core"; +import { SqlAdapter } from "./d.js"; +import { MysqlAdapter } from "./mysql.js"; @Provide() @Scope(ScopeEnum.Request, { allowDowngrade: true }) export class DbAdapter implements SqlAdapter { adapter: SqlAdapter; - @Config('typeorm.dataSource.default.type') + @Config("typeorm.dataSource.default.type") dbType: string; @Init() @@ -25,13 +25,13 @@ export class DbAdapter implements SqlAdapter { } isSqlite() { - return this.dbType === 'better-sqlite3'; + return this.dbType === "better-sqlite3"; } isPostgresql() { - return this.dbType === 'postgres'; + return this.dbType === "postgres"; } isMysql() { - return this.dbType === 'mysql' || this.dbType === 'mariadb'; + return this.dbType === "mysql" || this.dbType === "mariadb"; } date(columnName: string) { diff --git a/packages/ui/certd-server/src/modules/db/mysql.ts b/packages/ui/certd-server/src/modules/db/mysql.ts index 456d69a0a..10a49c0fa 100644 --- a/packages/ui/certd-server/src/modules/db/mysql.ts +++ b/packages/ui/certd-server/src/modules/db/mysql.ts @@ -1,4 +1,4 @@ -import { SqlAdapter } from './d.js'; +import { SqlAdapter } from "./d.js"; export class MysqlAdapter implements SqlAdapter { date(columnName: string) { diff --git a/packages/ui/certd-server/src/modules/db/postgresql.ts b/packages/ui/certd-server/src/modules/db/postgresql.ts index b7c05fa0d..731359769 100644 --- a/packages/ui/certd-server/src/modules/db/postgresql.ts +++ b/packages/ui/certd-server/src/modules/db/postgresql.ts @@ -1,4 +1,4 @@ -import { SqlAdapter } from './d.js'; +import { SqlAdapter } from "./d.js"; export class PostgresqlAdapter implements SqlAdapter { date(columnName: string) { diff --git a/packages/ui/certd-server/src/modules/db/sqlite.ts b/packages/ui/certd-server/src/modules/db/sqlite.ts index 3caedcdc6..1a26d6d64 100644 --- a/packages/ui/certd-server/src/modules/db/sqlite.ts +++ b/packages/ui/certd-server/src/modules/db/sqlite.ts @@ -1,4 +1,4 @@ -import { SqlAdapter } from './d.js'; +import { SqlAdapter } from "./d.js"; export class SqliteAdapter implements SqlAdapter { date(columnName: string) { diff --git a/packages/ui/certd-server/src/modules/login/entity/oauth-bound.ts b/packages/ui/certd-server/src/modules/login/entity/oauth-bound.ts index 87115f9a1..22eebf97a 100644 --- a/packages/ui/certd-server/src/modules/login/entity/oauth-bound.ts +++ b/packages/ui/certd-server/src/modules/login/entity/oauth-bound.ts @@ -1,22 +1,22 @@ -import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; +import { Column, Entity, PrimaryGeneratedColumn } from "typeorm"; -@Entity('cd_oauth_bound') +@Entity("cd_oauth_bound") export class OauthBoundEntity { @PrimaryGeneratedColumn() id: number; - @Column({ name: 'user_id', comment: '用户id' }) + @Column({ name: "user_id", comment: "用户id" }) userId: number; - @Column({ name: 'type', comment: '第三方类型' }) + @Column({ name: "type", comment: "第三方类型" }) type: string; // oidc, wechat, github, gitee , qq , alipay - @Column({ name: 'open_id', comment: '第三方openid' }) + @Column({ name: "open_id", comment: "第三方openid" }) openId: string; - @Column({ name: 'create_time',comment: '创建时间', default: () => 'CURRENT_TIMESTAMP',}) + @Column({ name: "create_time", comment: "创建时间", default: () => "CURRENT_TIMESTAMP" }) createTime: Date; - @Column({ name: 'update_time', comment: '修改时间',default: () => 'CURRENT_TIMESTAMP',}) + @Column({ name: "update_time", comment: "修改时间", default: () => "CURRENT_TIMESTAMP" }) updateTime: Date; } diff --git a/packages/ui/certd-server/src/modules/login/entity/passkey.ts b/packages/ui/certd-server/src/modules/login/entity/passkey.ts index 05c9b9431..cafdca240 100644 --- a/packages/ui/certd-server/src/modules/login/entity/passkey.ts +++ b/packages/ui/certd-server/src/modules/login/entity/passkey.ts @@ -1,35 +1,34 @@ -import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; +import { Column, Entity, PrimaryGeneratedColumn } from "typeorm"; -@Entity('sys_passkey') +@Entity("sys_passkey") export class PasskeyEntity { @PrimaryGeneratedColumn() id: number; - @Column({ name: 'user_id', comment: '用户id' }) + @Column({ name: "user_id", comment: "用户id" }) userId: number; - @Column({ name: 'device_name', comment: '设备名称' }) + @Column({ name: "device_name", comment: "设备名称" }) deviceName: string; - @Column({ name: 'passkey_id', comment: 'passkey_id' }) + @Column({ name: "passkey_id", comment: "passkey_id" }) passkeyId: string; - @Column({ name: 'public_key', comment: '公钥', type: 'text' }) + @Column({ name: "public_key", comment: "公钥", type: "text" }) publicKey: string; - @Column({ name: 'counter', comment: '计数器' }) + @Column({ name: "counter", comment: "计数器" }) counter: number; - @Column({ name: 'transports', comment: '传输方式', type: 'text', nullable: true }) + @Column({ name: "transports", comment: "传输方式", type: "text", nullable: true }) transports: string; - @Column({ name: 'registered_at', comment: '注册时间' }) + @Column({ name: "registered_at", comment: "注册时间" }) registeredAt: number; - @Column({ name: 'create_time', comment: '创建时间', default: () => 'CURRENT_TIMESTAMP' }) + @Column({ name: "create_time", comment: "创建时间", default: () => "CURRENT_TIMESTAMP" }) createTime: Date; - @Column({ name: 'update_time', comment: '修改时间', default: () => 'CURRENT_TIMESTAMP' }) + @Column({ name: "update_time", comment: "修改时间", default: () => "CURRENT_TIMESTAMP" }) updateTime: Date; - } diff --git a/packages/ui/certd-server/src/modules/login/service/login-service.ts b/packages/ui/certd-server/src/modules/login/service/login-service.ts index 3b46739fd..d44b1eba7 100644 --- a/packages/ui/certd-server/src/modules/login/service/login-service.ts +++ b/packages/ui/certd-server/src/modules/login/service/login-service.ts @@ -1,13 +1,7 @@ import { Config, Inject, Provide, Scope, ScopeEnum } from "@midwayjs/core"; import { UserService } from "../../sys/authority/service/user-service.js"; import jwt from "jsonwebtoken"; -import { - AuthException, - CommonException, - Need2FAException, - SysPrivateSettings, - SysSettingsService -} from "@certd/lib-server"; +import { AuthException, CommonException, Need2FAException, SysPrivateSettings, SysSettingsService } from "@certd/lib-server"; import { RoleService } from "../../sys/authority/service/role-service.js"; import { UserEntity } from "../../sys/authority/entity/user.js"; import { cache, utils } from "@certd/basic"; @@ -24,7 +18,7 @@ import { InviteService } from "@certd/commercial-core"; /** */ @Provide() -@Scope(ScopeEnum.Request, {allowDowngrade: true}) +@Scope(ScopeEnum.Request, { allowDowngrade: true }) export class LoginService { @Inject() userService: UserService; @@ -33,7 +27,7 @@ export class LoginService { @Inject() codeService: CodeService; - @Config('auth.jwt') + @Config("auth.jwt") private jwt: any; @Inject() @@ -57,7 +51,7 @@ export class LoginService { const blockDurationKey = `login_block_duration:${username}`; const value = cache.get(blockDurationKey); if (value) { - const ttl = cache.getRemainingTTL(blockDurationKey) + const ttl = cache.getRemainingTTL(blockDurationKey); const leftMin = Math.ceil(ttl / 1000 / 60); throw new CommonException(`账号被锁定,请${leftMin}分钟后重试`); } @@ -102,7 +96,7 @@ export class LoginService { const leftMin = Math.ceil(ttl / 1000 / 60); cache.set(blockDurationKey, 1, { ttl: ttl, - }) + }); // 清除error次数 cache.delete(errorTimesKey); throw new LoginErrorException(`登录失败次数过多,请${leftMin}分钟后重试`, 0); @@ -114,10 +108,8 @@ export class LoginService { throw new LoginErrorException(errorMessage, leftTimes); } - async loginBySmsCode(req: { mobile: string; phoneCode: string; smsCode: string; randomStr: string; inviteCode?: string }) { - - this.checkIsBlocked(req.mobile) + this.checkIsBlocked(req.mobile); const smsChecked = await this.codeService.checkSmsCode({ mobile: req.mobile, @@ -126,19 +118,19 @@ export class LoginService { throwError: false, }); - const {mobile, phoneCode} = req; + const { mobile, phoneCode } = req; if (!smsChecked) { - this.addErrorTimes(mobile, '手机验证码错误'); + this.addErrorTimes(mobile, "手机验证码错误"); } - let info = await this.userService.findOne({phoneCode, mobile: mobile}); + let info = await this.userService.findOne({ phoneCode, mobile: mobile }); if (info == null) { //用户不存在,注册 const registerUser = { phoneCode, mobile, - password: '', + password: "", } as any; - info = await this.userService.register('mobile', registerUser, async txManager => { + info = await this.userService.register("mobile", registerUser, async txManager => { await this.inviteService.bindInvitee({ manager: txManager }, { inviteeUserId: registerUser.id, inviteCode: req.inviteCode }); }); } @@ -147,18 +139,22 @@ export class LoginService { } async loginByPassword(req: { username: string; password: string; phoneCode: string }) { - this.checkIsBlocked(req.username) - const {username, password, phoneCode} = req; - const info = await this.userService.findOne([{username: username}, {email: username}, { - phoneCode, - mobile: username - }]); + this.checkIsBlocked(req.username); + const { username, password, phoneCode } = req; + const info = await this.userService.findOne([ + { username: username }, + { email: username }, + { + phoneCode, + mobile: username, + }, + ]); if (info == null) { - throw new CommonException('用户名或密码错误'); + throw new CommonException("用户名或密码错误"); } const right = await this.userService.checkPassword(password, info.password, info.passwordVersion); if (!right) { - this.addErrorTimes(username, '用户名或密码错误'); + this.addErrorTimes(username, "用户名或密码错误"); } this.clearCacheOnSuccess(username); return this.onLoginSuccess(info); @@ -167,56 +163,54 @@ export class LoginService { async checkTwoFactorEnabled(userId: number) { //检查是否开启多重认证 if (!isPlus()) { - return true + return true; } - const twoFactorSetting = await this.twoFactorService.getSetting(userId) + const twoFactorSetting = await this.twoFactorService.getSetting(userId); - const authenticatorSetting = twoFactorSetting.authenticator + const authenticatorSetting = twoFactorSetting.authenticator; if (authenticatorSetting.enabled) { //要检查 - const randomKey = utils.id.simpleNanoId(12) + const randomKey = utils.id.simpleNanoId(12); cache.set(`login_2fa_code:${randomKey}`, userId, { ttl: 60 * 1000 * 2, - }) - throw new Need2FAException('已开启多重认证,请在2分钟内输入OPT验证码',randomKey) + }); + throw new Need2FAException("已开启多重认证,请在2分钟内输入OPT验证码", randomKey); } - } async loginByTwoFactor(req: { loginId: string; verifyCode: string }) { //检查是否开启多重认证 if (!isPlus()) { - throw new Error('本功能需要开通Certd专业版') + throw new Error("本功能需要开通Certd专业版"); } - const userId = cache.get(`login_2fa_code:${req.loginId}`) + const userId = cache.get(`login_2fa_code:${req.loginId}`); if (!userId) { - throw new AuthException('已超时,请返回重新登录') + throw new AuthException("已超时,请返回重新登录"); } - await this.twoFactorService.verifyAuthenticatorCode(userId, req.verifyCode) + await this.twoFactorService.verifyAuthenticatorCode(userId, req.verifyCode); const user = await this.userService.info(userId); if (!user) { - throw new AuthException('用户不存在') + throw new AuthException("用户不存在"); } - return this.generateToken(user) + return this.generateToken(user); } private async onLoginSuccess(info: UserEntity) { if (info.status === 0) { - throw new CommonException('用户已被禁用'); + throw new CommonException("用户已被禁用"); } - await this.checkTwoFactorEnabled(info.id) + await this.checkTwoFactorEnabled(info.id); return this.generateToken(info); } - writeTokenCookie(ctx:any,token: { expire: any; token: any }) { + writeTokenCookie(ctx: any, token: { expire: any; token: any }) { ctx.cookies.set("certd_token", token.token, { - maxAge: 1000 * token.expire + maxAge: 1000 * token.expire, }); } - /** * 生成token * @param user 用户对象 @@ -224,7 +218,7 @@ export class LoginService { */ async generateToken(user: UserEntity) { if (user.status === 0) { - throw new CommonException('用户已被禁用'); + throw new CommonException("用户已被禁用"); } const roleIds = await this.roleService.getRoleIdsByUserId(user.id); @@ -248,26 +242,26 @@ export class LoginService { }; } - - async loginByOpenId(req: { openId: string, type:string }) { - const {openId, type} = req; + async loginByOpenId(req: { openId: string; type: string }) { + const { openId, type } = req; const oauthBound = await this.oauthBoundService.findOne({ - where:{openId, type} + where: { openId, type }, }); if (oauthBound == null) { - return null + return null; } - const info = await this.userService.findOne({id: oauthBound.userId}); + const info = await this.userService.findOne({ id: oauthBound.userId }); if (info == null) { // 用户已被删除,删除此oauth绑定 await this.oauthBoundService.delete([oauthBound.id]); - return null + return null; } return this.generateToken(info); } async loginByPasskey(req: { credential: any; challenge: string }, ctx: any) { - const {credential, challenge} = req; + const { credential, challenge } = req; const user = await this.passkeyService.loginByPasskey(credential, challenge, ctx); return this.generateToken(user); - }} + } +} diff --git a/packages/ui/certd-server/src/modules/login/service/oauth-bound-service.ts b/packages/ui/certd-server/src/modules/login/service/oauth-bound-service.ts index e7c29be9d..0b0202c9f 100644 --- a/packages/ui/certd-server/src/modules/login/service/oauth-bound-service.ts +++ b/packages/ui/certd-server/src/modules/login/service/oauth-bound-service.ts @@ -4,27 +4,24 @@ import { InjectEntityModel } from "@midwayjs/typeorm"; import { Repository } from "typeorm"; import { OauthBoundEntity } from "../entity/oauth-bound.js"; - @Provide() @Scope(ScopeEnum.Request, { allowDowngrade: true }) export class OauthBoundService extends BaseService { - @InjectEntityModel(OauthBoundEntity) repository: Repository; @Inject() sysSettingsService: SysSettingsService; - //@ts-ignore getRepository() { return this.repository; } - async unbind(req: { userId: any; type: any; }) { + async unbind(req: { userId: any; type: any }) { const { userId, type } = req; if (!userId || !type) { - throw new Error('参数错误'); + throw new Error("参数错误"); } await this.repository.delete({ @@ -33,10 +30,10 @@ export class OauthBoundService extends BaseService { }); } - async bind(req: { userId: any; type: any; openId: any; }) { + async bind(req: { userId: any; type: any; openId: any }) { const { userId, type, openId } = req; if (!userId || !type || !openId) { - throw new Error('参数错误'); + throw new Error("参数错误"); } const exist = await this.repository.findOne({ where: { @@ -44,11 +41,11 @@ export class OauthBoundService extends BaseService { type, }, }); - if (exist ) { - if(exist.userId === userId){ + if (exist) { + if (exist.userId === userId) { return; } - throw new Error('该第三方账号已绑定其他用户'); + throw new Error("该第三方账号已绑定其他用户"); } const exist2 = await this.repository.findOne({ @@ -65,7 +62,7 @@ export class OauthBoundService extends BaseService { openId, }); return; - } + } //新增 await this.add({ userId, @@ -73,5 +70,4 @@ export class OauthBoundService extends BaseService { openId, }); } - } diff --git a/packages/ui/certd-server/src/modules/login/service/passkey-service.ts b/packages/ui/certd-server/src/modules/login/service/passkey-service.ts index a4fc9a137..4fc9bdd14 100644 --- a/packages/ui/certd-server/src/modules/login/service/passkey-service.ts +++ b/packages/ui/certd-server/src/modules/login/service/passkey-service.ts @@ -10,7 +10,6 @@ import { PasskeyEntity } from "../entity/passkey.js"; @Provide() @Scope(ScopeEnum.Request, { allowDowngrade: true }) export class PasskeyService extends BaseService { - @Inject() userService: UserService; @@ -25,7 +24,7 @@ export class PasskeyService extends BaseService { } async getRpInfo() { - let rpName = "Certd" + let rpName = "Certd"; if (isComm()) { const siteInfo = await this.sysSettingsService.getSetting(SysSiteInfo); rpName = siteInfo.title || rpName; @@ -42,7 +41,7 @@ export class PasskeyService extends BaseService { rpName, rpId, origin, - } + }; } async generateRegistrationOptions(userId: number, username: string, remoteIp: string, ctx: any) { const { generateRegistrationOptions } = await import("@simplewebauthn/server"); @@ -50,7 +49,6 @@ export class PasskeyService extends BaseService { const { rpName, rpId } = await this.getRpInfo(); - const options = await generateRegistrationOptions({ rpName: rpName, rpID: rpId, @@ -60,15 +58,15 @@ export class PasskeyService extends BaseService { timeout: 60000, attestationType: "none", excludeCredentials: [], - preferredAuthenticatorType: 'localDevice', + preferredAuthenticatorType: "localDevice", authenticatorSelection: { - authenticatorAttachment: "cross-platform", - userVerification: "preferred", + authenticatorAttachment: "cross-platform", + userVerification: "preferred", residentKey: "preferred", - requireResidentKey: false + requireResidentKey: false, }, }); - logger.info('[passkey] 注册选项:', JSON.stringify(options)); + logger.info("[passkey] 注册选项:", JSON.stringify(options)); cache.set(`passkey:registration:${options.challenge}`, userId, { ttl: 5 * 60 * 1000, }); @@ -78,12 +76,7 @@ export class PasskeyService extends BaseService { }; } - async verifyRegistrationResponse( - userId: number, - response: any, - challenge: string, - ctx: any - ) { + async verifyRegistrationResponse(userId: number, response: any, challenge: string, ctx: any) { const { verifyRegistrationResponse } = await import("@simplewebauthn/server"); const storedUserId = cache.get(`passkey:registration:${challenge}`); @@ -105,13 +98,12 @@ export class PasskeyService extends BaseService { verification = await verifyRegistrationResponse(verifyReq); } catch (error) { // 后端验证时 - logger.error('[passkey] 注册验证失败:', JSON.stringify(verifyReq)); + logger.error("[passkey] 注册验证失败:", JSON.stringify(verifyReq)); throw new AuthException(`注册验证失败:${error.message || error}`); } if (!verification.verified) { throw new AuthException("注册验证失败"); } - cache.delete(`passkey:registration:${challenge}`); @@ -129,7 +121,7 @@ export class PasskeyService extends BaseService { rpID: rpId, timeout: 60000, allowCredentials: [], - userVerification: 'preferred' //'required' | 'preferred' | 'discouraged'; + userVerification: "preferred", //'required' | 'preferred' | 'discouraged'; }); // cache.set(`passkey:authentication:${options.challenge}`, userId, { @@ -141,11 +133,7 @@ export class PasskeyService extends BaseService { }; } - async verifyAuthenticationResponse( - credential: any, - challenge: string, - ctx: any - ) { + async verifyAuthenticationResponse(credential: any, challenge: string, ctx: any) { const { verifyAuthenticationResponse } = await import("@simplewebauthn/server"); const passkey = await this.repository.findOne({ @@ -168,7 +156,7 @@ export class PasskeyService extends BaseService { requireUserVerification: false, credential: { id: passkey.passkeyId, - publicKey: new Uint8Array(Buffer.from(passkey.publicKey, 'base64')), + publicKey: new Uint8Array(Buffer.from(passkey.publicKey, "base64")), counter: passkey.counter, transports: passkey.transports as any, }, @@ -187,24 +175,13 @@ export class PasskeyService extends BaseService { }; } - async registerPasskey( - userId: number, - response: any, - challenge: string, - deviceName: string, - ctx: any - ) { - const verification = await this.verifyRegistrationResponse( - userId, - response, - challenge, - ctx - ); + async registerPasskey(userId: number, response: any, challenge: string, deviceName: string, ctx: any) { + const verification = await this.verifyRegistrationResponse(userId, response, challenge, ctx); await this.add({ userId, passkeyId: verification.credentialId, - publicKey: Buffer.from(verification.credentialPublicKey).toString('base64'), + publicKey: Buffer.from(verification.credentialPublicKey).toString("base64"), counter: verification.counter, deviceName, registeredAt: Date.now(), @@ -214,11 +191,7 @@ export class PasskeyService extends BaseService { } async loginByPasskey(credential: any, challenge: string, ctx: any) { - const verification = await this.verifyAuthenticationResponse( - credential, - challenge, - ctx - ); + const verification = await this.verifyAuthenticationResponse(credential, challenge, ctx); const passkey = await this.repository.findOne({ where: { diff --git a/packages/ui/certd-server/src/modules/mine/entity/user-settings.ts b/packages/ui/certd-server/src/modules/mine/entity/user-settings.ts index 86f15f69e..a54b5aedc 100644 --- a/packages/ui/certd-server/src/modules/mine/entity/user-settings.ts +++ b/packages/ui/certd-server/src/modules/mine/entity/user-settings.ts @@ -1,34 +1,33 @@ -import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; +import { Column, Entity, PrimaryGeneratedColumn } from "typeorm"; /** */ -@Entity('user_settings') +@Entity("user_settings") export class UserSettingsEntity { @PrimaryGeneratedColumn() id: number; - @Column({ name: 'user_id', comment: '用户id' }) + @Column({ name: "user_id", comment: "用户id" }) userId: number; - @Column({ comment: 'key', length: 100 }) + @Column({ comment: "key", length: 100 }) key: string; - @Column({ comment: '名称', length: 100 }) + @Column({ comment: "名称", length: 100 }) title: string; - @Column({ name: 'setting', comment: '设置', length: 1024, nullable: true }) + @Column({ name: "setting", comment: "设置", length: 1024, nullable: true }) setting: string; - @Column({ name: 'project_id', comment: '项目Id' }) + @Column({ name: "project_id", comment: "项目Id" }) projectId: number; @Column({ - name: 'create_time', - comment: '创建时间', - default: () => 'CURRENT_TIMESTAMP', + name: "create_time", + comment: "创建时间", + default: () => "CURRENT_TIMESTAMP", }) createTime: Date; @Column({ - name: 'update_time', - comment: '修改时间', - default: () => 'CURRENT_TIMESTAMP', + name: "update_time", + comment: "修改时间", + default: () => "CURRENT_TIMESTAMP", }) updateTime: Date; - } diff --git a/packages/ui/certd-server/src/modules/mine/service/models.ts b/packages/ui/certd-server/src/modules/mine/service/models.ts index b7e944a1b..effd64121 100644 --- a/packages/ui/certd-server/src/modules/mine/service/models.ts +++ b/packages/ui/certd-server/src/modules/mine/service/models.ts @@ -4,65 +4,57 @@ export type TwoFactorAuthenticator = { enabled: boolean; secret?: string; type?: string; - verified?:boolean; -} + verified?: boolean; +}; export class UserTwoFactorSetting extends BaseSettings { static __title__ = "用户多重认证设置"; static __key__ = "user.two.factor"; authenticator: TwoFactorAuthenticator = { - enabled:false, - verified:false, + enabled: false, + verified: false, }; - } - - export class UserSiteMonitorSetting extends BaseSettings { static __title__ = "站点监控设置"; static __key__ = "user.site.monitor"; - notificationId?:number= 0; - cron?:string = undefined; - retryTimes?:number = 3; - dnsServer?:string[] = undefined; - certValidDays?:number = 14; + notificationId?: number = 0; + cron?: string = undefined; + retryTimes?: number = 3; + dnsServer?: string[] = undefined; + certValidDays?: number = 14; } - export class UserDomainMonitorSetting extends BaseSettings { static __title__ = "域名到期监控设置"; static __key__ = "user.domain.monitor"; - enabled?:boolean = false; - notificationId?:number= 0; - cron?:string = undefined; - willExpireDays?:number = 30; + enabled?: boolean = false; + notificationId?: number = 0; + cron?: string = undefined; + willExpireDays?: number = 30; } - export class UserEmailSetting extends BaseSettings { static __title__ = "用户邮箱设置"; static __key__ = "user.email"; - list:string[] = []; + list: string[] = []; } - - export class UserGrantSetting extends BaseSettings { static __title__ = "用户授权设置"; static __key__ = "user.grant"; - allowAdminViewCerts:boolean = false; + allowAdminViewCerts = false; } - export class UserDomainImportSetting extends BaseSettings { static __title__ = "用户域名导入设置"; static __key__ = "user.domain.import"; - domainImportList:{dnsProviderType:string,dnsProviderAccessId:number,key:string,title:string,icon?:string}[]; + domainImportList: { dnsProviderType: string; dnsProviderAccessId: number; key: string; title: string; icon?: string }[]; } diff --git a/packages/ui/certd-server/src/modules/mine/service/two-factor-service.ts b/packages/ui/certd-server/src/modules/mine/service/two-factor-service.ts index 4f327ba64..1e0a7f764 100644 --- a/packages/ui/certd-server/src/modules/mine/service/two-factor-service.ts +++ b/packages/ui/certd-server/src/modules/mine/service/two-factor-service.ts @@ -14,15 +14,14 @@ export class TwoFactorService { @Inject() userService: UserService; - async getAuthenticatorQrCode(userId: any) { - const setting = await this.getSetting(userId) + const setting = await this.getSetting(userId); const authenticatorSetting = setting.authenticator; if (!authenticatorSetting.secret) { - const { authenticator } = await import("otplib"); + const { authenticator } = await import("otplib"); - authenticatorSetting.secret = authenticator.generateSecret() + authenticatorSetting.secret = authenticator.generateSecret(); await this.userSettingsService.saveSetting(userId, null, setting); } @@ -34,14 +33,13 @@ export class TwoFactorService { //生成qrcode base64 const qrcode = await import("qrcode"); const qrcodeBase64 = await qrcode.toDataURL(qrcodeContent); - return {qrcode:qrcodeBase64,link:qrcodeContent,secret} - + return { qrcode: qrcodeBase64, link: qrcodeContent, secret }; } async saveAuthenticator(req: { userId: any; verifyCode: any }) { const userId = req.userId; const { authenticator } = await import("otplib"); - const setting = await this.getSetting(userId) + const setting = await this.getSetting(userId); const authenticatorSetting = setting.authenticator; if (!authenticatorSetting.secret) { @@ -62,26 +60,25 @@ export class TwoFactorService { await this.userSettingsService.saveSetting(userId, null, setting); } - async offAuthenticator(userId:number) { + async offAuthenticator(userId: number) { if (!userId || userId <= 0) { throw new Error("userId is required"); } - const setting = await this.getSetting(userId) + const setting = await this.getSetting(userId); setting.authenticator.enabled = false; setting.authenticator.verified = false; - setting.authenticator.secret = ''; + setting.authenticator.secret = ""; await this.userSettingsService.saveSetting(userId, null, setting); } - async getSetting(userId:number) { + async getSetting(userId: number) { return await this.userSettingsService.getSetting(userId, null, UserTwoFactorSetting); - } async verifyAuthenticatorCode(userId: any, verifyCode: string) { const { authenticator } = await import("otplib"); - const setting = await this.getSetting(userId) + const setting = await this.getSetting(userId); if (!setting.authenticator.enabled) { throw new Error("authenticator 未开启"); } diff --git a/packages/ui/certd-server/src/modules/mine/service/user-settings-service.ts b/packages/ui/certd-server/src/modules/mine/service/user-settings-service.ts index d5cfdd178..63a06c85d 100644 --- a/packages/ui/certd-server/src/modules/mine/service/user-settings-service.ts +++ b/packages/ui/certd-server/src/modules/mine/service/user-settings-service.ts @@ -4,7 +4,7 @@ import { Repository } from "typeorm"; import { BaseService, BaseSettings } from "@certd/lib-server"; import { UserSettingsEntity } from "../entity/user-settings.js"; import { LocalCache, mergeUtils } from "@certd/basic"; -const {merge} = mergeUtils +const { merge } = mergeUtils; const UserSettingCache = new LocalCache({ clearInterval: 5 * 60 * 1000, @@ -33,13 +33,13 @@ export class UserSettingsService extends BaseService { const setting = JSON.parse(entity.setting); return { id: entity.id, - ...setting + ...setting, }; } async getByKey(key: string, userId: number, projectId: number): Promise { - if(userId == null){ - throw new Error('userId is required'); + if (userId == null) { + throw new Error("userId is required"); } if (!key) { return null; @@ -48,14 +48,14 @@ export class UserSettingsService extends BaseService { where: { key, userId, - projectId - } + projectId, + }, }); } async getSettingByKey(key: string, userId: number, projectId: number): Promise { - if(userId == null){ - throw new Error('userId is required'); + if (userId == null) { + throw new Error("userId is required"); } const entity = await this.getByKey(key, userId, projectId); if (!entity) { @@ -69,8 +69,8 @@ export class UserSettingsService extends BaseService { where: { key: bean.key, userId: bean.userId, - projectId: bean.projectId - } + projectId: bean.projectId, + }, }); if (entity) { entity.setting = bean.setting; @@ -81,15 +81,14 @@ export class UserSettingsService extends BaseService { } } - - async getSetting( userId: number, projectId: number,type: any, cache:boolean = false): Promise { - if(userId==null){ - throw new Error('userId is required'); + async getSetting(userId: number, projectId: number, type: any, cache = false): Promise { + if (userId == null) { + throw new Error("userId is required"); } const key = type.__key__; - let cacheKey = key + '_' + userId ; + let cacheKey = key + "_" + userId; if (projectId) { - cacheKey += '_' + projectId; + cacheKey += "_" + projectId; } if (cache) { @@ -109,23 +108,23 @@ export class UserSettingsService extends BaseService { return newSetting; } - async saveSetting(userId:number, projectId: number,bean: T) { - if(userId == null){ - throw new Error('userId is required'); + async saveSetting(userId: number, projectId: number, bean: T) { + if (userId == null) { + throw new Error("userId is required"); } - const old = await this.getSetting(userId, projectId,bean.constructor) - bean = merge(old,bean) + const old = await this.getSetting(userId, projectId, bean.constructor); + bean = merge(old, bean); const type: any = bean.constructor; const key = type.__key__; - if(!key){ + if (!key) { throw new Error(`${type.name} must have __key__`); } - const entity = await this.getByKey(key,userId, projectId); + const entity = await this.getByKey(key, userId, projectId); const newEntity = new UserSettingsEntity(); if (entity) { newEntity.id = entity.id; - }else{ + } else { newEntity.key = key; newEntity.title = type.__title__; newEntity.userId = userId; @@ -134,5 +133,4 @@ export class UserSettingsService extends BaseService { newEntity.setting = JSON.stringify(bean); await this.repository.save(newEntity); } - } diff --git a/packages/ui/certd-server/src/modules/monitor/entity/cert-info.ts b/packages/ui/certd-server/src/modules/monitor/entity/cert-info.ts index d47d19138..d8f4807bb 100644 --- a/packages/ui/certd-server/src/modules/monitor/entity/cert-info.ts +++ b/packages/ui/certd-server/src/modules/monitor/entity/cert-info.ts @@ -1,64 +1,64 @@ -import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; -import { PipelineEntity } from '../../pipeline/entity/pipeline.js'; +import { Column, Entity, PrimaryGeneratedColumn } from "typeorm"; +import { PipelineEntity } from "../../pipeline/entity/pipeline.js"; -@Entity('cd_cert_info') +@Entity("cd_cert_info") export class CertInfoEntity { @PrimaryGeneratedColumn() id: number; - @Column({ name: 'user_id', comment: '用户id' }) + @Column({ name: "user_id", comment: "用户id" }) userId: number; - @Column({ name: 'domain', comment: '主域名' }) + @Column({ name: "domain", comment: "主域名" }) domain: string; - @Column({ name: 'domains', comment: '域名' }) + @Column({ name: "domains", comment: "域名" }) domains: string; - @Column({ name: 'domain_count', comment: '域名数量' }) + @Column({ name: "domain_count", comment: "域名数量" }) domainCount: number; - @Column({ name: 'wildcard_domain_count', comment: '泛域名数量', default: 0 }) + @Column({ name: "wildcard_domain_count", comment: "泛域名数量", default: 0 }) wildcardDomainCount: number; - @Column({ name: 'pipeline_id', comment: '关联流水线id' }) + @Column({ name: "pipeline_id", comment: "关联流水线id" }) pipelineId: number; - @Column({ name: 'apply_time', comment: '申请时间' }) + @Column({ name: "apply_time", comment: "申请时间" }) applyTime: number; - @Column({ name: 'from_type', comment: '来源' }) + @Column({ name: "from_type", comment: "来源" }) fromType: string; - @Column({ name: 'cert_provider', comment: '证书颁发机构' }) + @Column({ name: "cert_provider", comment: "证书颁发机构" }) certProvider: string; - @Column({ name: 'effective_time', comment: '生效时间' }) + @Column({ name: "effective_time", comment: "生效时间" }) effectiveTime: number; - @Column({ name: 'expires_time', comment: '过期时间' }) + @Column({ name: "expires_time", comment: "过期时间" }) expiresTime: number; - @Column({ name: 'cert_info', comment: '证书详情' }) + @Column({ name: "cert_info", comment: "证书详情" }) certInfo: string; - @Column({ name: 'cert_file', comment: '证书下载' }) + @Column({ name: "cert_file", comment: "证书下载" }) certFile: string; - @Column({ name: 'project_id', comment: '项目id' }) + @Column({ name: "project_id", comment: "项目id" }) projectId: number; @Column({ - name: 'create_time', - comment: '创建时间', - default: () => 'CURRENT_TIMESTAMP', + name: "create_time", + comment: "创建时间", + default: () => "CURRENT_TIMESTAMP", }) createTime: Date; @Column({ - name: 'update_time', - comment: '修改时间', - default: () => 'CURRENT_TIMESTAMP', + name: "update_time", + comment: "修改时间", + default: () => "CURRENT_TIMESTAMP", }) updateTime: Date; diff --git a/packages/ui/certd-server/src/modules/monitor/entity/job-history.ts b/packages/ui/certd-server/src/modules/monitor/entity/job-history.ts index 13b8851bb..750c46cc8 100644 --- a/packages/ui/certd-server/src/modules/monitor/entity/job-history.ts +++ b/packages/ui/certd-server/src/modules/monitor/entity/job-history.ts @@ -1,50 +1,49 @@ -import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; -import { PipelineEntity } from '../../pipeline/entity/pipeline.js'; +import { Column, Entity, PrimaryGeneratedColumn } from "typeorm"; +import { PipelineEntity } from "../../pipeline/entity/pipeline.js"; -@Entity('cd_job_history') +@Entity("cd_job_history") export class JobHistoryEntity { @PrimaryGeneratedColumn() id: number; - @Column({ name: 'user_id', comment: '用户id' }) + @Column({ name: "user_id", comment: "用户id" }) userId: number; - @Column({ name: 'project_id', comment: '项目id' }) + @Column({ name: "project_id", comment: "项目id" }) projectId: number; - - @Column({ name: 'type', comment: '类型' }) + @Column({ name: "type", comment: "类型" }) type: string; - @Column({ name: 'title', comment: '标题' }) + @Column({ name: "title", comment: "标题" }) title: string; - @Column({ name: 'content', comment: '内容' }) + @Column({ name: "content", comment: "内容" }) content: string; - @Column({ name: 'related_id', comment: '关联id' }) + @Column({ name: "related_id", comment: "关联id" }) relatedId: string; - @Column({ name: 'result', comment: '结果' }) + @Column({ name: "result", comment: "结果" }) result: string; - @Column({ name: 'start_at', comment: '开始时间' }) + @Column({ name: "start_at", comment: "开始时间" }) startAt: number; - @Column({ name: 'end_at', comment: '结束时间' }) + @Column({ name: "end_at", comment: "结束时间" }) endAt: number; @Column({ - name: 'create_time', - comment: '创建时间', - default: () => 'CURRENT_TIMESTAMP', + name: "create_time", + comment: "创建时间", + default: () => "CURRENT_TIMESTAMP", }) createTime: Date; @Column({ - name: 'update_time', - comment: '修改时间', - default: () => 'CURRENT_TIMESTAMP', + name: "update_time", + comment: "修改时间", + default: () => "CURRENT_TIMESTAMP", }) updateTime: Date; diff --git a/packages/ui/certd-server/src/modules/monitor/entity/site-info.ts b/packages/ui/certd-server/src/modules/monitor/entity/site-info.ts index 80aae8a10..a10bbb38d 100644 --- a/packages/ui/certd-server/src/modules/monitor/entity/site-info.ts +++ b/packages/ui/certd-server/src/modules/monitor/entity/site-info.ts @@ -1,84 +1,82 @@ -import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; +import { Column, Entity, PrimaryGeneratedColumn } from "typeorm"; /** */ -@Entity('cd_site_info') +@Entity("cd_site_info") export class SiteInfoEntity { @PrimaryGeneratedColumn() id: number; - @Column({ name: 'user_id', comment: '用户id' }) + @Column({ name: "user_id", comment: "用户id" }) userId: number; - @Column({ name: 'name', comment: '站点名称', length: 100 }) + @Column({ name: "name", comment: "站点名称", length: 100 }) name: string; - @Column({ name: 'domain', comment: '域名', length: 100 }) + @Column({ name: "domain", comment: "域名", length: 100 }) domain: string; - @Column({ name: 'https_port', comment: '端口' }) + @Column({ name: "https_port", comment: "端口" }) httpsPort: number; - @Column({ name: 'cert_domains', comment: '证书域名', length: 4096 }) + @Column({ name: "cert_domains", comment: "证书域名", length: 4096 }) certDomains: string; - @Column({ name: 'cert_info', comment: '证书详情', length: 4096 }) + @Column({ name: "cert_info", comment: "证书详情", length: 4096 }) certInfo: string; - @Column({ name: 'cert_status', comment: '证书状态', length: 100 }) + @Column({ name: "cert_status", comment: "证书状态", length: 100 }) certStatus: string; - @Column({ name: 'cert_provider', comment: '证书颁发机构', length: 100 }) + @Column({ name: "cert_provider", comment: "证书颁发机构", length: 100 }) certProvider: string; - @Column({ name: 'cert_effective_time', comment: '证书生效时间' }) + @Column({ name: "cert_effective_time", comment: "证书生效时间" }) certEffectiveTime: number; - @Column({ name: 'cert_expires_time', comment: '证书到期时间' }) + @Column({ name: "cert_expires_time", comment: "证书到期时间" }) certExpiresTime: number; - @Column({ name: 'last_check_time', comment: '上次检查时间' }) + @Column({ name: "last_check_time", comment: "上次检查时间" }) lastCheckTime: number; - @Column({ name: 'check_status', comment: '检查状态' }) + @Column({ name: "check_status", comment: "检查状态" }) checkStatus: string; - @Column({ name: 'error', comment: '错误信息' }) + @Column({ name: "error", comment: "错误信息" }) error: string; - @Column({ name: 'pipeline_id', comment: '关联流水线id' }) + @Column({ name: "pipeline_id", comment: "关联流水线id" }) pipelineId: number; - @Column({ name: 'cert_info_id', comment: '证书id' }) + @Column({ name: "cert_info_id", comment: "证书id" }) certInfoId: number; - - @Column({ name: 'ip_check', comment: '是否检查IP' }) + @Column({ name: "ip_check", comment: "是否检查IP" }) ipCheck: boolean; - @Column({ name: 'ip_sync_auto', comment: '是否自动同步IP' }) + @Column({ name: "ip_sync_auto", comment: "是否自动同步IP" }) ipSyncAuto: boolean; - @Column({ name: 'ip_sync_mode', comment: 'IP同步模式' }) + @Column({ name: "ip_sync_mode", comment: "IP同步模式" }) ipSyncMode: string; - @Column({ name: 'ip_ignore_coherence', comment: '忽略证书一致性' }) + @Column({ name: "ip_ignore_coherence", comment: "忽略证书一致性" }) ipIgnoreCoherence: boolean; - @Column({ name: 'ip_count', comment: 'ip数量' }) - ipCount: number + @Column({ name: "ip_count", comment: "ip数量" }) + ipCount: number; - @Column({ name: 'ip_error_count', comment: 'ip异常数量' }) - ipErrorCount: number + @Column({ name: "ip_error_count", comment: "ip异常数量" }) + ipErrorCount: number; - - @Column({ name: 'disabled', comment: '禁用启用' }) + @Column({ name: "disabled", comment: "禁用启用" }) disabled: boolean; - @Column({ name: 'remark', comment: '备注', length: 512 }) + @Column({ name: "remark", comment: "备注", length: 512 }) remark: string; - @Column({ name: 'group_id', comment: '分组id' }) + @Column({ name: "group_id", comment: "分组id" }) groupId: number; - @Column({ name: 'ip_address', comment: 'IP地址', length: 128 }) + @Column({ name: "ip_address", comment: "IP地址", length: 128 }) ipAddress: string; - @Column({ name: 'project_id', comment: '项目id' }) + @Column({ name: "project_id", comment: "项目id" }) projectId: number; - @Column({ name: 'create_time', comment: '创建时间', default: () => 'CURRENT_TIMESTAMP' }) + @Column({ name: "create_time", comment: "创建时间", default: () => "CURRENT_TIMESTAMP" }) createTime: Date; - @Column({ name: 'update_time', comment: '修改时间', default: () => 'CURRENT_TIMESTAMP' }) + @Column({ name: "update_time", comment: "修改时间", default: () => "CURRENT_TIMESTAMP" }) updateTime: Date; } diff --git a/packages/ui/certd-server/src/modules/monitor/entity/site-ip.ts b/packages/ui/certd-server/src/modules/monitor/entity/site-ip.ts index 91887f815..59af371b9 100644 --- a/packages/ui/certd-server/src/modules/monitor/entity/site-ip.ts +++ b/packages/ui/certd-server/src/modules/monitor/entity/site-ip.ts @@ -1,43 +1,43 @@ -import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; +import { Column, Entity, PrimaryGeneratedColumn } from "typeorm"; /** */ -@Entity('cd_site_ip') +@Entity("cd_site_ip") export class SiteIpEntity { @PrimaryGeneratedColumn() id: number; - @Column({ name: 'user_id', comment: '用户id' }) + @Column({ name: "user_id", comment: "用户id" }) userId: number; - @Column({ name: 'site_id', comment: '站点id' }) + @Column({ name: "site_id", comment: "站点id" }) siteId: number; - @Column({ name: 'ip_address', comment: 'IP', length: 100 }) + @Column({ name: "ip_address", comment: "IP", length: 100 }) ipAddress: string; - @Column({ name: 'cert_domains', comment: '证书域名', length: 4096 }) + @Column({ name: "cert_domains", comment: "证书域名", length: 4096 }) certDomains: string; - @Column({ name: 'cert_status', comment: '证书状态', length: 100 }) + @Column({ name: "cert_status", comment: "证书状态", length: 100 }) certStatus: string; - @Column({ name: 'cert_provider', comment: '证书颁发机构', length: 100 }) + @Column({ name: "cert_provider", comment: "证书颁发机构", length: 100 }) certProvider: string; - @Column({ name: 'cert_expires_time', comment: '证书到期时间' }) + @Column({ name: "cert_expires_time", comment: "证书到期时间" }) certExpiresTime: number; - @Column({ name: 'last_check_time', comment: '上次检查时间' }) + @Column({ name: "last_check_time", comment: "上次检查时间" }) lastCheckTime: number; - @Column({ name: 'check_status', comment: '检查状态' }) + @Column({ name: "check_status", comment: "检查状态" }) checkStatus: string; - @Column({ name: 'error', comment: '错误信息' }) + @Column({ name: "error", comment: "错误信息" }) error: string; - @Column({ name: 'from', comment: '来源' }) - from: string - @Column({ name: 'remark', comment: '备注' }) + @Column({ name: "from", comment: "来源" }) + from: string; + @Column({ name: "remark", comment: "备注" }) remark: string; @Column({ name: "disabled", comment: "禁用启用" }) disabled: boolean; - @Column({ name: 'project_id', comment: '项目id' }) + @Column({ name: "project_id", comment: "项目id" }) projectId: number; - @Column({ name: 'create_time', comment: '创建时间', default: () => 'CURRENT_TIMESTAMP' }) + @Column({ name: "create_time", comment: "创建时间", default: () => "CURRENT_TIMESTAMP" }) createTime: Date; - @Column({ name: 'update_time', comment: '修改时间', default: () => 'CURRENT_TIMESTAMP' }) + @Column({ name: "update_time", comment: "修改时间", default: () => "CURRENT_TIMESTAMP" }) updateTime: Date; } diff --git a/packages/ui/certd-server/src/modules/monitor/facade/cert-info-facade.ts b/packages/ui/certd-server/src/modules/monitor/facade/cert-info-facade.ts index d0d63eafb..ba431c0a3 100644 --- a/packages/ui/certd-server/src/modules/monitor/facade/cert-info-facade.ts +++ b/packages/ui/certd-server/src/modules/monitor/facade/cert-info-facade.ts @@ -10,25 +10,23 @@ import { CertInfoService } from "../service/cert-info-service.js"; import { DomainService } from "../../cert/service/domain-service.js"; import { DomainVerifierGetter } from "../../pipeline/service/getter/domain-verifier-getter.js"; - @Provide("CertInfoFacade") @Scope(ScopeEnum.Request, { allowDowngrade: true }) -export class CertInfoFacade { - +export class CertInfoFacade { @Inject() pipelineService: PipelineService; @Inject() - certInfoService: CertInfoService ; + certInfoService: CertInfoService; @Inject() - domainService: DomainService + domainService: DomainService; @Inject() - userSettingsService : UserSettingsService + userSettingsService: UserSettingsService; - async getCertInfo(req: { domains?: string; certId?: number; userId: number, projectId:number, autoApply?:boolean,format?:string }) { - const { domains, certId, userId,projectId } = req; + async getCertInfo(req: { domains?: string; certId?: number; userId: number; projectId: number; autoApply?: boolean; format?: string }) { + const { domains, certId, userId, projectId } = req; if (certId) { return await this.certInfoService.getCertInfoById({ id: certId, userId, projectId }); } @@ -38,41 +36,38 @@ export class CertInfoFacade { message: "参数错误,certId和domains必须传一个", }); } - const domainArr = domains.split(','); + const domainArr = domains.split(","); - const matchedList = await this.certInfoService.getMatchCertList({domains:domainArr,userId,projectId}) + const matchedList = await this.certInfoService.getMatchCertList({ domains: domainArr, userId, projectId }); - if (matchedList.length === 0 ) { - if(req.autoApply === true){ + if (matchedList.length === 0) { + if (req.autoApply === true) { //自动申请,先创建自动申请流水线 - const pipeline:PipelineEntity = await this.createAutoPipeline({domains:domainArr,userId,projectId}) - await this.triggerApplyPipeline({pipelineId:pipeline.id}) - }else{ + const pipeline: PipelineEntity = await this.createAutoPipeline({ domains: domainArr, userId, projectId }); + await this.triggerApplyPipeline({ pipelineId: pipeline.id }); + } else { throw new CodeException({ ...Constants.res.openCertNotFound, - message:"在证书仓库中没有找到匹配域名的证书,请先创建证书流水线,或传入autoApply参数,自动创建" + message: "在证书仓库中没有找到匹配域名的证书,请先创建证书流水线,或传入autoApply参数,自动创建", }); } } - let matched = this.getMinixMatched(matchedList); + const matched = this.getMinixMatched(matchedList); if (!matched) { - if(req.autoApply === true){ + if (req.autoApply === true) { //如果没有找到有效期内的证书,则自动触发一次申请 - const first = matchedList[0] - await this.triggerApplyPipeline({pipelineId:first.pipelineId}) - return - }else{ + const first = matchedList[0]; + await this.triggerApplyPipeline({ pipelineId: first.pipelineId }); + return; + } else { throw new CodeException({ ...Constants.res.openCertNotFound, - message:"证书已过期,请触发流水线申请,或者传入autoApply参数,自动触发" + message: "证书已过期,请触发流水线申请,或者传入autoApply参数,自动触发", }); } } - return await this.certInfoService.getCertInfoById({ id: matched.id, userId: userId,projectId,format:req.format }); - - - + return await this.certInfoService.getCertInfoById({ id: matched.id, userId: userId, projectId, format: req.format }); } public getMinixMatched(matchedList: CertInfoEntity[]) { @@ -103,59 +98,55 @@ export class CertInfoFacade { return matched; } - async createAutoPipeline(req:{domains:string[],userId:number,projectId:number}){ + async createAutoPipeline(req: { domains: string[]; userId: number; projectId: number }) { + const verifierGetter = new DomainVerifierGetter(req.userId, req.projectId, this.domainService); - const verifierGetter = new DomainVerifierGetter(req.userId, req.projectId, this.domainService) - - const allDomains = [] + const allDomains = []; for (const item of req.domains) { - allDomains.push(item.replaceAll("*.","")) + allDomains.push(item.replaceAll("*.", "")); } - const verifiers = await verifierGetter.getVerifiers(allDomains) + const verifiers = await verifierGetter.getVerifiers(allDomains); for (const item of allDomains) { - if (!verifiers[item]){ + if (!verifiers[item]) { throw new CodeException({ ...Constants.res.openDomainNoVerifier, - message:`域名${item}没有配置校验方式,请先在域名管理页面配置`, - data:{ - domain:item - } + message: `域名${item}没有配置校验方式,请先在域名管理页面配置`, + data: { + domain: item, + }, }); } } - const userEmailSetting = await this.userSettingsService.getSetting(req.userId,null, UserEmailSetting) - if(!userEmailSetting.list){ - throw new CodeException(Constants.res.openEmailNotFound) + const userEmailSetting = await this.userSettingsService.getSetting(req.userId, null, UserEmailSetting); + if (!userEmailSetting.list) { + throw new CodeException(Constants.res.openEmailNotFound); } - const email = userEmailSetting.list[0] + const email = userEmailSetting.list[0]; return await this.pipelineService.createAutoPipeline({ domains: req.domains, email, projectId: req.projectId, userId: req.userId, - from: "OpenAPI" - }) - - } - - async triggerApplyPipeline(req:{pipelineId:number}){ - //查询流水线状态 - const status = await this.pipelineService.getStatus(req.pipelineId) - if (status != 'running') { - await this.pipelineService.trigger(req.pipelineId) - await utils.sleep(1000) - } - const certInfo = await this.certInfoService.getByPipelineId(req.pipelineId) - throw new CodeException({ - ...Constants.res.openCertApplying, - data:{ - pipelineId:req.pipelineId, - certId:certInfo?.id - } + from: "OpenAPI", }); } - + async triggerApplyPipeline(req: { pipelineId: number }) { + //查询流水线状态 + const status = await this.pipelineService.getStatus(req.pipelineId); + if (status != "running") { + await this.pipelineService.trigger(req.pipelineId); + await utils.sleep(1000); + } + const certInfo = await this.certInfoService.getByPipelineId(req.pipelineId); + throw new CodeException({ + ...Constants.res.openCertApplying, + data: { + pipelineId: req.pipelineId, + certId: certInfo?.id, + }, + }); + } } diff --git a/packages/ui/certd-server/src/modules/monitor/index.ts b/packages/ui/certd-server/src/modules/monitor/index.ts index 9dd8939de..2e836e704 100644 --- a/packages/ui/certd-server/src/modules/monitor/index.ts +++ b/packages/ui/certd-server/src/modules/monitor/index.ts @@ -1,5 +1,5 @@ -export * from './entity/site-info.js'; -export * from './entity/cert-info.js'; +export * from "./entity/site-info.js"; +export * from "./entity/cert-info.js"; -export * from './service/cert-info-service.js'; -export * from './service/site-info-service.js'; +export * from "./service/cert-info-service.js"; +export * from "./service/site-info-service.js"; diff --git a/packages/ui/certd-server/src/modules/monitor/service/cert-info-service.ts b/packages/ui/certd-server/src/modules/monitor/service/cert-info-service.ts index 4c7c2852d..e94351c2b 100644 --- a/packages/ui/certd-server/src/modules/monitor/service/cert-info-service.ts +++ b/packages/ui/certd-server/src/modules/monitor/service/cert-info-service.ts @@ -12,10 +12,9 @@ export type UploadCertReq = { fromType?: string; userId?: number; projectId?: number; - file?:any + file?: any; }; - @Provide("CertInfoService") @Scope(ScopeEnum.Request, { allowDowngrade: true }) export class CertInfoService extends BaseService { @@ -32,19 +31,19 @@ export class CertInfoService extends BaseService { } async getUserDomainCount(userId: number) { - if (userId==null) { - throw new Error('userId is required'); + if (userId == null) { + throw new Error("userId is required"); } - return await this.repository.sum('domainCount', { + return await this.repository.sum("domainCount", { userId, }); } async getUserWildcardDomainCount(userId: number) { if (userId == null) { - throw new Error('userId is required'); + throw new Error("userId is required"); } - return await this.repository.sum('wildcardDomainCount', { + return await this.repository.sum("wildcardDomainCount", { userId, }); } @@ -56,7 +55,7 @@ export class CertInfoService extends BaseService { return domains.filter(domain => domain?.trim().toLowerCase().startsWith("*.")).length; } - async updateDomains(pipelineId: number, userId: number, projectId: number, domains: string[],fromType?:string) { + async updateDomains(pipelineId: number, userId: number, projectId: number, domains: string[], fromType?: string) { const found = await this.repository.findOne({ where: { pipelineId, @@ -73,26 +72,26 @@ export class CertInfoService extends BaseService { bean.pipelineId = pipelineId; bean.userId = userId; bean.projectId = projectId; - bean.fromType = fromType + bean.fromType = fromType; if (!domains || domains.length === 0) { return; } } if (!domains || domains.length === 0) { - bean.domain = ''; - bean.domains = ''; + bean.domain = ""; + bean.domains = ""; bean.domainCount = 0; bean.wildcardDomainCount = 0; } else { bean.domain = domains[0]; - bean.domains = domains.join(','); + bean.domains = domains.join(","); bean.domainCount = domains.length; bean.wildcardDomainCount = this.countWildcardDomains(domains); } await this.addOrUpdate(bean); - return bean.id + return bean.id; } async deleteByPipelineId(id: number) { @@ -104,12 +103,12 @@ export class CertInfoService extends BaseService { }); } - async getMatchCertList(params: { domains: string[]; userId: number,projectId?:number }) { - const { domains, userId,projectId } = params; + async getMatchCertList(params: { domains: string[]; userId: number; projectId?: number }) { + const { domains, userId, projectId } = params; if (!domains) { throw new CodeException({ ...Constants.res.openCertNotFound, - message:"域名不能为空" + message: "域名不能为空", }); } @@ -117,27 +116,27 @@ export class CertInfoService extends BaseService { select: { id: true, domains: true, - expiresTime:true, - pipelineId:true, + expiresTime: true, + pipelineId: true, }, where: { userId, projectId, }, order: { - id: 'DESC', + id: "DESC", }, }); //遍历查找 return list.filter(item => { - const itemDomains = item.domains.split(','); + const itemDomains = item.domains.split(","); return utils.domain.match(domains, itemDomains); }); } - async getCertInfoById(req: { id: number; userId: number,projectId:number,format?:string }) { + async getCertInfoById(req: { id: number; userId: number; projectId: number; format?: string }) { const entity = await this.info(req.id); - if (!entity || entity.userId !== req.userId ) { + if (!entity || entity.userId !== req.userId) { throw new CodeException(Constants.res.openCertNotFound); } if (req.projectId && entity.projectId !== req.projectId) { @@ -153,13 +152,13 @@ export class CertInfoService extends BaseService { ...certReader.toCertInfo(req.format), detail: { id: entity.id, - domains: entity.domains.split(','), + domains: entity.domains.split(","), notAfter: certReader.expires, }, }; } - async updateCertByPipelineId(pipelineId: number, cert: CertInfo,file?:string,fromType = 'pipeline') { + async updateCertByPipelineId(pipelineId: number, cert: CertInfo, file?: string, fromType = "pipeline") { const found = await this.repository.findOne({ where: { pipelineId, @@ -169,14 +168,14 @@ export class CertInfoService extends BaseService { id: found?.id, certReader: new CertReader(cert), fromType, - file + file, }); return bean; } private async updateCert(req: UploadCertReq) { const bean = new CertInfoEntity(); - const { id, fromType,userId, certReader } = req; + const { id, fromType, userId, certReader } = req; if (id) { bean.id = id; } else { @@ -186,7 +185,7 @@ export class CertInfoService extends BaseService { bean.certInfo = JSON.stringify(certInfo); bean.applyTime = new Date().getTime(); const domains = certReader.detail.domains.altNames; - bean.domains = domains.join(','); + bean.domains = domains.join(","); bean.domain = domains[0]; bean.domainCount = domains.length; bean.wildcardDomainCount = this.countWildcardDomains(domains); @@ -195,8 +194,8 @@ export class CertInfoService extends BaseService { bean.certProvider = certReader.detail.issuer.commonName; bean.userId = userId; bean.projectId = req.projectId; - if(req.file){ - bean.certFile = req.file + if (req.file) { + bean.certFile = req.file; } await this.addOrUpdate(bean); return bean; @@ -210,7 +209,7 @@ export class CertInfoService extends BaseService { }); } - async count({ userId,projectId }: { userId: number,projectId?:number }) { + async count({ userId, projectId }: { userId: number; projectId?: number }) { const total = await this.repository.count({ where: { userId, diff --git a/packages/ui/certd-server/src/modules/monitor/service/dns-custom.ts b/packages/ui/certd-server/src/modules/monitor/service/dns-custom.ts index 951dd1dae..d4f278c2d 100644 --- a/packages/ui/certd-server/src/modules/monitor/service/dns-custom.ts +++ b/packages/ui/certd-server/src/modules/monitor/service/dns-custom.ts @@ -1,17 +1,17 @@ -import {LocalCache, logger} from '@certd/basic'; -import dnsSdk, {AnyRecord} from 'dns' -import {LookupAddress} from "node:dns"; +import { LocalCache, logger } from "@certd/basic"; +import dnsSdk, { AnyRecord } from "dns"; +import { LookupAddress } from "node:dns"; -const dns = dnsSdk.promises +const dns = dnsSdk.promises; -export class DnsCustom{ +export class DnsCustom { private resolver: dnsSdk.promises.Resolver; // private cache = new LRUCache({ // max: 1000, // ttl: 1000 * 60 * 5, // }); - constructor(dnsServers:string[]) { + constructor(dnsServers: string[]) { const resolver = new dns.Resolver(); resolver.setServers(dnsServers); this.resolver = resolver; @@ -27,103 +27,100 @@ export class DnsCustom{ // this.cache.set(cacheKey,res) // return res // } - async lookup(hostname:string,options?:{ family: any, hints: number, all: boolean }):Promise{ + async lookup(hostname: string, options?: { family: any; hints: number; all: boolean }): Promise { // { family: undefined, hints: 0, all: true } - let v4:LookupAddress[] = [] - let v6:LookupAddress[] = [] - let errors = [] - const queryV6 = async ()=>{ - try{ - const list = await this.resolver.resolve6(hostname) + let v4: LookupAddress[] = []; + let v6: LookupAddress[] = []; + const errors = []; + const queryV6 = async () => { + try { + const list = await this.resolver.resolve6(hostname); if (list && list.length > 0) { - v6 = list.map(item=>{ + v6 = list.map(item => { return { address: item, - family: 6 - } - }) + family: 6, + }; + }); } - }catch (e) { - logger.warn("query v6 error",e) - errors.push(e) + } catch (e) { + logger.warn("query v6 error", e); + errors.push(e); } - } - const queryV4 = async ()=>{ - try{ - const list =await this.resolver.resolve4(hostname) + }; + const queryV4 = async () => { + try { + const list = await this.resolver.resolve4(hostname); if (list && list.length > 0) { - v4 = list.map(item=>{ + v4 = list.map(item => { return { address: item, - family: 4 - } - }) + family: 4, + }; + }); } - }catch (e) { - logger.warn("query v4 error",e) - errors.push(e) + } catch (e) { + logger.warn("query v4 error", e); + errors.push(e); + } + }; + + const queries: Promise[] = []; + + const { family, all } = options; + if (all) { + queries.push(queryV6()); + queries.push(queryV4()); + } else { + if (family === 6) { + queries.push(queryV6()); + } + if (family === 4) { + queries.push(queryV4()); } } - - const queries:Promise[] = [] - - - const {family, all} = options - if (all){ - queries.push(queryV6()) - queries.push(queryV4()) - }else{ - if(family === 6 ){ - queries.push(queryV6()) - } - if(family === 4 ){ - queries.push(queryV4()) - } - } - await Promise.all(queries) - const res = [...v4,...v6] - if(res.length === 0){ - if (errors.length > 0){ - const e = new Error(errors[0]) + await Promise.all(queries); + const res = [...v4, ...v6]; + if (res.length === 0) { + if (errors.length > 0) { + const e = new Error(errors[0]); // @ts-ignore - e.errors = errors - throw e + e.errors = errors; + throw e; } } - return res + return res; } - async resolve4(hostname:string):Promise{ - return await this.resolver.resolve4(hostname) + async resolve4(hostname: string): Promise { + return await this.resolver.resolve4(hostname); } - async resolve6(hostname:string):Promise{ - return await this.resolver.resolve6(hostname) + async resolve6(hostname: string): Promise { + return await this.resolver.resolve6(hostname); } - async resolveAny(hostname:string):Promise{ - return await this.resolver.resolveAny(hostname) + async resolveAny(hostname: string): Promise { + return await this.resolver.resolveAny(hostname); } - async resolveCname(hostname:string):Promise{ - return await this.resolver.resolveCname(hostname) + async resolveCname(hostname: string): Promise { + return await this.resolver.resolveCname(hostname); } - - } -export class DnsContainer{ - bucket: LocalCache = new LocalCache() +export class DnsContainer { + bucket: LocalCache = new LocalCache(); constructor() {} - getDns(server:string[]){ - const key = server.join(',') - let dns = this.bucket.get(key) - if (dns){ - return dns + getDns(server: string[]) { + const key = server.join(","); + let dns = this.bucket.get(key); + if (dns) { + return dns; } - dns = new DnsCustom(server) - this.bucket.set(key,dns) - return dns + dns = new DnsCustom(server); + this.bucket.set(key, dns); + return dns; } } -export const dnsContainer = new DnsContainer() +export const dnsContainer = new DnsContainer(); diff --git a/packages/ui/certd-server/src/modules/monitor/service/job-history-service.ts b/packages/ui/certd-server/src/modules/monitor/service/job-history-service.ts index 6a17812b1..650a5e83d 100644 --- a/packages/ui/certd-server/src/modules/monitor/service/job-history-service.ts +++ b/packages/ui/certd-server/src/modules/monitor/service/job-history-service.ts @@ -5,14 +5,12 @@ import { Repository } from "typeorm"; import { UserSettingsService } from "../../mine/service/user-settings-service.js"; import { JobHistoryEntity } from "../entity/job-history.js"; - @Provide() @Scope(ScopeEnum.Request, { allowDowngrade: true }) export class JobHistoryService extends BaseService { @InjectEntityModel(JobHistoryEntity) repository: Repository; - @Inject() userSettingsService: UserSettingsService; diff --git a/packages/ui/certd-server/src/modules/monitor/service/site-info-service.ts b/packages/ui/certd-server/src/modules/monitor/service/site-info-service.ts index c3b2b618d..36acdd973 100644 --- a/packages/ui/certd-server/src/modules/monitor/service/site-info-service.ts +++ b/packages/ui/certd-server/src/modules/monitor/service/site-info-service.ts @@ -1,20 +1,20 @@ -import {Inject, Provide, Scope, ScopeEnum} from "@midwayjs/core"; -import {BaseService, Constants, isEnterprise, NeedSuiteException, NeedVIPException, SysSettingsService} from "@certd/lib-server"; -import {InjectEntityModel} from "@midwayjs/typeorm"; -import {In, Repository} from "typeorm"; -import {SiteInfoEntity} from "../entity/site-info.js"; -import {siteTester} from "./site-tester.js"; +import { Inject, Provide, Scope, ScopeEnum } from "@midwayjs/core"; +import { BaseService, Constants, isEnterprise, NeedSuiteException, NeedVIPException, SysSettingsService } from "@certd/lib-server"; +import { InjectEntityModel } from "@midwayjs/typeorm"; +import { In, Repository } from "typeorm"; +import { SiteInfoEntity } from "../entity/site-info.js"; +import { siteTester } from "./site-tester.js"; import dayjs from "dayjs"; -import {logger, utils} from "@certd/basic"; -import {PeerCertificate} from "tls"; -import {NotificationService} from "../../pipeline/service/notification-service.js"; -import {isComm, isPlus} from "@certd/plus-core"; -import {UserSuiteService} from "@certd/commercial-core"; -import {UserSettingsService} from "../../mine/service/user-settings-service.js"; -import {UserSiteMonitorSetting} from "../../mine/service/models.js"; -import {SiteIpService} from "./site-ip-service.js"; -import {SiteIpEntity} from "../entity/site-ip.js"; -import {Cron} from "../../cron/cron.js"; +import { logger, utils } from "@certd/basic"; +import { PeerCertificate } from "tls"; +import { NotificationService } from "../../pipeline/service/notification-service.js"; +import { isComm, isPlus } from "@certd/plus-core"; +import { UserSuiteService } from "@certd/commercial-core"; +import { UserSettingsService } from "../../mine/service/user-settings-service.js"; +import { UserSiteMonitorSetting } from "../../mine/service/models.js"; +import { SiteIpService } from "./site-ip-service.js"; +import { SiteIpEntity } from "../entity/site-ip.js"; +import { Cron } from "../../cron/cron.js"; import { dnsContainer } from "./dns-custom.js"; import { merge } from "lodash-es"; import { JobHistoryService } from "./job-history-service.js"; @@ -23,7 +23,7 @@ import { UserService } from "../../sys/authority/service/user-service.js"; import { ProjectService } from "../../sys/enterprise/service/project-service.js"; @Provide() -@Scope(ScopeEnum.Request, {allowDowngrade: true}) +@Scope(ScopeEnum.Request, { allowDowngrade: true }) export class SiteInfoService extends BaseService { @InjectEntityModel(SiteInfoEntity) repository: Repository; @@ -87,18 +87,18 @@ export class SiteInfoService extends BaseService { } await this.checkMonitorLimit(data.userId); - + data.disabled = false; const found = await this.repository.findOne({ where: { domain: data.domain, userId: data.userId, - httpsPort: data.httpsPort || 443 - } + httpsPort: data.httpsPort || 443, + }, }); if (found) { - return {id: found.id}; + return { id: found.id }; } return await super.add(data); @@ -113,11 +113,11 @@ export class SiteInfoService extends BaseService { } async getUserMonitorCount(userId: number) { - if (userId==null) { + if (userId == null) { throw new Error("userId is required"); } return await this.repository.count({ - where: {userId} + where: { userId }, }); } @@ -132,18 +132,18 @@ export class SiteInfoService extends BaseService { throw new Error("站点域名不能为空"); } - const setting = await this.userSettingsService.getSetting(site.userId,site.projectId, UserSiteMonitorSetting); - const dnsServer = setting.dnsServer - let customDns = null + const setting = await this.userSettingsService.getSetting(site.userId, site.projectId, UserSiteMonitorSetting); + const dnsServer = setting.dnsServer; + let customDns = null; if (dnsServer && dnsServer.length > 0) { - customDns = dnsContainer.getDns(dnsServer) as any + customDns = dnsContainer.getDns(dnsServer) as any; } try { await this.update({ id: site.id, checkStatus: "checking", - lastCheckTime: dayjs().valueOf() + lastCheckTime: dayjs().valueOf(), }); const res = await siteTester.test({ host: site.domain, @@ -177,56 +177,56 @@ export class SiteInfoService extends BaseService { certExpiresTime: dayjs(expires).valueOf(), lastCheckTime: dayjs().valueOf(), error: null, - checkStatus: "ok" + checkStatus: "ok", }; - logger.info(`测试站点成功:id=${updateData.id},site=${site.name},certEffectiveTime=${updateData.certEffectiveTime},expiresTime=${updateData.certExpiresTime}`) + logger.info(`测试站点成功:id=${updateData.id},site=${site.name},certEffectiveTime=${updateData.certEffectiveTime},expiresTime=${updateData.certExpiresTime}`); if (site.ipCheck) { - delete updateData.checkStatus + delete updateData.checkStatus; } await this.update(updateData); - const setting = await this.userSettingsService.getSetting(site.userId,site.projectId, UserSiteMonitorSetting) + const setting = await this.userSettingsService.getSetting(site.userId, site.projectId, UserSiteMonitorSetting); - merge(site,updateData) + merge(site, updateData); //检查ip - await this.checkAllIp(site,retryTimes,setting); + await this.checkAllIp(site, retryTimes, setting); if (!notify) { return; } try { - await this.sendExpiresNotify(site.id,setting); + await this.sendExpiresNotify(site.id, setting); } catch (e) { logger.error("send notify error", e); } } catch (e) { logger.error("check site error", e); - let message = e.message - if (!message){ - message = e.code + let message = e.message; + if (!message) { + message = e.code; } - if (e.errors &&e.errors.length > 0){ - message += "\n"+e.errors.map((item:any)=>item.message).join("\n") + if (e.errors && e.errors.length > 0) { + message += "\n" + e.errors.map((item: any) => item.message).join("\n"); } await this.update({ id: site.id, checkStatus: "error", lastCheckTime: dayjs().valueOf(), - error: message + error: message, }); if (!notify) { return; } try { - await this.sendCheckErrorNotify(site.id,false,setting); + await this.sendCheckErrorNotify(site.id, false, setting); } catch (e) { logger.error("send notify error", e); } } } - async checkAllIp(site: SiteInfoEntity,retryTimes = null,setting: UserSiteMonitorSetting) { + async checkAllIp(site: SiteInfoEntity, retryTimes = null, setting: UserSiteMonitorSetting) { if (!site.ipCheck) { return; } @@ -248,11 +248,11 @@ export class SiteInfoService extends BaseService { errorMessage += `${item.ipAddress}:${item.error}; \n`; } else if (item.certExpiresTime !== certExpiresTime && !site.ipIgnoreCoherence) { errorMessage += `${item.ipAddress}:与主站证书过期时间不一致(主站:${dayjs(certExpiresTime).format("YYYY-MM-DD")},IP:${dayjs(item.certExpiresTime).format("YYYY-MM-DD")}); \n`; - } else if (isExpired){ + } else if (isExpired) { errorMessage += `${item.ipAddress}:证书已过期(过期时间:${dayjs(item.certExpiresTime).format("YYYY-MM-DD")}); \n`; - }else if (isWillExpired){ + } else if (isWillExpired) { errorMessage += `${item.ipAddress}:证书将过期(过期时间:${dayjs(item.certExpiresTime).format("YYYY-MM-DD")}); \n`; - }else { + } else { errorCount--; } } @@ -262,7 +262,7 @@ export class SiteInfoService extends BaseService { id: site.id, checkStatus: "ok", error: "", - ipErrorCount: 0 + ipErrorCount: 0, }); return; } @@ -270,20 +270,19 @@ export class SiteInfoService extends BaseService { id: site.id, checkStatus: "error", error: errorMessage, - ipErrorCount: errorCount + ipErrorCount: errorCount, }); try { - await this.sendCheckErrorNotify(site.id, true,setting); + await this.sendCheckErrorNotify(site.id, true, setting); } catch (e) { logger.error("send notify error", e); } }; if (site.ipSyncAuto === false) { - await this.siteIpService.checkAll(site, retryTimes,onFinished); - }else{ - await this.siteIpService.syncAndCheck(site, retryTimes,onFinished); + await this.siteIpService.checkAll(site, retryTimes, onFinished); + } else { + await this.siteIpService.syncAndCheck(site, retryTimes, onFinished); } - } /** @@ -298,13 +297,13 @@ export class SiteInfoService extends BaseService { throw new Error("站点不存在"); } - this.doCheck(site, notify, retryTimes).catch((err) => { + this.doCheck(site, notify, retryTimes).catch(err => { logger.error("check site error", err); }); - return + return; } - async sendCheckErrorNotify(siteId: number, fromIpCheck = false,setting: UserSiteMonitorSetting) { + async sendCheckErrorNotify(siteId: number, fromIpCheck = false, setting: UserSiteMonitorSetting) { const site = await this.info(siteId); const url = await this.notificationService.getBindUrl("#/certd/monitor/site"); // 发邮件 @@ -319,13 +318,13 @@ export class SiteInfoService extends BaseService { content: `站点名称: ${site.name} \n站点域名: ${site.domain} \n错误信息:${site.error}`, errorMessage: site.error, notificationType: "siteCheckError", - } + }, }, site.userId ); } - async sendExpiresNotify(siteId: number,setting: UserSiteMonitorSetting) { + async sendExpiresNotify(siteId: number, setting: UserSiteMonitorSetting) { const tipDays = setting?.certValidDays || 10; const site = await this.info(siteId); const expires = site.certExpiresTime; @@ -345,7 +344,7 @@ export class SiteInfoService extends BaseService { url, errorMessage: "站点证书即将过期", notificationType: "siteCertExpireRemind", - } + }, }, site.userId ); @@ -362,7 +361,7 @@ export class SiteInfoService extends BaseService { url, errorMessage: "站点证书已过期", notificationType: "siteCertExpireRemind", - } + }, }, site.userId ); @@ -370,45 +369,44 @@ export class SiteInfoService extends BaseService { } async checkList(sites: SiteInfoEntity[]) { - const cache = {} - const getFromCache = async (userId: number,projectId?: number) =>{ - const key = `${userId}_${projectId??""}` + const cache = {}; + const getFromCache = async (userId: number, projectId?: number) => { + const key = `${userId}_${projectId ?? ""}`; if (cache[key]) { return cache[key]; } - const setting = await this.userSettingsService.getSetting(userId,projectId, UserSiteMonitorSetting) - cache[key] = setting + const setting = await this.userSettingsService.getSetting(userId, projectId, UserSiteMonitorSetting); + cache[key] = setting; return setting; - } + }; for (const site of sites) { - const setting = await getFromCache(site.userId,site.projectId) - let retryTimes = setting?.retryTimes - this.doCheck(site,true,retryTimes).catch(e => { + const setting = await getFromCache(site.userId, site.projectId); + const retryTimes = setting?.retryTimes; + this.doCheck(site, true, retryTimes).catch(e => { logger.error(`检查站点证书失败,${site.domain}`, e.message); }); await utils.sleep(100); } } - async getSetting(userId: number,projectId?: number) { - return await this.userSettingsService.getSetting(userId,projectId, UserSiteMonitorSetting); + async getSetting(userId: number, projectId?: number) { + return await this.userSettingsService.getSetting(userId, projectId, UserSiteMonitorSetting); } - async saveSetting(userId: number,projectId: number, bean: UserSiteMonitorSetting) { - await this.userSettingsService.saveSetting(userId,projectId, bean); - if(bean.cron){ + async saveSetting(userId: number, projectId: number, bean: UserSiteMonitorSetting) { + await this.userSettingsService.saveSetting(userId, projectId, bean); + if (bean.cron) { //注册job - await this.registerSiteMonitorJob(userId,projectId); - }else{ - this.clearSiteMonitorJob(userId,projectId); + await this.registerSiteMonitorJob(userId, projectId); + } else { + this.clearSiteMonitorJob(userId, projectId); } } async ipCheckChange(req: { id: any; ipCheck: any }) { - await this.update({ id: req.id, - ipCheck: req.ipCheck + ipCheck: req.ipCheck, }); if (req.ipCheck) { const site = await this.info(req.id); @@ -419,7 +417,7 @@ export class SiteInfoService extends BaseService { async disabledChange(req: { disabled: any; id: any }) { await this.update({ id: req.id, - disabled: req.disabled + disabled: req.disabled, }); if (!req.disabled) { const site = await this.info(req.id); @@ -427,7 +425,7 @@ export class SiteInfoService extends BaseService { } } - async doImport(req: { text: string; userId: number,groupId?:number,projectId?:number }) { + async doImport(req: { text: string; userId: number; groupId?: number; projectId?: number }) { if (!req.text) { throw new Error("text is required"); } @@ -459,7 +457,7 @@ export class SiteInfoService extends BaseService { if (arr.length > 2) { name = arr[2] || domain; } - let remark:string = ""; + let remark = ""; if (arr.length > 3) { remark = arr[3] || ""; } @@ -471,7 +469,7 @@ export class SiteInfoService extends BaseService { userId: req.userId, remark, groupId: req.groupId, - projectId: req.projectId + projectId: req.projectId, }); } @@ -485,77 +483,77 @@ export class SiteInfoService extends BaseService { await batchAdd(list); } - clearSiteMonitorJob(userId: number,projectId?: number) { - this.cron.remove(`siteMonitor_${userId}_${projectId||""}`); + clearSiteMonitorJob(userId: number, projectId?: number) { + this.cron.remove(`siteMonitor_${userId}_${projectId || ""}`); } - async registerSiteMonitorJob(userId?: number,projectId?: number) { - const setting = await this.userSettingsService.getSetting(userId,projectId, UserSiteMonitorSetting); + async registerSiteMonitorJob(userId?: number, projectId?: number) { + const setting = await this.userSettingsService.getSetting(userId, projectId, UserSiteMonitorSetting); if (!setting.cron) { return; } //注册个人的 或项目的 this.cron.register({ - name: `siteMonitor_${userId}_${projectId||""}`, + name: `siteMonitor_${userId}_${projectId || ""}`, cron: setting.cron, - job: () => this.triggerJobOnce(userId,projectId), + job: () => this.triggerJobOnce(userId, projectId), }); } - async triggerCommonJob(){ + async triggerCommonJob() { //遍历用户 - const userIds = await this.userService.getAllUserIds() + const userIds = await this.userService.getAllUserIds(); for (const userId of userIds) { - const setting = await this.userSettingsService.getSetting(userId,null,UserSiteMonitorSetting) - if(setting && setting.cron){ + const setting = await this.userSettingsService.getSetting(userId, null, UserSiteMonitorSetting); + if (setting && setting.cron) { //该用户有自定义检查时间,跳过公共job - continue + continue; } - await this.triggerJobOnce(userId) + await this.triggerJobOnce(userId); } //遍历项目 - const projectIds = await this.projectService.getAllProjectIds() + const projectIds = await this.projectService.getAllProjectIds(); for (const projectId of projectIds) { - const userId = Constants.enterpriseUserId - const setting = await this.userSettingsService.getSetting(userId,projectId,UserSiteMonitorSetting) - if(setting && setting.cron){ + const userId = Constants.enterpriseUserId; + const setting = await this.userSettingsService.getSetting(userId, projectId, UserSiteMonitorSetting); + if (setting && setting.cron) { //该项目有自定义检查时间,跳过公共job - continue + continue; } - await this.triggerJobOnce(userId,projectId) + await this.triggerJobOnce(userId, projectId); } } - async triggerJobOnce(userId?:number,projectId?:number) { - if(userId==null){ + async triggerJobOnce(userId?: number, projectId?: number) { + if (userId == null) { throw new Error("userId is required"); } - const query:any = { disabled: false }; + const query: any = { disabled: false }; query.userId = userId; - if(projectId){ + if (projectId) { query.projectId = projectId; } const siteCount = await this.repository.count({ where: query, }); if (siteCount === 0) { - logger.info(`用户/项目[${userId}_${projectId||""}]没有站点证书需要检查`) + logger.info(`用户/项目[${userId}_${projectId || ""}]没有站点证书需要检查`); return; } - logger.info(`站点证书检查开始执行[${userId}_${projectId||""}]`); - - let jobEntity :Partial = null; - - jobEntity = { + logger.info(`站点证书检查开始执行[${userId}_${projectId || ""}]`); + + let jobEntity: Partial = null; + + jobEntity = { userId, projectId, - type:"siteCertMonitor", - title: '站点证书检查', - result:"start", - startAt:new Date().getTime(), - } + type: "siteCertMonitor", + title: "站点证书检查", + result: "start", + startAt: new Date().getTime(), + }; await this.jobHistoryService.add(jobEntity); let offset = 0; const limit = 50; @@ -575,17 +573,17 @@ export class SiteInfoService extends BaseService { await this.checkList(records); } - logger.info(`站点证书检查完成[${userId}_${projectId||""}]`); + logger.info(`站点证书检查完成[${userId}_${projectId || ""}]`); await this.jobHistoryService.update({ id: jobEntity.id, result: "done", - content:`共检查${count}个站点`, - endAt:new Date().getTime(), - updateTime:new Date(), + content: `共检查${count}个站点`, + endAt: new Date().getTime(), + updateTime: new Date(), }); } - async batchDelete(ids: number[], userId: number,projectId?:number): Promise { + async batchDelete(ids: number[], userId: number, projectId?: number): Promise { await this.repository.delete({ id: In(ids), userId, diff --git a/packages/ui/certd-server/src/modules/monitor/service/site-ip-service.ts b/packages/ui/certd-server/src/modules/monitor/service/site-ip-service.ts index b3f696601..0e486e2ab 100644 --- a/packages/ui/certd-server/src/modules/monitor/service/site-ip-service.ts +++ b/packages/ui/certd-server/src/modules/monitor/service/site-ip-service.ts @@ -1,21 +1,21 @@ -import {Inject, Provide, Scope, ScopeEnum} from "@midwayjs/core"; -import {BaseService, SysSettingsService} from "@certd/lib-server"; -import {InjectEntityModel} from "@midwayjs/typeorm"; -import {Repository} from "typeorm"; -import {SiteInfoEntity} from "../entity/site-info.js"; -import {NotificationService} from "../../pipeline/service/notification-service.js"; -import {UserSuiteService} from "@certd/commercial-core"; -import {UserSettingsService} from "../../mine/service/user-settings-service.js"; -import {SiteIpEntity} from "../entity/site-ip.js"; +import { Inject, Provide, Scope, ScopeEnum } from "@midwayjs/core"; +import { BaseService, SysSettingsService } from "@certd/lib-server"; +import { InjectEntityModel } from "@midwayjs/typeorm"; +import { Repository } from "typeorm"; +import { SiteInfoEntity } from "../entity/site-info.js"; +import { NotificationService } from "../../pipeline/service/notification-service.js"; +import { UserSuiteService } from "@certd/commercial-core"; +import { UserSettingsService } from "../../mine/service/user-settings-service.js"; +import { SiteIpEntity } from "../entity/site-ip.js"; import dnsSdk from "dns"; -import {logger} from "@certd/basic"; +import { logger } from "@certd/basic"; import dayjs from "dayjs"; -import {siteTester} from "./site-tester.js"; -import {PeerCertificate} from "tls"; +import { siteTester } from "./site-tester.js"; +import { PeerCertificate } from "tls"; import { UserSiteMonitorSetting } from "../../mine/service/models.js"; import { dnsContainer } from "./dns-custom.js"; -const dns = dnsSdk.promises; +const dns = dnsSdk.promises; @Provide() @Scope(ScopeEnum.Request, { allowDowngrade: true }) @@ -47,12 +47,11 @@ export class SiteIpService extends BaseService { throw new Error("userId is required"); } data.disabled = false; - const res= await super.add(data); - await this.updateIpCount(data.siteId) - return res + const res = await super.add(data); + await this.updateIpCount(data.siteId); + return res; } - async update(data: any) { if (!data.id) { throw new Error("id is required"); @@ -61,52 +60,52 @@ export class SiteIpService extends BaseService { await super.update(data); } - - - async sync(entity: SiteInfoEntity,check:boolean = true) { - + async sync(entity: SiteInfoEntity, check = true) { const domain = entity.domain; - const setting = await this.userSettingsService.getSetting(entity.userId,entity.projectId, UserSiteMonitorSetting); + const setting = await this.userSettingsService.getSetting(entity.userId, entity.projectId, UserSiteMonitorSetting); - const dnsServer = setting.dnsServer - let resolver = dns + const dnsServer = setting.dnsServer; + let resolver = dns; if (dnsServer && dnsServer.length > 0) { - resolver = dnsContainer.getDns(dnsServer) as any + resolver = dnsContainer.getDns(dnsServer) as any; } //从域名解析中获取所有ip - const ips = await this.getAllIpsFromDomain(domain,resolver,entity.ipSyncMode); - if (ips.length === 0 ) { - logger.warn(`没有发现${domain}的IP`) - return + const ips = await this.getAllIpsFromDomain(domain, resolver, entity.ipSyncMode); + if (ips.length === 0) { + logger.warn(`没有发现${domain}的IP`); + return; } const oldIps = await this.repository.find({ - where:{ - siteId: entity.id, - from:"sync" - } - }) + where: { + siteId: entity.id, + from: "sync", + }, + }); - let hasChanged = true - if (oldIps.length === ips.length ){ + let hasChanged = true; + if (oldIps.length === ips.length) { //检查是否有变化 - const oldIpList = oldIps.map(ip=>ip.ipAddress).sort().join(",") - const newIpList = ips.sort().join(",") - if(oldIpList === newIpList){ - //无变化 - hasChanged = false - } + const oldIpList = oldIps + .map(ip => ip.ipAddress) + .sort() + .join(","); + const newIpList = ips.sort().join(","); + if (oldIpList === newIpList) { + //无变化 + hasChanged = false; + } } - if(hasChanged){ - logger.info(`发现${domain}的IP变化,需要更新,旧IP:${oldIps.map(ip=>ip.ipAddress).join(",")},新IP:${ips.join(",")}`) + if (hasChanged) { + logger.info(`发现${domain}的IP变化,需要更新,旧IP:${oldIps.map(ip => ip.ipAddress).join(",")},新IP:${ips.join(",")}`); //有变化需要更新 //删除所有的ip await this.repository.delete({ siteId: entity.id, - from: "sync" + from: "sync", }); //添加新的ip @@ -116,36 +115,36 @@ export class SiteIpService extends BaseService { userId: entity.userId, siteId: entity.id, from: "sync", - disabled:false, + disabled: false, }); - await this.updateIpCount(entity.id) + await this.updateIpCount(entity.id); } } - if (check){ + if (check) { await this.checkAll(entity); } } - async check(ipId: number, domain: string, port: number,retryTimes = null ,tipDays = 10) { - if(!ipId){ - return + async check(ipId: number, domain: string, port: number, retryTimes = null, tipDays = 10) { + if (!ipId) { + return; } const entity = await this.info(ipId); if (!entity) { return; } - logger.info(`开始测试站点ip: id=${entity.id},ip=${entity.ipAddress}`) + logger.info(`开始测试站点ip: id=${entity.id},ip=${entity.ipAddress}`); try { await this.update({ id: entity.id, checkStatus: "checking", - lastCheckTime: dayjs().valueOf() + lastCheckTime: dayjs().valueOf(), }); const res = await siteTester.test({ host: domain, port: port, - retryTimes : retryTimes??3, - ipAddress: entity.ipAddress + retryTimes: retryTimes ?? 3, + ipAddress: entity.ipAddress, }); const certi: PeerCertificate = res.certificate; @@ -170,39 +169,38 @@ export class SiteIpService extends BaseService { certExpiresTime: dayjs(expires).valueOf(), lastCheckTime: dayjs().valueOf(), error: null, - checkStatus: "ok" + checkStatus: "ok", }; await this.update(updateData); - logger.info(`测试站点ip成功: id=${updateData.id},ip=${entity.ipAddress},expiresTime=${updateData.certExpiresTime}`) + logger.info(`测试站点ip成功: id=${updateData.id},ip=${entity.ipAddress},expiresTime=${updateData.certExpiresTime}`); return { ...updateData, ipAddress: entity.ipAddress, - } - + }; } catch (e) { logger.error("check site ip error", e); await this.update({ id: entity.id, checkStatus: "error", lastCheckTime: dayjs().valueOf(), - error: e.message + error: e.message, }); return { id: entity.id, ipAddress: entity.ipAddress, - error: e.message - } + error: e.message, + }; } } - async checkAll(siteInfo: SiteInfoEntity,retryTimes = null,onFinish?: (e: any) => void) { + async checkAll(siteInfo: SiteInfoEntity, retryTimes = null, onFinish?: (e: any) => void) { const siteId = siteInfo.id; const ips = await this.repository.find({ where: { - siteId: siteId - } + siteId: siteId, + }, }); const domain = siteInfo.domain; const port = siteInfo.httpsPort; @@ -210,44 +208,44 @@ export class SiteIpService extends BaseService { for (const item of ips) { const func = async () => { try { - return await this.check(item.id, domain, port,retryTimes); + return await this.check(item.id, domain, port, retryTimes); } catch (e) { logger.error("check site item error", e); return { ...item, - error:e.message - } + error: e.message, + }; } - } + }; promiseList.push(func()); } - Promise.all(promiseList).then((res)=>{ - const finished = res.filter(item=>{ - return item!=null - }) + Promise.all(promiseList).then(res => { + const finished = res.filter(item => { + return item != null; + }); if (onFinish) { - onFinish && onFinish(finished) + onFinish && onFinish(finished); } - }) + }); } - async getAllIpsFromDomain(domain: string,resolver:any = dns,ipSyncMode:string = "all"):Promise { - const getFromV4 = async ():Promise => { - try{ + async getAllIpsFromDomain(domain: string, resolver: any = dns, ipSyncMode = "all"): Promise { + const getFromV4 = async (): Promise => { + try { return await resolver.resolve4(domain); - }catch (err) { - logger.warn(`[${domain}] resolve4 error`, err) - return [] + } catch (err) { + logger.warn(`[${domain}] resolve4 error`, err); + return []; } - } - const getFromV6 = async ():Promise => { - try{ + }; + const getFromV6 = async (): Promise => { + try { return await resolver.resolve6(domain); - }catch (err) { - logger.warn(`[${domain}] resolve6 error`, err) - return [] + } catch (err) { + logger.warn(`[${domain}] resolve6 error`, err); + return []; } - } + }; if (ipSyncMode === "ipv4") { return await getFromV4(); @@ -261,24 +259,25 @@ export class SiteIpService extends BaseService { }); } - - async updateIpCount(siteId:number){ + async updateIpCount(siteId: number) { const count = await this.repository.count({ - where:{ - siteId - } - }) - await this.siteInfoRepository.update({ - //where - id:siteId, - }, + where: { + siteId, + }, + }); + await this.siteInfoRepository.update( + { + //where + id: siteId, + }, { //update - ipCount:count - }) + ipCount: count, + } + ); } - async doImport(req: { text: string; userId:number, siteId:number,projectId?:number }) { + async doImport(req: { text: string; userId: number; siteId: number; projectId?: number }) { if (!req.text) { throw new Error("text is required"); } @@ -289,9 +288,9 @@ export class SiteIpService extends BaseService { const siteEntity = await this.siteInfoRepository.findOne({ where: { id: req.siteId, - userId:req.userId, - projectId:req.projectId - } + userId: req.userId, + projectId: req.projectId, + }, }); if (!siteEntity) { throw new Error(`站点${req.siteId}不存在`); @@ -307,11 +306,11 @@ export class SiteIpService extends BaseService { continue; } list.push({ - ipAddress:item, + ipAddress: item, userId: userId, siteId: req.siteId, from: "import", - disabled:false, + disabled: false, projectId: req.projectId, }); } @@ -324,8 +323,8 @@ export class SiteIpService extends BaseService { await batchAdd(list); } - async syncAndCheck(siteEntity:SiteInfoEntity,retryTimes = null,onFinish?: (e: any) => void){ - await this.sync(siteEntity,false); - await this.checkAll(siteEntity,retryTimes,onFinish); + async syncAndCheck(siteEntity: SiteInfoEntity, retryTimes = null, onFinish?: (e: any) => void) { + await this.sync(siteEntity, false); + await this.checkAll(siteEntity, retryTimes, onFinish); } } diff --git a/packages/ui/certd-server/src/modules/monitor/service/site-tester.ts b/packages/ui/certd-server/src/modules/monitor/service/site-tester.ts index a3d134709..0c48b9ab6 100644 --- a/packages/ui/certd-server/src/modules/monitor/service/site-tester.ts +++ b/packages/ui/certd-server/src/modules/monitor/service/site-tester.ts @@ -2,7 +2,7 @@ import { logger, safePromise, utils } from "@certd/basic"; import { merge } from "lodash-es"; import https from "https"; import { PeerCertificate } from "tls"; -import {DnsCustom} from "./dns-custom.js"; +import { DnsCustom } from "./dns-custom.js"; export type SiteTestReq = { host: string; // 只用域名部分 @@ -20,8 +20,8 @@ export type SiteTestRes = { export class SiteTester { async test(req: SiteTestReq): Promise { - const req_ = {...req} - delete req_.customDns + const req_ = { ...req }; + delete req_.customDns; logger.info("测试站点:", JSON.stringify(req_)); const maxRetryTimes = req.retryTimes == null ? 3 : req.retryTimes; let tryCount = 0; @@ -49,40 +49,40 @@ export class SiteTester { { port: 443, method: "GET", - rejectUnauthorized: false + rejectUnauthorized: false, }, req ); - let customLookup = null + let customLookup = null; if (req.ipAddress) { //使用固定的ip const ipAddress = req.ipAddress; options.headers = { host: options.host, //sni - servername: options.host + servername: options.host, }; options.host = ipAddress; - }else if (req.customDns ) { + } else if (req.customDns) { // 非ip address 请求时 - const customDns = req.customDns - customLookup = async (hostname:string, options:any, callback)=> { + const customDns = req.customDns; + customLookup = async (hostname: string, options: any, callback) => { console.log(hostname, options); // { family: undefined, hints: 0, all: true } - const res = await customDns.lookup(hostname, options) - console.log("custom lookup res:",res) + const res = await customDns.lookup(hostname, options); + console.log("custom lookup res:", res); if (!res || res.length === 0) { callback(new Error("没有解析到IP")); } callback(null, res); - } + }; } - const agentOptions:any = { keepAlive: false }; + const agentOptions: any = { keepAlive: false }; if (customLookup) { - agentOptions.lookup = customLookup + agentOptions.lookup = customLookup; } options.agent = new https.Agent(agentOptions); @@ -95,19 +95,19 @@ export class SiteTester { }); // ✅ 关键:在 'socket' 事件中获取证书(握手完成后立即执行) - req.on('socket', (socket:any) => { - socket.on('secureConnect', () => { + req.on("socket", (socket: any) => { + socket.on("secureConnect", () => { // TLS握手完成,证书已经可用 const certificate = socket.getPeerCertificate(); if (certificate.subject) { - logger.info('证书获取成功', certificate.subject); + logger.info("证书获取成功", certificate.subject); resolve({ - certificate + certificate, }); - }else{ + } else { logger.warn("证书信息为空"); resolve({ - certificate: null + certificate: null, }); } }); diff --git a/packages/ui/certd-server/src/modules/open/entity/open-key.ts b/packages/ui/certd-server/src/modules/open/entity/open-key.ts index 1e8fe0614..6bfd6b34e 100644 --- a/packages/ui/certd-server/src/modules/open/entity/open-key.ts +++ b/packages/ui/certd-server/src/modules/open/entity/open-key.ts @@ -1,28 +1,28 @@ -import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; +import { Column, Entity, PrimaryGeneratedColumn } from "typeorm"; -@Entity('cd_open_key') +@Entity("cd_open_key") export class OpenKeyEntity { @PrimaryGeneratedColumn() id: number; - @Column({ name: 'user_id', comment: '用户id' }) + @Column({ name: "user_id", comment: "用户id" }) userId: number; - @Column({ name: 'key_id', comment: 'keyId' }) + @Column({ name: "key_id", comment: "keyId" }) keyId: string; - @Column({ name: 'key_secret', comment: 'keySecret' }) + @Column({ name: "key_secret", comment: "keySecret" }) keySecret: string; - @Column({ name: 'scope', comment: '权限范围' }) + @Column({ name: "scope", comment: "权限范围" }) scope: string; // open 仅开放接口、 user 用户所有权限 - @Column({ name: 'project_id', comment: '项目id' }) + @Column({ name: "project_id", comment: "项目id" }) projectId: number; - @Column({ name: 'create_time', comment: '创建时间', default: () => 'CURRENT_TIMESTAMP' }) + @Column({ name: "create_time", comment: "创建时间", default: () => "CURRENT_TIMESTAMP" }) createTime: Date; - @Column({ name: 'update_time', comment: '修改时间', default: () => 'CURRENT_TIMESTAMP' }) + @Column({ name: "update_time", comment: "修改时间", default: () => "CURRENT_TIMESTAMP" }) updateTime: Date; } diff --git a/packages/ui/certd-server/src/modules/open/service/open-key-service.ts b/packages/ui/certd-server/src/modules/open/service/open-key-service.ts index 778be22aa..9ddb4b4e5 100644 --- a/packages/ui/certd-server/src/modules/open/service/open-key-service.ts +++ b/packages/ui/certd-server/src/modules/open/service/open-key-service.ts @@ -1,11 +1,11 @@ -import { Provide, Scope, ScopeEnum } from '@midwayjs/core'; -import { BaseService, Constants, CodeException, PageReq } from '@certd/lib-server'; -import { InjectEntityModel } from '@midwayjs/typeorm'; -import { Repository } from 'typeorm'; -import { OpenKeyEntity } from '../entity/open-key.js'; -import { utils } from '@certd/basic'; -import crypto from 'crypto'; -import dayjs from 'dayjs'; +import { Provide, Scope, ScopeEnum } from "@midwayjs/core"; +import { BaseService, Constants, CodeException, PageReq } from "@certd/lib-server"; +import { InjectEntityModel } from "@midwayjs/typeorm"; +import { Repository } from "typeorm"; +import { OpenKeyEntity } from "../entity/open-key.js"; +import { utils } from "@certd/basic"; +import crypto from "crypto"; +import dayjs from "dayjs"; export type OpenKey = { userId: number; @@ -31,34 +31,34 @@ export class OpenKeyService extends BaseService { } async add(bean: OpenKeyEntity) { - return await this.generate(bean.userId,bean.projectId, bean.scope); + return await this.generate(bean.userId, bean.projectId, bean.scope); } - async generate(userId: number, projectId?: number, scope: string = 'open') { - const keyId = utils.id.simpleNanoId(18) + '_key'; + async generate(userId: number, projectId?: number, scope = "open") { + const keyId = utils.id.simpleNanoId(18) + "_key"; const secretKey = crypto.randomBytes(32); - const keySecret = Buffer.from(secretKey).toString('hex'); + const keySecret = Buffer.from(secretKey).toString("hex"); const entity = new OpenKeyEntity(); entity.userId = userId; entity.projectId = projectId; entity.keyId = keyId; entity.keySecret = keySecret; - entity.scope = scope ?? 'open'; + entity.scope = scope ?? "open"; await this.repository.save(entity); return entity; } async getByKeyId(keyId: string) { if (!keyId) { - throw new Error('keyId不能为空'); + throw new Error("keyId不能为空"); } return this.repository.findOne({ where: { keyId } }); } async verifyOpenKey(openKey: string): Promise { // openkey 组成,content = base64({keyId,t,encrypt,signType}) ,sign = md5({keyId,t,encrypt,signType}secret) , key = content.sign - const [content, sign] = openKey.split('.'); - const contentJson = Buffer.from(content, 'base64').toString(); + const [content, sign] = openKey.split("."); + const contentJson = Buffer.from(content, "base64").toString(); const { keyId, t, encrypt, signType } = JSON.parse(contentJson); // 正负不超过3分钟 ,timestamps单位为秒 if (Math.abs(Number(t) - Math.floor(Date.now() / 1000)) > 180) { @@ -67,22 +67,22 @@ export class OpenKeyService extends BaseService { const entity = await this.getByKeyId(keyId); if (!entity) { - throw new Error('openKey不存在'); + throw new Error("openKey不存在"); } const secret = entity.keySecret; - let computedSign = ''; - if (signType === 'md5') { + let computedSign = ""; + if (signType === "md5") { computedSign = utils.hash.md5(contentJson + secret); - } else if (signType === 'sha256') { + } else if (signType === "sha256") { computedSign = utils.hash.sha256(contentJson + secret); } else { throw new CodeException(Constants.res.openKeySignTypeError); } - if (Buffer.from(computedSign).toString('base64') !== sign) { + if (Buffer.from(computedSign).toString("base64") !== sign) { throw new CodeException(Constants.res.openKeySignError); } - if (entity.userId==null) { + if (entity.userId == null) { throw new CodeException(Constants.res.openKeyError); } @@ -98,21 +98,21 @@ export class OpenKeyService extends BaseService { async getApiToken(id: number) { if (!id) { - throw new Error('id不能为空'); + throw new Error("id不能为空"); } const entity = await this.repository.findOne({ where: { id } }); if (!entity) { - throw new Error('id不存在'); + throw new Error("id不存在"); } const { keyId, keySecret } = entity; const openKey = { keyId, t: dayjs().unix(), encrypt: false, - signType: 'md5', + signType: "md5", }; const content = JSON.stringify(openKey); const sign = utils.hash.md5(content + keySecret); - return Buffer.from(content).toString('base64') + '.' + Buffer.from(sign).toString('base64'); + return Buffer.from(content).toString("base64") + "." + Buffer.from(sign).toString("base64"); } } diff --git a/packages/ui/certd-server/src/modules/pipeline/entity/history-log.ts b/packages/ui/certd-server/src/modules/pipeline/entity/history-log.ts index 0f2425b88..7fa40edf0 100644 --- a/packages/ui/certd-server/src/modules/pipeline/entity/history-log.ts +++ b/packages/ui/certd-server/src/modules/pipeline/entity/history-log.ts @@ -1,44 +1,44 @@ -import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; +import { Column, Entity, PrimaryGeneratedColumn } from "typeorm"; -@Entity('pi_history_log') +@Entity("pi_history_log") export class HistoryLogEntity { @PrimaryGeneratedColumn() id: number; - @Column({ name: 'user_id', comment: '用户id' }) + @Column({ name: "user_id", comment: "用户id" }) userId: number; - @Column({ name: 'pipeline_id', comment: '流水线' }) + @Column({ name: "pipeline_id", comment: "流水线" }) pipelineId: number; - @Column({ name: 'history_id', comment: '历史id' }) + @Column({ name: "history_id", comment: "历史id" }) historyId: number; @Column({ - name: 'node_id', - comment: '任务节点id', + name: "node_id", + comment: "任务节点id", length: 100, nullable: true, }) nodeId: string; - @Column({ comment: '日志内容', length: 40960, nullable: true }) + @Column({ comment: "日志内容", length: 40960, nullable: true }) logs: string; - @Column({ name: 'project_id', comment: '项目id' }) + @Column({ name: "project_id", comment: "项目id" }) projectId: number; @Column({ - name: 'create_time', - comment: '创建时间', - default: () => 'CURRENT_TIMESTAMP', + name: "create_time", + comment: "创建时间", + default: () => "CURRENT_TIMESTAMP", }) createTime: Date; @Column({ - name: 'update_time', - comment: '修改时间', - default: () => 'CURRENT_TIMESTAMP', + name: "update_time", + comment: "修改时间", + default: () => "CURRENT_TIMESTAMP", }) updateTime: Date; } diff --git a/packages/ui/certd-server/src/modules/pipeline/entity/history.ts b/packages/ui/certd-server/src/modules/pipeline/entity/history.ts index 5fb7aa2b7..ce8d0e259 100644 --- a/packages/ui/certd-server/src/modules/pipeline/entity/history.ts +++ b/packages/ui/certd-server/src/modules/pipeline/entity/history.ts @@ -1,47 +1,46 @@ -import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; +import { Column, Entity, PrimaryGeneratedColumn } from "typeorm"; -@Entity('pi_history') +@Entity("pi_history") export class HistoryEntity { @PrimaryGeneratedColumn() id: number; - @Column({ name: 'user_id', comment: '用户id' }) + @Column({ name: "user_id", comment: "用户id" }) userId: number; - @Column({ name: 'pipeline_id', comment: '流水线' }) + @Column({ name: "pipeline_id", comment: "流水线" }) pipelineId: number; - @Column({ comment: '运行状态', length: 40960, nullable: true }) + @Column({ comment: "运行状态", length: 40960, nullable: true }) pipeline: string; - @Column({ comment: '结果状态', length: 20, nullable: true }) + @Column({ comment: "结果状态", length: 20, nullable: true }) status: string; - @Column({ name: 'trigger_type',comment: '触发类型', length: 20, nullable: true }) + @Column({ name: "trigger_type", comment: "触发类型", length: 20, nullable: true }) triggerType: string; @Column({ - name: 'end_time', - comment: '结束时间', + name: "end_time", + comment: "结束时间", nullable: true, }) endTime: Date; - @Column({ name: 'project_id', comment: '项目id' }) + @Column({ name: "project_id", comment: "项目id" }) projectId: number; @Column({ - name: 'create_time', - comment: '创建时间', - default: () => 'CURRENT_TIMESTAMP', + name: "create_time", + comment: "创建时间", + default: () => "CURRENT_TIMESTAMP", }) createTime: Date; @Column({ - name: 'update_time', - comment: '修改时间', - default: () => 'CURRENT_TIMESTAMP', + name: "update_time", + comment: "修改时间", + default: () => "CURRENT_TIMESTAMP", }) updateTime: Date; - pipelineTitle: string; diff --git a/packages/ui/certd-server/src/modules/pipeline/entity/notification.ts b/packages/ui/certd-server/src/modules/pipeline/entity/notification.ts index b1271e3ad..05a92396a 100644 --- a/packages/ui/certd-server/src/modules/pipeline/entity/notification.ts +++ b/packages/ui/certd-server/src/modules/pipeline/entity/notification.ts @@ -1,41 +1,41 @@ -import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; +import { Column, Entity, PrimaryGeneratedColumn } from "typeorm"; -@Entity('pi_notification') +@Entity("pi_notification") export class NotificationEntity { @PrimaryGeneratedColumn() id: number; - @Column({ name: 'key_id', comment: 'key_id', length: 100 }) + @Column({ name: "key_id", comment: "key_id", length: 100 }) keyId: string; - @Column({ name: 'user_id', comment: 'UserId' }) + @Column({ name: "user_id", comment: "UserId" }) userId: number; - @Column({ name: 'type', comment: '通知类型' }) + @Column({ name: "type", comment: "通知类型" }) type: string; - @Column({ name: 'name', comment: '名称' }) + @Column({ name: "name", comment: "名称" }) name: string; - @Column({ name: 'setting', comment: '通知配置', length: 10240 }) + @Column({ name: "setting", comment: "通知配置", length: 10240 }) setting: string; - @Column({ name: 'is_default', comment: '是否默认' }) + @Column({ name: "is_default", comment: "是否默认" }) isDefault: boolean; - @Column({ name: 'project_id', comment: '项目id' }) + @Column({ name: "project_id", comment: "项目id" }) projectId: number; @Column({ - name: 'create_time', - comment: '创建时间', - default: () => 'CURRENT_TIMESTAMP', + name: "create_time", + comment: "创建时间", + default: () => "CURRENT_TIMESTAMP", }) createTime: Date; @Column({ - name: 'update_time', - comment: '修改时间', - default: () => 'CURRENT_TIMESTAMP', + name: "update_time", + comment: "修改时间", + default: () => "CURRENT_TIMESTAMP", }) updateTime: Date; } diff --git a/packages/ui/certd-server/src/modules/pipeline/entity/pipeline-group.ts b/packages/ui/certd-server/src/modules/pipeline/entity/pipeline-group.ts index 31d1003cc..692f34955 100644 --- a/packages/ui/certd-server/src/modules/pipeline/entity/pipeline-group.ts +++ b/packages/ui/certd-server/src/modules/pipeline/entity/pipeline-group.ts @@ -1,36 +1,36 @@ -import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; +import { Column, Entity, PrimaryGeneratedColumn } from "typeorm"; -@Entity('pi_pipeline_group') +@Entity("pi_pipeline_group") export class PipelineGroupEntity { @PrimaryGeneratedColumn() id: number; - @Column({ name: 'user_id', comment: '用户id' }) + @Column({ name: "user_id", comment: "用户id" }) userId: number; - @Column({ name: 'name', comment: '分组名称' }) + @Column({ name: "name", comment: "分组名称" }) name: string; - @Column({ name: 'icon', comment: '图标' }) + @Column({ name: "icon", comment: "图标" }) icon: string; - @Column({ name: 'favorite', comment: '收藏' }) + @Column({ name: "favorite", comment: "收藏" }) favorite: boolean; - @Column({ name: 'project_id', comment: '项目id' }) + @Column({ name: "project_id", comment: "项目id" }) projectId: number; @Column({ - name: 'create_time', - comment: '创建时间', - default: () => 'CURRENT_TIMESTAMP', + name: "create_time", + comment: "创建时间", + default: () => "CURRENT_TIMESTAMP", }) createTime: Date; @Column({ - name: 'update_time', - comment: '修改时间', - default: () => 'CURRENT_TIMESTAMP', + name: "update_time", + comment: "修改时间", + default: () => "CURRENT_TIMESTAMP", }) updateTime: Date; } diff --git a/packages/ui/certd-server/src/modules/pipeline/entity/pipeline.ts b/packages/ui/certd-server/src/modules/pipeline/entity/pipeline.ts index 6c3b0edf3..9ba9033ab 100644 --- a/packages/ui/certd-server/src/modules/pipeline/entity/pipeline.ts +++ b/packages/ui/certd-server/src/modules/pipeline/entity/pipeline.ts @@ -1,58 +1,58 @@ -import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; +import { Column, Entity, PrimaryGeneratedColumn } from "typeorm"; -@Entity('pi_pipeline') +@Entity("pi_pipeline") export class PipelineEntity { @PrimaryGeneratedColumn() id: number; - @Column({ name: 'user_id', comment: '用户id' }) + @Column({ name: "user_id", comment: "用户id" }) userId: number; - @Column({ name: 'title', comment: '标题' }) + @Column({ name: "title", comment: "标题" }) title: string; - @Column({ comment: '配置', length: 40960 }) + @Column({ comment: "配置", length: 40960 }) content: string; - @Column({ name: 'keep_history_count', comment: '历史记录保持数量', nullable: true }) + @Column({ name: "keep_history_count", comment: "历史记录保持数量", nullable: true }) keepHistoryCount: number; - @Column({ name: 'group_id', comment: '分组id', nullable: true }) + @Column({ name: "group_id", comment: "分组id", nullable: true }) groupId: number; - @Column({ comment: '备注', length: 100, nullable: true }) + @Column({ comment: "备注", length: 100, nullable: true }) remark: string; - @Column({ comment: '状态', length: 100, nullable: true }) + @Column({ comment: "状态", length: 100, nullable: true }) status: string; - @Column({ comment: '启用/禁用', nullable: true, default: false }) + @Column({ comment: "启用/禁用", nullable: true, default: false }) disabled: boolean; // cert_apply: 证书申请;cert_upload: 证书上传; backup: 备份; custom:自定义; template: 模板 - @Column({ comment: '类型', nullable: true, default: 'cert' }) + @Column({ comment: "类型", nullable: true, default: "cert" }) type: string; - @Column({ name: 'webhook_key', comment: 'webhookkey', length: 100, nullable: true }) + @Column({ name: "webhook_key", comment: "webhookkey", length: 100, nullable: true }) webhookKey: string; - @Column({ name: 'trigger_count', comment: '触发器数量', nullable: true, default: 0 }) + @Column({ name: "trigger_count", comment: "触发器数量", nullable: true, default: 0 }) triggerCount: number; // custom: 自定义; monitor: 监控; - @Column({ comment: '来源', nullable: true, default: '' }) + @Column({ comment: "来源", nullable: true, default: "" }) from: string; - @Column({ name:"template_id", comment: '关联模版id', nullable: true, default: 0 }) + @Column({ name: "template_id", comment: "关联模版id", nullable: true, default: 0 }) templateId: number; - @Column({ name:"is_template", comment: '是否模版', nullable: true, default: false }) + @Column({ name: "is_template", comment: "是否模版", nullable: true, default: false }) isTemplate: boolean; - @Column({name: 'last_history_time',comment: '最后一次执行时间',nullable: true,}) + @Column({ name: "last_history_time", comment: "最后一次执行时间", nullable: true }) lastHistoryTime: number; - @Column({name: 'valid_time',comment: '到期时间',nullable: true,default: 0}) + @Column({ name: "valid_time", comment: "到期时间", nullable: true, default: 0 }) validTime: number; // 变量 @@ -60,19 +60,18 @@ export class PipelineEntity { nextRunTime: number; - @Column({name: 'order', comment: '排序', nullable: true,}) + @Column({ name: "order", comment: "排序", nullable: true }) order: number; - @Column({ name: 'project_id', comment: '项目id' }) + @Column({ name: "project_id", comment: "项目id" }) projectId: number; - @Column({name: 'create_time',comment: '创建时间', default: () => 'CURRENT_TIMESTAMP',}) + @Column({ name: "create_time", comment: "创建时间", default: () => "CURRENT_TIMESTAMP" }) createTime: Date; @Column({ - name: 'update_time', - comment: '修改时间', - default: () => 'CURRENT_TIMESTAMP', + name: "update_time", + comment: "修改时间", + default: () => "CURRENT_TIMESTAMP", }) updateTime: Date; - } diff --git a/packages/ui/certd-server/src/modules/pipeline/entity/storage.ts b/packages/ui/certd-server/src/modules/pipeline/entity/storage.ts index aa87e1d15..bf858bb2a 100644 --- a/packages/ui/certd-server/src/modules/pipeline/entity/storage.ts +++ b/packages/ui/certd-server/src/modules/pipeline/entity/storage.ts @@ -1,41 +1,41 @@ -import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; +import { Column, Entity, PrimaryGeneratedColumn } from "typeorm"; -@Entity('pi_storage') +@Entity("pi_storage") export class StorageEntity { @PrimaryGeneratedColumn() id: number; - @Column({ name: 'user_id', comment: '用户id' }) + @Column({ name: "user_id", comment: "用户id" }) userId: number; - @Column({ name: 'scope', comment: '范围' }) + @Column({ name: "scope", comment: "范围" }) scope: string; - @Column({ name: 'namespace', comment: '命名空间' }) + @Column({ name: "namespace", comment: "命名空间" }) namespace: string; - @Column({ comment: 'version', length: 100, nullable: true }) + @Column({ comment: "version", length: 100, nullable: true }) version: string; - @Column({ comment: 'key', length: 100, nullable: true }) + @Column({ comment: "key", length: 100, nullable: true }) key: string; - @Column({ comment: 'value', length: 40960, nullable: true }) + @Column({ comment: "value", length: 40960, nullable: true }) value: string; - @Column({ name: 'project_id', comment: '项目id' }) + @Column({ name: "project_id", comment: "项目id" }) projectId: number; @Column({ - name: 'create_time', - comment: '创建时间', - default: () => 'CURRENT_TIMESTAMP', + name: "create_time", + comment: "创建时间", + default: () => "CURRENT_TIMESTAMP", }) createTime: Date; @Column({ - name: 'update_time', - comment: '修改时间', - default: () => 'CURRENT_TIMESTAMP', + name: "update_time", + comment: "修改时间", + default: () => "CURRENT_TIMESTAMP", }) updateTime: Date; } diff --git a/packages/ui/certd-server/src/modules/pipeline/entity/sub-domain.ts b/packages/ui/certd-server/src/modules/pipeline/entity/sub-domain.ts index e775ab675..03a3d5a08 100644 --- a/packages/ui/certd-server/src/modules/pipeline/entity/sub-domain.ts +++ b/packages/ui/certd-server/src/modules/pipeline/entity/sub-domain.ts @@ -1,35 +1,35 @@ -import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; +import { Column, Entity, PrimaryGeneratedColumn } from "typeorm"; /** * 子域名托管 */ -@Entity('pi_sub_domain') +@Entity("pi_sub_domain") export class SubDomainEntity { @PrimaryGeneratedColumn() id: number; - @Column({ name: 'user_id', comment: 'UserId' }) + @Column({ name: "user_id", comment: "UserId" }) userId: number; - @Column({ name: 'domain', comment: '子域名' }) + @Column({ name: "domain", comment: "子域名" }) domain: string; - @Column({ name: 'disabled', comment: '禁用' }) + @Column({ name: "disabled", comment: "禁用" }) disabled: boolean; - @Column({ name: 'project_id', comment: '项目Id' }) + @Column({ name: "project_id", comment: "项目Id" }) projectId: number; @Column({ - name: 'create_time', - comment: '创建时间', - default: () => 'CURRENT_TIMESTAMP', + name: "create_time", + comment: "创建时间", + default: () => "CURRENT_TIMESTAMP", }) createTime: Date; @Column({ - name: 'update_time', - comment: '修改时间', - default: () => 'CURRENT_TIMESTAMP', + name: "update_time", + comment: "修改时间", + default: () => "CURRENT_TIMESTAMP", }) updateTime: Date; } diff --git a/packages/ui/certd-server/src/modules/pipeline/entity/template.ts b/packages/ui/certd-server/src/modules/pipeline/entity/template.ts index bb31b641f..8702f080b 100644 --- a/packages/ui/certd-server/src/modules/pipeline/entity/template.ts +++ b/packages/ui/certd-server/src/modules/pipeline/entity/template.ts @@ -1,57 +1,55 @@ -import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; - +import { Column, Entity, PrimaryGeneratedColumn } from "typeorm"; export type PipelineTemplateType = { input: { [key: string]: { - value: string; + value: string; }; - } -} + }; +}; - -@Entity('pi_template') +@Entity("pi_template") export class TemplateEntity { @PrimaryGeneratedColumn() id: number; - @Column({ name: 'user_id', comment: '用户id' }) + @Column({ name: "user_id", comment: "用户id" }) userId: number; - @Column({ name: 'pipeline_id', comment: '流水线id' }) + @Column({ name: "pipeline_id", comment: "流水线id" }) pipelineId: number; - @Column({ name: 'title', comment: '标题' }) + @Column({ name: "title", comment: "标题" }) title: string; - @Column({ name: 'desc', comment: '说明' }) + @Column({ name: "desc", comment: "说明" }) desc: string; - @Column({ comment: '配置', length: 40960 }) + @Column({ comment: "配置", length: 40960 }) content: string; - @Column({ comment: '启用/禁用', nullable: true, default: false }) + @Column({ comment: "启用/禁用", nullable: true, default: false }) disabled: boolean; @Column({ - name: 'order', - comment: '排序', + name: "order", + comment: "排序", nullable: true, }) order: number; - @Column({ name: 'project_id', comment: '项目id' }) + @Column({ name: "project_id", comment: "项目id" }) projectId: number; @Column({ - name: 'create_time', - comment: '创建时间', - default: () => 'CURRENT_TIMESTAMP', + name: "create_time", + comment: "创建时间", + default: () => "CURRENT_TIMESTAMP", }) createTime: Date; @Column({ - name: 'update_time', - comment: '修改时间', - default: () => 'CURRENT_TIMESTAMP', + name: "update_time", + comment: "修改时间", + default: () => "CURRENT_TIMESTAMP", }) updateTime: Date; } diff --git a/packages/ui/certd-server/src/modules/pipeline/entity/vo/history-detail.ts b/packages/ui/certd-server/src/modules/pipeline/entity/vo/history-detail.ts index 7d39a9cc2..dce2dabd6 100644 --- a/packages/ui/certd-server/src/modules/pipeline/entity/vo/history-detail.ts +++ b/packages/ui/certd-server/src/modules/pipeline/entity/vo/history-detail.ts @@ -1,5 +1,5 @@ -import { HistoryEntity } from '../history.js'; -import { HistoryLogEntity } from '../history-log.js'; +import { HistoryEntity } from "../history.js"; +import { HistoryLogEntity } from "../history-log.js"; export class HistoryDetail { history: HistoryEntity; diff --git a/packages/ui/certd-server/src/modules/pipeline/entity/vo/pipeline-detail.ts b/packages/ui/certd-server/src/modules/pipeline/entity/vo/pipeline-detail.ts index dffa9fd53..556b7f088 100644 --- a/packages/ui/certd-server/src/modules/pipeline/entity/vo/pipeline-detail.ts +++ b/packages/ui/certd-server/src/modules/pipeline/entity/vo/pipeline-detail.ts @@ -1,6 +1,6 @@ -import { PipelineEntity } from '../pipeline.js'; -import { HistoryEntity } from '../history.js'; -import { HistoryLogEntity } from '../history-log.js'; +import { PipelineEntity } from "../pipeline.js"; +import { HistoryEntity } from "../history.js"; +import { HistoryLogEntity } from "../history-log.js"; export class PipelineDetail { pipeline: PipelineEntity; diff --git a/packages/ui/certd-server/src/modules/pipeline/service/addon-getter-service.ts b/packages/ui/certd-server/src/modules/pipeline/service/addon-getter-service.ts index ba6048aa6..d0f59cdf2 100644 --- a/packages/ui/certd-server/src/modules/pipeline/service/addon-getter-service.ts +++ b/packages/ui/certd-server/src/modules/pipeline/service/addon-getter-service.ts @@ -8,15 +8,13 @@ import { AddonService, newAddon, PermissionException, ValidateException } from " */ @Provide() @Scope(ScopeEnum.Request, { allowDowngrade: true }) -export class AddonGetterService { - +export class AddonGetterService { @Inject() taskServiceBuilder: TaskServiceBuilder; @Inject() addonService: AddonService; - - async getAddonById(id: any, checkUserId: boolean, userId?: number, projectId?: number, defaultAddon?:{type:string,name:string} ): Promise { + async getAddonById(id: any, checkUserId: boolean, userId?: number, projectId?: number, defaultAddon?: { type: string; name: string }): Promise { const serviceGetter = this.taskServiceBuilder.create({ userId, projectId, @@ -25,8 +23,8 @@ export class AddonGetterService { http, logger, utils, - serviceGetter - } + serviceGetter, + }; if (!id) { if (!defaultAddon) { @@ -53,7 +51,7 @@ export class AddonGetterService { const setting = JSON.parse(entity.setting ?? "{}"); const input = { id: entity.id, - ...setting + ...setting, }; return await newAddon(entity.addonType, entity.type, input, ctx); @@ -63,11 +61,10 @@ export class AddonGetterService { return await this.getAddonById(id, true, userId, projectId); } - - async getBlank(addonType:string,subType:string,projectId?: number){ - return await this.getAddonById(null,false,0,projectId,{ - type: addonType, name:subType - }) + async getBlank(addonType: string, subType: string, projectId?: number) { + return await this.getAddonById(null, false, 0, projectId, { + type: addonType, + name: subType, + }); } - } 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 d04ec2a27..6ab272c3a 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 @@ -1,6 +1,6 @@ -import { Provide, Scope, ScopeEnum } from '@midwayjs/core'; -import { pluginGroups, pluginRegistry } from '@certd/pipeline'; -import { cloneDeep } from 'lodash-es'; +import { Provide, Scope, ScopeEnum } from "@midwayjs/core"; +import { pluginGroups, pluginRegistry } from "@certd/pipeline"; +import { cloneDeep } from "lodash-es"; @Provide() @Scope(ScopeEnum.Request, { allowDowngrade: true }) @@ -14,23 +14,23 @@ export class BuiltInPluginService { continue; } //@ts-ignore - if(Plugin.define?.type && Plugin.define?.type.toLowerCase() !== 'builtin'){ + if (Plugin.define?.type && Plugin.define?.type.toLowerCase() !== "builtin") { continue; } list.push({ ...Plugin.define, key }); } list = list.sort((a, b) => { - return (a.order ?? 10 )- (b.order ?? 10); + return (a.order ?? 10) - (b.order ?? 10); }); return list; } getGroups() { - const groups:any = cloneDeep(pluginGroups); + const groups: any = cloneDeep(pluginGroups); for (const key in groups) { const group = groups[key]; group.plugins = group.plugins.sort((a, b) => { - return (a.order ?? 10 )- (b.order ?? 10); + return (a.order ?? 10) - (b.order ?? 10); }); } return groups; diff --git a/packages/ui/certd-server/src/modules/pipeline/service/db-storage.ts b/packages/ui/certd-server/src/modules/pipeline/service/db-storage.ts index 76ef7d2f2..c03b4e4eb 100644 --- a/packages/ui/certd-server/src/modules/pipeline/service/db-storage.ts +++ b/packages/ui/certd-server/src/modules/pipeline/service/db-storage.ts @@ -1,5 +1,5 @@ -import { IStorage } from '@certd/pipeline'; -import { StorageService } from './storage-service.js'; +import { IStorage } from "@certd/pipeline"; +import { StorageService } from "./storage-service.js"; export class DbStorage implements IStorage { /** @@ -13,7 +13,7 @@ export class DbStorage implements IStorage { } async remove(scope: string, namespace: string, version: string, key: string): Promise { - throw new Error('Method not implemented.'); + throw new Error("Method not implemented."); } async get(scope: string, namespace: string, version: string, key: string): Promise { diff --git a/packages/ui/certd-server/src/modules/pipeline/service/dns-provider-service.ts b/packages/ui/certd-server/src/modules/pipeline/service/dns-provider-service.ts index 32006ad33..55f194238 100644 --- a/packages/ui/certd-server/src/modules/pipeline/service/dns-provider-service.ts +++ b/packages/ui/certd-server/src/modules/pipeline/service/dns-provider-service.ts @@ -1,5 +1,5 @@ -import { Provide } from '@midwayjs/core'; -import { dnsProviderRegistry } from '@certd/plugin-cert'; +import { Provide } from "@midwayjs/core"; +import { dnsProviderRegistry } from "@certd/plugin-cert"; @Provide() export class DnsProviderService { diff --git a/packages/ui/certd-server/src/modules/pipeline/service/getter/cert-info-getter.ts b/packages/ui/certd-server/src/modules/pipeline/service/getter/cert-info-getter.ts index 462b1ee81..d664b2539 100644 --- a/packages/ui/certd-server/src/modules/pipeline/service/getter/cert-info-getter.ts +++ b/packages/ui/certd-server/src/modules/pipeline/service/getter/cert-info-getter.ts @@ -1,7 +1,7 @@ -import { CertInfo, CertReader, ICertInfoGetter } from '@certd/plugin-lib'; -import { CertInfoService } from '../../../monitor/index.js'; +import { CertInfo, CertReader, ICertInfoGetter } from "@certd/plugin-lib"; +import { CertInfoService } from "../../../monitor/index.js"; -export class CertInfoGetter implements ICertInfoGetter { +export class CertInfoGetter implements ICertInfoGetter { userId: number; projectId: number; certInfoService: CertInfoService; @@ -12,20 +12,20 @@ export class CertInfoGetter implements ICertInfoGetter { } async getByPipelineId(pipelineId: number): Promise { if (!pipelineId) { - throw new Error(`流水线id不能为空`) - } - const query :any= { - pipelineId, - userId: this.userId, + throw new Error(`流水线id不能为空`); } + const query: any = { + pipelineId, + userId: this.userId, + }; if (this.projectId) { - query.projectId = this.projectId + query.projectId = this.projectId; } - const entity = await this.certInfoService.findOne({ - where:query - }) + const entity = await this.certInfoService.findOne({ + where: query, + }); if (!entity || !entity.certInfo) { - throw new Error(`流水线(${pipelineId})还未生成证书,请先运行一次流水线`) + throw new Error(`流水线(${pipelineId})还未生成证书,请先运行一次流水线`); } return new CertReader(JSON.parse(entity.certInfo)).cert; } diff --git a/packages/ui/certd-server/src/modules/pipeline/service/getter/cname-proxy-service.ts b/packages/ui/certd-server/src/modules/pipeline/service/getter/cname-proxy-service.ts index e8b5df3b9..bc743e803 100644 --- a/packages/ui/certd-server/src/modules/pipeline/service/getter/cname-proxy-service.ts +++ b/packages/ui/certd-server/src/modules/pipeline/service/getter/cname-proxy-service.ts @@ -1,4 +1,4 @@ -import { CnameRecord, ICnameProxyService } from '@certd/pipeline'; +import { CnameRecord, ICnameProxyService } from "@certd/pipeline"; export class CnameProxyService implements ICnameProxyService { userId: number; diff --git a/packages/ui/certd-server/src/modules/pipeline/service/getter/domain-verifier-getter.ts b/packages/ui/certd-server/src/modules/pipeline/service/getter/domain-verifier-getter.ts index 251f8003e..9b093d17d 100644 --- a/packages/ui/certd-server/src/modules/pipeline/service/getter/domain-verifier-getter.ts +++ b/packages/ui/certd-server/src/modules/pipeline/service/getter/domain-verifier-getter.ts @@ -1,5 +1,5 @@ -import {DomainVerifiers, IDomainVerifierGetter} from "@certd/plugin-cert"; -import {DomainService} from "../../../cert/service/domain-service.js"; +import { DomainVerifiers, IDomainVerifierGetter } from "@certd/plugin-cert"; +import { DomainService } from "../../../cert/service/domain-service.js"; export class DomainVerifierGetter implements IDomainVerifierGetter { private userId: number; @@ -12,8 +12,7 @@ export class DomainVerifierGetter implements IDomainVerifierGetter { this.domainService = domainService; } - async getVerifiers(domains: string[]): Promise{ - return await this.domainService.getDomainVerifiers(this.userId,this.projectId,domains); + async getVerifiers(domains: string[]): Promise { + return await this.domainService.getDomainVerifiers(this.userId, this.projectId, domains); } - } diff --git a/packages/ui/certd-server/src/modules/pipeline/service/getter/notification-getter.ts b/packages/ui/certd-server/src/modules/pipeline/service/getter/notification-getter.ts index a3987a276..52c0890b5 100644 --- a/packages/ui/certd-server/src/modules/pipeline/service/getter/notification-getter.ts +++ b/packages/ui/certd-server/src/modules/pipeline/service/getter/notification-getter.ts @@ -1,5 +1,5 @@ -import { INotificationService, NotificationSendReq } from '@certd/pipeline'; -import {NotificationService} from "../notification-service.js"; +import { INotificationService, NotificationSendReq } from "@certd/pipeline"; +import { NotificationService } from "../notification-service.js"; export class NotificationGetter implements INotificationService { userId: number; diff --git a/packages/ui/certd-server/src/modules/pipeline/service/getter/site-info-getter.ts b/packages/ui/certd-server/src/modules/pipeline/service/getter/site-info-getter.ts index 6d6c8ca2a..95e3baab5 100644 --- a/packages/ui/certd-server/src/modules/pipeline/service/getter/site-info-getter.ts +++ b/packages/ui/certd-server/src/modules/pipeline/service/getter/site-info-getter.ts @@ -1,20 +1,18 @@ import { SysSettingsService, SysInstallInfo } from "@certd/lib-server"; import { Inject, Provide, Scope, ScopeEnum } from "@midwayjs/core"; -import { SiteInfo ,ISiteInfoGetter} from "@certd/plugin-lib"; +import { SiteInfo, ISiteInfoGetter } from "@certd/plugin-lib"; @Provide("siteInfoGetter") @Scope(ScopeEnum.Request, { allowDowngrade: true }) -export class SiteInfoGetter implements ISiteInfoGetter{ - @Inject() - sysSettingsService: SysSettingsService; +export class SiteInfoGetter implements ISiteInfoGetter { + @Inject() + sysSettingsService: SysSettingsService; + async getSiteInfo(): Promise { + const installInfo = await this.sysSettingsService.getSetting(SysInstallInfo); - async getSiteInfo(): Promise { - - const installInfo = await this.sysSettingsService.getSetting(SysInstallInfo); - - return { - siteUrl: installInfo?.bindUrl || "", - } - } + return { + siteUrl: installInfo?.bindUrl || "", + }; + } } diff --git a/packages/ui/certd-server/src/modules/pipeline/service/getter/sub-domain-getter.ts b/packages/ui/certd-server/src/modules/pipeline/service/getter/sub-domain-getter.ts index f5b0f490a..f78a88e31 100644 --- a/packages/ui/certd-server/src/modules/pipeline/service/getter/sub-domain-getter.ts +++ b/packages/ui/certd-server/src/modules/pipeline/service/getter/sub-domain-getter.ts @@ -19,7 +19,7 @@ export class SubDomainsGetter implements ISubDomainsGetter { } async getSubDomains() { - const projectSubDomains = await this.subDomainService.getListByUserId(this.userId, this.projectId) || []; + const projectSubDomains = (await this.subDomainService.getListByUserId(this.userId, this.projectId)) || []; const cnameProviderSubDomains = await this.cnameProviderService.getSubDomains(); return [...projectSubDomains, ...cnameProviderSubDomains] .map(item => item?.trim()) @@ -28,8 +28,8 @@ export class SubDomainsGetter implements ISubDomainsGetter { } async hasSubDomain(fullDomain: string) { - let arr = fullDomain.split(".") - const subDomains = await this.getSubDomains() + let arr = fullDomain.split("."); + const subDomains = await this.getSubDomains(); if (subDomains && subDomains.length > 0) { const fullDomainDot = "." + fullDomain; for (const subDomain of subDomains) { @@ -41,40 +41,38 @@ export class SubDomainsGetter implements ISubDomainsGetter { if (subDomain.startsWith("*.")) { //如果子域名配置的是泛域名,说明这一层及以下的子域名都是托管的 //以fullDomain在这一层的子域名作为返回值 - const nonStarDomain = subDomain.slice(1) + const nonStarDomain = subDomain.slice(1); if (fullDomainDot.endsWith(nonStarDomain)) { //提取fullDomain在这一层的子域名 - const fullArr = arr.reverse() - const subArr = subDomain.split(".").reverse() - let strBuilder = "" - for (let i =0 ;i 0) { - const subDomain = arr.join(".") + const subDomain = arr.join("."); const domain = await this.domainService.findOne({ where: { userId: this.userId, domain: subDomain, challengeType: "dns", - } - }) + }, + }); if (domain) { - return subDomain + return subDomain; } - arr = arr.slice(1) + arr = arr.slice(1); } - return null + return null; } - } diff --git a/packages/ui/certd-server/src/modules/pipeline/service/getter/task-service-getter.ts b/packages/ui/certd-server/src/modules/pipeline/service/getter/task-service-getter.ts index e42b8f116..fe25b4bae 100644 --- a/packages/ui/certd-server/src/modules/pipeline/service/getter/task-service-getter.ts +++ b/packages/ui/certd-server/src/modules/pipeline/service/getter/task-service-getter.ts @@ -14,93 +14,87 @@ import { CertInfoService } from "../../../monitor/index.js"; import { ICertInfoGetter } from "@certd/plugin-lib"; import { CnameProviderService } from "../../../cname/service/cname-provider-service.js"; -const serviceNames = [ - 'ocrService', -] -export class TaskServiceGetter implements IServiceGetter{ +const serviceNames = ["ocrService"]; +export class TaskServiceGetter implements IServiceGetter { private userId: number; private projectId: number; - private appCtx : IMidwayContainer; - constructor(userId:number,projectId:number,appCtx:IMidwayContainer) { + private appCtx: IMidwayContainer; + constructor(userId: number, projectId: number, appCtx: IMidwayContainer) { this.userId = userId; this.projectId = projectId; - this.appCtx = appCtx + this.appCtx = appCtx; } async get(serviceName: string): Promise { - - if(serviceName === 'subDomainsGetter'){ - return await this.getSubDomainsGetter() as T - } if (serviceName === 'accessService') { - return await this.getAccessService() as T - } else if (serviceName === 'cnameProxyService') { - return await this.getCnameProxyService() as T - } else if (serviceName === 'notificationService') { - return await this.getNotificationService() as T - } else if (serviceName === 'domainVerifierGetter') { - return await this.getDomainVerifierGetter() as T - } else if (serviceName === 'certInfoGetter') { - return await this.getCertInfoGetter() as T - }else{ - if(!serviceNames.includes(serviceName)){ - throw new Error(`${serviceName} not in whitelist`) + if (serviceName === "subDomainsGetter") { + return (await this.getSubDomainsGetter()) as T; + } + if (serviceName === "accessService") { + return (await this.getAccessService()) as T; + } else if (serviceName === "cnameProxyService") { + return (await this.getCnameProxyService()) as T; + } else if (serviceName === "notificationService") { + return (await this.getNotificationService()) as T; + } else if (serviceName === "domainVerifierGetter") { + return (await this.getDomainVerifierGetter()) as T; + } else if (serviceName === "certInfoGetter") { + return (await this.getCertInfoGetter()) as T; + } else { + if (!serviceNames.includes(serviceName)) { + throw new Error(`${serviceName} not in whitelist`); } - const service = await this.appCtx.getAsync(serviceName) - if (! service){ - throw new Error(`${serviceName} not found`) + const service = await this.appCtx.getAsync(serviceName); + if (!service) { + throw new Error(`${serviceName} not found`); } } } async getSubDomainsGetter(): Promise { - const subDomainsService:SubDomainService = await this.appCtx.getAsync("subDomainService") - const domainService:DomainService = await this.appCtx.getAsync("domainService") - const cnameProviderService:CnameProviderService = await this.appCtx.getAsync("cnameProviderService") - return new SubDomainsGetter(this.userId,this.projectId, subDomainsService,domainService,cnameProviderService) + const subDomainsService: SubDomainService = await this.appCtx.getAsync("subDomainService"); + const domainService: DomainService = await this.appCtx.getAsync("domainService"); + const cnameProviderService: CnameProviderService = await this.appCtx.getAsync("cnameProviderService"); + return new SubDomainsGetter(this.userId, this.projectId, subDomainsService, domainService, cnameProviderService); } async getCertInfoGetter(): Promise { - const certInfoService:CertInfoService = await this.appCtx.getAsync("certInfoService") - return new CertInfoGetter(this.userId, this.projectId, certInfoService) + const certInfoService: CertInfoService = await this.appCtx.getAsync("certInfoService"); + return new CertInfoGetter(this.userId, this.projectId, certInfoService); } async getAccessService(): Promise { - const accessService:AccessService = await this.appCtx.getAsync("accessService") + const accessService: AccessService = await this.appCtx.getAsync("accessService"); return new AccessGetter(this.userId, this.projectId, accessService.getById.bind(accessService)); } - async getCnameProxyService(): Promise { - const cnameRecordService:CnameRecordService = await this.appCtx.getAsync("cnameRecordService") + const cnameRecordService: CnameRecordService = await this.appCtx.getAsync("cnameRecordService"); return new CnameProxyService(this.userId, this.projectId, cnameRecordService.getWithAccessByDomain.bind(cnameRecordService)); } async getNotificationService(): Promise { - const notificationService:NotificationService = await this.appCtx.getAsync("notificationService") + const notificationService: NotificationService = await this.appCtx.getAsync("notificationService"); return new NotificationGetter(this.userId, this.projectId, notificationService); } async getDomainVerifierGetter(): Promise { - const domainService:DomainService = await this.appCtx.getAsync("domainService") + const domainService: DomainService = await this.appCtx.getAsync("domainService"); return new DomainVerifierGetter(this.userId, this.projectId, domainService); } } @Provide() @Scope(ScopeEnum.Request, { allowDowngrade: true }) -export class TaskServiceBuilder { +export class TaskServiceBuilder { @ApplicationContext() appCtx: IMidwayContainer; - create(req:TaskServiceCreateReq){ + create(req: TaskServiceCreateReq) { const userId = req.userId; const projectId = req.projectId; - return new TaskServiceGetter(userId,projectId,this.appCtx) + return new TaskServiceGetter(userId, projectId, this.appCtx); } } export type TaskServiceCreateReq = { userId: number; projectId?: number; -} - - - +}; diff --git a/packages/ui/certd-server/src/modules/pipeline/service/history-log-service.ts b/packages/ui/certd-server/src/modules/pipeline/service/history-log-service.ts index 5ea505ff8..6c4e39c61 100644 --- a/packages/ui/certd-server/src/modules/pipeline/service/history-log-service.ts +++ b/packages/ui/certd-server/src/modules/pipeline/service/history-log-service.ts @@ -1,8 +1,8 @@ -import { Provide, Scope, ScopeEnum } from '@midwayjs/core'; -import { InjectEntityModel } from '@midwayjs/typeorm'; -import { In, Repository } from 'typeorm'; -import { BaseService } from '@certd/lib-server'; -import { HistoryLogEntity } from '../entity/history-log.js'; +import { Provide, Scope, ScopeEnum } from "@midwayjs/core"; +import { InjectEntityModel } from "@midwayjs/typeorm"; +import { In, Repository } from "typeorm"; +import { BaseService } from "@certd/lib-server"; +import { HistoryLogEntity } from "../entity/history-log.js"; /** * 证书申请 diff --git a/packages/ui/certd-server/src/modules/pipeline/service/history-service.ts b/packages/ui/certd-server/src/modules/pipeline/service/history-service.ts index 352582482..17b24df2f 100644 --- a/packages/ui/certd-server/src/modules/pipeline/service/history-service.ts +++ b/packages/ui/certd-server/src/modules/pipeline/service/history-service.ts @@ -1,16 +1,16 @@ -import { Config, Inject, Provide, Scope, ScopeEnum } from '@midwayjs/core'; -import { InjectEntityModel } from '@midwayjs/typeorm'; -import { In, MoreThan, Repository } from 'typeorm'; -import { BaseService, PageReq } from '@certd/lib-server'; -import { HistoryEntity } from '../entity/history.js'; -import { PipelineEntity } from '../entity/pipeline.js'; -import { HistoryDetail } from '../entity/vo/history-detail.js'; -import { HistoryLogService } from './history-log-service.js'; -import { FileItem, FileStore, Pipeline, RunnableCollection } from '@certd/pipeline'; +import { Config, Inject, Provide, Scope, ScopeEnum } from "@midwayjs/core"; +import { InjectEntityModel } from "@midwayjs/typeorm"; +import { In, MoreThan, Repository } from "typeorm"; +import { BaseService, PageReq } from "@certd/lib-server"; +import { HistoryEntity } from "../entity/history.js"; +import { PipelineEntity } from "../entity/pipeline.js"; +import { HistoryDetail } from "../entity/vo/history-detail.js"; +import { HistoryLogService } from "./history-log-service.js"; +import { FileItem, FileStore, Pipeline, RunnableCollection } from "@certd/pipeline"; -import dayjs from 'dayjs'; -import { DbAdapter } from '../../db/index.js'; -import { logger } from '@certd/basic'; +import dayjs from "dayjs"; +import { DbAdapter } from "../../db/index.js"; +import { logger } from "@certd/basic"; /** * 证书申请 @@ -29,7 +29,7 @@ export class HistoryService extends BaseService { @Inject() dbAdapter: DbAdapter; - @Config('certd') + @Config("certd") private certdConfig: any; //@ts-ignore @@ -60,12 +60,12 @@ export class HistoryService extends BaseService { return new HistoryDetail(entity, log); } - async start(pipeline: PipelineEntity,triggerType:string) { + async start(pipeline: PipelineEntity, triggerType: string) { const bean = { userId: pipeline.userId, pipelineId: pipeline.id, title: pipeline.title, - status: 'start', + status: "start", triggerType, projectId: pipeline.projectId, }; @@ -104,7 +104,7 @@ export class HistoryService extends BaseService { pipelineId, }, order: { - id: 'ASC', + id: "ASC", }, skip: 0, take: deleteCountBatch, @@ -130,7 +130,7 @@ export class HistoryService extends BaseService { pipelineId, }, order: { - id: 'DESC', + id: "DESC", }, }); } @@ -139,7 +139,7 @@ export class HistoryService extends BaseService { const status: Pipeline = JSON.parse(history.pipeline); const files: FileItem[] = []; RunnableCollection.each([status], runnable => { - if (runnable.runnableType !== 'step') { + if (runnable.runnableType !== "step") { return; } if (runnable.status?.files != null) { @@ -174,32 +174,32 @@ export class HistoryService extends BaseService { try { const fileStore = new FileStore({ rootDir: this.certdConfig.fileRootDir, - scope: id + '', - parent: '0', + scope: id + "", + parent: "0", }); - fileStore.deleteByParent(id + '', ''); + fileStore.deleteByParent(id + "", ""); } catch (e) { - logger.error('删除文件失败', e); + logger.error("删除文件失败", e); } } - async countPerDay(param: { days: number; userId?: any,projectId?:number }) { - const todayEnd = dayjs().endOf('day'); + async countPerDay(param: { days: number; userId?: any; projectId?: number }) { + const todayEnd = dayjs().endOf("day"); const where: any = { - createTime: MoreThan(todayEnd.add(-param.days, 'day').toDate()), + createTime: MoreThan(todayEnd.add(-param.days, "day").toDate()), }; - + if (param.projectId > 0) { where.projectId = param.projectId; - }else if (param.userId > 0) { + } else if (param.userId > 0) { where.userId = param.userId; } const result = await this.getRepository() - .createQueryBuilder('main') - .select(`${this.dbAdapter.date('main.createTime')} AS date`) // 将UNIX时间戳转换为日期 - .addSelect('COUNT(1) AS count') + .createQueryBuilder("main") + .select(`${this.dbAdapter.date("main.createTime")} AS date`) // 将UNIX时间戳转换为日期 + .addSelect("COUNT(1) AS count") .where(where) - .groupBy('date') + .groupBy("date") .getRawMany(); return result; diff --git a/packages/ui/certd-server/src/modules/pipeline/service/notification-service.ts b/packages/ui/certd-server/src/modules/pipeline/service/notification-service.ts index aaf1cc51e..976508bc1 100644 --- a/packages/ui/certd-server/src/modules/pipeline/service/notification-service.ts +++ b/packages/ui/certd-server/src/modules/pipeline/service/notification-service.ts @@ -1,19 +1,12 @@ -import { Inject, Provide, Scope, ScopeEnum } from '@midwayjs/core'; -import { - BaseService, - NeedVIPException, - SysInstallInfo, - SysSettingsService, - SysSiteInfo, - ValidateException -} from "@certd/lib-server"; -import { InjectEntityModel } from '@midwayjs/typeorm'; -import { Repository } from 'typeorm'; -import { NotificationEntity } from '../entity/notification.js'; -import { NotificationInstanceConfig, notificationRegistry, NotificationSendReq, sendNotification } from '@certd/pipeline'; -import { http, utils } from '@certd/basic'; -import { EmailService } from '../../basic/service/email-service.js'; -import { isComm, isPlus } from '@certd/plus-core'; +import { Inject, Provide, Scope, ScopeEnum } from "@midwayjs/core"; +import { BaseService, NeedVIPException, SysInstallInfo, SysSettingsService, SysSiteInfo, ValidateException } from "@certd/lib-server"; +import { InjectEntityModel } from "@midwayjs/typeorm"; +import { Repository } from "typeorm"; +import { NotificationEntity } from "../entity/notification.js"; +import { NotificationInstanceConfig, notificationRegistry, NotificationSendReq, sendNotification } from "@certd/pipeline"; +import { http, utils } from "@certd/basic"; +import { EmailService } from "../../basic/service/email-service.js"; +import { isComm, isPlus } from "@certd/plus-core"; @Provide() @Scope(ScopeEnum.Request, { allowDowngrade: true }) @@ -35,7 +28,7 @@ export class NotificationService extends BaseService { async getSimpleInfo(id: number) { const entity = await this.info(id); if (entity == null) { - throw new ValidateException('该通知配置不存在,请确认是否已被删除'); + throw new ValidateException("该通知配置不存在,请确认是否已被删除"); } return { id: entity.id, @@ -56,32 +49,31 @@ export class NotificationService extends BaseService { async add(bean: NotificationEntity) { this.checkNeedPlus(bean.type); const res = await super.add(bean); - if(bean.isDefault){ + if (bean.isDefault) { await this.setDefault(res.id, bean.userId); } bean.keyId = "nt_" + utils.id.simpleNanoId(); - return res + return res; } async update(bean: NotificationEntity) { - const old = await this.info(bean.id); this.checkNeedPlus(old.type); delete bean.userId; - delete bean.type - delete bean.keyId + delete bean.type; + delete bean.keyId; const res = await super.update(bean); - if(bean.isDefault){ + if (bean.isDefault) { await this.setDefault(bean.id, old.userId); } - return res + return res; } - checkNeedPlus(type: string){ - const define = this.getDefineByType(type) - //@ts-ignore + checkNeedPlus(type: string) { + const define = this.getDefineByType(type); + //@ts-ignore if (define.needPlus && !isPlus()) { throw new NeedVIPException("此通知类型为Certd专业版功能,请升级到专业版或以上级别"); } @@ -89,10 +81,10 @@ export class NotificationService extends BaseService { async getById(id: number, userId: number, projectId?: number): Promise { if (!id) { - throw new ValidateException('id不能为空'); + throw new ValidateException("id不能为空"); } - if (userId==null) { - throw new ValidateException('userId不能为空'); + if (userId == null) { + throw new ValidateException("userId不能为空"); } const res = await this.repository.findOne({ where: { @@ -125,7 +117,7 @@ export class NotificationService extends BaseService { projectId, }, order: { - isDefault: 'DESC', + isDefault: "DESC", }, }); if (!res) { @@ -136,30 +128,24 @@ export class NotificationService extends BaseService { async setDefault(id: number, userId: number, projectId?: number) { if (!id) { - throw new ValidateException('id不能为空'); + throw new ValidateException("id不能为空"); } - if (userId==null) { - throw new ValidateException('userId不能为空'); + if (userId == null) { + throw new ValidateException("userId不能为空"); } - const query:any = { - userId, + const query: any = { + userId, + }; + if (projectId) { + query.projectId = projectId; } - if (projectId){ - query.projectId = projectId - } - await this.repository.update( - query, - { - isDefault: false, - } - ); - query.id = id - await this.repository.update( - query, - { - isDefault: true, - } - ); + await this.repository.update(query, { + isDefault: false, + }); + query.id = id; + await this.repository.update(query, { + isDefault: true, + }); } async getOrCreateDefault(email: string, userId: any, projectId?: number) { @@ -172,8 +158,8 @@ export class NotificationService extends BaseService { }; const res = await this.repository.save({ userId, - type: 'email', - name: '邮件通知', + type: "email", + name: "邮件通知", setting: JSON.stringify(setting), isDefault: true, projectId, @@ -199,11 +185,11 @@ export class NotificationService extends BaseService { if (notifyConfig) { //发送通知 - logger.info('发送通知, 使用通知渠道:' + notifyConfig.name); + logger.info("发送通知, 使用通知渠道:" + notifyConfig.name); - if (notifyConfig.type != 'email') { + if (notifyConfig.type != "email") { //非邮件通知,需要加上站点名称 - let siteTitle = 'Certd'; + let siteTitle = "Certd"; if (isComm()) { const siteInfo = await this.sysSettingsService.getSetting(SysSiteInfo); siteTitle = siteInfo?.title || siteTitle; @@ -223,7 +209,7 @@ export class NotificationService extends BaseService { }); } else { if (req.useEmail && req.emailAddress) { - logger.info('使用邮件通知'); + logger.info("使用邮件通知"); await this.emailService.send({ receivers: [req.emailAddress], subject: req.body.title, @@ -235,7 +221,7 @@ export class NotificationService extends BaseService { async getBindUrl(path: string) { const installInfo = await this.sysSettingsService.getSetting(SysInstallInfo); - const bindUrl = installInfo.bindUrl || 'http://127.0.0.1:7001'; + const bindUrl = installInfo.bindUrl || "http://127.0.0.1:7001"; return bindUrl + path; } } diff --git a/packages/ui/certd-server/src/modules/pipeline/service/pipeline-batch-update.test.ts b/packages/ui/certd-server/src/modules/pipeline/service/pipeline-batch-update.test.ts index 06c6bb857..b6ab7bc2e 100644 --- a/packages/ui/certd-server/src/modules/pipeline/service/pipeline-batch-update.test.ts +++ b/packages/ui/certd-server/src/modules/pipeline/service/pipeline-batch-update.test.ts @@ -115,7 +115,10 @@ describe("pipeline batch update", () => { }, }; - assert.equal(updateCertApplyStepInputs(pipeline, {}, stepType => inputDefines[stepType]), 0); + assert.equal( + updateCertApplyStepInputs(pipeline, {}, stepType => inputDefines[stepType]), + 0 + ); assert.equal( updateCertApplyStepInputs( pipeline, diff --git a/packages/ui/certd-server/src/modules/pipeline/service/pipeline-group-service.ts b/packages/ui/certd-server/src/modules/pipeline/service/pipeline-group-service.ts index b3630d868..0624aafa1 100644 --- a/packages/ui/certd-server/src/modules/pipeline/service/pipeline-group-service.ts +++ b/packages/ui/certd-server/src/modules/pipeline/service/pipeline-group-service.ts @@ -1,9 +1,9 @@ -import { Provide, Scope, ScopeEnum } from '@midwayjs/core'; -import { BaseService } from '@certd/lib-server'; -import { InjectEntityModel } from '@midwayjs/typeorm'; -import { Repository } from 'typeorm'; -import { PipelineGroupEntity } from '../entity/pipeline-group.js'; -import { merge } from 'lodash-es'; +import { Provide, Scope, ScopeEnum } from "@midwayjs/core"; +import { BaseService } from "@certd/lib-server"; +import { InjectEntityModel } from "@midwayjs/typeorm"; +import { Repository } from "typeorm"; +import { PipelineGroupEntity } from "../entity/pipeline-group.js"; +import { merge } from "lodash-es"; @Provide() @Scope(ScopeEnum.Request, { allowDowngrade: true }) diff --git a/packages/ui/certd-server/src/modules/pipeline/service/pipeline-service.ts b/packages/ui/certd-server/src/modules/pipeline/service/pipeline-service.ts index 15829588f..6d89cfe7c 100644 --- a/packages/ui/certd-server/src/modules/pipeline/service/pipeline-service.ts +++ b/packages/ui/certd-server/src/modules/pipeline/service/pipeline-service.ts @@ -1,32 +1,10 @@ import { Config, Inject, Provide, Scope, ScopeEnum, sleep } from "@midwayjs/core"; import { InjectEntityModel } from "@midwayjs/typeorm"; import { In, MoreThan, Repository } from "typeorm"; -import { - AccessService, - BaseService, - isEnterprise, - NeedSuiteException, - NeedVIPException, - PageReq, - SysPublicSettings, - SysSettingsService, - SysSiteInfo -} from "@certd/lib-server"; +import { AccessService, BaseService, isEnterprise, NeedSuiteException, NeedVIPException, PageReq, SysPublicSettings, SysSettingsService, SysSiteInfo } from "@certd/lib-server"; import { PipelineEntity } from "../entity/pipeline.js"; import { PipelineDetail } from "../entity/vo/pipeline-detail.js"; -import { - Executor, - IAccessService, - ICnameProxyService, - INotificationService, Notification, - Pipeline, - pluginRegistry, - ResultType, - RunHistory, - RunnableCollection, - SysInfo, - UserInfo -} from "@certd/pipeline"; +import { Executor, IAccessService, ICnameProxyService, INotificationService, Notification, Pipeline, pluginRegistry, ResultType, RunHistory, RunnableCollection, SysInfo, UserInfo } from "@certd/pipeline"; import { DbStorage } from "./db-storage.js"; import { StorageService } from "./storage-service.js"; import { Cron } from "../../cron/cron.js"; @@ -56,7 +34,6 @@ import { CertApplyStepInputPatch, updateCertApplyStepInputs } from "./pipeline-b import { calcNextSuiteCountUsed } from "./pipeline-suite-limit.js"; const runningTasks: Map = new Map(); - /** * 证书申请 */ @@ -154,9 +131,9 @@ export class PipelineService extends BaseService { //获取下次执行时间 if (pipeline.triggers?.length > 0) { - const triggers = pipeline.triggers.filter((item) => item.type === 'timer'); + const triggers = pipeline.triggers.filter(item => item.type === "timer"); if (triggers && triggers.length > 0) { - let nextTimes: any = []; + const nextTimes: any = []; for (const item of triggers) { if (!item.props?.cron) { continue; @@ -164,9 +141,8 @@ export class PipelineService extends BaseService { const ret = this.getCronNextTimes(item.props?.cron, 1); nextTimes.push(...ret); } - item.nextRunTime = nextTimes[0] + item.nextRunTime = nextTimes[0]; } - } delete item.content; @@ -175,7 +151,7 @@ export class PipelineService extends BaseService { return result; } - getCronNextTimes(cron: string, count: number = 1) { + getCronNextTimes(cron: string, count = 1) { if (cron == null) { return []; } @@ -188,7 +164,6 @@ export class PipelineService extends BaseService { return nextTimes; } - private async fillLastVars(records: PipelineEntity[]) { const pipelineIds: number[] = []; const recordMap = {}; @@ -235,8 +210,6 @@ export class PipelineService extends BaseService { } } - - /** * 获取详情 * @param id @@ -270,7 +243,6 @@ export class PipelineService extends BaseService { const isUpdate = bean.id > 0 && old != null; - const pipeline = JSON.parse(bean.content || "{}"); RunnableCollection.initPipelineRunnableType(pipeline); pipeline.userId = bean.userId; @@ -334,12 +306,12 @@ export class PipelineService extends BaseService { } pipeline.version++; - bean.triggerCount = pipeline.triggers?.filter((trigger) => trigger.type === "timer").length || 0; + bean.triggerCount = pipeline.triggers?.filter(trigger => trigger.type === "timer").length || 0; bean.content = JSON.stringify(pipeline); await this.addOrUpdate(bean); await this.registerTrigger(bean); - return bean + return bean; } private async checkMaxPipelineCount(bean: PipelineEntity, pipeline: Pipeline, domains: string[], old?: PipelineEntity) { @@ -351,7 +323,7 @@ export class PipelineService extends BaseService { // } if (isEnterprise()) { //企业模式不限制 - checkPlus() + checkPlus(); return; } @@ -397,18 +369,17 @@ export class PipelineService extends BaseService { } } } - } async foreachPipeline(callback: (pipeline: PipelineEntity) => void) { const idEntityList = await this.repository.find({ select: { - id: true + id: true, }, where: { disabled: false, - isTemplate: false - } + isTemplate: false, + }, }); const ids = idEntityList.map(item => { return item.id; @@ -428,7 +399,7 @@ export class PipelineService extends BaseService { //分段加载记录 for (const idArr of idsSpan) { const list = await this.repository.findBy({ - id: In(idArr) + id: In(idArr), }); for (const entity of list) { @@ -478,12 +449,9 @@ export class PipelineService extends BaseService { } catch (e) { logger.error(e); } - } } - - async trigger(id: any, stepId?: string, doCheck = false) { const entity: PipelineEntity = await this.info(id); if (doCheck) { @@ -499,7 +467,7 @@ export class PipelineService extends BaseService { } catch (e) { logger.error("手动job执行失败:", e); } - } + }, }); } @@ -511,7 +479,7 @@ export class PipelineService extends BaseService { logger.error(e.message); await this.update({ id: pipelineId, - status: "no_deploy_count" + status: "no_deploy_count", }); } throw e; @@ -595,22 +563,21 @@ export class PipelineService extends BaseService { } catch (e) { logger.error("定时job执行失败:", e); } - } + }, }); - } + }, }); logger.info("当前定时器数量:", this.cron.getTaskSize()); } - async isPipelineValidTimeEnabled(entity: PipelineEntity) { const settings = await this.sysSettingsService.getPublicSettings(); if (isPlus() && settings.pipelineValidTimeEnabled) { if (entity.validTime > 0 && entity.validTime < Date.now()) { - return false + return false; } } - return true + return true; } /** @@ -629,13 +596,12 @@ export class PipelineService extends BaseService { } async beforeCheck(entity: PipelineEntity) { - if (isEnterprise()) { - checkPlus() - return {} + checkPlus(); + return {}; } - const validTimeEnabled = await this.isPipelineValidTimeEnabled(entity) + const validTimeEnabled = await this.isPipelineValidTimeEnabled(entity); if (!validTimeEnabled) { throw new Error(`流水线${entity.id}已过期,不予执行`); } @@ -647,16 +613,15 @@ export class PipelineService extends BaseService { await this.checkUserStatus(entity.userId); return { - suite - } + suite, + }; } async doRun(entity: PipelineEntity, triggerId: string, stepId?: string) { - - let suite: any = null + let suite: any = null; try { const res = await this.beforeCheck(entity); - suite = res.suite + suite = res.suite; } catch (e) { logger.error(`流水线${entity.id}触发失败(${triggerId}):${e.message}`); return; @@ -668,7 +633,7 @@ export class PipelineService extends BaseService { pipeline.id = id; } - if(entity.userId !=null){ + if (entity.userId != null) { pipeline.userId = entity.userId; pipeline.projectId = entity.projectId; } @@ -688,7 +653,7 @@ export class PipelineService extends BaseService { return; } } - + const doSaveHistory = async (history: RunHistory) => { //保存执行历史 try { @@ -707,8 +672,8 @@ export class PipelineService extends BaseService { class HistorySaver { latest: RunHistory = null; interval: any = null; - started: boolean = false; - async save(){ + started = false; + async save() { const latest = this.latest; this.latest = null; if (latest == null) { @@ -716,43 +681,43 @@ export class PipelineService extends BaseService { } await doSaveHistory(latest); } - async start(){ - this.started = true + async start() { + this.started = true; //先存一次,确保有数据 await this.save(); - setTimeout(()=>{ + setTimeout(() => { //2秒后保存一次,尽快显示第一个任务的状态 - this.save(); + this.save(); }, 1000 * 2); - this.interval = setInterval(()=>{ + this.interval = setInterval(() => { //之后每5秒保存一次 this.save(); }, 1000 * 5); } - async push(history: RunHistory){ + async push(history: RunHistory) { this.latest = history; - if(!this.started){ - await this.start(); + if (!this.started) { + await this.start(); } } - async done(){ + async done() { clearInterval(this.interval); await this.save(); } } const historySaver = new HistorySaver(); - const onChanged = async (history: RunHistory)=>{ + const onChanged = async (history: RunHistory) => { await historySaver.push(history); - } - const onFinished = async (history: RunHistory)=>{ + }; + const onFinished = async (history: RunHistory) => { await onChanged(history); await historySaver.done(); - } + }; const userId = entity.userId; const projectId = entity.projectId; - let userIsAdmin = false + let userIsAdmin = false; if (projectId && projectId > 0) { userIsAdmin = await this.projectService.isAdmin(projectId); @@ -761,7 +726,7 @@ export class PipelineService extends BaseService { } const user: UserInfo = { id: userId, - role: userIsAdmin ? "admin" : "user" + role: userIsAdmin ? "admin" : "user", }; const historyId = await this.historyService.start(entity, triggerType); @@ -773,7 +738,7 @@ export class PipelineService extends BaseService { const taskServiceGetter = this.taskServiceBuilder.create({ userId, - projectId + projectId, }); const accessGetter = await taskServiceGetter.get("accessService"); const notificationGetter = await taskServiceGetter.get("notificationService"); @@ -792,7 +757,7 @@ export class PipelineService extends BaseService { notificationService: notificationGetter, fileRootDir: this.certdConfig.fileRootDir, sysInfo, - serviceGetter: taskServiceGetter + serviceGetter: taskServiceGetter, }); try { runningTasks.set(historyId, executor); @@ -875,13 +840,13 @@ export class PipelineService extends BaseService { }, }); if (!pipelineEntity) { - return null + return null; } return pipelineEntity.projectId; } private async saveHistory(history: RunHistory) { //修改pipeline状态 - let pipelineEntity = new PipelineEntity(); + const pipelineEntity = new PipelineEntity(); pipelineEntity.id = parseInt(history.pipeline.id); pipelineEntity.status = history.pipeline.status.result + ""; pipelineEntity.lastHistoryTime = history.pipeline.status.startTime; @@ -909,18 +874,18 @@ export class PipelineService extends BaseService { await this.historyLogService.addOrUpdate(logEntity); } - async count(param: { userId?: any, projectId?: number }) { + async count(param: { userId?: any; projectId?: number }) { const count = await this.repository.count({ where: { userId: param.userId, projectId: param.projectId, - isTemplate: false - } + isTemplate: false, + }, }); return count; } - async statusCount(param: { userId?: any, projectId?: number } = {}) { + async statusCount(param: { userId?: any; projectId?: number } = {}) { const statusCount = await this.repository .createQueryBuilder() .select("status") @@ -928,14 +893,14 @@ export class PipelineService extends BaseService { .where({ userId: param.userId, projectId: param.projectId, - isTemplate: false + isTemplate: false, }) .groupBy("status") .getRawMany(); return statusCount; } - async enableCount(param: { userId?: any, projectId?: number } = {}) { + async enableCount(param: { userId?: any; projectId?: number } = {}) { const statusCount = await this.repository .createQueryBuilder() .select("disabled") @@ -943,7 +908,7 @@ export class PipelineService extends BaseService { .where({ userId: param.userId, projectId: param.projectId, - isTemplate: false + isTemplate: false, }) .groupBy("disabled") .getRawMany(); @@ -962,14 +927,14 @@ export class PipelineService extends BaseService { select: { id: true, title: true, - status: true + status: true, }, where: { userId, disabled: false, projectId, - isTemplate: false - } + isTemplate: false, + }, }); await this.fillLastVars(list); list = list.filter(item => { @@ -991,7 +956,7 @@ export class PipelineService extends BaseService { .where({ // 0点 createTime: MoreThan(todayEnd.add(-param.days, "day").toDate()), - isTemplate: false + isTemplate: false, }) .groupBy("date") .getRawMany(); @@ -1008,7 +973,7 @@ export class PipelineService extends BaseService { await this.checkUserId(id, userId); } if (projectId) { - await this.checkUserId(id, projectId, "projectId") + await this.checkUserId(id, projectId, "projectId"); } await this.delete(id); } @@ -1018,7 +983,7 @@ export class PipelineService extends BaseService { if (!isPlus()) { throw new NeedVIPException("此功能需要升级Certd专业版"); } - const query: any = {} + const query: any = {}; if (userId && userId > 0) { query.userId = userId; } @@ -1028,15 +993,12 @@ export class PipelineService extends BaseService { await this.repository.update( { id: In(ids), - ...query + ...query, }, { groupId } ); } - - - /** * 批量转移到其他项目 */ @@ -1050,7 +1012,7 @@ export class PipelineService extends BaseService { if (!projectId || projectId <= 0) { throw new Error("projectId不能为空"); } - const userId = -1 // 强制为-1 + const userId = -1; // 强制为-1 async function eachSteps(pipeline, callback) { for (const stage of pipeline.stages) { @@ -1062,7 +1024,6 @@ export class PipelineService extends BaseService { } } - for (const id of ids) { const pipelineEntity = await this.info(id); if (!pipelineEntity) { @@ -1080,16 +1041,16 @@ export class PipelineService extends BaseService { userId: userId, projectId: projectId, groupId: null, - } + }; const pipeline = JSON.parse(pipelineEntity.content); pipeline.userId = userId; pipeline.projectId = projectId; //转移和修改access 和 Notification - await eachSteps(pipeline, async (step) => { + await eachSteps(pipeline, async step => { const type = step.type; - //plugin + //plugin const pluginDefine: any = pluginRegistry.getDefine(type); if (pluginDefine) { for (const key in step.input) { @@ -1097,48 +1058,40 @@ export class PipelineService extends BaseService { if (!value || value <= 0) { continue; } - if (!pluginDefine.input[key]){ + if (!pluginDefine.input[key]) { continue; } const componentName = pluginDefine.input[key].component?.name; if (componentName === "access-selector" || componentName === "AccessSelector") { //这是一个授权ID属性,检查是否需要转移授权 - const newAccessId = await this.accessService.copyTo(value,projectId); + const newAccessId = await this.accessService.copyTo(value, projectId); step.input[key] = newAccessId; } } } - }) - pipeline.notifications = [ + }); + (pipeline.notifications = [ { - "type": "custom", - "when": [ - "error", - "turnToSuccess" - ], - "notificationId": 0, - "title": "使用默认通知", - "id": nanoid() - } - ], - - entity.content = JSON.stringify(pipeline); + type: "custom", + when: ["error", "turnToSuccess"], + notificationId: 0, + title: "使用默认通知", + id: nanoid(), + }, + ]), + (entity.content = JSON.stringify(pipeline)); await this.unregisterTriggers(entity.id); await this.repository.save(entity); - await this.save(entity) + await this.save(entity); } - - - } - async batchUpdateTrigger(ids: number[], trigger: any, userId: any, projectId?: number) { if (!isPlus()) { throw new NeedVIPException("此功能需要升级Certd专业版"); } //允许管理员修改,userId=null - const query: any = {} + const query: any = {}; if (userId && userId > 0) { query.userId = userId; } @@ -1148,15 +1101,15 @@ export class PipelineService extends BaseService { const list = await this.find({ where: { id: In(ids), - ...query - } + ...query, + }, }); for (const item of list) { const pipeline = JSON.parse(item.content); if (trigger.props === false) { //清除trigger - pipeline.triggers = [] + pipeline.triggers = []; } else { if (trigger.random === true) { //随机时间 @@ -1170,20 +1123,21 @@ export class PipelineService extends BaseService { const endTime = dayjs(end).valueOf(); const randomTime = Math.floor(Math.random() * (endTime - startTime)) + startTime; const time = dayjs(randomTime).format(" ss:mm:HH").replaceAll(":", " ").replaceAll(" 0", " ").trim(); - set(trigger, "props.cron", `${time} * * *`) + set(trigger, "props.cron", `${time} * * *`); } - delete trigger.random + delete trigger.random; delete trigger.randomRange; - pipeline.triggers = [{ - id: nanoid(), - title: "定时触发", - ...trigger - }]; + pipeline.triggers = [ + { + id: nanoid(), + title: "定时触发", + ...trigger, + }, + ]; } await this.doUpdatePipelineJson(item, pipeline); } - } async batchUpdateNotifications(ids: number[], notification: Notification, userId: any, projectId?: number) { @@ -1191,7 +1145,7 @@ export class PipelineService extends BaseService { throw new NeedVIPException("此功能需要升级Certd专业版"); } //允许管理员修改,userId=null - const query: any = {} + const query: any = {}; if (userId && userId > 0) { query.userId = userId; } @@ -1201,26 +1155,28 @@ export class PipelineService extends BaseService { const list = await this.find({ where: { id: In(ids), - ...query - } + ...query, + }, }); for (const item of list) { const pipeline = JSON.parse(item.content); - pipeline.notifications = [{ - id: nanoid(), - title: "通知", - /** - * type: NotificationType; - * when: NotificationWhen[]; - * options: EmailOptions; - * notificationId: number; - * title: string; - * subType: string; - */ - type: "other", - ...notification - }]; + pipeline.notifications = [ + { + id: nanoid(), + title: "通知", + /** + * type: NotificationType; + * when: NotificationWhen[]; + * options: EmailOptions; + * notificationId: number; + * title: string; + * subType: string; + */ + type: "other", + ...notification, + }, + ]; await this.doUpdatePipelineJson(item, pipeline); } } @@ -1229,7 +1185,7 @@ export class PipelineService extends BaseService { if (!isPlus()) { throw new NeedVIPException("此功能需要升级Certd专业版"); } - const query: any = {} + const query: any = {}; if (userId && userId > 0) { query.userId = userId; } @@ -1239,8 +1195,8 @@ export class PipelineService extends BaseService { const list = await this.find({ where: { id: In(ids), - ...query - } + ...query, + }, }); for (const item of list) { @@ -1267,15 +1223,15 @@ export class PipelineService extends BaseService { const where: any = { id: In(ids), userId, - } + }; if (projectId) { - where.projectId = projectId + where.projectId = projectId; } const list = await this.repository.find({ select: { - id: true + id: true, }, - where: where + where: where, }); ids = list.map(item => item.id); @@ -1293,12 +1249,11 @@ export class PipelineService extends BaseService { } else { await this.run(id, null); } - } + }, }); } } - async getUserPipelineCount(userId) { return await this.repository.count({ where: { userId } }); } @@ -1307,21 +1262,20 @@ export class PipelineService extends BaseService { return await this.repository.find({ select: { id: true, - title: true + title: true, }, where: { id: In(pipelineIds), userId, - projectId - } + projectId, + }, }); } - private async checkUserStatus(userId: number) { if (isEnterprise()) { //企业模式不检查用户状态,都允许运行流水线 - return + return; } const userEntity = await this.userService.info(userId); if (userEntity == null) { @@ -1344,12 +1298,12 @@ export class PipelineService extends BaseService { } } - async createAutoPipeline(req: { domains: string[]; email: string; userId: number, projectId?: number, from: string }) { + async createAutoPipeline(req: { domains: string[]; email: string; userId: number; projectId?: number; from: string }) { const randomHour = Math.floor(Math.random() * 6); const randomMin = Math.floor(Math.random() * 60); const randomCron = `0 ${randomMin} ${randomHour} * * *`; - let pipeline: any = { + const pipeline: any = { title: req.domains[0] + `证书自动申请【${req.from ?? "OpenAPI"}】`, runnableType: "pipeline", triggers: [ @@ -1359,8 +1313,8 @@ export class PipelineService extends BaseService { props: { cron: randomCron, }, - type: "timer" - } + type: "timer", + }, ], notifications: [ { @@ -1369,7 +1323,7 @@ export class PipelineService extends BaseService { when: ["error", "turnToSuccess", "success"], notificationId: 0, title: "默认通知", - } + }, ], stages: [ { @@ -1391,28 +1345,28 @@ export class PipelineService extends BaseService { renewDays: 20, domains: req.domains, email: req.email, - "challengeType": "auto", - "sslProvider": "letsencrypt", - "privateKeyType": "rsa_2048", - "certProfile": "classic", - "preferredChain": "ISRG Root X1", - "useProxy": false, - "skipLocalVerify": false, - "maxCheckRetryCount": 20, - "waitDnsDiffuseTime": 30, - "pfxArgs": "-macalg SHA1 -keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES", - "successNotify": true + challengeType: "auto", + sslProvider: "letsencrypt", + privateKeyType: "rsa_2048", + certProfile: "classic", + preferredChain: "ISRG Root X1", + useProxy: false, + skipLocalVerify: false, + maxCheckRetryCount: 20, + waitDnsDiffuseTime: 30, + pfxArgs: "-macalg SHA1 -keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES", + successNotify: true, }, strategy: { - runStrategy: 0 // 正常执行 + runStrategy: 0, // 正常执行 }, - type: "CertApply" - } - ] - } - ] - } - ] + type: "CertApply", + }, + ], + }, + ], + }, + ], }; const bean = new PipelineEntity(); @@ -1421,11 +1375,10 @@ export class PipelineService extends BaseService { bean.userId = req.userId; bean.status = "none"; bean.type = "cert_auto"; - bean.disabled = false - bean.keepHistoryCount = 30 - bean.projectId = req.projectId - await this.save(bean) - + bean.disabled = false; + bean.keepHistoryCount = 30; + bean.projectId = req.projectId; + await this.save(bean); return bean; } @@ -1433,11 +1386,11 @@ export class PipelineService extends BaseService { async getStatus(pipelineId: number) { const res = await this.repository.findOne({ select: { - status: true + status: true, }, where: { - id: pipelineId - } + id: pipelineId, + }, }); return res?.status; } @@ -1445,11 +1398,11 @@ export class PipelineService extends BaseService { async getPipelineUserId(pipelineId: number) { const res = await this.repository.findOne({ select: { - userId: true + userId: true, }, where: { - id: pipelineId - } + id: pipelineId, + }, }); return res?.userId; } @@ -1474,9 +1427,9 @@ export class PipelineService extends BaseService { content: true, }, where: { - webhookKey - } - }) + webhookKey, + }, + }); if (!pipelineEntity) { throw new Error("webhookKey不存在"); } diff --git a/packages/ui/certd-server/src/modules/pipeline/service/storage-service.ts b/packages/ui/certd-server/src/modules/pipeline/service/storage-service.ts index 978fbf5fe..e6b6155ce 100644 --- a/packages/ui/certd-server/src/modules/pipeline/service/storage-service.ts +++ b/packages/ui/certd-server/src/modules/pipeline/service/storage-service.ts @@ -1,8 +1,8 @@ -import { Provide, Scope, ScopeEnum } from '@midwayjs/core'; -import { InjectEntityModel } from '@midwayjs/typeorm'; -import { In, Repository } from 'typeorm'; -import { BaseService } from '@certd/lib-server'; -import { StorageEntity } from '../entity/storage.js'; +import { Provide, Scope, ScopeEnum } from "@midwayjs/core"; +import { InjectEntityModel } from "@midwayjs/typeorm"; +import { In, Repository } from "typeorm"; +import { BaseService } from "@certd/lib-server"; +import { StorageEntity } from "../entity/storage.js"; /** */ @@ -19,7 +19,7 @@ export class StorageService extends BaseService { async get(where: { scope: any; namespace: any; userId: number; version: string; key: string }) { if (where.userId == null) { - throw new Error('userId 不能为空'); + throw new Error("userId 不能为空"); } return await this.repository.findOne({ where, @@ -34,7 +34,7 @@ export class StorageService extends BaseService { if (ret != null) { entity.id = ret.id; if (ret.userId !== entity.userId) { - throw new Error('您没有权限修改此数据'); + throw new Error("您没有权限修改此数据"); } await this.repository.save(entity); } else { @@ -49,9 +49,9 @@ export class StorageService extends BaseService { } return await this.repository.find({ where: { - scope: 'pipeline', + scope: "pipeline", namespace: In(pipelineIds), - key: 'vars', + key: "vars", }, }); } @@ -62,9 +62,9 @@ export class StorageService extends BaseService { } const res = await this.repository.findOne({ where: { - scope: 'pipeline', - namespace: pipelineId + '', - key: 'privateVars', + scope: "pipeline", + namespace: pipelineId + "", + key: "privateVars", }, }); if (!res) { diff --git a/packages/ui/certd-server/src/modules/pipeline/service/sub-domain-service.ts b/packages/ui/certd-server/src/modules/pipeline/service/sub-domain-service.ts index 5f2d6c742..8e7b6a497 100644 --- a/packages/ui/certd-server/src/modules/pipeline/service/sub-domain-service.ts +++ b/packages/ui/certd-server/src/modules/pipeline/service/sub-domain-service.ts @@ -1,9 +1,9 @@ -import {Inject, Provide, Scope, ScopeEnum} from '@midwayjs/core'; -import {BaseService, SysSettingsService} from '@certd/lib-server'; -import {InjectEntityModel} from '@midwayjs/typeorm'; -import {Repository} from 'typeorm'; -import {SubDomainEntity} from '../entity/sub-domain.js'; -import {EmailService} from '../../basic/service/email-service.js'; +import { Inject, Provide, Scope, ScopeEnum } from "@midwayjs/core"; +import { BaseService, SysSettingsService } from "@certd/lib-server"; +import { InjectEntityModel } from "@midwayjs/typeorm"; +import { Repository } from "typeorm"; +import { SubDomainEntity } from "../entity/sub-domain.js"; +import { EmailService } from "../../basic/service/email-service.js"; @Provide() @Scope(ScopeEnum.Request, { allowDowngrade: true }) @@ -22,8 +22,8 @@ export class SubDomainService extends BaseService { return this.repository; } - async getListByUserId(userId:number, projectId?: number):Promise{ - if (userId==null) { + async getListByUserId(userId: number, projectId?: number): Promise { + if (userId == null) { return []; } const list = await this.find({ @@ -34,16 +34,16 @@ export class SubDomainService extends BaseService { }, }); - return list.map(item=>item.domain); + return list.map(item => item.domain); } async add(bean: SubDomainEntity) { - const {domain, userId, projectId} = bean; + const { domain, userId, projectId } = bean; if (!domain) { - throw new Error('域名不能为空'); + throw new Error("域名不能为空"); } - if (userId==null) { - throw new Error('用户ID不能为空'); + if (userId == null) { + throw new Error("用户ID不能为空"); } const exist = await this.repository.findOne({ where: { @@ -52,10 +52,9 @@ export class SubDomainService extends BaseService { projectId, }, }); - if (exist) { - throw new Error('域名已存在'); - } - return await super.add(bean) + if (exist) { + throw new Error("域名已存在"); + } + return await super.add(bean); } - } diff --git a/packages/ui/certd-server/src/modules/pipeline/service/template-service.ts b/packages/ui/certd-server/src/modules/pipeline/service/template-service.ts index 7e5e41067..b4db0ce0b 100644 --- a/packages/ui/certd-server/src/modules/pipeline/service/template-service.ts +++ b/packages/ui/certd-server/src/modules/pipeline/service/template-service.ts @@ -1,15 +1,15 @@ -import {Inject, Provide, Scope, ScopeEnum} from '@midwayjs/core'; -import {BaseService, SysSettingsService} from '@certd/lib-server'; -import {InjectEntityModel} from '@midwayjs/typeorm'; -import {In, Repository} from 'typeorm'; -import {TemplateEntity} from '../entity/template.js'; -import {PipelineService} from './pipeline-service.js'; -import {cloneDeep} from "lodash-es"; -import {PipelineEntity} from "../entity/pipeline.js"; -import {Pipeline} from "@certd/pipeline"; +import { Inject, Provide, Scope, ScopeEnum } from "@midwayjs/core"; +import { BaseService, SysSettingsService } from "@certd/lib-server"; +import { InjectEntityModel } from "@midwayjs/typeorm"; +import { In, Repository } from "typeorm"; +import { TemplateEntity } from "../entity/template.js"; +import { PipelineService } from "./pipeline-service.js"; +import { cloneDeep } from "lodash-es"; +import { PipelineEntity } from "../entity/pipeline.js"; +import { Pipeline } from "@certd/pipeline"; @Provide() -@Scope(ScopeEnum.Request, {allowDowngrade: true}) +@Scope(ScopeEnum.Request, { allowDowngrade: true }) export class TemplateService extends BaseService { @InjectEntityModel(TemplateEntity) repository: Repository; @@ -31,82 +31,77 @@ export class TemplateService extends BaseService { const pipelineEntity = await this.pipelineService.info(pipelineId); if (!pipelineEntity) { - throw new Error('pipeline not found'); + throw new Error("pipeline not found"); } if (pipelineEntity.userId !== param.userId) { - throw new Error('permission denied'); + throw new Error("permission denied"); } - - let template = null + let template = null; await this.transaction(async (tx: any) => { - template = await tx.getRepository(TemplateEntity).save(param); - let newPipeline = cloneDeep(pipelineEntity) + let newPipeline = cloneDeep(pipelineEntity); //创建pipeline模版 newPipeline.id = undefined; - newPipeline.title = template.title + "模版流水线" - newPipeline.templateId = template.id - newPipeline.isTemplate = true - newPipeline.userId = template.userId + newPipeline.title = template.title + "模版流水线"; + newPipeline.templateId = template.id; + newPipeline.isTemplate = true; + newPipeline.userId = template.userId; - const pipelineJson: Pipeline = JSON.parse(newPipeline.content) - delete pipelineJson.triggers - pipelineJson.userId = template.userId - pipelineJson.title = newPipeline.title - newPipeline.content = JSON.stringify(pipelineJson) - newPipeline = await tx.getRepository(PipelineEntity).save(newPipeline) + const pipelineJson: Pipeline = JSON.parse(newPipeline.content); + delete pipelineJson.triggers; + pipelineJson.userId = template.userId; + pipelineJson.title = newPipeline.title; + newPipeline.content = JSON.stringify(pipelineJson); + newPipeline = await tx.getRepository(PipelineEntity).save(newPipeline); - const update: any = {} - update.id = template.id - update.pipelineId = newPipeline.id - await tx.getRepository(TemplateEntity).save(update) - }) - - return template + const update: any = {}; + update.id = template.id; + update.pipelineId = newPipeline.id; + await tx.getRepository(TemplateEntity).save(update); + }); + return template; } - async detail(id: number, userId: number,projectId?:number) { - const info = await this.info(id) + async detail(id: number, userId: number, projectId?: number) { + const info = await this.info(id); if (!info) { - throw new Error('模板不存在'); + throw new Error("模板不存在"); } if (info.userId !== userId) { - throw new Error('无权限'); + throw new Error("无权限"); } if (projectId && info.projectId !== projectId) { - throw new Error('无权限'); + throw new Error("无权限"); } - let pipeline = null + let pipeline = null; if (info.pipelineId) { const pipelineEntity = await this.pipelineService.info(info.pipelineId); - pipeline = JSON.parse(pipelineEntity.content) + pipeline = JSON.parse(pipelineEntity.content); } - return { template: info, pipeline, - } + }; } - async batchDelete(ids: number[], userId: number,projectId?:number) { - + async batchDelete(ids: number[], userId: number, projectId?: number) { const where: any = { id: In(ids), - } + }; if (userId != null) { - where.userId = userId + where.userId = userId; } if (projectId) { - where.projectId = projectId + where.projectId = projectId; } - const list = await this.getRepository().find({where}) - ids = list.map(item => item.id) - const pipelineIds = list.map(item => item.pipelineId) + const list = await this.getRepository().find({ where }); + ids = list.map(item => item.id); + const pipelineIds = list.map(item => item.pipelineId); await this.delete(ids); - await this.pipelineService.batchDelete(pipelineIds, userId, projectId) + await this.pipelineService.batchDelete(pipelineIds, userId, projectId); } async createPipelineByTemplate(body: PipelineEntity) { @@ -114,21 +109,20 @@ export class TemplateService extends BaseService { const template = await this.info(templateId); if (!template && template.userId !== body.userId) { - throw new Error('模板不存在'); + throw new Error("模板不存在"); } - const tempPipeline = await this.pipelineService.info(template.pipelineId) + const tempPipeline = await this.pipelineService.info(template.pipelineId); const newPipeline = { type: tempPipeline.type, - from : "template", + from: "template", keepHistoryCount: tempPipeline.keepHistoryCount, - ... body, - } + ...body, + }; - await this.pipelineService.save(newPipeline) + await this.pipelineService.save(newPipeline); - return newPipeline + return newPipeline; } } - diff --git a/packages/ui/certd-server/src/modules/pipeline/service/url-service.ts b/packages/ui/certd-server/src/modules/pipeline/service/url-service.ts index d7bd31d60..60b1c0e88 100644 --- a/packages/ui/certd-server/src/modules/pipeline/service/url-service.ts +++ b/packages/ui/certd-server/src/modules/pipeline/service/url-service.ts @@ -1,6 +1,6 @@ -import { IUrlService } from '@certd/pipeline'; -import { Inject, Provide, Scope, ScopeEnum } from '@midwayjs/core'; -import { SysInstallInfo, SysSettingsService } from '@certd/lib-server'; +import { IUrlService } from "@certd/pipeline"; +import { Inject, Provide, Scope, ScopeEnum } from "@midwayjs/core"; +import { SysInstallInfo, SysSettingsService } from "@certd/lib-server"; @Provide() @Scope(ScopeEnum.Request, { allowDowngrade: true }) @@ -10,7 +10,7 @@ export class UrlService implements IUrlService { async getPipelineDetailUrl(pipelineId: number, historyId: number): Promise { const installInfo = await this.sysSettingsService.getSetting(SysInstallInfo); - let baseUrl = 'http://127.0.0.1:7001'; + let baseUrl = "http://127.0.0.1:7001"; if (installInfo.bindUrl) { baseUrl = installInfo.bindUrl; } diff --git a/packages/ui/certd-server/src/modules/plugin/entity/plugin.ts b/packages/ui/certd-server/src/modules/plugin/entity/plugin.ts index 2c15de374..3371d5122 100644 --- a/packages/ui/certd-server/src/modules/plugin/entity/plugin.ts +++ b/packages/ui/certd-server/src/modules/plugin/entity/plugin.ts @@ -1,66 +1,65 @@ -import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; +import { Column, Entity, PrimaryGeneratedColumn } from "typeorm"; -@Entity('pi_plugin') +@Entity("pi_plugin") export class PluginEntity { @PrimaryGeneratedColumn() id: number; - @Column({ name: 'name', comment: 'Key' }) + @Column({ name: "name", comment: "Key" }) name: string; - @Column({ name: 'icon', comment: '图标' }) + @Column({ name: "icon", comment: "图标" }) icon: string; - @Column({ name: 'title', comment: '标题' }) + @Column({ name: "title", comment: "标题" }) title: string; - @Column({ name: 'group', comment: '分组' }) + @Column({ name: "group", comment: "分组" }) group: string; - @Column({ name: 'desc', comment: '描述' }) + @Column({ name: "desc", comment: "描述" }) desc: string; - @Column({ comment: '配置', length: 40960 }) + @Column({ comment: "配置", length: 40960 }) setting: string; - @Column({ name: 'sys_setting', comment: '系统配置', length: 40960 }) + @Column({ name: "sys_setting", comment: "系统配置", length: 40960 }) sysSetting: string; - @Column({ comment: '脚本', length: 40960 }) + @Column({ comment: "脚本", length: 40960 }) content: string; - @Column({ comment: '类型', length: 100, nullable: true }) + @Column({ comment: "类型", length: 100, nullable: true }) type: string; // builtIn | local | download - @Column({ comment: '启用/禁用', default: false }) + @Column({ comment: "启用/禁用", default: false }) disabled: boolean; - @Column({ comment: '版本', length: 100, nullable: true }) + @Column({ comment: "版本", length: 100, nullable: true }) version: string; - @Column({ comment: '插件类型', length: 100, nullable: true }) + @Column({ comment: "插件类型", length: 100, nullable: true }) pluginType: string; - @Column({ comment: '元数据', length: 40960, nullable: true }) + @Column({ comment: "元数据", length: 40960, nullable: true }) metadata: string; - @Column({ comment: '额外配置', length: 40960, nullable: true }) + @Column({ comment: "额外配置", length: 40960, nullable: true }) extra: string; - @Column({ comment: '作者', length: 100, nullable: true }) + @Column({ comment: "作者", length: 100, nullable: true }) author: string; - @Column({ - name: 'create_time', - comment: '创建时间', - default: () => 'CURRENT_TIMESTAMP', + name: "create_time", + comment: "创建时间", + default: () => "CURRENT_TIMESTAMP", }) createTime: Date; @Column({ - name: 'update_time', - comment: '修改时间', - default: () => 'CURRENT_TIMESTAMP', + name: "update_time", + comment: "修改时间", + default: () => "CURRENT_TIMESTAMP", }) updateTime: Date; } diff --git a/packages/ui/certd-server/src/modules/plugin/service/default-plugin.ts b/packages/ui/certd-server/src/modules/plugin/service/default-plugin.ts index 0728ffcfb..f0b25d1a9 100644 --- a/packages/ui/certd-server/src/modules/plugin/service/default-plugin.ts +++ b/packages/ui/certd-server/src/modules/plugin/service/default-plugin.ts @@ -1,6 +1,5 @@ import { CertApplyPluginNames } from "@certd/plugin-cert"; - export function getDefaultAccessPlugin() { const metadata = ` input: @@ -18,7 +17,7 @@ input: component: name: a-input allowClear: true -` +`; const script = ` // 必须使用 await import 来引入模块 @@ -31,19 +30,18 @@ return class DemoAccess extends BaseAccess { } `; return { - metadata:metadata, - content: script + metadata: metadata, + content: script, }; } export function getDefaultDeployPlugin() { - - let certApplyNames = '' + let certApplyNames = ""; for (const name of CertApplyPluginNames) { certApplyNames += ` - - "${name}"` + - "${name}"`; } - const metadata =` + const metadata = ` input: # 插件的输入参数 cert: title: 前置任务证书 @@ -90,8 +88,7 @@ input: # 插件的输入参数 #output: # 输出参数,一般插件都不需要配置此项 # outputName: # -` - +`; const script = ` // 要用await来import模块 @@ -129,10 +126,10 @@ return class DemoTask extends AbstractTaskPlugin { // this.outputName = xxxx //设置输出参数,可以被其他插件选择使用 } } -` +`; return { metadata: metadata, - content: script + content: script, }; } @@ -144,7 +141,7 @@ accessType: aliyun # 授权类型名称 #dependLibs: # 依赖的插件,应用商店安装时会先安装依赖插件 # aliyun: * - ` + `; const script = ` const { AbstractDnsProvider } = await import("@certd/pipeline") @@ -186,10 +183,10 @@ return class DemoDnsProvider extends AbstractDnsProvider { } } -` +`; return { metadata: metadata, - content: script - } + content: script, + }; } diff --git a/packages/ui/certd-server/src/modules/plugin/service/plugin-config-getter.ts b/packages/ui/certd-server/src/modules/plugin/service/plugin-config-getter.ts index 622972044..755b7b888 100644 --- a/packages/ui/certd-server/src/modules/plugin/service/plugin-config-getter.ts +++ b/packages/ui/certd-server/src/modules/plugin/service/plugin-config-getter.ts @@ -1,6 +1,6 @@ -import { Inject, Provide, Scope, ScopeEnum } from '@midwayjs/core'; -import { IPluginConfigService, PluginConfig } from '@certd/pipeline'; -import { PluginConfigService } from './plugin-config-service.js'; +import { Inject, Provide, Scope, ScopeEnum } from "@midwayjs/core"; +import { IPluginConfigService, PluginConfig } from "@certd/pipeline"; +import { PluginConfigService } from "./plugin-config-service.js"; @Provide() @Scope(ScopeEnum.Request, { allowDowngrade: true }) @@ -11,7 +11,7 @@ export class PluginConfigGetter implements IPluginConfigService { async getPluginConfig(pluginName: string): Promise { const res = await this.pluginConfigService.getPluginConfig({ name: pluginName, - type: 'builtIn', + type: "builtIn", }); return { name: res.name, diff --git a/packages/ui/certd-server/src/modules/plugin/service/plugin-config-service.ts b/packages/ui/certd-server/src/modules/plugin/service/plugin-config-service.ts index d77000fd5..1a4ec2d49 100644 --- a/packages/ui/certd-server/src/modules/plugin/service/plugin-config-service.ts +++ b/packages/ui/certd-server/src/modules/plugin/service/plugin-config-service.ts @@ -1,5 +1,5 @@ -import { Inject, Provide, Scope, ScopeEnum } from '@midwayjs/core'; -import { PluginService } from './plugin-service.js'; +import { Inject, Provide, Scope, ScopeEnum } from "@midwayjs/core"; +import { PluginService } from "./plugin-service.js"; export type PluginConfig = { name: string; @@ -20,7 +20,6 @@ export type PluginFindReq = { type: string; }; - @Provide() @Scope(ScopeEnum.Request, { allowDowngrade: true }) export class PluginConfigService { @@ -31,18 +30,18 @@ export class PluginConfigService { const configs: CommPluginConfig = {}; configs.CertApply = await this.getPluginConfig({ - name: 'CertApply', - type: 'builtIn', + name: "CertApply", + type: "builtIn", }); return configs; } async saveCommPluginConfig(config: CommPluginConfig) { - config.CertApply.name = 'CertApply'; + config.CertApply.name = "CertApply"; await this.savePluginConfig(config.CertApply); } - async savePluginConfig( config: PluginConfig) { + async savePluginConfig(config: PluginConfig) { const name = config.name; const sysSetting = config?.sysSetting; if (!sysSetting) { @@ -55,12 +54,12 @@ export class PluginConfigService { await this.pluginService.add({ name, sysSetting: JSON.stringify(sysSetting), - type: 'builtIn', + type: "builtIn", disabled: false, author: "certd", }); } else { - let setting = JSON.parse(pluginEntity.sysSetting || "{}"); + const setting = JSON.parse(pluginEntity.sysSetting || "{}"); if (sysSetting.metadata) { setting.metadata = sysSetting.metadata; } @@ -73,7 +72,7 @@ export class PluginConfigService { async get(req: PluginFindReq) { if (!req.name && !req.id) { - throw new Error('plugin s name or id is required'); + throw new Error("plugin s name or id is required"); } return await this.pluginService.getRepository().findOne({ where: { 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 922182751..290905683 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 @@ -15,21 +15,21 @@ import fs from "fs"; import path from "path"; export type PluginImportReq = { - content: string, + content: string; override?: boolean; }; - async function importer(modulePath: string) { +async function importer(modulePath: string) { if (!modulePath) { - throw new Error("modules path 不能为空") + throw new Error("modules path 不能为空"); } if (!modulePath.startsWith("/@/")) { - return await import(modulePath) + return await import(modulePath); } - modulePath = modulePath.replace("/@/", "") + modulePath = modulePath.replace("/@/", ""); //替换@为相对地址 - modulePath = `../../../${modulePath}` - return await import(modulePath) + modulePath = `../../../${modulePath}`; + return await import(modulePath); } @Provide() @@ -48,7 +48,6 @@ export class PluginService extends BaseService { // eslint-disable-next-line @typescript-eslint/no-unused-vars async page(pageReq: PageReq) { - if (pageReq.query.type && pageReq.query.type !== "builtIn") { return await super.page(pageReq); } @@ -56,7 +55,6 @@ export class PluginService extends BaseService { const offset = pageReq.page.offset; const limit = pageReq.page.limit; - const builtInList = await this.getBuiltInEntityList(); //获取分页数据 @@ -66,11 +64,11 @@ export class PluginService extends BaseService { records: data, total: builtInList.length, offset: offset, - limit: limit + limit: limit, }; } - 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) { @@ -81,7 +79,6 @@ export class PluginService extends BaseService { } } - if (!isComm()) { return groups; } @@ -91,14 +88,14 @@ export class PluginService extends BaseService { select: { id: true, name: true, - sysSetting: 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; @@ -113,17 +110,16 @@ export class PluginService extends BaseService { for (const item of group.plugins) { const pluginSetting = pluginSettingMap[item.name]; if (pluginSetting) { - item.sysSetting = pluginSetting + item.sysSetting = pluginSetting; } } } - //排除禁用的 const list = await this.list({ query: { - disabled: true - } + disabled: true, + }, }); const disabledNames = list.map(it => it.name); for (const key in groups) { @@ -145,8 +141,8 @@ export class PluginService extends BaseService { const list = await this.list({ query: { type: "builtIn", - disabled: true - } + disabled: true, + }, }); const disabledNames = list.map(it => it.name); @@ -159,8 +155,8 @@ export class PluginService extends BaseService { const builtInList = this.builtInPluginService.getList(); const list = await this.list({ query: { - type: "builtIn" - } + type: "builtIn", + }, }); const records: PluginEntity[] = []; @@ -177,7 +173,7 @@ export class PluginService extends BaseService { type: "builtIn", icon: item.icon, desc: item.desc, - group: item.group + group: item.group, }); records.push(record); } @@ -215,12 +211,11 @@ export class PluginService extends BaseService { * @param param 数据 */ async add(param: any) { - const old = await this.repository.findOne({ where: { name: param.name, - author: param.author - } + author: param.author, + }, }); if (old) { @@ -248,11 +243,11 @@ export class PluginService extends BaseService { const res = await super.add({ ...param, - ...plugin + ...plugin, }); await this.registerById(res.id); - return res + return res; } async registerById(id: any) { @@ -276,20 +271,20 @@ export class PluginService extends BaseService { } let name = item.name; if (item.author && !item.name.startsWith(`${item.author}/`)) { - name = `${item.author}/${item.name}` + name = `${item.author}/${item.name}`; } if (item.pluginType === "access") { - accessRegistry.unRegister(name) + accessRegistry.unRegister(name); } else if (item.pluginType === "deploy") { - pluginRegistry.unRegister(name) + pluginRegistry.unRegister(name); } else if (item.pluginType === "dnsProvider") { - dnsProviderRegistry.unRegister(name) + dnsProviderRegistry.unRegister(name); } else if (item.pluginType === "notification") { - notificationRegistry.unRegister(name) - }else if (item.pluginType === "addon") { - addonRegistry.unRegister(name) + notificationRegistry.unRegister(name); + } else if (item.pluginType === "addon") { + addonRegistry.unRegister(name); } else { - logger.warn(`不支持的插件类型:${item.pluginType}`) + logger.warn(`不支持的插件类型:${item.pluginType}`); } } @@ -297,8 +292,8 @@ export class PluginService extends BaseService { const old = await this.repository.findOne({ where: { name: param.name, - author: param.author - } + author: param.author, + }, }); if (old && old.id !== param.id) { @@ -309,22 +304,21 @@ export class PluginService extends BaseService { const res = await super.update(param); await this.registerById(param.id); - return res + return res; } 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 classNames = Object.keys(res) - return res[classNames[classNames.length - 1]] + const res = await import(`../../..${scriptFilePath}`); + const classNames = Object.keys(res); + return res[classNames[classNames.length - 1]]; } async getPluginClassFromDb(pluginName: string) { @@ -341,14 +335,13 @@ export class PluginService extends BaseService { const info = await this.find({ where: { name: name, - author: author - } + author: author, + }, }); if (info && info.length > 0) { const plugin = info[0]; try { - const AsyncFunction = Object.getPrototypeOf(async () => { - }).constructor; + const AsyncFunction = Object.getPrototypeOf(async () => {}).constructor; // const script = await this.compile(plugin.content); const script = plugin.content; const getPluginClass = new AsyncFunction("_ctx", script); @@ -357,7 +350,6 @@ export class PluginService extends BaseService { logger.error("编译插件失败:", e); throw e; } - } throw new Error(`插件${pluginName}不存在`); } @@ -367,11 +359,11 @@ export class PluginService extends BaseService { */ async registerFromDb() { const res = await this.list({ - buildQuery: ((bq) => { + buildQuery: bq => { bq.andWhere("type != :type", { - type: "builtIn" + type: "builtIn", }); - }) + }, }); for (const item of res) { @@ -382,7 +374,7 @@ export class PluginService extends BaseService { async registerFromLocal(localDir: string) { //scan path const files = fs.readdirSync(localDir); - let list = [] + let list = []; for (const file of files) { if (!file.endsWith(".yaml")) { continue; @@ -390,7 +382,6 @@ export class PluginService extends BaseService { const item = yaml.load(fs.readFileSync(path.join(localDir, file), "utf8")); list.push(item); - } //排序 list = list.sort((a, b) => { @@ -408,7 +399,7 @@ export class PluginService extends BaseService { const item = { ...plugin, ...metadata, - ...extra + ...extra, }; delete item.metadata; delete item.content; @@ -416,7 +407,7 @@ export class PluginService extends BaseService { if (item.author && !item.name.startsWith(`${item.author}/`)) { item.name = item.author + "/" + item.name; } - let name = item.name + let name = item.name; if (item.addonType) { name = item.addonType + ":" + name; } @@ -444,7 +435,7 @@ export class PluginService extends BaseService { } else { return await this.getPluginClassFromDb(name); } - } + }, }); } @@ -466,35 +457,34 @@ export class PluginService extends BaseService { ...info, ...metadata, ...extra, - content + content, }; return yaml.dump(plugin) as string; } async importPlugin(req: PluginImportReq) { - const loaded = yaml.load(req.content); if (!loaded) { throw new Error("插件内容不能为空"); } - delete loaded.id + delete loaded.id; const old = await this.repository.findOne({ where: { name: loaded.name, - author: loaded.author - } + author: loaded.author, + }, }); const metadata = { input: loaded.input, - output: loaded.output + output: loaded.output, }; const extra = { dependPlugins: loaded.dependPlugins, default: loaded.default, - showRunStrategy: loaded.showRunStrategy + showRunStrategy: loaded.showRunStrategy, }; const pluginEntity = { @@ -502,7 +492,7 @@ export class PluginService extends BaseService { metadata: yaml.dump(metadata), extra: yaml.dump(extra), content: loaded.content, - disabled: false + disabled: false, }; if (!pluginEntity.pluginType) { throw new Error(`插件类型不能为空`); @@ -521,7 +511,7 @@ export class PluginService extends BaseService { //update await this.update(pluginEntity); return { - id: pluginEntity.id + id: pluginEntity.id, }; } async deleteByIds(ids: any[]) { @@ -531,5 +521,4 @@ export class PluginService extends BaseService { await this.delete(id); } } - } diff --git a/packages/ui/certd-server/src/modules/suite/payments/index.ts b/packages/ui/certd-server/src/modules/suite/payments/index.ts index e5d401f45..0d8141122 100644 --- a/packages/ui/certd-server/src/modules/suite/payments/index.ts +++ b/packages/ui/certd-server/src/modules/suite/payments/index.ts @@ -1,6 +1,5 @@ -import {paymentProviderFactory} from "@certd/commercial-core" +import { paymentProviderFactory } from "@certd/commercial-core"; export function registerPaymentProviders() { - paymentProviderFactory.registerProvider("alipay", async () => (await import("./alipay.js")).PaymentAlipay); paymentProviderFactory.registerProvider("wxpay", async () => (await import("./wxpay.js")).PaymentWxpay); paymentProviderFactory.registerProvider("yizhifu", async () => (await import("./yizhifu.js")).PaymentYizhifu); diff --git a/packages/ui/certd-server/src/modules/suite/service/my-count-service.ts b/packages/ui/certd-server/src/modules/suite/service/my-count-service.ts index cedef6bf5..ed52e8952 100644 --- a/packages/ui/certd-server/src/modules/suite/service/my-count-service.ts +++ b/packages/ui/certd-server/src/modules/suite/service/my-count-service.ts @@ -1,10 +1,10 @@ -import { Inject, Provide, Scope, ScopeEnum } from '@midwayjs/core'; -import { PipelineService } from '../../pipeline/service/pipeline-service.js'; -import { CertInfoService } from '../../monitor/service/cert-info-service.js'; -import { IUsedCountService } from '@certd/commercial-core'; -import { SiteInfoService } from '../../monitor/service/site-info-service.js'; +import { Inject, Provide, Scope, ScopeEnum } from "@midwayjs/core"; +import { PipelineService } from "../../pipeline/service/pipeline-service.js"; +import { CertInfoService } from "../../monitor/service/cert-info-service.js"; +import { IUsedCountService } from "@certd/commercial-core"; +import { SiteInfoService } from "../../monitor/service/site-info-service.js"; -@Provide('myCountService') +@Provide("myCountService") @Scope(ScopeEnum.Request, { allowDowngrade: true }) export class MyCountService implements IUsedCountService { @Inject() @@ -17,7 +17,7 @@ export class MyCountService implements IUsedCountService { async getUsedCount(userId: number) { if (!userId) { - throw new Error('userId is required'); + throw new Error("userId is required"); } const pipelineCountUsed = await this.pipelineService.getUserPipelineCount(userId); const domainCountUsed = await this.certInfoService.getUserDomainCount(userId); diff --git a/packages/ui/certd-server/src/modules/sys/authority/entity/permission.ts b/packages/ui/certd-server/src/modules/sys/authority/entity/permission.ts index 6fa91e18d..33dc8b0a4 100644 --- a/packages/ui/certd-server/src/modules/sys/authority/entity/permission.ts +++ b/packages/ui/certd-server/src/modules/sys/authority/entity/permission.ts @@ -1,37 +1,37 @@ -import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; +import { Column, Entity, PrimaryGeneratedColumn } from "typeorm"; /** * 权限 */ -@Entity('sys_permission') +@Entity("sys_permission") export class PermissionEntity { @PrimaryGeneratedColumn() id: number; - @Column({ comment: '标题', length: 100 }) + @Column({ comment: "标题", length: 100 }) title: string; /** * 权限代码 * 示例:sys:user:read */ - @Column({ comment: '权限代码', length: 100, nullable: true }) + @Column({ comment: "权限代码", length: 100, nullable: true }) permission: string; - @Column({ name: 'parent_id', comment: '父节点ID', default: -1 }) + @Column({ name: "parent_id", comment: "父节点ID", default: -1 }) parentId: number; - @Column({ comment: '排序号' }) + @Column({ comment: "排序号" }) sort: number; @Column({ - name: 'create_time', - comment: '创建时间', - default: () => 'CURRENT_TIMESTAMP', + name: "create_time", + comment: "创建时间", + default: () => "CURRENT_TIMESTAMP", }) createTime: Date; @Column({ - name: 'update_time', - comment: '修改时间', - default: () => 'CURRENT_TIMESTAMP', + name: "update_time", + comment: "修改时间", + default: () => "CURRENT_TIMESTAMP", }) updateTime: Date; diff --git a/packages/ui/certd-server/src/modules/sys/authority/entity/role-permission.ts b/packages/ui/certd-server/src/modules/sys/authority/entity/role-permission.ts index 85ac0c734..ff9ae1ef1 100644 --- a/packages/ui/certd-server/src/modules/sys/authority/entity/role-permission.ts +++ b/packages/ui/certd-server/src/modules/sys/authority/entity/role-permission.ts @@ -1,12 +1,12 @@ -import { Entity, PrimaryColumn } from 'typeorm'; +import { Entity, PrimaryColumn } from "typeorm"; /** * 角色权限多对多 */ -@Entity('sys_role_permission') +@Entity("sys_role_permission") export class RolePermissionEntity { - @PrimaryColumn({ name: 'role_id' }) + @PrimaryColumn({ name: "role_id" }) roleId: number; - @PrimaryColumn({ name: 'permission_id' }) + @PrimaryColumn({ name: "permission_id" }) permissionId: number; } diff --git a/packages/ui/certd-server/src/modules/sys/authority/entity/role.ts b/packages/ui/certd-server/src/modules/sys/authority/entity/role.ts index 2aecfb743..034d87533 100644 --- a/packages/ui/certd-server/src/modules/sys/authority/entity/role.ts +++ b/packages/ui/certd-server/src/modules/sys/authority/entity/role.ts @@ -1,26 +1,26 @@ -import { Column, Entity, Index, PrimaryGeneratedColumn } from 'typeorm'; +import { Column, Entity, Index, PrimaryGeneratedColumn } from "typeorm"; /** * 角色 */ -@Entity('sys_role') +@Entity("sys_role") export class RoleEntity { @PrimaryGeneratedColumn() id: number; @Index({ unique: true }) - @Column({ comment: '角色名称', length: 100 }) + @Column({ comment: "角色名称", length: 100 }) name: string; @Column({ - name: 'create_time', - comment: '创建时间', - default: () => 'CURRENT_TIMESTAMP', + name: "create_time", + comment: "创建时间", + default: () => "CURRENT_TIMESTAMP", }) createTime: Date; @Column({ - name: 'update_time', - comment: '修改时间', - default: () => 'CURRENT_TIMESTAMP', + name: "update_time", + comment: "修改时间", + default: () => "CURRENT_TIMESTAMP", }) updateTime: Date; diff --git a/packages/ui/certd-server/src/modules/sys/authority/entity/user-role.ts b/packages/ui/certd-server/src/modules/sys/authority/entity/user-role.ts index f22255b87..9dc51919d 100644 --- a/packages/ui/certd-server/src/modules/sys/authority/entity/user-role.ts +++ b/packages/ui/certd-server/src/modules/sys/authority/entity/user-role.ts @@ -1,13 +1,13 @@ -import { Entity, PrimaryColumn } from 'typeorm'; +import { Entity, PrimaryColumn } from "typeorm"; /** * 用户角色多对多 */ -@Entity('sys_user_role') +@Entity("sys_user_role") export class UserRoleEntity { - @PrimaryColumn({ name: 'role_id' }) + @PrimaryColumn({ name: "role_id" }) roleId: number; - @PrimaryColumn({ name: 'user_id' }) + @PrimaryColumn({ name: "user_id" }) userId: number; static of(userId: number, roleId: number): UserRoleEntity { diff --git a/packages/ui/certd-server/src/modules/sys/authority/entity/user.ts b/packages/ui/certd-server/src/modules/sys/authority/entity/user.ts index c7deb0289..922b2f657 100644 --- a/packages/ui/certd-server/src/modules/sys/authority/entity/user.ts +++ b/packages/ui/certd-server/src/modules/sys/authority/entity/user.ts @@ -1,56 +1,56 @@ -import { Column, Entity, Index, PrimaryGeneratedColumn } from 'typeorm'; +import { Column, Entity, Index, PrimaryGeneratedColumn } from "typeorm"; /** * 系统用户 */ -@Entity('sys_user') +@Entity("sys_user") export class UserEntity { @PrimaryGeneratedColumn() id: number; @Index({ unique: true }) - @Column({ comment: '用户名', length: 100 }) + @Column({ comment: "用户名", length: 100 }) username: string; - @Column({ comment: '密码', length: 100 }) + @Column({ comment: "密码", length: 100 }) password: string; - @Column({ name: 'password_version', comment: '密码版本' }) + @Column({ name: "password_version", comment: "密码版本" }) passwordVersion: number; - @Column({ name: 'nick_name', comment: '昵称', length: 100, nullable: true }) + @Column({ name: "nick_name", comment: "昵称", length: 100, nullable: true }) nickName: string; - @Column({ comment: '头像', length: 255, nullable: true }) + @Column({ comment: "头像", length: 255, nullable: true }) avatar: string; - @Column({ name: 'phone_code', comment: '区号', length: 20, nullable: true }) + @Column({ name: "phone_code", comment: "区号", length: 20, nullable: true }) phoneCode: string; - @Column({ comment: '手机', length: 20, nullable: true }) + @Column({ comment: "手机", length: 20, nullable: true }) mobile: string; - @Column({ comment: '邮箱', length: 50, nullable: true }) + @Column({ comment: "邮箱", length: 50, nullable: true }) email: string; - @Column({ comment: '备注', length: 100, nullable: true }) + @Column({ comment: "备注", length: 100, nullable: true }) remark: string; - @Column({ comment: '状态 0:禁用 1:启用', default: 1 }) + @Column({ comment: "状态 0:禁用 1:启用", default: 1 }) status: number; - @Column({ name: 'valid_time', comment: '有效期', nullable: true }) + @Column({ name: "valid_time", comment: "有效期", nullable: true }) validTime: number; @Column({ - name: 'create_time', - comment: '创建时间', - default: () => 'CURRENT_TIMESTAMP', + name: "create_time", + comment: "创建时间", + default: () => "CURRENT_TIMESTAMP", }) createTime: Date; @Column({ - name: 'update_time', - comment: '修改时间', - default: () => 'CURRENT_TIMESTAMP', + name: "update_time", + comment: "修改时间", + default: () => "CURRENT_TIMESTAMP", }) updateTime: Date; diff --git a/packages/ui/certd-server/src/modules/sys/authority/enums/ResourceTypeEnum.ts b/packages/ui/certd-server/src/modules/sys/authority/enums/ResourceTypeEnum.ts index 8067a520a..ac999c56e 100644 --- a/packages/ui/certd-server/src/modules/sys/authority/enums/ResourceTypeEnum.ts +++ b/packages/ui/certd-server/src/modules/sys/authority/enums/ResourceTypeEnum.ts @@ -1,9 +1,9 @@ -import { EnumItem } from '@certd/lib-server'; -import * as _ from 'lodash-es'; +import { EnumItem } from "@certd/lib-server"; +import * as _ from "lodash-es"; class ResourceTypes { - MENU = new EnumItem('menu', '菜单', 'blue'); - BTN = new EnumItem('btn', '按钮', 'green'); - ROUTE = new EnumItem('route', '路由', 'red'); + MENU = new EnumItem("menu", "菜单", "blue"); + BTN = new EnumItem("btn", "按钮", "green"); + ROUTE = new EnumItem("route", "路由", "red"); names() { const list = []; diff --git a/packages/ui/certd-server/src/modules/sys/authority/service/auth-service.ts b/packages/ui/certd-server/src/modules/sys/authority/service/auth-service.ts index 3eaa1dd4a..0f069d293 100644 --- a/packages/ui/certd-server/src/modules/sys/authority/service/auth-service.ts +++ b/packages/ui/certd-server/src/modules/sys/authority/service/auth-service.ts @@ -1,5 +1,5 @@ -import { Inject, Provide, Scope, ScopeEnum } from '@midwayjs/core'; -import { RoleService } from './role-service.js'; +import { Inject, Provide, Scope, ScopeEnum } from "@midwayjs/core"; +import { RoleService } from "./role-service.js"; /** * 权限校验 @@ -28,7 +28,7 @@ export class AuthService { } //管理员有权限查看其他用户的数据 - async checkUserIdButAllowAdmin(ctx: any, service: any, ids: number| number[] = null, userKey = 'userId') { + async checkUserIdButAllowAdmin(ctx: any, service: any, ids: number | number[] = null, userKey = "userId") { const isAdmin = await this.isAdmin(ctx); if (isAdmin) { return true; @@ -36,11 +36,11 @@ export class AuthService { await service.checkUserId(ids, ctx.user.id, userKey); } - async checkProjectId(service:any,ids:number| number[] = null,projectId = null){ - await service.checkUserId(ids, projectId , "projectId"); + async checkProjectId(service: any, ids: number | number[] = null, projectId = null) { + await service.checkUserId(ids, projectId, "projectId"); } - async checkUserId(service:any,ids:number| number[] = null,userId = null){ - await service.checkUserId(ids, userId , "userId"); + async checkUserId(service: any, ids: number | number[] = null, userId = null) { + await service.checkUserId(ids, userId, "userId"); } } diff --git a/packages/ui/certd-server/src/modules/sys/authority/service/permission-service.ts b/packages/ui/certd-server/src/modules/sys/authority/service/permission-service.ts index 98432b42f..6a49cef2b 100644 --- a/packages/ui/certd-server/src/modules/sys/authority/service/permission-service.ts +++ b/packages/ui/certd-server/src/modules/sys/authority/service/permission-service.ts @@ -1,8 +1,8 @@ -import { Provide, Scope, ScopeEnum } from '@midwayjs/core'; -import { InjectEntityModel } from '@midwayjs/typeorm'; -import { Repository } from 'typeorm'; -import { BaseService } from '@certd/lib-server'; -import { PermissionEntity } from '../entity/permission.js'; +import { Provide, Scope, ScopeEnum } from "@midwayjs/core"; +import { InjectEntityModel } from "@midwayjs/typeorm"; +import { Repository } from "typeorm"; +import { BaseService } from "@certd/lib-server"; +import { PermissionEntity } from "../entity/permission.js"; /** * 权限资源 @@ -21,7 +21,7 @@ export class PermissionService extends BaseService { async tree(options: any = {}) { if (options.order == null) { options.order = { - sort: 'ASC', + sort: "ASC", }; } const list = await this.find(options); diff --git a/packages/ui/certd-server/src/modules/sys/authority/service/role-permission-service.ts b/packages/ui/certd-server/src/modules/sys/authority/service/role-permission-service.ts index 45ffa8092..10278a9d2 100644 --- a/packages/ui/certd-server/src/modules/sys/authority/service/role-permission-service.ts +++ b/packages/ui/certd-server/src/modules/sys/authority/service/role-permission-service.ts @@ -1,8 +1,8 @@ -import { Provide, Scope, ScopeEnum } from '@midwayjs/core'; -import { InjectEntityModel } from '@midwayjs/typeorm'; -import { Repository } from 'typeorm'; -import { BaseService } from '@certd/lib-server'; -import { RolePermissionEntity } from '../entity/role-permission.js'; +import { Provide, Scope, ScopeEnum } from "@midwayjs/core"; +import { InjectEntityModel } from "@midwayjs/typeorm"; +import { Repository } from "typeorm"; +import { BaseService } from "@certd/lib-server"; +import { RolePermissionEntity } from "../entity/role-permission.js"; /** * 角色->权限 diff --git a/packages/ui/certd-server/src/modules/sys/authority/service/role-service.ts b/packages/ui/certd-server/src/modules/sys/authority/service/role-service.ts index 636ae8488..29bc24853 100644 --- a/packages/ui/certd-server/src/modules/sys/authority/service/role-service.ts +++ b/packages/ui/certd-server/src/modules/sys/authority/service/role-service.ts @@ -1,14 +1,14 @@ -import { Inject, Provide, Scope, ScopeEnum } from '@midwayjs/core'; -import { InjectEntityModel } from '@midwayjs/typeorm'; -import { In, Repository } from 'typeorm'; -import { BaseService } from '@certd/lib-server'; -import { RoleEntity } from '../entity/role.js'; -import { UserRoleService } from './user-role-service.js'; -import { RolePermissionEntity } from '../entity/role-permission.js'; -import { PermissionService } from './permission-service.js'; -import * as _ from 'lodash-es'; -import { RolePermissionService } from './role-permission-service.js'; -import { LRUCache } from 'lru-cache'; +import { Inject, Provide, Scope, ScopeEnum } from "@midwayjs/core"; +import { InjectEntityModel } from "@midwayjs/typeorm"; +import { In, Repository } from "typeorm"; +import { BaseService } from "@certd/lib-server"; +import { RoleEntity } from "../entity/role.js"; +import { UserRoleService } from "./user-role-service.js"; +import { RolePermissionEntity } from "../entity/role-permission.js"; +import { PermissionService } from "./permission-service.js"; +import * as _ from "lodash-es"; +import { RolePermissionService } from "./role-permission-service.js"; +import { LRUCache } from "lru-cache"; const permissionCache = new LRUCache({ max: 1000, @@ -30,8 +30,6 @@ export class RoleService extends BaseService { @Inject() rolePermissionService: RolePermissionService; - - //@ts-ignore getRepository() { return this.repository; @@ -55,10 +53,7 @@ export class RoleService extends BaseService { if (!roleIds || roleIds.length === 0) { return []; } - return await this.permissionService.repository - .createQueryBuilder('permission') - .innerJoinAndSelect(RolePermissionEntity, 'rp', 'rp.permissionId = permission.id and rp.roleId in (:...roleIds)', { roleIds }) - .getMany(); + return await this.permissionService.repository.createQueryBuilder("permission").innerJoinAndSelect(RolePermissionEntity, "rp", "rp.permissionId = permission.id and rp.roleId in (:...roleIds)", { roleIds }).getMany(); } async addRoles(userId: number, roles) { @@ -122,7 +117,7 @@ export class RoleService extends BaseService { } async getCachedPermissionSetByRoleIds(roleIds: number[]): Promise> { - const roleIdsKey = roleIds.join(','); + const roleIdsKey = roleIds.join(","); let permissionSet = permissionCache.get(roleIdsKey); if (permissionSet) { return permissionSet; @@ -138,7 +133,7 @@ export class RoleService extends BaseService { //@ts-ignore const urs = await this.userRoleService.find({ where: { roleId: In(idArr) } }); if (urs.length > 0) { - throw new Error('该角色已被用户使用,无法删除'); + throw new Error("该角色已被用户使用,无法删除"); } await this.deleteWhere({ id: In(idArr) }); } diff --git a/packages/ui/certd-server/src/modules/sys/authority/service/user-contact.test.ts b/packages/ui/certd-server/src/modules/sys/authority/service/user-contact.test.ts index ce0f6818a..044bcadbe 100644 --- a/packages/ui/certd-server/src/modules/sys/authority/service/user-contact.test.ts +++ b/packages/ui/certd-server/src/modules/sys/authority/service/user-contact.test.ts @@ -1,27 +1,27 @@ /// -import assert from 'node:assert/strict'; -import { Not } from 'typeorm'; -import { buildUserContactConflictWhere } from './user-service.js'; +import assert from "node:assert/strict"; +import { Not } from "typeorm"; +import { buildUserContactConflictWhere } from "./user-service.js"; -describe('buildUserContactConflictWhere', () => { - it('checks username, mobile and email conflicts except current user', () => { - const where = buildUserContactConflictWhere('user@example.com', 12); +describe("buildUserContactConflictWhere", () => { + it("checks username, mobile and email conflicts except current user", () => { + const where = buildUserContactConflictWhere("user@example.com", 12); assert.deepEqual(where, [ - { username: 'user@example.com', id: Not(12) }, - { mobile: 'user@example.com', id: Not(12) }, - { email: 'user@example.com', id: Not(12) }, + { username: "user@example.com", id: Not(12) }, + { mobile: "user@example.com", id: Not(12) }, + { email: "user@example.com", id: Not(12) }, ]); }); - it('trims contact value before building conflict query', () => { - const where = buildUserContactConflictWhere(' 13800138000 ', 3); + it("trims contact value before building conflict query", () => { + const where = buildUserContactConflictWhere(" 13800138000 ", 3); assert.deepEqual(where, [ - { username: '13800138000', id: Not(3) }, - { mobile: '13800138000', id: Not(3) }, - { email: '13800138000', id: Not(3) }, + { username: "13800138000", id: Not(3) }, + { mobile: "13800138000", id: Not(3) }, + { email: "13800138000", id: Not(3) }, ]); }); }); diff --git a/packages/ui/certd-server/src/modules/sys/authority/service/user-role-service.ts b/packages/ui/certd-server/src/modules/sys/authority/service/user-role-service.ts index d106aef71..647b6234a 100644 --- a/packages/ui/certd-server/src/modules/sys/authority/service/user-role-service.ts +++ b/packages/ui/certd-server/src/modules/sys/authority/service/user-role-service.ts @@ -1,8 +1,8 @@ -import { Provide, Scope, ScopeEnum } from '@midwayjs/core'; -import { InjectEntityModel } from '@midwayjs/typeorm'; -import { Repository } from 'typeorm'; -import { BaseService } from '@certd/lib-server'; -import { UserRoleEntity } from '../entity/user-role.js'; +import { Provide, Scope, ScopeEnum } from "@midwayjs/core"; +import { InjectEntityModel } from "@midwayjs/typeorm"; +import { Repository } from "typeorm"; +import { BaseService } from "@certd/lib-server"; +import { UserRoleEntity } from "../entity/user-role.js"; /** * 用户->角色 diff --git a/packages/ui/certd-server/src/modules/sys/enterprise/entity/audit-log.ts b/packages/ui/certd-server/src/modules/sys/enterprise/entity/audit-log.ts index 3de938245..b053977ca 100644 --- a/packages/ui/certd-server/src/modules/sys/enterprise/entity/audit-log.ts +++ b/packages/ui/certd-server/src/modules/sys/enterprise/entity/audit-log.ts @@ -1,46 +1,46 @@ -import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; +import { Column, Entity, PrimaryGeneratedColumn } from "typeorm"; /** */ -@Entity('cd_audit_log') +@Entity("cd_audit_log") export class AuditLogEntity { @PrimaryGeneratedColumn() id: number; - @Column({ name: 'user_id', comment: 'UserId' }) + @Column({ name: "user_id", comment: "UserId" }) userId: number; - @Column({ name: 'user_name', comment: '用户名' }) + @Column({ name: "user_name", comment: "用户名" }) userName: string; - @Column({ name: 'project_id', comment: 'ProjectId' }) + @Column({ name: "project_id", comment: "ProjectId" }) projectId: number; - @Column({ name: 'project_name', comment: '项目名称' }) + @Column({ name: "project_name", comment: "项目名称" }) projectName: string; - @Column({ name: 'type', comment: '类型' }) + @Column({ name: "type", comment: "类型" }) type: string; - @Column({ name: 'action', comment: '操作' }) + @Column({ name: "action", comment: "操作" }) action: string; - @Column({ name: 'content', comment: '内容' }) + @Column({ name: "content", comment: "内容" }) content: string; - @Column({ name: 'ip_address', comment: 'IP地址' }) - ipAddress: string; + @Column({ name: "ip_address", comment: "IP地址" }) + ipAddress: string; @Column({ - name: 'create_time', - comment: '创建时间', - default: () => 'CURRENT_TIMESTAMP', + name: "create_time", + comment: "创建时间", + default: () => "CURRENT_TIMESTAMP", }) createTime: Date; @Column({ - name: 'update_time', - comment: '修改时间', - default: () => 'CURRENT_TIMESTAMP', + name: "update_time", + comment: "修改时间", + default: () => "CURRENT_TIMESTAMP", }) updateTime: Date; } diff --git a/packages/ui/certd-server/src/modules/sys/enterprise/entity/project-member.ts b/packages/ui/certd-server/src/modules/sys/enterprise/entity/project-member.ts index 516b65b8c..0297a346f 100644 --- a/packages/ui/certd-server/src/modules/sys/enterprise/entity/project-member.ts +++ b/packages/ui/certd-server/src/modules/sys/enterprise/entity/project-member.ts @@ -1,34 +1,34 @@ -import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; +import { Column, Entity, PrimaryGeneratedColumn } from "typeorm"; /** */ -@Entity('cd_project_member') +@Entity("cd_project_member") export class ProjectMemberEntity { @PrimaryGeneratedColumn() id: number; - @Column({ name: 'user_id', comment: 'UserId' }) + @Column({ name: "user_id", comment: "UserId" }) userId: number; - @Column({ name: 'project_id', comment: 'ProjectId' }) + @Column({ name: "project_id", comment: "ProjectId" }) projectId: number; - - @Column({ name: 'permission', comment: '权限' }) + + @Column({ name: "permission", comment: "权限" }) permission: string; // read / write / admin - @Column({ name: 'status', comment: '申请状态' }) + @Column({ name: "status", comment: "申请状态" }) status: string; // pending / approved / rejected @Column({ - name: 'create_time', - comment: '创建时间', - default: () => 'CURRENT_TIMESTAMP', + name: "create_time", + comment: "创建时间", + default: () => "CURRENT_TIMESTAMP", }) createTime: Date; @Column({ - name: 'update_time', - comment: '修改时间', - default: () => 'CURRENT_TIMESTAMP', + name: "update_time", + comment: "修改时间", + default: () => "CURRENT_TIMESTAMP", }) updateTime: Date; } diff --git a/packages/ui/certd-server/src/modules/sys/enterprise/entity/project.ts b/packages/ui/certd-server/src/modules/sys/enterprise/entity/project.ts index 78897dcee..47ef30312 100644 --- a/packages/ui/certd-server/src/modules/sys/enterprise/entity/project.ts +++ b/packages/ui/certd-server/src/modules/sys/enterprise/entity/project.ts @@ -1,47 +1,45 @@ -import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; +import { Column, Entity, PrimaryGeneratedColumn } from "typeorm"; /** */ -@Entity('cd_project') +@Entity("cd_project") export class ProjectEntity { @PrimaryGeneratedColumn() id: number; - @Column({ name: 'user_id', comment: 'UserId' }) + @Column({ name: "user_id", comment: "UserId" }) userId: number; - @Column({ name: 'admin_id', comment: '管理员Id' }) + @Column({ name: "admin_id", comment: "管理员Id" }) adminId: number; - @Column({ name: 'name', comment: '项目名称' }) + @Column({ name: "name", comment: "项目名称" }) name: string; - @Column({ name: 'disabled', comment: '禁用' }) + @Column({ name: "disabled", comment: "禁用" }) disabled: boolean; - @Column({ name: 'is_system', comment: '是否系统项目' }) + @Column({ name: "is_system", comment: "是否系统项目" }) isSystem: boolean; //系统项目内的流水线允许运行管理员级别的插件 - @Column({ - name: 'create_time', - comment: '创建时间', - default: () => 'CURRENT_TIMESTAMP', + name: "create_time", + comment: "创建时间", + default: () => "CURRENT_TIMESTAMP", }) createTime: Date; @Column({ - name: 'update_time', - comment: '修改时间', - default: () => 'CURRENT_TIMESTAMP', + name: "update_time", + comment: "修改时间", + default: () => "CURRENT_TIMESTAMP", }) updateTime: Date; // user permission read write admin - permission:string - + permission: string; } export type ProjectMemberItem = { memberId: number; status: string; -} & ProjectEntity +} & ProjectEntity; diff --git a/packages/ui/certd-server/src/modules/sys/enterprise/service/project-member-service.ts b/packages/ui/certd-server/src/modules/sys/enterprise/service/project-member-service.ts index e61dcd7d3..c0dd8bb90 100644 --- a/packages/ui/certd-server/src/modules/sys/enterprise/service/project-member-service.ts +++ b/packages/ui/certd-server/src/modules/sys/enterprise/service/project-member-service.ts @@ -1,8 +1,8 @@ -import {Inject, Provide, Scope, ScopeEnum} from '@midwayjs/core'; -import {BaseService, SysSettingsService} from '@certd/lib-server'; -import {InjectEntityModel} from '@midwayjs/typeorm'; -import {Repository} from 'typeorm'; -import { ProjectMemberEntity } from '../entity/project-member.js'; +import { Inject, Provide, Scope, ScopeEnum } from "@midwayjs/core"; +import { BaseService, SysSettingsService } from "@certd/lib-server"; +import { InjectEntityModel } from "@midwayjs/typeorm"; +import { Repository } from "typeorm"; +import { ProjectMemberEntity } from "../entity/project-member.js"; @Provide() @Scope(ScopeEnum.Request, { allowDowngrade: true }) @@ -19,12 +19,12 @@ export class ProjectMemberService extends BaseService { } async add(bean: Partial) { - const {projectId, userId} = bean; + const { projectId, userId } = bean; if (!projectId) { - throw new Error('项目ID不能为空'); + throw new Error("项目ID不能为空"); } if (!userId || userId <= 0) { - throw new Error('用户ID不能为空'); + throw new Error("用户ID不能为空"); } const exist = await this.repository.findOne({ where: { @@ -32,13 +32,13 @@ export class ProjectMemberService extends BaseService { userId, }, }); - if (exist) { - throw new Error('项目用户已存在'); - } - return await super.add(bean) + if (exist) { + throw new Error("项目用户已存在"); + } + return await super.add(bean); } - async getByUserId(userId: number,status?:string) { + async getByUserId(userId: number, status?: string) { return await this.repository.find({ where: { userId, @@ -47,7 +47,7 @@ export class ProjectMemberService extends BaseService { }); } - async getMember(projectId: number,userId: number,status?:string) { + async getMember(projectId: number, userId: number, status?: string) { return await this.repository.findOne({ where: { userId, @@ -59,15 +59,14 @@ export class ProjectMemberService extends BaseService { async getProjectId(id: number) { const member = await this.repository.findOne({ - select: ['projectId'], + select: ["projectId"], where: { id: id, }, }); if (!member) { - throw new Error('项目成员记录不存在'); + throw new Error("项目成员记录不存在"); } return member.projectId; } - } diff --git a/packages/ui/certd-server/src/modules/sys/enterprise/service/project-service.ts b/packages/ui/certd-server/src/modules/sys/enterprise/service/project-service.ts index 454336707..a23a98a4d 100644 --- a/packages/ui/certd-server/src/modules/sys/enterprise/service/project-service.ts +++ b/packages/ui/certd-server/src/modules/sys/enterprise/service/project-service.ts @@ -1,10 +1,10 @@ -import { BaseService, Constants, SysSettingsService } from '@certd/lib-server'; -import { Inject, Provide, Scope, ScopeEnum } from '@midwayjs/core'; -import { InjectEntityModel } from '@midwayjs/typeorm'; -import { LRUCache } from 'lru-cache'; -import { Repository } from 'typeorm'; -import { ProjectEntity, ProjectMemberItem } from '../entity/project.js'; -import { ProjectMemberService } from './project-member-service.js'; +import { BaseService, Constants, SysSettingsService } from "@certd/lib-server"; +import { Inject, Provide, Scope, ScopeEnum } from "@midwayjs/core"; +import { InjectEntityModel } from "@midwayjs/typeorm"; +import { LRUCache } from "lru-cache"; +import { Repository } from "typeorm"; +import { ProjectEntity, ProjectMemberItem } from "../entity/project.js"; +import { ProjectMemberService } from "./project-member-service.js"; const projectCache = new LRUCache({ max: 1000, @@ -16,7 +16,6 @@ const ENTERPRISE_USER_ID = Constants.enterpriseUserId; //企业模式下 企业u @Provide() @Scope(ScopeEnum.Request, { allowDowngrade: true }) export class ProjectService extends BaseService { - @InjectEntityModel(ProjectEntity) repository: Repository; @@ -34,7 +33,7 @@ export class ProjectService extends BaseService { async add(bean: ProjectEntity) { const { name } = bean; if (!name) { - throw new Error('项目名称不能为空'); + throw new Error("项目名称不能为空"); } const exist = await this.repository.findOne({ where: { @@ -43,40 +42,43 @@ export class ProjectService extends BaseService { }, }); if (exist) { - throw new Error('项目名称已存在'); + throw new Error("项目名称已存在"); } - bean.disabled = false - const res = await super.add(bean) + bean.disabled = false; + const res = await super.add(bean); projectCache.clear(); return res; } async update(bean: ProjectEntity) { - const res = await super.update(bean) + const res = await super.update(bean); projectCache.clear(); return res; } async setDisabled(id: number, disabled: boolean) { - await this.repository.update({ - id, - userId: ENTERPRISE_USER_ID, - }, { - disabled, - }); + await this.repository.update( + { + id, + userId: ENTERPRISE_USER_ID, + }, + { + disabled, + } + ); } async getUserProjects(userId: number) { - - const memberList = await this.projectMemberService.getByUserId(userId, 'approved'); - let projectIds = memberList.map(item => item.projectId); + const memberList = await this.projectMemberService.getByUserId(userId, "approved"); + let projectIds = memberList.map(item => item.projectId); if (!projectIds || projectIds.length === 0) { - projectIds = [0] + projectIds = [0]; } - const projectList = await this.repository.createQueryBuilder('project') - .where(' project.disabled = false') - .where(' project.userId = :userId', { userId: ENTERPRISE_USER_ID }) - .where(' project.id IN (:...projectIds) or project.adminId = :userId', { projectIds, userId }) + const projectList = await this.repository + .createQueryBuilder("project") + .where(" project.disabled = false") + .where(" project.userId = :userId", { userId: ENTERPRISE_USER_ID }) + .where(" project.id IN (:...projectIds) or project.adminId = :userId", { projectIds, userId }) .getMany(); const memberPermissionMap = memberList.reduce((prev, cur) => { @@ -86,23 +88,23 @@ export class ProjectService extends BaseService { projectList.forEach(item => { if (item.adminId === userId) { - item.permission = 'admin'; + item.permission = "admin"; } else { - item.permission = memberPermissionMap[item.id] || 'read'; + item.permission = memberPermissionMap[item.id] || "read"; } - }) + }); - return projectList + return projectList; } async getAllWithStatus(userId: number): Promise { - let projectList: any = await this.find({ + const projectList: any = await this.find({ where: { disabled: false, userId: ENTERPRISE_USER_ID, }, - }) - const projectMemberItemList: ProjectMemberItem[] = projectList + }); + const projectMemberItemList: ProjectMemberItem[] = projectList; const memberList = await this.projectMemberService.getByUserId(userId); @@ -113,101 +115,100 @@ export class ProjectService extends BaseService { projectMemberItemList.forEach(item => { if (item.adminId === userId) { - item.permission = 'admin'; - item.status = 'approved'; - item.memberId = userId + item.permission = "admin"; + item.status = "approved"; + item.memberId = userId; } else { - const memberItem: any = memberMap[item.id] + const memberItem: any = memberMap[item.id]; if (memberItem) { item.permission = memberItem.permission; item.status = memberItem.status; - item.memberId = memberItem.userId + item.memberId = memberItem.userId; } } - }) - return projectMemberItemList + }); + return projectMemberItemList; } - async getDetail(projectId: number, userId?: number): Promise { const project: any = await this.info(projectId); if (!project) { - throw new Error('项目不存在'); + throw new Error("项目不存在"); } if (project.adminId === userId) { - project.permission = 'admin'; - project.status = 'approved'; - project.memberId = userId + project.permission = "admin"; + project.status = "approved"; + project.memberId = userId; } else { const member = await this.projectMemberService.getMember(projectId, userId); if (member) { project.permission = member.permission; project.status = member.status; - project.memberId = member.userId + project.memberId = member.userId; } } - return project + return project; } - async checkAdminPermission({ userId, projectId }: { userId: number, projectId: number }) { + async checkAdminPermission({ userId, projectId }: { userId: number; projectId: number }) { return await this.checkPermission({ userId, projectId, - permission: 'admin', - }) + permission: "admin", + }); } - async checkWritePermission({ userId, projectId }: { userId: number, projectId: number }) { + async checkWritePermission({ userId, projectId }: { userId: number; projectId: number }) { return await this.checkPermission({ userId, projectId, - permission: 'write', - }) + permission: "write", + }); } - async checkReadPermission({ userId, projectId }: { userId: number, projectId: number }) { + async checkReadPermission({ userId, projectId }: { userId: number; projectId: number }) { return await this.checkPermission({ userId, projectId, - permission: 'read', - }) + permission: "read", + }); } - async checkPermission({ userId, projectId, permission }: { userId: number, projectId: number, permission: string }) { - if (permission !== 'admin' && permission !== 'write' && permission !== 'read') { - throw new Error('权限类型错误'); + async checkPermission({ userId, projectId, permission }: { userId: number; projectId: number; permission: string }) { + if (permission !== "admin" && permission !== "write" && permission !== "read") { + throw new Error("权限类型错误"); } if (!userId) { - throw new Error('用户ID不能为空'); + throw new Error("用户ID不能为空"); } if (!projectId) { - throw new Error('项目ID不能为空'); + throw new Error("项目ID不能为空"); } if (userId === ENTERPRISE_USER_ID) { - return true + return true; } - const cacheKey = `projectPermission:${projectId}:${userId}` + const cacheKey = `projectPermission:${projectId}:${userId}`; let savedPermission = projectCache.get(cacheKey); if (!savedPermission) { const project = await this.findOne({ - select: ['id', 'userId', 'adminId', 'disabled'], + select: ["id", "userId", "adminId", "disabled"], where: { id: projectId, }, }); if (!project) { - throw new Error('项目不存在'); + throw new Error("项目不存在"); } if (project.adminId === userId) { //创建者拥有管理权限 - savedPermission = 'admin'; + savedPermission = "admin"; } else { if (project.disabled) { - throw new Error('项目已禁用'); + throw new Error("项目已禁用"); } const member = await this.projectMemberService.getMember(projectId, userId); - if (!member || member.status !== 'approved') { + if (!member || member.status !== "approved") { throw new Error(`用户${userId}还不是项目${projectId}的成员`); } savedPermission = member.permission; @@ -218,12 +219,12 @@ export class ProjectService extends BaseService { throw new Error(`权限不足,需要${permission}权限`); } - if (permission === 'read') { - return true + if (permission === "read") { + return true; } - if (permission === 'write') { - if (savedPermission === 'admin' || savedPermission === 'write') { - return true + if (permission === "write") { + if (savedPermission === "admin" || savedPermission === "write") { + return true; } else { throw new Error(`权限不足,需要${permission}权限`); } @@ -231,67 +232,65 @@ export class ProjectService extends BaseService { if (savedPermission !== permission) { throw new Error(`权限不足,需要${permission}权限`); } - return true + return true; } - - async applyJoin({ userId, projectId }: { userId: number, projectId: number }) { + async applyJoin({ userId, projectId }: { userId: number; projectId: number }) { const project = await this.info(projectId); if (!project) { - throw new Error('项目不存在'); + throw new Error("项目不存在"); } if (project.disabled) { - throw new Error('项目已禁用'); + throw new Error("项目已禁用"); } if (project.adminId === userId) { - throw new Error('申请用户已经是该项目的管理员'); + throw new Error("申请用户已经是该项目的管理员"); } const member = await this.projectMemberService.getMember(projectId, userId); - if (member && member.status === 'approved') { - throw new Error('用户已加入项目'); + if (member && member.status === "approved") { + throw new Error("用户已加入项目"); } if (member) { this.projectMemberService.update({ id: member.id, - status: 'pending', - }) + status: "pending", + }); } else { // 加入项目 await this.projectMemberService.add({ userId, projectId, - permission: 'read', - status: 'pending', - }) + permission: "read", + status: "pending", + }); } } - async approveJoin({ userId, projectId, status, permission }: { userId: number, projectId: number, status: string, permission: string }) { + async approveJoin({ userId, projectId, status, permission }: { userId: number; projectId: number; status: string; permission: string }) { const member = await this.projectMemberService.getMember(projectId, userId); if (!member) { - throw new Error('找不到用户的申请记录'); + throw new Error("找不到用户的申请记录"); } await this.projectMemberService.update({ id: member.id, status: status, permission, - }) + }); } - async isAdmin(projectId: number): Promise { + async isAdmin(projectId: number): Promise { const project = await this.info(projectId); return project?.isSystem ?? false; } - async getAllProjectIds() { const projects = await this.repository.find({ - select: ['id'], + select: ["id"], where: { disabled: false, }, - }) + }); return projects.map(item => item.id); } } diff --git a/packages/ui/certd-server/src/modules/sys/enterprise/service/transfer-service.ts b/packages/ui/certd-server/src/modules/sys/enterprise/service/transfer-service.ts index 8a3fbd441..9a071ec4a 100644 --- a/packages/ui/certd-server/src/modules/sys/enterprise/service/transfer-service.ts +++ b/packages/ui/certd-server/src/modules/sys/enterprise/service/transfer-service.ts @@ -7,11 +7,10 @@ export class TransferService { @ApplicationContext() appCtx: IMidwayContainer; - async getServices() { const getService = async (key: string) => { return await this.appCtx.getAsync(key); - } + }; const serviceNames = [ "pipeline", "certInfo", @@ -29,9 +28,9 @@ export class TransferService { "history", "historyLog", "storage", - ] + ]; - const services: any = {} + const services: any = {}; for (const key of serviceNames) { services[key] = await getService(`${key}Service`); } @@ -40,18 +39,17 @@ export class TransferService { /** * 获取用户资源 - * @param userId - * @returns + * @param userId + * @returns */ async getUserResources(userId: number) { - const query = { userId, - } + }; const services = await this.getServices(); - const counts: any = {} + const counts: any = {}; let totalCount = 0; for (const key of Object.keys(services)) { const count = await services[key].repository.count({ where: query }); @@ -59,28 +57,26 @@ export class TransferService { totalCount += count; } - return { ...counts, totalCount, - } + }; } async transferAll(userId: number, projectId: number) { - if (!isEnterprise()) { - throw new Error('当前非企业模式,不支持资源迁移到项目'); + throw new Error("当前非企业模式,不支持资源迁移到项目"); } if (projectId === 0) { - throw new Error('项目ID不能为0'); + throw new Error("项目ID不能为0"); } if (userId == null) { - throw new Error('用户ID不能为空'); + throw new Error("用户ID不能为空"); } const query = { userId, - } + }; const services = await this.getServices(); for (const key of Object.keys(services)) { await services[key].repository.update(query, { @@ -89,5 +85,4 @@ export class TransferService { }); } } - -} \ No newline at end of file +} diff --git a/packages/ui/certd-server/src/modules/sys/nettest/nettest-service.ts b/packages/ui/certd-server/src/modules/sys/nettest/nettest-service.ts index e2a0c887d..b269fff6e 100644 --- a/packages/ui/certd-server/src/modules/sys/nettest/nettest-service.ts +++ b/packages/ui/certd-server/src/modules/sys/nettest/nettest-service.ts @@ -1,5 +1,5 @@ -import { Provide, Scope, ScopeEnum } from '@midwayjs/core'; -import { http, logger, utils } from '@certd/basic'; +import { Provide, Scope, ScopeEnum } from "@midwayjs/core"; +import { http, logger, utils } from "@certd/basic"; // 使用@certd/basic包中已有的utils.sp.spawn函数替代自定义的asyncExec // 该函数已经内置了Windows系统编码问题的解决方案 @@ -9,9 +9,9 @@ export type NetTestResult = { message: string; //结果 testLog: string; //测试日志 error?: string; //执行错误信息 -} +}; -@Provide('nettestService') +@Provide("nettestService") @Scope(ScopeEnum.Request, { allowDowngrade: true }) export class NetTestService { /** @@ -22,7 +22,7 @@ export class NetTestService { */ async telnet(domain: string, port: number): Promise { try { - let command = ''; + let command = ""; if (this.isWindows()) { // Windows系统使用PowerShell执行测试,避免输入重定向问题 @@ -36,25 +36,22 @@ export class NetTestService { // 使用utils.sp.spawn执行命令,它会自动处理Windows编码问题 const output = await utils.sp.spawn({ cmd: command, - logger: undefined // 可以根据需要传入logger + logger: undefined, // 可以根据需要传入logger }); // 判断测试是否成功 - const success = this.isWindows() - ? output.includes('端口连接成功') - : output.includes(' open'); + const success = this.isWindows() ? output.includes("端口连接成功") : output.includes(" open"); // 处理结果 return { success, - message: success ? '端口连接测试成功' : '端口连接测试失败', + message: success ? "端口连接测试成功" : "端口连接测试失败", testLog: output, }; - } catch (error) { return { success: false, - message: 'Telnet测试执行失败', + message: "Telnet测试执行失败", testLog: error.stdout || error.stderr || error?.message || String(error), error: error.stderr || error?.message || String(error), }; @@ -68,7 +65,7 @@ export class NetTestService { */ async ping(domain: string): Promise { try { - let command = ''; + let command = ""; if (this.isWindows()) { // Windows系统ping命令,发送4个包 @@ -81,33 +78,30 @@ export class NetTestService { // 使用utils.sp.spawn执行命令 const output = await utils.sp.spawn({ cmd: command, - logger: undefined + logger: undefined, }); // 判断测试是否成功 - const success = this.isWindows() - ? output.includes('TTL=') - : output.includes('time='); + const success = this.isWindows() ? output.includes("TTL=") : output.includes("time="); return { success, - message: success ? 'Ping测试成功' : 'Ping测试失败', + message: success ? "Ping测试成功" : "Ping测试失败", testLog: output, }; - } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); return { success: false, - message: 'Ping测试执行失败', - testLog: error.stderr|| error.stdout || errorMessage, - error: errorMessage + message: "Ping测试执行失败", + testLog: error.stderr || error.stdout || errorMessage, + error: errorMessage, }; } } private isWindows() { - return process.platform === 'win32'; + return process.platform === "win32"; } /** @@ -117,7 +111,7 @@ export class NetTestService { */ async domainResolve(domain: string): Promise { try { - let command = ''; + let command = ""; if (this.isWindows()) { // Windows系统使用nslookup命令 command = `nslookup ${domain}`; @@ -129,39 +123,37 @@ export class NetTestService { // 使用utils.sp.spawn执行命令 const output = await utils.sp.spawn({ cmd: command, - logger: undefined + logger: undefined, }); // 判断测试是否成功 - const success = output.includes('Address:') || output.includes('IN A') || output.includes('IN AAAA') || - (this.isWindows() && output.includes('Name:')); + const success = output.includes("Address:") || output.includes("IN A") || output.includes("IN AAAA") || (this.isWindows() && output.includes("Name:")); return { success, - message: success ? '域名解析测试成功' : '域名解析测试失败', + message: success ? "域名解析测试成功" : "域名解析测试失败", testLog: output, }; } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); return { success: false, - message: '域名解析测试执行失败', - testLog: error.stdoout || error.stderr || errorMessage, - error: errorMessage + message: "域名解析测试执行失败", + testLog: error.stdoout || error.stderr || errorMessage, + error: errorMessage, }; } } - async getLocalIP(): Promise { try { const output = await utils.sp.spawn({ - cmd: 'ip a | grep \'inet \' | grep -v \'127.0.0.1\' | awk \'{print $2}\' | cut -d/ -f1', - logger: undefined + cmd: "ip a | grep 'inet ' | grep -v '127.0.0.1' | awk '{print $2}' | cut -d/ -f1", + logger: undefined, }); // 去除 inet 前缀 - let ips = output.trim().replace(/inet /g, ''); - return ips.split('\n').filter(ip => ip.length > 0); + const ips = output.trim().replace(/inet /g, ""); + return ips.split("\n").filter(ip => ip.length > 0); } catch (error) { return [error instanceof Error ? error.message : String(error)]; } @@ -170,12 +162,12 @@ export class NetTestService { async getPublicIP(): Promise { try { const res = await http.request({ - url:"https://ipinfo.io/ip", - method:"GET", - }) - return[res] + url: "https://ipinfo.io/ip", + method: "GET", + }); + return [res]; } catch (error) { - return [error instanceof Error ? error.message : String(error)] + return [error instanceof Error ? error.message : String(error)]; } } @@ -183,30 +175,30 @@ export class NetTestService { let dnsServers: string[] = []; try { const output = await utils.sp.spawn({ - cmd: 'cat /etc/resolv.conf | grep nameserver | awk \'{print $2}\'', - logger: undefined + cmd: "cat /etc/resolv.conf | grep nameserver | awk '{print $2}'", + logger: undefined, }); - dnsServers = output.trim().split('\n'); + dnsServers = output.trim().split("\n"); } catch (error) { dnsServers = [error instanceof Error ? error.message : String(error)]; } - try{ + try { /** * /app # cat /etc/resolv.conf | grep "ExtServers" # ExtServers: [223.5.5.5 223.6.6.6] */ const extDnsServers = await utils.sp.spawn({ cmd: 'cat /etc/resolv.conf | grep "ExtServers"', - logger: undefined + logger: undefined, }); - const line = extDnsServers.trim() - if (line.includes('ExtServers') && line.includes('[')) { - const extDns = line.substring(line.indexOf('[') + 1, line.indexOf(']')).split(' '); - const dnsList = extDns.map(item=>`Ext:${item}`) - dnsServers = dnsServers.concat(dnsList); + const line = extDnsServers.trim(); + if (line.includes("ExtServers") && line.includes("[")) { + const extDns = line.substring(line.indexOf("[") + 1, line.indexOf("]")).split(" "); + const dnsList = extDns.map(item => `Ext:${item}`); + dnsServers = dnsServers.concat(dnsList); } } catch (error) { - logger.error('获取DNS ExtServers 服务器失败', error); + logger.error("获取DNS ExtServers 服务器失败", error); // dnsServers.push(error instanceof Error ? error.message : String(error)); } return dnsServers; @@ -216,16 +208,15 @@ export class NetTestService { * @returns 服务器信息 */ async serverInfo(): Promise { - const res = { - localIP: [], - publicIP: [], + localIP: [], + publicIP: [], dnsServers: [], - } + }; res.localIP = await this.getLocalIP(); res.publicIP = await this.getPublicIP(); res.dnsServers = await this.getDNSservers(); - return res + return res; } } diff --git a/packages/ui/certd-server/src/modules/sys/settings/fix.ts b/packages/ui/certd-server/src/modules/sys/settings/fix.ts index 37886464e..8fd5654aa 100644 --- a/packages/ui/certd-server/src/modules/sys/settings/fix.ts +++ b/packages/ui/certd-server/src/modules/sys/settings/fix.ts @@ -1,12 +1,12 @@ -import { SysEmailConf, SysSettingsService } from '@certd/lib-server'; -import * as _ from 'lodash-es'; -import { UserSettingsService } from '../../mine/service/user-settings-service.js'; +import { SysEmailConf, SysSettingsService } from "@certd/lib-server"; +import * as _ from "lodash-es"; +import { UserSettingsService } from "../../mine/service/user-settings-service.js"; export async function getEmailSettings(sysSettingService: SysSettingsService, userSettingsService: UserSettingsService): Promise { let conf = await sysSettingService.getSetting(SysEmailConf); if (!conf.host || conf.usePlus == null) { //到userSetting里面去找 - const adminEmailSetting = await userSettingsService.getByKey('email', 1,null); + const adminEmailSetting = await userSettingsService.getByKey("email", 1, null); if (adminEmailSetting) { const setting = JSON.parse(adminEmailSetting.setting); conf = _.merge(conf, setting); diff --git a/packages/ui/certd-server/src/modules/sys/settings/safe-service.ts b/packages/ui/certd-server/src/modules/sys/settings/safe-service.ts index f04ff7b57..65ee6d749 100644 --- a/packages/ui/certd-server/src/modules/sys/settings/safe-service.ts +++ b/packages/ui/certd-server/src/modules/sys/settings/safe-service.ts @@ -1,23 +1,20 @@ -import {Inject, Provide, Scope, ScopeEnum} from '@midwayjs/core'; -import {SiteHidden, SysSafeSetting, SysSettingsService} from "@certd/lib-server"; +import { Inject, Provide, Scope, ScopeEnum } from "@midwayjs/core"; +import { SiteHidden, SysSafeSetting, SysSettingsService } from "@certd/lib-server"; import fs from "fs"; -import {logger, utils} from "@certd/basic"; -import {cloneDeep, merge} from "lodash-es"; - +import { logger, utils } from "@certd/basic"; +import { cloneDeep, merge } from "lodash-es"; export class HiddenStatus { - - isHidden = false; lastRequestTime = 0; intervalId: any = null; hasUnHiddenFile() { if (fs.existsSync(`./data/.unhidden`)) { - fs.unlinkSync(`./data/.unhidden`) - return true + fs.unlinkSync(`./data/.unhidden`); + return true; } - return false + return false; } updateRequestTime() { @@ -25,37 +22,33 @@ export class HiddenStatus { } startCheck(autoHiddenTimes = 5) { - this.stopCheck() + this.stopCheck(); this.intervalId = setInterval(() => { //默认5分钟后自动隐藏 if (!this.isHidden && Date.now() - this.lastRequestTime > 1000 * 60 * autoHiddenTimes) { this.isHidden = true; } - }, 1000 * 60) + }, 1000 * 60); } stopCheck() { if (this.intervalId) { - clearInterval(this.intervalId) - this.intervalId = null + clearInterval(this.intervalId); + this.intervalId = null; } } - } export const hiddenStatus = new HiddenStatus(); - -@Provide('safeService') -@Scope(ScopeEnum.Request, {allowDowngrade: true}) +@Provide("safeService") +@Scope(ScopeEnum.Request, { allowDowngrade: true }) export class SafeService { - @Inject() sysSettingsService: SysSettingsService; - async reloadHiddenStatus(immediate = false) { - const hidden = await this.getHiddenSetting() + const hidden = await this.getHiddenSetting(); if (hidden.enabled) { logger.info("启动站点隐藏"); hiddenStatus.isHidden = immediate; @@ -64,44 +57,41 @@ export class SafeService { } else { logger.info("当前站点隐藏已关闭"); hiddenStatus.isHidden = false; - hiddenStatus.stopCheck() + hiddenStatus.stopCheck(); } } - async getHiddenSetting(): Promise { - const safeSetting = await this.getSafeSetting() - return safeSetting.hidden || {enabled: false} + const safeSetting = await this.getSafeSetting(); + return safeSetting.hidden || { enabled: false }; } async getSafeSetting() { - return await this.sysSettingsService.getSetting(SysSafeSetting) + return await this.sysSettingsService.getSetting(SysSafeSetting); } async hiddenImmediately() { - return hiddenStatus.isHidden = true + return (hiddenStatus.isHidden = true); } async saveSafeSetting(body: SysSafeSetting) { - // 更新hidden配置 if (body.hidden.openPassword) { body.hidden.openPassword = utils.hash.md5(body.hidden.openPassword); } - const blankSetting = new SysSafeSetting() - const setting = await this.getSafeSetting() + const blankSetting = new SysSafeSetting(); + const setting = await this.getSafeSetting(); const newSetting = merge(blankSetting, cloneDeep(setting), body); if (newSetting.hidden?.enabled && !newSetting.hidden?.openPassword) { - throw new Error("首次设置需要填写解锁密码") + throw new Error("首次设置需要填写解锁密码"); } - if(isNaN(newSetting.hidden.autoHiddenTimes) || newSetting.hidden.autoHiddenTimes < 1){ - newSetting.hidden.autoHiddenTimes = 1 + if (isNaN(newSetting.hidden.autoHiddenTimes) || newSetting.hidden.autoHiddenTimes < 1) { + newSetting.hidden.autoHiddenTimes = 1; } await this.sysSettingsService.saveSetting(newSetting); - await this.reloadHiddenStatus(false) - + await this.reloadHiddenStatus(false); } } diff --git a/packages/ui/certd-server/src/plugins/plugin-51dns/access.ts b/packages/ui/certd-server/src/plugins/plugin-51dns/access.ts index 73a568b22..842eadb7e 100644 --- a/packages/ui/certd-server/src/plugins/plugin-51dns/access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-51dns/access.ts @@ -1,54 +1,53 @@ -import { IsAccess, AccessInput, BaseAccess } from '@certd/pipeline'; -import { Dns51Client } from './client.js'; +import { IsAccess, AccessInput, BaseAccess } from "@certd/pipeline"; +import { Dns51Client } from "./client.js"; /** * 这个注解将注册一个授权配置 * 在certd的后台管理系统中,用户可以选择添加此类型的授权 */ @IsAccess({ - name: '51dns', - title: '51dns授权', - icon: 'arcticons:dns-changer-3', - desc: '', + name: "51dns", + title: "51dns授权", + icon: "arcticons:dns-changer-3", + desc: "", }) export class Dns51Access extends BaseAccess { /** * 授权属性配置 */ @AccessInput({ - title: '用户名', + title: "用户名", component: { - placeholder: '用户名或手机号', + placeholder: "用户名或手机号", }, required: true, encrypt: false, }) - username = ''; + username = ""; @AccessInput({ - title: '登录密码', + title: "登录密码", component: { name: "a-input-password", vModel: "value", - placeholder: '密码', + placeholder: "密码", }, required: true, encrypt: true, }) - password = ''; + password = ""; @AccessInput({ title: "测试", component: { name: "api-test", - action: "TestRequest" + action: "TestRequest", }, - helper: "测试授权是否正确" + helper: "测试授权是否正确", }) testRequest = true; async onTestRequest() { - const client = new Dns51Client({ logger: this.ctx.logger, access: this, @@ -58,8 +57,6 @@ export class Dns51Access extends BaseAccess { return "ok"; } - - } new Dns51Access(); diff --git a/packages/ui/certd-server/src/plugins/plugin-51dns/client.ts b/packages/ui/certd-server/src/plugins/plugin-51dns/client.ts index 2eaca4b09..7944a210c 100644 --- a/packages/ui/certd-server/src/plugins/plugin-51dns/client.ts +++ b/packages/ui/certd-server/src/plugins/plugin-51dns/client.ts @@ -12,42 +12,35 @@ export class Dns51Client { _token = ""; _cookie = ""; - constructor(options: { - logger: ILogger; - access: Dns51Access; - }) { + constructor(options: { logger: ILogger; access: Dns51Access }) { this.logger = options.logger; this.access = options.access; this.http = createAxiosService({ - logger: this.logger + logger: this.logger, }); - } - aes(val: string) { if (!this.cryptoJs) { throw new Error("crypto-js not init"); } const CryptoJS = this.cryptoJs; - var k = CryptoJS.enc.Utf8.parse("1234567890abcDEF"); - var iv = CryptoJS.enc.Utf8.parse("1234567890abcDEF"); + const k = CryptoJS.enc.Utf8.parse("1234567890abcDEF"); + const iv = CryptoJS.enc.Utf8.parse("1234567890abcDEF"); return CryptoJS.AES.encrypt(val, k, { iv: iv, mode: CryptoJS.mode.CBC, - padding: CryptoJS.pad.ZeroPadding + padding: CryptoJS.pad.ZeroPadding, }).toString(); } - async init() { if (this.cryptoJs) { return; } const CryptoJSModule = await import("crypto-js"); this.cryptoJs = CryptoJSModule.default; - } async login() { @@ -63,77 +56,79 @@ export class Dns51Client { returnOriginRes: true, headers: { // 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.95 Safari/537.36', - 'Origin': 'https://www.51dns.com', - 'Referer': 'https://www.51dns.com', + Origin: "https://www.51dns.com", + Referer: "https://www.51dns.com", }, }); - let setCookie = res.headers['set-cookie'] - let cookie = setCookie.map((item: any) => { - return item.split(';')[0] - }).join(';') - + let setCookie = res.headers["set-cookie"]; + const cookie = setCookie + .map((item: any) => { + return item.split(";")[0]; + }) + .join(";"); //提取 var csrfToken = "ieOfM21eDd9nWJv3OZtMJF6ogDsnPKQHJ17dlMck"; const _token = res.data.match(/var csrfToken = "(.*?)"/)[1]; this.logger.info("_token:", _token); this._token = _token; - var obj = { - "email_or_phone": this.aes(this.access.username), - "password": this.aes(this.access.password), - "type": this.aes("account"), - "redirectTo": "https://www.51dns.com/domain", - "_token": _token + const obj = { + email_or_phone: this.aes(this.access.username), + password: this.aes(this.access.password), + type: this.aes("account"), + redirectTo: "https://www.51dns.com/domain", + _token: _token, }; const res2 = await this.http.request({ url: "https://www.51dns.com/login", method: "post", data: { - ...obj + ...obj, }, withCredentials: true, logRes: false, returnOriginRes: true, headers: { - 'Origin': 'https://www.51dns.com', - 'Referer': 'https://www.51dns.com', - 'Content-Type': 'application/x-www-form-urlencoded', - 'Cookie': cookie, - 'X-Requested-With': 'XMLHttpRequest' - } + Origin: "https://www.51dns.com", + Referer: "https://www.51dns.com", + "Content-Type": "application/x-www-form-urlencoded", + Cookie: cookie, + "X-Requested-With": "XMLHttpRequest", + }, }); - this.logger.info("return headers:", JSON.stringify(res2.headers)) + this.logger.info("return headers:", JSON.stringify(res2.headers)); if (res2.data.code == 0) { - setCookie = res2.headers['set-cookie'] - this._cookie = setCookie.map((item: any) => { - return item.split(';')[0] - }).join(';') - this.logger.info("cookie:", this._cookie) - this.logger.info("登录成功") + setCookie = res2.headers["set-cookie"]; + this._cookie = setCookie + .map((item: any) => { + return item.split(";")[0]; + }) + .join(";"); + this.logger.info("cookie:", this._cookie); + this.logger.info("登录成功"); } else { - throw new Error("登录失败:", res2.data) + throw new Error("登录失败:", res2.data); } - const res3 = await this.http.request({ - url: 'https://www.51dns.com/domain', - method: 'get', + url: "https://www.51dns.com/domain", + method: "get", withCredentials: true, logRes: false, returnOriginRes: true, headers: { // 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.95 Safari/537.36', - 'Origin': 'https://www.51dns.com', - 'Referer': 'https://www.51dns.com/login.html', - 'Cookie': this._cookie, - } - }) + Origin: "https://www.51dns.com", + Referer: "https://www.51dns.com/login.html", + Cookie: this._cookie, + }, + }); - const success2 = res3.data.includes('DNS解析') + const success2 = res3.data.includes('DNS解析'); if (!success2) { - throw new Error("检查登录失败") + throw new Error("检查登录失败"); } - this.logger.info("检查登录成功") + this.logger.info("检查登录成功"); this.isLogined = true; } @@ -147,7 +142,7 @@ export class Dns51Client { withCredentials: true, logRes: false, returnOriginRes: true, - headers: this.getRequestHeaders() + headers: this.getRequestHeaders(), }); // 提取 > { - if (req.pageNo >=2) { //不知道翻页查询的参数是什么 + if (req.pageNo >= 2) { + //不知道翻页查询的参数是什么 return { total: 0, - list: [] - } + list: [], + }; } await this.login(); const query = { - //domain=&id=&status=&perPage=500 - perPage: 1000, - } + //domain=&id=&status=&perPage=500 + perPage: 1000, + }; const res = await this.http.request({ - url: 'https://www.51dns.com/domain?' + qs.stringify(query), - method: 'get', + url: "https://www.51dns.com/domain?" + qs.stringify(query), + method: "get", withCredentials: true, logRes: false, returnOriginRes: true, - headers: this.getRequestHeaders() + headers: this.getRequestHeaders(), }); //提取记录 - const content = res.data || "" - const startIndex = content.indexOf(``) + const content = res.data || ""; + const startIndex = content.indexOf(`
`); if (startIndex < 0) { - throw new Error("解析域名列表失败,未找到域名列表") + throw new Error("解析域名列表失败,未找到域名列表"); } - const endIndex = content.indexOf(`
`, startIndex) - const tableContent = content.substring(startIndex, endIndex + 8) + const endIndex = content.indexOf(``, startIndex); + const tableContent = content.substring(startIndex, endIndex + 8); // //
docmirror.cn - const list: DomainRecord[] = [] - const trArr = tableContent.split(``) + const list: DomainRecord[] = []; + const trArr = tableContent.split(``); for (const tr of trArr) { - const lines = tr.trim().split("\n") - const row:any = {} + const lines = tr.trim().split("\n"); + const row: any = {}; for (const line of lines) { if (line.includes(` { access!: Dns51Access; - client!:Dns51Client; + client!: Dns51Client; async onInstance() { //一些初始化的操作 // 也可以通过ctx成员变量传递context @@ -43,30 +43,26 @@ export class Dns51DnsProvider extends AbstractDnsProvider { * type: 'TXT', * domain: 'example.com' */ - const { fullRecord,hostRecord, value, type, domain } = options; - this.logger.info('添加域名解析:', fullRecord, value, type, domain); - - - + const { fullRecord, hostRecord, value, type, domain } = options; + this.logger.info("添加域名解析:", fullRecord, value, type, domain); const domainId = await this.client.getDomainId(domain); - this.logger.info('获取domainId成功:', domainId); + this.logger.info("获取domainId成功:", domainId); const res = await this.client.createRecord({ domain: domain, domainId: domainId, - type: 'TXT', + type: "TXT", host: hostRecord, data: value, ttl: 300, - }) + }); return { id: res.id, domainId: domainId, }; } - /** * 删除dns解析记录,清理申请痕迹 * @param options @@ -74,9 +70,9 @@ export class Dns51DnsProvider extends AbstractDnsProvider { async removeRecord(options: RemoveRecordOptions): Promise { const { fullRecord, value } = options.recordReq; const record = options.recordRes; - this.logger.info('删除域名解析:', fullRecord, value); + this.logger.info("删除域名解析:", fullRecord, value); if (!record) { - this.logger.info('record为空,不执行删除'); + this.logger.info("record为空,不执行删除"); return; } //这里调用删除txt dns解析记录接口 @@ -86,16 +82,16 @@ export class Dns51DnsProvider extends AbstractDnsProvider { * Authorization: Basic {token} * 请求参数 */ - const {id,domainId} = record + const { id, domainId } = record; await this.client.deleteRecord({ id, - domainId - }) + domainId, + }); this.logger.info(`删除域名解析成功:fullRecord=${fullRecord},id=${id}`); } async getDomainListPage(req: PageSearch): Promise> { - return await this.client.getDomainListPage(req) + return await this.client.getDomainListPage(req); } } diff --git a/packages/ui/certd-server/src/plugins/plugin-51dns/index.ts b/packages/ui/certd-server/src/plugins/plugin-51dns/index.ts index 3a9e17436..e73296290 100644 --- a/packages/ui/certd-server/src/plugins/plugin-51dns/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-51dns/index.ts @@ -1,3 +1,3 @@ -export * from './dns-provider.js'; -export * from './access.js'; -export * from './client.js'; +export * from "./dns-provider.js"; +export * from "./access.js"; +export * from "./client.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-acepanel/access.ts b/packages/ui/certd-server/src/plugins/plugin-acepanel/access.ts index 8ba8db3c5..d9ebc36a1 100644 --- a/packages/ui/certd-server/src/plugins/plugin-acepanel/access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-acepanel/access.ts @@ -1,10 +1,8 @@ -import {AccessInput, BaseAccess, IsAccess, Pager, PageSearch} from "@certd/pipeline"; -import {HttpRequestConfig} from "@certd/basic"; +import { AccessInput, BaseAccess, IsAccess, Pager, PageSearch } from "@certd/pipeline"; +import { HttpRequestConfig } from "@certd/basic"; import crypto from "crypto"; import url from "url"; - - /** * AcePanel授权 */ @@ -12,22 +10,21 @@ import url from "url"; name: "acepanel", title: "AcePanel授权", desc: "", - icon: "svg:icon-lucky" + icon: "svg:icon-lucky", }) export class AcePanelAccess extends BaseAccess { - @AccessInput({ title: "AcePanel管理地址", component: { placeholder: "http://127.0.0.1:25475/entrance", }, - helper:"请输入AcePanel管理地址,格式为http://127.0.0.1:25475/entrance, 要带安全入口,最后面不要加/", + helper: "请输入AcePanel管理地址,格式为http://127.0.0.1:25475/entrance, 要带安全入口,最后面不要加/", required: true, }) - endpoint = ''; + endpoint = ""; @AccessInput({ - title: '访问令牌ID', + title: "访问令牌ID", component: { name: "a-input-number", vModel: "value", @@ -35,20 +32,20 @@ export class AcePanelAccess extends BaseAccess { helper: "AcePanel控制台->设置->用户->访问令牌->创建访问令牌", required: true, }) - tokenId :number; + tokenId: number; @AccessInput({ - title: '访问令牌', + title: "访问令牌", component: { - placeholder: 'AccessToken', + placeholder: "AccessToken", }, helper: "创建访问令牌后复制该令牌填到这里", required: true, encrypt: true, }) - accessToken = ''; + accessToken = ""; - @AccessInput({ + @AccessInput({ title: "忽略证书校验", value: true, component: { @@ -63,37 +60,38 @@ export class AcePanelAccess extends BaseAccess { title: "测试", component: { name: "api-test", - action: "TestRequest" + action: "TestRequest", }, - helper: "点击测试接口是否正常" + helper: "点击测试接口是否正常", }) testRequest = true; async onTestRequest() { await this.testApi(); - return "ok" + return "ok"; } + /** + * 计算字符串的SHA256哈希值 + */ + sha256Hash(text: string) { + return crypto + .createHash("sha256") + .update(text || "") + .digest("hex"); + } + /** + * 使用HMAC-SHA256算法计算签名 + */ + hmacSha256(key: string, message: string) { + return crypto.createHmac("sha256", key).update(message).digest("hex"); + } -/** - * 计算字符串的SHA256哈希值 - */ - sha256Hash(text: string) { - return crypto.createHash('sha256').update(text || '').digest('hex'); -} - -/** - * 使用HMAC-SHA256算法计算签名 - */ - hmacSha256(key: string, message: string) { - return crypto.createHmac('sha256', key).update(message).digest('hex'); -} - -/** - * 为API请求生成签名 - */ - signRequest(method: string, apiUrl: string, body: string, id: number, token: string) { + /** + * 为API请求生成签名 + */ + signRequest(method: string, apiUrl: string, body: string, id: number, token: string) { // 解析URL const parsedUrl = new url.URL(apiUrl); const path = parsedUrl.pathname; @@ -101,61 +99,50 @@ export class AcePanelAccess extends BaseAccess { // 规范化路径 let canonicalPath = path; - if (!path.startsWith('/api')) { - const apiPos = path.indexOf('/api'); - if (apiPos !== -1) { - canonicalPath = path.slice(apiPos); - } + if (!path.startsWith("/api")) { + const apiPos = path.indexOf("/api"); + if (apiPos !== -1) { + canonicalPath = path.slice(apiPos); + } } // 构造规范化请求 - const canonicalRequest = [ - method, - canonicalPath, - query, - this.sha256Hash(body || '') - ].join('\n'); + const canonicalRequest = [method, canonicalPath, query, this.sha256Hash(body || "")].join("\n"); // 获取当前时间戳 const timestamp = Math.floor(Date.now() / 1000); // 构造待签名字符串 - const stringToSign = [ - 'HMAC-SHA256', - timestamp, - this.sha256Hash(canonicalRequest) - ].join('\n'); + const stringToSign = ["HMAC-SHA256", timestamp, this.sha256Hash(canonicalRequest)].join("\n"); // 计算签名 const signature = this.hmacSha256(token, stringToSign); return { - timestamp, - signature, - id + timestamp, + signature, + id, }; -} - + } async doRequest(req: HttpRequestConfig) { - let endpoint = this.endpoint - if (endpoint.endsWith('/')) { + let endpoint = this.endpoint; + if (endpoint.endsWith("/")) { endpoint = endpoint.slice(0, -1); } const fullUrl = endpoint + req.url; - - const method = req.method || 'GET'; - const body = req.data ? JSON.stringify(req.data) : ''; + const method = req.method || "GET"; + const body = req.data ? JSON.stringify(req.data) : ""; const token = this.accessToken; const tokenId = this.tokenId; const signingData = this.signRequest(method, fullUrl, body, tokenId, token); // 准备HTTP请求头 const headers = { - 'Content-Type': 'application/json', - 'X-Timestamp': signingData.timestamp, - 'Authorization': `HMAC-SHA256 Credential=${signingData.id}, Signature=${signingData.signature}` + "Content-Type": "application/json", + "X-Timestamp": signingData.timestamp, + Authorization: `HMAC-SHA256 Credential=${signingData.id}, Signature=${signingData.signature}`, }; // 发送请求 @@ -170,17 +157,15 @@ export class AcePanelAccess extends BaseAccess { }); return res; - } async testApi() { - await this.getWebSiteList({ pageNo: 1, pageSize: 1, - }) + }); - return "ok" + return "ok"; } async getWebSiteList(opts: PageSearch) { @@ -198,8 +183,8 @@ export class AcePanelAccess extends BaseAccess { method: "POST", data: { cert, - key - } + key, + }, }; return await this.doRequest(req); } @@ -210,14 +195,13 @@ export class AcePanelAccess extends BaseAccess { method: "POST", data: { id: certId, - website_id: websiteId - } + website_id: websiteId, + }, }; return await this.doRequest(req); } async updatePanelCert(cert: string, key: string) { - const oldSettingRes = await this.doRequest({ url: "/api/setting", method: "GET", @@ -232,12 +216,11 @@ export class AcePanelAccess extends BaseAccess { acme: false, https: true, cert, - key - } + key, + }, }; return await this.doRequest(req); } - } new AcePanelAccess(); diff --git a/packages/ui/certd-server/src/plugins/plugin-acepanel/index.ts b/packages/ui/certd-server/src/plugins/plugin-acepanel/index.ts index 68f7e466c..02dc3945d 100644 --- a/packages/ui/certd-server/src/plugins/plugin-acepanel/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-acepanel/index.ts @@ -1,2 +1,2 @@ export * from "./plugins/index.js"; -export * from "./access.js"; \ No newline at end of file +export * from "./access.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-acepanel/plugins/index.ts b/packages/ui/certd-server/src/plugins/plugin-acepanel/plugins/index.ts index 244eff2bf..1004f7b5a 100644 --- a/packages/ui/certd-server/src/plugins/plugin-acepanel/plugins/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-acepanel/plugins/index.ts @@ -1,3 +1,2 @@ export * from "./plugin-deploy-to-website.js"; export * from "./plugin-panel-cert.js"; - diff --git a/packages/ui/certd-server/src/plugins/plugin-acepanel/plugins/plugin-deploy-to-website.ts b/packages/ui/certd-server/src/plugins/plugin-acepanel/plugins/plugin-deploy-to-website.ts index 74d697b64..48d62e084 100644 --- a/packages/ui/certd-server/src/plugins/plugin-acepanel/plugins/plugin-deploy-to-website.ts +++ b/packages/ui/certd-server/src/plugins/plugin-acepanel/plugins/plugin-deploy-to-website.ts @@ -13,19 +13,18 @@ import { AcePanelAccess } from "../access.js"; needPlus: true, default: { strategy: { - runStrategy: RunStrategy.SkipWhenSucceed - } - } + runStrategy: RunStrategy.SkipWhenSucceed, + }, + }, }) - export class AcePanelDeployToWebsite extends AbstractPlusTaskPlugin { @TaskInput({ title: "域名证书", helper: "请选择前置任务输出的域名证书", component: { name: "output-selector", - from: [...CertApplyPluginNames] - } + from: [...CertApplyPluginNames], + }, }) cert!: CertInfo; @@ -36,9 +35,9 @@ export class AcePanelDeployToWebsite extends AbstractPlusTaskPlugin { title: "ACEPanel授权", component: { name: "access-selector", - type: "acepanel" + type: "acepanel", }, - required: true + required: true, }) accessId!: string; @@ -48,13 +47,12 @@ export class AcePanelDeployToWebsite extends AbstractPlusTaskPlugin { helper: "选择需要部署证书的网站", action: AcePanelDeployToWebsite.prototype.onGetWebsiteList.name, pager: false, - search: false + search: false, }) ) websiteList!: number[]; - async onInstance() { - } + async onInstance() {} async onGetWebsiteList(data: PageSearch = {}) { const access = await this.getAccess(this.accessId); @@ -65,9 +63,9 @@ export class AcePanelDeployToWebsite extends AbstractPlusTaskPlugin { } const options = items.map((item: any) => { return { - label: `${item.name} (${item.domains.join(', ')})`, + label: `${item.name} (${item.domains.join(", ")})`, value: item.id, - domain: item.domains + domain: item.domains, }; }); return { @@ -83,7 +81,7 @@ export class AcePanelDeployToWebsite extends AbstractPlusTaskPlugin { const result = await access.uploadCert(this.cert.crt, this.cert.key); const certId = result.data.id; this.logger.info(`证书上传成功,证书ID:${certId}`); - this.logger.info(`证书域名:${result.data.domains.join(', ')}`); + this.logger.info(`证书域名:${result.data.domains.join(", ")}`); // 部署证书到选择的网站 if (this.websiteList && this.websiteList.length > 0) { diff --git a/packages/ui/certd-server/src/plugins/plugin-acepanel/plugins/plugin-panel-cert.ts b/packages/ui/certd-server/src/plugins/plugin-acepanel/plugins/plugin-panel-cert.ts index acc1e94ad..8b631ddd7 100644 --- a/packages/ui/certd-server/src/plugins/plugin-acepanel/plugins/plugin-panel-cert.ts +++ b/packages/ui/certd-server/src/plugins/plugin-acepanel/plugins/plugin-panel-cert.ts @@ -1,6 +1,6 @@ -import {IsTaskPlugin, pluginGroups, RunStrategy, TaskInput} from "@certd/pipeline"; -import {CertApplyPluginNames, CertInfo} from "@certd/plugin-cert"; -import {AcePanelAccess} from "../access.js"; +import { IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; +import { CertApplyPluginNames, CertInfo } from "@certd/plugin-cert"; +import { AcePanelAccess } from "../access.js"; import { AbstractPlusTaskPlugin } from "@certd/plugin-plus"; @IsTaskPlugin({ @@ -12,19 +12,18 @@ import { AbstractPlusTaskPlugin } from "@certd/plugin-plus"; needPlus: true, default: { strategy: { - runStrategy: RunStrategy.SkipWhenSucceed - } - } + runStrategy: RunStrategy.SkipWhenSucceed, + }, + }, }) - export class AcePanelPanelCert extends AbstractPlusTaskPlugin { @TaskInput({ title: "域名证书", helper: "请选择前置任务输出的域名证书", component: { name: "output-selector", - from: [...CertApplyPluginNames] - } + from: [...CertApplyPluginNames], + }, }) cert!: CertInfo; @@ -32,14 +31,13 @@ export class AcePanelPanelCert extends AbstractPlusTaskPlugin { title: "ACEPanel授权", component: { name: "access-selector", - type: "acepanel" + type: "acepanel", }, - required: true + required: true, }) accessId!: string; - async onInstance() { - } + async onInstance() {} async execute(): Promise { const access = await this.getAccess(this.accessId); @@ -50,4 +48,4 @@ export class AcePanelPanelCert extends AbstractPlusTaskPlugin { } } -new AcePanelPanelCert(); +new AcePanelPanelCert(); diff --git a/packages/ui/certd-server/src/plugins/plugin-admin/index.ts b/packages/ui/certd-server/src/plugins/plugin-admin/index.ts index 132b274f3..9c1dc5cb4 100644 --- a/packages/ui/certd-server/src/plugins/plugin-admin/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-admin/index.ts @@ -1,4 +1,4 @@ -export * from './plugin-restart.js'; -export * from './plugin-script.js'; -export * from './plugin-db-backup.js'; -export * from './plugin-deploy-to-certd.js'; +export * from "./plugin-restart.js"; +export * from "./plugin-script.js"; +export * from "./plugin-db-backup.js"; +export * from "./plugin-deploy-to-certd.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-admin/plugin-db-backup.ts b/packages/ui/certd-server/src/plugins/plugin-admin/plugin-db-backup.ts index 1499f26c0..44e572f0d 100644 --- a/packages/ui/certd-server/src/plugins/plugin-admin/plugin-db-backup.ts +++ b/packages/ui/certd-server/src/plugins/plugin-admin/plugin-db-backup.ts @@ -5,7 +5,7 @@ import dayjs from "dayjs"; import { AbstractPlusTaskPlugin } from "@certd/plugin-plus"; import JSZip from "jszip"; import * as os from "node:os"; -import { OssClientContext, ossClientFactory, OssClientRemoveByOpts} from "../plugin-lib/oss/index.js"; +import { OssClientContext, ossClientFactory, OssClientRemoveByOpts } from "../plugin-lib/oss/index.js"; import { SshAccess, SshClient } from "../plugin-lib/ssh/index.js"; import { pipeline } from "stream/promises"; const defaultBackupDir = "certd_backup"; diff --git a/packages/ui/certd-server/src/plugins/plugin-admin/plugin-deploy-to-certd.ts b/packages/ui/certd-server/src/plugins/plugin-admin/plugin-deploy-to-certd.ts index 12279bb8d..72c9a5bd6 100644 --- a/packages/ui/certd-server/src/plugins/plugin-admin/plugin-deploy-to-certd.ts +++ b/packages/ui/certd-server/src/plugins/plugin-admin/plugin-deploy-to-certd.ts @@ -1,15 +1,15 @@ -import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from '@certd/pipeline'; -import { httpsServer } from '../../modules/auto/https/server.js'; -import { RestartCertdPlugin } from './plugin-restart.js'; -import path from 'path'; -import fs from 'fs'; -import { CertApplyPluginNames, CertInfo, CertReader } from '@certd/plugin-lib'; +import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; +import { httpsServer } from "../../modules/auto/https/server.js"; +import { RestartCertdPlugin } from "./plugin-restart.js"; +import path from "path"; +import fs from "fs"; +import { CertApplyPluginNames, CertInfo, CertReader } from "@certd/plugin-lib"; @IsTaskPlugin({ - name: 'DeployToCertd', - title: '部署证书到Certd本身', - icon: 'mdi:restart', - desc: '【仅管理员可用】 部署证书到 certd的https服务,用于更新 Certd 的 ssl 证书,建议将此任务放在流水线的最后一步', + name: "DeployToCertd", + title: "部署证书到Certd本身", + icon: "mdi:restart", + desc: "【仅管理员可用】 部署证书到 certd的https服务,用于更新 Certd 的 ssl 证书,建议将此任务放在流水线的最后一步", group: pluginGroups.admin.key, onlyAdmin: true, default: { @@ -19,18 +19,17 @@ import { CertApplyPluginNames, CertInfo, CertReader } from '@certd/plugin-lib'; }, }) export class DeployToCertdPlugin extends AbstractTaskPlugin { - @TaskInput({ - title: '域名证书', - helper: '请选择前置任务输出的域名证书', + title: "域名证书", + helper: "请选择前置任务输出的域名证书", component: { - name: 'output-selector', + name: "output-selector", from: [...CertApplyPluginNames], }, required: true, }) cert!: CertInfo; - async onInstance() { } + async onInstance() {} async execute(): Promise { this.checkAdmin(); @@ -40,15 +39,15 @@ export class DeployToCertdPlugin extends AbstractTaskPlugin { const certReader = new CertReader(this.cert); const dataDir = "./data"; - const handle = async ({ tmpCrtPath, tmpKeyPath, }) => { - this.logger.info('复制到目标路径'); + const handle = async ({ tmpCrtPath, tmpKeyPath }) => { + this.logger.info("复制到目标路径"); if (crtPath) { - crtPath = crtPath.startsWith('/') ? crtPath : path.join(dataDir, crtPath); + crtPath = crtPath.startsWith("/") ? crtPath : path.join(dataDir, crtPath); this.copyFile(tmpCrtPath, crtPath); } if (keyPath) { keyPath = keyPath.trim(); - keyPath = keyPath.startsWith('/') ? keyPath : path.join(dataDir, keyPath); + keyPath = keyPath.startsWith("/") ? keyPath : path.join(dataDir, keyPath); this.copyFile(tmpKeyPath, keyPath); } }; @@ -56,8 +55,7 @@ export class DeployToCertdPlugin extends AbstractTaskPlugin { await certReader.readCertFile({ logger: this.logger, handle }); this.logger.info(`证书已部署到 ${crtPath} 和 ${keyPath}`); - - this.logger.info('Certd https server 将在 30 秒后重启'); + this.logger.info("Certd https server 将在 30 秒后重启"); await this.ctx.utils.sleep(30000); await httpsServer.restart(); } diff --git a/packages/ui/certd-server/src/plugins/plugin-admin/plugin-restart.ts b/packages/ui/certd-server/src/plugins/plugin-admin/plugin-restart.ts index 1a9698daa..affa27bf0 100644 --- a/packages/ui/certd-server/src/plugins/plugin-admin/plugin-restart.ts +++ b/packages/ui/certd-server/src/plugins/plugin-admin/plugin-restart.ts @@ -1,13 +1,13 @@ -import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy } from '@certd/pipeline'; -import { httpsServer } from '../../modules/auto/https/server.js'; +import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy } from "@certd/pipeline"; +import { httpsServer } from "../../modules/auto/https/server.js"; @IsTaskPlugin({ - name: 'RestartCertd', - title: '重启 Certd', - icon: 'mdi:restart', - desc: '【仅管理员可用】 重启 certd的https服务,用于更新 Certd 的 ssl 证书', + name: "RestartCertd", + title: "重启 Certd", + icon: "mdi:restart", + desc: "【仅管理员可用】 重启 certd的https服务,用于更新 Certd 的 ssl 证书", group: pluginGroups.admin.key, - onlyAdmin:true, + onlyAdmin: true, default: { strategy: { runStrategy: RunStrategy.SkipWhenSucceed, @@ -18,7 +18,7 @@ export class RestartCertdPlugin extends AbstractTaskPlugin { async onInstance() {} async execute(): Promise { this.checkAdmin(); - this.logger.info('Certd https server 将在 3 秒后重启'); + this.logger.info("Certd https server 将在 3 秒后重启"); await this.ctx.utils.sleep(3000); await httpsServer.restart(); } diff --git a/packages/ui/certd-server/src/plugins/plugin-admin/plugin-script.ts b/packages/ui/certd-server/src/plugins/plugin-admin/plugin-script.ts index 4a4c00834..b545e0d57 100644 --- a/packages/ui/certd-server/src/plugins/plugin-admin/plugin-script.ts +++ b/packages/ui/certd-server/src/plugins/plugin-admin/plugin-script.ts @@ -1,16 +1,16 @@ -import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput, TaskInstanceContext } from '@certd/pipeline'; -import { CertInfo, CertReader } from '@certd/plugin-cert'; -import { CertApplyPluginNames} from '@certd/plugin-cert'; +import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput, TaskInstanceContext } from "@certd/pipeline"; +import { CertInfo, CertReader } from "@certd/plugin-cert"; +import { CertApplyPluginNames } from "@certd/plugin-cert"; export type CustomScriptContext = { CertReader: typeof CertReader; self: CustomScriptPlugin; } & TaskInstanceContext; @IsTaskPlugin({ - name: 'CustomScript', - title: '自定义js脚本', - icon: 'ri:javascript-line', - desc: '【仅管理员】运行自定义js脚本执行', + name: "CustomScript", + title: "自定义js脚本", + icon: "ri:javascript-line", + desc: "【仅管理员】运行自定义js脚本执行", group: pluginGroups.admin.key, showRunStrategy: true, onlyAdmin: true, @@ -22,23 +22,23 @@ export type CustomScriptContext = { }) export class CustomScriptPlugin extends AbstractTaskPlugin { @TaskInput({ - title: '脚本', - helper: '自定义js脚本,[脚本编写帮助文档](https://certd.docmirror.cn/guide/use/custom-script/)', + title: "脚本", + helper: "自定义js脚本,[脚本编写帮助文档](https://certd.docmirror.cn/guide/use/custom-script/)", component: { - name: 'a-textarea', - vModel: 'value', + name: "a-textarea", + vModel: "value", rows: 10, - style: 'background-color: #000c17;color: #fafafa;', + style: "background-color: #000c17;color: #fafafa;", }, required: true, }) script!: string; @TaskInput({ - title: '域名证书', - helper: '请选择前置任务输出的域名证书', + title: "域名证书", + helper: "请选择前置任务输出的域名证书", component: { - name: 'output-selector', + name: "output-selector", from: [...CertApplyPluginNames], }, required: false, @@ -48,14 +48,14 @@ export class CustomScriptPlugin extends AbstractTaskPlugin { async onInstance() {} async execute(): Promise { this.checkAdmin(); - this.logger.info('执行自定义脚本:\n', this.script); + this.logger.info("执行自定义脚本:\n", this.script); const ctx: CustomScriptContext = { CertReader, self: this, ...this.ctx, }; const AsyncFunction = Object.getPrototypeOf(async () => {}).constructor; - const func = new AsyncFunction('ctx', this.script); + const func = new AsyncFunction("ctx", this.script); return await func(ctx); } } diff --git a/packages/ui/certd-server/src/plugins/plugin-aliyun/dns-provider/aliesa-dns-provider.ts b/packages/ui/certd-server/src/plugins/plugin-aliyun/dns-provider/aliesa-dns-provider.ts index 4043e2c98..74b60ae4c 100644 --- a/packages/ui/certd-server/src/plugins/plugin-aliyun/dns-provider/aliesa-dns-provider.ts +++ b/packages/ui/certd-server/src/plugins/plugin-aliyun/dns-provider/aliesa-dns-provider.ts @@ -1,27 +1,23 @@ -import { PageRes, PageSearch } from '@certd/pipeline'; -import { AbstractDnsProvider, CreateRecordOptions, DomainRecord, IsDnsProvider, RemoveRecordOptions } from '@certd/plugin-cert'; -import { AliesaAccess } from '../../plugin-lib/aliyun/index.js'; -import { AliyunClientV2 } from '../../plugin-lib/aliyun/lib/aliyun-client-v2.js'; - +import { PageRes, PageSearch } from "@certd/pipeline"; +import { AbstractDnsProvider, CreateRecordOptions, DomainRecord, IsDnsProvider, RemoveRecordOptions } from "@certd/plugin-cert"; +import { AliesaAccess } from "../../plugin-lib/aliyun/index.js"; +import { AliyunClientV2 } from "../../plugin-lib/aliyun/lib/aliyun-client-v2.js"; @IsDnsProvider({ - name: 'aliesa', - title: '阿里ESA', - desc: '阿里ESA DNS解析', - accessType: 'aliesa', - icon: 'svg:icon-aliyun', + name: "aliesa", + title: "阿里ESA", + desc: "阿里ESA DNS解析", + accessType: "aliesa", + icon: "svg:icon-aliyun", order: 0, }) export class AliesaDnsProvider extends AbstractDnsProvider { - - - client: AliyunClientV2 + client: AliyunClientV2; async onInstance() { - const access : AliesaAccess = this.ctx.access as AliesaAccess - this.client = await access.getEsaClient() + const access: AliesaAccess = this.ctx.access as AliesaAccess; + this.client = await access.getEsaClient(); } - async getSiteItem(domain: string) { const ret = await this.client.doRequest({ // 接口名称 @@ -39,26 +35,23 @@ export class AliesaDnsProvider extends AbstractDnsProvider { SiteName: domain, // ["SiteSearchType"] = "exact"; SiteSearchType: "exact", - AccessType: "NS" - } - } - }) - const list = ret.Sites + AccessType: "NS", + }, + }, + }); + const list = ret.Sites; if (list?.length === 0) { throw new Error(`阿里云ESA中不存在此域名站点:${domain},请确认域名已添加到ESA中,且为NS接入方式`); } - return list[0] - + return list[0]; } async createRecord(options: CreateRecordOptions): Promise { const { fullRecord, value, type, domain } = options; - this.logger.info('添加域名解析:', fullRecord, value, domain); - - - const siteItem = await this.getSiteItem(domain) - const siteId = siteItem.SiteId + this.logger.info("添加域名解析:", fullRecord, value, domain); + const siteItem = await this.getSiteItem(domain); + const siteId = siteItem.SiteId; const res = await this.client.doRequest({ action: "CreateRecord", @@ -72,16 +65,15 @@ export class AliesaDnsProvider extends AbstractDnsProvider { // queries["Ttl"] = 1231311; Ttl: 100, Data: JSON.stringify({ Value: value }), - } - } - }) + }, + }, + }); - this.logger.info('添加域名解析成功:', fullRecord, value, res.RecordId); + this.logger.info("添加域名解析成功:", fullRecord, value, res.RecordId); return { RecordId: res.RecordId, SiteId: siteId, - } - + }; } async removeRecord(options: RemoveRecordOptions): Promise { @@ -91,16 +83,16 @@ export class AliesaDnsProvider extends AbstractDnsProvider { action: "DeleteRecord", version: "2024-09-10", data: { - query: { - RecordId: record.RecordId, - } - } - }) - this.logger.info('删除域名解析成功:', record.RecordId); + query: { + RecordId: record.RecordId, + }, + }, + }); + this.logger.info("删除域名解析成功:", record.RecordId); } async getDomainListPage(req: PageSearch): Promise> { - return await this.ctx.access.getDomainListPage(req) + return await this.ctx.access.getDomainListPage(req); } } diff --git a/packages/ui/certd-server/src/plugins/plugin-aliyun/dns-provider/aliyun-dns-provider.ts b/packages/ui/certd-server/src/plugins/plugin-aliyun/dns-provider/aliyun-dns-provider.ts index ef5d25306..e1e6a2c9e 100644 --- a/packages/ui/certd-server/src/plugins/plugin-aliyun/dns-provider/aliyun-dns-provider.ts +++ b/packages/ui/certd-server/src/plugins/plugin-aliyun/dns-provider/aliyun-dns-provider.ts @@ -1,29 +1,27 @@ -import { AbstractDnsProvider, CreateRecordOptions, DomainRecord, IsDnsProvider, RemoveRecordOptions } from '@certd/plugin-cert'; -import { AliyunAccess } from '../../plugin-lib/aliyun/access/aliyun-access.js'; -import { AliyunClient } from '../../plugin-lib/aliyun/index.js'; -import { Pager, PageRes, PageSearch } from '@certd/pipeline'; - +import { AbstractDnsProvider, CreateRecordOptions, DomainRecord, IsDnsProvider, RemoveRecordOptions } from "@certd/plugin-cert"; +import { AliyunAccess } from "../../plugin-lib/aliyun/access/aliyun-access.js"; +import { AliyunClient } from "../../plugin-lib/aliyun/index.js"; +import { Pager, PageRes, PageSearch } from "@certd/pipeline"; @IsDnsProvider({ - name: 'aliyun', - title: '阿里云', - desc: '阿里云DNS解析提供商', - accessType: 'aliyun', - icon: 'svg:icon-aliyun', - order:0, + name: "aliyun", + title: "阿里云", + desc: "阿里云DNS解析提供商", + accessType: "aliyun", + icon: "svg:icon-aliyun", + order: 0, }) export class AliyunDnsProvider extends AbstractDnsProvider { - client: any; async onInstance() { - const access: AliyunAccess = this.ctx.access as AliyunAccess + const access: AliyunAccess = this.ctx.access as AliyunAccess; this.client = new AliyunClient({ logger: this.logger }); await this.client.init({ accessKeyId: access.accessKeyId, accessKeySecret: access.accessKeySecret, - endpoint: 'https://alidns.aliyuncs.com', - apiVersion: '2015-01-09', + endpoint: "https://alidns.aliyuncs.com", + apiVersion: "2015-01-09", }); } // @@ -88,11 +86,11 @@ export class AliyunDnsProvider extends AbstractDnsProvider { // } async createRecord(options: CreateRecordOptions): Promise { - const { fullRecord,hostRecord, value, type, domain } = options; - this.logger.info('添加域名解析:', fullRecord, value, domain); + const { fullRecord, hostRecord, value, type, domain } = options; + this.logger.info("添加域名解析:", fullRecord, value, domain); // const domain = await this.matchDomain(fullRecord); const params = { - RegionId: 'cn-hangzhou', + RegionId: "cn-hangzhou", DomainName: domain, RR: hostRecord, Type: type, @@ -101,31 +99,31 @@ export class AliyunDnsProvider extends AbstractDnsProvider { }; const requestOption = { - method: 'POST', + method: "POST", }; try { - const ret = await this.client.request('AddDomainRecord', params, requestOption); - this.logger.info('添加域名解析成功:', JSON.stringify(options), ret.RecordId); + const ret = await this.client.request("AddDomainRecord", params, requestOption); + this.logger.info("添加域名解析成功:", JSON.stringify(options), ret.RecordId); return ret.RecordId; } catch (e: any) { - if (e.code === 'DomainRecordDuplicate') { + if (e.code === "DomainRecordDuplicate") { return; } - if(e.code === "LastOperationNotFinished"){ - this.logger.info('上一个操作还未完成,5s后重试') - await this.ctx.utils.sleep(5000) - return this.createRecord(options) + if (e.code === "LastOperationNotFinished") { + this.logger.info("上一个操作还未完成,5s后重试"); + await this.ctx.utils.sleep(5000); + return this.createRecord(options); } - if (e.code === 'SignatureDoesNotMatch') { - this.logger.error('阿里云账号的AccessKeyId或AccessKeySecret错误,请检查AccessKey是否被删除、过期、或者选择了错误的授权记录'); + if (e.code === "SignatureDoesNotMatch") { + this.logger.error("阿里云账号的AccessKeyId或AccessKeySecret错误,请检查AccessKey是否被删除、过期、或者选择了错误的授权记录"); } - this.logger.info('添加域名解析出错', e); + this.logger.info("添加域名解析出错", e); this.resolveError(e, options); } } resolveError(e: any, req: CreateRecordOptions) { - if (e.message?.indexOf('The specified domain name does not exist') > -1) { + if (e.message?.indexOf("The specified domain name does not exist") > -1) { throw new Error(`阿里云账号中不存在此域名:${req.domain}`); } throw e; @@ -134,53 +132,50 @@ export class AliyunDnsProvider extends AbstractDnsProvider { const { fullRecord, value } = options.recordReq; const record = options.recordRes; const params = { - RegionId: 'cn-hangzhou', + RegionId: "cn-hangzhou", RecordId: record, }; const requestOption = { - method: 'POST', + method: "POST", }; - try{ - const ret = await this.client.request('DeleteDomainRecord', params, requestOption); - this.logger.info('删除域名解析成功:', fullRecord, value, ret.RecordId); + try { + const ret = await this.client.request("DeleteDomainRecord", params, requestOption); + this.logger.info("删除域名解析成功:", fullRecord, value, ret.RecordId); return ret.RecordId; - }catch (e) { - if(e.code === "LastOperationNotFinished"){ - this.logger.info('上一个操作还未完成,5s后重试') - await this.ctx.utils.sleep(5000) - return this.removeRecord(options) + } catch (e) { + if (e.code === "LastOperationNotFinished") { + this.logger.info("上一个操作还未完成,5s后重试"); + await this.ctx.utils.sleep(5000); + return this.removeRecord(options); } - throw e + throw e; } } - async getDomainListPage(req: PageSearch) :Promise> { + async getDomainListPage(req: PageSearch): Promise> { const pager = new Pager(req); const params = { - RegionId: 'cn-hangzhou', + RegionId: "cn-hangzhou", PageSize: pager.pageSize, PageNumber: pager.pageNo, }; const requestOption = { - method: 'POST', + method: "POST", }; - const ret = await this.client.request( - 'DescribeDomains', - params, - requestOption - ); - const list = ret.Domains?.Domain?.map(item => ({ - id: item.DomainId, - domain: item.DomainName, - })) || [] + const ret = await this.client.request("DescribeDomains", params, requestOption); + const list = + ret.Domains?.Domain?.map(item => ({ + id: item.DomainId, + domain: item.DomainName, + })) || []; return { list, total: ret.TotalCount, - } + }; } } diff --git a/packages/ui/certd-server/src/plugins/plugin-aliyun/dns-provider/index.ts b/packages/ui/certd-server/src/plugins/plugin-aliyun/dns-provider/index.ts index 565ab1b93..4dbf026a4 100644 --- a/packages/ui/certd-server/src/plugins/plugin-aliyun/dns-provider/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-aliyun/dns-provider/index.ts @@ -1,2 +1,2 @@ -import './aliyun-dns-provider.js'; -import './aliesa-dns-provider.js'; +import "./aliyun-dns-provider.js"; +import "./aliesa-dns-provider.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-aliyun/index.ts b/packages/ui/certd-server/src/plugins/plugin-aliyun/index.ts index 67dfdda2d..6db2fa679 100644 --- a/packages/ui/certd-server/src/plugins/plugin-aliyun/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-aliyun/index.ts @@ -1,2 +1,2 @@ -export * from './dns-provider/index.js'; -export * from './plugin/index.js'; \ No newline at end of file +export * from "./dns-provider/index.js"; +export * from "./plugin/index.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/delete-expiring-cert/index.ts b/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/delete-expiring-cert/index.ts index 1cec2c5be..a025371d2 100644 --- a/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/delete-expiring-cert/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/delete-expiring-cert/index.ts @@ -1,15 +1,15 @@ -import { IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from '@certd/pipeline'; +import { IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; import { AbstractPlusTaskPlugin } from "@certd/plugin-plus"; -import dayjs from 'dayjs'; -import { AliyunAccess } from '../../../plugin-lib/aliyun/access/index.js'; -import { AliyunSslClient } from '../../../plugin-lib/aliyun/lib/index.js'; +import dayjs from "dayjs"; +import { AliyunAccess } from "../../../plugin-lib/aliyun/access/index.js"; +import { AliyunSslClient } from "../../../plugin-lib/aliyun/lib/index.js"; @IsTaskPlugin({ - name: 'AliyunDeleteExpiringCert', - title: '阿里云-删除即将过期证书', - icon: 'ant-design:aliyun-outlined', + name: "AliyunDeleteExpiringCert", + title: "阿里云-删除即将过期证书", + icon: "ant-design:aliyun-outlined", group: pluginGroups.aliyun.key, - desc: '仅删除未使用的证书', + desc: "仅删除未使用的证书", default: { strategy: { runStrategy: RunStrategy.AlwaysRun, @@ -19,28 +19,28 @@ import { AliyunSslClient } from '../../../plugin-lib/aliyun/lib/index.js'; }) export class AliyunDeleteExpiringCert extends AbstractPlusTaskPlugin { @TaskInput({ - title: 'Access提供者', - helper: 'access 授权', + title: "Access提供者", + helper: "access 授权", component: { - name: 'access-selector', - type: 'aliyun', + name: "access-selector", + type: "aliyun", }, required: true, }) accessId!: string; @TaskInput({ - title: '地域', - helper: '阿里云CAS证书服务地域', + title: "地域", + helper: "阿里云CAS证书服务地域", component: { - name: 'a-select', + name: "a-select", options: [ - { value: 'cas.aliyuncs.com', label: '中国大陆' }, - { value: 'cas.ap-southeast-1.aliyuncs.com', label: '新加坡' }, + { value: "cas.aliyuncs.com", label: "中国大陆" }, + { value: "cas.ap-southeast-1.aliyuncs.com", label: "新加坡" }, ], }, required: true, - value: 'cas.aliyuncs.com', + value: "cas.aliyuncs.com", }) endpoint!: string; @@ -55,36 +55,36 @@ export class AliyunDeleteExpiringCert extends AbstractPlusTaskPlugin { // searchKey!: string; @TaskInput({ - title: '最大删除数量', - helper: '单次运行最大删除数量', + title: "最大删除数量", + helper: "单次运行最大删除数量", value: 100, component: { - name: 'a-input-number', - vModel: 'value', + name: "a-input-number", + vModel: "value", }, required: true, }) maxCount!: number; @TaskInput({ - title: '即将过期天数', - helper: '仅删除有效期小于此天数的证书,0表示完全过期时才删除', + title: "即将过期天数", + helper: "仅删除有效期小于此天数的证书,0表示完全过期时才删除", value: 0, component: { - name: 'a-input-number', - vModel: 'value', + name: "a-input-number", + vModel: "value", }, required: true, }) expiringDays!: number; @TaskInput({ - title: '检查超时时间', - helper: '检查删除任务结果超时时间,单位分钟', + title: "检查超时时间", + helper: "检查删除任务结果超时时间,单位分钟", value: 10, component: { - name: 'a-input-number', - vModel: 'value', + name: "a-input-number", + vModel: "value", }, required: true, }) @@ -106,17 +106,17 @@ export class AliyunDeleteExpiringCert extends AbstractPlusTaskPlugin { // Keyword: this.searchKey, }; const certificates: any[] = []; - while(true){ - const res = await sslClient.doRequest('ListCertificates', params, { - method: 'POST', - }); + while (true) { + const res = await sslClient.doRequest("ListCertificates", params, { + method: "POST", + }); let list = res?.CertificateList; if (!list || list.length === 0) { break; } this.logger.info(`查询第${params.CurrentPage}页,每页${params.ShowSize}个证书,当前页共${list.length}个证书`); - const lastDay = dayjs().add(this.expiringDays, 'day'); + const lastDay = dayjs().add(this.expiringDays, "day"); list = list.filter((item: any) => { const notAfter = item.NotAfter; const usingProducts = item.UsingProductList; @@ -131,7 +131,7 @@ export class AliyunDeleteExpiringCert extends AbstractPlusTaskPlugin { this.logger.info(`即将过期的证书数量:${certificates.length}`); if (certificates.length === 0) { - this.logger.info('没有即将过期的证书, 无需删除'); + this.logger.info("没有即将过期的证书, 无需删除"); return; } this.logger.info(`开始删除证书,共${certificates.length}个证书`); @@ -140,12 +140,15 @@ export class AliyunDeleteExpiringCert extends AbstractPlusTaskPlugin { for (const certificate of certificates) { try { - const deleteRes = await sslClient.doRequest('DeleteUserCertificate', { - CertId: certificate.CertificateId, - }, { method: 'POST' }); + const deleteRes = await sslClient.doRequest( + "DeleteUserCertificate", + { + CertId: certificate.CertificateId, + }, + { method: "POST" } + ); this.logger.info(`删除证书成功,证书ID:${certificate.CertificateId}, 名称:${certificate.CertificateName}, requestId:${deleteRes?.RequestId}`); successCount++; - } catch (error: any) { this.logger.error(`删除证书失败,证书ID:${certificate.CertificateId}, 名称:${certificate.CertificateName}, 错误:${error.message}`); failedCount++; @@ -156,4 +159,4 @@ export class AliyunDeleteExpiringCert extends AbstractPlusTaskPlugin { } } -new AliyunDeleteExpiringCert(); \ No newline at end of file +new AliyunDeleteExpiringCert(); diff --git a/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-alb/index.ts b/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-alb/index.ts index c571527cd..fc820cb12 100644 --- a/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-alb/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-alb/index.ts @@ -1,9 +1,6 @@ import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; import { CertApplyPluginNames, CertInfo, CertReader } from "@certd/plugin-cert"; -import { - createCertDomainGetterInputDefine, - createRemoteSelectInputDefine -} from "@certd/plugin-lib"; +import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from "@certd/plugin-lib"; import { AliyunAccess } from "../../../plugin-lib/aliyun/access/index.js"; import { AliyunClient, AliyunSslClient, CasCertId } from "../../../plugin-lib/aliyun/lib/index.js"; import { AliyunClientV2 } from "../../../plugin-lib/aliyun/lib/aliyun-client-v2.js"; @@ -17,9 +14,9 @@ import { AliyunClientV2 } from "../../../plugin-lib/aliyun/lib/aliyun-client-v2. needPlus: false, default: { strategy: { - runStrategy: RunStrategy.SkipWhenSucceed - } - } + runStrategy: RunStrategy.SkipWhenSucceed, + }, + }, }) export class AliyunDeployCertToALB extends AbstractTaskPlugin { @TaskInput({ @@ -27,9 +24,9 @@ export class AliyunDeployCertToALB extends AbstractTaskPlugin { helper: "请选择证书申请任务输出的域名证书\n或者选择前置任务“上传证书到阿里云”任务的证书ID,可以减少上传到阿里云的证书数量", component: { name: "output-selector", - from: [...CertApplyPluginNames, "uploadCertToAliyun"] + from: [...CertApplyPluginNames, "uploadCertToAliyun"], }, - required: true + required: true, }) cert!: CertInfo | CasCertId | number; @@ -45,10 +42,10 @@ export class AliyunDeployCertToALB extends AbstractTaskPlugin { options: [ { value: "cas.aliyuncs.com", label: "中国大陆" }, { value: "cas.ap-southeast-1.aliyuncs.com", label: "新加坡" }, - { value: "cas.eu-central-1.aliyuncs.com", label: "德国(法兰克福)" } - ] + { value: "cas.eu-central-1.aliyuncs.com", label: "德国(法兰克福)" }, + ], }, - required: true + required: true, }) casEndpoint!: string; @@ -57,9 +54,9 @@ export class AliyunDeployCertToALB extends AbstractTaskPlugin { helper: "阿里云授权AccessKeyId、AccessKeySecret", component: { name: "access-selector", - type: "aliyun" + type: "aliyun", }, - required: true + required: true, }) accessId!: string; @@ -69,7 +66,7 @@ export class AliyunDeployCertToALB extends AbstractTaskPlugin { typeName: "AliyunDeployCertToALB", single: true, action: AliyunDeployCertToALB.prototype.onGetRegionList.name, - watches: ["accessId"] + watches: ["accessId"], }) ) regionId: string; @@ -80,7 +77,7 @@ export class AliyunDeployCertToALB extends AbstractTaskPlugin { helper: "要部署证书的负载均衡ID", typeName: "AliyunDeployCertToALB", action: AliyunDeployCertToALB.prototype.onGetLoadBalanceList.name, - watches: ["regionId"] + watches: ["regionId"], }) ) loadBalancers!: string[]; @@ -91,12 +88,11 @@ export class AliyunDeployCertToALB extends AbstractTaskPlugin { helper: "要部署证书的监听器列表", typeName: "AliyunDeployCertToALB", action: AliyunDeployCertToALB.prototype.onGetListenerList.name, - watches: ["loadBalancers"] + watches: ["loadBalancers"], }) ) listeners!: string[]; - @TaskInput({ title: "部署证书类型", value: "default", @@ -106,18 +102,17 @@ export class AliyunDeployCertToALB extends AbstractTaskPlugin { options: [ { label: "默认证书", - value: "default" + value: "default", }, { label: "扩展证书", - value: "extension" - } - ] + value: "extension", + }, + ], }, - required: true - } - ) - deployType: string = "default"; + required: true, + }) + deployType = "default"; @TaskInput({ title: "是否清理过期证书", @@ -126,14 +121,11 @@ export class AliyunDeployCertToALB extends AbstractTaskPlugin { name: "a-switch", vModel: "checked", }, - required: true - } - ) + required: true, + }) clearExpiredCert: boolean; - - async onInstance() { - } + async onInstance() {} async getLBClient(access: AliyunAccess, region: string) { const client = new AliyunClient({ logger: this.logger }); @@ -144,7 +136,7 @@ export class AliyunDeployCertToALB extends AbstractTaskPlugin { accessKeySecret: access.accessKeySecret, //https://wafopenapi.cn-hangzhou.aliyuncs.com endpoint: `https://alb.${region}.aliyuncs.com`, - apiVersion: version + apiVersion: version, }); return client; } @@ -166,9 +158,9 @@ export class AliyunDeployCertToALB extends AbstractTaskPlugin { const client = await this.getLBClient(access, this.regionId); await this.deployDefaultCert(certId, client); } - if (this.clearExpiredCert!==false) { + if (this.clearExpiredCert !== false) { this.logger.info(`准备开始清理过期证书`); - await this.ctx.utils.sleep(30000) + await this.ctx.utils.sleep(30000); for (const listener of this.listeners) { try { await this.clearInvalidCert(albClientV2, listener); @@ -188,9 +180,9 @@ export class AliyunDeployCertToALB extends AbstractTaskPlugin { ListenerId: listener, Certificates: [ { - CertificateId: certId - } - ] + CertificateId: certId, + }, + ], }; const res = await client.request("UpdateListenerAttribute", params); @@ -212,11 +204,11 @@ export class AliyunDeployCertToALB extends AbstractTaskPlugin { ListenerId: listenerId, Certificates: [ { - CertificateId: certId - } - ] - } - } + CertificateId: certId, + }, + ], + }, + }, }); this.logger.info(`部署监听器${listenerId}的扩展证书成功`); @@ -232,24 +224,23 @@ export class AliyunDeployCertToALB extends AbstractTaskPlugin { version: "2020-06-16", data: { query: { - ListenerId: listener - } - } + ListenerId: listener, + }, + }, }; const res = await client.doRequest(req); const list = res.Certificates; if (list.length === 0) { this.logger.info(`监听器${listener}没有绑定证书`); - return + return; } const sslClient = new AliyunSslClient({ access: client.access, logger: this.logger, - endpoint: this.casEndpoint + endpoint: this.casEndpoint, }); - const certIds = []; for (const item of list) { this.logger.info(`监听器${listener}绑定的证书${item.CertificateId},status:${item.Status},IsDefault:${item.IsDefault}`); @@ -273,7 +264,7 @@ export class AliyunDeployCertToALB extends AbstractTaskPlugin { } if (invalidCertIds.length === 0) { this.logger.info(`监听器${listener}没有过期的证书`); - return + return; } this.logger.info(`开始解绑过期的证书:${invalidCertIds},listener:${listener}`); await client.doRequest({ @@ -284,13 +275,13 @@ export class AliyunDeployCertToALB extends AbstractTaskPlugin { data: { query: { ListenerId: listener, - Certificates: invalidCertIds.map((item) => { + Certificates: invalidCertIds.map(item => { return { - CertificateId: item - } - }) - } - } + CertificateId: item, + }; + }), + }, + }, }); this.logger.info(`解绑过期证书成功`); } @@ -298,13 +289,12 @@ export class AliyunDeployCertToALB extends AbstractTaskPlugin { async getAliyunCertId(access: AliyunAccess) { let certId: any = this.cert; if (typeof this.cert === "object") { - const certInfo = this.cert as CertInfo; - const casCert = this.cert as CasCertId; + const casCert = this.cert as CasCertId; const sslClient = new AliyunSslClient({ access, logger: this.logger, - endpoint: this.casEndpoint + endpoint: this.casEndpoint, }); if (certInfo.crt) { @@ -313,11 +303,11 @@ export class AliyunDeployCertToALB extends AbstractTaskPlugin { name: certName, cert: certInfo, }); - certId = certIdRes.certId as any; - }else if (casCert.certId){ + certId = certIdRes.certId as any; + } else if (casCert.certId) { certId = casCert.certId; - }else{ - throw new Error('证书格式错误'+JSON.stringify(this.cert)); + } else { + throw new Error("证书格式错误" + JSON.stringify(this.cert)); } } @@ -341,7 +331,7 @@ export class AliyunDeployCertToALB extends AbstractTaskPlugin { return { label: item.LocalName, value: item.RegionId, - endpoint: item.RegionEndpoint + endpoint: item.RegionEndpoint, }; }); } @@ -357,7 +347,7 @@ export class AliyunDeployCertToALB extends AbstractTaskPlugin { const client = await this.getLBClient(access, this.regionId); const params = { - MaxResults: 100 + MaxResults: 100, }; const res = await client.request("ListLoadBalancers", params); this.checkRet(res); @@ -369,7 +359,7 @@ export class AliyunDeployCertToALB extends AbstractTaskPlugin { const label = `${item.LoadBalancerId}<${item.LoadBalancerName}}>`; return { label: label, - value: item.LoadBalancerId + value: item.LoadBalancerId, }; }); } @@ -385,7 +375,7 @@ export class AliyunDeployCertToALB extends AbstractTaskPlugin { const client = await this.getLBClient(access, this.regionId); const params: any = { - MaxResults: 100 + MaxResults: 100, }; if (this.loadBalancers && this.loadBalancers.length > 0) { params.LoadBalancerIds = this.loadBalancers; @@ -401,19 +391,16 @@ export class AliyunDeployCertToALB extends AbstractTaskPlugin { return { label: label, value: item.ListenerId, - lbid: item.LoadBalancerId + lbid: item.LoadBalancerId, }; }); } - checkRet(ret: any) { if (ret.Code != null) { throw new Error(ret.Message); } } - - } new AliyunDeployCertToALB(); diff --git a/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-apig/index.ts b/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-apig/index.ts index 14e5ac6a1..3fd16e97b 100644 --- a/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-apig/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-apig/index.ts @@ -1,19 +1,16 @@ -import {AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput} from '@certd/pipeline'; -import { - createCertDomainGetterInputDefine, - createRemoteSelectInputDefine -} from "@certd/plugin-lib"; +import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; +import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from "@certd/plugin-lib"; import { AliyunAccess } from "../../../plugin-lib/aliyun/access/index.js"; import { AliyunSslClient, CasCertId } from "../../../plugin-lib/aliyun/lib/ssl-client.js"; import { CertApplyPluginNames, CertInfo, CertReader } from "@certd/plugin-cert"; -import {optionsUtils} from "@certd/basic"; +import { optionsUtils } from "@certd/basic"; @IsTaskPlugin({ - name: 'DeployCertToAliyunApig', - title: '阿里云-部署至云原生API网关/AI网关', - icon: 'svg:icon-aliyun', + name: "DeployCertToAliyunApig", + title: "阿里云-部署至云原生API网关/AI网关", + icon: "svg:icon-aliyun", group: pluginGroups.aliyun.key, - desc: '自动部署域名证书至云原生API网关、AI网关', + desc: "自动部署域名证书至云原生API网关、AI网关", default: { strategy: { runStrategy: RunStrategy.SkipWhenSucceed, @@ -22,27 +19,25 @@ import {optionsUtils} from "@certd/basic"; }) export class DeployCertToAliyunApig extends AbstractTaskPlugin { @TaskInput({ - title: '域名证书', - helper: '请选择前置任务输出的域名证书', + title: "域名证书", + helper: "请选择前置任务输出的域名证书", component: { - name: 'output-selector', - from: [...CertApplyPluginNames, 'uploadCertToAliyun'], + name: "output-selector", + from: [...CertApplyPluginNames, "uploadCertToAliyun"], }, required: true, }) - cert!: CertInfo | CasCertId |number; + cert!: CertInfo | CasCertId | number; @TaskInput(createCertDomainGetterInputDefine({ props: { required: false } })) certDomains!: string[]; - - @TaskInput({ - title: 'Access授权', - helper: '阿里云授权', + title: "Access授权", + helper: "阿里云授权", component: { - name: 'access-selector', - type: 'aliyun', + name: "access-selector", + type: "aliyun", }, required: true, }) @@ -50,88 +45,83 @@ export class DeployCertToAliyunApig extends AbstractTaskPlugin { @TaskInput( createRemoteSelectInputDefine({ - title: '区域', - helper: '请选择区域', + title: "区域", + helper: "请选择区域", action: DeployCertToAliyunApig.prototype.onGetRegionList.name, - watches: ['certDomains', 'accessId'], + watches: ["certDomains", "accessId"], required: true, - component:{ - name:"remote-auto-complete" - } + component: { + name: "remote-auto-complete", + }, }) ) regionEndpoint!: string; - @TaskInput({ title: "网关类型", component: { name: "a-select", - vModel:"value", - options:[ - {value:"AI",label:"AI"}, - {value:"API",label:"API"}, - ] + vModel: "value", + options: [ + { value: "AI", label: "AI" }, + { value: "API", label: "API" }, + ], }, - required: true //必填 + required: true, //必填 }) gatewayType!: string; - @TaskInput( createRemoteSelectInputDefine({ - title: '绑定域名', - helper: '请选择域名', + title: "绑定域名", + helper: "请选择域名", action: DeployCertToAliyunApig.prototype.onGetDomainList.name, - watches: ['region', 'accessId','gatewayType'], + watches: ["region", "accessId", "gatewayType"], required: true, }) ) domainList!: string[]; - @TaskInput({ title: "强制HTTPS", component: { name: "a-select", - vModel:"value", - options:[ - {value:true,label:"强制HTTPS"}, - {value:false,label:"不强制HTTPS"}, - ] + vModel: "value", + options: [ + { value: true, label: "强制HTTPS" }, + { value: false, label: "不强制HTTPS" }, + ], }, - required: true //必填 + required: true, //必填 }) forceHttps!: boolean; @TaskInput({ - title: '证书服务接入点', - helper: '不会选就按默认', - value: 'cn-hangzhou', + title: "证书服务接入点", + helper: "不会选就按默认", + value: "cn-hangzhou", component: { - name: 'a-select', + name: "a-select", options: [ - { value: 'cn-hangzhou', label: '中国大陆' }, - { value: 'ap-southeast-1', label: '新加坡' }, + { value: "cn-hangzhou", label: "中国大陆" }, + { value: "ap-southeast-1", label: "新加坡" }, ], }, required: true, }) casRegion!: string; - async onInstance() {} async execute(): Promise { - this.logger.info('开始部署证书到云原生Api网关'); - if(!this.domainList){ - throw new Error('您还未选择域名'); + this.logger.info("开始部署证书到云原生Api网关"); + if (!this.domainList) { + throw new Error("您还未选择域名"); } const access = await this.getAccess(this.accessId); - const client = access.getClient(this.regionEndpoint) - + const client = access.getClient(this.regionEndpoint); let certId: any = this.cert; - if (typeof this.cert === 'object') { + if (typeof this.cert === "object") { const sslClient = new AliyunSslClient({ access, logger: this.logger, @@ -146,25 +136,23 @@ export class DeployCertToAliyunApig extends AbstractTaskPlugin { name: this.buildCertName(CertReader.getMainDomain(certInfo.crt)), cert: certInfo, }); - }else{ - throw new Error('证书格式错误'+JSON.stringify(this.cert)); + } else { + throw new Error("证书格式错误" + JSON.stringify(this.cert)); } } - const certIdentify = `${certId}-${this.casRegion}` + const certIdentify = `${certId}-${this.casRegion}`; - for (const domainId of this.domainList ) { - this.logger.info(`[${domainId}]开始部署`) - await this.updateCert(client, domainId,certIdentify); - this.logger.info(`[${domainId}]部署成功`) + for (const domainId of this.domainList) { + this.logger.info(`[${domainId}]开始部署`); + await this.updateCert(client, domainId, certIdentify); + this.logger.info(`[${domainId}]部署成功`); } - this.logger.info('部署完成'); + this.logger.info("部署完成"); } - - async updateCert(client: any, domainId: string,certIdentify:string) { - + async updateCert(client: any, domainId: string, certIdentify: string) { const domainInfoRes = await client.doRequest({ action: "GetDomain", version: "2024-03-27", @@ -175,57 +163,56 @@ export class DeployCertToAliyunApig extends AbstractTaskPlugin { pathname: `/v1/domains/${domainId}`, }); - const tlsCipherSuitesConfig = domainInfoRes.data?.tlsCipherSuitesConfig + const tlsCipherSuitesConfig = domainInfoRes.data?.tlsCipherSuitesConfig; - - const ret = await client.doRequest({ - action: "UpdateDomain", - version: "2024-03-27", - method: "PUT", - style: "ROA", - pathname: `/v1/domains/${domainId}`, - data:{ - body:{ + const ret = await client.doRequest({ + action: "UpdateDomain", + version: "2024-03-27", + method: "PUT", + style: "ROA", + pathname: `/v1/domains/${domainId}`, + data: { + body: { certIdentifier: certIdentify, protocol: "HTTPS", - forceHttps:this.forceHttps, - tlsCipherSuitesConfig - } - } - }) + forceHttps: this.forceHttps, + tlsCipherSuitesConfig, + }, + }, + }); this.logger.info(`设置${domainId}证书成功:`, ret.requestId); } async onGetDomainList(data: any) { if (!this.accessId) { - throw new Error('请选择Access授权'); + throw new Error("请选择Access授权"); } if (!this.regionEndpoint) { - throw new Error('请选择区域'); + throw new Error("请选择区域"); } if (!this.gatewayType) { - throw new Error('请选择网关类型'); + throw new Error("请选择网关类型"); } const access = await this.getAccess(this.accessId); - const client = access.getClient(this.regionEndpoint) + const client = access.getClient(this.regionEndpoint); - const res =await client.doRequest({ - action: "ListDomains", - version: "2024-03-27", - method: "GET", - style: "ROA", - pathname: `/v1/domains`, - data:{ - query:{ - pageSize: 100, - gatewayType: this.gatewayType , - } - } - }) + const res = await client.doRequest({ + action: "ListDomains", + version: "2024-03-27", + method: "GET", + style: "ROA", + pathname: `/v1/domains`, + data: { + query: { + pageSize: 100, + gatewayType: this.gatewayType, + }, + }, + }); const list = res?.data?.items; if (!list || list.length === 0) { - return [] + return []; } const options = list.map((item: any) => { return { @@ -237,43 +224,42 @@ export class DeployCertToAliyunApig extends AbstractTaskPlugin { return optionsUtils.buildGroupOptions(options, this.certDomains); } - async onGetRegionList(data: any) { const list = [ - {value:"cn-qingdao",label:"华北1(青岛)",endpoint:"apig.cn-qingdao.aliyuncs.com"}, - {value:"cn-beijing",label:"华北2(北京)",endpoint:"apig.cn-beijing.aliyuncs.com"}, - {value:"cn-zhangjiakou",label:"华北3(张家口)",endpoint:"apig.cn-zhangjiakou.aliyuncs.com"}, - {value:"cn-wulanchabu",label:"华北6(乌兰察布)",endpoint:"apig.cn-wulanchabu.aliyuncs.com"}, - {value:"cn-hangzhou",label:"华东1(杭州)",endpoint:"apig.cn-hangzhou.aliyuncs.com"}, - {value:"cn-shanghai",label:"华东2(上海)",endpoint:"apig.cn-shanghai.aliyuncs.com"}, - {value:"cn-shenzhen",label:"华南1(深圳)",endpoint:"apig.cn-shenzhen.aliyuncs.com"}, - {value:"cn-heyuan",label:"华南2(河源)",endpoint:"apig.cn-heyuan.aliyuncs.com"}, - {value:"cn-guangzhou",label:"华南3(广州)",endpoint:"apig.cn-guangzhou.aliyuncs.com"}, - {value:"ap-southeast-2",label:"澳大利亚(悉尼)已关停",endpoint:"apig.ap-southeast-2.aliyuncs.com"}, - {value:"ap-southeast-6",label:"菲律宾(马尼拉)",endpoint:"apig.ap-southeast-6.aliyuncs.com"}, - {value:"ap-northeast-2",label:"韩国(首尔)",endpoint:"apig.ap-northeast-2.aliyuncs.com"}, - {value:"ap-southeast-3",label:"马来西亚(吉隆坡)",endpoint:"apig.ap-southeast-3.aliyuncs.com"}, - {value:"ap-northeast-1",label:"日本(东京)",endpoint:"apig.ap-northeast-1.aliyuncs.com"}, - {value:"ap-southeast-7",label:"泰国(曼谷)",endpoint:"apig.ap-southeast-7.aliyuncs.com"}, - {value:"cn-chengdu",label:"西南1(成都)",endpoint:"apig.cn-chengdu.aliyuncs.com"}, - {value:"ap-southeast-1",label:"新加坡",endpoint:"apig.ap-southeast-1.aliyuncs.com"}, - {value:"ap-southeast-5",label:"印度尼西亚(雅加达)",endpoint:"apig.ap-southeast-5.aliyuncs.com"}, - {value:"cn-hongkong",label:"中国香港",endpoint:"apig.cn-hongkong.aliyuncs.com"}, - {value:"eu-central-1",label:"德国(法兰克福)",endpoint:"apig.eu-central-1.aliyuncs.com"}, - {value:"us-east-1",label:"美国(弗吉尼亚)",endpoint:"apig.us-east-1.aliyuncs.com"}, - {value:"us-west-1",label:"美国(硅谷)",endpoint:"apig.us-west-1.aliyuncs.com"}, - {value:"eu-west-1",label:"英国(伦敦)",endpoint:"apig.eu-west-1.aliyuncs.com"}, - {value:"me-east-1",label:"阿联酋(迪拜)",endpoint:"apig.me-east-1.aliyuncs.com"}, - {value:"me-central-1",label:"沙特(利雅得)",endpoint:"apig.me-central-1.aliyuncs.com"}, - ] + { value: "cn-qingdao", label: "华北1(青岛)", endpoint: "apig.cn-qingdao.aliyuncs.com" }, + { value: "cn-beijing", label: "华北2(北京)", endpoint: "apig.cn-beijing.aliyuncs.com" }, + { value: "cn-zhangjiakou", label: "华北3(张家口)", endpoint: "apig.cn-zhangjiakou.aliyuncs.com" }, + { value: "cn-wulanchabu", label: "华北6(乌兰察布)", endpoint: "apig.cn-wulanchabu.aliyuncs.com" }, + { value: "cn-hangzhou", label: "华东1(杭州)", endpoint: "apig.cn-hangzhou.aliyuncs.com" }, + { value: "cn-shanghai", label: "华东2(上海)", endpoint: "apig.cn-shanghai.aliyuncs.com" }, + { value: "cn-shenzhen", label: "华南1(深圳)", endpoint: "apig.cn-shenzhen.aliyuncs.com" }, + { value: "cn-heyuan", label: "华南2(河源)", endpoint: "apig.cn-heyuan.aliyuncs.com" }, + { value: "cn-guangzhou", label: "华南3(广州)", endpoint: "apig.cn-guangzhou.aliyuncs.com" }, + { value: "ap-southeast-2", label: "澳大利亚(悉尼)已关停", endpoint: "apig.ap-southeast-2.aliyuncs.com" }, + { value: "ap-southeast-6", label: "菲律宾(马尼拉)", endpoint: "apig.ap-southeast-6.aliyuncs.com" }, + { value: "ap-northeast-2", label: "韩国(首尔)", endpoint: "apig.ap-northeast-2.aliyuncs.com" }, + { value: "ap-southeast-3", label: "马来西亚(吉隆坡)", endpoint: "apig.ap-southeast-3.aliyuncs.com" }, + { value: "ap-northeast-1", label: "日本(东京)", endpoint: "apig.ap-northeast-1.aliyuncs.com" }, + { value: "ap-southeast-7", label: "泰国(曼谷)", endpoint: "apig.ap-southeast-7.aliyuncs.com" }, + { value: "cn-chengdu", label: "西南1(成都)", endpoint: "apig.cn-chengdu.aliyuncs.com" }, + { value: "ap-southeast-1", label: "新加坡", endpoint: "apig.ap-southeast-1.aliyuncs.com" }, + { value: "ap-southeast-5", label: "印度尼西亚(雅加达)", endpoint: "apig.ap-southeast-5.aliyuncs.com" }, + { value: "cn-hongkong", label: "中国香港", endpoint: "apig.cn-hongkong.aliyuncs.com" }, + { value: "eu-central-1", label: "德国(法兰克福)", endpoint: "apig.eu-central-1.aliyuncs.com" }, + { value: "us-east-1", label: "美国(弗吉尼亚)", endpoint: "apig.us-east-1.aliyuncs.com" }, + { value: "us-west-1", label: "美国(硅谷)", endpoint: "apig.us-west-1.aliyuncs.com" }, + { value: "eu-west-1", label: "英国(伦敦)", endpoint: "apig.eu-west-1.aliyuncs.com" }, + { value: "me-east-1", label: "阿联酋(迪拜)", endpoint: "apig.me-east-1.aliyuncs.com" }, + { value: "me-central-1", label: "沙特(利雅得)", endpoint: "apig.me-central-1.aliyuncs.com" }, + ]; return list.map((item: any) => { return { value: item.endpoint, label: item.label, endpoint: item.endpoint, - regionId : item.value + regionId: item.value, }; - }) + }); } } new DeployCertToAliyunApig(); diff --git a/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-apigateway/index.ts b/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-apigateway/index.ts index 5053121fb..71e6d6b36 100644 --- a/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-apigateway/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-apigateway/index.ts @@ -1,15 +1,15 @@ -import {AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput} from '@certd/pipeline'; -import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine} from "@certd/plugin-lib"; -import {CertApplyPluginNames, CertInfo} from '@certd/plugin-cert'; -import {optionsUtils} from "@certd/basic"; +import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; +import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from "@certd/plugin-lib"; +import { CertApplyPluginNames, CertInfo } from "@certd/plugin-cert"; +import { optionsUtils } from "@certd/basic"; import { AliyunAccess } from "../../../plugin-lib/aliyun/access/index.js"; @IsTaskPlugin({ - name: 'DeployCertToAliyunApiGateway', - title: '阿里云-部署证书至API网关', - icon: 'svg:icon-aliyun', + name: "DeployCertToAliyunApiGateway", + title: "阿里云-部署证书至API网关", + icon: "svg:icon-aliyun", group: pluginGroups.aliyun.key, - desc: '自动部署域名证书至阿里云API网关(APIGateway)', + desc: "自动部署域名证书至阿里云API网关(APIGateway)", default: { strategy: { runStrategy: RunStrategy.SkipWhenSucceed, @@ -18,10 +18,10 @@ import { AliyunAccess } from "../../../plugin-lib/aliyun/access/index.js"; }) export class DeployCertToAliyunApiGateway extends AbstractTaskPlugin { @TaskInput({ - title: '域名证书', - helper: '请选择前置任务输出的域名证书', + title: "域名证书", + helper: "请选择前置任务输出的域名证书", component: { - name: 'output-selector', + name: "output-selector", from: [...CertApplyPluginNames], }, required: true, @@ -32,122 +32,117 @@ export class DeployCertToAliyunApiGateway extends AbstractTaskPlugin { certDomains!: string[]; @TaskInput({ - title: 'Access授权', - helper: '阿里云授权AccessKeyId、AccessKeySecret', + title: "Access授权", + helper: "阿里云授权AccessKeyId、AccessKeySecret", component: { - name: 'access-selector', - type: 'aliyun', + name: "access-selector", + type: "aliyun", }, required: true, }) accessId!: string; - @TaskInput({ - title: '证书名称', - helper: '上传后将以此名称作为前缀备注', + title: "证书名称", + helper: "上传后将以此名称作为前缀备注", }) certName!: string; @TaskInput( createRemoteSelectInputDefine({ - title: '区域', - helper: '请选择区域', + title: "区域", + helper: "请选择区域", action: DeployCertToAliyunApiGateway.prototype.onGetRegionList.name, - watches: ['certDomains', 'accessId'], + watches: ["certDomains", "accessId"], required: true, - component:{ - name:"remote-auto-complete" - } + component: { + name: "remote-auto-complete", + }, }) ) regionEndpoint!: string; @TaskInput( createRemoteSelectInputDefine({ - title: 'API分组', - helper: '请选择API分组', + title: "API分组", + helper: "请选择API分组", action: DeployCertToAliyunApiGateway.prototype.onGetGroupList.name, - watches: ['regionEndpoint', 'accessId'], + watches: ["regionEndpoint", "accessId"], required: true, - component:{ - name:"remote-auto-complete" - } + component: { + name: "remote-auto-complete", + }, }) ) groupId!: string; - @TaskInput( createRemoteSelectInputDefine({ - title: '绑定域名', - helper: '在API分组上配置的绑定域名', + title: "绑定域名", + helper: "在API分组上配置的绑定域名", action: DeployCertToAliyunApiGateway.prototype.onGetDomainList.name, - watches: ['groupId','regionEndpoint', 'accessId'], + watches: ["groupId", "regionEndpoint", "accessId"], required: true, }) ) customDomains!: string[]; - async onInstance() {} async execute(): Promise { - this.logger.info('开始部署证书到阿里云Api网关'); - if(!this.customDomains){ - throw new Error('您还未选择域名'); + this.logger.info("开始部署证书到阿里云Api网关"); + if (!this.customDomains) { + throw new Error("您还未选择域名"); } const access = await this.getAccess(this.accessId); - const client = access.getClient(this.regionEndpoint) + const client = access.getClient(this.regionEndpoint); - for (const domainName of this.customDomains ) { - this.logger.info(`[${domainName}]开始部署`) + for (const domainName of this.customDomains) { + this.logger.info(`[${domainName}]开始部署`); await this.updateCert(client, domainName); - this.logger.info(`[${domainName}]部署成功`) + this.logger.info(`[${domainName}]部署成功`); } - this.logger.info('部署完成'); + this.logger.info("部署完成"); } - async updateCert(client: any, domainName: string) { - const ret = await client.doRequest({ + const ret = await client.doRequest({ // 接口名称 action: "SetDomainCertificate", // 接口版本 version: "2016-07-14", - data:{ - query:{ + data: { + query: { GroupId: this.groupId, DomainName: domainName, CertificateName: this.buildCertName(domainName), CertificateBody: this.cert.crt, - CertificatePrivateKey: this.cert.key - } - } - }) + CertificatePrivateKey: this.cert.key, + }, + }, + }); this.logger.info(`设置${domainName}证书成功:`, ret.RequestId); } - async onGetGroupList(data: any) { if (!this.accessId) { - throw new Error('请选择Access授权'); + throw new Error("请选择Access授权"); } if (!this.regionEndpoint) { - throw new Error('请选择区域'); + throw new Error("请选择区域"); } const access = await this.getAccess(this.accessId); - const client = access.getClient(this.regionEndpoint) - const res =await client.doRequest({ + const client = access.getClient(this.regionEndpoint); + const res = await client.doRequest({ // 接口名称 action: "DescribeApiGroups", // 接口版本 version: "2016-07-14", - data:{} - }) + data: {}, + }); const list = res?.ApiGroupAttributes?.ApiGroupAttribute; if (!list || list.length === 0) { - throw new Error('没有数据,您可以手动输入API网关ID'); + throw new Error("没有数据,您可以手动输入API网关ID"); } return list.map((item: any) => { return { @@ -159,32 +154,32 @@ export class DeployCertToAliyunApiGateway extends AbstractTaskPlugin { async onGetDomainList(data: any) { if (!this.accessId) { - throw new Error('请选择Access授权'); + throw new Error("请选择Access授权"); } if (!this.regionEndpoint) { - throw new Error('请选择区域'); + throw new Error("请选择区域"); } if (!this.groupId) { - throw new Error('请选择分组'); + throw new Error("请选择分组"); } const access = await this.getAccess(this.accessId); - const client = access.getClient(this.regionEndpoint) + const client = access.getClient(this.regionEndpoint); - const res =await client.doRequest({ - // 接口名称 - action: "DescribeApiGroup", - // 接口版本 - version: "2016-07-14", - data:{ - query:{ - GroupId: this.groupId - } - } - }) + const res = await client.doRequest({ + // 接口名称 + action: "DescribeApiGroup", + // 接口版本 + version: "2016-07-14", + data: { + query: { + GroupId: this.groupId, + }, + }, + }); const list = res?.CustomDomains?.DomainItem; if (!list || list.length === 0) { - throw new Error('没有数据,您可以手动输入'); + throw new Error("没有数据,您可以手动输入"); } const options = list.map((item: any) => { return { @@ -196,32 +191,31 @@ export class DeployCertToAliyunApiGateway extends AbstractTaskPlugin { return optionsUtils.buildGroupOptions(options, this.certDomains); } - async onGetRegionList(data: any) { if (!this.accessId) { - throw new Error('请选择Access授权'); + throw new Error("请选择Access授权"); } const access = await this.getAccess(this.accessId); - const client = access.getClient("apigateway.cn-hangzhou.aliyuncs.com") + const client = access.getClient("apigateway.cn-hangzhou.aliyuncs.com"); - const res =await client.doRequest({ + const res = await client.doRequest({ // 接口名称 action: "DescribeRegions", // 接口版本 version: "2016-07-14", - data:{} - }) - const list = res.Regions.Region ; + data: {}, + }); + const list = res.Regions.Region; if (!list || list.length === 0) { - throw new Error('没有数据,您可以手动输入'); + throw new Error("没有数据,您可以手动输入"); } return list.map((item: any) => { return { value: item.RegionEndpoint, label: item.LocalName, endpoint: item.RegionEndpoint, - regionId: item.RegionId + regionId: item.RegionId, }; }); } diff --git a/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-cdn/index.ts b/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-cdn/index.ts index aa45e6259..7b6507838 100644 --- a/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-cdn/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-cdn/index.ts @@ -1,15 +1,15 @@ -import { optionsUtils } from '@certd/basic'; -import { AbstractTaskPlugin, CertTargetItem, IsTaskPlugin, Pager, PageSearch, pluginGroups, RunStrategy, TaskInput, TaskOutput } from '@certd/pipeline'; +import { optionsUtils } from "@certd/basic"; +import { AbstractTaskPlugin, CertTargetItem, IsTaskPlugin, Pager, PageSearch, pluginGroups, RunStrategy, TaskInput, TaskOutput } from "@certd/pipeline"; import { CertApplyPluginNames, CertReader } from "@certd/plugin-cert"; -import { CertInfo, createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from '@certd/plugin-lib'; +import { CertInfo, createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from "@certd/plugin-lib"; import { AliyunAccess } from "../../../plugin-lib/aliyun/access/index.js"; import { AliyunClient, AliyunSslClient, CasCertId } from "../../../plugin-lib/aliyun/lib/index.js"; @IsTaskPlugin({ - name: 'DeployCertToAliyunCDN', - title: '阿里云-部署证书至CDN', - icon: 'svg:icon-aliyun', + name: "DeployCertToAliyunCDN", + title: "阿里云-部署证书至CDN", + icon: "svg:icon-aliyun", group: pluginGroups.aliyun.key, - desc: '自动部署域名证书至阿里云CDN', + desc: "自动部署域名证书至阿里云CDN", runStrategy: RunStrategy.AlwaysRun, // default: { // strategy: { @@ -19,15 +19,15 @@ import { AliyunClient, AliyunSslClient, CasCertId } from "../../../plugin-lib/al }) export class DeployCertToAliyunCDN extends AbstractTaskPlugin { @TaskInput({ - title: '证书服务接入点', - helper: '不会选就按默认', - value: 'cas.aliyuncs.com', + title: "证书服务接入点", + helper: "不会选就按默认", + value: "cas.aliyuncs.com", component: { - name: 'a-select', + name: "a-select", options: [ - { value: 'cas.aliyuncs.com', label: '中国大陆' }, - { value: 'cas.ap-southeast-1.aliyuncs.com', label: '新加坡' }, - { value: 'cas.eu-central-1.aliyuncs.com', label: '德国(法兰克福)' }, + { value: "cas.aliyuncs.com", label: "中国大陆" }, + { value: "cas.ap-southeast-1.aliyuncs.com", label: "新加坡" }, + { value: "cas.eu-central-1.aliyuncs.com", label: "德国(法兰克福)" }, ], }, required: true, @@ -35,11 +35,11 @@ export class DeployCertToAliyunCDN extends AbstractTaskPlugin { endpoint!: string; @TaskInput({ - title: '域名证书', - helper: '请选择前置任务输出的域名证书', + title: "域名证书", + helper: "请选择前置任务输出的域名证书", component: { - name: 'output-selector', - from: [...CertApplyPluginNames, 'uploadCertToAliyun'], + name: "output-selector", + from: [...CertApplyPluginNames, "uploadCertToAliyun"], }, template: false, required: true, @@ -50,62 +50,61 @@ export class DeployCertToAliyunCDN extends AbstractTaskPlugin { certDomains!: string[]; @TaskInput({ - title: 'Access授权', - helper: '阿里云授权AccessKeyId、AccessKeySecret', + title: "Access授权", + helper: "阿里云授权AccessKeyId、AccessKeySecret", component: { - name: 'access-selector', - type: 'aliyun', + name: "access-selector", + type: "aliyun", }, required: true, }) accessId!: string; @TaskInput({ - title: '证书所在地域', - helper: 'cn-hangzhou和ap-southeast-1,默认cn-hangzhou。国际站用户建议使用ap-southeast-1。', + title: "证书所在地域", + helper: "cn-hangzhou和ap-southeast-1,默认cn-hangzhou。国际站用户建议使用ap-southeast-1。", value: "cn-hangzhou", component: { - name: 'a-select', + name: "a-select", options: [ - { value: 'cn-hangzhou', label: '中国大陆' }, - { value: 'ap-southeast-1', label: '新加坡' } - ] + { value: "cn-hangzhou", label: "中国大陆" }, + { value: "ap-southeast-1", label: "新加坡" }, + ], }, required: true, }) - certRegion: string + certRegion: string; @TaskInput({ - title: '证书名称', - helper: '上传后将以此名称作为前缀备注', + title: "证书名称", + helper: "上传后将以此名称作为前缀备注", }) certName!: string; - @TaskInput({ - title: '域名匹配模式', - helper: '根据证书匹配:根据证书域名自动匹配DCDN加速域名自动部署,新增加速域名自动感知,自动新增部署', + title: "域名匹配模式", + helper: "根据证书匹配:根据证书域名自动匹配DCDN加速域名自动部署,新增加速域名自动感知,自动新增部署", component: { - name: 'a-select', + name: "a-select", options: [ - { label: '手动选择', value: 'manual' }, - { label: '根据证书匹配', value: 'auto' }, + { label: "手动选择", value: "manual" }, + { label: "根据证书匹配", value: "auto" }, ], }, - value: 'manual', + value: "manual", }) - domainMatchMode!: 'manual' | 'auto'; + domainMatchMode!: "manual" | "auto"; @TaskInput( createRemoteSelectInputDefine({ - title: 'CDN加速域名', - helper: '你在阿里云上配置的CDN加速域名,比如:certd.docmirror.cn', - typeName: 'DeployCertToAliyunCDN', + title: "CDN加速域名", + helper: "你在阿里云上配置的CDN加速域名,比如:certd.docmirror.cn", + typeName: "DeployCertToAliyunCDN", action: DeployCertToAliyunCDN.prototype.onGetDomainList.name, - watches: ['certDomains', 'accessId'], + watches: ["certDomains", "accessId"], required: true, pageSize: 100, - search:true, + search: true, mergeScript: ` return { show: ctx.compute(({form})=>{ @@ -113,72 +112,70 @@ export class DeployCertToAliyunCDN extends AbstractTaskPlugin { }) } `, - pager:true, + pager: true, }) ) domainName!: string | string[]; @TaskOutput({ - title: '已部署过的DCDN加速域名', + title: "已部署过的DCDN加速域名", }) deployedList!: string[]; - async onInstance() { } + async onInstance() {} async execute(): Promise { - this.logger.info('开始部署证书到阿里云cdn'); + this.logger.info("开始部署证书到阿里云cdn"); const access = await this.getAccess(this.accessId); if (this.cert == null) { - throw new Error('域名证书参数为空,请检查前置任务') + throw new Error("域名证书参数为空,请检查前置任务"); } const client = await this.getClient(access); const sslClient = new AliyunSslClient({ access, logger: this.logger, - endpoint: this.endpoint || 'cas.aliyuncs.com', + endpoint: this.endpoint || "cas.aliyuncs.com", }); - if (this.domainMatchMode === 'auto') { - + if (this.domainMatchMode === "auto") { const { result, deployedList } = await this.autoMatchedDeploy({ - targetName: 'DCDN加速域名', + targetName: "DCDN加速域名", uploadCert: async () => { return await sslClient.uploadCertOrGet(this.cert); }, - deployOne: async (req: { target: CertTargetItem, cert: any }) => { + deployOne: async (req: { target: CertTargetItem; cert: any }) => { return await this.deployOne(client, req.target.value, req.cert); }, - getCertDomains:async ()=>{ - return sslClient.getCertDomains(this.cert); + getCertDomains: async () => { + return sslClient.getCertDomains(this.cert); }, - getDeployTargetList: this.onGetDomainList.bind(this) + getDeployTargetList: this.onGetDomainList.bind(this), }); this.deployedList = deployedList; return result; - } else { if (this.isNotChanged()) { - this.logger.info('输入参数未变更,跳过'); + this.logger.info("输入参数未变更,跳过"); return "skip"; } const certId = await this.getOrUploadCasCert(sslClient); - if (typeof this.domainName === 'string') { + if (typeof this.domainName === "string") { this.domainName = [this.domainName]; } for (const domain of this.domainName) { - await this.deployOne(client, domain, certId ); + await this.deployOne(client, domain, certId); } } - this.logger.info('部署完成'); + this.logger.info("部署完成"); } async getOrUploadCasCert(sslClient: AliyunSslClient) { let certId: any = this.cert; let certName = this.appendTimeSuffix(this.certName); - if (typeof this.cert === 'object') { + if (typeof this.cert === "object") { const certInfo = this.cert as CertInfo; const casCert = this.cert as CasCertId; if (casCert.certId) { @@ -191,23 +188,23 @@ export class DeployCertToAliyunCDN extends AbstractTaskPlugin { }); certId = certIdRes.certId as any; } else { - throw new Error('证书格式错误' + JSON.stringify(this.cert)); + throw new Error("证书格式错误" + JSON.stringify(this.cert)); } } return { certId, certName, - } + }; } - async deployOne(client: any, domain: string, cert: any ) { + async deployOne(client: any, domain: string, cert: any) { const { certId, certName } = cert; await this.SetCdnDomainSSLCertificate(client, { CertId: certId, DomainName: domain, CertName: certName, - CertRegion: this.certRegion || 'cn-hangzhou', + CertRegion: this.certRegion || "cn-hangzhou", }); } @@ -216,23 +213,23 @@ export class DeployCertToAliyunCDN extends AbstractTaskPlugin { await client.init({ accessKeyId: access.accessKeyId, accessKeySecret: access.accessKeySecret, - endpoint: 'https://cdn.aliyuncs.com', - apiVersion: '2018-05-10', + endpoint: "https://cdn.aliyuncs.com", + apiVersion: "2018-05-10", }); return client; } - async SetCdnDomainSSLCertificate(client: any, params: { CertId: number; DomainName: string, CertName: string, CertRegion: string }) { - this.logger.info('设置CDN: ', JSON.stringify(params)); + async SetCdnDomainSSLCertificate(client: any, params: { CertId: number; DomainName: string; CertName: string; CertRegion: string }) { + this.logger.info("设置CDN: ", JSON.stringify(params)); const requestOption = { - method: 'POST', + method: "POST", formatParams: false, }; const ret: any = await client.request( - 'SetCdnDomainSSLCertificate', + "SetCdnDomainSSLCertificate", { - SSLProtocol: 'on', + SSLProtocol: "on", CertType: "cas", ...params, }, @@ -244,41 +241,41 @@ export class DeployCertToAliyunCDN extends AbstractTaskPlugin { checkRet(ret: any) { if (ret.Code != null) { - throw new Error('执行失败:' + ret.Message); + throw new Error("执行失败:" + ret.Message); } } async onGetDomainList(data: PageSearch) { if (!this.accessId) { - throw new Error('请选择Access授权'); + throw new Error("请选择Access授权"); } const access = await this.getAccess(this.accessId); const client = await this.getClient(access); - const pager = new Pager(data) + const pager = new Pager(data); const params = { DomainName: data.searchKey, PageSize: pager.pageSize || 100, PageNumber: pager.pageNo || 1, - DomainSearchType: "fuzzy_match" + DomainSearchType: "fuzzy_match", }; const requestOption = { - method: 'POST', + method: "POST", formatParams: false, }; - const res = await client.request('DescribeUserDomains', params, requestOption); + const res = await client.request("DescribeUserDomains", params, requestOption); this.checkRet(res); const pageData = res?.Domains?.PageData; if (!pageData || pageData.length === 0) { - return { - list: [], - total: 0, - }; + return { + list: [], + total: 0, + }; } - const total = res?.TotalCount || 0; + const total = res?.TotalCount || 0; const options = pageData.map((item: any) => { return { value: item.DomainName, diff --git a/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-dcdn/index.ts b/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-dcdn/index.ts index 64976f79f..c760d664c 100644 --- a/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-dcdn/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-dcdn/index.ts @@ -1,20 +1,17 @@ -import { AbstractTaskPlugin, CertTargetItem, IsTaskPlugin, Pager, PageSearch, pluginGroups, RunStrategy, TaskInput, TaskOutput } from '@certd/pipeline'; -import { - createCertDomainGetterInputDefine, - createRemoteSelectInputDefine -} from "@certd/plugin-lib"; -import dayjs from 'dayjs'; +import { AbstractTaskPlugin, CertTargetItem, IsTaskPlugin, Pager, PageSearch, pluginGroups, RunStrategy, TaskInput, TaskOutput } from "@certd/pipeline"; +import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from "@certd/plugin-lib"; +import dayjs from "dayjs"; import { AliyunAccess } from "../../../plugin-lib/aliyun/access/index.js"; import { optionsUtils } from "@certd/basic"; -import { CertApplyPluginNames, CertInfo } from '@certd/plugin-cert'; +import { CertApplyPluginNames, CertInfo } from "@certd/plugin-cert"; import { AliyunClient, AliyunSslClient, CasCertId } from "../../../plugin-lib/aliyun/lib/index.js"; @IsTaskPlugin({ - name: 'DeployCertToAliyunDCDN', - title: '阿里云-部署证书至DCDN', - icon: 'svg:icon-aliyun', + name: "DeployCertToAliyunDCDN", + title: "阿里云-部署证书至DCDN", + icon: "svg:icon-aliyun", group: pluginGroups.aliyun.key, - desc: '依赖证书申请前置任务,自动部署域名证书至阿里云DCDN', + desc: "依赖证书申请前置任务,自动部署域名证书至阿里云DCDN", runStrategy: RunStrategy.AlwaysRun, // default: { // strategy: { @@ -24,11 +21,11 @@ import { AliyunClient, AliyunSslClient, CasCertId } from "../../../plugin-lib/al }) export class DeployCertToAliyunDCDN extends AbstractTaskPlugin { @TaskInput({ - title: '域名证书', - helper: '请选择前置任务输出的域名证书', + title: "域名证书", + helper: "请选择前置任务输出的域名证书", component: { - name: 'output-selector', - from: [...CertApplyPluginNames, 'uploadCertToAliyun'], + name: "output-selector", + from: [...CertApplyPluginNames, "uploadCertToAliyun"], }, required: true, }) @@ -38,47 +35,46 @@ export class DeployCertToAliyunDCDN extends AbstractTaskPlugin { certDomains!: string[]; @TaskInput({ - title: 'Access授权', - helper: '阿里云授权AccessKeyId、AccessKeySecret', + title: "Access授权", + helper: "阿里云授权AccessKeyId、AccessKeySecret", component: { - name: 'access-selector', - type: 'aliyun', + name: "access-selector", + type: "aliyun", }, required: true, }) accessId!: string; - @TaskInput({ - title: '证书名称', - helper: '上传后将以此名称作为前缀备注', + title: "证书名称", + helper: "上传后将以此名称作为前缀备注", }) certName!: string; @TaskInput({ - title: '域名匹配模式', - helper: '根据证书匹配:根据证书域名自动匹配DCDN加速域名自动部署,新增加速域名自动感知,自动新增部署', + title: "域名匹配模式", + helper: "根据证书匹配:根据证书域名自动匹配DCDN加速域名自动部署,新增加速域名自动感知,自动新增部署", component: { - name: 'a-select', + name: "a-select", options: [ - { label: '手动选择', value: 'manual' }, - { label: '根据证书匹配', value: 'auto' }, + { label: "手动选择", value: "manual" }, + { label: "根据证书匹配", value: "auto" }, ], }, - value: 'manual', + value: "manual", }) - domainMatchMode!: 'manual' | 'auto'; + domainMatchMode!: "manual" | "auto"; @TaskInput( createRemoteSelectInputDefine({ - title: 'DCDN加速域名', - helper: '你在阿里云上配置的DCDN加速域名,比如:certd.docmirror.cn', + title: "DCDN加速域名", + helper: "你在阿里云上配置的DCDN加速域名,比如:certd.docmirror.cn", action: DeployCertToAliyunDCDN.prototype.onGetDomainList.name, - watches: ['certDomains', 'accessId'], + watches: ["certDomains", "accessId"], required: true, pageSize: 100, - search:true, - pager:true, + search: true, + pager: true, mergeScript: ` return { show: ctx.compute(({form})=>{ @@ -91,63 +87,59 @@ export class DeployCertToAliyunDCDN extends AbstractTaskPlugin { domainName!: string | string[]; @TaskOutput({ - title: '已部署过的DCDN加速域名', + title: "已部署过的DCDN加速域名", }) deployedList!: string[]; - - async onInstance() { } + async onInstance() {} async execute(): Promise { - this.logger.info('开始部署证书到阿里云DCDN'); + this.logger.info("开始部署证书到阿里云DCDN"); const access = (await this.getAccess(this.accessId)) as AliyunAccess; const client = await this.getClient(access); const sslClient = new AliyunSslClient({ access, logger: this.logger }); - - if (this.domainMatchMode === 'auto') { + if (this.domainMatchMode === "auto") { const { result, deployedList } = await this.autoMatchedDeploy({ - targetName: 'CDN加速域名', + targetName: "CDN加速域名", uploadCert: async () => { return await sslClient.uploadCertOrGet(this.cert); }, - deployOne: async (req: { target: CertTargetItem, cert: any }) => { + deployOne: async (req: { target: CertTargetItem; cert: any }) => { return await this.deployOne(client, req.target.value, req.cert); }, - getCertDomains: async ()=>{ + getCertDomains: async () => { return sslClient.getCertDomains(this.cert); }, - getDeployTargetList: this.onGetDomainList.bind(this) + getDeployTargetList: this.onGetDomainList.bind(this), }); this.deployedList = deployedList; return result; - } else { if (this.isNotChanged()) { - this.logger.info('输入参数未变更,跳过'); + this.logger.info("输入参数未变更,跳过"); return "skip"; } - + if (!this.domainName) { - throw new Error('您还未选择DCDN域名'); + throw new Error("您还未选择DCDN域名"); } let domains: string[] = []; - domains = typeof this.domainName === 'string' ? [this.domainName] : this.domainName; + domains = typeof this.domainName === "string" ? [this.domainName] : this.domainName; const aliCrtId = await sslClient.uploadCertOrGet(this.cert); for (const domainName of domains) { await this.deployOne(client, domainName, aliCrtId); } } - - this.logger.info('部署完成'); + this.logger.info("部署完成"); } async deployOne(client: any, domainName: string, aliCrtId: CasCertId) { - this.logger.info(`[${domainName}]开始部署`) + this.logger.info(`[${domainName}]开始部署`); const params = await this.buildParams(domainName, aliCrtId); await this.doRequest(client, params); await this.ctx.utils.sleep(1000); - this.logger.info(`[${domainName}]部署成功`) + this.logger.info(`[${domainName}]部署成功`); } async getClient(access: AliyunAccess) { @@ -155,20 +147,20 @@ export class DeployCertToAliyunDCDN extends AbstractTaskPlugin { await client.init({ accessKeyId: access.accessKeyId, accessKeySecret: access.accessKeySecret, - endpoint: 'https://dcdn.aliyuncs.com', - apiVersion: '2018-01-15', + endpoint: "https://dcdn.aliyuncs.com", + apiVersion: "2018-01-15", }); return client; } async buildParams(domainName: string, aliCrtId: CasCertId) { - const CertName = (this.certName ?? 'certd') + '-' + dayjs().format('YYYYMMDDHHmmss'); + const CertName = (this.certName ?? "certd") + "-" + dayjs().format("YYYYMMDDHHmmss"); const certId = aliCrtId.certId; - this.logger.info('使用已上传的证书:', certId); + this.logger.info("使用已上传的证书:", certId); return { DomainName: domainName, - SSLProtocol: 'on', - CertType: 'cas', + SSLProtocol: "on", + CertType: "cas", CertName: CertName, CertId: certId, }; @@ -176,42 +168,41 @@ export class DeployCertToAliyunDCDN extends AbstractTaskPlugin { async doRequest(client: any, params: any) { const requestOption = { - method: 'POST', + method: "POST", formatParams: false, }; - const ret: any = await client.request('SetDcdnDomainSSLCertificate', params, requestOption); + const ret: any = await client.request("SetDcdnDomainSSLCertificate", params, requestOption); this.checkRet(ret); - this.logger.info('设置Dcdn证书成功:', ret.RequestId); + this.logger.info("设置Dcdn证书成功:", ret.RequestId); } checkRet(ret: any) { if (ret.Code != null) { - throw new Error('执行失败:' + ret.Message); + throw new Error("执行失败:" + ret.Message); } } - - async onGetDomainList(data: PageSearch): Promise<{ list: CertTargetItem[], total: number }> { + async onGetDomainList(data: PageSearch): Promise<{ list: CertTargetItem[]; total: number }> { if (!this.accessId) { - throw new Error('请选择Access授权'); + throw new Error("请选择Access授权"); } const access = await this.getAccess(this.accessId); const client = await this.getClient(access); - const pager = new Pager(data) + const pager = new Pager(data); const params = { DomainName: data.searchKey, PageSize: pager.pageSize || 200, PageNumber: pager.pageNo || 1, - DomainSearchType: "fuzzy_match" + DomainSearchType: "fuzzy_match", }; const requestOption = { - method: 'POST', + method: "POST", formatParams: false, }; - const res = await client.request('DescribeDcdnUserDomains', params, requestOption); + const res = await client.request("DescribeDcdnUserDomains", params, requestOption); this.checkRet(res); const pageData = res?.Domains?.PageData || []; const total = res?.TotalCount || 0; diff --git a/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-esa/index.ts b/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-esa/index.ts index c5e657825..c72c1acdf 100644 --- a/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-esa/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-esa/index.ts @@ -1,9 +1,6 @@ import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; import { CertApplyPluginNames, CertInfo, CertReader } from "@certd/plugin-cert"; -import { - createCertDomainGetterInputDefine, - createRemoteSelectInputDefine -} from "@certd/plugin-lib"; +import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from "@certd/plugin-lib"; import { AliyunAccess } from "../../../plugin-lib/aliyun/access/index.js"; import { AliyunSslClient, CasCertId } from "../../../plugin-lib/aliyun/lib/ssl-client.js"; import { AliyunClientV2 } from "../../../plugin-lib/aliyun/lib/aliyun-client-v2.js"; @@ -18,9 +15,9 @@ import dayjs from "dayjs"; needPlus: false, default: { strategy: { - runStrategy: RunStrategy.SkipWhenSucceed - } - } + runStrategy: RunStrategy.SkipWhenSucceed, + }, + }, }) export class AliyunDeployCertToESA extends AbstractTaskPlugin { @TaskInput({ @@ -28,9 +25,9 @@ export class AliyunDeployCertToESA extends AbstractTaskPlugin { helper: "请选择证书申请任务输出的域名证书", component: { name: "output-selector", - from: [...CertApplyPluginNames, 'uploadCertToAliyun'] + from: [...CertApplyPluginNames, "uploadCertToAliyun"], }, - required: true + required: true, }) cert!: CertInfo | CasCertId | number; @@ -45,10 +42,10 @@ export class AliyunDeployCertToESA extends AbstractTaskPlugin { vModel: "value", options: [ { value: "cn-hangzhou", label: "华东1(杭州)" }, - { value: "ap-southeast-1", label: "新加坡" } - ] + { value: "ap-southeast-1", label: "新加坡" }, + ], }, - required: true + required: true, }) regionId!: string; @@ -60,23 +57,22 @@ export class AliyunDeployCertToESA extends AbstractTaskPlugin { name: "a-select", options: [ { value: "cas.aliyuncs.com", label: "中国大陆" }, - { value: "cas.ap-southeast-1.aliyuncs.com", label: "新加坡" } + { value: "cas.ap-southeast-1.aliyuncs.com", label: "新加坡" }, // { value: "cas.eu-central-1.aliyuncs.com", label: "德国(法兰克福)" } - ] + ], }, - required: true + required: true, }) casEndpoint!: string; - @TaskInput({ title: "Access授权", helper: "阿里云授权AccessKeyId、AccessKeySecret", component: { name: "access-selector", - type: "aliyun" + type: "aliyun", }, - required: true + required: true, }) accessId!: string; @@ -85,7 +81,7 @@ export class AliyunDeployCertToESA extends AbstractTaskPlugin { title: "站点", helper: "请选择要部署证书的站点", action: AliyunDeployCertToESA.prototype.onGetSiteList.name, - watches: ["accessId", "regionId"] + watches: ["accessId", "regionId"], }) ) siteIds!: string[]; @@ -95,15 +91,14 @@ export class AliyunDeployCertToESA extends AbstractTaskPlugin { value: 2, component: { name: "a-input-number", - vModel: "value" + vModel: "value", }, helper: "将检查证书数量限制,如果超限将删除最旧的那张证书", - required: true + required: true, }) - certLimit: number = 2; + certLimit = 2; - async onInstance() { - } + async onInstance() {} async getAliyunCertId(access: AliyunAccess) { let certId: any = this.cert; @@ -112,7 +107,7 @@ export class AliyunDeployCertToESA extends AbstractTaskPlugin { const sslClient = new AliyunSslClient({ access, logger: this.logger, - endpoint: this.casEndpoint + endpoint: this.casEndpoint, }); const certInfo = this.cert as CertInfo; @@ -121,21 +116,21 @@ export class AliyunDeployCertToESA extends AbstractTaskPlugin { certId = casCert.certId; certName = casCert.certName; } else if (certInfo.crt) { - certName = this.buildCertName(CertReader.getMainDomain(certInfo.crt),"certd"); + certName = this.buildCertName(CertReader.getMainDomain(certInfo.crt), "certd"); const certIdRes = await sslClient.uploadCertificate({ name: certName, - cert: certInfo + cert: certInfo, }); certId = certIdRes.certId as any; this.logger.info("上传证书成功", certId, certName); - }else{ - throw new Error('证书格式错误'+JSON.stringify(this.cert)); + } else { + throw new Error("证书格式错误" + JSON.stringify(this.cert)); } } return { certId, - certName + certName, }; } @@ -160,12 +155,11 @@ export class AliyunDeployCertToESA extends AbstractTaskPlugin { SiteId: siteId, CasId: certId, Type: "cas", - Name: certName - } - } + Name: certName, + }, + }, }); this.logger.info(`部署站点[${siteId}]证书成功:${JSON.stringify(res)}`); - } catch (e) { if (e.message.includes("Certificate.Duplicated")) { this.logger.info(`站点[${siteId}]证书已存在,无需重复部署`); @@ -176,13 +170,12 @@ export class AliyunDeployCertToESA extends AbstractTaskPlugin { try { await this.clearSiteExpiredCert(client, siteId); } catch (e) { - this.logger.error(`清理站点[${siteId}]过期证书失败`, e) + this.logger.error(`清理站点[${siteId}]过期证书失败`, e); } } } } - async getClient(access: AliyunAccess) { const endpoint = `esa.${this.regionId}.aliyuncs.com`; return access.getClient(endpoint); @@ -199,7 +192,7 @@ export class AliyunDeployCertToESA extends AbstractTaskPlugin { action: "ListSites", version: "2024-09-10", method: "GET", - data: {} + data: {}, }); const list = res?.Sites; @@ -211,7 +204,7 @@ export class AliyunDeployCertToESA extends AbstractTaskPlugin { return { label: item.SiteName, value: item.SiteId, - domain: item.SiteName + domain: item.SiteName, }; }); return this.ctx.utils.options.buildGroupOptions(options, this.certDomains); @@ -226,9 +219,9 @@ export class AliyunDeployCertToESA extends AbstractTaskPlugin { data: { query: { SiteId: siteId, - PageSize: 100 - } - } + PageSize: 100, + }, + }, }); const list = certListRes.Result; @@ -245,21 +238,19 @@ export class AliyunDeployCertToESA extends AbstractTaskPlugin { data: { query: { SiteId: siteId, - Id: item.id - } - } + Id: item.id, + }, + }, }); this.logger.info(`证书${item.Name}已删除`); } catch (e) { - this.logger.error(`过期证书${item.Name}删除失败:`, e.message) + this.logger.error(`过期证书${item.Name}删除失败:`, e.message); } } } } - async clearSiteLimitCert(client: AliyunClientV2, siteId: string) { - //删除最旧的证书 const certLimit = this.certLimit || 2; this.logger.info(`站点[${siteId}]证书数量检查,当前限制${certLimit}`); @@ -270,31 +261,31 @@ export class AliyunDeployCertToESA extends AbstractTaskPlugin { data: { query: { SiteId: siteId, - PageSize: 100 - } - } + PageSize: 100, + }, + }, }); let list = certListRes.Result || []; list = list.filter((item: any) => item.Type === "cas"); if (!list || list.length === 0) { this.logger.info(`站点[${siteId}]没有CAS证书, 无需删除`); - return + return; } - + if (list.length < certLimit) { this.logger.info(`站点[${siteId}]证书数量(${list.length})未超限制, 无需删除`); return; } this.logger.info(`站点[${siteId}]证书数量(${list.length})已超限制, 开始删除最旧的证书`); - let oldly:any = null; + let oldly: any = null; for (const item of list) { if (!oldly) { oldly = item; continue; } - if (dayjs(item.CreateTime).valueOf() < (dayjs(oldly.CreateTime)).valueOf()){ + if (dayjs(item.CreateTime).valueOf() < dayjs(oldly.CreateTime).valueOf()) { oldly = item; } } @@ -306,9 +297,9 @@ export class AliyunDeployCertToESA extends AbstractTaskPlugin { data: { query: { SiteId: siteId, - Id: oldly.Id - } - } + Id: oldly.Id, + }, + }, }); this.logger.info(`最旧证书${oldly.Name}已删除`); } diff --git a/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-fc/index.ts b/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-fc/index.ts index a372c272f..6540681ad 100644 --- a/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-fc/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-fc/index.ts @@ -1,6 +1,6 @@ import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; import { CertApplyPluginNames, CertInfo, CertReader } from "@certd/plugin-cert"; -import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from "@certd/plugin-lib"; +import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from "@certd/plugin-lib"; import fs from "fs"; import path from "path"; import { tmpdir } from "node:os"; @@ -8,11 +8,11 @@ import { sp } from "@certd/basic"; import { AliyunAccess } from "../../../plugin-lib/aliyun/access/index.js"; @IsTaskPlugin({ - name: 'AliyunDeployCertToFC', - title: '阿里云-部署至阿里云FC(3.0)', - icon: 'svg:icon-aliyun', + name: "AliyunDeployCertToFC", + title: "阿里云-部署至阿里云FC(3.0)", + icon: "svg:icon-aliyun", group: pluginGroups.aliyun.key, - desc: '部署证书到阿里云函数计算(FC3.0)', + desc: "部署证书到阿里云函数计算(FC3.0)", needPlus: false, default: { strategy: { @@ -22,10 +22,10 @@ import { AliyunAccess } from "../../../plugin-lib/aliyun/access/index.js"; }) export class AliyunDeployCertToFC extends AbstractTaskPlugin { @TaskInput({ - title: '域名证书', - helper: '请选择证书申请任务输出的域名证书', + title: "域名证书", + helper: "请选择证书申请任务输出的域名证书", component: { - name: 'output-selector', + name: "output-selector", from: [...CertApplyPluginNames], }, required: true, @@ -36,56 +36,55 @@ export class AliyunDeployCertToFC extends AbstractTaskPlugin { certDomains!: string[]; @TaskInput({ - title: 'FC大区', - value: 'cn-hangzhou', + title: "FC大区", + value: "cn-hangzhou", component: { - name: 'a-auto-complete', - vModel: 'value', + name: "a-auto-complete", + vModel: "value", options: [ - { value: 'cn-qingdao', label: '华北1(青岛)' }, - { value: 'cn-beijing', label: '华北2(北京)' }, - { value: 'cn-zhangjiakou', label: '华北 3(张家口)' }, - { value: 'cn-huhehaote', label: '华北5(呼和浩特)' }, - { value: 'cn-hangzhou', label: '华东1(杭州)' }, - { value: 'cn-shanghai', label: '华东2(上海)' }, - { value: 'cn-shenzhen', label: '华南1(深圳)' }, - { value: 'ap-southeast-2', label: '澳大利亚(悉尼)' }, - { value: 'eu-central-1', label: '德国(法兰克福)' }, - { value: 'ap-southeast-3', label: '马来西亚(吉隆坡)' }, - { value: 'us-east-1', label: '美国(弗吉尼亚)' }, - { value: 'us-west-1', label: '美国(硅谷)' }, - { value: 'ap-northeast-1', label: '日本(东京)' }, - { value: 'ap-southeast-7', label: '泰国(曼谷)' }, - { value: 'cn-chengdu', label: '西南1(成都)' }, - { value: 'ap-southeast-1', label: '新加坡' }, - { value: 'ap-south-1', label: '印度(孟买)' }, - { value: 'ap-southeast-5', label: '印度尼西亚(雅加达)' }, - { value: 'eu-west-1', label: '英国(伦敦)' }, - { value: 'cn-hongkong', label: '中国香港' }, + { value: "cn-qingdao", label: "华北1(青岛)" }, + { value: "cn-beijing", label: "华北2(北京)" }, + { value: "cn-zhangjiakou", label: "华北 3(张家口)" }, + { value: "cn-huhehaote", label: "华北5(呼和浩特)" }, + { value: "cn-hangzhou", label: "华东1(杭州)" }, + { value: "cn-shanghai", label: "华东2(上海)" }, + { value: "cn-shenzhen", label: "华南1(深圳)" }, + { value: "ap-southeast-2", label: "澳大利亚(悉尼)" }, + { value: "eu-central-1", label: "德国(法兰克福)" }, + { value: "ap-southeast-3", label: "马来西亚(吉隆坡)" }, + { value: "us-east-1", label: "美国(弗吉尼亚)" }, + { value: "us-west-1", label: "美国(硅谷)" }, + { value: "ap-northeast-1", label: "日本(东京)" }, + { value: "ap-southeast-7", label: "泰国(曼谷)" }, + { value: "cn-chengdu", label: "西南1(成都)" }, + { value: "ap-southeast-1", label: "新加坡" }, + { value: "ap-south-1", label: "印度(孟买)" }, + { value: "ap-southeast-5", label: "印度尼西亚(雅加达)" }, + { value: "eu-west-1", label: "英国(伦敦)" }, + { value: "cn-hongkong", label: "中国香港" }, ], }, required: true, }) regionId!: string; - @TaskInput({ - title: '阿里云账号id', - helper: '阿里云主账号ID,右上角头像下方获取', + title: "阿里云账号id", + helper: "阿里云主账号ID,右上角头像下方获取", component: { - name: 'a-input', - vModel:"value" + name: "a-input", + vModel: "value", }, required: true, }) accountId!: string; @TaskInput({ - title: 'Access授权', - helper: '阿里云授权AccessKeyId、AccessKeySecret', + title: "Access授权", + helper: "阿里云授权AccessKeyId、AccessKeySecret", component: { - name: 'access-selector', - type: 'aliyun', + name: "access-selector", + type: "aliyun", }, required: true, }) @@ -93,33 +92,33 @@ export class AliyunDeployCertToFC extends AbstractTaskPlugin { @TaskInput( createRemoteSelectInputDefine({ - title: 'FC域名', + title: "FC域名", helper: "请选择要部署证书的域名", - typeName: 'AliyunDeployCertToFC', + typeName: "AliyunDeployCertToFC", action: AliyunDeployCertToFC.prototype.onGetDomainList.name, - watches: ['accessId', 'regionId'], + watches: ["accessId", "regionId"], }) ) fcDomains!: string[]; @TaskInput({ - title: '域名支持的协议类型', - value: '', + title: "域名支持的协议类型", + value: "", component: { - name: 'a-select', - vModel:"value", + name: "a-select", + vModel: "value", options: [ - { value: '', label: '保持原样(适用于原来已经开启了HTTPS)' }, - { value: 'HTTPS', label: '仅HTTPS' }, - { value: 'HTTP,HTTPS', label: 'HTTP与HTTPS同时支持' }, + { value: "", label: "保持原样(适用于原来已经开启了HTTPS)" }, + { value: "HTTPS", label: "仅HTTPS" }, + { value: "HTTP,HTTPS", label: "HTTP与HTTPS同时支持" }, ], }, }) protocol!: string; @TaskInput({ - title: '证书名称', - helper: '上传后将以此名称作为前缀备注', + title: "证书名称", + helper: "上传后将以此名称作为前缀备注", }) certName!: string; @@ -133,17 +132,16 @@ export class AliyunDeployCertToFC extends AbstractTaskPlugin { }); } async execute(): Promise { - this.logger.info('开始部署证书到阿里云'); + this.logger.info("开始部署证书到阿里云"); const access = await this.getAccess(this.accessId); const client = await this.getClient(access); - const $Util = await import('@alicloud/tea-util'); - const $OpenApi = await import('@alicloud/openapi-client'); + const $Util = await import("@alicloud/tea-util"); + const $OpenApi = await import("@alicloud/openapi-client"); - - let privateKey = this.cert.key - try{ + let privateKey = this.cert.key; + try { // openssl rsa -in private_key.pem -out private_key_pkcs1.pem const tempDir = path.join(tmpdir(), "certd"); if (!fs.existsSync(tempDir)) { @@ -151,7 +149,7 @@ export class AliyunDeployCertToFC extends AbstractTaskPlugin { } const keyFileName = this.ctx.utils.id.randomNumber(10); const tempPem = `${tempDir}/${keyFileName}.pem`; - const tempPkcs1Pem =`${tempDir}/${keyFileName}_pkcs1.pem`; + const tempPkcs1Pem = `${tempDir}/${keyFileName}_pkcs1.pem`; fs.writeFileSync(tempPem, this.cert.key); const oldPfxCmd = `openssl rsa -in ${tempPem} -traditional -out ${tempPkcs1Pem}`; await this.exec(oldPfxCmd); @@ -159,34 +157,31 @@ export class AliyunDeployCertToFC extends AbstractTaskPlugin { privateKey = fileBuffer.toString(); fs.unlinkSync(tempPem); fs.unlinkSync(tempPkcs1Pem); - }catch (e) { - this.logger.warn("私钥转换为PKCS#1格式失败",e); + } catch (e) { + this.logger.warn("私钥转换为PKCS#1格式失败", e); } - - - for (const domainName of this.fcDomains) { const params = new $OpenApi.Params({ // 接口名称 - action: 'UpdateCustomDomain', + action: "UpdateCustomDomain", // 接口版本 - version: '2023-03-30', + version: "2023-03-30", // 接口协议 - protocol: 'HTTPS', + protocol: "HTTPS", // 接口 HTTP 方法 - method: 'PUT', - authType: 'AK', - style: 'FC', + method: "PUT", + authType: "AK", + style: "FC", // 接口 PATH pathname: `/2023-03-30/custom-domains/${domainName}`, // 接口请求体内容格式 - reqBodyType: 'json', + reqBodyType: "json", // 接口响应体内容格式 - bodyType: 'json', + bodyType: "json", }); // body params - const certName = this.buildCertName(CertReader.getMainDomain(this.cert.crt),this.certName??"") + const certName = this.buildCertName(CertReader.getMainDomain(this.cert.crt), this.certName ?? ""); const body: { [key: string]: any } = { certConfig: { @@ -209,7 +204,7 @@ export class AliyunDeployCertToFC extends AbstractTaskPlugin { } async getClient(access: AliyunAccess) { - const $OpenApi = await import('@alicloud/openapi-client'); + const $OpenApi = await import("@alicloud/openapi-client"); const config = new $OpenApi.Config({ accessKeyId: access.accessKeyId, accessKeySecret: access.accessKeySecret, @@ -221,30 +216,30 @@ export class AliyunDeployCertToFC extends AbstractTaskPlugin { async onGetDomainList(data: any) { if (!this.accessId) { - throw new Error('请选择Access授权'); + throw new Error("请选择Access授权"); } const access = await this.getAccess(this.accessId); const client = await this.getClient(access); - const $OpenApi = await import('@alicloud/openapi-client'); - const $Util = await import('@alicloud/tea-util'); + const $OpenApi = await import("@alicloud/openapi-client"); + const $Util = await import("@alicloud/tea-util"); const params = new $OpenApi.Params({ // 接口名称 - action: 'ListCustomDomains', + action: "ListCustomDomains", // 接口版本 - version: '2023-03-30', + version: "2023-03-30", // 接口协议 - protocol: 'HTTPS', + protocol: "HTTPS", // 接口 HTTP 方法 - method: 'GET', - authType: 'AK', - style: 'FC', + method: "GET", + authType: "AK", + style: "FC", // 接口 PATH pathname: `/2023-03-30/custom-domains`, // 接口请求体内容格式 - reqBodyType: 'json', + reqBodyType: "json", // 接口响应体内容格式 - bodyType: 'json', + bodyType: "json", }); const runtime = new $Util.RuntimeOptions({}); @@ -255,7 +250,7 @@ export class AliyunDeployCertToFC extends AbstractTaskPlugin { const list = res?.body?.customDomains; if (!list || list.length === 0) { - throw new Error('没有找到FC域名,请先创建FC域名'); + throw new Error("没有找到FC域名,请先创建FC域名"); } const options = list.map((item: any) => { diff --git a/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-ga/index.ts b/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-ga/index.ts index f5be0dcfc..545a8c908 100644 --- a/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-ga/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-ga/index.ts @@ -1,9 +1,6 @@ import { AbstractTaskPlugin, IsTaskPlugin, Pager, PageSearch, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; import { CertApplyPluginNames, CertInfo } from "@certd/plugin-cert"; -import { - createCertDomainGetterInputDefine, - createRemoteSelectInputDefine -} from "@certd/plugin-lib"; +import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from "@certd/plugin-lib"; import { AliyunAccess } from "../../../plugin-lib/aliyun/access/index.js"; import { AliyunSslClient, CasCertId } from "../../../plugin-lib/aliyun/lib/ssl-client.js"; @@ -16,9 +13,9 @@ import { AliyunSslClient, CasCertId } from "../../../plugin-lib/aliyun/lib/ssl-c needPlus: false, default: { strategy: { - runStrategy: RunStrategy.SkipWhenSucceed - } - } + runStrategy: RunStrategy.SkipWhenSucceed, + }, + }, }) export class AliyunDeployCertToGA extends AbstractTaskPlugin { @TaskInput({ @@ -26,11 +23,11 @@ export class AliyunDeployCertToGA extends AbstractTaskPlugin { helper: "请选择证书申请任务输出的域名证书", component: { name: "output-selector", - from: [...CertApplyPluginNames, 'uploadCertToAliyun'] + from: [...CertApplyPluginNames, "uploadCertToAliyun"], }, - required: true + required: true, }) - cert!: CertInfo|number | CasCertId; + cert!: CertInfo | number | CasCertId; @TaskInput(createCertDomainGetterInputDefine({ props: { required: false } })) certDomains!: string[]; @@ -43,10 +40,10 @@ export class AliyunDeployCertToGA extends AbstractTaskPlugin { name: "a-select", options: [ { value: "cas.aliyuncs.com", label: "中国大陆" }, - { value: "cas.ap-southeast-1.aliyuncs.com", label: "新加坡" } - ] + { value: "cas.ap-southeast-1.aliyuncs.com", label: "新加坡" }, + ], }, - required: true + required: true, }) casEndpoint!: string; @@ -55,9 +52,9 @@ export class AliyunDeployCertToGA extends AbstractTaskPlugin { helper: "阿里云授权AccessKeyId、AccessKeySecret", component: { name: "access-selector", - type: "aliyun" + type: "aliyun", }, - required: true + required: true, }) accessId!: string; @@ -77,7 +74,7 @@ export class AliyunDeployCertToGA extends AbstractTaskPlugin { title: "监听", helper: "请选择要部署证书的监听", action: AliyunDeployCertToGA.prototype.onGetListenerList.name, - watches: ["accessId", "acceleratorId"] + watches: ["accessId", "acceleratorId"], }) ) listenerIds!: string[]; @@ -90,8 +87,8 @@ export class AliyunDeployCertToGA extends AbstractTaskPlugin { name: "a-select", options: [ { value: "default", label: "默认证书" }, - { value: "additional", label: "扩展证书" } - ] + { value: "additional", label: "扩展证书" }, + ], }, required: true, }) @@ -109,21 +106,20 @@ export class AliyunDeployCertToGA extends AbstractTaskPlugin { return form.certType === "additional"; }) } - ` + `, }) ) additionalDomains!: string[]; - async onInstance() { - } + async onInstance() {} async getAliyunCertId(access: AliyunAccess) { const sslClient = new AliyunSslClient({ access, logger: this.logger, - endpoint: this.casEndpoint + endpoint: this.casEndpoint, }); - return await sslClient.uploadCertOrGet(this.cert as any) + return await sslClient.uploadCertOrGet(this.cert as any); } async execute(): Promise { @@ -133,7 +129,7 @@ export class AliyunDeployCertToGA extends AbstractTaskPlugin { const client = await this.getClient(access); const { certIdentifier } = await this.getAliyunCertId(access); - + for (const listenerId of this.listenerIds) { if (this.certType === "default") { // 更新默认证书 @@ -146,11 +142,9 @@ export class AliyunDeployCertToGA extends AbstractTaskPlugin { RegionId: "cn-hangzhou", AcceleratorId: this.acceleratorId, ListenerId: listenerId, - Certificates: [ - { Id: certIdentifier}, - ] - } - } + Certificates: [{ Id: certIdentifier }], + }, + }, }); this.logger.info(`部署默认证书到实例[${this.acceleratorId}]监听[${listenerId}]成功:${JSON.stringify(res)}`); } else if (this.certType === "additional") { @@ -166,14 +160,12 @@ export class AliyunDeployCertToGA extends AbstractTaskPlugin { query: { RegionId: "cn-hangzhou", AcceleratorId: this.acceleratorId, - ListenerId: listenerId - } - } + ListenerId: listenerId, + }, + }, }); - const domainExists = existingCerts.Certificates?.some((cert: any) => - cert.Domain === domain - ); + const domainExists = existingCerts.Certificates?.some((cert: any) => cert.Domain === domain); if (domainExists) { // 更新扩展证书 @@ -187,9 +179,9 @@ export class AliyunDeployCertToGA extends AbstractTaskPlugin { AcceleratorId: this.acceleratorId, ListenerId: listenerId, Domain: domain, - CertificateId: certIdentifier - } - } + CertificateId: certIdentifier, + }, + }, }); this.logger.info(`更新扩展证书到实例[${this.acceleratorId}]监听[${listenerId}]域名[${domain}]成功:${JSON.stringify(res)}`); } else { @@ -203,12 +195,14 @@ export class AliyunDeployCertToGA extends AbstractTaskPlugin { RegionId: "cn-hangzhou", AcceleratorId: this.acceleratorId, ListenerId: listenerId, - Certificates: [{ - Id: certIdentifier, - Domain: domain - }] - } - } + Certificates: [ + { + Id: certIdentifier, + Domain: domain, + }, + ], + }, + }, }); this.logger.info(`新增扩展证书绑定到实例[${this.acceleratorId}]监听[${listenerId}]域名[${domain}]成功:${JSON.stringify(res)}`); } @@ -228,8 +222,8 @@ export class AliyunDeployCertToGA extends AbstractTaskPlugin { throw new Error("请选择Access授权"); } - const pager = new Pager(data) - pager.pageSize = 50 + const pager = new Pager(data); + pager.pageSize = 50; const access = await this.getAccess(this.accessId); const client = await this.getClient(access); @@ -242,9 +236,9 @@ export class AliyunDeployCertToGA extends AbstractTaskPlugin { RegionId: "cn-hangzhou", PageNumber: pager.pageNo, PageSize: pager.pageSize, - State: "active" - } - } + State: "active", + }, + }, }); const list = res?.Accelerators; @@ -253,7 +247,7 @@ export class AliyunDeployCertToGA extends AbstractTaskPlugin { } const options = list.map((item: any) => { - const label = `${item.Name} (${item.AcceleratorId})` + const label = `${item.Name} (${item.AcceleratorId})`; return { label: label, value: item.AcceleratorId, @@ -279,9 +273,9 @@ export class AliyunDeployCertToGA extends AbstractTaskPlugin { data: { query: { RegionId: "cn-hangzhou", - AcceleratorId: this.acceleratorId - } - } + AcceleratorId: this.acceleratorId, + }, + }, }); const listeners = res?.Listeners; @@ -327,4 +321,4 @@ export class AliyunDeployCertToGA extends AbstractTaskPlugin { } } -new AliyunDeployCertToGA(); \ No newline at end of file +new AliyunDeployCertToGA(); diff --git a/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-live/index.ts b/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-live/index.ts index 8e5f1bbf4..305979e3e 100644 --- a/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-live/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-live/index.ts @@ -1,15 +1,15 @@ -import { AbstractTaskPlugin, IsTaskPlugin, PageSearch, pluginGroups, RunStrategy, TaskInput } from '@certd/pipeline'; -import { CertApplyPluginNames } from '@certd/plugin-cert'; -import { CertInfo, createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from '@certd/plugin-lib'; -import { AliyunAccess } from '../../../plugin-lib/aliyun/access/index.js'; -import { AliyunSslClient, CasCertId } from '../../../plugin-lib/aliyun/lib/index.js'; +import { AbstractTaskPlugin, IsTaskPlugin, PageSearch, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; +import { CertApplyPluginNames } from "@certd/plugin-cert"; +import { CertInfo, createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from "@certd/plugin-lib"; +import { AliyunAccess } from "../../../plugin-lib/aliyun/access/index.js"; +import { AliyunSslClient, CasCertId } from "../../../plugin-lib/aliyun/lib/index.js"; @IsTaskPlugin({ - name: 'DeployCertToAliyunLive', - title: '阿里云-部署至直播(Live)', - icon: 'svg:icon-aliyun', + name: "DeployCertToAliyunLive", + title: "阿里云-部署至直播(Live)", + icon: "svg:icon-aliyun", group: pluginGroups.aliyun.key, - desc: '部署证书到阿里云视频直播(Live)域名', + desc: "部署证书到阿里云视频直播(Live)域名", needPlus: false, default: { strategy: { @@ -18,14 +18,12 @@ import { AliyunSslClient, CasCertId } from '../../../plugin-lib/aliyun/lib/index }, }) export class DeployCertToAliyunLive extends AbstractTaskPlugin { - - @TaskInput({ - title: '域名证书', - helper: '请选择前置任务输出的域名证书', + title: "域名证书", + helper: "请选择前置任务输出的域名证书", component: { - name: 'output-selector', - from: [...CertApplyPluginNames, 'uploadCertToAliyun'], + name: "output-selector", + from: [...CertApplyPluginNames, "uploadCertToAliyun"], }, template: false, required: true, @@ -35,28 +33,27 @@ export class DeployCertToAliyunLive extends AbstractTaskPlugin { @TaskInput(createCertDomainGetterInputDefine({ props: { required: false } })) certDomains!: string[]; - @TaskInput({ - title: 'Access授权', - helper: '阿里云授权AccessKeyId、AccessKeySecret', + title: "Access授权", + helper: "阿里云授权AccessKeyId、AccessKeySecret", component: { - name: 'access-selector', - type: 'aliyun', + name: "access-selector", + type: "aliyun", }, required: true, }) accessId!: string; @TaskInput({ - title: '证书服务接入点', - helper: '不会选就按默认', - value: 'cas.aliyuncs.com', + title: "证书服务接入点", + helper: "不会选就按默认", + value: "cas.aliyuncs.com", component: { - name: 'a-select', + name: "a-select", options: [ - { value: 'cas.aliyuncs.com', label: '中国大陆' }, - { value: 'cas.ap-southeast-1.aliyuncs.com', label: '新加坡' }, - { value: 'cas.eu-central-1.aliyuncs.com', label: '德国(法兰克福)' }, + { value: "cas.aliyuncs.com", label: "中国大陆" }, + { value: "cas.ap-southeast-1.aliyuncs.com", label: "新加坡" }, + { value: "cas.eu-central-1.aliyuncs.com", label: "德国(法兰克福)" }, ], }, required: true, @@ -65,11 +62,11 @@ export class DeployCertToAliyunLive extends AbstractTaskPlugin { @TaskInput( createRemoteSelectInputDefine({ - title: '直播域名', - helper: '请选择要部署证书的直播域名', - typeName: 'DeployCertToAliyunLive', + title: "直播域名", + helper: "请选择要部署证书的直播域名", + typeName: "DeployCertToAliyunLive", action: DeployCertToAliyunLive.prototype.onGetDomainList.name, - watches: ['certDomains', 'accessId'], + watches: ["certDomains", "accessId"], pager: true, search: true, }) @@ -79,18 +76,18 @@ export class DeployCertToAliyunLive extends AbstractTaskPlugin { async onInstance() {} async execute(): Promise { - this.logger.info('开始部署证书到阿里云直播'); + this.logger.info("开始部署证书到阿里云直播"); const access = await this.getAccess(this.accessId); if (this.cert == null) { - throw new Error('域名证书参数为空,请检查前置任务'); + throw new Error("域名证书参数为空,请检查前置任务"); } const client = await this.getClient(access); const sslClient = new AliyunSslClient({ access, logger: this.logger, - endpoint: this.endpoint || 'cas.aliyuncs.com', + endpoint: this.endpoint || "cas.aliyuncs.com", }); // 确保证书已上传到 CAS,统一使用 cas 方式部署 @@ -98,39 +95,39 @@ export class DeployCertToAliyunLive extends AbstractTaskPlugin { // const certName = this.appendTimeSuffix(this.certName || casCert.certName); for (const domain of this.domainList) { const res = await client.doRequest({ - action: 'SetLiveDomainCertificate', - version: '2016-11-01', - protocol: 'HTTPS', + action: "SetLiveDomainCertificate", + version: "2016-11-01", + protocol: "HTTPS", data: { query: { DomainName: domain, CertName: casCert.certName, - CertType: 'cas', - SSLProtocol: 'on', + CertType: "cas", + SSLProtocol: "on", CertId: casCert.certId, }, }, }); - this.logger.info('部署直播域名[' + domain + ']证书成功:' + JSON.stringify(res)); + this.logger.info("部署直播域名[" + domain + "]证书成功:" + JSON.stringify(res)); } } async getClient(access: AliyunAccess) { - const endpoint = 'live.aliyuncs.com'; + const endpoint = "live.aliyuncs.com"; return access.getClient(endpoint); } async onGetDomainList(data: PageSearch) { if (!this.accessId) { - throw new Error('请选择Access授权'); + throw new Error("请选择Access授权"); } const access = await this.getAccess(this.accessId); const client = await this.getClient(access); const res = await client.doRequest({ - action: 'DescribeLiveUserDomains', - version: '2016-11-01', - protocol: 'HTTPS', + action: "DescribeLiveUserDomains", + version: "2016-11-01", + protocol: "HTTPS", data: { query: { DomainName: data.searchKey || undefined, @@ -142,7 +139,7 @@ export class DeployCertToAliyunLive extends AbstractTaskPlugin { const list = res?.Domains?.PageData; if (!list || list.length === 0) { - throw new Error('没有找到直播域名,请先在阿里云添加直播域名'); + throw new Error("没有找到直播域名,请先在阿里云添加直播域名"); } const options = list.map((item: any) => { diff --git a/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-nlb/index.ts b/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-nlb/index.ts index 119214e70..27d6c8610 100644 --- a/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-nlb/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-nlb/index.ts @@ -1,19 +1,16 @@ -import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from '@certd/pipeline'; +import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; import { CertInfo, CertReader } from "@certd/plugin-cert"; -import { - createCertDomainGetterInputDefine, - createRemoteSelectInputDefine -} from "@certd/plugin-lib"; -import { CertApplyPluginNames} from '@certd/plugin-cert'; +import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from "@certd/plugin-lib"; +import { CertApplyPluginNames } from "@certd/plugin-cert"; import { AliyunAccess } from "../../../plugin-lib/aliyun/access/index.js"; import { AliyunClient, AliyunSslClient, CasCertId } from "../../../plugin-lib/aliyun/lib/index.js"; -import { AliyunClientV2 } from '../../../plugin-lib/aliyun/lib/aliyun-client-v2.js'; +import { AliyunClientV2 } from "../../../plugin-lib/aliyun/lib/aliyun-client-v2.js"; @IsTaskPlugin({ - name: 'AliyunDeployCertToNLB', - title: '阿里云-部署至NLB(网络负载均衡)', - icon: 'svg:icon-aliyun', + name: "AliyunDeployCertToNLB", + title: "阿里云-部署至NLB(网络负载均衡)", + icon: "svg:icon-aliyun", group: pluginGroups.aliyun.key, - desc: 'NLB,网络负载均衡,更新监听器的默认证书', + desc: "NLB,网络负载均衡,更新监听器的默认证书", needPlus: false, default: { strategy: { @@ -23,11 +20,11 @@ import { AliyunClientV2 } from '../../../plugin-lib/aliyun/lib/aliyun-client-v2. }) export class AliyunDeployCertToNLB extends AbstractTaskPlugin { @TaskInput({ - title: '域名证书', - helper: '请选择证书申请任务输出的域名证书\n或者选择前置任务“上传证书到阿里云”任务的证书ID,可以减少上传到阿里云的证书数量', + title: "域名证书", + helper: "请选择证书申请任务输出的域名证书\n或者选择前置任务“上传证书到阿里云”任务的证书ID,可以减少上传到阿里云的证书数量", component: { - name: 'output-selector', - from: [...CertApplyPluginNames, 'uploadCertToAliyun'], + name: "output-selector", + from: [...CertApplyPluginNames, "uploadCertToAliyun"], }, required: true, }) @@ -36,17 +33,16 @@ export class AliyunDeployCertToNLB extends AbstractTaskPlugin { @TaskInput(createCertDomainGetterInputDefine({ props: { required: false } })) certDomains!: string[]; - @TaskInput({ - title: '证书接入点', - helper: '不会选就保持默认即可', - value: 'cas.aliyuncs.com', + title: "证书接入点", + helper: "不会选就保持默认即可", + value: "cas.aliyuncs.com", component: { - name: 'a-select', + name: "a-select", options: [ - { value: 'cas.aliyuncs.com', label: '中国大陆' }, - { value: 'cas.ap-southeast-1.aliyuncs.com', label: '新加坡' }, - { value: 'cas.eu-central-1.aliyuncs.com', label: '德国(法兰克福)' }, + { value: "cas.aliyuncs.com", label: "中国大陆" }, + { value: "cas.ap-southeast-1.aliyuncs.com", label: "新加坡" }, + { value: "cas.eu-central-1.aliyuncs.com", label: "德国(法兰克福)" }, ], }, required: true, @@ -54,11 +50,11 @@ export class AliyunDeployCertToNLB extends AbstractTaskPlugin { casEndpoint!: string; @TaskInput({ - title: 'Access授权', - helper: '阿里云授权AccessKeyId、AccessKeySecret', + title: "Access授权", + helper: "阿里云授权AccessKeyId、AccessKeySecret", component: { - name: 'access-selector', - type: 'aliyun', + name: "access-selector", + type: "aliyun", }, required: true, }) @@ -66,68 +62,64 @@ export class AliyunDeployCertToNLB extends AbstractTaskPlugin { @TaskInput( createRemoteSelectInputDefine({ - title: 'NLB所在地区', - typeName: 'AliyunDeployCertToNLB', + title: "NLB所在地区", + typeName: "AliyunDeployCertToNLB", single: true, action: AliyunDeployCertToNLB.prototype.onGetRegionList.name, - watches: ['accessId'], + watches: ["accessId"], }) ) regionId: string; @TaskInput( createRemoteSelectInputDefine({ - title: '负载均衡列表', - helper: '要部署证书的负载均衡ID', - typeName: 'AliyunDeployCertToNLB', + title: "负载均衡列表", + helper: "要部署证书的负载均衡ID", + typeName: "AliyunDeployCertToNLB", action: AliyunDeployCertToNLB.prototype.onGetLoadBalanceList.name, - watches: ['regionId'], + watches: ["regionId"], }) ) loadBalancers!: string[]; @TaskInput( createRemoteSelectInputDefine({ - title: '监听器列表', - helper: '要部署证书的监听器列表', - typeName: 'AliyunDeployCertToNLB', + title: "监听器列表", + helper: "要部署证书的监听器列表", + typeName: "AliyunDeployCertToNLB", action: AliyunDeployCertToNLB.prototype.onGetListenerList.name, - watches: ['loadBalancers'], + watches: ["loadBalancers"], }) ) listeners!: string[]; - - - @TaskInput({ - title: "部署证书类型", - value: "default", - component: { - name: "a-select", - vModel: "value", - options: [ - { - label: "默认证书", - value: "default" - }, - { - label: "扩展证书", - value: "extension" - } - ] - }, - required: true - } - ) - deployType: string = "default"; + title: "部署证书类型", + value: "default", + component: { + name: "a-select", + vModel: "value", + options: [ + { + label: "默认证书", + value: "default", + }, + { + label: "扩展证书", + value: "extension", + }, + ], + }, + required: true, + }) + deployType = "default"; async onInstance() {} async getLBClient(access: AliyunAccess, region: string) { const client = new AliyunClient({ logger: this.logger }); - const version = '2022-04-30'; + const version = "2022-04-30"; await client.init({ accessKeyId: access.accessKeyId, accessKeySecret: access.accessKeySecret, @@ -152,16 +144,16 @@ export class AliyunDeployCertToNLB extends AbstractTaskPlugin { } this.logger.info(`准备开始清理过期证书`); - await this.ctx.utils.sleep(30000) + await this.ctx.utils.sleep(30000); for (const listener of this.listeners) { - try{ + try { await this.clearInvalidCert(nlbClientV2, listener); - }catch(e){ + } catch (e) { this.logger.error(`清理监听器${listener}的过期证书失败`, e); } } - this.logger.info('执行完成'); + this.logger.info("执行完成"); } async deployExtensionCert(client: AliyunClientV2, certId: any) { @@ -176,32 +168,30 @@ export class AliyunDeployCertToNLB extends AbstractTaskPlugin { body: { ListenerId: listenerId, RegionId: this.regionId, - "AdditionalCertificateIds.1": certId - } - } + "AdditionalCertificateIds.1": certId, + }, + }, }); this.logger.info(`部署监听器${listenerId}的扩展证书成功`); } } - async deployDefaultCert(certId: any, client: AliyunClient) { for (const listener of this.listeners) { //查询原来的证书 const params: any = { RegionId: this.regionId, ListenerId: listener, - CertificateIds:[certId], //旧sdk + CertificateIds: [certId], //旧sdk }; - const res = await client.request('UpdateListenerAttribute', params); + const res = await client.request("UpdateListenerAttribute", params); this.checkRet(res); this.logger.info(`部署${listener}监听器证书成功`, JSON.stringify(res)); } } - getNLBClientV2(access: AliyunAccess) { return access.getClient(`nlb.${this.regionId}.aliyuncs.com`); } @@ -216,24 +206,23 @@ export class AliyunDeployCertToNLB extends AbstractTaskPlugin { data: { body: { ListenerId: listener, - RegionId: this.regionId - } - } + RegionId: this.regionId, + }, + }, }; const res = await client.doRequest(req); const list = res.Certificates; if (list.length === 0) { this.logger.info(`监听器${listener}没有绑定证书`); - return + return; } const sslClient = new AliyunSslClient({ access: client.access, logger: this.logger, - endpoint: this.casEndpoint + endpoint: this.casEndpoint, }); - const certIds = []; for (const item of list) { this.logger.info(`监听器${listener}绑定的证书${item.CertificateId},status:${item.Status},IsDefault:${item.IsDefault}`); @@ -243,7 +232,7 @@ export class AliyunDeployCertToNLB extends AbstractTaskPlugin { if (item.IsDefault) { continue; } - certIds.push( parseInt(item.CertificateId)); + certIds.push(parseInt(item.CertificateId)); } this.logger.info(`监听器${listener}绑定的证书${certIds}`); //检查是否过期,过期则删除 @@ -257,14 +246,14 @@ export class AliyunDeployCertToNLB extends AbstractTaskPlugin { } if (invalidCertIds.length === 0) { this.logger.info(`监听器${listener}没有过期的证书`); - return + return; } this.logger.info(`开始解绑过期的证书:${invalidCertIds},listener:${listener}`); - const ids:any = {} - let i = 0 + const ids: any = {}; + let i = 0; for (const certId of invalidCertIds) { - i++ + i++; ids[`AdditionalCertificateIds.${i}`] = certId; } await client.doRequest({ @@ -276,17 +265,16 @@ export class AliyunDeployCertToNLB extends AbstractTaskPlugin { body: { ListenerId: listener, RegionId: this.regionId, - ...ids - } - } + ...ids, + }, + }, }); this.logger.info(`解绑过期证书成功`); } async getAliyunCertId(access: AliyunAccess) { let certId: any = this.cert; - if (typeof this.cert === 'object') { - + if (typeof this.cert === "object") { const casCert = this.cert as CasCertId; if (casCert.certId) { return casCert.certId; @@ -300,7 +288,7 @@ export class AliyunDeployCertToNLB extends AbstractTaskPlugin { endpoint: this.casEndpoint, }); - const certName = this.buildCertName(CertReader.getMainDomain(certInfo.crt)) + const certName = this.buildCertName(CertReader.getMainDomain(certInfo.crt)); const certIdRes = await sslClient.uploadCertificate({ name: certName, @@ -313,15 +301,15 @@ export class AliyunDeployCertToNLB extends AbstractTaskPlugin { async onGetRegionList(data: any) { if (!this.accessId) { - throw new Error('请选择Access授权'); + throw new Error("请选择Access授权"); } const access = await this.getAccess(this.accessId); - const client = await this.getLBClient(access, 'cn-shanghai'); + const client = await this.getLBClient(access, "cn-shanghai"); - const res = await client.request('DescribeRegions', {}); + const res = await client.request("DescribeRegions", {}); this.checkRet(res); if (!res?.Regions || res?.Regions.length === 0) { - throw new Error('没有找到Regions列表'); + throw new Error("没有找到Regions列表"); } return res.Regions.map((item: any) => { @@ -335,10 +323,10 @@ export class AliyunDeployCertToNLB extends AbstractTaskPlugin { async onGetLoadBalanceList(data: any) { if (!this.accessId) { - throw new Error('请先选择Access授权'); + throw new Error("请先选择Access授权"); } if (!this.regionId) { - throw new Error('请先选择地区'); + throw new Error("请先选择地区"); } const access = await this.getAccess(this.accessId); const client = await this.getLBClient(access, this.regionId); @@ -346,10 +334,10 @@ export class AliyunDeployCertToNLB extends AbstractTaskPlugin { const params = { MaxResults: 100, }; - const res = await client.request('ListLoadBalancers', params); + const res = await client.request("ListLoadBalancers", params); this.checkRet(res); if (!res?.LoadBalancers || res?.LoadBalancers.length === 0) { - throw new Error('没有找到LoadBalancers'); + throw new Error("没有找到LoadBalancers"); } return res.LoadBalancers.map((item: any) => { @@ -363,10 +351,10 @@ export class AliyunDeployCertToNLB extends AbstractTaskPlugin { async onGetListenerList(data: any) { if (!this.accessId) { - throw new Error('请先选择Access授权'); + throw new Error("请先选择Access授权"); } if (!this.regionId) { - throw new Error('请先选择地区'); + throw new Error("请先选择地区"); } const access = await this.getAccess(this.accessId); const client = await this.getLBClient(access, this.regionId); @@ -377,10 +365,10 @@ export class AliyunDeployCertToNLB extends AbstractTaskPlugin { if (this.loadBalancers && this.loadBalancers.length > 0) { params.LoadBalancerIds = this.loadBalancers; } - const res = await client.request('ListListeners', params); + const res = await client.request("ListListeners", params); this.checkRet(res); if (!res?.Listeners || res?.Listeners.length === 0) { - throw new Error('没有找到TCPSSL监听器'); + throw new Error("没有找到TCPSSL监听器"); } return res.Listeners.map((item: any) => { diff --git a/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-oss/index.ts b/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-oss/index.ts index 5a351ccee..552aa9c75 100644 --- a/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-oss/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-oss/index.ts @@ -1,19 +1,16 @@ import { optionsUtils } from "@certd/basic"; -import { AbstractTaskPlugin, IsTaskPlugin, Pager, pluginGroups, RunStrategy, TaskInput } from '@certd/pipeline'; -import { CertApplyPluginNames, CertInfo } from '@certd/plugin-cert'; -import { - createCertDomainGetterInputDefine, - createRemoteSelectInputDefine -} from '@certd/plugin-lib'; +import { AbstractTaskPlugin, IsTaskPlugin, Pager, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; +import { CertApplyPluginNames, CertInfo } from "@certd/plugin-cert"; +import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from "@certd/plugin-lib"; import { isArray } from "lodash-es"; -import { AliyunAccess } from '../../../plugin-lib/aliyun/access/index.js'; -import { CasCertId } from '../../../plugin-lib/aliyun/lib/index.js'; +import { AliyunAccess } from "../../../plugin-lib/aliyun/access/index.js"; +import { CasCertId } from "../../../plugin-lib/aliyun/lib/index.js"; @IsTaskPlugin({ - name: 'DeployCertToAliyunOSS', - title: '阿里云-部署证书至OSS', - icon: 'svg:icon-aliyun', + name: "DeployCertToAliyunOSS", + title: "阿里云-部署证书至OSS", + icon: "svg:icon-aliyun", group: pluginGroups.aliyun.key, - desc: '部署域名证书至阿里云OSS自定义域名,不是上传到阿里云oss', + desc: "部署域名证书至阿里云OSS自定义域名,不是上传到阿里云oss", default: { strategy: { runStrategy: RunStrategy.SkipWhenSucceed, @@ -21,13 +18,12 @@ import { CasCertId } from '../../../plugin-lib/aliyun/lib/index.js'; }, }) export class DeployCertToAliyunOSS extends AbstractTaskPlugin { - @TaskInput({ - title: '域名证书', - helper: '请选择前置任务输出的域名证书', + title: "域名证书", + helper: "请选择前置任务输出的域名证书", component: { - name: 'output-selector', - from: [...CertApplyPluginNames,"uploadCertToAliyun"], + name: "output-selector", + from: [...CertApplyPluginNames, "uploadCertToAliyun"], }, required: true, }) @@ -36,42 +32,41 @@ export class DeployCertToAliyunOSS extends AbstractTaskPlugin { @TaskInput(createCertDomainGetterInputDefine({ props: { required: false } })) certDomains!: string[]; - @TaskInput({ - title: '大区', + title: "大区", component: { - name: 'a-auto-complete', - vModel: 'value', + name: "a-auto-complete", + vModel: "value", options: [ - { value: 'oss-cn-hangzhou', label: '华东1(杭州)' }, - { value: 'oss-cn-shanghai', label: '华东2(上海)' }, - { value: 'oss-cn-nanjing', label: '华东5(南京-本地地域)' }, - { value: 'oss-cn-fuzhou', label: '华东6(福州-本地地域)' }, - { value: 'oss-cn-wuhan-lr', label: '华中1(武汉-本地地域)' }, - { value: 'oss-cn-qingdao', label: '华北1(青岛)' }, - { value: 'oss-cn-beijing', label: '华北2(北京)' }, - { value: 'oss-cn-zhangjiakou', label: '华北 3(张家口)' }, - { value: 'oss-cn-huhehaote', label: '华北5(呼和浩特)' }, - { value: 'oss-cn-wulanchabu', label: '华北6(乌兰察布)' }, - { value: 'oss-cn-shenzhen', label: '华南1(深圳)' }, - { value: 'oss-cn-heyuan', label: '华南2(河源)' }, - { value: 'oss-cn-guangzhou', label: '华南3(广州)' }, - { value: 'oss-cn-chengdu', label: '西南1(成都)' }, - { value: 'oss-cn-hongkong', label: '中国香港' }, - { value: 'oss-us-west-1', label: '美国(硅谷)①' }, - { value: 'oss-us-east-1', label: '美国(弗吉尼亚)①' }, - { value: 'oss-ap-northeast-1', label: '日本(东京)①' }, - { value: 'oss-ap-northeast-2', label: '韩国(首尔)' }, - { value: 'oss-ap-southeast-1', label: '新加坡①' }, - { value: 'oss-ap-southeast-2', label: '澳大利亚(悉尼)①' }, - { value: 'oss-ap-southeast-3', label: '马来西亚(吉隆坡)①' }, - { value: 'oss-ap-southeast-5', label: '印度尼西亚(雅加达)①' }, - { value: 'oss-ap-southeast-6', label: '菲律宾(马尼拉)' }, - { value: 'oss-ap-southeast-7', label: '泰国(曼谷)' }, - { value: 'oss-eu-central-1', label: '德国(法兰克福)①' }, - { value: 'oss-eu-west-1', label: '英国(伦敦)' }, - { value: 'oss-me-east-1', label: '阿联酋(迪拜)①' }, - { value: 'oss-rg-china-mainland', label: '无地域属性(中国内地)' }, + { value: "oss-cn-hangzhou", label: "华东1(杭州)" }, + { value: "oss-cn-shanghai", label: "华东2(上海)" }, + { value: "oss-cn-nanjing", label: "华东5(南京-本地地域)" }, + { value: "oss-cn-fuzhou", label: "华东6(福州-本地地域)" }, + { value: "oss-cn-wuhan-lr", label: "华中1(武汉-本地地域)" }, + { value: "oss-cn-qingdao", label: "华北1(青岛)" }, + { value: "oss-cn-beijing", label: "华北2(北京)" }, + { value: "oss-cn-zhangjiakou", label: "华北 3(张家口)" }, + { value: "oss-cn-huhehaote", label: "华北5(呼和浩特)" }, + { value: "oss-cn-wulanchabu", label: "华北6(乌兰察布)" }, + { value: "oss-cn-shenzhen", label: "华南1(深圳)" }, + { value: "oss-cn-heyuan", label: "华南2(河源)" }, + { value: "oss-cn-guangzhou", label: "华南3(广州)" }, + { value: "oss-cn-chengdu", label: "西南1(成都)" }, + { value: "oss-cn-hongkong", label: "中国香港" }, + { value: "oss-us-west-1", label: "美国(硅谷)①" }, + { value: "oss-us-east-1", label: "美国(弗吉尼亚)①" }, + { value: "oss-ap-northeast-1", label: "日本(东京)①" }, + { value: "oss-ap-northeast-2", label: "韩国(首尔)" }, + { value: "oss-ap-southeast-1", label: "新加坡①" }, + { value: "oss-ap-southeast-2", label: "澳大利亚(悉尼)①" }, + { value: "oss-ap-southeast-3", label: "马来西亚(吉隆坡)①" }, + { value: "oss-ap-southeast-5", label: "印度尼西亚(雅加达)①" }, + { value: "oss-ap-southeast-6", label: "菲律宾(马尼拉)" }, + { value: "oss-ap-southeast-7", label: "泰国(曼谷)" }, + { value: "oss-eu-central-1", label: "德国(法兰克福)①" }, + { value: "oss-eu-west-1", label: "英国(伦敦)" }, + { value: "oss-me-east-1", label: "阿联酋(迪拜)①" }, + { value: "oss-rg-china-mainland", label: "无地域属性(中国内地)" }, ], }, required: true, @@ -79,49 +74,48 @@ export class DeployCertToAliyunOSS extends AbstractTaskPlugin { region!: string; @TaskInput({ - title: 'Bucket', - helper: '存储桶名称', + title: "Bucket", + helper: "存储桶名称", component: { - name: 'remote-auto-complete', - vModel: 'value', - type: 'plugin', - action: 'onGetBucketList', + name: "remote-auto-complete", + vModel: "value", + type: "plugin", + action: "onGetBucketList", search: false, pager: false, - watches: ['accessId', 'region'] + watches: ["accessId", "region"], }, required: true, }) bucket!: string; - @TaskInput(createRemoteSelectInputDefine({ - title: '绑定的域名', - helper: '你在阿里云OSS上绑定的域名,比如:certd.docmirror.cn', - required: true, - action: DeployCertToAliyunOSS.prototype.onGetDomainList.name, - watches: ['certDomains', 'accessId','bucket'], - })) + @TaskInput( + createRemoteSelectInputDefine({ + title: "绑定的域名", + helper: "你在阿里云OSS上绑定的域名,比如:certd.docmirror.cn", + required: true, + action: DeployCertToAliyunOSS.prototype.onGetDomainList.name, + watches: ["certDomains", "accessId", "bucket"], + }) + ) domainName!: string | string[]; - @TaskInput({ - title: '证书名称', - helper: '上传后将以此名称作为前缀备注', + title: "证书名称", + helper: "上传后将以此名称作为前缀备注", }) certName!: string; - - @TaskInput({ - title: '证书服务接入点', - helper: '不会选就按默认', - value: 'cn-hangzhou', + title: "证书服务接入点", + helper: "不会选就按默认", + value: "cn-hangzhou", component: { - name: 'a-select', + name: "a-select", options: [ - { value: 'cn-hangzhou', label: '中国大陆' }, - { value: 'ap-southeast-1', label: '新加坡' }, - { value: 'eu-central-1', label: '德国(法兰克福)' }, + { value: "cn-hangzhou", label: "中国大陆" }, + { value: "ap-southeast-1", label: "新加坡" }, + { value: "eu-central-1", label: "德国(法兰克福)" }, ], }, required: true, @@ -130,11 +124,11 @@ export class DeployCertToAliyunOSS extends AbstractTaskPlugin { casRegion!: string; @TaskInput({ - title: 'Access授权', - helper: '阿里云授权AccessKeyId、AccessKeySecret', + title: "Access授权", + helper: "阿里云授权AccessKeyId、AccessKeySecret", component: { - name: 'access-selector', - type: 'aliyun', + name: "access-selector", + type: "aliyun", }, required: true, order: -98, @@ -143,44 +137,43 @@ export class DeployCertToAliyunOSS extends AbstractTaskPlugin { async onInstance() {} async execute(): Promise { - this.logger.info('开始部署证书到阿里云OSS'); + this.logger.info("开始部署证书到阿里云OSS"); const access = (await this.getAccess(this.accessId)) as AliyunAccess; this.logger.info(`bucket: ${this.bucket}, region: ${this.region}, domainName: ${this.domainName}`); const client = await this.getClient(access); - if (typeof this.domainName === "string"){ + if (typeof this.domainName === "string") { this.domainName = [this.domainName]; } for (const domainName of this.domainName) { - this.logger.info("开始部署证书到阿里云oss自定义域名:", domainName) - await this.updateCert(domainName,client, {}); + this.logger.info("开始部署证书到阿里云oss自定义域名:", domainName); + await this.updateCert(domainName, client, {}); } - this.logger.info('部署完成'); + this.logger.info("部署完成"); } - - async updateCert(domainName:string,client: any, params: any) { - params = client._bucketRequestParams('POST', this.bucket, { - cname: '', - comp: 'add', + async updateCert(domainName: string, client: any, params: any) { + params = client._bucketRequestParams("POST", this.bucket, { + cname: "", + comp: "add", }); - let certStr = "" + let certStr = ""; - if (typeof this.cert === "object" ){ + if (typeof this.cert === "object") { const certInfo = this.cert as CertInfo; - if (certInfo.crt){ + if (certInfo.crt) { certStr = ` ${certInfo.key} ${certInfo.crt} - ` - }else { + `; + } else { const casCert = this.cert as CasCertId; - certStr = `${casCert.certIdentifier}` + certStr = `${casCert.certIdentifier}`; } - }else { - certStr = `${this.cert}-${this.casRegion}` + } else { + certStr = `${this.cert}-${this.casRegion}`; } const xml = ` @@ -194,17 +187,16 @@ export class DeployCertToAliyunOSS extends AbstractTaskPlugin { `; params.content = xml; - params.mime = 'xml'; + params.mime = "xml"; params.successStatuses = [200]; const res = await client.request(params); this.checkRet(res); return res; } - async getClient(access: AliyunAccess) { // @ts-ignore - const OSS = await import('ali-oss'); + const OSS = await import("ali-oss"); return new OSS.default({ accessKeyId: access.accessKeyId, accessKeySecret: access.accessKeySecret, @@ -218,34 +210,30 @@ export class DeployCertToAliyunOSS extends AbstractTaskPlugin { } async onGetBucketList(data: Pager) { - const access = (await this.getAccess(this.accessId)) as AliyunAccess; const client = await this.getClient(access); let res; - const buckets = [] - do{ - const requestData = {'marker': res?.nextMarker || null, 'max-keys': 1000}; - res = await client.listBuckets(requestData) - buckets.push(...(res?.buckets || [])) - } while (!!res?.nextMarker) - return buckets - .filter(bucket => bucket?.region === this.region) - .map(bucket => ({label: `${bucket.name}<${bucket.region}>`, value: bucket.name})); + const buckets = []; + do { + const requestData = { marker: res?.nextMarker || null, "max-keys": 1000 }; + res = await client.listBuckets(requestData); + buckets.push(...(res?.buckets || [])); + } while (!!res?.nextMarker); + return buckets.filter(bucket => bucket?.region === this.region).map(bucket => ({ label: `${bucket.name}<${bucket.region}>`, value: bucket.name })); } async onGetDomainList(data: any) { - const access = (await this.getAccess(this.accessId)) as AliyunAccess; const client = await this.getClient(access); - const res = await this.doListCnameRequest(client,this.bucket) - let domains = res.data?.Cname - if (domains == null || domains.length === 0){ - return [] + const res = await this.doListCnameRequest(client, this.bucket); + let domains = res.data?.Cname; + if (domains == null || domains.length === 0) { + return []; } - if (!isArray(domains)){ - domains = [domains] + if (!isArray(domains)) { + domains = [domains]; } const options = domains.map((item: any) => { @@ -258,13 +246,12 @@ export class DeployCertToAliyunOSS extends AbstractTaskPlugin { return optionsUtils.buildGroupOptions(options, this.certDomains); } - - async doListCnameRequest(client: any,bucket:string) { - const params = client._bucketRequestParams('GET', this.bucket, { - cname: '', - bucket + async doListCnameRequest(client: any, bucket: string) { + const params = client._bucketRequestParams("GET", this.bucket, { + cname: "", + bucket, }); - params.mime = 'xml'; + params.mime = "xml"; params.successStatuses = [200]; params.xmlResponse = true; const res = await client.request(params); @@ -272,11 +259,9 @@ export class DeployCertToAliyunOSS extends AbstractTaskPlugin { return res; } - - checkRet(ret: any) { - if (ret.Code != null || ret.status!==200) { - throw new Error('执行失败:' + ret.Message || ret.data); + if (ret.Code != null || ret.status !== 200) { + throw new Error("执行失败:" + ret.Message || ret.data); } } } diff --git a/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-slb/index.ts b/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-slb/index.ts index bf696627a..f4898b5f4 100644 --- a/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-slb/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-slb/index.ts @@ -1,19 +1,16 @@ -import { AbstractTaskPlugin, IsTaskPlugin, PageSearch, pluginGroups, RunStrategy, TaskInput } from '@certd/pipeline'; -import { CertInfo } from '@certd/plugin-cert'; -import { - createCertDomainGetterInputDefine, - createRemoteSelectInputDefine -} from '@certd/plugin-lib'; -import { CertApplyPluginNames } from '@certd/plugin-cert'; -import { AliyunAccess } from '../../../plugin-lib/aliyun/access/index.js'; -import { AliyunClient, AliyunSslClient, CasCertInfo } from '../../../plugin-lib/aliyun/lib/index.js'; +import { AbstractTaskPlugin, IsTaskPlugin, PageSearch, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; +import { CertInfo } from "@certd/plugin-cert"; +import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from "@certd/plugin-lib"; +import { CertApplyPluginNames } from "@certd/plugin-cert"; +import { AliyunAccess } from "../../../plugin-lib/aliyun/access/index.js"; +import { AliyunClient, AliyunSslClient, CasCertInfo } from "../../../plugin-lib/aliyun/lib/index.js"; @IsTaskPlugin({ - name: 'AliyunDeployCertToSLB', - title: '阿里云-部署至CLB(传统负载均衡)', - icon: 'svg:icon-aliyun', + name: "AliyunDeployCertToSLB", + title: "阿里云-部署至CLB(传统负载均衡)", + icon: "svg:icon-aliyun", group: pluginGroups.aliyun.key, - desc: '部署证书到阿里云CLB(传统负载均衡)', + desc: "部署证书到阿里云CLB(传统负载均衡)", needPlus: false, default: { strategy: { @@ -23,11 +20,11 @@ import { AliyunClient, AliyunSslClient, CasCertInfo } from '../../../plugin-lib/ }) export class AliyunDeployCertToSLB extends AbstractTaskPlugin { @TaskInput({ - title: '域名证书', - helper: '请选择证书申请任务输出的域名证书\n或者选择前置任务“上传证书到阿里云”任务的证书ID,可以减少上传到阿里云的证书数量', + title: "域名证书", + helper: "请选择证书申请任务输出的域名证书\n或者选择前置任务“上传证书到阿里云”任务的证书ID,可以减少上传到阿里云的证书数量", component: { - name: 'output-selector', - from: [...CertApplyPluginNames, 'uploadCertToAliyun'], + name: "output-selector", + from: [...CertApplyPluginNames, "uploadCertToAliyun"], }, required: true, }) @@ -36,77 +33,71 @@ export class AliyunDeployCertToSLB extends AbstractTaskPlugin { @TaskInput(createCertDomainGetterInputDefine({ props: { required: false } })) certDomains!: string[]; - @TaskInput({ - title: '证书接入点', - helper: '不会选就保持默认即可', - value: 'cas.aliyuncs.com', + title: "证书接入点", + helper: "不会选就保持默认即可", + value: "cas.aliyuncs.com", component: { - name: 'a-select', + name: "a-select", options: [ - { value: 'cas.aliyuncs.com', label: '中国大陆' }, - { value: 'cas.ap-southeast-1.aliyuncs.com', label: '新加坡' }, - { value: 'cas.eu-central-1.aliyuncs.com', label: '德国(法兰克福)' }, + { value: "cas.aliyuncs.com", label: "中国大陆" }, + { value: "cas.ap-southeast-1.aliyuncs.com", label: "新加坡" }, + { value: "cas.eu-central-1.aliyuncs.com", label: "德国(法兰克福)" }, ], }, required: true, }) casEndpoint!: string; - @TaskInput({ - title: 'Access授权', - helper: '阿里云授权AccessKeyId、AccessKeySecret', + title: "Access授权", + helper: "阿里云授权AccessKeyId、AccessKeySecret", component: { - name: 'access-selector', - type: 'aliyun', + name: "access-selector", + type: "aliyun", }, required: true, }) accessId!: string; - - @TaskInput( createRemoteSelectInputDefine({ - title: 'LB所在地区', + title: "LB所在地区", single: true, action: AliyunDeployCertToSLB.prototype.onGetRegionList.name, - watches: ['accessId'], + watches: ["accessId"], }) ) regionId: string; @TaskInput( createRemoteSelectInputDefine({ - title: '负载均衡列表', - helper: '要部署证书的负载均衡ID', + title: "负载均衡列表", + helper: "要部署证书的负载均衡ID", action: AliyunDeployCertToSLB.prototype.onGetLoadBalanceList.name, - watches: ['regionId'], + watches: ["regionId"], }) ) loadBalancers!: string[]; @TaskInput( createRemoteSelectInputDefine({ - title: '监听器列表', - helper: '要部署证书的监听器列表', + title: "监听器列表", + helper: "要部署证书的监听器列表", action: AliyunDeployCertToSLB.prototype.onGetListenerList.name, - watches: ['loadBalancers'], + watches: ["loadBalancers"], }) ) listeners!: string[]; - @TaskInput({ title: "部署默认证书", value: true, component: { name: "a-switch", - vModel: "checked" - } - } - ) + vModel: "checked", + }, + }) deployDefault!: boolean; @TaskInput({ @@ -114,37 +105,33 @@ export class AliyunDeployCertToSLB extends AbstractTaskPlugin { value: false, component: { name: "a-switch", - vModel: "checked" - } - } - ) + vModel: "checked", + }, + }) deployExtension!: boolean; - @TaskInput( createRemoteSelectInputDefine({ - title: '扩展域名列表', - helper: '要部署扩展域名列表', + title: "扩展域名列表", + helper: "要部署扩展域名列表", action: AliyunDeployCertToSLB.prototype.onGetExtensionDomainList.name, - watches: ['listeners', 'deployExtension'], + watches: ["listeners", "deployExtension"], mergeScript: ` return { show: ctx.compute(({form})=>{ return form.deployExtension; }) } - ` + `, }) ) extensionDomains!: string[]; - - async onInstance() { - } + async onInstance() {} async getLBClient(access: AliyunAccess, region: string) { const client = new AliyunClient({ logger: this.logger }); - const version = '2014-05-15'; + const version = "2014-05-15"; await client.init({ accessKeyId: access.accessKeyId, accessKeySecret: access.accessKeySecret, @@ -164,9 +151,9 @@ export class AliyunDeployCertToSLB extends AbstractTaskPlugin { const slbServerCertId = await this.uploadServerCert(client, aliyunCert); if (this.deployDefault !== false) { - this.logger.info("部署监听器默认证书") + this.logger.info("部署监听器默认证书"); for (const listener of this.listeners) { - const { port, loadBalanceId } = this.resolveListenerKey(listener) + const { port, loadBalanceId } = this.resolveListenerKey(listener); const params = { RegionId: this.regionId, LoadBalancerId: loadBalanceId, @@ -174,18 +161,18 @@ export class AliyunDeployCertToSLB extends AbstractTaskPlugin { ServerCertificateId: slbServerCertId, }; - const res = await client.request('SetLoadBalancerHTTPSListenerAttribute', params); + const res = await client.request("SetLoadBalancerHTTPSListenerAttribute", params); this.checkRet(res); this.logger.info(`部署${listener}监听器证书成功`, JSON.stringify(res)); } } if (this.deployExtension) { - this.logger.info("部署监听器扩展域名证书") + this.logger.info("部署监听器扩展域名证书"); const clientV2 = this.getCLBClientV2(access); for (const domainStr of this.extensionDomains) { - const { extensionDomainId } = this.resolveListenerKey(domainStr) + const { extensionDomainId } = this.resolveListenerKey(domainStr); const res = await clientV2.doRequest({ action: "SetDomainExtensionAttribute", // 接口版本 @@ -194,22 +181,22 @@ export class AliyunDeployCertToSLB extends AbstractTaskPlugin { query: { RegionId: this.regionId, DomainExtensionId: extensionDomainId, - ServerCertificateId: slbServerCertId - } - } - }) - this.logger.info(`部署扩展域名${extensionDomainId}证书成功`, JSON.stringify(res)) + ServerCertificateId: slbServerCertId, + }, + }, + }); + this.logger.info(`部署扩展域名${extensionDomainId}证书成功`, JSON.stringify(res)); } } - this.logger.info('执行完成'); + this.logger.info("执行完成"); } getCLBClientV2(access: AliyunAccess) { - return access.getClient(`slb.${this.regionId}.aliyuncs.com`) + return access.getClient(`slb.${this.regionId}.aliyuncs.com`); } resolveListenerKey(listener: string) { - const arr = listener.split('_'); + const arr = listener.split("_"); const loadBalanceId = arr[0]; const protocol = arr[1]; const port = arr[2]; @@ -222,8 +209,8 @@ export class AliyunDeployCertToSLB extends AbstractTaskPlugin { loadBalanceId, port: parseInt(port), extensionDomainId: extensionDomainId, - protocol: protocol - } + protocol: protocol, + }; } async uploadServerCert(client: any, aliyunCert: CasCertInfo) { @@ -231,12 +218,12 @@ export class AliyunDeployCertToSLB extends AbstractTaskPlugin { RegionId: this.regionId, AliCloudCertificateId: aliyunCert.certId, AliCloudCertificateName: aliyunCert.certName, - AliCloudCertificateRegionId: aliyunCert.casRegion + AliCloudCertificateRegionId: aliyunCert.casRegion, }; - const res = await client.request('UploadServerCertificate', params); + const res = await client.request("UploadServerCertificate", params); this.checkRet(res); - this.logger.info('SLBServerCertificate创建成功', res.ServerCertificateId); + this.logger.info("SLBServerCertificate创建成功", res.ServerCertificateId); return res.ServerCertificateId; } @@ -249,8 +236,8 @@ export class AliyunDeployCertToSLB extends AbstractTaskPlugin { endpoint: this.casEndpoint, }); - if (typeof this.cert === 'object') { - const name = this.appendTimeSuffix('certd'); + if (typeof this.cert === "object") { + const name = this.appendTimeSuffix("certd"); const casCert = this.cert as CasCertInfo; if (casCert.certIdentifier) { @@ -263,8 +250,6 @@ export class AliyunDeployCertToSLB extends AbstractTaskPlugin { }); certId = certIdRes.certId as any; } - - } return await sslClient.getCertInfo(certId); @@ -272,15 +257,15 @@ export class AliyunDeployCertToSLB extends AbstractTaskPlugin { async onGetRegionList(data: any) { if (!this.accessId) { - throw new Error('请选择Access授权'); + throw new Error("请选择Access授权"); } const access = await this.getAccess(this.accessId); - const client = await this.getLBClient(access, 'cn-shanghai'); + const client = await this.getLBClient(access, "cn-shanghai"); - const res = await client.request('DescribeRegions', {}); + const res = await client.request("DescribeRegions", {}); this.checkRet(res); if (!res?.Regions?.Region || res?.Regions?.Region.length === 0) { - throw new Error('没有找到Regions列表'); + throw new Error("没有找到Regions列表"); } return res.Regions.Region.map((item: any) => { @@ -294,10 +279,10 @@ export class AliyunDeployCertToSLB extends AbstractTaskPlugin { async onGetLoadBalanceList(data: any) { if (!this.accessId) { - throw new Error('请先选择Access授权'); + throw new Error("请先选择Access授权"); } if (!this.regionId) { - throw new Error('请先选择地区'); + throw new Error("请先选择地区"); } const access = await this.getAccess(this.accessId); const client = await this.getLBClient(access, this.regionId); @@ -306,10 +291,10 @@ export class AliyunDeployCertToSLB extends AbstractTaskPlugin { RegionId: this.regionId, MaxResults: 100, }; - const res = await client.request('DescribeLoadBalancers', params); + const res = await client.request("DescribeLoadBalancers", params); this.checkRet(res); if (!res?.LoadBalancers?.LoadBalancer || res?.LoadBalancers.LoadBalancer.length === 0) { - throw new Error('没有找到LoadBalancers'); + throw new Error("没有找到LoadBalancers"); } return res.LoadBalancers.LoadBalancer.map((item: any) => { @@ -323,10 +308,10 @@ export class AliyunDeployCertToSLB extends AbstractTaskPlugin { async onGetListenerList(data: any) { if (!this.accessId) { - throw new Error('请先选择Access授权'); + throw new Error("请先选择Access授权"); } if (!this.regionId) { - throw new Error('请先选择地区'); + throw new Error("请先选择地区"); } const access = await this.getAccess(this.accessId); const client = await this.getLBClient(access, this.regionId); @@ -334,15 +319,15 @@ export class AliyunDeployCertToSLB extends AbstractTaskPlugin { const params: any = { MaxResults: 100, RegionId: this.regionId, - ListenerProtocol: 'HTTPS', + ListenerProtocol: "HTTPS", }; if (this.loadBalancers && this.loadBalancers.length > 0) { params.LoadBalancerId = this.loadBalancers; } - const res = await client.request('DescribeLoadBalancerListeners', params); + const res = await client.request("DescribeLoadBalancerListeners", params); this.checkRet(res); if (!res?.Listeners || res?.Listeners.length === 0) { - throw new Error('没有找到HTTPS监听器'); + throw new Error("没有找到HTTPS监听器"); } return res.Listeners.map((item: any) => { @@ -357,46 +342,39 @@ export class AliyunDeployCertToSLB extends AbstractTaskPlugin { async onGetExtensionDomainList(data: PageSearch) { if (!this.accessId) { - throw new Error('请先选择Access授权'); + throw new Error("请先选择Access授权"); } if (!this.regionId) { - throw new Error('请先选择地区'); + throw new Error("请先选择地区"); } if (!this.listeners && this.listeners.length == 0) { - throw new Error('请先选择监听器'); + throw new Error("请先选择监听器"); } const access = await this.getAccess(this.accessId); - const allDomains: any[] = [] + const allDomains: any[] = []; for (const ls of this.listeners) { - const { port, loadBalanceId, protocol } = this.resolveListenerKey(ls) + const { port, loadBalanceId, protocol } = this.resolveListenerKey(ls); const domains = await this.doGetExtensionDomainList({ access, loadBalancerId: loadBalanceId, listenerPort: port, listenerProtocol: protocol, }); - allDomains.push(...domains) + allDomains.push(...domains); } - return this.ctx.utils.options.buildGroupOptions(allDomains, this.certDomains) - + return this.ctx.utils.options.buildGroupOptions(allDomains, this.certDomains); } - - async doGetExtensionDomainList(data: { - loadBalancerId: string, - listenerPort: number, - listenerProtocol: string, - access: AliyunAccess - }) { + async doGetExtensionDomainList(data: { loadBalancerId: string; listenerPort: number; listenerProtocol: string; access: AliyunAccess }) { const { loadBalancerId, listenerPort, listenerProtocol, access } = data; - const client = access.getClient(`slb.${this.regionId}.aliyuncs.com`) + const client = access.getClient(`slb.${this.regionId}.aliyuncs.com`); - let queries = { + const queries = { RegionId: this.regionId, LoadBalancerId: loadBalancerId, - ListenerPort: listenerPort + ListenerPort: listenerPort, }; const res = await client.doRequest({ @@ -406,13 +384,13 @@ export class AliyunDeployCertToSLB extends AbstractTaskPlugin { version: "2014-05-15", data: { query: queries, - } - }) + }, + }); this.checkRet(res); const list = res?.DomainExtensions.DomainExtension; if (!list || list.length === 0) { - return [] + return []; } return list.map((i: any) => { @@ -421,12 +399,11 @@ export class AliyunDeployCertToSLB extends AbstractTaskPlugin { return { value: value, label: label, - domain: i.Domain + domain: i.Domain, }; }); } - checkRet(ret: any) { if (ret.Code != null) { throw new Error(ret.Message); diff --git a/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-vod/index.ts b/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-vod/index.ts index 3742c8a03..5ab310bc9 100644 --- a/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-vod/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-vod/index.ts @@ -12,9 +12,9 @@ import { AliyunAccess } from "../../../plugin-lib/aliyun/access/index.js"; needPlus: false, default: { strategy: { - runStrategy: RunStrategy.SkipWhenSucceed - } - } + runStrategy: RunStrategy.SkipWhenSucceed, + }, + }, }) export class AliyunDeployCertToVod extends AbstractTaskPlugin { @TaskInput({ @@ -22,9 +22,9 @@ export class AliyunDeployCertToVod extends AbstractTaskPlugin { helper: "请选择证书申请任务输出的域名证书", component: { name: "output-selector", - from: [...CertApplyPluginNames] + from: [...CertApplyPluginNames], }, - required: true + required: true, }) cert!: CertInfo; @@ -55,22 +55,21 @@ export class AliyunDeployCertToVod extends AbstractTaskPlugin { options: [ { value: "cas.aliyuncs.com", label: "中国大陆" }, { value: "cas.ap-southeast-1.aliyuncs.com", label: "新加坡" }, - { value: "cas.eu-central-1.aliyuncs.com", label: "德国(法兰克福)" } - ] + { value: "cas.eu-central-1.aliyuncs.com", label: "德国(法兰克福)" }, + ], }, - required: true + required: true, }) casEndpoint!: string; - @TaskInput({ title: "Access授权", helper: "阿里云授权AccessKeyId、AccessKeySecret", component: { name: "access-selector", - type: "aliyun" + type: "aliyun", }, - required: true + required: true, }) accessId!: string; @@ -81,15 +80,12 @@ export class AliyunDeployCertToVod extends AbstractTaskPlugin { action: AliyunDeployCertToVod.prototype.onGetDomainList.name, watches: ["accessId"], pager: true, - search: true + search: true, }) ) domainList!: string[]; - - async onInstance() { - } - + async onInstance() {} async execute(): Promise { this.logger.info("开始部署证书到阿里云VOD"); @@ -97,7 +93,6 @@ export class AliyunDeployCertToVod extends AbstractTaskPlugin { const client = await this.getClient(access); - for (const siteId of this.domainList) { /** * let queries : {[key: string ]: any} = { }; @@ -122,9 +117,9 @@ export class AliyunDeployCertToVod extends AbstractTaskPlugin { CertName: this.appendTimeSuffix("certd"), SSLProtocol: "on", SSLPub: this.cert.crt, - SSLPri: this.cert.key - } - } + SSLPri: this.cert.key, + }, + }, }); this.logger.info(`部署站点[${siteId}]证书成功:${JSON.stringify(res)}`); } @@ -161,9 +156,9 @@ export class AliyunDeployCertToVod extends AbstractTaskPlugin { query: { DomainName: data.searchKey, PageNumber: data.pageNo, - PageSize: data.pageSize - } - } + PageSize: data.pageSize, + }, + }, }); const list = res?.Domains.PageData; @@ -175,12 +170,11 @@ export class AliyunDeployCertToVod extends AbstractTaskPlugin { return { label: item.DomainName, value: item.DomainName, - domain: item.DomainName + domain: item.DomainName, }; }); return this.ctx.utils.options.buildGroupOptions(options, this.certDomains); } - } new AliyunDeployCertToVod(); diff --git a/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-waf/deploy-to-waf-cloud.ts b/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-waf/deploy-to-waf-cloud.ts index 713eb2a69..d250a551d 100644 --- a/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-waf/deploy-to-waf-cloud.ts +++ b/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-waf/deploy-to-waf-cloud.ts @@ -1,18 +1,15 @@ import { AbstractTaskPlugin, IsTaskPlugin, Pager, PageSearch, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; import { CertApplyPluginNames, CertInfo, CertReader } from "@certd/plugin-cert"; -import { - createCertDomainGetterInputDefine, - createRemoteSelectInputDefine -} from "@certd/plugin-lib"; +import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from "@certd/plugin-lib"; import { AliyunAccess } from "../../../plugin-lib/aliyun/access/index.js"; import { AliyunClient, AliyunSslClient, CasCertInfo } from "../../../plugin-lib/aliyun/lib/index.js"; @IsTaskPlugin({ - name: 'AliyunDeployCertToWafCloud', - title: '阿里云-部署至阿里云WAF(云产品接入)', - icon: 'svg:icon-aliyun', + name: "AliyunDeployCertToWafCloud", + title: "阿里云-部署至阿里云WAF(云产品接入)", + icon: "svg:icon-aliyun", group: pluginGroups.aliyun.key, - desc: '部署证书到阿里云WAF(云产品接入),CNAME方式接入的请选择另外一个waf插件', + desc: "部署证书到阿里云WAF(云产品接入),CNAME方式接入的请选择另外一个waf插件", needPlus: false, default: { strategy: { @@ -22,11 +19,11 @@ import { AliyunClient, AliyunSslClient, CasCertInfo } from "../../../plugin-lib/ }) export class AliyunDeployCertToWafCloud extends AbstractTaskPlugin { @TaskInput({ - title: '域名证书', - helper: '请选择证书申请任务输出的域名证书\n或者选择前置任务“上传证书到阿里云”任务的证书ID,可以减少上传到阿里云的证书数量', + title: "域名证书", + helper: "请选择证书申请任务输出的域名证书\n或者选择前置任务“上传证书到阿里云”任务的证书ID,可以减少上传到阿里云的证书数量", component: { - name: 'output-selector', - from: [...CertApplyPluginNames, 'uploadCertToAliyun'], + name: "output-selector", + from: [...CertApplyPluginNames, "uploadCertToAliyun"], }, required: true, }) @@ -36,14 +33,14 @@ export class AliyunDeployCertToWafCloud extends AbstractTaskPlugin { certDomains!: string[]; @TaskInput({ - title: 'WAF接入点', - helper: '不会选就按默认', - value: 'cn-hangzhou', + title: "WAF接入点", + helper: "不会选就按默认", + value: "cn-hangzhou", component: { - name: 'a-select', + name: "a-select", options: [ - { value: 'cn-hangzhou', label: '中国内地' }, - { value: 'ap-southeast-1', label: '非中国内地' }, + { value: "cn-hangzhou", label: "中国内地" }, + { value: "ap-southeast-1", label: "非中国内地" }, ], }, required: true, @@ -51,15 +48,15 @@ export class AliyunDeployCertToWafCloud extends AbstractTaskPlugin { regionId!: string; @TaskInput({ - title: '证书接入点', - helper: '跟上面保持一致即可', - value: 'cas.aliyuncs.com', + title: "证书接入点", + helper: "跟上面保持一致即可", + value: "cas.aliyuncs.com", component: { - name: 'a-select', + name: "a-select", options: [ - { value: 'cas.aliyuncs.com', label: '中国大陆' }, - { value: 'cas.ap-southeast-1.aliyuncs.com', label: '新加坡' }, - { value: 'cas.eu-central-1.aliyuncs.com', label: '德国(法兰克福)' }, + { value: "cas.aliyuncs.com", label: "中国大陆" }, + { value: "cas.ap-southeast-1.aliyuncs.com", label: "新加坡" }, + { value: "cas.eu-central-1.aliyuncs.com", label: "德国(法兰克福)" }, ], }, required: true, @@ -67,11 +64,11 @@ export class AliyunDeployCertToWafCloud extends AbstractTaskPlugin { casEndpoint!: string; @TaskInput({ - title: 'Access授权', - helper: '阿里云授权AccessKeyId、AccessKeySecret', + title: "Access授权", + helper: "阿里云授权AccessKeyId、AccessKeySecret", component: { - name: 'access-selector', - type: 'aliyun', + name: "access-selector", + type: "aliyun", }, required: true, }) @@ -79,33 +76,31 @@ export class AliyunDeployCertToWafCloud extends AbstractTaskPlugin { @TaskInput( createRemoteSelectInputDefine({ - title: '云产品资源', - helper: '请选择要部署证书的云产品资源', + title: "云产品资源", + helper: "请选择要部署证书的云产品资源", action: AliyunDeployCertToWafCloud.prototype.onGetCloudResourceList.name, - watches: ['accessId', 'regionId'], + watches: ["accessId", "regionId"], pager: true, search: true, }) ) cloudResources!: string[]; - - @TaskInput({ - title: '证书部署类型', - value: 'default', + title: "证书部署类型", + value: "default", component: { - name: 'a-select', + name: "a-select", options: [ - { value: 'default', label: '默认证书' }, - { value: 'extension', label: '扩展证书' }, + { value: "default", label: "默认证书" }, + { value: "extension", label: "扩展证书" }, ], }, required: true, }) certType!: string; - async onInstance() { } + async onInstance() {} async getWafClient(access: AliyunAccess) { const client = new AliyunClient({ logger: this.logger }); @@ -113,7 +108,7 @@ export class AliyunDeployCertToWafCloud extends AbstractTaskPlugin { accessKeyId: access.accessKeyId, accessKeySecret: access.accessKeySecret, endpoint: `https://wafopenapi.${this.regionId}.aliyuncs.com`, - apiVersion: '2021-10-01', + apiVersion: "2021-10-01", }); return client; } @@ -122,17 +117,17 @@ export class AliyunDeployCertToWafCloud extends AbstractTaskPlugin { const params = { RegionId: this.regionId, }; - this.logger.info('调用DescribeInstance API', JSON.stringify(params)); - const res = await client.request('DescribeInstance', params); - this.logger.info('获取实例ID', res.InstanceId); + this.logger.info("调用DescribeInstance API", JSON.stringify(params)); + const res = await client.request("DescribeInstance", params); + this.logger.info("获取实例ID", res.InstanceId); return res.InstanceId; } async execute(): Promise { - this.logger.info('开始部署证书到阿里云WAF(云产品接入)'); + this.logger.info("开始部署证书到阿里云WAF(云产品接入)"); const access = await this.getAccess(this.accessId); let certId: any = this.cert; - if (typeof this.cert === 'object') { + if (typeof this.cert === "object") { const sslClient = new AliyunSslClient({ access, logger: this.logger, @@ -153,16 +148,16 @@ export class AliyunDeployCertToWafCloud extends AbstractTaskPlugin { } else if (casCert.certId) { certId = casCert.certId; } else { - throw new Error('证书格式错误'+JSON.stringify(this.cert)); + throw new Error("证书格式错误" + JSON.stringify(this.cert)); } } const client = await this.getWafClient(access); const instanceId = await this.getInstanceId(client); for (const cloudResourceId of this.cloudResources) { - this.logger.info('开始部署', cloudResourceId); - - if (this.certType === 'default') { + this.logger.info("开始部署", cloudResourceId); + + if (this.certType === "default") { // 部署默认证书 const params = { RegionId: this.regionId, @@ -170,10 +165,10 @@ export class AliyunDeployCertToWafCloud extends AbstractTaskPlugin { CloudResourceId: cloudResourceId, CertId: certId, }; - this.logger.info('调用ModifyCloudResourceDefaultCert API', JSON.stringify(params)); - const res = await client.request('ModifyCloudResourceDefaultCert', params); - this.logger.info('部署默认证书成功', JSON.stringify(res)); - } else if (this.certType === 'extension') { + this.logger.info("调用ModifyCloudResourceDefaultCert API", JSON.stringify(params)); + const res = await client.request("ModifyCloudResourceDefaultCert", params); + this.logger.info("部署默认证书成功", JSON.stringify(res)); + } else if (this.certType === "extension") { // 部署扩展证书 const addCertParams = { RegionId: this.regionId, @@ -181,10 +176,10 @@ export class AliyunDeployCertToWafCloud extends AbstractTaskPlugin { CloudResourceId: cloudResourceId, CertId: certId, }; - this.logger.info('调用CreateCloudResourceExtensionCert API', JSON.stringify(addCertParams)); - const addCertRes = await client.request('CreateCloudResourceExtensionCert', addCertParams); - this.logger.info('部署扩展证书成功', JSON.stringify(addCertRes)); - + this.logger.info("调用CreateCloudResourceExtensionCert API", JSON.stringify(addCertParams)); + const addCertRes = await client.request("CreateCloudResourceExtensionCert", addCertParams); + this.logger.info("部署扩展证书成功", JSON.stringify(addCertRes)); + // 清理过期扩展证书 await this.cleanupExpiredExtensionCerts(client, instanceId, cloudResourceId, certId); } @@ -193,20 +188,20 @@ export class AliyunDeployCertToWafCloud extends AbstractTaskPlugin { async cleanupExpiredExtensionCerts(client: AliyunClient, instanceId: string, cloudResourceId: string, currentCertId: string) { try { - this.logger.info('开始清理过期扩展证书, cloudResourceId: ' + cloudResourceId); - + this.logger.info("开始清理过期扩展证书, cloudResourceId: " + cloudResourceId); + // 解析CloudResourceId获取ResourceInstanceId // CloudResourceId格式:{ResourceInstanceId}-{Port}-{ResourceProduct} - const resourceInfo = cloudResourceId.split('-'); + const resourceInfo = cloudResourceId.split("-"); if (resourceInfo.length < 3) { - this.logger.warn('CloudResourceId格式不正确: ' + cloudResourceId); + this.logger.warn("CloudResourceId格式不正确: " + cloudResourceId); return; } // 从后往前解析,因为ResourceInstanceId可能包含"-" const product = resourceInfo.pop(); const port = resourceInfo.pop(); - const resourceInstanceId = resourceInfo.join('-'); - this.logger.info('ResourceInstanceId: ' + resourceInstanceId, 'Port: ' + port, 'Product: ' + product); + const resourceInstanceId = resourceInfo.join("-"); + this.logger.info("ResourceInstanceId: " + resourceInstanceId, "Port: " + port, "Product: " + product); // 查询云产品实例的证书列表 const certsParams = { InstanceId: instanceId, @@ -214,22 +209,22 @@ export class AliyunDeployCertToWafCloud extends AbstractTaskPlugin { ResourceInstanceId: resourceInstanceId, PageSize: 100, }; - this.logger.info('调用DescribeResourceInstanceCerts API: ' + JSON.stringify(certsParams)); - const certsRes = await client.request('DescribeResourceInstanceCerts', certsParams); - + this.logger.info("调用DescribeResourceInstanceCerts API: " + JSON.stringify(certsParams)); + const certsRes = await client.request("DescribeResourceInstanceCerts", certsParams); + if (!certsRes || !certsRes.Certs || certsRes.Certs.length === 0) { - this.logger.info('没有找到证书, cloudResourceId: ' + cloudResourceId); + this.logger.info("没有找到证书, cloudResourceId: " + cloudResourceId); return; } - this.logger.info('查询到的证书数量: ' + certsRes.Certs.length); + this.logger.info("查询到的证书数量: " + certsRes.Certs.length); const now = Date.now(); const expiredCerts = certsRes.Certs.filter((cert: any) => { // 检查证书是否有必要的属性 if (!cert || !cert.AfterDate || !cert.CertIdentifier) { - this.logger.warn('证书格式不正确: ' + JSON.stringify(cert)); + this.logger.warn("证书格式不正确: " + JSON.stringify(cert)); return false; } - + // 检查是否为当前部署的证书 if (cert.CertIdentifier === currentCertId) { return false; @@ -239,13 +234,13 @@ export class AliyunDeployCertToWafCloud extends AbstractTaskPlugin { // 检查是否过期 return afterDate < now; }); - + if (expiredCerts.length === 0) { - this.logger.info('没有过期的扩展证书, cloudResourceId: ' + cloudResourceId); + this.logger.info("没有过期的扩展证书, cloudResourceId: " + cloudResourceId); return; } - this.logger.info('过期的扩展证书数量: ' + expiredCerts.length); - + this.logger.info("过期的扩展证书数量: " + expiredCerts.length); + // 删除过期的扩展证书 for (const expiredCert of expiredCerts) { const deleteParams = { @@ -254,26 +249,26 @@ export class AliyunDeployCertToWafCloud extends AbstractTaskPlugin { CloudResourceId: cloudResourceId, CertId: expiredCert.CertIdentifier, }; - this.logger.info('调用DeleteCloudResourceExtensionCert API: ' + JSON.stringify(deleteParams)); - const deleteRes = await client.request('DeleteCloudResourceExtensionCert', deleteParams); - this.logger.info('删除过期扩展证书成功, certId: ' + expiredCert.CertIdentifier + ', response: ' + JSON.stringify(deleteRes)); + this.logger.info("调用DeleteCloudResourceExtensionCert API: " + JSON.stringify(deleteParams)); + const deleteRes = await client.request("DeleteCloudResourceExtensionCert", deleteParams); + this.logger.info("删除过期扩展证书成功, certId: " + expiredCert.CertIdentifier + ", response: " + JSON.stringify(deleteRes)); } - - this.logger.info('清理过期扩展证书完成, cloudResourceId: ' + cloudResourceId + ', deletedCount: ' + expiredCerts.length); + + this.logger.info("清理过期扩展证书完成, cloudResourceId: " + cloudResourceId + ", deletedCount: " + expiredCerts.length); } catch (error) { - this.logger.error('清理过期扩展证书失败, cloudResourceId: ' + cloudResourceId + ', error: ' + JSON.stringify(error)); + this.logger.error("清理过期扩展证书失败, cloudResourceId: " + cloudResourceId + ", error: " + JSON.stringify(error)); // 清理失败不影响主流程 } } async onGetCloudResourceList(data: PageSearch) { if (!this.accessId) { - throw new Error('请选择Access授权'); + throw new Error("请选择Access授权"); } const access = await this.getAccess(this.accessId); const client = await this.getWafClient(access); - const pager = new Pager(data) + const pager = new Pager(data); const instanceId = await this.getInstanceId(client); const params: any = { @@ -286,17 +281,17 @@ export class AliyunDeployCertToWafCloud extends AbstractTaskPlugin { params.ResourceInstanceId = data.searchKey; } - this.logger.info('调用DescribeCloudResourceList API', JSON.stringify(params)); - const res = await client.request('DescribeCloudResourceList', params); - this.logger.info('DescribeCloudResourceList API返回', JSON.stringify(res)); - + this.logger.info("调用DescribeCloudResourceList API", JSON.stringify(params)); + const res = await client.request("DescribeCloudResourceList", params); + this.logger.info("DescribeCloudResourceList API返回", JSON.stringify(res)); + if (!res || !res.CloudResourceList || res.CloudResourceList.length === 0) { - this.logger.warn('没有找到云产品接入的资源'); + this.logger.warn("没有找到云产品接入的资源"); return { list: [], total: 0, pageNo: pager.pageNo, - pageSize: pager.pageSize + pageSize: pager.pageSize, }; } const total = res.TotalCount || 0; @@ -315,9 +310,9 @@ export class AliyunDeployCertToWafCloud extends AbstractTaskPlugin { list, total: total, pageNo: pager.pageNo, - pageSize: pager.pageSize + pageSize: pager.pageSize, }; } } -new AliyunDeployCertToWafCloud(); \ No newline at end of file +new AliyunDeployCertToWafCloud(); diff --git a/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-waf/deploy-to-waf-cname.ts b/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-waf/deploy-to-waf-cname.ts index 0bd4f3bc2..b48e740ab 100644 --- a/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-waf/deploy-to-waf-cname.ts +++ b/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-waf/deploy-to-waf-cname.ts @@ -1,18 +1,15 @@ import { AbstractTaskPlugin, IsTaskPlugin, Pager, PageSearch, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; import { CertApplyPluginNames, CertInfo, CertReader } from "@certd/plugin-cert"; -import { - createCertDomainGetterInputDefine, - createRemoteSelectInputDefine -} from "@certd/plugin-lib"; +import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from "@certd/plugin-lib"; import { AliyunAccess } from "../../../plugin-lib/aliyun/access/index.js"; import { AliyunClient, AliyunSslClient, CasCertInfo } from "../../../plugin-lib/aliyun/lib/index.js"; @IsTaskPlugin({ - name: 'AliyunDeployCertToWaf', - title: '阿里云-部署至阿里云WAF(cname接入)', - icon: 'svg:icon-aliyun', + name: "AliyunDeployCertToWaf", + title: "阿里云-部署至阿里云WAF(cname接入)", + icon: "svg:icon-aliyun", group: pluginGroups.aliyun.key, - desc: '部署证书到阿里云WAF(cname接入),云资源的请选择另外一个waf插件', + desc: "部署证书到阿里云WAF(cname接入),云资源的请选择另外一个waf插件", needPlus: false, default: { strategy: { @@ -22,11 +19,11 @@ import { AliyunClient, AliyunSslClient, CasCertInfo } from "../../../plugin-lib/ }) export class AliyunDeployCertToWaf extends AbstractTaskPlugin { @TaskInput({ - title: '域名证书', - helper: '请选择证书申请任务输出的域名证书\n或者选择前置任务“上传证书到阿里云”任务的证书ID,可以减少上传到阿里云的证书数量', + title: "域名证书", + helper: "请选择证书申请任务输出的域名证书\n或者选择前置任务“上传证书到阿里云”任务的证书ID,可以减少上传到阿里云的证书数量", component: { - name: 'output-selector', - from: [...CertApplyPluginNames, 'uploadCertToAliyun'], + name: "output-selector", + from: [...CertApplyPluginNames, "uploadCertToAliyun"], }, required: true, }) @@ -36,14 +33,14 @@ export class AliyunDeployCertToWaf extends AbstractTaskPlugin { certDomains!: string[]; @TaskInput({ - title: 'WAF接入点', - helper: '不会选就按默认', - value: 'cn-hangzhou', + title: "WAF接入点", + helper: "不会选就按默认", + value: "cn-hangzhou", component: { - name: 'a-select', + name: "a-select", options: [ - { value: 'cn-hangzhou', label: '中国大陆-华东1(杭州)' }, - { value: 'ap-southeast-1', label: '新加坡' }, + { value: "cn-hangzhou", label: "中国大陆-华东1(杭州)" }, + { value: "ap-southeast-1", label: "新加坡" }, ], }, required: true, @@ -51,15 +48,15 @@ export class AliyunDeployCertToWaf extends AbstractTaskPlugin { regionId!: string; @TaskInput({ - title: '证书接入点', - helper: '跟上面保持一致即可', - value: 'cas.aliyuncs.com', + title: "证书接入点", + helper: "跟上面保持一致即可", + value: "cas.aliyuncs.com", component: { - name: 'a-select', + name: "a-select", options: [ - { value: 'cas.aliyuncs.com', label: '中国大陆' }, - { value: 'cas.ap-southeast-1.aliyuncs.com', label: '新加坡' }, - { value: 'cas.eu-central-1.aliyuncs.com', label: '德国(法兰克福)' }, + { value: "cas.aliyuncs.com", label: "中国大陆" }, + { value: "cas.ap-southeast-1.aliyuncs.com", label: "新加坡" }, + { value: "cas.eu-central-1.aliyuncs.com", label: "德国(法兰克福)" }, ], }, required: true, @@ -67,11 +64,11 @@ export class AliyunDeployCertToWaf extends AbstractTaskPlugin { casEndpoint!: string; @TaskInput({ - title: 'Access授权', - helper: '阿里云授权AccessKeyId、AccessKeySecret', + title: "Access授权", + helper: "阿里云授权AccessKeyId、AccessKeySecret", component: { - name: 'access-selector', - type: 'aliyun', + name: "access-selector", + type: "aliyun", }, required: true, }) @@ -79,26 +76,25 @@ export class AliyunDeployCertToWaf extends AbstractTaskPlugin { @TaskInput( createRemoteSelectInputDefine({ - title: 'CNAME站点', - helper: '请选择要部署证书的CNAME站点', + title: "CNAME站点", + helper: "请选择要部署证书的CNAME站点", action: AliyunDeployCertToWaf.prototype.onGetCnameList.name, - watches: ['accessId', 'regionId'], + watches: ["accessId", "regionId"], pager: true, search: true, }) ) cnameDomains!: string[]; - @TaskInput({ - title: 'TLS版本', - value: 'tlsv1.2', + title: "TLS版本", + value: "tlsv1.2", component: { - name: 'a-select', + name: "a-select", options: [ - { value: 'tlsv1', label: 'TLSv1' }, - { value: 'tlsv1.1', label: 'TLSv1.1' }, - { value: 'tlsv1.2', label: 'TLSv1.2' }, + { value: "tlsv1", label: "TLSv1" }, + { value: "tlsv1.1", label: "TLSv1.1" }, + { value: "tlsv1.2", label: "TLSv1.2" }, ], }, required: true, @@ -106,19 +102,17 @@ export class AliyunDeployCertToWaf extends AbstractTaskPlugin { tlsVersion!: string; @TaskInput({ - title: '启用TLSv3', + title: "启用TLSv3", value: true, component: { - name: 'a-switch', - vModel: 'checked', + name: "a-switch", + vModel: "checked", }, required: true, }) enableTLSv3!: boolean; - - - async onInstance() { } + async onInstance() {} async getWafClient(access: AliyunAccess) { const client = new AliyunClient({ logger: this.logger }); @@ -127,25 +121,25 @@ export class AliyunDeployCertToWaf extends AbstractTaskPlugin { accessKeySecret: access.accessKeySecret, //https://wafopenapi.cn-hangzhou.aliyuncs.com endpoint: `https://wafopenapi.${this.regionId}.aliyuncs.com`, - apiVersion: '2021-10-01', + apiVersion: "2021-10-01", }); return client; } async getInstanceId(client: AliyunClient) { const params = { - RegionId: 'cn-hangzhou', + RegionId: "cn-hangzhou", }; - const res = await client.request('DescribeInstance', params); - this.logger.info('获取实例ID', res.InstanceId); + const res = await client.request("DescribeInstance", params); + this.logger.info("获取实例ID", res.InstanceId); return res.InstanceId; } async execute(): Promise { - this.logger.info('开始部署证书到阿里云'); + this.logger.info("开始部署证书到阿里云"); const access = await this.getAccess(this.accessId); let certId: any = this.cert; - if (typeof this.cert === 'object') { + if (typeof this.cert === "object") { const sslClient = new AliyunSslClient({ access, logger: this.logger, @@ -163,21 +157,21 @@ export class AliyunDeployCertToWaf extends AbstractTaskPlugin { } else if (casCert.certId) { certId = casCert.certId; } else { - throw new Error('证书格式错误'+JSON.stringify(this.cert)); + throw new Error("证书格式错误" + JSON.stringify(this.cert)); } } const client = await this.getWafClient(access); const instanceId = await this.getInstanceId(client); for (const siteDomain of this.cnameDomains) { - this.logger.info('开始部署', siteDomain); + this.logger.info("开始部署", siteDomain); const params = { RegionId: this.regionId, InstanceId: instanceId, Domain: siteDomain, }; - const siteDetail = await client.request('DescribeDomainDetail', params); - this.logger.info('站点详情', JSON.stringify(siteDetail)); + const siteDetail = await client.request("DescribeDomainDetail", params); + this.logger.info("站点详情", JSON.stringify(siteDetail)); const listen = siteDetail.Listen; if (!listen) { throw new Error(`没有找到${siteDomain}的监听器`); @@ -190,7 +184,7 @@ export class AliyunDeployCertToWaf extends AbstractTaskPlugin { */ const redirect = siteDetail.Redirect; redirect.Backends = redirect.AllBackends; - listen.CertId = certId + '-' + this.regionId; + listen.CertId = certId + "-" + this.regionId; if (!listen.HttpsPorts || listen.HttpsPorts.length === 0) { listen.HttpsPorts = [443]; } @@ -200,23 +194,22 @@ export class AliyunDeployCertToWaf extends AbstractTaskPlugin { Redirect: JSON.stringify(redirect), Listen: JSON.stringify(listen), Domain: siteDomain, - TLSVersion: this.tlsVersion || 'tlsv1.2', + TLSVersion: this.tlsVersion || "tlsv1.2", EnableTLSv3: this.enableTLSv3 ?? true, }; - const res = await client.request('ModifyDomain', updateParams); - this.logger.info('部署成功', JSON.stringify(res)); + const res = await client.request("ModifyDomain", updateParams); + this.logger.info("部署成功", JSON.stringify(res)); } } async onGetCnameList(data: PageSearch) { if (!this.accessId) { - throw new Error('请选择Access授权'); + throw new Error("请选择Access授权"); } const access = await this.getAccess(this.accessId); const client = await this.getWafClient(access); - - const pager = new Pager(data) + const pager = new Pager(data); const instanceId = await this.getInstanceId(client); const params: any = { @@ -226,12 +219,12 @@ export class AliyunDeployCertToWaf extends AbstractTaskPlugin { PageNumber: pager.pageNo, }; if (data.searchKey) { - params.Domain = data.searchKey + params.Domain = data.searchKey; } - const res = await client.request('DescribeDomains', params); + const res = await client.request("DescribeDomains", params); if (!res?.Domains || res?.Domains.length === 0) { - throw new Error('没有找到CNAME接入的域名站点'); + throw new Error("没有找到CNAME接入的域名站点"); } const total = res.TotalCount; @@ -251,7 +244,7 @@ export class AliyunDeployCertToWaf extends AbstractTaskPlugin { list, total: total, pageNo: pager.pageNo, - pageSize: pager.pageSize + pageSize: pager.pageSize, }; } } diff --git a/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-waf/index.ts b/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-waf/index.ts index f0c95698b..e20927fec 100644 --- a/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-waf/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-waf/index.ts @@ -1,2 +1,2 @@ -export * from './deploy-to-waf-cname.js'; -export * from './deploy-to-waf-cloud.js'; \ No newline at end of file +export * from "./deploy-to-waf-cname.js"; +export * from "./deploy-to-waf-cloud.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/index.ts b/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/index.ts index 81ba9bb05..5c07f9dca 100644 --- a/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/index.ts @@ -1,18 +1,18 @@ -export * from './deploy-to-cdn/index.js'; -export * from './deploy-to-dcdn/index.js'; -export * from './deploy-to-oss/index.js'; -export * from './upload-to-aliyun/index.js'; -export * from './deploy-to-waf/index.js'; -export * from './deploy-to-alb/index.js'; -export * from './deploy-to-nlb/index.js'; -export * from './deploy-to-slb/index.js'; -export * from './deploy-to-fc/index.js'; -export * from './deploy-to-esa/index.js'; -export * from './deploy-to-ga/index.js'; -export * from './deploy-to-vod/index.js'; -export * from './deploy-to-live/index.js'; -export * from './deploy-to-apigateway/index.js'; -export * from './deploy-to-apig/index.js'; -export * from './deploy-to-ack/index.js'; -export * from './deploy-to-all/index.js'; -export * from './delete-expiring-cert/index.js'; +export * from "./deploy-to-cdn/index.js"; +export * from "./deploy-to-dcdn/index.js"; +export * from "./deploy-to-oss/index.js"; +export * from "./upload-to-aliyun/index.js"; +export * from "./deploy-to-waf/index.js"; +export * from "./deploy-to-alb/index.js"; +export * from "./deploy-to-nlb/index.js"; +export * from "./deploy-to-slb/index.js"; +export * from "./deploy-to-fc/index.js"; +export * from "./deploy-to-esa/index.js"; +export * from "./deploy-to-ga/index.js"; +export * from "./deploy-to-vod/index.js"; +export * from "./deploy-to-live/index.js"; +export * from "./deploy-to-apigateway/index.js"; +export * from "./deploy-to-apig/index.js"; +export * from "./deploy-to-ack/index.js"; +export * from "./deploy-to-all/index.js"; +export * from "./delete-expiring-cert/index.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/upload-to-aliyun/index.ts b/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/upload-to-aliyun/index.ts index 1ae805f98..6baf8ecf4 100644 --- a/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/upload-to-aliyun/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/upload-to-aliyun/index.ts @@ -1,7 +1,7 @@ -import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput, TaskOutput } from '@certd/pipeline'; +import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput, TaskOutput } from "@certd/pipeline"; import { CertApplyPluginNames, CertReader } from "@certd/plugin-cert"; -import { AliyunAccess } from '../../../plugin-lib/aliyun/access/index.js'; -import { AliyunSslClient, CasCertId } from '../../../plugin-lib/aliyun/lib/index.js'; +import { AliyunAccess } from "../../../plugin-lib/aliyun/access/index.js"; +import { AliyunSslClient, CasCertId } from "../../../plugin-lib/aliyun/lib/index.js"; /** * 华东1(杭州) cn-hangzhou cas.aliyuncs.com cas-vpc.cn-hangzhou.aliyuncs.com * 马来西亚(吉隆坡) ap-southeast-3 cas.ap-southeast-3.aliyuncs.com cas-vpc.ap-southeast-3.aliyuncs.com @@ -13,21 +13,21 @@ import { AliyunSslClient, CasCertId } from '../../../plugin-lib/aliyun/lib/index * 德国(法兰克福) eu-central-1 cas.eu-central-1.aliyuncs.com */ const regionDict = [ - { value: 'cn-hangzhou', endpoint: 'cas.aliyuncs.com', label: 'cn-hangzhou-中国大陆' }, - { value: 'ap-southeast-1', endpoint: 'cas.ap-southeast-1.aliyuncs.com', label: 'ap-southeast-1-新加坡(国际版选这个)' }, - { value: 'private-', endpoint: '', disabled:true, label: '以下是私有证书区域' }, - { value: 'eu-central-1', endpoint: 'cas.eu-central-1.aliyuncs.com', label: 'eu-central-1-德国(法兰克福)' }, - { value: 'ap-southeast-3', endpoint: 'cas.ap-southeast-3.aliyuncs.com', label: 'ap-southeast-3-马来西亚(吉隆坡)' }, - { value: 'ap-southeast-5', endpoint: 'cas.ap-southeast-5.aliyuncs.com', label: 'ap-southeast-5-印度尼西亚(雅加达)' }, - { value: 'cn-hongkong', endpoint: 'cas.cn-hongkong.aliyuncs.com', label: 'cn-hongkong-中国香港' }, + { value: "cn-hangzhou", endpoint: "cas.aliyuncs.com", label: "cn-hangzhou-中国大陆" }, + { value: "ap-southeast-1", endpoint: "cas.ap-southeast-1.aliyuncs.com", label: "ap-southeast-1-新加坡(国际版选这个)" }, + { value: "private-", endpoint: "", disabled: true, label: "以下是私有证书区域" }, + { value: "eu-central-1", endpoint: "cas.eu-central-1.aliyuncs.com", label: "eu-central-1-德国(法兰克福)" }, + { value: "ap-southeast-3", endpoint: "cas.ap-southeast-3.aliyuncs.com", label: "ap-southeast-3-马来西亚(吉隆坡)" }, + { value: "ap-southeast-5", endpoint: "cas.ap-southeast-5.aliyuncs.com", label: "ap-southeast-5-印度尼西亚(雅加达)" }, + { value: "cn-hongkong", endpoint: "cas.cn-hongkong.aliyuncs.com", label: "cn-hongkong-中国香港" }, ]; @IsTaskPlugin({ - name: 'uploadCertToAliyun', - title: '阿里云-上传证书到CAS', - icon: 'svg:icon-aliyun', + name: "uploadCertToAliyun", + title: "阿里云-上传证书到CAS", + icon: "svg:icon-aliyun", group: pluginGroups.aliyun.key, - desc: '上传证书到阿里云证书管理服务(CAS),如果不想在阿里云上同一份证书上传多次,可以把此任务作为前置任务,其他阿里云任务证书那一项选择此任务的输出', + desc: "上传证书到阿里云证书管理服务(CAS),如果不想在阿里云上同一份证书上传多次,可以把此任务作为前置任务,其他阿里云任务证书那一项选择此任务的输出", default: { strategy: { runStrategy: RunStrategy.SkipWhenSucceed, @@ -36,17 +36,17 @@ const regionDict = [ }) export class UploadCertToAliyun extends AbstractTaskPlugin { @TaskInput({ - title: '证书名称', - helper: '证书上传后将以此参数作为名称前缀', + title: "证书名称", + helper: "证书上传后将以此参数作为名称前缀", }) name!: string; @TaskInput({ - title: '大区', - value: 'cn-hangzhou', + title: "大区", + value: "cn-hangzhou", component: { - name: 'a-auto-complete', - vModel: 'value', + name: "a-auto-complete", + vModel: "value", options: regionDict, }, required: true, @@ -54,10 +54,10 @@ export class UploadCertToAliyun extends AbstractTaskPlugin { regionId!: string; @TaskInput({ - title: '域名证书', - helper: '请选择前置任务输出的域名证书', + title: "域名证书", + helper: "请选择前置任务输出的域名证书", component: { - name: 'output-selector', + name: "output-selector", from: [...CertApplyPluginNames], }, required: true, @@ -65,28 +65,28 @@ export class UploadCertToAliyun extends AbstractTaskPlugin { cert!: any; @TaskInput({ - title: 'Access授权', - helper: '阿里云授权AccessKeyId、AccessKeySecret', + title: "Access授权", + helper: "阿里云授权AccessKeyId、AccessKeySecret", component: { - name: 'access-selector', - type: 'aliyun', + name: "access-selector", + type: "aliyun", }, required: true, }) accessId!: string; @TaskOutput({ - title: '上传成功后的阿里云CertId', + title: "上传成功后的阿里云CertId", }) aliyunCertId!: CasCertId; async onInstance() {} async execute(): Promise { - this.logger.info('开始上传证书到阿里云证书管理CAS'); + this.logger.info("开始上传证书到阿里云证书管理CAS"); const access: AliyunAccess = await this.getAccess(this.accessId); - let endpoint = ''; + let endpoint = ""; for (const region of regionDict) { if (region.value === this.regionId) { endpoint = region.endpoint; @@ -98,12 +98,12 @@ export class UploadCertToAliyun extends AbstractTaskPlugin { logger: this.logger, endpoint, }); - let certName = "" + let certName = ""; const certReader = new CertReader(this.cert); - if (this.name){ - certName = this.appendTimeSuffix(this.name) - }else { - certName = this.buildCertName(certReader.getMainDomain()) + if (this.name) { + certName = this.appendTimeSuffix(this.name); + } else { + certName = this.buildCertName(certReader.getMainDomain()); } const certIdRes = await client.uploadCertificate({ diff --git a/packages/ui/certd-server/src/plugins/plugin-apisix/access.ts b/packages/ui/certd-server/src/plugins/plugin-apisix/access.ts index df21b626f..ad281a2a2 100644 --- a/packages/ui/certd-server/src/plugins/plugin-apisix/access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-apisix/access.ts @@ -1,6 +1,6 @@ -import {AccessInput, BaseAccess, IsAccess} from "@certd/pipeline"; -import {HttpRequestConfig} from "@certd/basic"; -import {CertInfo, CertReader} from "@certd/plugin-cert"; +import { AccessInput, BaseAccess, IsAccess } from "@certd/pipeline"; +import { HttpRequestConfig } from "@certd/basic"; +import { CertInfo, CertReader } from "@certd/plugin-cert"; /** */ @@ -8,10 +8,9 @@ import {CertInfo, CertReader} from "@certd/plugin-cert"; name: "apisix", title: "APISIX授权", desc: "", - icon: "svg:icon-lucky" + icon: "svg:icon-lucky", }) export class ApisixAccess extends BaseAccess { - @AccessInput({ title: "Apisix管理地址", component: { @@ -19,23 +18,23 @@ export class ApisixAccess extends BaseAccess { }, required: true, }) - endpoint = ''; + endpoint = ""; @AccessInput({ - title: 'ApiKey', + title: "ApiKey", component: { - placeholder: 'ApiKey', + placeholder: "ApiKey", }, helper: "[参考文档](https://apisix.apache.org/docs/apisix/admin-api/#using-environment-variables)在config中配置admin apiKey", required: true, encrypt: true, }) - apiKey = ''; + apiKey = ""; @AccessInput({ - title: '版本', + title: "版本", component: { - name:"a-select", + name: "a-select", options: [ { label: "v3.x", @@ -45,78 +44,77 @@ export class ApisixAccess extends BaseAccess { label: "v2.x", value: "2", }, - ] + ], }, helper: "apisix系统的版本", - value:"3", + value: "3", required: true, }) - version = '3'; - + version = "3"; @AccessInput({ title: "测试", component: { name: "api-test", - action: "TestRequest" + action: "TestRequest", }, - helper: "点击测试接口是否正常" + helper: "点击测试接口是否正常", }) testRequest = true; async onTestRequest() { await this.getCertList(); - return "ok" + return "ok"; } - async getCertList(){ + async getCertList() { const sslPath = this.getSslPath(); const req = { - url :`/apisix/admin/${sslPath}`, + url: `/apisix/admin/${sslPath}`, method: "get", - } + }; return await this.doRequest(req); } - getSslPath(){ - const sslPath = this.version === '3' ? 'ssls' : 'ssl'; + getSslPath() { + const sslPath = this.version === "3" ? "ssls" : "ssl"; return sslPath; } - async createCert(opts:{cert:CertInfo}){ - const certReader = new CertReader(opts.cert) + async createCert(opts: { cert: CertInfo }) { + const certReader = new CertReader(opts.cert); const sslPath = this.getSslPath(); const req = { - url :`/apisix/admin/${sslPath}`, + url: `/apisix/admin/${sslPath}`, method: "post", - data:{ + data: { cert: opts.cert.crt, key: opts.cert.key, - snis: certReader.getAllDomains() - } - } + snis: certReader.getAllDomains(), + }, + }; return await this.doRequest(req); } - async updateCert (opts:{cert:CertInfo,id:string}){ - const certReader = new CertReader(opts.cert) + async updateCert(opts: { cert: CertInfo; id: string }) { + const certReader = new CertReader(opts.cert); const sslPath = this.getSslPath(); const req = { - url :`/apisix/admin/${sslPath}/${opts.id}`, + url: `/apisix/admin/${sslPath}/${opts.id}`, method: "put", - data:{ + data: { cert: opts.cert.crt, key: opts.cert.key, - snis: certReader.getAllDomains() - } - } + snis: certReader.getAllDomains(), + }, + }; return await this.doRequest(req); } - async doRequest(req: HttpRequestConfig){ + async doRequest(req: HttpRequestConfig) { const headers = { "X-API-KEY": this.apiKey, - ...req.headers + ...req.headers, }; return await this.ctx.http.request({ headers, @@ -125,9 +123,6 @@ export class ApisixAccess extends BaseAccess { logRes: false, }); } - - } - new ApisixAccess(); diff --git a/packages/ui/certd-server/src/plugins/plugin-apisix/plugins/index.ts b/packages/ui/certd-server/src/plugins/plugin-apisix/plugins/index.ts index 705339de6..a77684b4b 100644 --- a/packages/ui/certd-server/src/plugins/plugin-apisix/plugins/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-apisix/plugins/index.ts @@ -1 +1 @@ -import "./plugin-refresh-cert.js" +import "./plugin-refresh-cert.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-apisix/plugins/plugin-refresh-cert.ts b/packages/ui/certd-server/src/plugins/plugin-apisix/plugins/plugin-refresh-cert.ts index 9c13fd654..542ad0a64 100644 --- a/packages/ui/certd-server/src/plugins/plugin-apisix/plugins/plugin-refresh-cert.ts +++ b/packages/ui/certd-server/src/plugins/plugin-apisix/plugins/plugin-refresh-cert.ts @@ -1,7 +1,7 @@ -import {IsTaskPlugin, PageSearch, pluginGroups, RunStrategy, TaskInput} from "@certd/pipeline"; -import {CertApplyPluginNames, CertInfo} from "@certd/plugin-cert"; -import {createCertDomainGetterInputDefine, createRemoteSelectInputDefine} from "@certd/plugin-lib"; -import {ApisixAccess} from "../access.js"; +import { IsTaskPlugin, PageSearch, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; +import { CertApplyPluginNames, CertInfo } from "@certd/plugin-cert"; +import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from "@certd/plugin-lib"; +import { ApisixAccess } from "../access.js"; import { AbstractPlusTaskPlugin } from "@certd/plugin-plus"; @IsTaskPlugin({ //命名规范,插件类型+功能(就是目录plugin-demo中的demo),大写字母开头,驼峰命名 @@ -15,9 +15,9 @@ import { AbstractPlusTaskPlugin } from "@certd/plugin-plus"; default: { //默认值配置照抄即可 strategy: { - runStrategy: RunStrategy.SkipWhenSucceed - } - } + runStrategy: RunStrategy.SkipWhenSucceed, + }, + }, }) //类名规范,跟上面插件名称(name)一致 export class ApisixRefreshCDNCert extends AbstractPlusTaskPlugin { @@ -27,8 +27,8 @@ export class ApisixRefreshCDNCert extends AbstractPlusTaskPlugin { helper: "请选择前置任务输出的域名证书", component: { name: "output-selector", - from: [...CertApplyPluginNames] - } + from: [...CertApplyPluginNames], + }, // required: true, // 必填 }) cert!: CertInfo; @@ -41,9 +41,9 @@ export class ApisixRefreshCDNCert extends AbstractPlusTaskPlugin { title: "Apisix授权", component: { name: "access-selector", - type: "apisix" //固定授权类型 + type: "apisix", //固定授权类型 }, - required: true //必填 + required: true, //必填 }) accessId!: string; // @@ -54,14 +54,13 @@ export class ApisixRefreshCDNCert extends AbstractPlusTaskPlugin { helper: "要更新的证书id,如果这里没有,请先给手动绑定一次证书", action: ApisixRefreshCDNCert.prototype.onGetCertList.name, pager: false, - search: false + search: false, }) ) certList!: string[]; //插件实例化时执行的方法 - async onInstance() { - } + async onInstance() {} //插件执行方法 async execute(): Promise { @@ -74,7 +73,7 @@ export class ApisixRefreshCDNCert extends AbstractPlusTaskPlugin { await access.updateCert({ id: certId, - cert: this.cert + cert: this.cert, }); this.logger.info(`----------- 更新证书${certId}成功`); } @@ -85,13 +84,12 @@ export class ApisixRefreshCDNCert extends AbstractPlusTaskPlugin { async onGetCertList(data: PageSearch = {}) { const access = await this.getAccess(this.accessId); - const res = await access.getCertList() - const list = res.list + const res = await access.getCertList(); + const list = res.list; if (!list || list.length === 0) { throw new Error("没有找到证书,你可以直接手动输入id,如果id不存在将自动创建"); } - /** * certificate-id * name @@ -101,7 +99,7 @@ export class ApisixRefreshCDNCert extends AbstractPlusTaskPlugin { return { label: `${item.value.snis[0]}<${item.value.id}>`, value: item.value.id, - domain: item.value.snis + domain: item.value.snis, }; }); return { diff --git a/packages/ui/certd-server/src/plugins/plugin-aws-cn/access.ts b/packages/ui/certd-server/src/plugins/plugin-aws-cn/access.ts index 0ef6da854..8aa1881b5 100644 --- a/packages/ui/certd-server/src/plugins/plugin-aws-cn/access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-aws-cn/access.ts @@ -1,33 +1,32 @@ -import { AccessInput, BaseAccess, IsAccess } from '@certd/pipeline'; +import { AccessInput, BaseAccess, IsAccess } from "@certd/pipeline"; @IsAccess({ - name: 'aws-cn', - title: '亚马逊云科技(国区)授权', - desc: '', - icon: 'svg:icon-aws', + name: "aws-cn", + title: "亚马逊云科技(国区)授权", + desc: "", + icon: "svg:icon-aws", }) export class AwsCNAccess extends BaseAccess { @AccessInput({ - title: 'accessKeyId', + title: "accessKeyId", component: { - placeholder: 'accessKeyId', + placeholder: "accessKeyId", }, - helper: - '右上角->安全凭证->访问密钥,[点击前往](https://cn-north-1.console.amazonaws.cn/iam/home?region=cn-north-1#/security_credentials/access-key-wizard#)', + helper: "右上角->安全凭证->访问密钥,[点击前往](https://cn-north-1.console.amazonaws.cn/iam/home?region=cn-north-1#/security_credentials/access-key-wizard#)", required: true, }) - accessKeyId = ''; + accessKeyId = ""; @AccessInput({ - title: 'secretAccessKey', + title: "secretAccessKey", component: { - placeholder: 'secretAccessKey', + placeholder: "secretAccessKey", }, required: true, encrypt: true, - helper: '请妥善保管您的安全访问密钥。您可以在AWS管理控制台的IAM中创建新的访问密钥。', + helper: "请妥善保管您的安全访问密钥。您可以在AWS管理控制台的IAM中创建新的访问密钥。", }) - secretAccessKey = ''; + secretAccessKey = ""; } new AwsCNAccess(); diff --git a/packages/ui/certd-server/src/plugins/plugin-aws-cn/constants.ts b/packages/ui/certd-server/src/plugins/plugin-aws-cn/constants.ts index 9f176b3f0..55907be8a 100644 --- a/packages/ui/certd-server/src/plugins/plugin-aws-cn/constants.ts +++ b/packages/ui/certd-server/src/plugins/plugin-aws-cn/constants.ts @@ -1,4 +1,4 @@ export const AwsCNRegions = [ - { label: 'cn-north-1', value: 'cn-north-1' }, - { label: 'cn-northwest-1', value: 'cn-northwest-1' }, -]; \ No newline at end of file + { label: "cn-north-1", value: "cn-north-1" }, + { label: "cn-northwest-1", value: "cn-northwest-1" }, +]; diff --git a/packages/ui/certd-server/src/plugins/plugin-aws-cn/index.ts b/packages/ui/certd-server/src/plugins/plugin-aws-cn/index.ts index 08fba9992..59fc3dda9 100644 --- a/packages/ui/certd-server/src/plugins/plugin-aws-cn/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-aws-cn/index.ts @@ -1,3 +1,3 @@ -export * from './plugins/index.js'; -export * from './access.js'; -export * from './constants.js'; \ No newline at end of file +export * from "./plugins/index.js"; +export * from "./access.js"; +export * from "./constants.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-aws-cn/libs/aws-iam-client.ts b/packages/ui/certd-server/src/plugins/plugin-aws-cn/libs/aws-iam-client.ts index 492e8ca7d..11083e7da 100644 --- a/packages/ui/certd-server/src/plugins/plugin-aws-cn/libs/aws-iam-client.ts +++ b/packages/ui/certd-server/src/plugins/plugin-aws-cn/libs/aws-iam-client.ts @@ -1,6 +1,6 @@ // 导入所需的 SDK 模块 -import { AwsCNAccess } from '../access.js'; -import { CertInfo } from '@certd/plugin-cert'; +import { AwsCNAccess } from "../access.js"; +import { CertInfo } from "@certd/plugin-cert"; type AwsIAMClientOptions = { access: AwsCNAccess; region: string }; @@ -15,7 +15,7 @@ export class AwsIAMClient { } async importCertificate(certInfo: CertInfo, certName: string) { // 创建 IAM 客户端 - const { IAMClient, UploadServerCertificateCommand } = await import('@aws-sdk/client-iam'); + const { IAMClient, UploadServerCertificateCommand } = await import("@aws-sdk/client-iam"); const iamClient = new IAMClient({ region: this.region, // 替换为您的 AWS 区域 credentials: { @@ -24,18 +24,18 @@ export class AwsIAMClient { }, }); - const cert = certInfo.crt.split('-----END CERTIFICATE-----')[0] + '-----END CERTIFICATE-----'; - const chain = certInfo.crt.split('-----END CERTIFICATE-----\n')[1]; + const cert = certInfo.crt.split("-----END CERTIFICATE-----")[0] + "-----END CERTIFICATE-----"; + const chain = certInfo.crt.split("-----END CERTIFICATE-----\n")[1]; // 构建上传参数 const command = new UploadServerCertificateCommand({ - Path: '/cloudfront/', + Path: "/cloudfront/", ServerCertificateName: certName, CertificateBody: cert, PrivateKey: certInfo.key, - CertificateChain: chain - }) + CertificateChain: chain, + }); const data = await iamClient.send(command); - console.log('Upload successful:', data); + console.log("Upload successful:", data); // 返回证书 ID return data.ServerCertificateMetadata.ServerCertificateId; } diff --git a/packages/ui/certd-server/src/plugins/plugin-aws-cn/plugins/index.ts b/packages/ui/certd-server/src/plugins/plugin-aws-cn/plugins/index.ts index b2dfca5d3..a548de6fd 100644 --- a/packages/ui/certd-server/src/plugins/plugin-aws-cn/plugins/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-aws-cn/plugins/index.ts @@ -1 +1 @@ -export * from './plugin-deploy-to-cloudfront.js'; +export * from "./plugin-deploy-to-cloudfront.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-aws-cn/plugins/plugin-deploy-to-cloudfront.ts b/packages/ui/certd-server/src/plugins/plugin-aws-cn/plugins/plugin-deploy-to-cloudfront.ts index 90b0d566c..662cf2b1f 100644 --- a/packages/ui/certd-server/src/plugins/plugin-aws-cn/plugins/plugin-deploy-to-cloudfront.ts +++ b/packages/ui/certd-server/src/plugins/plugin-aws-cn/plugins/plugin-deploy-to-cloudfront.ts @@ -3,14 +3,13 @@ import { CertApplyPluginNames, CertInfo } from "@certd/plugin-cert"; import { AwsCNAccess } from "../access.js"; import { AwsIAMClient } from "../libs/aws-iam-client.js"; import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from "@certd/plugin-lib"; -import { AwsCNRegions } from '../constants.js'; - +import { AwsCNRegions } from "../constants.js"; @IsTaskPlugin({ - name: 'AwsCNDeployToCloudFront', - title: 'AWS(国区)-部署证书到CloudFront', - desc: '部署证书到 AWS CloudFront', - icon: 'svg:icon-aws', + name: "AwsCNDeployToCloudFront", + title: "AWS(国区)-部署证书到CloudFront", + desc: "部署证书到 AWS CloudFront", + icon: "svg:icon-aws", group: pluginGroups.aws.key, needPlus: false, default: { @@ -21,11 +20,11 @@ import { AwsCNRegions } from '../constants.js'; }) export class AwsCNDeployToCloudFront extends AbstractTaskPlugin { @TaskInput({ - title: '域名证书', - helper: '请选择前置任务输出的域名证书', + title: "域名证书", + helper: "请选择前置任务输出的域名证书", component: { - name: 'output-selector', - from: [...CertApplyPluginNames, 'AwsUploadToACM'], + name: "output-selector", + from: [...CertApplyPluginNames, "AwsUploadToACM"], }, required: true, }) @@ -35,11 +34,11 @@ export class AwsCNDeployToCloudFront extends AbstractTaskPlugin { certDomains!: string[]; @TaskInput({ - title: '区域', - helper: '证书上传区域', + title: "区域", + helper: "证书上传区域", component: { - name: 'a-auto-complete', - vModel: 'value', + name: "a-auto-complete", + vModel: "value", options: AwsCNRegions, }, required: true, @@ -47,26 +46,26 @@ export class AwsCNDeployToCloudFront extends AbstractTaskPlugin { region!: string; @TaskInput({ - title: 'Access授权', - helper: 'aws的授权', + title: "Access授权", + helper: "aws的授权", component: { - name: 'access-selector', - type: 'aws-cn', + name: "access-selector", + type: "aws-cn", }, required: true, }) accessId!: string; @TaskInput({ - title: '证书名称', - helper: '上传后将以此名称作为前缀备注', + title: "证书名称", + helper: "上传后将以此名称作为前缀备注", }) certName!: string; @TaskInput( createRemoteSelectInputDefine({ - title: '分配ID', - helper: '请选择distributions id', + title: "分配ID", + helper: "请选择distributions id", action: AwsCNDeployToCloudFront.prototype.onGetDistributions.name, required: true, }) @@ -79,13 +78,13 @@ export class AwsCNDeployToCloudFront extends AbstractTaskPlugin { const access = await this.getAccess(this.accessId); let certId = this.cert as string; - if (typeof this.cert !== 'string') { + if (typeof this.cert !== "string") { //先上传 certId = await this.uploadToIAM(access, this.cert); } //部署到CloudFront - const { CloudFrontClient, UpdateDistributionCommand, GetDistributionConfigCommand } = await import('@aws-sdk/client-cloudfront'); + const { CloudFrontClient, UpdateDistributionCommand, GetDistributionConfigCommand } = await import("@aws-sdk/client-cloudfront"); const cloudFrontClient = new CloudFrontClient({ region: this.region, credentials: { @@ -116,7 +115,7 @@ export class AwsCNDeployToCloudFront extends AbstractTaskPlugin { await cloudFrontClient.send(updateDistributionCommand); this.logger.info(`部署${distributionId}完成:`); } - this.logger.info('部署完成'); + this.logger.info("部署完成"); } private async uploadToIAM(access: AwsCNAccess, cert: CertInfo) { @@ -125,18 +124,18 @@ export class AwsCNDeployToCloudFront extends AbstractTaskPlugin { region: this.region, }); const awsCertID = await acmClient.importCertificate(cert, this.appendTimeSuffix(this.certName)); - this.logger.info('证书上传成功,id=', awsCertID); + this.logger.info("证书上传成功,id=", awsCertID); return awsCertID; } //查找分配ID列表选项 async onGetDistributions() { if (!this.accessId) { - throw new Error('请选择Access授权'); + throw new Error("请选择Access授权"); } const access = await this.getAccess(this.accessId); - const { CloudFrontClient, ListDistributionsCommand } = await import('@aws-sdk/client-cloudfront'); + const { CloudFrontClient, ListDistributionsCommand } = await import("@aws-sdk/client-cloudfront"); const cloudFrontClient = new CloudFrontClient({ region: this.region, credentials: { @@ -149,7 +148,7 @@ export class AwsCNDeployToCloudFront extends AbstractTaskPlugin { const data = await cloudFrontClient.send(listDistributionsCommand); const distributions = data.DistributionList?.Items; if (!distributions || distributions.length === 0) { - throw new Error('找不到CloudFront分配ID,您可以手动输入'); + throw new Error("找不到CloudFront分配ID,您可以手动输入"); } const options = distributions.map((item: any) => { diff --git a/packages/ui/certd-server/src/plugins/plugin-aws/access.ts b/packages/ui/certd-server/src/plugins/plugin-aws/access.ts index b74bfb252..d4a12606d 100644 --- a/packages/ui/certd-server/src/plugins/plugin-aws/access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-aws/access.ts @@ -1,66 +1,62 @@ -import { AccessInput, BaseAccess, IsAccess } from '@certd/pipeline'; -import { AwsRegions } from './constants.js'; -import { AwsClient } from './libs/aws-client.js'; +import { AccessInput, BaseAccess, IsAccess } from "@certd/pipeline"; +import { AwsRegions } from "./constants.js"; +import { AwsClient } from "./libs/aws-client.js"; @IsAccess({ - name: 'aws', - title: '亚马逊云aws授权', - desc: '', - icon: 'svg:icon-aws', + name: "aws", + title: "亚马逊云aws授权", + desc: "", + icon: "svg:icon-aws", }) export class AwsAccess extends BaseAccess { @AccessInput({ - title: 'accessKeyId', + title: "accessKeyId", component: { - placeholder: 'accessKeyId', + placeholder: "accessKeyId", }, - helper: - '右上角->安全凭证->访问密钥,[点击前往](https://us-east-1.console.aws.amazon.com/iam/home?region=ap-east-1#/security_credentials/access-key-wizard)', + helper: "右上角->安全凭证->访问密钥,[点击前往](https://us-east-1.console.aws.amazon.com/iam/home?region=ap-east-1#/security_credentials/access-key-wizard)", required: true, }) - accessKeyId = ''; + accessKeyId = ""; @AccessInput({ - title: 'secretAccessKey', + title: "secretAccessKey", component: { - placeholder: 'secretAccessKey', + placeholder: "secretAccessKey", }, required: true, encrypt: true, - helper: '请妥善保管您的安全访问密钥。您可以在AWS管理控制台的IAM中创建新的访问密钥。', + helper: "请妥善保管您的安全访问密钥。您可以在AWS管理控制台的IAM中创建新的访问密钥。", }) - secretAccessKey = ''; + secretAccessKey = ""; @AccessInput({ - title: 'region', + title: "region", component: { name: "a-select", options: AwsRegions, }, required: true, - helper: '请选择您的默认AWS区域,主要区分中国区还是海外区即可', + helper: "请选择您的默认AWS区域,主要区分中国区还是海外区即可", options: AwsRegions, }) - region = ''; - + region = ""; @AccessInput({ title: "测试", component: { name: "api-test", - action: "TestRequest" + action: "TestRequest", }, - helper: "测试授权是否正确" + helper: "测试授权是否正确", }) testRequest = true; async onTestRequest() { - - const client = new AwsClient({ access: this, logger: this.ctx.logger, region: this.region || 'us-east-1' }); + const client = new AwsClient({ access: this, logger: this.ctx.logger, region: this.region || "us-east-1" }); await client.getCallerIdentity(); return "ok"; } - } new AwsAccess(); diff --git a/packages/ui/certd-server/src/plugins/plugin-aws/aws-route53-provider.ts b/packages/ui/certd-server/src/plugins/plugin-aws/aws-route53-provider.ts index 5685e545f..2a212cd3d 100644 --- a/packages/ui/certd-server/src/plugins/plugin-aws/aws-route53-provider.ts +++ b/packages/ui/certd-server/src/plugins/plugin-aws/aws-route53-provider.ts @@ -1,61 +1,58 @@ -import { AbstractDnsProvider, CreateRecordOptions, DomainRecord, IsDnsProvider, RemoveRecordOptions } from '@certd/plugin-cert'; -import { AwsClient } from './libs/aws-client.js'; -import { AwsAccess } from './access.js'; -import { PageRes, PageSearch } from '@certd/pipeline'; - +import { AbstractDnsProvider, CreateRecordOptions, DomainRecord, IsDnsProvider, RemoveRecordOptions } from "@certd/plugin-cert"; +import { AwsClient } from "./libs/aws-client.js"; +import { AwsAccess } from "./access.js"; +import { PageRes, PageSearch } from "@certd/pipeline"; @IsDnsProvider({ - name: 'aws-route53', - title: 'AWS Route53', - desc: 'AWS Route53 DNS解析提供商', - accessType: 'aws', - icon: 'svg:icon-aws', - order:0, + name: "aws-route53", + title: "AWS Route53", + desc: "AWS Route53 DNS解析提供商", + accessType: "aws", + icon: "svg:icon-aws", + order: 0, }) export class AwsRoute53Provider extends AbstractDnsProvider { - client: AwsClient; async onInstance() { - const access: AwsAccess = this.ctx.access as AwsAccess - this.client = new AwsClient({ access: access, logger: this.logger, region:access.region || 'us-east-1' }); + const access: AwsAccess = this.ctx.access as AwsAccess; + this.client = new AwsClient({ access: access, logger: this.logger, region: access.region || "us-east-1" }); } async createRecord(options: CreateRecordOptions): Promise { const { fullRecord, value, type, domain } = options; - this.logger.info('添加域名解析:', fullRecord, value, domain); + this.logger.info("添加域名解析:", fullRecord, value, domain); // const domain = await this.matchDomain(fullRecord); - const {ZoneId,ZoneName} = await this.client.route53GetHostedZoneId(domain); + const { ZoneId, ZoneName } = await this.client.route53GetHostedZoneId(domain); this.logger.info(`获取到hostedZoneId:${ZoneId},name:${ZoneName},domain:${domain}`); - + await this.client.route53ChangeRecord({ hostedZoneId: ZoneId, fullRecord: fullRecord, type: type, value: value, - action: 'UPSERT', + action: "UPSERT", }); return { hostedZoneId: ZoneId, - } + }; } - async removeRecord(options: RemoveRecordOptions): Promise { - const { fullRecord, value,type } = options.recordReq; + const { fullRecord, value, type } = options.recordReq; const record = options.recordRes; const hostedZoneId = record.hostedZoneId; - try{ + try { await this.client.route53ChangeRecord({ hostedZoneId: hostedZoneId, fullRecord: fullRecord, type: type, value: value, - action: 'DELETE', + action: "DELETE", }); - }catch(e){ - this.logger.warn(`删除域名解析失败:${e.message} : ${hostedZoneId} ${fullRecord} ${value} ${type} `, ); + } catch (e) { + this.logger.warn(`删除域名解析失败:${e.message} : ${hostedZoneId} ${fullRecord} ${value} ${type} `); } } diff --git a/packages/ui/certd-server/src/plugins/plugin-aws/constants.ts b/packages/ui/certd-server/src/plugins/plugin-aws/constants.ts index 03de965a9..be01b1046 100644 --- a/packages/ui/certd-server/src/plugins/plugin-aws/constants.ts +++ b/packages/ui/certd-server/src/plugins/plugin-aws/constants.ts @@ -1,37 +1,36 @@ - export const AwsRegions = [ - { label: '------中国区------', value: 'cn',disabled: true }, - { label: '北京', value: 'cn-north-1' }, - { label: '宁夏', value: 'cn-northwest-1' }, - { label: '------海外-----', value: 'out',disabled: true }, - { label: 'us-east-1', value: 'us-east-1' }, - { label: 'us-east-2', value: 'us-east-2' }, - { label: 'us-west-1', value: 'us-west-1' }, - { label: 'us-west-2', value: 'us-west-2' }, - { label: 'af-south-1', value: 'af-south-1' }, - { label: 'ap-east-1', value: 'ap-east-1' }, - { label: 'ap-northeast-1', value: 'ap-northeast-1' }, - { label: 'ap-northeast-2', value: 'ap-northeast-2' }, - { label: 'ap-northeast-3', value: 'ap-northeast-3' }, - { label: 'ap-south-1', value: 'ap-south-1' }, - { label: 'ap-south-2', value: 'ap-south-2' }, - { label: 'ap-southeast-1', value: 'ap-southeast-1' }, - { label: 'ap-southeast-2', value: 'ap-southeast-2' }, - { label: 'ap-southeast-3', value: 'ap-southeast-3' }, - { label: 'ap-southeast-4', value: 'ap-southeast-4' }, - { label: 'ap-southeast-5', value: 'ap-southeast-5' }, - { label: 'ca-central-1', value: 'ca-central-1' }, - { label: 'ca-west-1', value: 'ca-west-1' }, - { label: 'eu-central-1', value: 'eu-central-1' }, - { label: 'eu-central-2', value: 'eu-central-2' }, - { label: 'eu-north-1', value: 'eu-north-1' }, - { label: 'eu-south-1', value: 'eu-south-1' }, - { label: 'eu-south-2', value: 'eu-south-2' }, - { label: 'eu-west-1', value: 'eu-west-1' }, - { label: 'eu-west-2', value: 'eu-west-2' }, - { label: 'eu-west-3', value: 'eu-west-3' }, - { label: 'il-central-1', value: 'il-central-1' }, - { label: 'me-central-1', value: 'me-central-1' }, - { label: 'me-south-1', value: 'me-south-1' }, - { label: 'sa-east-1', value: 'sa-east-1' }, -]; \ No newline at end of file + { label: "------中国区------", value: "cn", disabled: true }, + { label: "北京", value: "cn-north-1" }, + { label: "宁夏", value: "cn-northwest-1" }, + { label: "------海外-----", value: "out", disabled: true }, + { label: "us-east-1", value: "us-east-1" }, + { label: "us-east-2", value: "us-east-2" }, + { label: "us-west-1", value: "us-west-1" }, + { label: "us-west-2", value: "us-west-2" }, + { label: "af-south-1", value: "af-south-1" }, + { label: "ap-east-1", value: "ap-east-1" }, + { label: "ap-northeast-1", value: "ap-northeast-1" }, + { label: "ap-northeast-2", value: "ap-northeast-2" }, + { label: "ap-northeast-3", value: "ap-northeast-3" }, + { label: "ap-south-1", value: "ap-south-1" }, + { label: "ap-south-2", value: "ap-south-2" }, + { label: "ap-southeast-1", value: "ap-southeast-1" }, + { label: "ap-southeast-2", value: "ap-southeast-2" }, + { label: "ap-southeast-3", value: "ap-southeast-3" }, + { label: "ap-southeast-4", value: "ap-southeast-4" }, + { label: "ap-southeast-5", value: "ap-southeast-5" }, + { label: "ca-central-1", value: "ca-central-1" }, + { label: "ca-west-1", value: "ca-west-1" }, + { label: "eu-central-1", value: "eu-central-1" }, + { label: "eu-central-2", value: "eu-central-2" }, + { label: "eu-north-1", value: "eu-north-1" }, + { label: "eu-south-1", value: "eu-south-1" }, + { label: "eu-south-2", value: "eu-south-2" }, + { label: "eu-west-1", value: "eu-west-1" }, + { label: "eu-west-2", value: "eu-west-2" }, + { label: "eu-west-3", value: "eu-west-3" }, + { label: "il-central-1", value: "il-central-1" }, + { label: "me-central-1", value: "me-central-1" }, + { label: "me-south-1", value: "me-south-1" }, + { label: "sa-east-1", value: "sa-east-1" }, +]; diff --git a/packages/ui/certd-server/src/plugins/plugin-aws/index.ts b/packages/ui/certd-server/src/plugins/plugin-aws/index.ts index f3bd691cc..ebcf22b70 100644 --- a/packages/ui/certd-server/src/plugins/plugin-aws/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-aws/index.ts @@ -1,4 +1,4 @@ -export * from './plugins/index.js'; -export * from './access.js'; -export * from './aws-route53-provider.js'; -export * from './constants.js'; \ No newline at end of file +export * from "./plugins/index.js"; +export * from "./access.js"; +export * from "./aws-route53-provider.js"; +export * from "./constants.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-aws/libs/aws-client.ts b/packages/ui/certd-server/src/plugins/plugin-aws/libs/aws-client.ts index 18a3d2b0c..767ea577e 100644 --- a/packages/ui/certd-server/src/plugins/plugin-aws/libs/aws-client.ts +++ b/packages/ui/certd-server/src/plugins/plugin-aws/libs/aws-client.ts @@ -1,9 +1,9 @@ // 导入所需的 SDK 模块 -import { AwsAccess } from '../access.js'; -import { CertInfo, DomainRecord } from '@certd/plugin-cert'; -import { ILogger, utils } from '@certd/basic'; -import { PageRes, PageSearch } from '@certd/pipeline'; -type AwsClientOptions = { access: AwsAccess; region: string, logger: ILogger }; +import { AwsAccess } from "../access.js"; +import { CertInfo, DomainRecord } from "@certd/plugin-cert"; +import { ILogger, utils } from "@certd/basic"; +import { PageRes, PageSearch } from "@certd/pipeline"; +type AwsClientOptions = { access: AwsAccess; region: string; logger: ILogger }; /** * https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/route-53-domains/ @@ -21,7 +21,7 @@ export class AwsClient { } async importCertificate(certInfo: CertInfo) { // 创建 ACM 客户端 - const { ACMClient, ImportCertificateCommand } = await import('@aws-sdk/client-acm'); + const { ACMClient, ImportCertificateCommand } = await import("@aws-sdk/client-acm"); const acmClient = new ACMClient({ region: this.region, // 替换为您的 AWS 区域 credentials: { @@ -30,7 +30,7 @@ export class AwsClient { }, }); - const cert = certInfo.crt.split('-----END CERTIFICATE-----')[0] + '-----END CERTIFICATE-----'; + const cert = certInfo.crt.split("-----END CERTIFICATE-----")[0] + "-----END CERTIFICATE-----"; // 构建上传参数 const data = await acmClient.send( new ImportCertificateCommand({ @@ -39,17 +39,16 @@ export class AwsClient { // CertificateChain: certificateChain, // 可选 }) ); - console.log('Upload successful:', data); + console.log("Upload successful:", data); // 返回证书 ARN(Amazon Resource Name) return data.CertificateArn; } - async getCallerIdentity() { - const { STSClient, GetCallerIdentityCommand } = await import ("@aws-sdk/client-sts"); + const { STSClient, GetCallerIdentityCommand } = await import("@aws-sdk/client-sts"); const client = new STSClient({ - region: this.access.region || 'us-east-1', + region: this.access.region || "us-east-1", credentials: { accessKeyId: this.access.accessKeyId, // 从环境变量中读取 secretAccessKey: this.access.secretAccessKey, @@ -64,9 +63,8 @@ export class AwsClient { return response; } - async route53ClientGet() { - const { Route53Client } = await import('@aws-sdk/client-route-53'); + const { Route53Client } = await import("@aws-sdk/client-route-53"); return new Route53Client({ region: this.region, credentials: { @@ -76,20 +74,21 @@ export class AwsClient { }); } - async route53GetHostedZoneId(name: string): Promise<{ ZoneId: string, ZoneName: string }> { + async route53GetHostedZoneId(name: string): Promise<{ ZoneId: string; ZoneName: string }> { const hostedZones = await this.route53ListHostedZones(name); - const zoneId = hostedZones[0].Id.replace('/hostedzone/', ''); + const zoneId = hostedZones[0].Id.replace("/hostedzone/", ""); this.logger.info(`获取到hostedZoneId:${zoneId},name:${hostedZones[0].Name}`); return { ZoneId: zoneId, ZoneName: hostedZones[0].Name, }; } - async route53ListHostedZones(name: string): Promise<{ Id: string, Name: string }[]> { + async route53ListHostedZones(name: string): Promise<{ Id: string; Name: string }[]> { const { ListHostedZonesByNameCommand } = await import("@aws-sdk/client-route-53"); // ES Modules import const client = await this.route53ClientGet(); - const input = { // ListHostedZonesByNameRequest + const input = { + // ListHostedZonesByNameRequest DNSName: name, }; const command = new ListHostedZonesByNameCommand(input); @@ -105,7 +104,8 @@ export class AwsClient { const { ListHostedZonesByNameCommand } = await import("@aws-sdk/client-route-53"); // ES Modules import const client = await this.route53ClientGet(); - const input: any = { // ListHostedZonesByNameRequest + const input: any = { + // ListHostedZonesByNameRequest MaxItems: req.pageSize, }; if (req.searchKey) { @@ -115,7 +115,7 @@ export class AwsClient { const response = await this.doRequest(() => client.send(command)); let list: any[] = response.HostedZones || []; list = list.map((item: any) => ({ - id: item.Id.replace('/hostedzone/', ''), + id: item.Id.replace("/hostedzone/", ""), domain: item.Name, })); return { @@ -124,24 +124,29 @@ export class AwsClient { }; } - async route53ChangeRecord(req: { - hostedZoneId: string, fullRecord: string, type: string, value: string, action: "UPSERT" | "DELETE" - }) { + async route53ChangeRecord(req: { hostedZoneId: string; fullRecord: string; type: string; value: string; action: "UPSERT" | "DELETE" }) { const { ChangeResourceRecordSetsCommand } = await import("@aws-sdk/client-route-53"); // ES Modules import // const { Route53Client, ChangeResourceRecordSetsCommand } = require("@aws-sdk/client-route-53"); // CommonJS import // import type { Route53ClientConfig } from "@aws-sdk/client-route-53"; const client = await this.route53ClientGet(); - const input = { // ChangeResourceRecordSetsRequest + const input = { + // ChangeResourceRecordSetsRequest HostedZoneId: req.hostedZoneId, // required - ChangeBatch: { // ChangeBatch - Changes: [ // Changes // required - { // Change + ChangeBatch: { + // ChangeBatch + Changes: [ + // Changes // required + { + // Change Action: req.action as any, // required - ResourceRecordSet: { // ResourceRecordSet + ResourceRecordSet: { + // ResourceRecordSet Name: req.fullRecord, // required Type: req.type.toUpperCase() as any, - ResourceRecords: [ // ResourceRecords - { // ResourceRecord + ResourceRecords: [ + // ResourceRecords + { + // ResourceRecord Value: `"${req.value}"`, // required }, ], @@ -154,7 +159,7 @@ export class AwsClient { this.logger.info(`设置域名解析参数:${JSON.stringify(input)}`); const command = new ChangeResourceRecordSetsCommand(input); const response = await this.doRequest(() => client.send(command)); - console.log('Add record successful:', JSON.stringify(response)); + console.log("Add record successful:", JSON.stringify(response)); await utils.sleep(3000); return response; /* diff --git a/packages/ui/certd-server/src/plugins/plugin-aws/plugins/index.ts b/packages/ui/certd-server/src/plugins/plugin-aws/plugins/index.ts index b715dc428..ae7baa97c 100644 --- a/packages/ui/certd-server/src/plugins/plugin-aws/plugins/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-aws/plugins/index.ts @@ -1,2 +1,2 @@ -export * from './plugin-deploy-to-cloudfront.js'; -export * from './plugin-upload-to-acm.js' +export * from "./plugin-deploy-to-cloudfront.js"; +export * from "./plugin-upload-to-acm.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-aws/plugins/plugin-deploy-to-cloudfront.ts b/packages/ui/certd-server/src/plugins/plugin-aws/plugins/plugin-deploy-to-cloudfront.ts index 38074dfca..8a5b731bf 100644 --- a/packages/ui/certd-server/src/plugins/plugin-aws/plugins/plugin-deploy-to-cloudfront.ts +++ b/packages/ui/certd-server/src/plugins/plugin-aws/plugins/plugin-deploy-to-cloudfront.ts @@ -7,10 +7,10 @@ import { optionsUtils } from "@certd/basic"; import { AwsRegions } from "../constants.js"; @IsTaskPlugin({ - name: 'AwsDeployToCloudFront', - title: 'AWS-部署证书到CloudFront', - desc: '部署证书到 AWS CloudFront', - icon: 'svg:icon-aws', + name: "AwsDeployToCloudFront", + title: "AWS-部署证书到CloudFront", + desc: "部署证书到 AWS CloudFront", + icon: "svg:icon-aws", group: pluginGroups.aws.key, needPlus: false, default: { @@ -21,11 +21,11 @@ import { AwsRegions } from "../constants.js"; }) export class AwsDeployToCloudFront extends AbstractTaskPlugin { @TaskInput({ - title: '域名证书', - helper: '请选择前置任务输出的域名证书', + title: "域名证书", + helper: "请选择前置任务输出的域名证书", component: { - name: 'output-selector', - from: [...CertApplyPluginNames, 'AwsUploadToACM'], + name: "output-selector", + from: [...CertApplyPluginNames, "AwsUploadToACM"], }, required: true, }) @@ -35,11 +35,11 @@ export class AwsDeployToCloudFront extends AbstractTaskPlugin { certDomains!: string[]; @TaskInput({ - title: '区域', - helper: '证书上传区域', + title: "区域", + helper: "证书上传区域", component: { - name: 'a-auto-complete', - vModel: 'value', + name: "a-auto-complete", + vModel: "value", options: AwsRegions, }, required: true, @@ -47,11 +47,11 @@ export class AwsDeployToCloudFront extends AbstractTaskPlugin { region!: string; @TaskInput({ - title: 'Access授权', - helper: 'aws的授权', + title: "Access授权", + helper: "aws的授权", component: { - name: 'access-selector', - type: 'aws', + name: "access-selector", + type: "aws", }, required: true, }) @@ -59,8 +59,8 @@ export class AwsDeployToCloudFront extends AbstractTaskPlugin { @TaskInput( createRemoteSelectInputDefine({ - title: '分配ID', - helper: '请选择distributions id', + title: "分配ID", + helper: "请选择distributions id", action: AwsDeployToCloudFront.prototype.onGetDistributions.name, required: true, }) @@ -73,13 +73,13 @@ export class AwsDeployToCloudFront extends AbstractTaskPlugin { const access = await this.getAccess(this.accessId); let certId = this.cert as string; - if (typeof this.cert !== 'string') { + if (typeof this.cert !== "string") { //先上传 certId = await this.uploadToACM(access, this.cert); } //部署到CloudFront - const { CloudFrontClient, UpdateDistributionCommand, GetDistributionConfigCommand } = await import('@aws-sdk/client-cloudfront'); + const { CloudFrontClient, UpdateDistributionCommand, GetDistributionConfigCommand } = await import("@aws-sdk/client-cloudfront"); const cloudFrontClient = new CloudFrontClient({ region: this.region, credentials: { @@ -112,7 +112,7 @@ export class AwsDeployToCloudFront extends AbstractTaskPlugin { await cloudFrontClient.send(updateDistributionCommand); this.logger.info(`部署${distributionId}完成:`); } - this.logger.info('部署完成'); + this.logger.info("部署完成"); } private async uploadToACM(access: AwsAccess, cert: CertInfo) { @@ -122,18 +122,18 @@ export class AwsDeployToCloudFront extends AbstractTaskPlugin { logger: this.logger, }); const awsCertARN = await acmClient.importCertificate(cert); - this.logger.info('证书上传成功,id=', awsCertARN); + this.logger.info("证书上传成功,id=", awsCertARN); return awsCertARN; } //查找分配ID列表选项 async onGetDistributions() { if (!this.accessId) { - throw new Error('请选择Access授权'); + throw new Error("请选择Access授权"); } const access = await this.getAccess(this.accessId); - const { CloudFrontClient, ListDistributionsCommand } = await import('@aws-sdk/client-cloudfront'); + const { CloudFrontClient, ListDistributionsCommand } = await import("@aws-sdk/client-cloudfront"); const cloudFrontClient = new CloudFrontClient({ region: this.region, credentials: { @@ -146,7 +146,7 @@ export class AwsDeployToCloudFront extends AbstractTaskPlugin { const data = await cloudFrontClient.send(listDistributionsCommand); const distributions = data.DistributionList?.Items; if (!distributions || distributions.length === 0) { - throw new Error('找不到CloudFront分配ID,您可以手动输入'); + throw new Error("找不到CloudFront分配ID,您可以手动输入"); } const options = distributions.map((item: any) => { diff --git a/packages/ui/certd-server/src/plugins/plugin-aws/plugins/plugin-upload-to-acm.ts b/packages/ui/certd-server/src/plugins/plugin-aws/plugins/plugin-upload-to-acm.ts index aff33b315..ea9cedc18 100644 --- a/packages/ui/certd-server/src/plugins/plugin-aws/plugins/plugin-upload-to-acm.ts +++ b/packages/ui/certd-server/src/plugins/plugin-aws/plugins/plugin-upload-to-acm.ts @@ -1,14 +1,14 @@ -import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput, TaskOutput } from '@certd/pipeline'; -import { CertInfo } from '@certd/plugin-cert'; -import { AwsAccess } from '../access.js'; -import { AwsClient } from '../libs/aws-client.js'; -import { CertApplyPluginNames} from '@certd/plugin-cert'; +import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput, TaskOutput } from "@certd/pipeline"; +import { CertInfo } from "@certd/plugin-cert"; +import { AwsAccess } from "../access.js"; +import { AwsClient } from "../libs/aws-client.js"; +import { CertApplyPluginNames } from "@certd/plugin-cert"; import { AwsRegions } from "../constants.js"; @IsTaskPlugin({ - name: 'AwsUploadToACM', - title: 'AWS-上传证书到ACM', - desc: '上传证书 AWS ACM', - icon: 'svg:icon-aws', + name: "AwsUploadToACM", + title: "AWS-上传证书到ACM", + desc: "上传证书 AWS ACM", + icon: "svg:icon-aws", group: pluginGroups.aws.key, default: { strategy: { @@ -18,10 +18,10 @@ import { AwsRegions } from "../constants.js"; }) export class AwsUploadToACM extends AbstractTaskPlugin { @TaskInput({ - title: '域名证书', - helper: '请选择前置任务输出的域名证书', + title: "域名证书", + helper: "请选择前置任务输出的域名证书", component: { - name: 'output-selector', + name: "output-selector", from: [...CertApplyPluginNames], }, required: true, @@ -29,21 +29,21 @@ export class AwsUploadToACM extends AbstractTaskPlugin { cert!: CertInfo; @TaskInput({ - title: 'Access授权', - helper: 'aws的授权', + title: "Access授权", + helper: "aws的授权", component: { - name: 'access-selector', - type: 'aws', + name: "access-selector", + type: "aws", }, required: true, }) accessId!: string; @TaskInput({ - title: '区域', - helper: '证书上传区域', + title: "区域", + helper: "证书上传区域", component: { - name: 'a-auto-complete', - vModel: 'value', + name: "a-auto-complete", + vModel: "value", options: AwsRegions, }, required: true, @@ -51,9 +51,9 @@ export class AwsUploadToACM extends AbstractTaskPlugin { region!: string; @TaskOutput({ - title: '证书ARN', + title: "证书ARN", }) - awsCertARN = ''; + awsCertARN = ""; async onInstance() {} @@ -66,7 +66,7 @@ export class AwsUploadToACM extends AbstractTaskPlugin { logger: this.logger, }); this.awsCertARN = await acmClient.importCertificate(cert); - this.logger.info('证书上传成功,id=', this.awsCertARN); + this.logger.info("证书上传成功,id=", this.awsCertARN); } } diff --git a/packages/ui/certd-server/src/plugins/plugin-azure/access.ts b/packages/ui/certd-server/src/plugins/plugin-azure/access.ts index 15216c864..2a6ef42de 100644 --- a/packages/ui/certd-server/src/plugins/plugin-azure/access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-azure/access.ts @@ -1,108 +1,97 @@ -import { AccessInput, BaseAccess, IsAccess } from '@certd/pipeline'; -import { DomainRecord } from '@certd/plugin-cert'; -import { utils } from '@certd/basic'; -import { PageRes, PageSearch } from '@certd/pipeline'; +import { AccessInput, BaseAccess, IsAccess } from "@certd/pipeline"; +import { DomainRecord } from "@certd/plugin-cert"; +import { utils } from "@certd/basic"; +import { PageRes, PageSearch } from "@certd/pipeline"; @IsAccess({ - name: 'azure', - title: '微软云Azure授权', - desc: '', - icon: 'simple-icons:microsoftazure', + name: "azure", + title: "微软云Azure授权", + desc: "", + icon: "simple-icons:microsoftazure", }) export class AzureAccess extends BaseAccess { @AccessInput({ - title: '订阅 ID', + title: "订阅 ID", component: { - placeholder: 'subscriptionId', + placeholder: "subscriptionId", }, - helper: 'Azure 订阅 ID', + helper: "Azure 订阅 ID", required: true, }) - subscriptionId = ''; - + subscriptionId = ""; @AccessInput({ - title: '资源组', + title: "资源组", component: { - placeholder: 'resourceGroupName', + placeholder: "resourceGroupName", }, - helper: 'DNS 区域所在的资源组名称', + helper: "DNS 区域所在的资源组名称", required: true, }) - resourceGroupName = ''; + resourceGroupName = ""; @AccessInput({ - title: '目录(租户) ID', + title: "目录(租户) ID", component: { - placeholder: 'tenantId', + placeholder: "tenantId", }, - helper: '目录(租户) ID', + helper: "目录(租户) ID", required: true, }) - tenantId = ''; + tenantId = ""; @AccessInput({ - title: '应用程序ID', + title: "应用程序ID", component: { - placeholder: 'clientId', + placeholder: "clientId", }, - helper: '应用程序(客户端) ID', + helper: "应用程序(客户端) ID", required: true, }) - clientId = ''; + clientId = ""; @AccessInput({ - title: '客户端凭据', + title: "客户端凭据", component: { - placeholder: 'clientSecret', + placeholder: "clientSecret", }, required: true, encrypt: true, - helper: '客户端凭据(机密)->客户端密码->新客户端密码->时间选长一点的->复制值', + helper: "客户端凭据(机密)->客户端密码->新客户端密码->时间选长一点的->复制值", }) - clientSecret = ''; - - + clientSecret = ""; @AccessInput({ title: "测试", component: { name: "api-test", - action: "TestRequest" + action: "TestRequest", }, - helper: "测试授权是否正确" + helper: "测试授权是否正确", }) testRequest = true; async onTestRequest() { - this.ctx.logger.info('开始测试 Azure 认证...'); - + this.ctx.logger.info("开始测试 Azure 认证..."); + // 1. 先测试身份认证,获取访问令牌 - const { ClientSecretCredential } = await import('@azure/identity'); - - const credential = new ClientSecretCredential( - this.tenantId, - this.clientId, - this.clientSecret - ); - + const { ClientSecretCredential } = await import("@azure/identity"); + + const credential = new ClientSecretCredential(this.tenantId, this.clientId, this.clientSecret); + // 获取 Azure 管理 API 的访问令牌来验证凭据 - this.ctx.logger.info('验证身份凭据...'); - const token = await credential.getToken('https://management.azure.com/.default'); - this.ctx.logger.info('身份认证成功!', token); - + this.ctx.logger.info("验证身份凭据..."); + const token = await credential.getToken("https://management.azure.com/.default"); + this.ctx.logger.info("身份认证成功!", token); + return "ok"; } async getDnsManagementClient() { - const { DnsManagementClient } = await import('@azure/arm-dns'); - const { ClientSecretCredential } = await import('@azure/identity'); + const { DnsManagementClient } = await import("@azure/arm-dns"); + const { ClientSecretCredential } = await import("@azure/identity"); - const credential = new ClientSecretCredential( - this.tenantId, - this.clientId, - this.clientSecret - ); + const credential = new ClientSecretCredential(this.tenantId, this.clientId, this.clientSecret); return new DnsManagementClient(credential, this.subscriptionId); } @@ -120,10 +109,10 @@ export class AzureAccess extends BaseAccess { async getZoneId(domain: string): Promise<{ id: string; name: string }> { const zones = await this.listZones(); - const domainSuffix = domain.endsWith('.') ? domain : domain + '.'; + const domainSuffix = domain.endsWith(".") ? domain : domain + "."; const matchingZone = zones.find((zone: any) => { - const zoneName = zone.name.endsWith('.') ? zone.name : zone.name + '.'; + const zoneName = zone.name.endsWith(".") ? zone.name : zone.name + "."; return domainSuffix.endsWith(zoneName) || domainSuffix === zoneName; }); @@ -133,7 +122,7 @@ export class AzureAccess extends BaseAccess { this.ctx.logger.info(`找到 DNS 区域: ${matchingZone.name}, ID: ${matchingZone.id}`); return { - id: matchingZone.id.split('/').pop()!, + id: matchingZone.id.split("/").pop()!, name: matchingZone.name, }; } @@ -147,7 +136,7 @@ export class AzureAccess extends BaseAccess { } list = list.map((item: any) => ({ - id: item.id.split('/').pop()!, + id: item.id.split("/").pop()!, domain: item.name, })); @@ -157,7 +146,6 @@ export class AzureAccess extends BaseAccess { }; } - async createOrUpdateRecordSet(zoneName: string, recordType: string, relativeRecordSetName: string, value: string) { const client = await this.getDnsManagementClient(); @@ -166,12 +154,7 @@ export class AzureAccess extends BaseAccess { // 获取现有记录集 let existingRecordSet: any = null; try { - existingRecordSet = await client.recordSets.get( - this.resourceGroupName, - zoneName, - relativeRecordSetName, - recordType as any - ); + existingRecordSet = await client.recordSets.get(this.resourceGroupName, zoneName, relativeRecordSetName, recordType as any); } catch (e) { // 记录集不存在,这是正常的 } @@ -189,19 +172,13 @@ export class AzureAccess extends BaseAccess { // 添加新记录 txtRecords.push({ - value: [value] + value: [value], }); - const recordSet = await client.recordSets.createOrUpdate( - this.resourceGroupName, - zoneName, - relativeRecordSetName, - recordType as any, - { - ttl: 60, - txtRecords: txtRecords - } - ); + const recordSet = await client.recordSets.createOrUpdate(this.resourceGroupName, zoneName, relativeRecordSetName, recordType as any, { + ttl: 60, + txtRecords: txtRecords, + }); await utils.sleep(3000); return recordSet; @@ -214,15 +191,10 @@ export class AzureAccess extends BaseAccess { try { // 获取现有记录集 - const existingRecordSet = await client.recordSets.get( - this.resourceGroupName, - zoneName, - relativeRecordSetName, - recordType as any - ); + const existingRecordSet = await client.recordSets.get(this.resourceGroupName, zoneName, relativeRecordSetName, recordType as any); if (!existingRecordSet.txtRecords || existingRecordSet.txtRecords.length === 0) { - this.ctx.logger.info('记录集不存在或已为空,无需删除'); + this.ctx.logger.info("记录集不存在或已为空,无需删除"); return; } @@ -238,26 +210,15 @@ export class AzureAccess extends BaseAccess { if (filteredTxtRecords.length === 0) { // 如果没有记录了,就删除整个记录集 - this.ctx.logger.info('删除空记录集'); - await client.recordSets.delete( - this.resourceGroupName, - zoneName, - relativeRecordSetName, - recordType as any - ); + this.ctx.logger.info("删除空记录集"); + await client.recordSets.delete(this.resourceGroupName, zoneName, relativeRecordSetName, recordType as any); } else { // 还有其他记录,只更新记录集,移除我们的值 this.ctx.logger.info(`更新记录集,移除指定值,剩余 ${filteredTxtRecords.length} 条记录`); - await client.recordSets.createOrUpdate( - this.resourceGroupName, - zoneName, - relativeRecordSetName, - recordType as any, - { - ttl: existingRecordSet.ttl, - txtRecords: filteredTxtRecords - } - ); + await client.recordSets.createOrUpdate(this.resourceGroupName, zoneName, relativeRecordSetName, recordType as any, { + ttl: existingRecordSet.ttl, + txtRecords: filteredTxtRecords, + }); } } catch (e: any) { this.ctx.logger.warn(`删除记录时出错: ${e.message}`); diff --git a/packages/ui/certd-server/src/plugins/plugin-azure/azure-dns-provider.ts b/packages/ui/certd-server/src/plugins/plugin-azure/azure-dns-provider.ts index 366803569..e05d6a792 100644 --- a/packages/ui/certd-server/src/plugins/plugin-azure/azure-dns-provider.ts +++ b/packages/ui/certd-server/src/plugins/plugin-azure/azure-dns-provider.ts @@ -1,33 +1,33 @@ -import { AbstractDnsProvider, CreateRecordOptions, DomainRecord, IsDnsProvider, RemoveRecordOptions } from '@certd/plugin-cert'; -import { AzureAccess } from './access.js'; -import { PageRes, PageSearch } from '@certd/pipeline'; +import { AbstractDnsProvider, CreateRecordOptions, DomainRecord, IsDnsProvider, RemoveRecordOptions } from "@certd/plugin-cert"; +import { AzureAccess } from "./access.js"; +import { PageRes, PageSearch } from "@certd/pipeline"; @IsDnsProvider({ - name: 'azure-dns', - title: 'Azure DNS', - desc: 'Azure DNS 解析提供商', - accessType: 'azure', - icon: 'simple-icons:microsoftazure', + name: "azure-dns", + title: "Azure DNS", + desc: "Azure DNS 解析提供商", + accessType: "azure", + icon: "simple-icons:microsoftazure", order: 1, }) export class AzureDnsProvider extends AbstractDnsProvider { access: AzureAccess; - + async onInstance() { this.access = this.ctx.access as AzureAccess; } async createRecord(options: CreateRecordOptions): Promise { const { fullRecord, value, type, domain } = options; - this.logger.info('添加域名解析:', fullRecord, value, type, domain); + this.logger.info("添加域名解析:", fullRecord, value, type, domain); const zone = await this.access.getZoneId(domain); this.logger.info(`获取到 DNS 区域: ${zone.name}, ID: ${zone.id}`); - - const relativeRecordSetName = fullRecord.replace(`.${zone.name}`, '').replace(`.${zone.name.replace(/\.$/, '')}`, ''); - + + const relativeRecordSetName = fullRecord.replace(`.${zone.name}`, "").replace(`.${zone.name.replace(/\.$/, "")}`, ""); + await this.access.createOrUpdateRecordSet(zone.name, type, relativeRecordSetName, value); - + return { zoneId: zone.id, zoneName: zone.name, @@ -40,9 +40,9 @@ export class AzureDnsProvider extends AbstractDnsProvider { async removeRecord(options: RemoveRecordOptions): Promise { const { fullRecord, value: reqValue, type } = options.recordReq; const record = options.recordRes; - + if (!record) { - this.logger.warn('记录信息为空,不执行删除'); + this.logger.warn("记录信息为空,不执行删除"); return; } @@ -51,7 +51,7 @@ export class AzureDnsProvider extends AbstractDnsProvider { await this.access.deleteRecordSet(record.zoneName, record.recordType, record.relativeRecordSetName, value); this.logger.info(`删除域名解析成功:${fullRecord} ${value} ${type}`); } catch (e: any) { - this.logger.warn(`删除域名解析失败:${e.message}`, ); + this.logger.warn(`删除域名解析失败:${e.message}`); } } diff --git a/packages/ui/certd-server/src/plugins/plugin-azure/index.ts b/packages/ui/certd-server/src/plugins/plugin-azure/index.ts index 91f51fd00..d29360ac9 100644 --- a/packages/ui/certd-server/src/plugins/plugin-azure/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-azure/index.ts @@ -1,2 +1,2 @@ -export * from './access.js'; -export * from './azure-dns-provider.js'; +export * from "./access.js"; +export * from "./azure-dns-provider.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-bind9/access.ts b/packages/ui/certd-server/src/plugins/plugin-bind9/access.ts index e437e58e4..b2a02a81f 100644 --- a/packages/ui/certd-server/src/plugins/plugin-bind9/access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-bind9/access.ts @@ -13,7 +13,7 @@ export class Bind9Access extends BaseAccess { component: { name: "access-selector", type: "ssh", - vModel:"modelValue" + vModel: "modelValue", }, required: true, }) @@ -37,7 +37,7 @@ export class Bind9Access extends BaseAccess { placeholder: "53", }, }) - dnsPort: number = 53; + dnsPort = 53; @AccessInput({ title: "测试", diff --git a/packages/ui/certd-server/src/plugins/plugin-bind9/dns-provider.ts b/packages/ui/certd-server/src/plugins/plugin-bind9/dns-provider.ts index 1d2cd3044..3a1fcf657 100644 --- a/packages/ui/certd-server/src/plugins/plugin-bind9/dns-provider.ts +++ b/packages/ui/certd-server/src/plugins/plugin-bind9/dns-provider.ts @@ -1,6 +1,6 @@ -import { AbstractDnsProvider, CreateRecordOptions, IsDnsProvider, RemoveRecordOptions } from '@certd/plugin-cert'; -import { Bind9Access } from './access.js'; -import { SshClient } from '../plugin-lib/ssh/index.js'; +import { AbstractDnsProvider, CreateRecordOptions, IsDnsProvider, RemoveRecordOptions } from "@certd/plugin-cert"; +import { Bind9Access } from "./access.js"; +import { SshClient } from "../plugin-lib/ssh/index.js"; export type Bind9Record = { fullRecord: string; @@ -10,11 +10,11 @@ export type Bind9Record = { }; @IsDnsProvider({ - name: 'bind9', - title: 'BIND9 DNS', - desc: '通过 SSH 连接到 BIND9 服务器,使用 nsupdate 命令管理 DNS 记录', - icon: 'clarity:host-line', - accessType: 'bind9', + name: "bind9", + title: "BIND9 DNS", + desc: "通过 SSH 连接到 BIND9 服务器,使用 nsupdate 命令管理 DNS 记录", + icon: "clarity:host-line", + accessType: "bind9", }) export class Bind9DnsProvider extends AbstractDnsProvider { access!: Bind9Access; @@ -32,7 +32,7 @@ export class Bind9DnsProvider extends AbstractDnsProvider { // 从 accessService 获取 SSH 授权配置 const sshAccess = await this.ctx.accessGetter.getById(this.access.sshAccessId); if (!sshAccess) { - throw new Error('SSH 授权不存在'); + throw new Error("SSH 授权不存在"); } return sshAccess; } @@ -42,12 +42,8 @@ export class Bind9DnsProvider extends AbstractDnsProvider { */ private buildNsupdateCommand(commands: string[]): string { const { dnsServer, dnsPort } = this.access; - const nsupdateScript = [ - `server ${dnsServer} ${dnsPort}`, - ...commands, - "send", - ].join("\n"); - + const nsupdateScript = [`server ${dnsServer} ${dnsPort}`, ...commands, "send"].join("\n"); + // 使用 heredoc 方式执行 nsupdate return `nsupdate << 'EOF' ${nsupdateScript} @@ -59,15 +55,15 @@ EOF`; */ async createRecord(options: CreateRecordOptions): Promise { const { fullRecord, value, type, domain } = options; - this.logger.info('添加域名解析:', fullRecord, value, type, domain); + this.logger.info("添加域名解析:", fullRecord, value, type, domain); // 构建 nsupdate 命令 // 格式: update add const updateCommand = `update add ${fullRecord} 60 ${type} "${value}"`; const nsupdateCmd = this.buildNsupdateCommand([updateCommand]); - this.logger.info('执行 nsupdate 命令添加记录'); - + this.logger.info("执行 nsupdate 命令添加记录"); + try { const sshAccess = await this.getSshAccess(); await this.sshClient.exec({ @@ -75,10 +71,10 @@ EOF`; script: nsupdateCmd, throwOnStdErr: true, }); - + this.logger.info(`添加域名解析成功: fullRecord=${fullRecord}, value=${value}`); } catch (error: any) { - this.logger.error('添加域名解析失败:', error.message); + this.logger.error("添加域名解析失败:", error.message); throw new Error(`添加 DNS 记录失败: ${error.message}`); } @@ -89,7 +85,7 @@ EOF`; type, domain, }; - + return record; } @@ -98,15 +94,15 @@ EOF`; */ async removeRecord(options: RemoveRecordOptions): Promise { const { fullRecord, value, type, domain } = options.recordRes; - this.logger.info('删除域名解析:', fullRecord, value, type, domain); + this.logger.info("删除域名解析:", fullRecord, value, type, domain); // 构建 nsupdate 命令 // 格式: update delete const updateCommand = `update delete ${fullRecord} ${type} "${value}"`; const nsupdateCmd = this.buildNsupdateCommand([updateCommand]); - this.logger.info('执行 nsupdate 命令删除记录'); - + this.logger.info("执行 nsupdate 命令删除记录"); + try { const sshAccess = await this.getSshAccess(); await this.sshClient.exec({ @@ -114,11 +110,11 @@ EOF`; script: nsupdateCmd, throwOnStdErr: false, // 删除时忽略错误(记录可能已不存在) }); - + this.logger.info(`删除域名解析成功: fullRecord=${fullRecord}, value=${value}`); } catch (error: any) { // 删除失败只记录警告,不抛出异常(清理操作不应影响主流程) - this.logger.warn('删除域名解析时出现警告:', error.message); + this.logger.warn("删除域名解析时出现警告:", error.message); } } } diff --git a/packages/ui/certd-server/src/plugins/plugin-bind9/index.ts b/packages/ui/certd-server/src/plugins/plugin-bind9/index.ts index db899c717..d0bc76d38 100644 --- a/packages/ui/certd-server/src/plugins/plugin-bind9/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-bind9/index.ts @@ -1,2 +1,2 @@ -export * from './dns-provider.js'; -export * from './access.js'; +export * from "./dns-provider.js"; +export * from "./access.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-cachefly/access.ts b/packages/ui/certd-server/src/plugins/plugin-cachefly/access.ts index 1549d892e..dd72c893b 100644 --- a/packages/ui/certd-server/src/plugins/plugin-cachefly/access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-cachefly/access.ts @@ -1,49 +1,45 @@ -import { AccessInput, BaseAccess, IsAccess } from '@certd/pipeline'; +import { AccessInput, BaseAccess, IsAccess } from "@certd/pipeline"; @IsAccess({ - name: 'CacheFly', - title: 'CacheFly', - desc: 'CacheFly', - icon: 'clarity:plugin-line', + name: "CacheFly", + title: "CacheFly", + desc: "CacheFly", + icon: "clarity:plugin-line", }) export class CacheflyAccess extends BaseAccess { - - - @AccessInput({ - title: 'username', + title: "username", component: { - placeholder: 'username', + placeholder: "username", }, required: true, }) - username = ''; + username = ""; @AccessInput({ - title: 'password', + title: "password", component: { - placeholder: 'password', + placeholder: "password", }, required: true, encrypt: true, }) - password = ''; + password = ""; @AccessInput({ - title: 'totp key', + title: "totp key", component: { - placeholder: 'totp key', + placeholder: "totp key", }, encrypt: true, }) - otpkey = ''; - + otpkey = ""; @AccessInput({ title: "测试", component: { name: "api-test", - action: "TestRequest" + action: "TestRequest", }, - helper: "测试授权是否正确" + helper: "测试授权是否正确", }) testRequest = true; @@ -52,16 +48,15 @@ export class CacheflyAccess extends BaseAccess { return "ok"; } - - async login(){ + async login() { let otp = null; if (this.otpkey) { const response = await this.ctx.http.request({ url: `https://cn-api.my-api.cn/api/totp/?key=${this.otpkey}`, - method: 'get', + method: "get", }); otp = response; - this.ctx.logger.info('获取到otp:', otp); + this.ctx.logger.info("获取到otp:", otp); } const loginResponse = await this.doRequestApi(`/api/2.6/auth/login`, { username: this.username, @@ -69,17 +64,16 @@ export class CacheflyAccess extends BaseAccess { ...(otp && { otp }), }); const token = loginResponse.token; - this.ctx.logger.info('Token 获取成功'); + this.ctx.logger.info("Token 获取成功"); return token; } - async doRequestApi(url: string, data: any = null, method = 'post', token: string | null = null) { - - const baseApi = 'https://api.cachefly.com'; + async doRequestApi(url: string, data: any = null, method = "post", token: string | null = null) { + const baseApi = "https://api.cachefly.com"; const headers = { - 'Content-Type': 'application/json', - ...(token ? { 'x-cf-authorization': `Bearer ${token}` } : {}), + "Content-Type": "application/json", + ...(token ? { "x-cf-authorization": `Bearer ${token}` } : {}), }; const res = await this.ctx.http.request({ url, diff --git a/packages/ui/certd-server/src/plugins/plugin-cachefly/index.ts b/packages/ui/certd-server/src/plugins/plugin-cachefly/index.ts index fdad254fb..02dc3945d 100644 --- a/packages/ui/certd-server/src/plugins/plugin-cachefly/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-cachefly/index.ts @@ -1,2 +1,2 @@ -export * from './plugins/index.js'; -export * from './access.js'; +export * from "./plugins/index.js"; +export * from "./access.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-cachefly/plugins/index.ts b/packages/ui/certd-server/src/plugins/plugin-cachefly/plugins/index.ts index cd1308a9c..c1300473f 100644 --- a/packages/ui/certd-server/src/plugins/plugin-cachefly/plugins/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-cachefly/plugins/index.ts @@ -1 +1 @@ -export * from './plugin-deploy-to-cdn.js'; +export * from "./plugin-deploy-to-cdn.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-cachefly/plugins/plugin-deploy-to-cdn.ts b/packages/ui/certd-server/src/plugins/plugin-cachefly/plugins/plugin-deploy-to-cdn.ts index 2bf1d83bf..0c9fde39c 100644 --- a/packages/ui/certd-server/src/plugins/plugin-cachefly/plugins/plugin-deploy-to-cdn.ts +++ b/packages/ui/certd-server/src/plugins/plugin-cachefly/plugins/plugin-deploy-to-cdn.ts @@ -1,12 +1,12 @@ -import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from '@certd/pipeline'; -import { CertInfo } from '@certd/plugin-cert'; -import { CacheflyAccess } from '../access.js'; -import { CertApplyPluginNames} from '@certd/plugin-cert'; +import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; +import { CertInfo } from "@certd/plugin-cert"; +import { CacheflyAccess } from "../access.js"; +import { CertApplyPluginNames } from "@certd/plugin-cert"; @IsTaskPlugin({ - name: 'CacheFly', - title: 'CacheFly-部署证书到CacheFly', - desc: '部署证书到 CacheFly', - icon: 'clarity:plugin-line', + name: "CacheFly", + title: "CacheFly-部署证书到CacheFly", + desc: "部署证书到 CacheFly", + icon: "clarity:plugin-line", group: pluginGroups.cdn.key, default: { strategy: { @@ -16,36 +16,32 @@ import { CertApplyPluginNames} from '@certd/plugin-cert'; }) export class CacheFlyPlugin extends AbstractTaskPlugin { @TaskInput({ - title: '域名证书', - helper: '请选择前置任务输出的域名证书', + title: "域名证书", + helper: "请选择前置任务输出的域名证书", component: { - name: 'output-selector', + name: "output-selector", from: [...CertApplyPluginNames], }, required: true, }) cert!: CertInfo; @TaskInput({ - title: 'Access授权', - helper: 'CacheFly 的授权', + title: "Access授权", + helper: "CacheFly 的授权", component: { - name: 'access-selector', - type: 'CacheFly', + name: "access-selector", + type: "CacheFly", }, required: true, }) accessId!: string; - async onInstance() {} - - - async execute(): Promise { const { cert, accessId } = this; const access = (await this.getAccess(accessId)) as CacheflyAccess; - + const token = await access.login(); // 更新证书 await access.doRequestApi( @@ -54,10 +50,10 @@ export class CacheFlyPlugin extends AbstractTaskPlugin { certificate: cert.crt, certificateKey: cert.key, }, - 'post', + "post", token ); - this.logger.info('证书更新成功'); + this.logger.info("证书更新成功"); } } diff --git a/packages/ui/certd-server/src/plugins/plugin-captcha/api.ts b/packages/ui/certd-server/src/plugins/plugin-captcha/api.ts index 29dc4fbc9..bde7a5c26 100644 --- a/packages/ui/certd-server/src/plugins/plugin-captcha/api.ts +++ b/packages/ui/certd-server/src/plugins/plugin-captcha/api.ts @@ -1,7 +1,7 @@ export type CaptchaRequest = { - remoteIp: string, -} -export interface ICaptchaAddon{ - onValidate(data?:any,req?:CaptchaRequest):Promise; - getCaptcha():Promise; + remoteIp: string; +}; +export interface ICaptchaAddon { + onValidate(data?: any, req?: CaptchaRequest): Promise; + getCaptcha(): Promise; } diff --git a/packages/ui/certd-server/src/plugins/plugin-captcha/cf-turnstile/index.ts b/packages/ui/certd-server/src/plugins/plugin-captcha/cf-turnstile/index.ts index b99e0c259..35158da00 100644 --- a/packages/ui/certd-server/src/plugins/plugin-captcha/cf-turnstile/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-captcha/cf-turnstile/index.ts @@ -9,7 +9,6 @@ import { CaptchaRequest, ICaptchaAddon } from "../api.js"; showTest: false, }) export class CfTurnstileCaptcha extends BaseAddon implements ICaptchaAddon { - @AddonInput({ title: "站点密钥", component: { @@ -37,30 +36,28 @@ export class CfTurnstileCaptcha extends BaseAddon implements ICaptchaAddon { const { remoteIp } = req; const formData = new FormData(); - formData.append('secret', this.secretKey); - formData.append('response', token); - formData.append('remoteip', remoteIp); + formData.append("secret", this.secretKey); + formData.append("response", token); + formData.append("remoteip", remoteIp); - const res = await this.http.request({ - url: 'https://challenges.cloudflare.com/turnstile/v0/siteverify', - method: 'POST', - headers: { - 'Content-Type': 'multipart/form-data', - }, - data: formData - }) - - if (res.success) { - // Token is valid - process the form - return true; - } else { - // Token is invalid - reject the submission - const errorMessage = 'Cloudflare Turnstile 校验失败:' + res['error-codes'].join(', ') - this.logger.error(errorMessage); - throw new Error(errorMessage); - } - + const res = await this.http.request({ + url: "https://challenges.cloudflare.com/turnstile/v0/siteverify", + method: "POST", + headers: { + "Content-Type": "multipart/form-data", + }, + data: formData, + }); + if (res.success) { + // Token is valid - process the form + return true; + } else { + // Token is invalid - reject the submission + const errorMessage = "Cloudflare Turnstile 校验失败:" + res["error-codes"].join(", "); + this.logger.error(errorMessage); + throw new Error(errorMessage); + } } async getCaptcha(): Promise { diff --git a/packages/ui/certd-server/src/plugins/plugin-captcha/geetest/index.ts b/packages/ui/certd-server/src/plugins/plugin-captcha/geetest/index.ts index a5272988a..120b76c7f 100644 --- a/packages/ui/certd-server/src/plugins/plugin-captcha/geetest/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-captcha/geetest/index.ts @@ -3,53 +3,50 @@ import crypto from "crypto"; import { ICaptchaAddon } from "../api.js"; @IsAddon({ - addonType:"captcha", - name: 'geetest', - title: '极验验证码v4', - desc: '', - showTest:false, + addonType: "captcha", + name: "geetest", + title: "极验验证码v4", + desc: "", + showTest: false, }) -export class GeeTestCaptcha extends BaseAddon implements ICaptchaAddon{ - +export class GeeTestCaptcha extends BaseAddon implements ICaptchaAddon { @AddonInput({ - title: '验证ID', + title: "验证ID", component: { - placeholder: 'captchaId', + placeholder: "captchaId", }, - helper:"[极验验证码v4](https://console.geetest.com/sensbot/management) -> 创建业务模块 -> 新增业务场景", + helper: "[极验验证码v4](https://console.geetest.com/sensbot/management) -> 创建业务模块 -> 新增业务场景", required: true, }) - captchaId = ''; + captchaId = ""; @AddonInput({ - title: '验证Key', + title: "验证Key", component: { - placeholder: 'captchaKey', + placeholder: "captchaKey", }, required: true, }) - captchaKey = ''; + captchaKey = ""; - - async onValidate(data?:any) { + async onValidate(data?: any) { if (!data) { - return false + return false; } // geetest 服务地址 -// geetest server url + // geetest server url const API_SERVER = "http://gcaptcha4.geetest.com"; -// geetest 验证接口 -// geetest server interface + // geetest 验证接口 + // geetest server interface const API_URL = API_SERVER + "/validate" + "?captcha_id=" + this.captchaId; - // 前端参数 // web parameter - var lot_number = data['lot_number']; - var captcha_output = data['captcha_output']; - var pass_token = data['pass_token']; - var gen_time = data['gen_time']; + const lot_number = data["lot_number"]; + const captcha_output = data["captcha_output"]; + const pass_token = data["pass_token"]; + const gen_time = data["gen_time"]; if (!lot_number || !captcha_output || !pass_token || !gen_time) { return false; } @@ -57,23 +54,23 @@ export class GeeTestCaptcha extends BaseAddon implements ICaptchaAddon{ // 生成签名, 使用标准的hmac算法,使用用户当前完成验证的流水号lot_number作为原始消息message,使用客户验证私钥作为key // 采用sha256散列算法将message和key进行单向散列生成最终的 “sign_token” 签名 // use lot_number + CAPTCHA_KEY, generate the signature - var sign_token = this.hmac_sha256_encode(lot_number, this.captchaKey); + const sign_token = this.hmac_sha256_encode(lot_number, this.captchaKey); // 向极验转发前端数据 + “sign_token” 签名 // send web parameter and “sign_token” to geetest server - var datas = { - 'lot_number': lot_number, - 'captcha_output': captcha_output, - 'pass_token': pass_token, - 'gen_time': gen_time, - 'sign_token': sign_token + const datas = { + lot_number: lot_number, + captcha_output: captcha_output, + pass_token: pass_token, + gen_time: gen_time, + sign_token: sign_token, }; // post request // 根据极验返回的用户验证状态, 网站主进行自己的业务逻辑 // According to the user authentication status returned by the geetest, the website owner carries out his own business logic - try{ - const res = await this.doRequest(datas, API_URL) + try { + const res = await this.doRequest(datas, API_URL); if (res.result == "success") { // 验证成功 // verification successful @@ -81,42 +78,38 @@ export class GeeTestCaptcha extends BaseAddon implements ICaptchaAddon{ } else { // 验证失败 // verification failed - this.logger.error("极验验证不通过 ",res.reason) + this.logger.error("极验验证不通过 ", res.reason); return false; } - }catch (e) { - this.ctx.logger.error("极验验证服务异常",e) - return true + } catch (e) { + this.ctx.logger.error("极验验证服务异常", e); + return true; } } // 生成签名 -// Generate signature - hmac_sha256_encode(value, key){ - var hash = crypto.createHmac("sha256", key) - .update(value, 'utf8') - .digest('hex'); + // Generate signature + hmac_sha256_encode(value, key) { + const hash = crypto.createHmac("sha256", key).update(value, "utf8").digest("hex"); return hash; } - -// 发送post请求, 响应json数据如:{"result": "success", "reason": "", "captcha_args": {}} -// Send a post request and respond to JSON data, such as: {result ":" success "," reason ":" "," captcha_args ": {}} - async doRequest(datas, url){ - var options = { + // 发送post请求, 响应json数据如:{"result": "success", "reason": "", "captcha_args": {}} + // Send a post request and respond to JSON data, such as: {result ":" success "," reason ":" "," captcha_args ": {}} + async doRequest(datas, url) { + const options = { url: url, method: "POST", params: datas, - timeout: 5000 + timeout: 5000, }; const result = await this.ctx.http.request(options); return result; } - async getCaptcha(): Promise { + async getCaptcha(): Promise { return { captchaId: this.captchaId, - } + }; } - } diff --git a/packages/ui/certd-server/src/plugins/plugin-captcha/image/index.ts b/packages/ui/certd-server/src/plugins/plugin-captcha/image/index.ts index ff3b79bd9..e80d9c11a 100644 --- a/packages/ui/certd-server/src/plugins/plugin-captcha/image/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-captcha/image/index.ts @@ -4,53 +4,52 @@ import { cache } from "@certd/basic"; import { nanoid } from "nanoid"; @IsAddon({ - addonType:"captcha", - name: 'image', - title: '图片验证码', - desc: '', - showTest:false, + addonType: "captcha", + name: "image", + title: "图片验证码", + desc: "", + showTest: false, }) -export class ImageCaptcha extends BaseAddon implements ICaptchaAddon{ - - async onValidate(data?:any) { +export class ImageCaptcha extends BaseAddon implements ICaptchaAddon { + async onValidate(data?: any) { if (!data) { return false; } - return await this.checkCaptcha(data.randomStr, data.imageCode) + return await this.checkCaptcha(data.randomStr, data.imageCode); } - async getCaptchaText(randomStr:string) { - return cache.get('imgCode:' + randomStr); + async getCaptchaText(randomStr: string) { + return cache.get("imgCode:" + randomStr); } - async removeCaptcha(randomStr:string) { - cache.delete('imgCode:' + randomStr); + async removeCaptcha(randomStr: string) { + cache.delete("imgCode:" + randomStr); } async checkCaptcha(randomStr: string, userCaptcha: string) { const code = await this.getCaptchaText(randomStr); if (code == null) { - throw new Error('验证码已过期'); + throw new Error("验证码已过期"); } if (code.toLowerCase() !== userCaptcha?.toLowerCase()) { - throw new Error('验证码不正确'); + throw new Error("验证码不正确"); } await this.removeCaptcha(randomStr); return true; } - async getCaptcha(): Promise { - const svgCaptcha = await import('svg-captcha'); - const c = svgCaptcha.create(); - //{data: '', text: 'abcd'} - const imgCode = c.text; // = RandomUtil.randomStr(4, true); - const randomStr = nanoid(10) - cache.set('imgCode:' + randomStr, imgCode, { - ttl: 2 * 60 * 1000, //过期时间 2分钟 - }) - return { - randomStr: randomStr, - imageData: c.data, - } - } + async getCaptcha(): Promise { + const svgCaptcha = await import("svg-captcha"); + const c = svgCaptcha.create(); + //{data: '', text: 'abcd'} + const imgCode = c.text; // = RandomUtil.randomStr(4, true); + const randomStr = nanoid(10); + cache.set("imgCode:" + randomStr, imgCode, { + ttl: 2 * 60 * 1000, //过期时间 2分钟 + }); + return { + randomStr: randomStr, + imageData: c.data, + }; + } } diff --git a/packages/ui/certd-server/src/plugins/plugin-captcha/index.ts b/packages/ui/certd-server/src/plugins/plugin-captcha/index.ts index 71a227b8b..8874a7228 100644 --- a/packages/ui/certd-server/src/plugins/plugin-captcha/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-captcha/index.ts @@ -1,4 +1,4 @@ -export * from './geetest/index.js'; -export * from './image/index.js'; -export * from './tencent/index.js'; -export * from './cf-turnstile/index.js'; \ No newline at end of file +export * from "./geetest/index.js"; +export * from "./image/index.js"; +export * from "./tencent/index.js"; +export * from "./cf-turnstile/index.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-captcha/tencent/index.ts b/packages/ui/certd-server/src/plugins/plugin-captcha/tencent/index.ts index ec7f00f7d..41b976eb6 100644 --- a/packages/ui/certd-server/src/plugins/plugin-captcha/tencent/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-captcha/tencent/index.ts @@ -94,7 +94,7 @@ export class TencentCaptcha extends BaseAddon implements ICaptchaAddon { this.logger.error("腾讯云验证码账户欠费,临时放行:", err.message); return true; } - throw err + throw err; } } diff --git a/packages/ui/certd-server/src/plugins/plugin-cert/plugin/cert-plugin/acme.ts b/packages/ui/certd-server/src/plugins/plugin-cert/plugin/cert-plugin/acme.ts index 395ed1e77..6d09decdd 100644 --- a/packages/ui/certd-server/src/plugins/plugin-cert/plugin/cert-plugin/acme.ts +++ b/packages/ui/certd-server/src/plugins/plugin-cert/plugin/cert-plugin/acme.ts @@ -335,7 +335,7 @@ export class AcmeService { try { const recordRes = await dnsProvider.createRecord(recordReq); this.logger.info("添加 TXT 解析记录成功", JSON.stringify(recordRes)); - return { + return { recordReq, recordRes, dnsProvider, @@ -345,9 +345,8 @@ export class AcmeService { } catch (e: any) { //@ts-ignore e.message = `[${dnsProvider?.constructor?.name}错误] ${e.message}`; - throw e + throw e; } - }; const doDnsPersistVerify = async (challenge: any, plan: DnsPersistVerifyPlan) => { diff --git a/packages/ui/certd-server/src/plugins/plugin-cert/plugin/cert-plugin/base-convert.ts b/packages/ui/certd-server/src/plugins/plugin-cert/plugin/cert-plugin/base-convert.ts index b493ea8fe..d2335c44c 100644 --- a/packages/ui/certd-server/src/plugins/plugin-cert/plugin/cert-plugin/base-convert.ts +++ b/packages/ui/certd-server/src/plugins/plugin-cert/plugin/cert-plugin/base-convert.ts @@ -1,10 +1,9 @@ import { AbstractTaskPlugin, FileItem, IContext, Step, TaskInput, TaskOutput } from "@certd/pipeline"; import dayjs from "dayjs"; import type { CertInfo } from "./acme.js"; -import { CertReader,CertConverter, EVENT_CERT_APPLY_SUCCESS } from "@certd/plugin-lib"; +import { CertReader, CertConverter, EVENT_CERT_APPLY_SUCCESS } from "@certd/plugin-lib"; import JSZip from "jszip"; - export abstract class CertApplyBaseConvertPlugin extends AbstractTaskPlugin { @TaskInput({ title: "证书域名", @@ -16,7 +15,7 @@ export abstract class CertApplyBaseConvertPlugin extends AbstractTaskPlugin { placeholder: "请输入证书域名/IP,比如:foo.com , *.foo.com , *.sub.foo.com , *.bar.com , 123.123.123.123", tokenSeparators: [",", " ", ",", "、", "|"], search: true, - pager:true, + pager: true, }, rules: [{ type: "domains" }], required: true, diff --git a/packages/ui/certd-server/src/plugins/plugin-cert/plugin/cert-plugin/base.ts b/packages/ui/certd-server/src/plugins/plugin-cert/plugin/cert-plugin/base.ts index e70f7c0d0..ae7edfbe9 100644 --- a/packages/ui/certd-server/src/plugins/plugin-cert/plugin/cert-plugin/base.ts +++ b/packages/ui/certd-server/src/plugins/plugin-cert/plugin/cert-plugin/base.ts @@ -20,7 +20,7 @@ export abstract class CertApplyBasePlugin extends CertApplyBaseConvertPlugin { @TaskInput({ title: "更新天数", - value:20, + value: 20, component: { name: "a-input-number", vModel: "value", @@ -140,25 +140,25 @@ export abstract class CertApplyBasePlugin extends CertApplyBaseConvertPlugin { */ isWillExpire(cert: CertReader, maxDays = 15) { const expires = cert.expires; - if (expires == null) { + if (expires == null) { throw new Error("过期时间不能为空"); } - const begin = dayjs(cert.detail?.notBefore ) + const begin = dayjs(cert.detail?.notBefore); //证书总天数 const totalDays = Math.floor((expires - begin.valueOf()) / (1000 * 60 * 60 * 24)); - // 检查有效期 + // 检查有效期 const leftDays = Math.floor((expires - dayjs().valueOf()) / (1000 * 60 * 60 * 24)); - this.logger.info(`证书有效期剩余天数:${leftDays}`); - if(totalDays < maxDays){ + this.logger.info(`证书有效期剩余天数:${leftDays}`); + if (totalDays < maxDays) { this.logger.warn(`当前更新天数为${maxDays},证书总天数${totalDays},总天数小于更新天数(更新天数是指到期前多少天更新证书,您可以在任务配置中调整该值)`); - maxDays = Math.floor(totalDays/2); - if(maxDays < 2){ + maxDays = Math.floor(totalDays / 2); + if (maxDays < 2) { maxDays = 2; } this.logger.warn(`为避免每次运行都更新证书,更新天数自动减半(即证书最大时长${totalDays}天减半),调整为${maxDays}`); } - + return { isWillExpire: leftDays <= maxDays, leftDays, diff --git a/packages/ui/certd-server/src/plugins/plugin-cert/plugin/cert-plugin/getter/aliyun.ts b/packages/ui/certd-server/src/plugins/plugin-cert/plugin/cert-plugin/getter/aliyun.ts index f4dc45047..f7b58a51a 100644 --- a/packages/ui/certd-server/src/plugins/plugin-cert/plugin/cert-plugin/getter/aliyun.ts +++ b/packages/ui/certd-server/src/plugins/plugin-cert/plugin/cert-plugin/getter/aliyun.ts @@ -28,27 +28,25 @@ export class CertApplyGetFormAliyunPlugin extends CertApplyBasePlugin { }) accessId!: string; - @TaskInput( - { - title: "证书API 版本", - value: "v1", - component: { - name: "a-select", - vModel: "value", - options: [ - { - label: "API 1.0 (旧版)", - value: "v1", - }, - { - label: "API 2.0 (新版)", - value: "v2", - }, - ], - }, - helper: "选择阿里云证书 API 版本", - } - ) + @TaskInput({ + title: "证书API 版本", + value: "v1", + component: { + name: "a-select", + vModel: "value", + options: [ + { + label: "API 1.0 (旧版)", + value: "v1", + }, + { + label: "API 2.0 (新版)", + value: "v2", + }, + ], + }, + helper: "选择阿里云证书 API 版本", + }) apiVersion!: string; @TaskInput( @@ -67,7 +65,7 @@ export class CertApplyGetFormAliyunPlugin extends CertApplyBasePlugin { ) orderId!: string; - async onInit(): Promise { } + async onInit(): Promise {} async doCertApply(): Promise { const access = await this.getAccess(this.accessId); @@ -102,7 +100,7 @@ export class CertApplyGetFormAliyunPlugin extends CertApplyBasePlugin { throw new Error("请先输入证书实例 ID"); } if (Array.isArray(this.orderId) && this.orderId.length > 0) { - this.orderId = this.orderId[0] + this.orderId = this.orderId[0]; } const certificateId = await this.getOrderDetailV2(client, this.orderId); this.logger.info(`获取到证书 ID:${certificateId}`); diff --git a/packages/ui/certd-server/src/plugins/plugin-cert/plugin/cert-plugin/index.ts b/packages/ui/certd-server/src/plugins/plugin-cert/plugin/cert-plugin/index.ts index c98286c7b..d0c8d871a 100644 --- a/packages/ui/certd-server/src/plugins/plugin-cert/plugin/cert-plugin/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-cert/plugin/cert-plugin/index.ts @@ -1,3 +1,2 @@ - export * from "./base.js"; export * from "./apply.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-cert/plugin/cert-plugin/lego/index.ts b/packages/ui/certd-server/src/plugins/plugin-cert/plugin/cert-plugin/lego/index.ts index 76dbaab40..edbfab999 100644 --- a/packages/ui/certd-server/src/plugins/plugin-cert/plugin/cert-plugin/lego/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-cert/plugin/cert-plugin/lego/index.ts @@ -7,7 +7,6 @@ import path from "path"; import JSZip from "jszip"; import { PrivateKeyType } from "./dns.js"; - @IsTaskPlugin({ name: "CertApplyLego", icon: "ph:certificate", diff --git a/packages/ui/certd-server/src/plugins/plugin-cloudflare/access.ts b/packages/ui/certd-server/src/plugins/plugin-cloudflare/access.ts index 6e50f8609..0f6e38142 100644 --- a/packages/ui/certd-server/src/plugins/plugin-cloudflare/access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-cloudflare/access.ts @@ -1,50 +1,48 @@ -import { IsAccess, AccessInput, BaseAccess } from '@certd/pipeline'; +import { IsAccess, AccessInput, BaseAccess } from "@certd/pipeline"; /** * 这个注解将注册一个授权配置 * 在certd的后台管理系统中,用户可以选择添加此类型的授权 */ @IsAccess({ - name: 'cloudflare', - title: 'cloudflare授权', - icon: 'simple-icons:cloudflare', - desc: '', + name: "cloudflare", + title: "cloudflare授权", + icon: "simple-icons:cloudflare", + desc: "", }) export class CloudflareAccess extends BaseAccess { /** * 授权属性配置 */ @AccessInput({ - title: 'API Token', + title: "API Token", component: { - placeholder: 'api token,用户 API 令牌', + placeholder: "api token,用户 API 令牌", }, - helper: - '前往 [获取API令牌](https://dash.cloudflare.com/profile/api-tokens),注意是令牌,不是密钥。\n token权限必须包含:[Zone区域-Zone区域-Edit编辑], [Zone区域-DNS-Edit编辑]', + helper: "前往 [获取API令牌](https://dash.cloudflare.com/profile/api-tokens),注意是令牌,不是密钥。\n token权限必须包含:[Zone区域-Zone区域-Edit编辑], [Zone区域-DNS-Edit编辑]", required: true, encrypt: true, }) - apiToken = ''; + apiToken = ""; @AccessInput({ - title: 'HTTP代理', + title: "HTTP代理", component: { - placeholder: 'http://xxxx.xxx.xx:10811', + placeholder: "http://xxxx.xxx.xx:10811", }, - helper: - '是否使用http代理', + helper: "是否使用http代理", required: false, encrypt: false, }) - proxy = ''; + proxy = ""; @AccessInput({ title: "测试", component: { name: "api-test", - action: "TestRequest" + action: "TestRequest", }, - helper: "测试授权是否正确" + helper: "测试授权是否正确", }) testRequest = true; @@ -53,20 +51,19 @@ export class CloudflareAccess extends BaseAccess { return "ok"; } - async getZoneList() { const url = `https://api.cloudflare.com/client/v4/zones`; - const res = await this.doRequestApi(url, null, 'get'); - return res.result + const res = await this.doRequestApi(url, null, "get"); + return res.result; } - async doRequestApi(url: string, data: any = null, method = 'post') { + async doRequestApi(url: string, data: any = null, method = "post") { try { const res = await this.ctx.http.request({ url, method, headers: { - 'Content-Type': 'application/json', + "Content-Type": "application/json", Authorization: `Bearer ${this.apiToken}`, }, data, @@ -81,14 +78,13 @@ export class CloudflareAccess extends BaseAccess { const data = e.response?.data; if (data && data.success === false && data.errors && data.errors.length > 0) { if (data.errors[0].code === 81058) { - this.ctx.logger.info('dns解析记录重复'); + this.ctx.logger.info("dns解析记录重复"); return null; } } throw e; } } - } new CloudflareAccess(); diff --git a/packages/ui/certd-server/src/plugins/plugin-cloudflare/dns-provider.ts b/packages/ui/certd-server/src/plugins/plugin-cloudflare/dns-provider.ts index 27e8700fe..d48868da2 100644 --- a/packages/ui/certd-server/src/plugins/plugin-cloudflare/dns-provider.ts +++ b/packages/ui/certd-server/src/plugins/plugin-cloudflare/dns-provider.ts @@ -1,7 +1,7 @@ -import { AbstractDnsProvider, CreateRecordOptions, DomainRecord, IsDnsProvider, RemoveRecordOptions } from '@certd/plugin-cert'; +import { AbstractDnsProvider, CreateRecordOptions, DomainRecord, IsDnsProvider, RemoveRecordOptions } from "@certd/plugin-cert"; -import { CloudflareAccess } from './access.js'; -import { Pager, PageRes, PageSearch } from '@certd/pipeline'; +import { CloudflareAccess } from "./access.js"; +import { Pager, PageRes, PageSearch } from "@certd/pipeline"; export type CloudflareRecord = { id: string; @@ -18,12 +18,12 @@ export type CloudflareRecord = { // 这里通过IsDnsProvider注册一个dnsProvider @IsDnsProvider({ - name: 'cloudflare', - title: 'cloudflare', - desc: 'cloudflare dns provider', - icon: 'simple-icons:cloudflare', + name: "cloudflare", + title: "cloudflare", + desc: "cloudflare dns provider", + icon: "simple-icons:cloudflare", // 这里是对应的 cloudflare的access类型名称 - accessType: 'cloudflare', + accessType: "cloudflare", }) export class CloudflareDnsProvider extends AbstractDnsProvider { access!: CloudflareAccess; @@ -39,17 +39,15 @@ export class CloudflareDnsProvider extends AbstractDnsProvider } async getZoneId(domain: string) { - this.logger.info('获取zoneId:', domain); + this.logger.info("获取zoneId:", domain); const url = `https://api.cloudflare.com/client/v4/zones?name=${domain}`; - const res = await this.access.doRequestApi(url, null, 'get'); + const res = await this.access.doRequestApi(url, null, "get"); if (res.result.length === 0) { throw new Error(`未找到域名${domain}的zoneId`); } return res.result[0].id; } - - /** * 创建dns解析记录,用于验证域名所有权 */ @@ -61,10 +59,10 @@ export class CloudflareDnsProvider extends AbstractDnsProvider * domain: 'example.com' */ const { fullRecord, value, type, domain } = options; - this.logger.info('添加域名解析:', fullRecord, value, type, domain); + this.logger.info("添加域名解析:", fullRecord, value, type, domain); const zoneId = await this.getZoneId(domain); - this.logger.info('获取zoneId成功:', zoneId); + this.logger.info("获取zoneId成功:", zoneId); // 给domain下创建txt类型的dns解析记录,fullRecord const url = `https://api.cloudflare.com/client/v4/zones/${zoneId}/dns_records`; @@ -92,7 +90,7 @@ export class CloudflareDnsProvider extends AbstractDnsProvider async findRecord(zoneId: string, options: CreateRecordOptions): Promise { const { fullRecord, value } = options; const url = `https://api.cloudflare.com/client/v4/zones/${zoneId}/dns_records?type=TXT&name=${fullRecord}&content=${value}`; - const res = await this.access.doRequestApi(url, null, 'get'); + const res = await this.access.doRequestApi(url, null, "get"); if (res.result.length === 0) { return null; } @@ -106,29 +104,29 @@ export class CloudflareDnsProvider extends AbstractDnsProvider async removeRecord(options: RemoveRecordOptions): Promise { const { fullRecord, value } = options.recordReq; const record = options.recordRes; - this.logger.info('删除域名解析:', fullRecord, value); + this.logger.info("删除域名解析:", fullRecord, value); if (!record) { - this.logger.info('record为空,不执行删除'); + this.logger.info("record为空,不执行删除"); return; } //这里调用删除txt dns解析记录接口 const zoneId = record.zone_id; const recordId = record.id; const url = `https://api.cloudflare.com/client/v4/zones/${zoneId}/dns_records/${recordId}`; - await this.access.doRequestApi(url, null, 'delete'); + await this.access.doRequestApi(url, null, "delete"); this.logger.info(`删除域名解析成功:fullRecord=${fullRecord},value=${value}`); } async getDomainListPage(req: PageSearch): Promise> { const pager = new Pager(req); - + let url = `https://api.cloudflare.com/client/v4/zones?page=${pager.pageNo}&per_page=${pager.pageSize}`; if (req.searchKey) { url += `&name=${req.searchKey}`; } - const ret = await this.access.doRequestApi(url, null, 'get'); + const ret = await this.access.doRequestApi(url, null, "get"); - let list = ret.result || [] + let list = ret.result || []; list = list.map((item: any) => ({ id: item.id, domain: item.name, diff --git a/packages/ui/certd-server/src/plugins/plugin-cloudflare/index.ts b/packages/ui/certd-server/src/plugins/plugin-cloudflare/index.ts index db899c717..d0bc76d38 100644 --- a/packages/ui/certd-server/src/plugins/plugin-cloudflare/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-cloudflare/index.ts @@ -1,2 +1,2 @@ -export * from './dns-provider.js'; -export * from './access.js'; +export * from "./dns-provider.js"; +export * from "./access.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-cmcc/access.ts b/packages/ui/certd-server/src/plugins/plugin-cmcc/access.ts index 4890042b2..c64b0a264 100644 --- a/packages/ui/certd-server/src/plugins/plugin-cmcc/access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-cmcc/access.ts @@ -11,45 +11,42 @@ import { CmccClient } from "./cmcc-client.js"; name: "cmcc", title: "中国移动CND授权", desc: "", - icon: "svg:cmcc" + icon: "svg:cmcc", }) export class CmccAccess extends BaseAccess { - @AccessInput({ - title: 'TenantID', + title: "TenantID", component: { - placeholder: 'TenantID', + placeholder: "TenantID", }, required: true, }) - tenantId = ''; - + tenantId = ""; @AccessInput({ - title: 'TenantKey', + title: "TenantKey", component: { - placeholder: 'TenantKey', + placeholder: "TenantKey", }, required: true, encrypt: true, }) - tenantKey = ''; - + tenantKey = ""; @AccessInput({ title: "测试", component: { name: "api-test", - action: "TestRequest" + action: "TestRequest", }, - helper: "点击测试接口是否正常" + helper: "点击测试接口是否正常", }) testRequest = true; async onTestRequest() { - const client = await this.getCmccClient() - await client.getDomainList({}) - return "ok" + const client = await this.getCmccClient(); + await client.getDomainList({}); + return "ok"; } async getCmccClient() { @@ -58,9 +55,8 @@ export class CmccAccess extends BaseAccess { tenantKey: this.tenantKey, http: this.ctx.http, logger: this.ctx.logger, - }) + }); } } - new CmccAccess(); diff --git a/packages/ui/certd-server/src/plugins/plugin-cmcc/cmcc-client.ts b/packages/ui/certd-server/src/plugins/plugin-cmcc/cmcc-client.ts index dcf72031c..857e36920 100644 --- a/packages/ui/certd-server/src/plugins/plugin-cmcc/cmcc-client.ts +++ b/packages/ui/certd-server/src/plugins/plugin-cmcc/cmcc-client.ts @@ -1,6 +1,6 @@ -import { HttpClient, ILogger } from '@certd/basic'; -import { CertInfo, CertReader } from '@certd/plugin-cert'; -import * as crypto from 'crypto'; +import { HttpClient, ILogger } from "@certd/basic"; +import { CertInfo, CertReader } from "@certd/plugin-cert"; +import * as crypto from "crypto"; export interface CmcdnConfig { tenantId: string; tenantKey: string; @@ -25,18 +25,18 @@ export class CmccClient { */ constructor(config: CmcdnConfig) { this.config = { - endpoint: 'https://p.cdn.10086.cn/', + endpoint: "https://p.cdn.10086.cn/", ...config, }; - this.http = config.http + this.http = config.http; this.logger = config.logger; if (!this.config.tenantId) { - throw new Error('tenantId is required'); + throw new Error("tenantId is required"); } if (!this.config.tenantKey) { - throw new Error('tenantKey is required'); + throw new Error("tenantKey is required"); } } @@ -46,7 +46,7 @@ export class CmccClient { * @returns SHA256哈希值 */ private sha256Hex(data: string): string { - return crypto.createHash('sha256').update(data).digest('hex'); + return crypto.createHash("sha256").update(data).digest("hex"); } /** @@ -74,7 +74,7 @@ export class CmccClient { * @returns 签名 */ private generateApiSign(body: any, token: string): string { - const bodyStr = body ? JSON.stringify(body) : ''; + const bodyStr = body ? JSON.stringify(body) : ""; return this.sha256Hex(bodyStr + token); } @@ -89,8 +89,6 @@ export class CmccClient { return Date.now() < this.tokenExpiresAt; } - - /** * 获取认证token * @returns 认证token @@ -114,17 +112,17 @@ export class CmccClient { const response = await this.http.request({ baseURL: this.config.endpoint, - url: '/api/authentication', - method: 'POST', + url: "/api/authentication", + method: "POST", headers: { - 'Content-Type': 'application/json', - 'Accept': 'application/json', + "Content-Type": "application/json", + Accept: "application/json", }, data: authRequest, skipSslVerify: true, logParams: false, logRes: false, - logData: false + logData: false, }); this.token = response.token; @@ -144,18 +142,18 @@ export class CmccClient { // 设置默认headers const defaultHeaders: Record = { - 'Content-Type': 'application/json', - 'Accept': 'application/vnd.cmcdn+json', - 'CMCDN-Auth-Token': token, + "Content-Type": "application/json", + Accept: "application/vnd.cmcdn+json", + "CMCDN-Auth-Token": token, }; // 生成签名 - if (req.method === 'POST' || req.method === 'PUT') { + if (req.method === "POST" || req.method === "PUT") { const signature = this.generateApiSign(req.data, token); - defaultHeaders['HTTP-X-CMCDN-Signature'] = signature; + defaultHeaders["HTTP-X-CMCDN-Signature"] = signature; } else { const signature = this.sha256Hex(token); - defaultHeaders['HTTP-X-CMCDN-Signature'] = signature; + defaultHeaders["HTTP-X-CMCDN-Signature"] = signature; } // 合并自定义headers @@ -172,7 +170,7 @@ export class CmccClient { skipSslVerify: true, logParams: false, logRes: false, - logData: false + logData: false, }); if (response.error_code != 0) { this.logger.error(`接口请求失败,${JSON.stringify(response)}`); @@ -283,16 +281,15 @@ export class CmccClient { ] } */ - async getDomainList(req: { domainName?: string, domainStatus?: string }) { - + async getDomainList(req: { domainName?: string; domainStatus?: string }) { const res = await this.doRequest({ url: "/api/domain_list", method: "GET", params: { domainName: req.domainName, domainStatus: req.domainStatus, - } - }) + }, + }); this.logger.info("getDomainList", res); @@ -364,7 +361,6 @@ export class CmccClient { 12.1.4.2请求报文示例 */ async uploadCert(req: { cert: CertInfo }) { - const certReader = new CertReader(req.cert); const res = await this.doRequest({ url: "/api/config/action?commandType=saveCrt&version=1", @@ -373,8 +369,8 @@ export class CmccClient { certificate: req.cert.crt, private_key: req.cert.key, crt_name: certReader.buildCertName(), - } - }) + }, + }); this.logger.info("uploadCert", res); @@ -382,10 +378,10 @@ export class CmccClient { } /** - * - * @param req + * + * @param req */ - async deployCertToCdn(req: { domainNames: string[], certId: string }) { + async deployCertToCdn(req: { domainNames: string[]; certId: string }) { // /api/config/action?commandType = manageDomainBaseConfig&version = 1 const res = await this.doRequest({ url: "/api/config/action?commandType=manageDomainBaseConfig&version=1", @@ -395,11 +391,10 @@ export class CmccClient { domains: req.domainNames, https_enable: true, unique_id: req.certId, - } - }) + }, + }); this.logger.info("deployCertToCdn", res); return res.data; } - } diff --git a/packages/ui/certd-server/src/plugins/plugin-cmcc/index.ts b/packages/ui/certd-server/src/plugins/plugin-cmcc/index.ts index 8572082ac..cd4b41cd8 100644 --- a/packages/ui/certd-server/src/plugins/plugin-cmcc/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-cmcc/index.ts @@ -1,2 +1,2 @@ -export * from './access.js' -export * from './plugin-deploy-to-cdn.js' \ No newline at end of file +export * from "./access.js"; +export * from "./plugin-deploy-to-cdn.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-cmcc/plugin-deploy-to-cdn.ts b/packages/ui/certd-server/src/plugins/plugin-cmcc/plugin-deploy-to-cdn.ts index f27d7473a..6f02b96be 100644 --- a/packages/ui/certd-server/src/plugins/plugin-cmcc/plugin-deploy-to-cdn.ts +++ b/packages/ui/certd-server/src/plugins/plugin-cmcc/plugin-deploy-to-cdn.ts @@ -1,10 +1,4 @@ -import { - IsTaskPlugin, - PageSearch, - pluginGroups, - RunStrategy, - TaskInput -} from "@certd/pipeline"; +import { IsTaskPlugin, PageSearch, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; import { CertApplyPluginNames, CertInfo } from "@certd/plugin-cert"; import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from "@certd/plugin-lib"; import { AbstractPlusTaskPlugin } from "@certd/plugin-plus"; @@ -22,9 +16,9 @@ import { CmccAccess } from "./access.js"; default: { //默认值配置照抄即可 strategy: { - runStrategy: RunStrategy.SkipWhenSucceed - } - } + runStrategy: RunStrategy.SkipWhenSucceed, + }, + }, }) //类名规范,跟上面插件名称(name)一致 export class CmccDeployCertToCdn extends AbstractPlusTaskPlugin { @@ -34,8 +28,8 @@ export class CmccDeployCertToCdn extends AbstractPlusTaskPlugin { helper: "请选择前置任务输出的域名证书", component: { name: "output-selector", - from: [...CertApplyPluginNames] - } + from: [...CertApplyPluginNames], + }, // required: true, // 必填 }) cert!: CertInfo; @@ -48,9 +42,9 @@ export class CmccDeployCertToCdn extends AbstractPlusTaskPlugin { title: "中国移动-授权", component: { name: "access-selector", - type: "cmcc" //固定授权类型 + type: "cmcc", //固定授权类型 }, - required: true //必填 + required: true, //必填 }) accessId!: string; // @@ -61,14 +55,13 @@ export class CmccDeployCertToCdn extends AbstractPlusTaskPlugin { helper: "要更新的中国移动CDN域名", action: CmccDeployCertToCdn.prototype.onGetDomainList.name, pager: false, - search: false + search: false, }) ) domainList!: string[]; //插件实例化时执行的方法 - async onInstance() { - } + async onInstance() {} //插件执行方法 async execute(): Promise { @@ -77,17 +70,16 @@ export class CmccDeployCertToCdn extends AbstractPlusTaskPlugin { const client = await access.getCmccClient(); this.logger.info(`----------- 开始更新证书:${this.domainList}`); - const newCert = await client.uploadCert({ - cert: this.cert - }) + cert: this.cert, + }); - const certId = newCert.unique_id + const certId = newCert.unique_id; this.logger.info(`----------- 上传证书成功,证书ID:${certId}`); await client.deployCertToCdn({ certId: certId, - domainNames: this.domainList + domainNames: this.domainList, }); this.logger.info(`----------- 更新证书${this.domainList}成功,等待10s`); await this.ctx.utils.sleep(10000); @@ -96,14 +88,13 @@ export class CmccDeployCertToCdn extends AbstractPlusTaskPlugin { async onGetDomainList(data: PageSearch = {}) { const access = await this.getAccess(this.accessId); - const client= await access.getCmccClient(); - const res = await client.getDomainList({}) - const list = res || [] + const client = await access.getCmccClient(); + const res = await client.getDomainList({}); + const list = res || []; if (!list || list.length === 0) { throw new Error("没有找到加速域名"); } - /** * certificate-id * name @@ -113,7 +104,7 @@ export class CmccDeployCertToCdn extends AbstractPlusTaskPlugin { return { label: `${item.domainName}`, value: item.domainName, - domain: item.domainName + domain: item.domainName, }; }); return { diff --git a/packages/ui/certd-server/src/plugins/plugin-demo/access.ts b/packages/ui/certd-server/src/plugins/plugin-demo/access.ts index 4124654a5..a9b184569 100644 --- a/packages/ui/certd-server/src/plugins/plugin-demo/access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-demo/access.ts @@ -1,66 +1,65 @@ -import { AccessInput, BaseAccess, IsAccess, Pager, PageRes, PageSearch } from '@certd/pipeline'; -import { DomainRecord } from '@certd/plugin-lib'; +import { AccessInput, BaseAccess, IsAccess, Pager, PageRes, PageSearch } from "@certd/pipeline"; +import { DomainRecord } from "@certd/plugin-lib"; /** * 这个注解将注册一个授权配置 * 在certd的后台管理系统中,用户可以选择添加此类型的授权 */ @IsAccess({ - name: 'demo', - title: '授权插件示例', - icon: 'clarity:plugin-line', //插件图标 - desc: '这是一个示例授权插件,用于演示如何实现一个授权插件', + name: "demo", + title: "授权插件示例", + icon: "clarity:plugin-line", //插件图标 + desc: "这是一个示例授权插件,用于演示如何实现一个授权插件", }) export class DemoAccess extends BaseAccess { - - /** + /** * 授权属性配置 */ @AccessInput({ - title: '授权方式', - value: 'apiKey', //默认值 + title: "授权方式", + value: "apiKey", //默认值 component: { name: "a-select", //基于antdv的输入组件 vModel: "value", // v-model绑定的属性名 - options: [ //组件参数 + options: [ + //组件参数 { label: "API密钥(推荐)", value: "apiKey" }, { label: "账号密码", value: "account" }, ], - placeholder: 'demoKeyId', + placeholder: "demoKeyId", }, required: true, }) - apiType = ''; + apiType = ""; /** * 授权属性配置 */ @AccessInput({ - title: '密钥Id', + title: "密钥Id", component: { - name:"a-input", + name: "a-input", allowClear: true, - placeholder: 'demoKeyId', + placeholder: "demoKeyId", }, required: true, }) - demoKeyId = ''; + demoKeyId = ""; @AccessInput({ - title: '密钥',//标题 - required: true, //text组件可以省略 + title: "密钥", //标题 + required: true, //text组件可以省略 encrypt: true, //该属性是否需要加密 }) - demoKeySecret = ''; - + demoKeySecret = ""; @AccessInput({ title: "测试", component: { name: "api-test", - action: "TestRequest" + action: "TestRequest", }, - helper: "点击测试接口是否正常" + helper: "点击测试接口是否正常", }) testRequest = true; @@ -69,7 +68,7 @@ export class DemoAccess extends BaseAccess { */ async onTestRequest() { await this.GetDomainList({}); - return "ok" + return "ok"; } /** @@ -85,17 +84,17 @@ export class DemoAccess extends BaseAccess { domain: req.searchKey, offset: pager.getOffset(), limit: pager.pageSize, - } + }, }); const total = resp?.TotalCount || 0; - let list = resp?.DomainList?.map((item) => { + const list = resp?.DomainList?.map(item => { item.domain = item.Domain; item.id = item.DomainId; return item; - }) + }); return { total, - list + list, }; } @@ -104,7 +103,7 @@ export class DemoAccess extends BaseAccess { /** * 通用api调用方法, 具体如何构造请求体,需参考对应应用的API文档 */ - async doRequest(req: { action: string, data?: any }) { + async doRequest(req: { action: string; data?: any }) { /** this.ctx中包含很多有用的工具类 type AccessContext = { @@ -119,12 +118,12 @@ export class DemoAccess extends BaseAccess { method: "POST", data: { Action: req.action, - Body: req.data - } + Body: req.data, + }, }); if (res.Code !== 0) { - //异常处理 + //异常处理 throw new Error(res.Message || "请求失败"); } return res.Resp; diff --git a/packages/ui/certd-server/src/plugins/plugin-demo/dns-provider.ts b/packages/ui/certd-server/src/plugins/plugin-demo/dns-provider.ts index 596159e35..5640178c6 100644 --- a/packages/ui/certd-server/src/plugins/plugin-demo/dns-provider.ts +++ b/packages/ui/certd-server/src/plugins/plugin-demo/dns-provider.ts @@ -1,8 +1,8 @@ -import { AbstractDnsProvider, CreateRecordOptions, DomainRecord, IsDnsProvider, RemoveRecordOptions } from '@certd/plugin-cert'; +import { AbstractDnsProvider, CreateRecordOptions, DomainRecord, IsDnsProvider, RemoveRecordOptions } from "@certd/plugin-cert"; -import { PageRes, PageSearch } from '@certd/pipeline'; -import { isDev } from '../../utils/env.js'; -import { DemoAccess } from './access.js'; +import { PageRes, PageSearch } from "@certd/pipeline"; +import { isDev } from "../../utils/env.js"; +import { DemoAccess } from "./access.js"; type DemoRecord = { // 这里定义Record记录的数据结构,跟对应云平台接口返回值一样即可,一般是拿到id就行,用于删除txt解析记录,清理申请痕迹 @@ -11,21 +11,21 @@ type DemoRecord = { // 这里通过IsDnsProvider注册一个dnsProvider @IsDnsProvider({ - name: 'demo', - title: 'Dns提供商Demo', - desc: 'dns provider示例', - icon: 'clarity:plugin-line', + name: "demo", + title: "Dns提供商Demo", + desc: "dns provider示例", + icon: "clarity:plugin-line", // 这里是对应的云平台的access类型名称 - accessType: 'demo', + accessType: "demo", order: 99, }) export class DemoDnsProvider extends AbstractDnsProvider { access!: DemoAccess; async onInstance() { - this.access = this.ctx.access as DemoAccess + this.access = this.ctx.access as DemoAccess; // 也可以通过ctx成员变量传递context - this.logger.debug('access', this.access); + this.logger.debug("access", this.access); //初始化的操作 //... } @@ -42,7 +42,7 @@ export class DemoDnsProvider extends AbstractDnsProvider { * domain: 'example.com' */ const { fullRecord, value, type, domain } = options; - this.logger.info('添加域名解析:', fullRecord, value, type, domain); + this.logger.info("添加域名解析:", fullRecord, value, type, domain); // 调用创建dns解析记录的对应的云端接口,创建txt类型的dns解析记录 // 请根据实际接口情况调用,例如: @@ -62,7 +62,7 @@ export class DemoDnsProvider extends AbstractDnsProvider { async removeRecord(options: RemoveRecordOptions): Promise { const { fullRecord, value, domain } = options.recordReq; const record = options.recordRes; - this.logger.info('删除域名解析:', domain, fullRecord, value, record); + this.logger.info("删除域名解析:", domain, fullRecord, value, record); //这里调用删除txt dns解析记录接口 //请根据实际接口情况调用,例如: @@ -73,29 +73,28 @@ export class DemoDnsProvider extends AbstractDnsProvider { // }) // - this.logger.info('删除域名解析成功:', fullRecord, value); + this.logger.info("删除域名解析成功:", fullRecord, value); } /** - * + * * @param req 实现获取域名列表 - * @returns + * @returns */ async getDomainListPage(req: PageSearch): Promise> { const res = await this.http.request({ // 请求接口获取域名列表 - }) - const list = [] + }); + const list = []; // const list = res.Domains?.map(item => ({ // id: item.Id, // domain: item.DomainName, // })) || [] - return { list, total: res.Total, - } + }; } } diff --git a/packages/ui/certd-server/src/plugins/plugin-demo/index.ts b/packages/ui/certd-server/src/plugins/plugin-demo/index.ts index bce2c52de..dde893dd1 100644 --- a/packages/ui/certd-server/src/plugins/plugin-demo/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-demo/index.ts @@ -1,3 +1,3 @@ -export * from './dns-provider.js'; -export * from './plugins/index.js'; -export * from './access.js'; +export * from "./dns-provider.js"; +export * from "./plugins/index.js"; +export * from "./access.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-demo/plugins/index.ts b/packages/ui/certd-server/src/plugins/plugin-demo/plugins/index.ts index 9c02cfce0..13101816a 100644 --- a/packages/ui/certd-server/src/plugins/plugin-demo/plugins/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-demo/plugins/index.ts @@ -1 +1 @@ -export * from './plugin-test.js'; +export * from "./plugin-test.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-demo/plugins/plugin-test.ts b/packages/ui/certd-server/src/plugins/plugin-demo/plugins/plugin-test.ts index 6239b0741..ae27860f8 100644 --- a/packages/ui/certd-server/src/plugins/plugin-demo/plugins/plugin-test.ts +++ b/packages/ui/certd-server/src/plugins/plugin-demo/plugins/plugin-test.ts @@ -1,13 +1,13 @@ -import { AbstractTaskPlugin, IsTaskPlugin, PageSearch, pluginGroups, RunStrategy, TaskInput } from '@certd/pipeline'; -import { CertInfo, CertReader } from '@certd/plugin-cert'; -import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from '@certd/plugin-lib'; -import { optionsUtils } from '@certd/basic'; -import { CertApplyPluginNames} from '@certd/plugin-cert'; +import { AbstractTaskPlugin, IsTaskPlugin, PageSearch, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; +import { CertInfo, CertReader } from "@certd/plugin-cert"; +import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from "@certd/plugin-lib"; +import { optionsUtils } from "@certd/basic"; +import { CertApplyPluginNames } from "@certd/plugin-cert"; @IsTaskPlugin({ //命名规范,插件类型+功能(就是目录plugin-demo中的demo),大写字母开头,驼峰命名 - name: 'DemoTest', - title: 'Demo-测试插件', - icon: 'clarity:plugin-line', + name: "DemoTest", + title: "Demo-测试插件", + icon: "clarity:plugin-line", //插件分组 group: pluginGroups.other.key, default: { @@ -21,37 +21,37 @@ import { CertApplyPluginNames} from '@certd/plugin-cert'; export class DemoTest extends AbstractTaskPlugin { //测试参数 @TaskInput({ - title: '属性示例', - value: '默认值', + title: "属性示例", + value: "默认值", component: { //前端组件配置,具体配置见组件文档 https://www.antdv.com/components/input-cn - name: 'a-input', - vModel: 'value', //双向绑定组件的props名称 + name: "a-input", + vModel: "value", //双向绑定组件的props名称 }, - helper: '帮助说明,[链接](https://certd.docmirror.cn)', + helper: "帮助说明,[链接](https://certd.docmirror.cn)", required: false, //是否必填 }) text!: string; //测试参数 @TaskInput({ - title: '选择框', + title: "选择框", component: { //前端组件配置,具体配置见组件文档 https://www.antdv.com/components/select-cn - name: 'a-auto-complete', - vModel: 'value', + name: "a-auto-complete", + vModel: "value", options: [ //选项列表 - { value: 'show', label: '动态显' }, - { value: 'hide', label: '动态隐' }, + { value: "show", label: "动态显" }, + { value: "hide", label: "动态隐" }, ], }, }) select!: string; @TaskInput({ - title: '动态显隐', - helper: '我会根据选择框的值进行显隐', + title: "动态显隐", + helper: "我会根据选择框的值进行显隐", show: true, //动态计算的值会覆盖它 //动态计算脚本, mergeScript返回的对象会合并当前配置,此处演示 show的值会被动态计算结果覆盖,show的值根据用户选择的select的值决定 mergeScript: ` @@ -66,16 +66,16 @@ export class DemoTest extends AbstractTaskPlugin { //测试参数 @TaskInput({ - title: '多选框', + title: "多选框", component: { //前端组件配置,具体配置见组件文档 https://www.antdv.com/components/select-cn - name: 'a-select', - vModel: 'value', - mode: 'tags', + name: "a-select", + vModel: "value", + mode: "tags", multiple: true, options: [ - { value: '1', label: '选项1' }, - { value: '2', label: '选项2' }, + { value: "1", label: "选项1" }, + { value: "2", label: "选项2" }, ], }, }) @@ -83,20 +83,20 @@ export class DemoTest extends AbstractTaskPlugin { //测试参数 @TaskInput({ - title: 'switch', + title: "switch", component: { //前端组件配置,具体配置见组件文档 https://www.antdv.com/components/switch-cn - name: 'a-switch', - vModel: 'checked', + name: "a-switch", + vModel: "checked", }, }) switch!: boolean; //证书选择,此项必须要有 @TaskInput({ - title: '域名证书', - helper: '请选择前置任务输出的域名证书', + title: "域名证书", + helper: "请选择前置任务输出的域名证书", component: { - name: 'output-selector', + name: "output-selector", from: [...CertApplyPluginNames], }, // required: true, // 必填 @@ -109,11 +109,11 @@ export class DemoTest extends AbstractTaskPlugin { //授权选择框 @TaskInput({ - title: 'demo授权', - helper: 'demoAccess授权', + title: "demo授权", + helper: "demoAccess授权", component: { - name: 'access-selector', - type: 'demo', //固定授权类型 + name: "access-selector", + type: "demo", //固定授权类型 }, // rules: [{ required: true, message: '此项必填' }], // required: true, //必填 @@ -122,11 +122,11 @@ export class DemoTest extends AbstractTaskPlugin { @TaskInput( createRemoteSelectInputDefine({ - title: '从后端获取选项', - helper: '选择时可以从后端获取选项', + title: "从后端获取选项", + helper: "选择时可以从后端获取选项", action: DemoTest.prototype.onGetSiteList.name, //当以下参数变化时,触发获取选项 - watches: ['certDomains', 'accessId'], + watches: ["certDomains", "accessId"], required: true, single: false, }) @@ -142,23 +142,23 @@ export class DemoTest extends AbstractTaskPlugin { try { const access = await this.getAccess(accessId); - this.logger.debug('access', access); + this.logger.debug("access", access); } catch (e) { - this.logger.error('获取授权失败', e); + this.logger.error("获取授权失败", e); } try { const certReader = new CertReader(cert); - this.logger.debug('certReader', certReader); + this.logger.debug("certReader", certReader); } catch (e) { - this.logger.error('读取crt失败', e); + this.logger.error("读取crt失败", e); } - this.logger.info('DemoTestPlugin execute'); - this.logger.info('text:', text); - this.logger.info('select:', select); - this.logger.info('switch:', this.switch); - this.logger.info('授权id:', accessId); + this.logger.info("DemoTestPlugin execute"); + this.logger.info("text:", text); + this.logger.info("select:", select); + this.logger.info("switch:", this.switch); + this.logger.info("授权id:", accessId); // const res = await this.http.request({ // url: 'https://api.demo.com', @@ -174,7 +174,7 @@ export class DemoTest extends AbstractTaskPlugin { //此方法演示,如何让前端在添加插件时可以从后端获取选项,这里是后端返回选项的方法 async onGetSiteList(req: PageSearch) { if (!this.accessId) { - throw new Error('请选择Access授权'); + throw new Error("请选择Access授权"); } // @ts-ignore @@ -183,9 +183,9 @@ export class DemoTest extends AbstractTaskPlugin { // const siteRes = await access.GetDomainList(req); //以下是模拟数据 const siteRes = [ - { id: 1, siteName: 'site1.com' }, - { id: 2, siteName: 'site2.com' }, - { id: 3, siteName: 'site2.com' }, + { id: 1, siteName: "site1.com" }, + { id: 2, siteName: "site2.com" }, + { id: 3, siteName: "site2.com" }, ]; //转换为前端所需要的格式 const options = siteRes.map((item: any) => { diff --git a/packages/ui/certd-server/src/plugins/plugin-dnsla/access.ts b/packages/ui/certd-server/src/plugins/plugin-dnsla/access.ts index e73c754e1..5f2e6bf5d 100644 --- a/packages/ui/certd-server/src/plugins/plugin-dnsla/access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-dnsla/access.ts @@ -1,50 +1,49 @@ -import { IsAccess, AccessInput, BaseAccess, PageSearch, PageRes, Pager } from '@certd/pipeline'; -import { DomainRecord } from '@certd/plugin-lib'; +import { IsAccess, AccessInput, BaseAccess, PageSearch, PageRes, Pager } from "@certd/pipeline"; +import { DomainRecord } from "@certd/plugin-lib"; /** * 这个注解将注册一个授权配置 * 在certd的后台管理系统中,用户可以选择添加此类型的授权 */ @IsAccess({ - name: 'dnsla', - title: 'dns.la授权', - icon: 'arcticons:dns-changer-3', - desc: '', + name: "dnsla", + title: "dns.la授权", + icon: "arcticons:dns-changer-3", + desc: "", }) export class DnslaAccess extends BaseAccess { /** * 授权属性配置 */ @AccessInput({ - title: 'APIID', + title: "APIID", component: { - placeholder: 'APIID', + placeholder: "APIID", }, helper: "从我的账户->API密钥中获取 APIID APISecret", required: true, encrypt: false, }) - apiId = ''; + apiId = ""; @AccessInput({ - title: 'APISecret', + title: "APISecret", component: { - placeholder: '', + placeholder: "", }, - helper: - '', + helper: "", required: false, encrypt: true, }) - apiSecret = ''; + apiSecret = ""; @AccessInput({ title: "测试", component: { name: "api-test", - action: "TestRequest" + action: "TestRequest", }, - helper: "测试授权是否正确" + helper: "测试授权是否正确", }) testRequest = true; @@ -56,13 +55,12 @@ export class DnslaAccess extends BaseAccess { return "ok"; } - async getDomainListPage(req: PageSearch): Promise> { const pager = new Pager(req); const url = `/api/domainList?pageIndex=${pager.pageNo}&pageSize=${pager.pageSize}`; - const ret = await this.doRequestApi(url, null, 'get'); + const ret = await this.doRequestApi(url, null, "get"); - let list = ret.data.results || [] + let list = ret.data.results || []; list = list.map((item: any) => ({ id: item.id, domain: item.domain, @@ -74,9 +72,7 @@ export class DnslaAccess extends BaseAccess { }; } - - - async doRequestApi(url: string, data: any = null, method = 'post') { + async doRequestApi(url: string, data: any = null, method = "post") { /** * Basic 认证 * 我的账户 API 密钥 中获取 APIID APISecret @@ -96,12 +92,12 @@ export class DnslaAccess extends BaseAccess { * "data":{} * } */ - const token = Buffer.from(`${this.apiId}:${this.apiSecret}`).toString('base64'); + const token = Buffer.from(`${this.apiId}:${this.apiSecret}`).toString("base64"); const res = await this.ctx.http.request({ url: "https://api.dns.la" + url, method, headers: { - 'Content-Type': 'application/json', + "Content-Type": "application/json", Authorization: `Basic ${token}`, }, data, @@ -111,9 +107,7 @@ export class DnslaAccess extends BaseAccess { throw new Error(res.msg); } return res; - } - } new DnslaAccess(); diff --git a/packages/ui/certd-server/src/plugins/plugin-dnsla/dns-provider.ts b/packages/ui/certd-server/src/plugins/plugin-dnsla/dns-provider.ts index d9d4ad30b..139817caf 100644 --- a/packages/ui/certd-server/src/plugins/plugin-dnsla/dns-provider.ts +++ b/packages/ui/certd-server/src/plugins/plugin-dnsla/dns-provider.ts @@ -9,12 +9,12 @@ export type DnslaRecord = { // 这里通过IsDnsProvider注册一个dnsProvider @IsDnsProvider({ - name: 'dnsla', - title: 'dns.la', - desc: 'dns.la', - icon: 'arcticons:dns-changer-3', + name: "dnsla", + title: "dns.la", + desc: "dns.la", + icon: "arcticons:dns-changer-3", // 这里是对应的 cloudflare的access类型名称 - accessType: 'dnsla', + accessType: "dnsla", }) export class DnslaDnsProvider extends AbstractDnsProvider { access!: DnslaAccess; @@ -24,9 +24,7 @@ export class DnslaDnsProvider extends AbstractDnsProvider { this.access = this.ctx.access as DnslaAccess; } - - - async getDomainDetail(domain:string){ + async getDomainDetail(domain: string) { /** * 请求示例 * GET /api/domain?id=85371689655342080&domain=test.com HTTP/1.1 @@ -51,8 +49,8 @@ export class DnslaDnsProvider extends AbstractDnsProvider { */ const url = `/api/domain?domain=${domain}`; - const res = await this.access.doRequestApi(url, null, 'get'); - return res.data + const res = await this.access.doRequestApi(url, null, "get"); + return res.data; } /** @@ -66,12 +64,11 @@ export class DnslaDnsProvider extends AbstractDnsProvider { * domain: 'example.com' */ const { fullRecord, value, type, domain } = options; - this.logger.info('添加域名解析:', fullRecord, value, type, domain); + this.logger.info("添加域名解析:", fullRecord, value, type, domain); const domainDetail = await this.getDomainDetail(domain); const domainId = domainDetail.id; - this.logger.info('获取domainId成功:', domainId); - + this.logger.info("获取domainId成功:", domainId); // 给domain下创建txt类型的dns解析记录,fullRecord /** @@ -107,7 +104,7 @@ export class DnslaDnsProvider extends AbstractDnsProvider { const res = await this.access.doRequestApi(url, { domainId: domainId, type: 16, - host: fullRecord.replace(`.${domain}`, ''), + host: fullRecord.replace(`.${domain}`, ""), data: value, ttl: 60, }); @@ -115,7 +112,6 @@ export class DnslaDnsProvider extends AbstractDnsProvider { return res.data; } - /** * 删除dns解析记录,清理申请痕迹 * @param options @@ -123,9 +119,9 @@ export class DnslaDnsProvider extends AbstractDnsProvider { async removeRecord(options: RemoveRecordOptions): Promise { const { fullRecord, value } = options.recordReq; const record = options.recordRes; - this.logger.info('删除域名解析:', fullRecord, value); + this.logger.info("删除域名解析:", fullRecord, value); if (!record) { - this.logger.info('record为空,不执行删除'); + this.logger.info("record为空,不执行删除"); return; } //这里调用删除txt dns解析记录接口 @@ -137,14 +133,13 @@ export class DnslaDnsProvider extends AbstractDnsProvider { */ const recordId = record.id; const url = `/api/record?id=${recordId}`; - await this.access.doRequestApi(url, null, 'delete'); + await this.access.doRequestApi(url, null, "delete"); this.logger.info(`删除域名解析成功:fullRecord=${fullRecord},value=${value}`); } async getDomainListPage(req: PageSearch): Promise> { return await this.access.getDomainListPage(req); } - } //实例化这个provider,将其自动注册到系统中 diff --git a/packages/ui/certd-server/src/plugins/plugin-dnsla/index.ts b/packages/ui/certd-server/src/plugins/plugin-dnsla/index.ts index db899c717..d0bc76d38 100644 --- a/packages/ui/certd-server/src/plugins/plugin-dnsla/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-dnsla/index.ts @@ -1,2 +1,2 @@ -export * from './dns-provider.js'; -export * from './access.js'; +export * from "./dns-provider.js"; +export * from "./access.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-dnsmgr/access.ts b/packages/ui/certd-server/src/plugins/plugin-dnsmgr/access.ts index 9d05507ee..8b60d4c6c 100644 --- a/packages/ui/certd-server/src/plugins/plugin-dnsmgr/access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-dnsmgr/access.ts @@ -1,49 +1,49 @@ -import { AccessInput, BaseAccess, IsAccess, Pager, PageRes, PageSearch } from '@certd/pipeline'; -import { DomainRecord } from '@certd/plugin-lib'; +import { AccessInput, BaseAccess, IsAccess, Pager, PageRes, PageSearch } from "@certd/pipeline"; +import { DomainRecord } from "@certd/plugin-lib"; @IsAccess({ - name: 'dnsmgr', - title: '彩虹DNS', - icon: 'clarity:plugin-line', - desc: '彩虹DNS管理系统授权', + name: "dnsmgr", + title: "彩虹DNS", + icon: "clarity:plugin-line", + desc: "彩虹DNS管理系统授权", }) export class DnsmgrAccess extends BaseAccess { @AccessInput({ - title: '系统地址', + title: "系统地址", component: { name: "a-input", allowClear: true, - placeholder: 'https://dnsmgr.example.com', + placeholder: "https://dnsmgr.example.com", }, required: true, }) - endpoint = ''; + endpoint = ""; @AccessInput({ - title: '用户ID', + title: "用户ID", component: { name: "a-input", allowClear: true, - placeholder: '123456', + placeholder: "123456", }, required: true, }) - uid = ''; + uid = ""; @AccessInput({ - title: 'API密钥', + title: "API密钥", required: true, encrypt: true, }) - key = ''; + key = ""; @AccessInput({ title: "测试", component: { name: "api-test", - action: "TestRequest" + action: "TestRequest", }, - helper: "点击测试接口是否正常" + helper: "点击测试接口是否正常", }) testRequest = true; @@ -56,7 +56,7 @@ export class DnsmgrAccess extends BaseAccess { this.ctx.logger.info(`获取域名列表,req:${JSON.stringify(req)}`); const pager = new Pager(req); const resp = await this.doRequest({ - url: '/api/domain', + url: "/api/domain", data: { offset: pager.getOffset(), limit: pager.pageSize, @@ -64,7 +64,7 @@ export class DnsmgrAccess extends BaseAccess { }, }); const total = resp?.total || 0; - let list = resp?.rows?.map((item: any) => { + const list = resp?.rows?.map((item: any) => { return { domain: item.name, ...item, @@ -76,17 +76,15 @@ export class DnsmgrAccess extends BaseAccess { }; } - - async createDnsRecord(domainId: string, record: string, value: string, type: string, domain: string) { this.ctx.logger.info(`创建DNS记录:${record} ${type} ${value}`); const resp = await this.doRequest({ url: `/api/record/add/${domainId}`, data: { - name: record.replace(`.${domain}`, ''), + name: record.replace(`.${domain}`, ""), type, value, - line: 'default', + line: "default", ttl: 600, }, }); @@ -121,12 +119,12 @@ export class DnsmgrAccess extends BaseAccess { const timestamp = Math.floor(Date.now() / 1000); const sign = this.ctx.utils.hash.md5(`${this.uid}${timestamp}${this.key}`); const url = `${this.endpoint}${req.url}`; - + const res = await this.ctx.http.request({ url, - method: 'POST', + method: "POST", headers: { - 'Content-Type': 'application/x-www-form-urlencoded', + "Content-Type": "application/x-www-form-urlencoded", }, data: { uid: this.uid, @@ -137,7 +135,7 @@ export class DnsmgrAccess extends BaseAccess { }); if (res.code !== undefined && res.code !== 0) { - throw new Error(res.msg || '请求失败'); + throw new Error(res.msg || "请求失败"); } return res; } diff --git a/packages/ui/certd-server/src/plugins/plugin-dnsmgr/dns-provider.ts b/packages/ui/certd-server/src/plugins/plugin-dnsmgr/dns-provider.ts index fb201e96e..26ea527d9 100644 --- a/packages/ui/certd-server/src/plugins/plugin-dnsmgr/dns-provider.ts +++ b/packages/ui/certd-server/src/plugins/plugin-dnsmgr/dns-provider.ts @@ -1,6 +1,6 @@ -import { AbstractDnsProvider, CreateRecordOptions, DomainRecord, IsDnsProvider, RemoveRecordOptions } from '@certd/plugin-cert'; -import { DnsmgrAccess } from './access.js'; -import { PageRes, PageSearch } from '@certd/pipeline'; +import { AbstractDnsProvider, CreateRecordOptions, DomainRecord, IsDnsProvider, RemoveRecordOptions } from "@certd/plugin-cert"; +import { DnsmgrAccess } from "./access.js"; +import { PageRes, PageSearch } from "@certd/pipeline"; type DnsmgrRecord = { domainId: string; @@ -9,11 +9,11 @@ type DnsmgrRecord = { }; @IsDnsProvider({ - name: 'dnsmgr', - title: '彩虹DNS', - desc: '彩虹DNS管理系统', - icon: 'clarity:plugin-line', - accessType: 'dnsmgr', + name: "dnsmgr", + title: "彩虹DNS", + desc: "彩虹DNS管理系统", + icon: "clarity:plugin-line", + accessType: "dnsmgr", order: 99, }) export class DnsmgrDnsProvider extends AbstractDnsProvider { @@ -21,39 +21,39 @@ export class DnsmgrDnsProvider extends AbstractDnsProvider { async onInstance() { this.access = this.ctx.access as DnsmgrAccess; - this.logger.debug('access', this.access); + this.logger.debug("access", this.access); } async createRecord(options: CreateRecordOptions): Promise { const { fullRecord, value, type, domain } = options; - this.logger.info('添加域名解析:', fullRecord, value, type, domain); + this.logger.info("添加域名解析:", fullRecord, value, type, domain); const domainList = await this.access.GetDomainList({ searchKey: domain }); const domainInfo = domainList.list?.find((item: any) => item.name === domain); - + if (!domainInfo) { throw new Error(`未找到域名:${domain}`); } - const name = fullRecord.replace(`.${domain}`, ''); + const name = fullRecord.replace(`.${domain}`, ""); const res = await this.access.createDnsRecord(domainInfo.id, fullRecord, value, type, domain); - return { domainId: domainInfo.id, name, value,res }; + return { domainId: domainInfo.id, name, value, res }; } async removeRecord(options: RemoveRecordOptions): Promise { const { fullRecord, value } = options.recordReq; const record = options.recordRes; - this.logger.info('删除域名解析:', fullRecord, value, record); + this.logger.info("删除域名解析:", fullRecord, value, record); if (record && record.domainId) { - const records = await this.access.getDnsRecords(record.domainId, 'TXT', record.name, record.value); + const records = await this.access.getDnsRecords(record.domainId, "TXT", record.name, record.value); if (records && records.rows && records.rows.length > 0) { const recordToDelete = records.rows[0]; await this.access.deleteDnsRecord(record.domainId, recordToDelete.RecordId); } } - this.logger.info('删除域名解析成功:', fullRecord, value); + this.logger.info("删除域名解析成功:", fullRecord, value); } async getDomainListPage(req: PageSearch): Promise> { diff --git a/packages/ui/certd-server/src/plugins/plugin-dnsmgr/index.ts b/packages/ui/certd-server/src/plugins/plugin-dnsmgr/index.ts index 35fce2541..58bdd1aa8 100644 --- a/packages/ui/certd-server/src/plugins/plugin-dnsmgr/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-dnsmgr/index.ts @@ -1,2 +1,2 @@ -export * from './access.js'; -export * from './dns-provider.js'; +export * from "./access.js"; +export * from "./dns-provider.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-doge/access.ts b/packages/ui/certd-server/src/plugins/plugin-doge/access.ts index ea8221131..68d37d733 100644 --- a/packages/ui/certd-server/src/plugins/plugin-doge/access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-doge/access.ts @@ -1,58 +1,55 @@ -import { IsAccess, AccessInput, BaseAccess } from '@certd/pipeline'; -import { DogeClient } from './lib/index.js'; +import { IsAccess, AccessInput, BaseAccess } from "@certd/pipeline"; +import { DogeClient } from "./lib/index.js"; /** * 这个注解将注册一个授权配置 * 在certd的后台管理系统中,用户可以选择添加此类型的授权 */ @IsAccess({ - name: 'dogecloud', - title: '多吉云', - desc: '', - icon: 'svg:icon-dogecloud', + name: "dogecloud", + title: "多吉云", + desc: "", + icon: "svg:icon-dogecloud", }) export class DogeCloudAccess extends BaseAccess { /** * 授权属性配置 */ @AccessInput({ - title: 'AccessKey', + title: "AccessKey", component: { - placeholder: 'AccessKey', + placeholder: "AccessKey", }, - helper: '请前往[多吉云-密钥管理](https://console.dogecloud.com/user/keys)获取', + helper: "请前往[多吉云-密钥管理](https://console.dogecloud.com/user/keys)获取", required: true, encrypt: false, }) - accessKey = ''; + accessKey = ""; @AccessInput({ - title: 'SecretKey', + title: "SecretKey", component: { - placeholder: 'SecretKey', + placeholder: "SecretKey", }, - helper: '请前往[多吉云-密钥管理](https://console.dogecloud.com/user/keys)获取', + helper: "请前往[多吉云-密钥管理](https://console.dogecloud.com/user/keys)获取", required: true, encrypt: true, }) - secretKey = ''; + secretKey = ""; @AccessInput({ title: "测试", component: { name: "api-test", - action: "TestRequest" + action: "TestRequest", }, - helper: "测试授权是否正确" + helper: "测试授权是否正确", }) testRequest = true; async onTestRequest() { const dogeClient = new DogeClient(this, this.ctx.http, this.ctx.logger); - await dogeClient.request( - '/cdn/domain/list.json', - {}, - ); + await dogeClient.request("/cdn/domain/list.json", {}); return "ok"; } } diff --git a/packages/ui/certd-server/src/plugins/plugin-doge/index.ts b/packages/ui/certd-server/src/plugins/plugin-doge/index.ts index 5bdf4efbf..9cd334bbd 100644 --- a/packages/ui/certd-server/src/plugins/plugin-doge/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-doge/index.ts @@ -1,3 +1,3 @@ -export * from './access.js'; -export * from './lib/index.js'; -export * from './plugins/index.js'; +export * from "./access.js"; +export * from "./lib/index.js"; +export * from "./plugins/index.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-doge/lib/index.ts b/packages/ui/certd-server/src/plugins/plugin-doge/lib/index.ts index 9c6ca471a..2dd3c3c0e 100644 --- a/packages/ui/certd-server/src/plugins/plugin-doge/lib/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-doge/lib/index.ts @@ -1,14 +1,14 @@ -import crypto from 'crypto'; -import querystring from 'querystring'; -import { DogeCloudAccess } from '../access.js'; -import { HttpClient, ILogger } from '@certd/basic'; +import crypto from "crypto"; +import querystring from "querystring"; +import { DogeCloudAccess } from "../access.js"; +import { HttpClient, ILogger } from "@certd/basic"; export class DogeClient { accessKey: string; secretKey: string; http: HttpClient; logger: ILogger; - constructor(access: DogeCloudAccess, http: HttpClient,logger: ILogger) { + constructor(access: DogeCloudAccess, http: HttpClient, logger: ILogger) { this.accessKey = access.accessKey; this.secretKey = access.secretKey; this.http = http; @@ -21,26 +21,26 @@ export class DogeClient { const body = jsonMode ? JSON.stringify(data) : querystring.encode(data); const sign = crypto - .createHmac('sha1', this.secretKey) - .update(Buffer.from(apiPath + '\n' + body, 'utf8')) - .digest('hex'); - const authorization = 'TOKEN ' + this.accessKey + ':' + sign; + .createHmac("sha1", this.secretKey) + .update(Buffer.from(apiPath + "\n" + body, "utf8")) + .digest("hex"); + const authorization = "TOKEN " + this.accessKey + ":" + sign; const res: any = await this.http.request({ - url: 'https://api.dogecloud.com' + apiPath, - method: 'POST', + url: "https://api.dogecloud.com" + apiPath, + method: "POST", data: body, - responseType: 'json', + responseType: "json", headers: { - 'Content-Type': jsonMode ? 'application/json' : 'application/x-www-form-urlencoded', + "Content-Type": jsonMode ? "application/json" : "application/x-www-form-urlencoded", Authorization: authorization, }, }); if (res.code == null && ignoreResNullCode) { //ignore - this.logger.warn('执行出错:', res); + this.logger.warn("执行出错:", res); } else if (res.code !== 200) { - throw new Error('API Error: ' + res.msg); + throw new Error("API Error: " + res.msg); } return res.data; } diff --git a/packages/ui/certd-server/src/plugins/plugin-doge/plugins/deploy-to-cdn/index.ts b/packages/ui/certd-server/src/plugins/plugin-doge/plugins/deploy-to-cdn/index.ts index 8759aca5a..97b9878a1 100644 --- a/packages/ui/certd-server/src/plugins/plugin-doge/plugins/deploy-to-cdn/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-doge/plugins/deploy-to-cdn/index.ts @@ -1,13 +1,13 @@ -import { AbstractTaskPlugin, IsTaskPlugin, PageSearch, pluginGroups, RunStrategy, TaskInput } from '@certd/pipeline'; -import { CertInfo } from '@certd/plugin-cert'; -import { DogeClient } from '../../lib/index.js'; -import dayjs from 'dayjs'; -import { CertApplyPluginNames } from '@certd/plugin-cert'; -import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from '@certd/plugin-lib'; +import { AbstractTaskPlugin, IsTaskPlugin, PageSearch, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; +import { CertInfo } from "@certd/plugin-cert"; +import { DogeClient } from "../../lib/index.js"; +import dayjs from "dayjs"; +import { CertApplyPluginNames } from "@certd/plugin-cert"; +import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from "@certd/plugin-lib"; @IsTaskPlugin({ - name: 'DogeCloudDeployToCDN', - title: '多吉云-部署到多吉云CDN', - icon: 'svg:icon-dogecloud', + name: "DogeCloudDeployToCDN", + title: "多吉云-部署到多吉云CDN", + icon: "svg:icon-dogecloud", group: pluginGroups.cdn.key, default: { strategy: { @@ -18,10 +18,10 @@ import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from export class DogeCloudDeployToCDNPlugin extends AbstractTaskPlugin { //证书选择,此项必须要有 @TaskInput({ - title: '证书', - helper: '请选择前置任务输出的域名证书', + title: "证书", + helper: "请选择前置任务输出的域名证书", component: { - name: 'output-selector', + name: "output-selector", from: [...CertApplyPluginNames], }, required: true, @@ -33,33 +33,35 @@ export class DogeCloudDeployToCDNPlugin extends AbstractTaskPlugin { //授权选择框 @TaskInput({ - title: '多吉云授权', - helper: '多吉云AccessKey', + title: "多吉云授权", + helper: "多吉云AccessKey", component: { - name: 'access-selector', - type: 'dogecloud', + name: "access-selector", + type: "dogecloud", }, - rules: [{ required: true, message: '此项必填' }], + rules: [{ required: true, message: "此项必填" }], }) accessId!: string; - @TaskInput(createRemoteSelectInputDefine({ - title: 'CDN域名', - helper: '请选择CDN域名,可以选择多个,一次性部署', - required: true, - action: DogeCloudDeployToCDNPlugin.prototype.onGetDomainList.name, - pager: false, - search: false - })) + @TaskInput( + createRemoteSelectInputDefine({ + title: "CDN域名", + helper: "请选择CDN域名,可以选择多个,一次性部署", + required: true, + action: DogeCloudDeployToCDNPlugin.prototype.onGetDomainList.name, + pager: false, + search: false, + }) + ) domain!: string | string[]; @TaskInput({ - title: '忽略部署接口报错', - helper: '当该域名部署后报错,但是实际上已经部署成功时,可以勾选', + title: "忽略部署接口报错", + helper: "当该域名部署后报错,但是实际上已经部署成功时,可以勾选", value: false, component: { - name: 'a-switch', - type: 'checked', + name: "a-switch", + type: "checked", }, }) ignoreDeployNullCode = false; @@ -73,13 +75,13 @@ export class DogeCloudDeployToCDNPlugin extends AbstractTaskPlugin { async execute(): Promise { const certId: number = await this.updateCert(); - let domains = this.domain - if (typeof domains === 'string'){ - domains = [domains] + let domains = this.domain; + if (typeof domains === "string") { + domains = [domains]; } for (const domain of domains) { this.ctx.logger.info(`绑定证书${certId}到域名${domain}`); - await this.bindCert(certId,domain); + await this.bindCert(certId, domain); } this.logger.info("执行完成,3秒后删除过期证书"); @@ -88,17 +90,17 @@ export class DogeCloudDeployToCDNPlugin extends AbstractTaskPlugin { } async updateCert() { - const data = await this.dogeClient.request('/cdn/cert/upload.json', { - note: 'certd-' + dayjs().format('YYYYMMDDHHmmss'), + const data = await this.dogeClient.request("/cdn/cert/upload.json", { + note: "certd-" + dayjs().format("YYYYMMDDHHmmss"), cert: this.cert.crt, private: this.cert.key, }); return data.id; } - async bindCert(certId: number,domain: string) { + async bindCert(certId: number, domain: string) { await this.dogeClient.request( - '/cdn/cert/bind.json', + "/cdn/cert/bind.json", { id: certId, domain: domain, @@ -108,34 +110,24 @@ export class DogeCloudDeployToCDNPlugin extends AbstractTaskPlugin { } async clearExpiredCert() { - const res = await this.dogeClient.request( - '/cdn/cert/list.json', - {}, - ); - const list = res.certs?.filter((item: any) => item.expire < dayjs().unix() && item.domainCount === 0) || []; + const res = await this.dogeClient.request("/cdn/cert/list.json", {}); + const list = res.certs?.filter((item: any) => item.expire < dayjs().unix() && item.domainCount === 0) || []; for (const item of list) { this.ctx.logger.info(`删除过期证书${item.id}->${item.domain}`); - try{ - await this.dogeClient.request( - '/cdn/cert/delete.json', - { - id: item.id, - }, - ); - }catch(err){ + try { + await this.dogeClient.request("/cdn/cert/delete.json", { + id: item.id, + }); + } catch (err) { this.ctx.logger.warn(`删除过期证书${item.id}->${item.domain}失败`, err); } } } - async onGetDomainList(data: PageSearch = {}) { - const res = await this.dogeClient.request( - '/cdn/domain/list.json', - {}, - ); + const res = await this.dogeClient.request("/cdn/domain/list.json", {}); - const list = res.domains + const list = res.domains; if (!list || list.length === 0) { throw new Error("没有找到CDN域名"); } @@ -144,7 +136,7 @@ export class DogeCloudDeployToCDNPlugin extends AbstractTaskPlugin { return { label: `${item.name}`, value: item.name, - domain: item.name + domain: item.name, }; }); return { diff --git a/packages/ui/certd-server/src/plugins/plugin-doge/plugins/index.ts b/packages/ui/certd-server/src/plugins/plugin-doge/plugins/index.ts index 71437bc96..8f2e3669d 100644 --- a/packages/ui/certd-server/src/plugins/plugin-doge/plugins/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-doge/plugins/index.ts @@ -1 +1 @@ -export * from './deploy-to-cdn/index.js'; +export * from "./deploy-to-cdn/index.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-dokploy/access.ts b/packages/ui/certd-server/src/plugins/plugin-dokploy/access.ts index 3a13131ad..42928f388 100644 --- a/packages/ui/certd-server/src/plugins/plugin-dokploy/access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-dokploy/access.ts @@ -8,10 +8,9 @@ import { CertInfo } from "@certd/plugin-cert"; name: "dokploy", title: "Dokploy授权", desc: "", - icon: "svg:icon-lucky" + icon: "svg:icon-lucky", }) export class DokployAccess extends BaseAccess { - @AccessInput({ title: "Dokploy地址", component: { @@ -19,12 +18,12 @@ export class DokployAccess extends BaseAccess { }, required: true, }) - endpoint = ''; + endpoint = ""; @AccessInput({ - title: 'ApiKey', + title: "ApiKey", component: { - placeholder: 'ApiKey', + placeholder: "ApiKey", }, // naAyXbZmxtsfrDfneOCeirbQNIICmBgfBiYXQwryPIUOdzPkXkfnaKjeAdbOQdwp //tlyvdNzojaFkNfGScALLmyuFHkHcYWaxoYjiDzWFHcnZAWdjOquMSqBwHLvGDGZK @@ -32,73 +31,71 @@ export class DokployAccess extends BaseAccess { required: true, encrypt: true, }) - apiKey = ''; - + apiKey = ""; @AccessInput({ title: "测试", component: { name: "api-test", - action: "TestRequest" + action: "TestRequest", }, - helper: "点击测试接口是否正常" + helper: "点击测试接口是否正常", }) testRequest = true; async onTestRequest() { await this.getCertList(); - return "ok" + return "ok"; } - async getServerList(){ + async getServerList() { const req = { - url :"/api/server.all", + url: "/api/server.all", method: "get", - } + }; return await this.doRequest(req); } - async getCertList(){ + async getCertList() { const req = { - url :"/api/certificates.all", + url: "/api/certificates.all", method: "get", - } + }; return await this.doRequest(req); } - async createCert(opts:{cert:CertInfo,serverId:string,name:string}){ + async createCert(opts: { cert: CertInfo; serverId: string; name: string }) { const req = { - url :"/api/certificates.create", + url: "/api/certificates.create", method: "post", - data:{ + data: { // certificateId:opts.certificateId, - "name": opts.name, - "certificateData": opts.cert.crt, - "privateKey": opts.cert.key, - "serverId": opts.serverId, + name: opts.name, + certificateData: opts.cert.crt, + privateKey: opts.cert.key, + serverId: opts.serverId, autoRenew: false, - organizationId : "" - } - } + organizationId: "", + }, + }; return await this.doRequest(req); } - - async removeCert (opts:{id:string}){ + async removeCert(opts: { id: string }) { const req = { - url :"/api/certificates.remove", + url: "/api/certificates.remove", method: "post", - data:{ - certificateId:opts.id, - } - } + data: { + certificateId: opts.id, + }, + }; return await this.doRequest(req); } - async doRequest(req: HttpRequestConfig){ + async doRequest(req: HttpRequestConfig) { const headers = { "x-api-key": this.apiKey, - ...req.headers + ...req.headers, }; return await this.ctx.http.request({ headers, @@ -107,9 +104,6 @@ export class DokployAccess extends BaseAccess { logRes: false, }); } - - } - new DokployAccess(); diff --git a/packages/ui/certd-server/src/plugins/plugin-dokploy/plugins/index.ts b/packages/ui/certd-server/src/plugins/plugin-dokploy/plugins/index.ts index 705339de6..a77684b4b 100644 --- a/packages/ui/certd-server/src/plugins/plugin-dokploy/plugins/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-dokploy/plugins/index.ts @@ -1 +1 @@ -import "./plugin-refresh-cert.js" +import "./plugin-refresh-cert.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-dokploy/plugins/plugin-refresh-cert.ts b/packages/ui/certd-server/src/plugins/plugin-dokploy/plugins/plugin-refresh-cert.ts index 000a3da9e..ace0400fa 100644 --- a/packages/ui/certd-server/src/plugins/plugin-dokploy/plugins/plugin-refresh-cert.ts +++ b/packages/ui/certd-server/src/plugins/plugin-dokploy/plugins/plugin-refresh-cert.ts @@ -1,7 +1,7 @@ import { AbstractTaskPlugin, IsTaskPlugin, PageSearch, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; -import {CertApplyPluginNames, CertInfo, CertReader} from "@certd/plugin-cert"; -import {createCertDomainGetterInputDefine, createRemoteSelectInputDefine} from "@certd/plugin-lib"; -import {DokployAccess} from "../access.js"; +import { CertApplyPluginNames, CertInfo, CertReader } from "@certd/plugin-cert"; +import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from "@certd/plugin-lib"; +import { DokployAccess } from "../access.js"; @IsTaskPlugin({ //命名规范,插件类型+功能(就是目录plugin-demo中的demo),大写字母开头,驼峰命名 @@ -15,9 +15,9 @@ import {DokployAccess} from "../access.js"; default: { //默认值配置照抄即可 strategy: { - runStrategy: RunStrategy.SkipWhenSucceed - } - } + runStrategy: RunStrategy.SkipWhenSucceed, + }, + }, }) //类名规范,跟上面插件名称(name)一致 export class DokployRefreshCert extends AbstractTaskPlugin { @@ -27,8 +27,8 @@ export class DokployRefreshCert extends AbstractTaskPlugin { helper: "请选择前置任务输出的域名证书", component: { name: "output-selector", - from: [...CertApplyPluginNames] - } + from: [...CertApplyPluginNames], + }, // required: true, // 必填 }) cert!: CertInfo; @@ -41,9 +41,9 @@ export class DokployRefreshCert extends AbstractTaskPlugin { title: "Dokploy授权", component: { name: "access-selector", - type: "dokploy" //固定授权类型 + type: "dokploy", //固定授权类型 }, - required: true //必填 + required: true, //必填 }) accessId!: string; // @@ -54,14 +54,13 @@ export class DokployRefreshCert extends AbstractTaskPlugin { helper: "要更新的证书名称,如果这里没有,请先给手动绑定一次证书", action: DokployRefreshCert.prototype.onGetServerList.name, pager: false, - search: false + search: false, }) ) serverList!: string[]; //插件实例化时执行的方法 - async onInstance() { - } + async onInstance() {} //插件执行方法 async execute(): Promise { @@ -75,11 +74,10 @@ export class DokployRefreshCert extends AbstractTaskPlugin { const oldCertList = await access.getCertList(); - const certReader = new CertReader(this.cert); for (const serverId of this.serverList) { this.logger.info(`----------- 开始部署server证书:${serverId}`); - if(!serverId){ + if (!serverId) { this.logger.error(`----------- serverId不能为空,跳过更新`); continue; } @@ -95,14 +93,13 @@ export class DokployRefreshCert extends AbstractTaskPlugin { await this.ctx.utils.sleep(10000); //清理过期证书 for (const certItem of oldCertList) { - const certDetail = CertReader.readCertDetail(certItem.certificateData); - if (certDetail.expires.getTime() < new Date().getTime()){ - this.logger.info(`----------- 证书${certItem.certificateId}已过期`); - await access.removeCert({id:certItem.certificateId}); - this.logger.info(`----------- 清理过期证书${certItem.certificateId}成功`); - }else{ - this.logger.info(`----------- 证书${certItem.certificateId}还未过期`); + if (certDetail.expires.getTime() < new Date().getTime()) { + this.logger.info(`----------- 证书${certItem.certificateId}已过期`); + await access.removeCert({ id: certItem.certificateId }); + this.logger.info(`----------- 清理过期证书${certItem.certificateId}成功`); + } else { + this.logger.info(`----------- 证书${certItem.certificateId}还未过期`); } } @@ -112,8 +109,8 @@ export class DokployRefreshCert extends AbstractTaskPlugin { async onGetServerList(data: PageSearch = {}) { const access = await this.getAccess(this.accessId); - const res = await access.getServerList() - const list = res + const res = await access.getServerList(); + const list = res; if (!list || list.length === 0) { throw new Error("没有找到Server,你可以直接手动输入serverId"); } diff --git a/packages/ui/certd-server/src/plugins/plugin-farcdn/access.ts b/packages/ui/certd-server/src/plugins/plugin-farcdn/access.ts index 99465aab8..50146ea20 100644 --- a/packages/ui/certd-server/src/plugins/plugin-farcdn/access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-farcdn/access.ts @@ -2,40 +2,38 @@ import { AccessInput, BaseAccess, IsAccess } from "@certd/pipeline"; import { HttpRequestConfig } from "@certd/basic"; import { CertInfo, CertReader } from "@certd/plugin-cert"; - /** */ @IsAccess({ name: "farcdn", title: "farcdn授权", desc: "", - icon: "svg:icon-lucky" + icon: "svg:icon-lucky", }) export class FarcdnAccess extends BaseAccess { @AccessInput({ title: "接口地址", - value:"https://open.farcdn.net/api/source", + value: "https://open.farcdn.net/api/source", component: { placeholder: "https://open.farcdn.net/api/source", name: "a-input", - vModel: "value" + vModel: "value", }, - required: true + required: true, }) endpoint!: string; - @AccessInput({ title: "accessKeyId", component: { placeholder: "accessKeyId", component: { name: "a-input", - vModel: "value" - } + vModel: "value", + }, }, encrypt: false, - required: true + required: true, }) accessKeyId!: string; @@ -45,49 +43,47 @@ export class FarcdnAccess extends BaseAccess { placeholder: "accessKey", component: { name: "a-input", - vModel: "value" - } + vModel: "value", + }, }, encrypt: true, - required: true + required: true, }) accessKey!: string; - @AccessInput({ title: "HttpProxy", component: { placeholder: "http://192.168.x.x:10811", component: { name: "a-input", - vModel: "value" - } + vModel: "value", + }, }, encrypt: false, - required: false + required: false, }) httpProxy!: string; - @AccessInput({ title: "测试", component: { name: "api-test", - action: "TestRequest" + action: "TestRequest", }, - helper: "点击测试接口是否正常" + helper: "点击测试接口是否正常", }) testRequest = true; async onTestRequest() { - await this.getSSLCertList({size:1}); - return "ok" + await this.getSSLCertList({ size: 1 }); + return "ok"; } - async getSSLCertList(req:{offset?:number,size?:number}){ + async getSSLCertList(req: { offset?: number; size?: number }) { return await this.doRequest({ url: "/getSSLCertList", - data: req + data: req, }); } @@ -115,18 +111,15 @@ export class FarcdnAccess extends BaseAccess { const params = { sslCertId, }; - const res= await this.doRequest({ + const res = await this.doRequest({ url: "/findSSLCertConfig", - data: params + data: params, }); this.ctx.logger.info(`找到证书${sslCertId}: name=${res.name},domain=${res.commonNames},dnsNames=${res.dnsNames}`); - return res + return res; } - async updateSSLCert(req:{ - sslCertId: number, - cert:CertInfo, - }){ + async updateSSLCert(req: { sslCertId: number; cert: CertInfo }) { /** * isOn boolean ✅ 是否启用证书 true * name string ✅ 证书显示名称 "example.com" @@ -141,9 +134,9 @@ export class FarcdnAccess extends BaseAccess { * commonNames string[] ✅ 证书的通用名称列表 ["example.com"] */ - const oldCert = await this.findSSLCertConfig(req.sslCertId) - const certReader = new CertReader(req.cert) - const {detail} = certReader.getCrtDetail(); + const oldCert = await this.findSSLCertConfig(req.sslCertId); + const certReader = new CertReader(req.cert); + const { detail } = certReader.getCrtDetail(); const params = { sslCertId: req.sslCertId, certData: req.cert.crt, @@ -155,28 +148,28 @@ export class FarcdnAccess extends BaseAccess { dnsNames: certReader.getAltNames(), timeBeginAt: detail.notBefore.getTime(), timeEndAt: detail.notAfter.getTime(), - name: oldCert.name|| certReader.buildCertName(), - description:oldCert.description||"" - } + name: oldCert.name || certReader.buildCertName(), + description: oldCert.description || "", + }; return await this.doRequest({ url: "/updateSSLCert", - data: params + data: params, }); } - async doRequest(req:HttpRequestConfig){ + async doRequest(req: HttpRequestConfig) { const params = { ...req.data, accessKeyId: this.accessKeyId, - accessKey: this.accessKey + accessKey: this.accessKey, }; - const res = await this.ctx.http.request({ + const res = await this.ctx.http.request({ url: req.url, - baseURL:this.endpoint, + baseURL: this.endpoint, method: "POST", data: params, - httpProxy: this.httpProxy||undefined, + httpProxy: this.httpProxy || undefined, }); if (res.code === 200) { @@ -186,6 +179,4 @@ export class FarcdnAccess extends BaseAccess { } } - - new FarcdnAccess(); diff --git a/packages/ui/certd-server/src/plugins/plugin-farcdn/plugins/plugin-refresh-cert.ts b/packages/ui/certd-server/src/plugins/plugin-farcdn/plugins/plugin-refresh-cert.ts index 7c509cf8f..eb0328c96 100644 --- a/packages/ui/certd-server/src/plugins/plugin-farcdn/plugins/plugin-refresh-cert.ts +++ b/packages/ui/certd-server/src/plugins/plugin-farcdn/plugins/plugin-refresh-cert.ts @@ -7,7 +7,7 @@ import { FarcdnAccess } from "../access.js"; //命名规范,插件类型+功能(就是目录plugin-demo中的demo),大写字母开头,驼峰命名 name: "FarcdnRefreshCert", title: "farcdn-更新证书", - desc:"www.farcdn.net", + desc: "www.farcdn.net", icon: "svg:icon-lucky", //插件分组 group: pluginGroups.cdn.key, @@ -15,9 +15,9 @@ import { FarcdnAccess } from "../access.js"; default: { //默认值配置照抄即可 strategy: { - runStrategy: RunStrategy.SkipWhenSucceed - } - } + runStrategy: RunStrategy.SkipWhenSucceed, + }, + }, }) //类名规范,跟上面插件名称(name)一致 export class FarcdnRefreshCert extends AbstractTaskPlugin { @@ -27,8 +27,8 @@ export class FarcdnRefreshCert extends AbstractTaskPlugin { helper: "请选择前置任务输出的域名证书", component: { name: "output-selector", - from: [...CertApplyPluginNames] - } + from: [...CertApplyPluginNames], + }, // required: true, // 必填 }) cert!: CertInfo; @@ -41,9 +41,9 @@ export class FarcdnRefreshCert extends AbstractTaskPlugin { title: "Farcdn授权", component: { name: "access-selector", - type: "farcdn" //固定授权类型 + type: "farcdn", //固定授权类型 }, - required: true //必填 + required: true, //必填 }) accessId!: string; // @@ -53,14 +53,13 @@ export class FarcdnRefreshCert extends AbstractTaskPlugin { title: "证书Id", helper: "要更新的Farcdn证书id", - action: FarcdnRefreshCert.prototype.onGetCertList.name + action: FarcdnRefreshCert.prototype.onGetCertList.name, }) ) certList!: number[]; //插件实例化时执行的方法 - async onInstance() { - } + async onInstance() {} //插件执行方法 async execute(): Promise { @@ -69,16 +68,16 @@ export class FarcdnRefreshCert extends AbstractTaskPlugin { for (const item of this.certList) { this.logger.info(`----------- 开始更新证书:${item}`); await access.updateSSLCert({ - sslCertId:item, + sslCertId: item, cert: this.cert, - }) + }); this.logger.info(`----------- 更新证书${item}成功`); } this.logger.info("部署完成"); } - async onGetCertList(data:PageSearch = {}) { + async onGetCertList(data: PageSearch = {}) { const access = await this.getAccess(this.accessId); const pager = new Pager(data); @@ -86,7 +85,7 @@ export class FarcdnRefreshCert extends AbstractTaskPlugin { offset: pager.getOffset(), size: pager.pageSize, }); - const list = res.list + const list = res.list; if (!list || list.length === 0) { throw new Error("没有找到证书,请先在控制台上传一次证书且关联网站"); } @@ -95,15 +94,15 @@ export class FarcdnRefreshCert extends AbstractTaskPlugin { return { label: `${item.name}<${item.id}>`, value: item.id, - domain: item.dnsNames + domain: item.dnsNames, }; }); return { - list:this.ctx.utils.options.buildGroupOptions(options, this.certDomains), - total:res.total, + list: this.ctx.utils.options.buildGroupOptions(options, this.certDomains), + total: res.total, pageNo: pager.pageNo, - pageSize: pager.pageSize - } + pageSize: pager.pageSize, + }; } } diff --git a/packages/ui/certd-server/src/plugins/plugin-flex/access.ts b/packages/ui/certd-server/src/plugins/plugin-flex/access.ts index 4bad301c9..d5ab3b453 100644 --- a/packages/ui/certd-server/src/plugins/plugin-flex/access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-flex/access.ts @@ -8,7 +8,7 @@ import { FlexCDNClient } from "./client.js"; name: "flexcdn", title: "FlexCDN授权", desc: "", - icon: "svg:icon-lucky" + icon: "svg:icon-lucky", }) export class FlexCDNAccess extends BaseAccess { @AccessInput({ @@ -16,9 +16,9 @@ export class FlexCDNAccess extends BaseAccess { component: { placeholder: "http://xxxxxxx:8080", name: "a-input", - vModel: "value" + vModel: "value", }, - required: true + required: true, }) endpoint!: string; @@ -31,15 +31,15 @@ export class FlexCDNAccess extends BaseAccess { options: [ { value: "user", - label: "普通用户" + label: "普通用户", }, { value: "admin", - label: "管理员" - } - ] + label: "管理员", + }, + ], }, - required: true + required: true, }) type!: string; @@ -49,11 +49,11 @@ export class FlexCDNAccess extends BaseAccess { placeholder: "accessKeyId", component: { name: "a-input", - vModel: "value" - } + vModel: "value", + }, }, encrypt: false, - required: true + required: true, }) accessKeyId!: string; @@ -63,11 +63,11 @@ export class FlexCDNAccess extends BaseAccess { placeholder: "accessKey", component: { name: "a-input", - vModel: "value" - } + vModel: "value", + }, }, encrypt: true, - required: true + required: true, }) accessKey!: string; @@ -75,7 +75,7 @@ export class FlexCDNAccess extends BaseAccess { title: "忽略证书校验", component: { name: "a-switch", - vModel: "checked" + vModel: "checked", }, encrypt: false, required: true, @@ -87,9 +87,9 @@ export class FlexCDNAccess extends BaseAccess { title: "测试", component: { name: "api-test", - action: "TestRequest" + action: "TestRequest", }, - helper: "点击测试接口看是否正常" + helper: "点击测试接口看是否正常", }) testRequest = true; @@ -98,7 +98,7 @@ export class FlexCDNAccess extends BaseAccess { const client = new FlexCDNClient({ logger: this.ctx.logger, http, - access: this + access: this, }); const token = await client.getToken(); if (token) { diff --git a/packages/ui/certd-server/src/plugins/plugin-flex/client.ts b/packages/ui/certd-server/src/plugins/plugin-flex/client.ts index 036158e51..c76044b92 100644 --- a/packages/ui/certd-server/src/plugins/plugin-flex/client.ts +++ b/packages/ui/certd-server/src/plugins/plugin-flex/client.ts @@ -14,7 +14,6 @@ export class FlexCDNClient { } async getToken() { - /* 步骤2:调用API获取AccessToken 接口地址 @@ -51,24 +50,23 @@ accessKeyId 和 accessKey 换成你在步骤1中创建的AccessKey对应的数 accessKey: this.access.accessKey, }, }); - this.token = res.token - return this.token + this.token = res.token; + return this.token; } async doRequest(req: HttpRequestConfig) { - const headers = { ...req.headers, - } - if(this.token){ - headers[ "X-Cloud-Access-Token"] = this.token + }; + if (this.token) { + headers["X-Cloud-Access-Token"] = this.token; } const res = await this.http.request({ ...req, headers, baseURL: this.access.endpoint, - logRes:false, - logParams:false, + logRes: false, + logParams: false, skipSslVerify: true, }); if (res.code === 200) { @@ -77,5 +75,4 @@ accessKeyId 和 accessKey 换成你在步骤1中创建的AccessKey对应的数 throw new Error(res.message); } } - } diff --git a/packages/ui/certd-server/src/plugins/plugin-flex/plugins/plugin-refresh-cert.ts b/packages/ui/certd-server/src/plugins/plugin-flex/plugins/plugin-refresh-cert.ts index 1feaf560e..5e775bdd2 100644 --- a/packages/ui/certd-server/src/plugins/plugin-flex/plugins/plugin-refresh-cert.ts +++ b/packages/ui/certd-server/src/plugins/plugin-flex/plugins/plugin-refresh-cert.ts @@ -1,5 +1,5 @@ import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; -import { CertApplyPluginNames, CertInfo,CertReader } from "@certd/plugin-cert"; +import { CertApplyPluginNames, CertInfo, CertReader } from "@certd/plugin-cert"; import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from "@certd/plugin-lib"; import { FlexCDNAccess } from "../access.js"; import { FlexCDNClient } from "../client.js"; @@ -15,9 +15,9 @@ import { FlexCDNClient } from "../client.js"; default: { //默认值配置照抄即可 strategy: { - runStrategy: RunStrategy.SkipWhenSucceed - } - } + runStrategy: RunStrategy.SkipWhenSucceed, + }, + }, }) //类名规范,跟上面插件名称(name)一致 export class FlexCDNRefreshCert extends AbstractTaskPlugin { @@ -27,8 +27,8 @@ export class FlexCDNRefreshCert extends AbstractTaskPlugin { helper: "请选择前置任务输出的域名证书", component: { name: "output-selector", - from: [...CertApplyPluginNames] - } + from: [...CertApplyPluginNames], + }, // required: true, // 必填 }) cert!: CertInfo; @@ -41,9 +41,9 @@ export class FlexCDNRefreshCert extends AbstractTaskPlugin { title: "FlexCDN授权", component: { name: "access-selector", - type: "flexcdn" //固定授权类型 + type: "flexcdn", //固定授权类型 }, - required: true //必填 + required: true, //必填 }) accessId!: string; // @@ -52,14 +52,13 @@ export class FlexCDNRefreshCert extends AbstractTaskPlugin { createRemoteSelectInputDefine({ title: "证书Id", helper: "要更新的Flex证书id", - action: FlexCDNRefreshCert.prototype.onGetCertList.name + action: FlexCDNRefreshCert.prototype.onGetCertList.name, }) ) certList!: number[]; //插件实例化时执行的方法 - async onInstance() { - } + async onInstance() {} //插件执行方法 async execute(): Promise { @@ -68,7 +67,7 @@ export class FlexCDNRefreshCert extends AbstractTaskPlugin { const client = new FlexCDNClient({ http: this.ctx.http, logger: this.logger, - access + access, }); await client.getToken(); for (const item of this.certList) { @@ -77,13 +76,13 @@ export class FlexCDNRefreshCert extends AbstractTaskPlugin { const res = await client.doRequest({ url: `/SSLCertService/findEnabledSSLCertConfig`, data: { - sslCertId: item - } + sslCertId: item, + }, }); - const sslCert = JSON.parse(this.ctx.utils.hash.base64Decode(res.sslCertJSON)) + const sslCert = JSON.parse(this.ctx.utils.hash.base64Decode(res.sslCertJSON)); this.logger.info(`证书信息:${sslCert.name},${sslCert.dnsNames}`); - const certReader = new CertReader(this.cert) + const certReader = new CertReader(this.cert); /** * commonNames: commonNames, * dnsNames: dnsNames, @@ -91,11 +90,11 @@ export class FlexCDNRefreshCert extends AbstractTaskPlugin { * timeEndAt: Math.floor((new Date(currentInfo.validTo)).getTime() / 1000), * */ - const topCrt = CertReader.readCertDetail(certReader.cert.ic) - const commonNames =[ topCrt.detail.issuer.commonName] - const dnsNames = certReader.getAllDomains() - const timeBeginAt = Math.floor(certReader.detail.notBefore.getTime() / 1000); - const timeEndAt = Math.floor(certReader.detail.notAfter.getTime() / 1000); + const topCrt = CertReader.readCertDetail(certReader.cert.ic); + const commonNames = [topCrt.detail.issuer.commonName]; + const dnsNames = certReader.getAllDomains(); + const timeBeginAt = Math.floor(certReader.detail.notBefore.getTime() / 1000); + const timeEndAt = Math.floor(certReader.detail.notAfter.getTime() / 1000); const body = { ...sslCert, // inherit old cert info like name and description commonNames, @@ -105,13 +104,13 @@ export class FlexCDNRefreshCert extends AbstractTaskPlugin { name: sslCert.name, sslCertId: item, certData: this.ctx.utils.hash.base64(this.cert.crt), - keyData: this.ctx.utils.hash.base64(this.cert.key) + keyData: this.ctx.utils.hash.base64(this.cert.key), }; await client.doRequest({ url: `/SSLCertService/updateSSLCert`, data: { - ...body - } + ...body, + }, }); this.logger.info(`----------- 更新证书${item}成功`); @@ -125,13 +124,13 @@ export class FlexCDNRefreshCert extends AbstractTaskPlugin { const client = new FlexCDNClient({ http: this.ctx.http, logger: this.logger, - access + access, }); await client.getToken(); const res = await client.doRequest({ url: "/SSLCertService/listSSLCerts", data: { size: 1000 }, - method: "POST" + method: "POST", }); const list = JSON.parse(this.ctx.utils.hash.base64Decode(res.sslCertsJSON)); if (!list || list.length === 0) { @@ -142,7 +141,7 @@ export class FlexCDNRefreshCert extends AbstractTaskPlugin { return { label: `${item.name}<${item.id}-${item.dnsNames?.[0]}>`, value: item.id, - domain: item.dnsNames + domain: item.dnsNames, }; }); return this.ctx.utils.options.buildGroupOptions(options, this.certDomains); diff --git a/packages/ui/certd-server/src/plugins/plugin-fnos/index.ts b/packages/ui/certd-server/src/plugins/plugin-fnos/index.ts index 8693be3ca..f1d7cca8c 100644 --- a/packages/ui/certd-server/src/plugins/plugin-fnos/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-fnos/index.ts @@ -1,9 +1,6 @@ import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; import { CertApplyPluginNames, CertInfo, CertReader } from "@certd/plugin-cert"; -import { - createCertDomainGetterInputDefine, - createRemoteSelectInputDefine, -} from "@certd/plugin-lib"; +import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from "@certd/plugin-lib"; import { SshAccess } from "../plugin-lib/ssh/ssh-access.js"; import { SshClient } from "../plugin-lib/ssh/ssh.js"; @@ -18,9 +15,9 @@ import { SshClient } from "../plugin-lib/ssh/ssh.js"; default: { //默认值配置照抄即可 strategy: { - runStrategy: RunStrategy.SkipWhenSucceed - } - } + runStrategy: RunStrategy.SkipWhenSucceed, + }, + }, }) //类名规范,跟上面插件名称(name)一致 export class FnOSDeployToNAS extends AbstractTaskPlugin { @@ -30,8 +27,8 @@ export class FnOSDeployToNAS extends AbstractTaskPlugin { helper: "请选择前置任务输出的域名证书", component: { name: "output-selector", - from: [...CertApplyPluginNames] - } + from: [...CertApplyPluginNames], + }, // required: true, // 必填 }) cert!: CertInfo; @@ -44,27 +41,24 @@ export class FnOSDeployToNAS extends AbstractTaskPlugin { title: "飞牛SSH授权", component: { name: "access-selector", - type: "ssh" //固定授权类型 + type: "ssh", //固定授权类型 }, - helper:"请先配置sudo免密:\nsudo visudo\n#在文件最后一行增加以下内容,需要将username替换成自己的用户名\nusername ALL=(ALL) NOPASSWD: NOPASSWD: ALL\nctrl+x 保存退出", - required: true //必填 + helper: "请先配置sudo免密:\nsudo visudo\n#在文件最后一行增加以下内容,需要将username替换成自己的用户名\nusername ALL=(ALL) NOPASSWD: NOPASSWD: ALL\nctrl+x 保存退出", + required: true, //必填 }) accessId!: string; - - @TaskInput( createRemoteSelectInputDefine({ title: "证书Id", helper: "面板证书请选择fnOS,其他FTP、webdav等证书请选择已使用,可多选(如果证书域名都匹配的话)", - action: FnOSDeployToNAS.prototype.onGetCertList.name + action: FnOSDeployToNAS.prototype.onGetCertList.name, }) ) certList!: number[]; //插件实例化时执行的方法 - async onInstance() { - } + async onInstance() {} //插件执行方法 async execute(): Promise { @@ -73,22 +67,22 @@ export class FnOSDeployToNAS extends AbstractTaskPlugin { const client = new SshClient(this.logger); //复制证书 - const list = await this.doGetCertList() + const list = await this.doGetCertList(); const certReader = new CertReader(this.cert); const expiresAt = certReader.expires; - const validFrom = certReader.detail.notBefore.getTime() + const validFrom = certReader.detail.notBefore.getTime(); for (const target of this.certList) { this.logger.info(`----------- 准备部署:${target}`); - let found = false + let found = false; for (const item of list) { if (item.sum === target) { - this.logger.info(`----------- 找到证书,开始部署:${item.sum},${item.domain}`) + this.logger.info(`----------- 找到证书,开始部署:${item.sum},${item.domain}`); const certPath = item.certificate; const keyPath = item.privateKey; const certDir = keyPath.substring(0, keyPath.lastIndexOf("/")); - const fullchainPath = certDir+ "/fullchain.crt" - const caPath = certDir+ "/issuer_certificate.crt" + const fullchainPath = certDir + "/fullchain.crt"; + const caPath = certDir + "/issuer_certificate.crt"; const cmd = ` sudo tee ${certPath} > /dev/null <<'EOF' ${this.cert.crt} @@ -107,16 +101,16 @@ sudo chmod 0755 "${certDir}/" -R sudo -u postgres psql -d trim_connect -c "UPDATE cert SET valid_to=${expiresAt},valid_from=${validFrom} WHERE private_key='${item.privateKey}'" -` +`; const res = await client.exec({ - connectConf: access, - script: cmd - }); - if (res.indexOf("Permission denied") > -1){ - this.logger.error("权限不足,请先配置 sudo 免密") + connectConf: access, + script: cmd, + }); + if (res.indexOf("Permission denied") > -1) { + this.logger.error("权限不足,请先配置 sudo 免密"); } - found = true - break + found = true; + break; } } if (!found) { @@ -124,60 +118,57 @@ sudo -u postgres psql -d trim_connect -c "UPDATE cert SET valid_to=${expiresAt} } } - this.logger.info("证书已上传,准备重启..."); - - const restartCmd= ` + const restartCmd = ` echo "正在重启相关服务..." sudo systemctl restart webdav.service sudo systemctl restart smbftpd.service sudo systemctl restart trim_nginx.service echo "服务重启完成!" -` +`; await client.exec({ connectConf: access, - script: restartCmd + script: restartCmd, }); this.logger.info("部署完成"); } - async doGetCertList(){ + async doGetCertList() { const access: SshAccess = await this.getAccess(this.accessId); const client = new SshClient(this.logger); /** * :/usr/trim/etc$ cat network_cert_all.conf | jq . */ - const sslListCmd = "cat /usr/trim/etc/network_cert_all.conf | jq ." + const sslListCmd = "cat /usr/trim/etc/network_cert_all.conf | jq ."; - const res:string = await client.exec({ + const res: string = await client.exec({ connectConf: access, - script: sslListCmd + script: sslListCmd, }); - let list = [] - try{ - list = JSON.parse(res.trim()) - }catch (e){ - throw new Error(`证书列表解析失败:${res}`) + let list = []; + try { + list = JSON.parse(res.trim()); + } catch (e) { + throw new Error(`证书列表解析失败:${res}`); } if (!list || list.length === 0) { throw new Error("没有找到证书,请先在证书管理页面上传一次证书"); } - return list + return list; } async onGetCertList() { - - const list = await this.doGetCertList() + const list = await this.doGetCertList(); const options = list.map((item: any) => { return { - label: `${item.domain}<${item.used?'已使用':"未使用"}-${item.sum}>`, + label: `${item.domain}<${item.used ? "已使用" : "未使用"}-${item.sum}>`, value: item.sum, - domain: item.san + domain: item.san, }; }); return this.ctx.utils.options.buildGroupOptions(options, this.certDomains); diff --git a/packages/ui/certd-server/src/plugins/plugin-gcore/access.ts b/packages/ui/certd-server/src/plugins/plugin-gcore/access.ts index 9a8c76128..65db62cba 100644 --- a/packages/ui/certd-server/src/plugins/plugin-gcore/access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-gcore/access.ts @@ -1,53 +1,51 @@ -import { AccessInput, BaseAccess, IsAccess } from '@certd/pipeline'; +import { AccessInput, BaseAccess, IsAccess } from "@certd/pipeline"; @IsAccess({ - name: 'Gcore', - title: 'Gcore', - desc: 'Gcore', - icon: 'clarity:plugin-line', + name: "Gcore", + title: "Gcore", + desc: "Gcore", + icon: "clarity:plugin-line", }) export class GcoreAccess extends BaseAccess { @AccessInput({ - title: 'username', + title: "username", component: { - placeholder: 'username', + placeholder: "username", }, required: true, }) - username = ''; + username = ""; @AccessInput({ - title: 'password', + title: "password", component: { - placeholder: 'password', + placeholder: "password", }, required: true, encrypt: true, }) - password = ''; + password = ""; @AccessInput({ - title: 'totp key', + title: "totp key", component: { - placeholder: 'totp key', + placeholder: "totp key", }, encrypt: true, }) - otpkey = ''; - - + otpkey = ""; @AccessInput({ title: "测试", component: { name: "api-test", - action: "TestRequest" + action: "TestRequest", }, - helper: "点击测试接口是否正常" + helper: "点击测试接口是否正常", }) testRequest = true; async onTestRequest() { await this.login(); - return "ok" + return "ok"; } async login() { @@ -55,10 +53,10 @@ export class GcoreAccess extends BaseAccess { if (this.otpkey) { const response = await this.ctx.http.request({ url: `https://cn-api.my-api.cn/api/totp/?key=${this.otpkey}`, - method: 'get', + method: "get", }); otp = response; - this.ctx.logger.info('获取到otp:', otp); + this.ctx.logger.info("获取到otp:", otp); } const loginResponse = await this.doRequestApi(`/iam/auth/jwt/login`, { username: this.username, @@ -66,14 +64,14 @@ export class GcoreAccess extends BaseAccess { ...(otp && { otp }), }); const token = loginResponse.access; - this.ctx.logger.info('Token 获取成功'); + this.ctx.logger.info("Token 获取成功"); return token; } - async doRequestApi(url: string, data: any = null, method = 'post', token: string | null = null) { - const baseApi = 'https://api.gcore.com'; + async doRequestApi(url: string, data: any = null, method = "post", token: string | null = null) { + const baseApi = "https://api.gcore.com"; const headers = { - 'Content-Type': 'application/json', + "Content-Type": "application/json", ...(token ? { authorization: `Bearer ${token}` } : {}), }; const res = await this.ctx.http.request({ diff --git a/packages/ui/certd-server/src/plugins/plugin-gcore/index.ts b/packages/ui/certd-server/src/plugins/plugin-gcore/index.ts index fdad254fb..02dc3945d 100644 --- a/packages/ui/certd-server/src/plugins/plugin-gcore/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-gcore/index.ts @@ -1,2 +1,2 @@ -export * from './plugins/index.js'; -export * from './access.js'; +export * from "./plugins/index.js"; +export * from "./access.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-gcore/plugins/index.ts b/packages/ui/certd-server/src/plugins/plugin-gcore/plugins/index.ts index aae7f9dde..ed3617617 100644 --- a/packages/ui/certd-server/src/plugins/plugin-gcore/plugins/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-gcore/plugins/index.ts @@ -1,2 +1,2 @@ -export * from './plugin-upload.js'; -export * from './plugin-flush.js'; +export * from "./plugin-upload.js"; +export * from "./plugin-flush.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-gcore/plugins/plugin-flush.ts b/packages/ui/certd-server/src/plugins/plugin-gcore/plugins/plugin-flush.ts index ec759fb82..9b98e0c47 100644 --- a/packages/ui/certd-server/src/plugins/plugin-gcore/plugins/plugin-flush.ts +++ b/packages/ui/certd-server/src/plugins/plugin-gcore/plugins/plugin-flush.ts @@ -1,12 +1,12 @@ -import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from '@certd/pipeline'; -import { CertInfo } from '@certd/plugin-cert'; -import { GcoreAccess } from '../access.js'; -import { CertApplyPluginNames} from '@certd/plugin-cert'; +import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; +import { CertInfo } from "@certd/plugin-cert"; +import { GcoreAccess } from "../access.js"; +import { CertApplyPluginNames } from "@certd/plugin-cert"; @IsTaskPlugin({ - name: 'Gcoreflush', - title: 'Gcore-刷新Gcore证书', - desc: '刷新现有的证书', - icon: 'clarity:plugin-line', + name: "Gcoreflush", + title: "Gcore-刷新Gcore证书", + desc: "刷新现有的证书", + icon: "clarity:plugin-line", group: pluginGroups.cdn.key, default: { strategy: { @@ -16,43 +16,43 @@ import { CertApplyPluginNames} from '@certd/plugin-cert'; }) export class GcoreflushPlugin extends AbstractTaskPlugin { @TaskInput({ - title: '证书名称', - helper: '可以修改也可以和现在的保留一致', + title: "证书名称", + helper: "可以修改也可以和现在的保留一致", }) certName!: string; @TaskInput({ - title: '证书ID', - required:true, + title: "证书ID", + required: true, }) ssl_id!: string; @TaskInput({ - title: '域名证书', - helper: '请选择前置任务输出的域名证书', + title: "域名证书", + helper: "请选择前置任务输出的域名证书", component: { - name: 'output-selector', + name: "output-selector", from: [...CertApplyPluginNames], }, required: true, }) cert!: CertInfo; @TaskInput({ - title: 'Access授权', - helper: 'Gcore', + title: "Access授权", + helper: "Gcore", component: { - name: 'access-selector', - type: 'Gcore', + name: "access-selector", + type: "Gcore", }, required: true, }) accessId!: string; - private readonly baseApi = 'https://api.gcore.com'; + private readonly baseApi = "https://api.gcore.com"; async onInstance() {} - private async doRequestApi(url: string, data: any = null, method = 'post', token: string | null = null) { + private async doRequestApi(url: string, data: any = null, method = "post", token: string | null = null) { const headers = { - 'Content-Type': 'application/json', + "Content-Type": "application/json", ...(token ? { authorization: `Bearer ${token}` } : {}), }; const res = await this.http.request({ @@ -68,18 +68,18 @@ export class GcoreflushPlugin extends AbstractTaskPlugin { async execute(): Promise { const { cert, accessId } = this; - if(!this.ssl_id){ - throw new Error('请填写要刷新的证书ID'); + if (!this.ssl_id) { + throw new Error("请填写要刷新的证书ID"); } const access = (await this.getAccess(accessId)) as GcoreAccess; let otp = null; if (access.otpkey) { const response = await this.http.request({ url: `https://cn-api.my-api.cn/api/totp/?key=${access.otpkey}`, - method: 'get', + method: "get", }); otp = response; - this.logger.info('获取到otp:', otp); + this.logger.info("获取到otp:", otp); } const loginResponse = await this.doRequestApi(`${this.baseApi}/iam/auth/jwt/login`, { username: access.username, @@ -87,8 +87,8 @@ export class GcoreflushPlugin extends AbstractTaskPlugin { ...(otp && { otp }), }); const token = loginResponse.access; - this.logger.info('Token 获取成功'); - this.logger.info('开始上传证书'); + this.logger.info("Token 获取成功"); + this.logger.info("开始上传证书"); await this.doRequestApi( `${this.baseApi}/cdn/sslData/${this.ssl_id}`, { @@ -97,10 +97,10 @@ export class GcoreflushPlugin extends AbstractTaskPlugin { sslPrivateKey: cert.key, validate_root_ca: true, }, - 'put', + "put", token ); - this.logger.info('证书部署成功'); + this.logger.info("证书部署成功"); } } diff --git a/packages/ui/certd-server/src/plugins/plugin-gcore/plugins/plugin-upload.ts b/packages/ui/certd-server/src/plugins/plugin-gcore/plugins/plugin-upload.ts index 54211c351..1ebb598ef 100644 --- a/packages/ui/certd-server/src/plugins/plugin-gcore/plugins/plugin-upload.ts +++ b/packages/ui/certd-server/src/plugins/plugin-gcore/plugins/plugin-upload.ts @@ -1,12 +1,12 @@ -import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from '@certd/pipeline'; -import { CertInfo } from '@certd/plugin-cert'; -import { GcoreAccess } from '../access.js'; -import { CertApplyPluginNames} from '@certd/plugin-cert'; +import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; +import { CertInfo } from "@certd/plugin-cert"; +import { GcoreAccess } from "../access.js"; +import { CertApplyPluginNames } from "@certd/plugin-cert"; @IsTaskPlugin({ - name: 'Gcoreupload', - title: 'Gcore-部署证书到Gcore', - desc: '仅上传 并不会部署到cdn', - icon: 'clarity:plugin-line', + name: "Gcoreupload", + title: "Gcore-部署证书到Gcore", + desc: "仅上传 并不会部署到cdn", + icon: "clarity:plugin-line", group: pluginGroups.cdn.key, default: { strategy: { @@ -16,27 +16,27 @@ import { CertApplyPluginNames} from '@certd/plugin-cert'; }) export class GcoreuploadPlugin extends AbstractTaskPlugin { @TaskInput({ - title: '证书名称', - helper: '作为备注', + title: "证书名称", + helper: "作为备注", }) certName!: string; @TaskInput({ - title: '域名证书', - helper: '请选择前置任务输出的域名证书', + title: "域名证书", + helper: "请选择前置任务输出的域名证书", component: { - name: 'output-selector', + name: "output-selector", from: [...CertApplyPluginNames], }, required: true, }) cert!: CertInfo; @TaskInput({ - title: 'Access授权', - helper: 'Gcore', + title: "Access授权", + helper: "Gcore", component: { - name: 'access-selector', - type: 'Gcore', + name: "access-selector", + type: "Gcore", }, required: true, }) @@ -44,15 +44,13 @@ export class GcoreuploadPlugin extends AbstractTaskPlugin { async onInstance() {} - - async execute(): Promise { const { cert, accessId } = this; const access = (await this.getAccess(accessId)) as GcoreAccess; - + const token = await access.login(); - this.logger.info('Token 获取成功'); - this.logger.info('开始上传证书'); + this.logger.info("Token 获取成功"); + this.logger.info("开始上传证书"); await access.doRequestApi( `/cdn/sslData`, { @@ -61,10 +59,10 @@ export class GcoreuploadPlugin extends AbstractTaskPlugin { sslPrivateKey: cert.key, validate_root_ca: true, }, - 'post', + "post", token ); - this.logger.info('证书上传成功'); + this.logger.info("证书上传成功"); } } diff --git a/packages/ui/certd-server/src/plugins/plugin-github/access.ts b/packages/ui/certd-server/src/plugins/plugin-github/access.ts index 823675756..aa940f679 100644 --- a/packages/ui/certd-server/src/plugins/plugin-github/access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-github/access.ts @@ -1,29 +1,27 @@ import { AccessInput, BaseAccess, IsAccess } from "@certd/pipeline"; import { HttpRequestConfig } from "@certd/basic"; - /** */ @IsAccess({ name: "github", title: "Github授权", desc: "", - icon: "ion:logo-github" + icon: "ion:logo-github", }) export class GithubAccess extends BaseAccess { - @AccessInput({ title: "接口地址", component: { placeholder: "可以使用反向代理地址", component: { name: "a-input", - vModel: "value" - } + vModel: "value", + }, }, - helper:"默认值:https://api.github.com", + helper: "默认值:https://api.github.com", encrypt: false, - required: false + required: false, }) endpoint!: string; @@ -33,12 +31,12 @@ export class GithubAccess extends BaseAccess { placeholder: "GithubToken", component: { name: "a-input", - vModel: "value" - } + vModel: "value", + }, }, - helper:"支持匿名访问的接口可以不填", + helper: "支持匿名访问的接口可以不填", encrypt: true, - required: false + required: false, }) githubToken!: string; @@ -48,41 +46,39 @@ export class GithubAccess extends BaseAccess { placeholder: "http://192.168.x.x:10811", component: { name: "a-input", - vModel: "value" - } + vModel: "value", + }, }, encrypt: false, - required: false + required: false, }) httpProxy!: string; - @AccessInput({ title: "测试", component: { name: "api-test", - action: "TestRequest" + action: "TestRequest", }, - helper: "点击测试接口是否正常" + helper: "点击测试接口是否正常", }) testRequest = true; async onTestRequest() { - await this.getRelease({repoName:"certd/certd"}) - return "ok" + await this.getRelease({ repoName: "certd/certd" }); + return "ok"; } - async getRelease(req:{repoName:string}){ - const url = `/repos/${req.repoName}/releases/latest`; - return await this.doRequest({ - url, - method: "GET", - data:{} - }); + async getRelease(req: { repoName: string }) { + const url = `/repos/${req.repoName}/releases/latest`; + return await this.doRequest({ + url, + method: "GET", + data: {}, + }); } - - async doRequest(req:HttpRequestConfig){ + async doRequest(req: HttpRequestConfig) { /** * async function getLatestRelease() { * const { REPO_OWNER, REPO_NAME, API_URL, TOKEN } = CONFIG.GITHUB; @@ -113,18 +109,18 @@ export class GithubAccess extends BaseAccess { * } */ - const headers:any = {} - if(this.githubToken){ - headers.Authorization = `token ${this.githubToken}` + const headers: any = {}; + if (this.githubToken) { + headers.Authorization = `token ${this.githubToken}`; } - const baseURL= this.endpoint || "https://api.github.com"; - const res = await this.ctx.http.request({ + const baseURL = this.endpoint || "https://api.github.com"; + const res = await this.ctx.http.request({ url: req.url, baseURL, method: req.method || "POST", data: req.data, headers, - httpProxy: this.httpProxy||undefined, + httpProxy: this.httpProxy || undefined, }); if (res) { @@ -134,6 +130,4 @@ export class GithubAccess extends BaseAccess { } } - - new GithubAccess(); diff --git a/packages/ui/certd-server/src/plugins/plugin-github/plugins/plugin-check-release.ts b/packages/ui/certd-server/src/plugins/plugin-github/plugins/plugin-check-release.ts index 660fa6ccb..aac6788ce 100644 --- a/packages/ui/certd-server/src/plugins/plugin-github/plugins/plugin-check-release.ts +++ b/packages/ui/certd-server/src/plugins/plugin-github/plugins/plugin-check-release.ts @@ -6,7 +6,7 @@ import { SshClient } from "../../plugin-lib/ssh/ssh.js"; //命名规范,插件类型+功能(就是目录plugin-demo中的demo),大写字母开头,驼峰命名 name: "GithubCheckRelease", title: "Github-检查Release版本", - desc:"检查最新Release版本并推送消息", + desc: "检查最新Release版本并推送消息", icon: "ion:logo-github", //插件分组 group: pluginGroups.other.key, @@ -14,9 +14,9 @@ import { SshClient } from "../../plugin-lib/ssh/ssh.js"; default: { //默认值配置照抄即可 strategy: { - runStrategy: RunStrategy.AlwaysRun - } - } + runStrategy: RunStrategy.AlwaysRun, + }, + }, }) //类名规范,跟上面插件名称(name)一致 export class GithubCheckRelease extends AbstractTaskPlugin { @@ -25,29 +25,28 @@ export class GithubCheckRelease extends AbstractTaskPlugin { title: "Github授权", component: { name: "access-selector", - type: "github" //固定授权类型 + type: "github", //固定授权类型 }, - required: true //必填 + required: true, //必填 }) accessId!: string; - @TaskInput({ title: "仓库名称", - helper:"owner/name,比如 certd/certd", - required:true, + helper: "owner/name,比如 certd/certd", + required: true, }) repoName!: string; @TaskInput({ title: "通知渠道", - component:{ - name:"notification-selector", - select:{ - mode:"tags" - } + component: { + name: "notification-selector", + select: { + mode: "tags", + }, }, - required:false, + required: false, }) notificationIds!: number[]; @@ -56,23 +55,22 @@ export class GithubCheckRelease extends AbstractTaskPlugin { }) lastVersion?: string; - @TaskInput({ - title: '主机登录配置', - helper: '登录', + title: "主机登录配置", + helper: "登录", component: { - name: 'access-selector', - type: 'ssh', + name: "access-selector", + type: "ssh", }, required: false, }) sshAccessId!: string; @TaskInput({ - title: 'shell脚本命令', + title: "shell脚本命令", component: { - name: 'a-textarea', - vModel: 'value', + name: "a-textarea", + vModel: "value", rows: 6, placeholder: ` # 拉取最新镜像 @@ -93,68 +91,63 @@ nohup sh -c '$RESTART_CERT' >/dev/null 2>&1 & echo '10秒后重启' && exit }) script!: string; - //插件实例化时执行的方法 - async onInstance() { - } + async onInstance() {} //插件执行方法 async execute(): Promise { const access = await this.getAccess(this.accessId); - const res = await access.getRelease({repoName:this.repoName}) - if(res == null){ - throw new Error(`获取${this.repoName}最新版本失败`) + const res = await access.getRelease({ repoName: this.repoName }); + if (res == null) { + throw new Error(`获取${this.repoName}最新版本失败`); } const lastVersion = this.ctx.lastStatus?.status?.output?.lastVersion; - if(res.tag_name == null || res.tag_name ==lastVersion){ + if (res.tag_name == null || res.tag_name == lastVersion) { this.logger.info(`暂无更新,${res.tag_name}`); this.lastVersion = res.tag_name || lastVersion; - return "skip" + return "skip"; } //有更新 - this.logger.info(`有更新,${lastVersion??"0"}->${res.tag_name}`) + this.logger.info(`有更新,${lastVersion ?? "0"}->${res.tag_name}`); this.lastVersion = res.tag_name; // const body = res.body.replaceAll("* ","- ") //仅每行开头的* 替换成 -, *号前面可以有空格 - const body = res.body.replace(/^(\s*)\* /gm, "$1- ") + const body = res.body.replace(/^(\s*)\* /gm, "$1- "); - if (this.notificationIds && this.notificationIds.length > 0){ + if (this.notificationIds && this.notificationIds.length > 0) { //发送通知 for (const notificationId of this.notificationIds) { await this.ctx.notificationService.send({ id: notificationId, useDefault: false, - useEmail:false, + useEmail: false, logger: this.logger, body: { title: `${this.repoName} 新版本 ${this.lastVersion} 发布`, content: `${body}\n\n > [Certd](https://certd.docmirror.cn),不止证书自动化,插件解锁无限可能!\n\n`, url: `https://github.com/${this.repoName}/releases/tag/${this.lastVersion}`, notificationType: "githubReleaseCheck", - } - }) + }, + }); } } - if (this.script != null && this.script.trim() != "") { const connectConf = await this.getAccess(this.sshAccessId); const sshClient = new SshClient(this.logger); - const scripts = this.script.split('\n'); + const scripts = this.script.split("\n"); await sshClient.exec({ connectConf, script: scripts, env: { REPO: this.repoName, LAST_VERSION: this.lastVersion, - } + }, }); } - } - } new GithubCheckRelease(); diff --git a/packages/ui/certd-server/src/plugins/plugin-godaddy/access.ts b/packages/ui/certd-server/src/plugins/plugin-godaddy/access.ts index 2e8e63046..c3f91471f 100644 --- a/packages/ui/certd-server/src/plugins/plugin-godaddy/access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-godaddy/access.ts @@ -1,84 +1,81 @@ -import {AccessInput, BaseAccess, IsAccess, Pager, PageSearch} from '@certd/pipeline'; -import {HttpRequestConfig} from "@certd/basic"; +import { AccessInput, BaseAccess, IsAccess, Pager, PageSearch } from "@certd/pipeline"; +import { HttpRequestConfig } from "@certd/basic"; /** * 这个注解将注册一个授权配置 * 在certd的后台管理系统中,用户可以选择添加此类型的授权 */ @IsAccess({ - name: 'godaddy', - title: 'godaddy授权', - icon: 'simple-icons:godaddy', - desc: '', + name: "godaddy", + title: "godaddy授权", + icon: "simple-icons:godaddy", + desc: "", }) export class GodaddyAccess extends BaseAccess { /** * 授权属性配置 */ @AccessInput({ - title: 'Key', + title: "Key", component: { - placeholder: '授权key', + placeholder: "授权key", }, - helper:"[https://developer.godaddy.com/keys](https://developer.godaddy.com/keys),创建key(选择product,不要选择ote)", + helper: "[https://developer.godaddy.com/keys](https://developer.godaddy.com/keys),创建key(选择product,不要选择ote)", required: true, encrypt: false, }) - key = ''; + key = ""; @AccessInput({ - title: 'Secret', + title: "Secret", component: { - name:"a-input-password", - vModel:"value", + name: "a-input-password", + vModel: "value", }, required: true, encrypt: true, }) - secret = ''; + secret = ""; @AccessInput({ - title: 'HTTP代理', + title: "HTTP代理", component: { - placeholder: 'http://xxxxx:xx', + placeholder: "http://xxxxx:xx", }, - helper: '使用https_proxy', + helper: "使用https_proxy", required: false, }) - httpProxy = ''; + httpProxy = ""; @AccessInput({ title: "测试", component: { name: "api-test", - action: "TestRequest" + action: "TestRequest", }, - helper: "点击测试接口是否正常(注意账号中必须要有50个域名才能使用API接口)" + helper: "点击测试接口是否正常(注意账号中必须要有50个域名才能使用API接口)", }) testRequest = true; async onTestRequest() { - const res = await this.getDomainList({pageSize:1}); - this.ctx.logger.info(res) - return "ok" + const res = await this.getDomainList({ pageSize: 1 }); + this.ctx.logger.info(res); + return "ok"; } - - async getDomainList(opts?: PageSearch){ - + async getDomainList(opts?: PageSearch) { const pager = new Pager(opts); const req = { - url :`/v1/domains?limit=${pager.pageSize}&offset=${pager.getOffset()}`, + url: `/v1/domains?limit=${pager.pageSize}&offset=${pager.getOffset()}`, method: "get", - } + }; return await this.doRequest(req); } - - async doRequest(req: HttpRequestConfig){ + async doRequest(req: HttpRequestConfig) { const headers = { - "Authorization": `sso-key ${this.key}:${this.secret}`, - ...req.headers + Authorization: `sso-key ${this.key}:${this.secret}`, + ...req.headers, }; return await this.ctx.http.request({ headers, @@ -88,9 +85,6 @@ export class GodaddyAccess extends BaseAccess { httpProxy: this.httpProxy, }); } - - - } new GodaddyAccess(); diff --git a/packages/ui/certd-server/src/plugins/plugin-godaddy/dns-provider.ts b/packages/ui/certd-server/src/plugins/plugin-godaddy/dns-provider.ts index 5aee4d06a..b3e82524e 100644 --- a/packages/ui/certd-server/src/plugins/plugin-godaddy/dns-provider.ts +++ b/packages/ui/certd-server/src/plugins/plugin-godaddy/dns-provider.ts @@ -4,21 +4,21 @@ import { GodaddyAccess } from "./access.js"; import { Pager, PageRes, PageSearch } from "@certd/pipeline"; export type GodaddyRecord = { - domain: string, - type: string, - name: string, - data: string, + domain: string; + type: string; + name: string; + data: string; }; // 这里通过IsDnsProvider注册一个dnsProvider @IsDnsProvider({ - name: 'godaddy', - title: 'godaddy', - desc: 'GoDaddy', - icon: 'simple-icons:godaddy', + name: "godaddy", + title: "godaddy", + desc: "GoDaddy", + icon: "simple-icons:godaddy", // 这里是对应的 cloudflare的access类型名称 - accessType: 'godaddy', - order:10, + accessType: "godaddy", + order: 10, }) export class GodaddyDnsProvider extends AbstractDnsProvider { access!: GodaddyAccess; @@ -39,32 +39,30 @@ export class GodaddyDnsProvider extends AbstractDnsProvider { * domain: 'example.com' * hostRecord: _acme-challenge.test */ - const { fullRecord,hostRecord, value, type, domain } = options; - this.logger.info('添加域名解析:', fullRecord, value, type, domain); - + const { fullRecord, hostRecord, value, type, domain } = options; + this.logger.info("添加域名解析:", fullRecord, value, type, domain); const res = await this.access.doRequest({ - method: 'PATCH', - url: '/v1/domains/'+domain+'/records', + method: "PATCH", + url: "/v1/domains/" + domain + "/records", data: [ { - type: 'TXT', + type: "TXT", name: hostRecord, data: value, ttl: 600, - } - ] - }) - this.logger.info('添加域名解析成功:', res); + }, + ], + }); + this.logger.info("添加域名解析成功:", res); return { domain: domain, - type: 'TXT', + type: "TXT", name: hostRecord, data: value, }; } - /** * 删除dns解析记录,清理申请痕迹 * @param options @@ -72,31 +70,31 @@ export class GodaddyDnsProvider extends AbstractDnsProvider { async removeRecord(options: RemoveRecordOptions): Promise { const { fullRecord, value } = options.recordReq; const record = options.recordRes; - this.logger.info('删除域名解析:', fullRecord, value); + this.logger.info("删除域名解析:", fullRecord, value); if (!record) { - this.logger.info('record为空,不执行删除'); + this.logger.info("record为空,不执行删除"); return; } //这里调用删除txt dns解析记录接口 - const {name,type,domain} = record + const { name, type, domain } = record; const res = await this.access.doRequest({ - method: 'DELETE', - url: '/v1/domains/'+domain+`/records/${type}/${name}`, - }) + method: "DELETE", + url: "/v1/domains/" + domain + `/records/${type}/${name}`, + }); this.logger.info(`删除域名解析成功:fullRecord=${fullRecord},id=${res}`); } async getDomainListPage(req: PageSearch): Promise> { const pager = new Pager(req); - - const ret = await this.access.getDomainList(req) - let list = ret.zones || [] + const ret = await this.access.getDomainList(req); + + let list = ret.zones || []; list = list.map((item: any) => ({ id: item.domainId, domain: item.domain, })); - const total = list.length === pager.pageSize ? list.length+1: list.length + const total = list.length === pager.pageSize ? list.length + 1 : list.length; return { total, list, diff --git a/packages/ui/certd-server/src/plugins/plugin-godaddy/index.ts b/packages/ui/certd-server/src/plugins/plugin-godaddy/index.ts index db899c717..d0bc76d38 100644 --- a/packages/ui/certd-server/src/plugins/plugin-godaddy/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-godaddy/index.ts @@ -1,2 +1,2 @@ -export * from './dns-provider.js'; -export * from './access.js'; +export * from "./dns-provider.js"; +export * from "./access.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-goedge/access.ts b/packages/ui/certd-server/src/plugins/plugin-goedge/access.ts index 02056759e..2eaf42bd5 100644 --- a/packages/ui/certd-server/src/plugins/plugin-goedge/access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-goedge/access.ts @@ -3,26 +3,24 @@ import { HttpRequestConfig } from "@certd/basic"; import { CertInfo, CertReader } from "@certd/plugin-cert"; import dayjs from "dayjs"; - /** */ @IsAccess({ name: "goedge", title: "GoEdge授权", icon: "fa-solid:leaf:#6C6BF6", - order: 100 + order: 100, }) export class GoEdgeAccess extends BaseAccess { - @AccessInput({ title: "系统地址", component: { name: "a-input", - vModel: "value" + vModel: "value", }, helper: "例如:http://yourdomain.com:8002, 需要在API节点配置中开启HTTP访问地址", encrypt: false, - required: true + required: true, }) endpoint!: string; @@ -34,16 +32,16 @@ export class GoEdgeAccess extends BaseAccess { options: [ { label: "用户", - value: "user" + value: "user", }, { label: "管理员", - value: "admin" - } - ] + value: "admin", + }, + ], }, encrypt: false, - required: true + required: true, }) userType!: string; @@ -53,10 +51,10 @@ export class GoEdgeAccess extends BaseAccess { 管理员AccessKey:在”系统用户-用户-详情-AccessKey” 中创建。`, component: { name: "a-input", - vModel: "value" + vModel: "value", }, encrypt: false, - required: true + required: true, }) accessKeyId!: string; @@ -64,30 +62,28 @@ export class GoEdgeAccess extends BaseAccess { title: "accessKey", component: { name: "a-input", - vModel: "value" + vModel: "value", }, encrypt: true, - required: true + required: true, }) accessKey!: string; - - @AccessInput({ title: "测试", component: { name: "api-test", - action: "TestRequest" + action: "TestRequest", }, - helper: "点击测试接口是否正常" + helper: "点击测试接口是否正常", }) testRequest = true; - accessToken: { expiresAt: number, token: string } + accessToken: { expiresAt: number; token: string }; async onTestRequest() { await this.getCertList({ pageSize: 1 }); - return "ok" + return "ok"; } /** @@ -115,14 +111,14 @@ export class GoEdgeAccess extends BaseAccess { "ocspError": "" * @returns */ - async getCertList(req: { pageNo?: number, pageSize?: number, query?: string, onlyUser?: boolean, userId?: number }) { + async getCertList(req: { pageNo?: number; pageSize?: number; query?: string; onlyUser?: boolean; userId?: number }) { const pageNo = req.pageNo ?? 1; const pageSize = req.pageSize ?? 20; const body: any = { keyword: req.query ?? "", offset: (pageNo - 1) * pageSize, size: pageSize, - } + }; if (req.onlyUser) { body["onlyUser"] = true; } @@ -133,14 +129,14 @@ export class GoEdgeAccess extends BaseAccess { const countRes = await this.doRequest({ url: `/SSLCertService/countSSLCerts`, method: "POST", - data: body + data: body, }); const total = countRes.count || 9999; const res = await this.doRequest({ url: `/SSLCertService/listSSLCerts`, method: "POST", - data: body + data: body, }); // this.ctx.logger.info("getCertList",JSON.stringify(res)); const sslCertsJSON = this.ctx.utils.hash.base64Decode(res.sslCertsJSON) || "[]"; @@ -149,20 +145,19 @@ export class GoEdgeAccess extends BaseAccess { total: total, list: sslCerts || [], pageNo: pageNo, - pageSize: pageSize - } + pageSize: pageSize, + }; } - async doCertReplace(req: { certId: number, cert: CertInfo }) { - - let sslCert:any = {} + async doCertReplace(req: { certId: number; cert: CertInfo }) { + let sslCert: any = {}; try { const res = await this.doRequest({ url: `/SSLCertService/findEnabledSSLCertConfig`, method: "POST", data: { sslCertId: req.certId, - } + }, }); const sslCertJSON = this.ctx.utils.hash.base64Decode(res.sslCertJSON) || "{}"; sslCert = JSON.parse(sslCertJSON); @@ -171,7 +166,7 @@ export class GoEdgeAccess extends BaseAccess { } const certReader = new CertReader(req.cert); - const dnsNames = certReader.getAllDomains() + const dnsNames = certReader.getAllDomains(); // /product/sslcenter/{id} return await this.doRequest({ @@ -206,12 +201,10 @@ export class GoEdgeAccess extends BaseAccess { []string dnsNames; []string commonNames; */ - } + }, }); - } - async getToken() { // /APIAccessTokenService/getAPIAccessToken if (this.accessToken && this.accessToken.expiresAt > dayjs().unix()) { @@ -223,17 +216,16 @@ export class GoEdgeAccess extends BaseAccess { method: "POST", data: { type: this.userType, - "accessKeyId": this.accessKeyId, - "accessKey": this.accessKey, - } + accessKeyId: this.accessKeyId, + accessKey: this.accessKey, + }, }); this.accessToken = res; return res; } async doRequest(req: HttpRequestConfig) { - - const headers: Record = {} + const headers: Record = {}; if (!req.url.endsWith("/getAPIAccessToken")) { if (!this.accessToken || this.accessToken.expiresAt < dayjs().unix()) { await this.getToken(); @@ -252,7 +244,7 @@ export class GoEdgeAccess extends BaseAccess { params: req.params, headers: { ...headers, - ...req.headers + ...req.headers, }, // httpProxy: this.httpProxy||undefined, }); @@ -264,6 +256,4 @@ export class GoEdgeAccess extends BaseAccess { } } - - new GoEdgeAccess(); diff --git a/packages/ui/certd-server/src/plugins/plugin-goedge/plugins/index.ts b/packages/ui/certd-server/src/plugins/plugin-goedge/plugins/index.ts index 3ce4f30c7..b8237e4f8 100644 --- a/packages/ui/certd-server/src/plugins/plugin-goedge/plugins/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-goedge/plugins/index.ts @@ -1 +1 @@ -export * from './plugin-refresh-cert.js' +export * from "./plugin-refresh-cert.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-goedge/plugins/plugin-refresh-cert.ts b/packages/ui/certd-server/src/plugins/plugin-goedge/plugins/plugin-refresh-cert.ts index 90e250c01..299eb22ab 100644 --- a/packages/ui/certd-server/src/plugins/plugin-goedge/plugins/plugin-refresh-cert.ts +++ b/packages/ui/certd-server/src/plugins/plugin-goedge/plugins/plugin-refresh-cert.ts @@ -15,9 +15,9 @@ import { GoEdgeAccess } from "../access.js"; default: { //默认值配置照抄即可 strategy: { - runStrategy: RunStrategy.SkipWhenSucceed - } - } + runStrategy: RunStrategy.SkipWhenSucceed, + }, + }, }) //类名规范,跟上面插件名称(name)一致 export class GoEdgeRefreshCert extends AbstractTaskPlugin { @@ -27,8 +27,8 @@ export class GoEdgeRefreshCert extends AbstractTaskPlugin { helper: "请选择前置任务输出的域名证书", component: { name: "output-selector", - from: [...CertApplyPluginNames] - } + from: [...CertApplyPluginNames], + }, // required: true, // 必填 }) cert!: CertInfo; @@ -36,28 +36,26 @@ export class GoEdgeRefreshCert extends AbstractTaskPlugin { @TaskInput(createCertDomainGetterInputDefine({ props: { required: false } })) certDomains!: string[]; - //授权选择框 @TaskInput({ title: "GoEdge授权", component: { name: "access-selector", - type: "goedge" //固定授权类型 + type: "goedge", //固定授权类型 }, - required: true //必填 + required: true, //必填 }) accessId!: string; // - @TaskInput({ title: "用户id", component: { name: "a-input-number", - vModel: "value" + vModel: "value", }, - helper:"用于查询用户证书,点击用户详情->浏览器地址中userId值,如:/users/user?userId=1\n如果为空,则查询管理员证书", - required: false //必填 + helper: "用于查询用户证书,点击用户详情->浏览器地址中userId值,如:/users/user?userId=1\n如果为空,则查询管理员证书", + required: false, //必填 }) userId!: number; @@ -65,16 +63,15 @@ export class GoEdgeRefreshCert extends AbstractTaskPlugin { createRemoteSelectInputDefine({ title: "证书Id", helper: "要更新的GoEdge证书id", - pager:true, - search:true, - action: GoEdgeRefreshCert.prototype.onGetCertList.name + pager: true, + search: true, + action: GoEdgeRefreshCert.prototype.onGetCertList.name, }) ) certList!: number[]; //插件实例化时执行的方法 - async onInstance() { - } + async onInstance() {} //插件执行方法 async execute(): Promise { @@ -84,7 +81,7 @@ export class GoEdgeRefreshCert extends AbstractTaskPlugin { this.logger.info(`----------- 开始更新证书:${item}`); await access.doCertReplace({ certId: item, - cert: this.cert + cert: this.cert, }); this.logger.info(`----------- 更新证书${item}成功`); } @@ -102,7 +99,7 @@ export class GoEdgeRefreshCert extends AbstractTaskPlugin { pageSize, query: req.searchKey, userId: this.userId, - onlyUser: this.userId !== undefined + onlyUser: this.userId !== undefined, }); const total = res.total; const list = res.list; @@ -115,14 +112,14 @@ export class GoEdgeRefreshCert extends AbstractTaskPlugin { label: `${item.name}<${item.id}>`, value: item.id, domain: item.dnsNames || [], - title: item.dnsNames?.join(",") || "" + title: item.dnsNames?.join(",") || "", }; }); return { list: this.ctx.utils.options.buildGroupOptions(options, this.certDomains), total: total, pageNo: pageNo, - pageSize: pageSize + pageSize: pageSize, }; } } diff --git a/packages/ui/certd-server/src/plugins/plugin-google/dns-provider.ts b/packages/ui/certd-server/src/plugins/plugin-google/dns-provider.ts index af197b5c8..032a2b188 100644 --- a/packages/ui/certd-server/src/plugins/plugin-google/dns-provider.ts +++ b/packages/ui/certd-server/src/plugins/plugin-google/dns-provider.ts @@ -1,11 +1,5 @@ import { Pager, PageRes, PageSearch } from "@certd/pipeline"; -import { - AbstractDnsProvider, - CreateRecordOptions, - DomainRecord, - IsDnsProvider, - RemoveRecordOptions, -} from "@certd/plugin-cert"; +import { AbstractDnsProvider, CreateRecordOptions, DomainRecord, IsDnsProvider, RemoveRecordOptions } from "@certd/plugin-cert"; import { GoogleAccess } from "../plugin-cert/access/index.js"; // TODO: 接口待明确 - 需要确认Google Cloud DNS API的具体参数和返回值格式 @@ -31,7 +25,7 @@ export class GoogleCloudDnsProvider extends AbstractDnsProvider - this.valuesEqual(existing, value) - ); + const valueExists = existingRrdatas.some((existing: string) => this.valuesEqual(existing, value)); if (valueExists) { this.logger.info("Google Cloud DNS: 值已存在,无需重复添加", fullRecord, value); @@ -206,9 +198,7 @@ export class GoogleCloudDnsProvider extends AbstractDnsProvider - this.valuesEqual(existing, value) - ); + const valueIndex = currentRrdatas.findIndex((existing: string) => this.valuesEqual(existing, value)); if (valueIndex === -1) { this.logger.info("Google Cloud DNS: 要删除的值不存在", fullRecord, value); @@ -262,9 +252,7 @@ export class GoogleCloudDnsProvider extends AbstractDnsProvider - item.domain.toLowerCase().includes(req.searchKey.toLowerCase()) - ); + filteredList = list.filter(item => item.domain.toLowerCase().includes(req.searchKey.toLowerCase())); } return { diff --git a/packages/ui/certd-server/src/plugins/plugin-hipmdnsmgr/access/hipmdnsmgr-access.ts b/packages/ui/certd-server/src/plugins/plugin-hipmdnsmgr/access/hipmdnsmgr-access.ts index 573f570be..a1f53859c 100644 --- a/packages/ui/certd-server/src/plugins/plugin-hipmdnsmgr/access/hipmdnsmgr-access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-hipmdnsmgr/access/hipmdnsmgr-access.ts @@ -1,49 +1,49 @@ -import { AccessInput, BaseAccess, IsAccess } from '@certd/pipeline'; +import { AccessInput, BaseAccess, IsAccess } from "@certd/pipeline"; /** * HiPM DNSMgr Access * 使用 API Token 认证(Bearer Token) */ @IsAccess({ - name: 'hipmdnsmgr', - title: 'HiPM DNSMgr', - icon: 'svg:icon-dns', - desc: 'HiPM DNSMgr API Token 授权', + name: "hipmdnsmgr", + title: "HiPM DNSMgr", + icon: "svg:icon-dns", + desc: "HiPM DNSMgr API Token 授权", }) export class HipmDnsmgrAccess extends BaseAccess { @AccessInput({ - title: '服务器地址', + title: "服务器地址", component: { - name: 'a-input', + name: "a-input", allowClear: true, - placeholder: 'http://localhost:3001', + placeholder: "http://localhost:3001", }, required: true, - helper: 'HiPM DNSMgr 服务器地址,例如: http://localhost:3001', + helper: "HiPM DNSMgr 服务器地址,例如: http://localhost:3001", }) - endpoint = ''; + endpoint = ""; @AccessInput({ - title: 'API Token', + title: "API Token", required: true, encrypt: true, - helper: '在 DNSMgr 设置 > API Token 中创建的令牌', + helper: "在 DNSMgr 设置 > API Token 中创建的令牌", }) - apiToken = ''; + apiToken = ""; @AccessInput({ - title: '测试连接', + title: "测试连接", component: { - name: 'api-test', - action: 'TestRequest', + name: "api-test", + action: "TestRequest", }, - helper: '点击测试接口是否正常', + helper: "点击测试接口是否正常", }) testRequest = true; async onTestRequest() { await this.getDomainList(); - return '连接成功'; + return "连接成功"; } /** @@ -51,10 +51,10 @@ export class HipmDnsmgrAccess extends BaseAccess { */ async getDomainList() { this.ctx.logger.info(`[HiPM DNSMgr] 获取域名列表`); - + const resp = await this.doRequest({ - method: 'GET', - path: '/domains', + method: "GET", + path: "/domains", params: { page: 1, pageSize: 100, @@ -62,11 +62,13 @@ export class HipmDnsmgrAccess extends BaseAccess { }); // DNSMgr 返回数组格式 - return resp?.map((item: any) => ({ - id: String(item.id), - domain: item.name, - ...item, - })) || []; + return ( + resp?.map((item: any) => ({ + id: String(item.id), + domain: item.name, + ...item, + })) || [] + ); } /** @@ -74,14 +76,14 @@ export class HipmDnsmgrAccess extends BaseAccess { */ async getDomainRecords(domainId: string, params?: { type?: string; subdomain?: string; value?: string }) { this.ctx.logger.info(`[HiPM DNSMgr] 获取域名记录列表:domainId=${domainId}`); - + let path = `/domains/${domainId}/records?page=1&pageSize=100`; if (params?.type) path += `&type=${encodeURIComponent(params.type)}`; if (params?.subdomain) path += `&subdomain=${encodeURIComponent(params.subdomain)}`; if (params?.value) path += `&value=${encodeURIComponent(params.value)}`; const resp = await this.doRequest({ - method: 'GET', + method: "GET", path, }); @@ -93,16 +95,16 @@ export class HipmDnsmgrAccess extends BaseAccess { */ async createDnsRecord(domainId: string, name: string, value: string, type: string) { this.ctx.logger.info(`[HiPM DNSMgr] 创建DNS记录:${name} ${type} ${value}`); - + const resp = await this.doRequest({ - method: 'POST', + method: "POST", path: `/domains/${domainId}/records`, data: { name, type, value, ttl: 600, - line: '0', + line: "0", }, }); @@ -114,9 +116,9 @@ export class HipmDnsmgrAccess extends BaseAccess { */ async deleteDnsRecord(domainId: string, recordId: string) { this.ctx.logger.info(`[HiPM DNSMgr] 删除DNS记录:domainId=${domainId}, recordId=${recordId}`); - + const resp = await this.doRequest({ - method: 'DELETE', + method: "DELETE", path: `/domains/${domainId}/records/${recordId}`, }); @@ -129,16 +131,16 @@ export class HipmDnsmgrAccess extends BaseAccess { async doRequest(req: { method: string; path: string; data?: any; params?: any }) { // 处理 URL let baseUrl = this.endpoint.trim(); - baseUrl = baseUrl.replace(/\/$/, ''); - baseUrl = baseUrl.replace(/\/api$/, ''); - + baseUrl = baseUrl.replace(/\/$/, ""); + baseUrl = baseUrl.replace(/\/api$/, ""); + let url = `${baseUrl}/api${req.path}`; - + // 添加查询参数 if (req.params) { const searchParams = new URLSearchParams(); for (const [key, value] of Object.entries(req.params)) { - if (value !== undefined && value !== null && value !== '') { + if (value !== undefined && value !== null && value !== "") { searchParams.append(key, String(value)); } } @@ -154,8 +156,8 @@ export class HipmDnsmgrAccess extends BaseAccess { url, method: req.method, headers: { - 'Content-Type': 'application/json', - 'Authorization': `Bearer ${this.apiToken}`, + "Content-Type": "application/json", + Authorization: `Bearer ${this.apiToken}`, }, data: req.data, }); @@ -164,7 +166,7 @@ export class HipmDnsmgrAccess extends BaseAccess { // DNSMgr API 返回格式: { code: 0, data: ..., msg: ... } if (res.code !== undefined && res.code !== 0) { - throw new Error(res.msg || '请求失败'); + throw new Error(res.msg || "请求失败"); } return res.data; diff --git a/packages/ui/certd-server/src/plugins/plugin-hipmdnsmgr/access/index.ts b/packages/ui/certd-server/src/plugins/plugin-hipmdnsmgr/access/index.ts index 2ef8fb7fb..290761c45 100644 --- a/packages/ui/certd-server/src/plugins/plugin-hipmdnsmgr/access/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-hipmdnsmgr/access/index.ts @@ -1 +1 @@ -export * from './hipmdnsmgr-access.js'; +export * from "./hipmdnsmgr-access.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-hipmdnsmgr/dns-provider/hipmdnsmgr-dns-provider.ts b/packages/ui/certd-server/src/plugins/plugin-hipmdnsmgr/dns-provider/hipmdnsmgr-dns-provider.ts index 6a6c79135..a04057ff8 100644 --- a/packages/ui/certd-server/src/plugins/plugin-hipmdnsmgr/dns-provider/hipmdnsmgr-dns-provider.ts +++ b/packages/ui/certd-server/src/plugins/plugin-hipmdnsmgr/dns-provider/hipmdnsmgr-dns-provider.ts @@ -1,23 +1,23 @@ -import { AbstractDnsProvider, CreateRecordOptions, IsDnsProvider, RemoveRecordOptions } from '@certd/plugin-cert'; -import { HipmDnsmgrAccess } from '../access/hipmdnsmgr-access.js'; +import { AbstractDnsProvider, CreateRecordOptions, IsDnsProvider, RemoveRecordOptions } from "@certd/plugin-cert"; +import { HipmDnsmgrAccess } from "../access/hipmdnsmgr-access.js"; /** * HiPM DNSMgr DNS Provider * 用于 ACME DNS-01 挑战验证 */ @IsDnsProvider({ - name: 'hipmdnsmgr', - title: 'HiPM DNSMgr', - desc: 'HiPM DNSMgr DNS 解析提供商', - accessType: 'hipmdnsmgr', - icon: 'svg:icon-dns', + name: "hipmdnsmgr", + title: "HiPM DNSMgr", + desc: "HiPM DNSMgr DNS 解析提供商", + accessType: "hipmdnsmgr", + icon: "svg:icon-dns", }) export class HipmDnsmgrDnsProvider extends AbstractDnsProvider<{ domainId: string; recordId: string; name: string; value: string }> { access!: HipmDnsmgrAccess; async onInstance() { this.access = this.ctx.access as HipmDnsmgrAccess; - this.logger.debug('[HiPM DNSMgr] 初始化完成'); + this.logger.debug("[HiPM DNSMgr] 初始化完成"); } /** @@ -25,7 +25,7 @@ export class HipmDnsmgrDnsProvider extends AbstractDnsProvider<{ domainId: strin */ async createRecord(options: CreateRecordOptions): Promise { const { fullRecord, hostRecord, value, type, domain } = options; - this.logger.info('[HiPM DNSMgr] 添加域名解析:', fullRecord, value, type, domain); + this.logger.info("[HiPM DNSMgr] 添加域名解析:", fullRecord, value, type, domain); // 1. 获取域名列表,找到对应的域名 ID const domainList = await this.access.getDomainList(); @@ -36,13 +36,13 @@ export class HipmDnsmgrDnsProvider extends AbstractDnsProvider<{ domainId: strin } const domainId = String(domainInfo.id); - this.logger.debug('[HiPM DNSMgr] 找到域名:', domain, 'ID:', domainId); + this.logger.debug("[HiPM DNSMgr] 找到域名:", domain, "ID:", domainId); // 2. 创建 DNS 记录 const name = hostRecord; // 使用子域名,如 _acme-challenge const res = await this.access.createDnsRecord(domainId, name, value, type); - - this.logger.info('[HiPM DNSMgr] 添加域名解析成功:', JSON.stringify(options), res?.id); + + this.logger.info("[HiPM DNSMgr] 添加域名解析成功:", JSON.stringify(options), res?.id); // 返回记录信息,用于后续删除 return { @@ -60,18 +60,18 @@ export class HipmDnsmgrDnsProvider extends AbstractDnsProvider<{ domainId: strin const { fullRecord, value } = options.recordReq; const record = options.recordRes; - this.logger.info('[HiPM DNSMgr] 删除域名解析:', fullRecord, value, record); + this.logger.info("[HiPM DNSMgr] 删除域名解析:", fullRecord, value, record); if (record && record.domainId && record.recordId) { try { await this.access.deleteDnsRecord(record.domainId, record.recordId); - this.logger.info('[HiPM DNSMgr] 删除域名解析成功:', fullRecord, value); + this.logger.info("[HiPM DNSMgr] 删除域名解析成功:", fullRecord, value); } catch (e: any) { // 记录可能已经被删除,忽略错误 - this.logger.warn('[HiPM DNSMgr] 删除域名解析失败(可能已不存在):', e.message); + this.logger.warn("[HiPM DNSMgr] 删除域名解析失败(可能已不存在):", e.message); } } else { - this.logger.warn('[HiPM DNSMgr] 无法删除记录,缺少 domainId 或 recordId'); + this.logger.warn("[HiPM DNSMgr] 无法删除记录,缺少 domainId 或 recordId"); } } } diff --git a/packages/ui/certd-server/src/plugins/plugin-hipmdnsmgr/dns-provider/index.ts b/packages/ui/certd-server/src/plugins/plugin-hipmdnsmgr/dns-provider/index.ts index 9282058db..5c86e47c2 100644 --- a/packages/ui/certd-server/src/plugins/plugin-hipmdnsmgr/dns-provider/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-hipmdnsmgr/dns-provider/index.ts @@ -1 +1 @@ -export * from './hipmdnsmgr-dns-provider.js'; +export * from "./hipmdnsmgr-dns-provider.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-hipmdnsmgr/index.ts b/packages/ui/certd-server/src/plugins/plugin-hipmdnsmgr/index.ts index e5dd343ce..303992b02 100644 --- a/packages/ui/certd-server/src/plugins/plugin-hipmdnsmgr/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-hipmdnsmgr/index.ts @@ -1,2 +1,2 @@ -export * from './access/index.js'; -export * from './dns-provider/index.js'; +export * from "./access/index.js"; +export * from "./dns-provider/index.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-host/index.ts b/packages/ui/certd-server/src/plugins/plugin-host/index.ts index 640fdbe36..f3e504d6c 100644 --- a/packages/ui/certd-server/src/plugins/plugin-host/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-host/index.ts @@ -1 +1 @@ -export * from './plugin/index.js'; +export * from "./plugin/index.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-host/plugin/copy-to-local/index.ts b/packages/ui/certd-server/src/plugins/plugin-host/plugin/copy-to-local/index.ts index cbd6fa884..734e92e4c 100644 --- a/packages/ui/certd-server/src/plugins/plugin-host/plugin/copy-to-local/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-host/plugin/copy-to-local/index.ts @@ -1,14 +1,14 @@ -import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput, TaskOutput } from '@certd/pipeline'; -import { CertInfo, CertReader } from '@certd/plugin-cert'; -import * as fs from 'fs'; -import path from 'path'; -import { CertApplyPluginNames} from '@certd/plugin-cert'; -const dataDir = "./data" +import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput, TaskOutput } from "@certd/pipeline"; +import { CertInfo, CertReader } from "@certd/plugin-cert"; +import * as fs from "fs"; +import path from "path"; +import { CertApplyPluginNames } from "@certd/plugin-cert"; +const dataDir = "./data"; @IsTaskPlugin({ - name: 'CopyToLocal', - title: '主机-复制到本机', - icon: 'solar:copy-bold-duotone', - desc: '【仅管理员使用】实际上是复制证书到docker容器内的某个路径,需要做目录映射到宿主机', + name: "CopyToLocal", + title: "主机-复制到本机", + icon: "solar:copy-bold-duotone", + desc: "【仅管理员使用】实际上是复制证书到docker容器内的某个路径,需要做目录映射到宿主机", group: pluginGroups.host.key, default: { strategy: { @@ -18,10 +18,10 @@ const dataDir = "./data" }) export class CopyCertToLocalPlugin extends AbstractTaskPlugin { @TaskInput({ - title: '域名证书', - helper: '请选择前置任务输出的域名证书', + title: "域名证书", + helper: "请选择前置任务输出的域名证书", component: { - name: 'output-selector', + name: "output-selector", from: [...CertApplyPluginNames], }, required: true, @@ -29,15 +29,15 @@ export class CopyCertToLocalPlugin extends AbstractTaskPlugin { cert!: CertInfo; @TaskInput({ - title: '证书类型', - helper: '要部署的证书格式,支持pem、pfx、der、jks格式', + title: "证书类型", + helper: "要部署的证书格式,支持pem、pfx、der、jks格式", component: { - name: 'a-select', + name: "a-select", options: [ - { value: 'pem', label: 'pem(crt),用于Nginx等大部分应用' }, - { value: 'pfx', label: 'pfx,一般用于IIS' }, - { value: 'der', label: 'der,一般用于Apache' }, - { value: 'jks', label: 'jks,一般用于JAVA应用' }, + { value: "pem", label: "pem(crt),用于Nginx等大部分应用" }, + { value: "pfx", label: "pfx,一般用于IIS" }, + { value: "der", label: "der,一般用于Apache" }, + { value: "jks", label: "jks,一般用于JAVA应用" }, ], }, required: true, @@ -45,10 +45,10 @@ export class CopyCertToLocalPlugin extends AbstractTaskPlugin { certType!: string; @TaskInput({ - title: '证书保存路径', - helper: '全链证书,路径要包含文件名' + '\n推荐使用相对路径,将写入与数据库同级目录,无需映射,例如:tmp/cert.pem', + title: "证书保存路径", + helper: "全链证书,路径要包含文件名" + "\n推荐使用相对路径,将写入与数据库同级目录,无需映射,例如:tmp/cert.pem", component: { - placeholder: 'tmp/full_chain.pem', + placeholder: "tmp/full_chain.pem", }, mergeScript: ` return { @@ -58,14 +58,14 @@ export class CopyCertToLocalPlugin extends AbstractTaskPlugin { } `, required: true, - rules: [{ type: 'filepath' }], + rules: [{ type: "filepath" }], }) crtPath!: string; @TaskInput({ - title: '私钥保存路径', - helper: '路径要包含文件名\n推荐使用相对路径,将写入与数据库同级目录,无需映射,例如:tmp/cert.key', + title: "私钥保存路径", + helper: "路径要包含文件名\n推荐使用相对路径,将写入与数据库同级目录,无需映射,例如:tmp/cert.key", component: { - placeholder: 'tmp/cert.key', + placeholder: "tmp/cert.key", }, mergeScript: ` return { @@ -75,15 +75,15 @@ export class CopyCertToLocalPlugin extends AbstractTaskPlugin { } `, required: true, - rules: [{ type: 'filepath' }], + rules: [{ type: "filepath" }], }) keyPath!: string; @TaskInput({ - title: '中间证书保存路径', - helper: '路径要包含文件名,一般情况传上面两个文件就行了,极少数情况需要这个中间证书', + title: "中间证书保存路径", + helper: "路径要包含文件名,一般情况传上面两个文件就行了,极少数情况需要这个中间证书", component: { - placeholder: '/root/deploy/nginx/intermediate.pem', + placeholder: "/root/deploy/nginx/intermediate.pem", }, mergeScript: ` return { @@ -92,15 +92,15 @@ export class CopyCertToLocalPlugin extends AbstractTaskPlugin { }) } `, - rules: [{ type: 'filepath' }], + rules: [{ type: "filepath" }], }) icPath!: string; @TaskInput({ - title: 'PFX证书保存路径', - helper: '用于IIS证书部署,路径要包含文件名\n推荐使用相对路径,将写入与数据库同级目录,无需映射,例如:tmp/cert.pfx', + title: "PFX证书保存路径", + helper: "用于IIS证书部署,路径要包含文件名\n推荐使用相对路径,将写入与数据库同级目录,无需映射,例如:tmp/cert.pfx", component: { - placeholder: 'tmp/cert.pfx', + placeholder: "tmp/cert.pfx", }, mergeScript: ` return { @@ -110,16 +110,15 @@ export class CopyCertToLocalPlugin extends AbstractTaskPlugin { } `, required: true, - rules: [{ type: 'filepath' }], + rules: [{ type: "filepath" }], }) pfxPath!: string; @TaskInput({ - title: 'DER证书保存路径', - helper: - '用于Apache证书部署,路径要包含文件名\n推荐使用相对路径,将写入与数据库同级目录,无需映射,例如:tmp/cert.der\n.der和.cer是相同的东西,改个后缀名即可', + title: "DER证书保存路径", + helper: "用于Apache证书部署,路径要包含文件名\n推荐使用相对路径,将写入与数据库同级目录,无需映射,例如:tmp/cert.der\n.der和.cer是相同的东西,改个后缀名即可", component: { - placeholder: 'tmp/cert.der 或 tmp/cert.cer', + placeholder: "tmp/cert.der 或 tmp/cert.cer", }, mergeScript: ` return { @@ -129,15 +128,15 @@ export class CopyCertToLocalPlugin extends AbstractTaskPlugin { } `, required: true, - rules: [{ type: 'filepath' }], + rules: [{ type: "filepath" }], }) derPath!: string; @TaskInput({ - title: 'jks证书保存路径', - helper: '用于java,路径要包含文件名,例如:tmp/cert.jks', + title: "jks证书保存路径", + helper: "用于java,路径要包含文件名,例如:tmp/cert.jks", component: { - placeholder: 'tmp/cert.jks', + placeholder: "tmp/cert.jks", }, mergeScript: ` return { @@ -147,43 +146,43 @@ export class CopyCertToLocalPlugin extends AbstractTaskPlugin { } `, required: true, - rules: [{ type: 'filepath' }], + rules: [{ type: "filepath" }], }) jksPath!: string; @TaskOutput({ - title: '证书保存路径', - type: 'HostCrtPath', + title: "证书保存路径", + type: "HostCrtPath", }) hostCrtPath!: string; @TaskOutput({ - title: '私钥保存路径', - type: 'HostKeyPath', + title: "私钥保存路径", + type: "HostKeyPath", }) hostKeyPath!: string; @TaskOutput({ - title: '中间证书保存路径', - type: 'HostKeyPath', + title: "中间证书保存路径", + type: "HostKeyPath", }) hostIcPath!: string; @TaskOutput({ - title: 'PFX保存路径', - type: 'HostPfxPath', + title: "PFX保存路径", + type: "HostPfxPath", }) hostPfxPath!: string; @TaskOutput({ - title: 'DER保存路径', - type: 'HostDerPath', + title: "DER保存路径", + type: "HostDerPath", }) hostDerPath!: string; @TaskOutput({ - title: 'jks保存路径', - type: 'HostJksPath', + title: "jks保存路径", + type: "HostJksPath", }) hostJksPath!: string; @@ -204,52 +203,50 @@ export class CopyCertToLocalPlugin extends AbstractTaskPlugin { const certReader = new CertReader(this.cert); const handle = async ({ reader, tmpCrtPath, tmpKeyPath, tmpDerPath, tmpPfxPath, tmpIcPath, tmpJksPath }) => { - this.logger.info('复制到目标路径'); + this.logger.info("复制到目标路径"); if (crtPath) { crtPath = crtPath.trim(); - crtPath = crtPath.startsWith('/') ? crtPath : path.join(dataDir, crtPath); + crtPath = crtPath.startsWith("/") ? crtPath : path.join(dataDir, crtPath); this.copyFile(tmpCrtPath, crtPath); this.hostCrtPath = crtPath; } if (keyPath) { keyPath = keyPath.trim(); - keyPath = keyPath.startsWith('/') ? keyPath : path.join(dataDir, keyPath); + keyPath = keyPath.startsWith("/") ? keyPath : path.join(dataDir, keyPath); this.copyFile(tmpKeyPath, keyPath); this.hostKeyPath = keyPath; } if (icPath) { icPath = icPath.trim(); - icPath = icPath.startsWith('/') ? icPath : path.join(dataDir, icPath); + icPath = icPath.startsWith("/") ? icPath : path.join(dataDir, icPath); this.copyFile(tmpIcPath, icPath); this.hostIcPath = icPath; } if (pfxPath) { pfxPath = pfxPath.trim(); - pfxPath = pfxPath.startsWith('/') ? pfxPath : path.join(dataDir, pfxPath); + pfxPath = pfxPath.startsWith("/") ? pfxPath : path.join(dataDir, pfxPath); this.copyFile(tmpPfxPath, pfxPath); this.hostPfxPath = pfxPath; } if (derPath) { derPath = derPath.trim(); - derPath = derPath.startsWith('/') ? derPath : path.join(dataDir, derPath); + derPath = derPath.startsWith("/") ? derPath : path.join(dataDir, derPath); this.copyFile(tmpDerPath, derPath); this.hostDerPath = derPath; } if (jksPath) { jksPath = jksPath.trim(); - jksPath = jksPath.startsWith('/') ? jksPath : path.join(dataDir, jksPath); + jksPath = jksPath.startsWith("/") ? jksPath : path.join(dataDir, jksPath); this.copyFile(tmpJksPath, jksPath); this.hostJksPath = jksPath; } - this.logger.info('请注意,如果使用的是相对路径,那么文件就在你的数据库同级目录下,默认是/data/certd/下面'); - this.logger.info( - '请注意,如果使用的是绝对路径,文件在容器内的目录下,你需要给容器做目录映射才能复制到宿主机,需要在docker-compose.yaml中配置主机目录映射: volumes: /你宿主机的路径:/任务配置的证书路径' - ); + this.logger.info("请注意,如果使用的是相对路径,那么文件就在你的数据库同级目录下,默认是/data/certd/下面"); + this.logger.info("请注意,如果使用的是绝对路径,文件在容器内的目录下,你需要给容器做目录映射才能复制到宿主机,需要在docker-compose.yaml中配置主机目录映射: volumes: /你宿主机的路径:/任务配置的证书路径"); }; await certReader.readCertFile({ logger: this.logger, handle }); - this.logger.info('执行完成'); + this.logger.info("执行完成"); } } diff --git a/packages/ui/certd-server/src/plugins/plugin-host/plugin/host-shell-execute/index.ts b/packages/ui/certd-server/src/plugins/plugin-host/plugin/host-shell-execute/index.ts index 0bbcb34b2..30ca4e9f0 100644 --- a/packages/ui/certd-server/src/plugins/plugin-host/plugin/host-shell-execute/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-host/plugin/host-shell-execute/index.ts @@ -1,11 +1,11 @@ -import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from '@certd/pipeline'; -import { SshClient } from '../../../plugin-lib/ssh/index.js'; +import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; +import { SshClient } from "../../../plugin-lib/ssh/index.js"; @IsTaskPlugin({ - name: 'hostShellExecute', - title: '主机-执行远程主机脚本命令', - icon: 'tabler:brand-powershell', + name: "hostShellExecute", + title: "主机-执行远程主机脚本命令", + icon: "tabler:brand-powershell", group: pluginGroups.host.key, - desc: '可以执行重启nginx等操作让证书生效', + desc: "可以执行重启nginx等操作让证书生效", input: {}, showRunStrategy: true, default: { @@ -17,24 +17,24 @@ import { SshClient } from '../../../plugin-lib/ssh/index.js'; }) export class HostShellExecutePlugin extends AbstractTaskPlugin { @TaskInput({ - title: '主机登录配置', - helper: '登录', + title: "主机登录配置", + helper: "登录", component: { - name: 'access-selector', - type: 'ssh', + name: "access-selector", + type: "ssh", }, required: true, }) accessId!: string; @TaskInput({ - title: 'shell脚本命令', + title: "shell脚本命令", component: { - name: 'a-textarea', - vModel: 'value', + name: "a-textarea", + vModel: "value", rows: 6, - placeholder: 'systemctl restart nginx', + placeholder: "systemctl restart nginx", }, - helper: '注意:如果目标主机是windows,且终端是cmd,系统会自动将多行命令通过“&&”连接成一行', + helper: "注意:如果目标主机是windows,且终端是cmd,系统会自动将多行命令通过“&&”连接成一行", required: true, }) script!: string; @@ -45,7 +45,7 @@ export class HostShellExecutePlugin extends AbstractTaskPlugin { const connectConf = await this.getAccess(accessId); const sshClient = new SshClient(this.logger); - const scripts = script.split('\n'); + const scripts = script.split("\n"); await sshClient.exec({ connectConf, script: scripts, diff --git a/packages/ui/certd-server/src/plugins/plugin-host/plugin/index.ts b/packages/ui/certd-server/src/plugins/plugin-host/plugin/index.ts index 03e172d46..c1c1f4afc 100644 --- a/packages/ui/certd-server/src/plugins/plugin-host/plugin/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-host/plugin/index.ts @@ -1,5 +1,5 @@ -export * from './host-shell-execute/index.js'; -export * from './upload-to-host/index.js'; -export * from './copy-to-local/index.js' -export * from './plugin-upload-to-oss.js' -export * from './plugin-deploy-to-iis.js' \ No newline at end of file +export * from "./host-shell-execute/index.js"; +export * from "./upload-to-host/index.js"; +export * from "./copy-to-local/index.js"; +export * from "./plugin-upload-to-oss.js"; +export * from "./plugin-deploy-to-iis.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-host/plugin/plugin-upload-to-oss.ts b/packages/ui/certd-server/src/plugins/plugin-host/plugin/plugin-upload-to-oss.ts index 3b0ea547e..59e9b5bf4 100644 --- a/packages/ui/certd-server/src/plugins/plugin-host/plugin/plugin-upload-to-oss.ts +++ b/packages/ui/certd-server/src/plugins/plugin-host/plugin/plugin-upload-to-oss.ts @@ -1,15 +1,15 @@ -import {AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput} from '@certd/pipeline'; -import {CertInfo} from "@certd/plugin-cert"; -import {utils} from "@certd/basic"; -import { ossClientFactory } from '../../plugin-lib/oss/factory.js'; +import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; +import { CertInfo } from "@certd/plugin-cert"; +import { utils } from "@certd/basic"; +import { ossClientFactory } from "../../plugin-lib/oss/factory.js"; @IsTaskPlugin({ - name: 'UploadCertToOss', - title: '上传证书到对象存储OSS', - icon: 'ion:cloud-upload-outline', - desc: '支持阿里云OSS、腾讯云COS、七牛云KODO、S3、MinIO、FTP、SFTP', + name: "UploadCertToOss", + title: "上传证书到对象存储OSS", + icon: "ion:cloud-upload-outline", + desc: "支持阿里云OSS、腾讯云COS、七牛云KODO、S3、MinIO、FTP、SFTP", group: pluginGroups.host.key, - showRunStrategy:false, + showRunStrategy: false, default: { strategy: { runStrategy: RunStrategy.SkipWhenSucceed, @@ -17,24 +17,22 @@ import { ossClientFactory } from '../../plugin-lib/oss/factory.js'; }, }) export class UploadCertToOssPlugin extends AbstractTaskPlugin { - @TaskInput({ - title: '域名证书', - helper: '请选择前置任务输出的域名证书', + title: "域名证书", + helper: "请选择前置任务输出的域名证书", component: { - name: 'output-selector', + name: "output-selector", from: [":cert:"], }, required: true, }) cert!: CertInfo; - @TaskInput({ - title: 'OSS类型', + title: "OSS类型", component: { - name: 'a-select', - vModel:"value", + name: "a-select", + vModel: "value", options: [ { label: "阿里云OSS", value: "alioss" }, { label: "腾讯云COS", value: "tencentcos" }, @@ -42,17 +40,16 @@ export class UploadCertToOssPlugin extends AbstractTaskPlugin { { label: "S3/Minio", value: "s3" }, { label: "SFTP", value: "sftp" }, { label: "FTP", value: "ftp" }, - ] + ], }, required: true, }) uploaderType!: string; - @TaskInput({ - title: 'OSS授权', + title: "OSS授权", component: { - name: 'access-selector', + name: "access-selector", }, required: true, mergeScript: ` @@ -67,18 +64,17 @@ export class UploadCertToOssPlugin extends AbstractTaskPlugin { }) accessId!: string; - @TaskInput({ - title: '证书格式', - helper: '要部署的证书格式,支持pem、pfx、der、jks', + title: "证书格式", + helper: "要部署的证书格式,支持pem、pfx、der、jks", component: { - name: 'a-select', + name: "a-select", options: [ - { value: 'pem', label: 'pem(crt),Nginx等大部分应用' }, - { value: 'pfx', label: 'pfx,一般用于IIS' }, - { value: 'der', label: 'der,一般用于Apache' }, - { value: 'jks', label: 'jks,一般用于JAVA应用' }, - { value: 'one', label: '证书私钥一体,crt+key简单合并为一个pem文件' }, + { value: "pem", label: "pem(crt),Nginx等大部分应用" }, + { value: "pfx", label: "pfx,一般用于IIS" }, + { value: "der", label: "der,一般用于Apache" }, + { value: "jks", label: "jks,一般用于JAVA应用" }, + { value: "one", label: "证书私钥一体,crt+key简单合并为一个pem文件" }, ], }, required: true, @@ -86,10 +82,10 @@ export class UploadCertToOssPlugin extends AbstractTaskPlugin { certType!: string; @TaskInput({ - title: '证书保存路径', - helper: '路径要包含证书文件名,例如:/tmp/cert.pem', + title: "证书保存路径", + helper: "路径要包含证书文件名,例如:/tmp/cert.pem", component: { - placeholder: '/root/deploy/nginx/full_chain.pem', + placeholder: "/root/deploy/nginx/full_chain.pem", }, mergeScript: ` return { @@ -99,14 +95,14 @@ export class UploadCertToOssPlugin extends AbstractTaskPlugin { } `, required: true, - rules: [{ type: 'filepath' }], + rules: [{ type: "filepath" }], }) crtPath!: string; @TaskInput({ - title: '私钥保存路径', - helper: '路径要包含私钥文件名,例如:/tmp/cert.key', + title: "私钥保存路径", + helper: "路径要包含私钥文件名,例如:/tmp/cert.key", component: { - placeholder: '/root/deploy/nginx/cert.key', + placeholder: "/root/deploy/nginx/cert.key", }, mergeScript: ` return { @@ -116,15 +112,15 @@ export class UploadCertToOssPlugin extends AbstractTaskPlugin { } `, required: true, - rules: [{ type: 'filepath' }], + rules: [{ type: "filepath" }], }) keyPath!: string; @TaskInput({ - title: '中间证书保存路径', - helper: '路径要包含文件名,一般情况传上面两个文件即可,极少数情况需要这个中间证书', + title: "中间证书保存路径", + helper: "路径要包含文件名,一般情况传上面两个文件即可,极少数情况需要这个中间证书", component: { - placeholder: '/root/deploy/nginx/intermediate.pem', + placeholder: "/root/deploy/nginx/intermediate.pem", }, mergeScript: ` return { @@ -133,15 +129,15 @@ export class UploadCertToOssPlugin extends AbstractTaskPlugin { }) } `, - rules: [{ type: 'filepath' }], + rules: [{ type: "filepath" }], }) icPath!: string; @TaskInput({ - title: 'PFX证书保存路径', - helper: '路径要包含证书文件名,例如:D:\\iis\\cert.pfx', + title: "PFX证书保存路径", + helper: "路径要包含证书文件名,例如:D:\\iis\\cert.pfx", component: { - placeholder: 'D:\\iis\\cert.pfx', + placeholder: "D:\\iis\\cert.pfx", }, mergeScript: ` return { @@ -151,15 +147,15 @@ export class UploadCertToOssPlugin extends AbstractTaskPlugin { } `, required: true, - rules: [{ type: 'filepath' }], + rules: [{ type: "filepath" }], }) pfxPath!: string; @TaskInput({ - title: 'DER证书保存路径', - helper: '路径要包含证书文件名,例如:/tmp/cert.der', + title: "DER证书保存路径", + helper: "路径要包含证书文件名,例如:/tmp/cert.der", component: { - placeholder: '/root/deploy/apache/cert.der', + placeholder: "/root/deploy/apache/cert.der", }, mergeScript: ` return { @@ -169,15 +165,15 @@ export class UploadCertToOssPlugin extends AbstractTaskPlugin { } `, required: true, - rules: [{ type: 'filepath' }], + rules: [{ type: "filepath" }], }) derPath!: string; @TaskInput({ - title: 'jks证书保存路径', - helper: '路径要包含证书文件名,例如:/tmp/cert.jks', + title: "jks证书保存路径", + helper: "路径要包含证书文件名,例如:/tmp/cert.jks", component: { - placeholder: '/root/deploy/java_app/cert.jks', + placeholder: "/root/deploy/java_app/cert.jks", }, mergeScript: ` return { @@ -187,15 +183,15 @@ export class UploadCertToOssPlugin extends AbstractTaskPlugin { } `, required: true, - rules: [{ type: 'filepath' }], + rules: [{ type: "filepath" }], }) jksPath!: string; @TaskInput({ - title: '一体证书保存路径', - helper: '路径要包含证书文件名,例如:/tmp/crt_key.pem', + title: "一体证书保存路径", + helper: "路径要包含证书文件名,例如:/tmp/crt_key.pem", component: { - placeholder: '/app/crt_key.pem', + placeholder: "/app/crt_key.pem", }, mergeScript: ` return { @@ -205,21 +201,20 @@ export class UploadCertToOssPlugin extends AbstractTaskPlugin { } `, required: true, - rules: [{ type: 'filepath' }], + rules: [{ type: "filepath" }], }) onePath!: string; - async onInstance() {} async execute(): Promise { const { accessId } = this; - let { crtPath, keyPath, icPath, pfxPath, derPath, jksPath, onePath } = this; + const { crtPath, keyPath, icPath, pfxPath, derPath, jksPath, onePath } = this; if (!accessId) { - throw new Error('OSS授权配置不能为空'); + throw new Error("OSS授权配置不能为空"); } - const uploaderType = this.uploaderType - const uploaderAccess = this.accessId + const uploaderType = this.uploaderType; + const uploaderAccess = this.accessId; const httpUploaderContext = { accessService: this.ctx.accessService, @@ -235,40 +230,39 @@ export class UploadCertToOssPlugin extends AbstractTaskPlugin { ctx: httpUploaderContext, }); - - this.logger.info('准备上传文件到OSS'); + this.logger.info("准备上传文件到OSS"); if (crtPath) { - await httpUploader.upload(crtPath, Buffer.from(this.cert.crt)) + await httpUploader.upload(crtPath, Buffer.from(this.cert.crt)); this.logger.info(`上传证书:${crtPath}`); } if (keyPath) { - await httpUploader.upload(keyPath, Buffer.from(this.cert.key)) + await httpUploader.upload(keyPath, Buffer.from(this.cert.key)); this.logger.info(`上传私钥:${keyPath}`); } if (icPath) { - await httpUploader.upload(icPath, Buffer.from(this.cert.ic)) + await httpUploader.upload(icPath, Buffer.from(this.cert.ic)); this.logger.info(`上传中间证书:${icPath}`); } if (pfxPath) { - await httpUploader.upload(pfxPath, Buffer.from(this.cert.pfx, "base64")) + await httpUploader.upload(pfxPath, Buffer.from(this.cert.pfx, "base64")); this.logger.info(`上传PFX证书:${pfxPath}`); } if (derPath) { - await httpUploader.upload(derPath, Buffer.from(this.cert.der, "base64")) + await httpUploader.upload(derPath, Buffer.from(this.cert.der, "base64")); this.logger.info(`上传DER证书:${derPath}`); } if (this.jksPath) { - await httpUploader.upload(jksPath,Buffer.from(this.cert.jks, "base64")) + await httpUploader.upload(jksPath, Buffer.from(this.cert.jks, "base64")); this.logger.info(`上传jks证书:${jksPath}`); } if (onePath) { - await httpUploader.upload(onePath, Buffer.from(this.cert.one)) + await httpUploader.upload(onePath, Buffer.from(this.cert.one)); this.logger.info(`上传一体证书:${onePath}`); } - this.logger.info('上传文件成功'); + this.logger.info("上传文件成功"); } } new UploadCertToOssPlugin(); diff --git a/packages/ui/certd-server/src/plugins/plugin-host/plugin/upload-to-host/index.ts b/packages/ui/certd-server/src/plugins/plugin-host/plugin/upload-to-host/index.ts index ccbcfe135..ff0f27368 100644 --- a/packages/ui/certd-server/src/plugins/plugin-host/plugin/upload-to-host/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-host/plugin/upload-to-host/index.ts @@ -1,14 +1,14 @@ -import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput, TaskOutput } from '@certd/pipeline'; -import { CertInfo, CertReader, CertReaderHandleContext } from '@certd/plugin-cert'; -import dayjs from 'dayjs'; -import { SshAccess, SshClient } from '../../../plugin-lib/ssh/index.js'; -import { CertApplyPluginNames} from '@certd/plugin-cert'; +import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput, TaskOutput } from "@certd/pipeline"; +import { CertInfo, CertReader, CertReaderHandleContext } from "@certd/plugin-cert"; +import dayjs from "dayjs"; +import { SshAccess, SshClient } from "../../../plugin-lib/ssh/index.js"; +import { CertApplyPluginNames } from "@certd/plugin-cert"; @IsTaskPlugin({ - name: 'uploadCertToHost', - title: '主机-部署证书到SSH主机', - icon: 'line-md:uploading-loop', + name: "uploadCertToHost", + title: "主机-部署证书到SSH主机", + icon: "line-md:uploading-loop", group: pluginGroups.host.key, - desc: '上传证书到主机覆盖原来的证书文件,然后自动执行部署脚本命令使证书生效', + desc: "上传证书到主机覆盖原来的证书文件,然后自动执行部署脚本命令使证书生效", order: 1, default: { strategy: { @@ -18,10 +18,10 @@ import { CertApplyPluginNames} from '@certd/plugin-cert'; }) export class UploadCertToHostPlugin extends AbstractTaskPlugin { @TaskInput({ - title: '域名证书', - helper: '请选择前置任务输出的域名证书', + title: "域名证书", + helper: "请选择前置任务输出的域名证书", component: { - name: 'output-selector', + name: "output-selector", from: [...CertApplyPluginNames], }, required: true, @@ -29,17 +29,17 @@ export class UploadCertToHostPlugin extends AbstractTaskPlugin { cert!: CertInfo; @TaskInput({ - title: '证书格式', - helper: '要部署的证书格式,支持pem/crt、pfx、der、jks、p7b\n你原来的证书是哪种格式就选择哪种', + title: "证书格式", + helper: "要部署的证书格式,支持pem/crt、pfx、der、jks、p7b\n你原来的证书是哪种格式就选择哪种", component: { - name: 'a-select', + name: "a-select", options: [ - { value: 'pem', label: 'pem/crt,用于Nginx等大部分应用,证书和私钥2个文件' }, - { value: 'pfx', label: 'pfx,一般用于IIS' }, - { value: 'der', label: 'der,一般用于Apache' }, - { value: 'jks', label: 'jks,一般用于JAVA应用' }, - { value: 'one', label: '证书私钥一体,crt+key简单合并为一个pem文件' }, - { value: 'p7b', label: 'p7b格式' }, + { value: "pem", label: "pem/crt,用于Nginx等大部分应用,证书和私钥2个文件" }, + { value: "pfx", label: "pfx,一般用于IIS" }, + { value: "der", label: "der,一般用于Apache" }, + { value: "jks", label: "jks,一般用于JAVA应用" }, + { value: "one", label: "证书私钥一体,crt+key简单合并为一个pem文件" }, + { value: "p7b", label: "p7b格式" }, ], }, required: true, @@ -47,10 +47,10 @@ export class UploadCertToHostPlugin extends AbstractTaskPlugin { certType!: string; @TaskInput({ - title: '证书保存路径', - helper: '填写应用原本的证书保存路径,路径要包含证书文件名,例如:/tmp/cert.pem', + title: "证书保存路径", + helper: "填写应用原本的证书保存路径,路径要包含证书文件名,例如:/tmp/cert.pem", component: { - placeholder: '/root/deploy/nginx/full_chain.pem', + placeholder: "/root/deploy/nginx/full_chain.pem", }, mergeScript: ` return { @@ -60,14 +60,14 @@ export class UploadCertToHostPlugin extends AbstractTaskPlugin { } `, required: true, - rules: [{ type: 'filepath' }], + rules: [{ type: "filepath" }], }) crtPath!: string; @TaskInput({ - title: '私钥保存路径', - helper: '原本的私钥保存路径,需要有写入权限,路径要包含私钥文件名,例如:/tmp/cert.key', + title: "私钥保存路径", + helper: "原本的私钥保存路径,需要有写入权限,路径要包含私钥文件名,例如:/tmp/cert.key", component: { - placeholder: '/root/deploy/nginx/cert.key', + placeholder: "/root/deploy/nginx/cert.key", }, mergeScript: ` return { @@ -77,15 +77,15 @@ export class UploadCertToHostPlugin extends AbstractTaskPlugin { } `, required: true, - rules: [{ type: 'filepath' }], + rules: [{ type: "filepath" }], }) keyPath!: string; @TaskInput({ - title: '中间证书保存路径', - helper: '路径要包含文件名,一般情况传上面两个文件即可,极少数情况需要这个中间证书', + title: "中间证书保存路径", + helper: "路径要包含文件名,一般情况传上面两个文件即可,极少数情况需要这个中间证书", component: { - placeholder: '/root/deploy/nginx/intermediate.pem', + placeholder: "/root/deploy/nginx/intermediate.pem", }, mergeScript: ` return { @@ -94,15 +94,15 @@ export class UploadCertToHostPlugin extends AbstractTaskPlugin { }) } `, - rules: [{ type: 'filepath' }], + rules: [{ type: "filepath" }], }) icPath!: string; @TaskInput({ - title: 'PFX证书保存路径', - helper: '填写应用原本的证书保存路径,路径要包含证书文件名,例如:D:\\iis\\cert.pfx', + title: "PFX证书保存路径", + helper: "填写应用原本的证书保存路径,路径要包含证书文件名,例如:D:\\iis\\cert.pfx", component: { - placeholder: 'D:\\iis\\cert.pfx', + placeholder: "D:\\iis\\cert.pfx", }, mergeScript: ` return { @@ -112,15 +112,15 @@ export class UploadCertToHostPlugin extends AbstractTaskPlugin { } `, required: true, - rules: [{ type: 'filepath' }], + rules: [{ type: "filepath" }], }) pfxPath!: string; @TaskInput({ - title: 'DER证书保存路径', - helper: '填写应用原本的证书保存路径,路径要包含证书文件名,例如:/tmp/cert.der', + title: "DER证书保存路径", + helper: "填写应用原本的证书保存路径,路径要包含证书文件名,例如:/tmp/cert.der", component: { - placeholder: '/root/deploy/apache/cert.der', + placeholder: "/root/deploy/apache/cert.der", }, mergeScript: ` return { @@ -130,15 +130,15 @@ export class UploadCertToHostPlugin extends AbstractTaskPlugin { } `, required: true, - rules: [{ type: 'filepath' }], + rules: [{ type: "filepath" }], }) derPath!: string; @TaskInput({ - title: 'jks证书保存路径', - helper: '填写应用原本的证书保存路径,路径要包含证书文件名,例如:/tmp/cert.jks', + title: "jks证书保存路径", + helper: "填写应用原本的证书保存路径,路径要包含证书文件名,例如:/tmp/cert.jks", component: { - placeholder: '/root/deploy/java_app/cert.jks', + placeholder: "/root/deploy/java_app/cert.jks", }, mergeScript: ` return { @@ -148,15 +148,15 @@ export class UploadCertToHostPlugin extends AbstractTaskPlugin { } `, required: true, - rules: [{ type: 'filepath' }], + rules: [{ type: "filepath" }], }) jksPath!: string; @TaskInput({ - title: '一体证书保存路径', - helper: '填写应用原本的证书保存路径,路径要包含证书文件名,例如:/tmp/crt_key.pem', + title: "一体证书保存路径", + helper: "填写应用原本的证书保存路径,路径要包含证书文件名,例如:/tmp/crt_key.pem", component: { - placeholder: '/root/deploy/app/crt_key.pem', + placeholder: "/root/deploy/app/crt_key.pem", }, mergeScript: ` return { @@ -166,15 +166,15 @@ export class UploadCertToHostPlugin extends AbstractTaskPlugin { } `, required: true, - rules: [{ type: 'filepath' }], + rules: [{ type: "filepath" }], }) onePath!: string; @TaskInput({ - title: 'p7b证书保存路径', - helper: '填写应用原本的证书保存路径,路径要包含证书文件名,例如:/tmp/domain_cert.p7b', + title: "p7b证书保存路径", + helper: "填写应用原本的证书保存路径,路径要包含证书文件名,例如:/tmp/domain_cert.p7b", component: { - placeholder: '/root/deploy/app/domain_cert.p7b', + placeholder: "/root/deploy/app/domain_cert.p7b", }, mergeScript: ` return { @@ -184,136 +184,135 @@ export class UploadCertToHostPlugin extends AbstractTaskPlugin { } `, required: true, - rules: [{ type: 'filepath' }], + rules: [{ type: "filepath" }], }) p7bPath!: string; @TaskInput({ - title: '主机登录配置', - helper: 'access授权', + title: "主机登录配置", + helper: "access授权", component: { - name: 'access-selector', - type: 'ssh', + name: "access-selector", + type: "ssh", }, required: true, }) accessId!: string; @TaskInput({ - title: '上传方式', - helper: '支持sftp或者scp\n需要有写入权限,如果没有,须先将证书上传到有权限的目录,再通过后置命令复制到目标路径', - value:"sftp", + title: "上传方式", + helper: "支持sftp或者scp\n需要有写入权限,如果没有,须先将证书上传到有权限的目录,再通过后置命令复制到目标路径", + value: "sftp", component: { - name: 'a-select', + name: "a-select", options: [ - { value: 'sftp', label: 'sftp' }, - { value: 'scp', label: 'scp' }, + { value: "sftp", label: "sftp" }, + { value: "scp", label: "scp" }, ], }, required: true, }) - uploadType: string = 'sftp'; + uploadType = "sftp"; @TaskInput({ - title: '自动创建远程目录', - helper: '是否自动创建远程目录,如果关闭则你需要自己确保远程目录存在', + title: "自动创建远程目录", + helper: "是否自动创建远程目录,如果关闭则你需要自己确保远程目录存在", value: true, component: { - name: 'a-switch', - vModel: 'checked', + name: "a-switch", + vModel: "checked", }, }) mkdirs = true; @TaskInput({ - title: '前置命令', + title: "前置命令", component: { - name: 'a-textarea', - vModel: 'value', + name: "a-textarea", + vModel: "value", rows: 3, - placeholder: 'mkdir /app/ssl', + placeholder: "mkdir /app/ssl", }, - helper: '上传前执行脚本命令,做上传前的准备工作', + helper: "上传前执行脚本命令,做上传前的准备工作", required: false, }) scriptPre!: string; @TaskInput({ - title: '后置命令', + title: "后置命令", component: { - name: 'a-textarea', - vModel: 'value', + name: "a-textarea", + vModel: "value", rows: 5, - placeholder: 'systemctl restart nginx ', + placeholder: "systemctl restart nginx ", }, - helper: '上传后执行脚本命令,让证书生效(比如重启nginx),不填则不执行\n注意:sudo需要配置免密,不要使用-i这种交互式命令\n注意:如果目标主机是windows,且终端是cmd,系统会自动将多行命令通过“&&”连接成一行', + helper: "上传后执行脚本命令,让证书生效(比如重启nginx),不填则不执行\n注意:sudo需要配置免密,不要使用-i这种交互式命令\n注意:如果目标主机是windows,且终端是cmd,系统会自动将多行命令通过“&&”连接成一行", required: false, }) script!: string; @TaskInput({ - title: '注入环境变量', + title: "注入环境变量", value: false, component: { - name: 'a-switch', - vModel: 'checked', + name: "a-switch", + vModel: "checked", }, - helper: '是否将证书域名、路径等信息注入脚本执行环境变量中,具体的变量名称,可以运行后从日志中查看', + helper: "是否将证书域名、路径等信息注入脚本执行环境变量中,具体的变量名称,可以运行后从日志中查看", required: false, }) injectEnv!: string; @TaskOutput({ - title: '证书保存路径', + title: "证书保存路径", }) hostCrtPath!: string; @TaskOutput({ - title: '私钥保存路径', + title: "私钥保存路径", }) hostKeyPath!: string; @TaskOutput({ - title: '中间证书保存路径', + title: "中间证书保存路径", }) hostIcPath!: string; @TaskOutput({ - title: 'PFX保存路径', + title: "PFX保存路径", }) hostPfxPath!: string; @TaskOutput({ - title: 'DER保存路径', + title: "DER保存路径", }) hostDerPath!: string; @TaskOutput({ - title: 'jks保存路径', + title: "jks保存路径", }) hostJksPath!: string; @TaskOutput({ - title: '一体证书保存路径', + title: "一体证书保存路径", }) hostOnePath!: string; @TaskOutput({ - title: 'p7b证书保存路径', + title: "p7b证书保存路径", }) hostP7bPath!: string; async onInstance() {} - async execute(): Promise { const { cert, accessId } = this; - let { crtPath, keyPath, icPath, pfxPath, derPath, jksPath, onePath,p7bPath } = this; + let { crtPath, keyPath, icPath, pfxPath, derPath, jksPath, onePath, p7bPath } = this; const certReader = new CertReader(cert); - const executeCmd = async ( script:string)=> { + const executeCmd = async (script: string) => { if (script && script?.trim()) { const connectConf: SshAccess = await this.getAccess(accessId); const sshClient = new SshClient(this.logger); - this.logger.info('执行脚本命令'); + this.logger.info("执行脚本命令"); //环境变量 const env = {}; @@ -323,41 +322,41 @@ export class UploadCertToHostPlugin extends AbstractTaskPlugin { env[`CERT_DOMAIN_${i}`] = domains[i]; } //环境变量必须是string - env['CERT_EXPIRES'] = "" + dayjs(certReader.getCrtDetail().expires).unix(); + env["CERT_EXPIRES"] = "" + dayjs(certReader.getCrtDetail().expires).unix(); - env['HOST_CRT_PATH'] = this.hostCrtPath || ''; - env['HOST_KEY_PATH'] = this.hostKeyPath || ''; - env['HOST_IC_PATH'] = this.hostIcPath || ''; - env['HOST_PFX_PATH'] = this.hostPfxPath || ''; - env['HOST_DER_PATH'] = this.hostDerPath || ''; - env['HOST_JKS_PATH'] = this.hostJksPath || ''; - env['HOST_ONE_PATH'] = this.hostOnePath || ''; - env['HOST_P7B_PATH'] = this.hostOnePath || ''; + env["HOST_CRT_PATH"] = this.hostCrtPath || ""; + env["HOST_KEY_PATH"] = this.hostKeyPath || ""; + env["HOST_IC_PATH"] = this.hostIcPath || ""; + env["HOST_PFX_PATH"] = this.hostPfxPath || ""; + env["HOST_DER_PATH"] = this.hostDerPath || ""; + env["HOST_JKS_PATH"] = this.hostJksPath || ""; + env["HOST_ONE_PATH"] = this.hostOnePath || ""; + env["HOST_P7B_PATH"] = this.hostOnePath || ""; } - const scripts = script.split('\n'); + const scripts = script.split("\n"); await sshClient.exec({ connectConf, script: scripts, env, }); } - } + }; const handle = async (opts: CertReaderHandleContext) => { - const { tmpCrtPath, tmpKeyPath, tmpDerPath, tmpJksPath, tmpPfxPath, tmpIcPath, tmpOnePath ,tmpP7bPath} = opts; + const { tmpCrtPath, tmpKeyPath, tmpDerPath, tmpJksPath, tmpPfxPath, tmpIcPath, tmpOnePath, tmpP7bPath } = opts; if (accessId == null) { - this.logger.error('复制到当前主机功能已迁移到 “复制到本机”插件,请换成复制到本机插件'); + this.logger.error("复制到当前主机功能已迁移到 “复制到本机”插件,请换成复制到本机插件"); return; } const connectConf: SshAccess = await this.getAccess(accessId); const sshClient = new SshClient(this.logger); if (!accessId) { - throw new Error('主机登录授权配置不能为空'); + throw new Error("主机登录授权配置不能为空"); } - this.logger.info('准备上传文件到服务器'); + this.logger.info("准备上传文件到服务器"); const transports: any = []; if (crtPath) { @@ -426,7 +425,7 @@ export class UploadCertToHostPlugin extends AbstractTaskPlugin { }); } - this.logger.info('开始上传文件到服务器'); + this.logger.info("开始上传文件到服务器"); await sshClient.uploadFiles({ connectConf, transports, @@ -434,7 +433,7 @@ export class UploadCertToHostPlugin extends AbstractTaskPlugin { uploadType: this.uploadType, }); - this.logger.info('上传文件到服务器成功'); + this.logger.info("上传文件到服务器成功"); //输出 this.hostCrtPath = crtPath; this.hostKeyPath = keyPath; diff --git a/packages/ui/certd-server/src/plugins/plugin-huawei/access/huawei-access.ts b/packages/ui/certd-server/src/plugins/plugin-huawei/access/huawei-access.ts index 1a7c6ff34..3025fb8b0 100644 --- a/packages/ui/certd-server/src/plugins/plugin-huawei/access/huawei-access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-huawei/access/huawei-access.ts @@ -1,67 +1,60 @@ -import { resetLogConfigure } from '@certd/basic'; -import { IsAccess, AccessInput, BaseAccess } from '@certd/pipeline'; +import { resetLogConfigure } from "@certd/basic"; +import { IsAccess, AccessInput, BaseAccess } from "@certd/pipeline"; @IsAccess({ - name: 'huawei', - title: '华为云授权', - desc: '', - icon: 'svg:icon-huawei', + name: "huawei", + title: "华为云授权", + desc: "", + icon: "svg:icon-huawei", order: 0, }) export class HuaweiAccess extends BaseAccess { @AccessInput({ - title: 'accessKeyId', + title: "accessKeyId", component: { - placeholder: 'accessKeyId', + placeholder: "accessKeyId", }, - helper: '证书申请需要有dns解析权限,前往[我的凭证-访问密钥](https://console.huaweicloud.com/iam/?region=cn-east-3#/mine/accessKey)获取', + helper: "证书申请需要有dns解析权限,前往[我的凭证-访问密钥](https://console.huaweicloud.com/iam/?region=cn-east-3#/mine/accessKey)获取", required: true, }) - accessKeyId = ''; + accessKeyId = ""; @AccessInput({ - title: 'accessKeySecret', + title: "accessKeySecret", component: { - placeholder: 'accessKeySecret', + placeholder: "accessKeySecret", }, required: true, encrypt: true, }) - accessKeySecret = ''; - - + accessKeySecret = ""; @AccessInput({ title: "测试", component: { name: "api-test", - action: "TestRequest" + action: "TestRequest", }, - helper: "点击测试接口是否正常" + helper: "点击测试接口是否正常", }) testRequest = true; - accessToken: { expiresAt: number, token: string } + accessToken: { expiresAt: number; token: string }; async onTestRequest() { await this.getProjectList(); - return "ok" + return "ok"; } - async getProjectList() { const endpoint = "https://iam.cn-north-4.myhuaweicloud.com"; - const { BasicCredentials } = await import('@huaweicloud/huaweicloud-sdk-core'); - const iam = await import('@huaweicloud/huaweicloud-sdk-iam/v3/public-api.js'); + const { BasicCredentials } = await import("@huaweicloud/huaweicloud-sdk-core"); + const iam = await import("@huaweicloud/huaweicloud-sdk-iam/v3/public-api.js"); //恢复华为云把log4j的config改了的问题 resetLogConfigure(); - const credentials: any = new BasicCredentials().withAk(this.accessKeyId).withSk(this.accessKeySecret) + const credentials: any = new BasicCredentials().withAk(this.accessKeyId).withSk(this.accessKeySecret); - - const client = iam.IamClient.newBuilder() - .withCredential(credentials) - .withEndpoint(endpoint) - .build(); + const client = iam.IamClient.newBuilder().withCredential(credentials).withEndpoint(endpoint).build(); const request = new iam.KeystoneListAuthProjectsRequest(); const result = await client.keystoneListAuthProjects(request); return result.projects; diff --git a/packages/ui/certd-server/src/plugins/plugin-huawei/access/index.ts b/packages/ui/certd-server/src/plugins/plugin-huawei/access/index.ts index 717c91442..1678dba77 100644 --- a/packages/ui/certd-server/src/plugins/plugin-huawei/access/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-huawei/access/index.ts @@ -1 +1 @@ -export * from './huawei-access.js'; +export * from "./huawei-access.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-huawei/dns-provider/huawei-dns-provider.ts b/packages/ui/certd-server/src/plugins/plugin-huawei/dns-provider/huawei-dns-provider.ts index 098c31e37..5aa998882 100644 --- a/packages/ui/certd-server/src/plugins/plugin-huawei/dns-provider/huawei-dns-provider.ts +++ b/packages/ui/certd-server/src/plugins/plugin-huawei/dns-provider/huawei-dns-provider.ts @@ -14,7 +14,7 @@ export type SearchRecordOptions = { title: "华为云", desc: "华为云DNS解析提供商", accessType: "huawei", - icon: "svg:icon-huawei" + icon: "svg:icon-huawei", }) export class HuaweiDnsProvider extends AbstractDnsProvider { client!: HuaweiYunClient; @@ -23,7 +23,7 @@ export class HuaweiDnsProvider extends AbstractDnsProvider { dnsEndpoint = "https://dns.cn-south-1.myhuaweicloud.com"; async onInstance() { - this.access = this.ctx.access as HuaweiAccess + this.access = this.ctx.access as HuaweiAccess; const access: any = this.access; this.client = new HuaweiYunClient(access, this.logger); } @@ -32,7 +32,7 @@ export class HuaweiDnsProvider extends AbstractDnsProvider { const url = `${this.dnsEndpoint}/v2/zones`; const ret = await this.client.request({ url, - method: "GET" + method: "GET", }); return ret.zones; } @@ -55,7 +55,7 @@ export class HuaweiDnsProvider extends AbstractDnsProvider { async searchRecord(options: SearchRecordOptions): Promise { const req: ApiRequestOptions = { url: `${this.dnsEndpoint}/v2/zones/${options.zoneId}/recordsets?search_mode=equal&name=${options.fullRecord}.&type=${options.type}`, - method: "GET" + method: "GET", }; const ret = await this.client.request(req); return ret.recordsets; @@ -70,7 +70,7 @@ export class HuaweiDnsProvider extends AbstractDnsProvider { const records: any = await this.searchRecord({ zoneId, - ...options + ...options, }); this.logger.info(`查询${options.type}数量:${records.length}`); let found = null; @@ -97,8 +97,8 @@ export class HuaweiDnsProvider extends AbstractDnsProvider { data: { name: fullRecord + ".", type, - records: [hwRecordValue, ...found.records] - } + records: [hwRecordValue, ...found.records], + }, }; const ret = await this.client.request(req); this.logger.info("添加域名解析成功:", value, ret); @@ -112,8 +112,8 @@ export class HuaweiDnsProvider extends AbstractDnsProvider { data: { name: fullRecord + ".", type, - records: [hwRecordValue] - } + records: [hwRecordValue], + }, }; const ret = await this.client.request(req); this.logger.info("添加域名解析成功:", value, ret); @@ -140,7 +140,7 @@ export class HuaweiDnsProvider extends AbstractDnsProvider { //查询原来的记录 const records: any = await this.searchRecord({ zoneId, - ...options.recordReq + ...options.recordReq, }); const hwRecordValue = `"${value}"`; @@ -157,8 +157,8 @@ export class HuaweiDnsProvider extends AbstractDnsProvider { data: { name: fullRecord + ".", type: found.type, - records: found.records.filter((item: string) => item !== hwRecordValue) - } + records: found.records.filter((item: string) => item !== hwRecordValue), + }, }; const ret = await this.client.request(req); this.logger.info("修改域名解析成功[put]:", value, ret); @@ -166,36 +166,36 @@ export class HuaweiDnsProvider extends AbstractDnsProvider { //删除 const req: ApiRequestOptions = { url: `${this.dnsEndpoint}/v2/zones/${zoneId}/recordsets/${found.id}`, - method: "DELETE" + method: "DELETE", }; const ret = await this.client.request(req); this.logger.info("删除域名解析成功[delete]:", fullRecord, value, ret.RecordId); } - }else{ - this.logger.info("没有找到records无需删除", fullRecord, value,found); + } else { + this.logger.info("没有找到records无需删除", fullRecord, value, found); } - }else{ + } else { this.logger.info("删除域名解析失败,没有找到解析记录", fullRecord, value); } } async getDomainListPage(req: PageSearch): Promise> { const pager = new Pager(req); - let url = `${this.dnsEndpoint}/v2/zones?offset=${pager.getOffset()}&limit=${pager.pageSize}`; - if (req.searchKey){ - url += `&name=${req.searchKey}` - } + let url = `${this.dnsEndpoint}/v2/zones?offset=${pager.getOffset()}&limit=${pager.pageSize}`; + if (req.searchKey) { + url += `&name=${req.searchKey}`; + } const ret = await this.client.request({ url, - method: "GET" + method: "GET", }); - let list = ret.zones || [] + let list = ret.zones || []; list = list.map((item: any) => ({ id: item.id, domain: item.name.endsWith(".") ? item.name.slice(0, -1) : item.name, })); return { - total:ret.metadata.total_count || list.length, + total: ret.metadata.total_count || list.length, list, }; } diff --git a/packages/ui/certd-server/src/plugins/plugin-huawei/dns-provider/index.ts b/packages/ui/certd-server/src/plugins/plugin-huawei/dns-provider/index.ts index 593c605fa..987952d31 100644 --- a/packages/ui/certd-server/src/plugins/plugin-huawei/dns-provider/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-huawei/dns-provider/index.ts @@ -1 +1 @@ -import './huawei-dns-provider.js'; +import "./huawei-dns-provider.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-huawei/index.ts b/packages/ui/certd-server/src/plugins/plugin-huawei/index.ts index f6e792f07..d13101c41 100644 --- a/packages/ui/certd-server/src/plugins/plugin-huawei/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-huawei/index.ts @@ -1,3 +1,3 @@ -export * from './access/index.js'; -export * from './dns-provider/index.js'; -export * from './plugins/index.js'; +export * from "./access/index.js"; +export * from "./dns-provider/index.js"; +export * from "./plugins/index.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-huawei/plugins/deploy-to-cdn/index.ts b/packages/ui/certd-server/src/plugins/plugin-huawei/plugins/deploy-to-cdn/index.ts index 9f04eefb5..9404da7ea 100644 --- a/packages/ui/certd-server/src/plugins/plugin-huawei/plugins/deploy-to-cdn/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-huawei/plugins/deploy-to-cdn/index.ts @@ -1,15 +1,15 @@ -import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from '@certd/pipeline'; -import { HuaweiAccess } from '../../access/index.js'; -import { CertInfo } from '@certd/plugin-cert'; -import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from '@certd/plugin-lib'; -import { resetLogConfigure } from '@certd/basic'; -import { CertApplyPluginNames} from '@certd/plugin-cert'; +import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; +import { HuaweiAccess } from "../../access/index.js"; +import { CertInfo } from "@certd/plugin-cert"; +import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from "@certd/plugin-lib"; +import { resetLogConfigure } from "@certd/basic"; +import { CertApplyPluginNames } from "@certd/plugin-cert"; @IsTaskPlugin({ - name: 'HauweiDeployCertToCDN', - title: '华为云-部署证书至CDN', - icon: 'svg:icon-huawei', + name: "HauweiDeployCertToCDN", + title: "华为云-部署证书至CDN", + icon: "svg:icon-huawei", group: pluginGroups.huawei.key, - desc: '', + desc: "", default: { strategy: { runStrategy: RunStrategy.SkipWhenSucceed, @@ -18,11 +18,11 @@ import { CertApplyPluginNames} from '@certd/plugin-cert'; }) export class HauweiDeployCertToCDN extends AbstractTaskPlugin { @TaskInput({ - title: '域名证书', - helper: '请选择前置任务输出的域名证书\n如果你选择使用ccm证书ID,则需要在[域名管理页面右上角开启SCM授权](https://console.huaweicloud.com/cdn/#/cdn/domain)', + title: "域名证书", + helper: "请选择前置任务输出的域名证书\n如果你选择使用ccm证书ID,则需要在[域名管理页面右上角开启SCM授权](https://console.huaweicloud.com/cdn/#/cdn/domain)", component: { - name: 'output-selector', - from: [...CertApplyPluginNames,'HauweiUploadToCCM'], + name: "output-selector", + from: [...CertApplyPluginNames, "HauweiUploadToCCM"], }, required: true, }) @@ -32,19 +32,19 @@ export class HauweiDeployCertToCDN extends AbstractTaskPlugin { certDomains!: string[]; @TaskInput({ - title: '企业项目ID', + title: "企业项目ID", helper: '华为云子账号必填,"all"表示查询所有项目', required: false, - value:"all" + value: "all", }) enterpriseProjectId!: string; @TaskInput({ - title: 'Access授权', - helper: '华为云授权AccessKeyId、AccessKeySecret', + title: "Access授权", + helper: "华为云授权AccessKeyId、AccessKeySecret", component: { - name: 'access-selector', - type: 'huawei', + name: "access-selector", + type: "huawei", }, required: true, }) @@ -52,87 +52,80 @@ export class HauweiDeployCertToCDN extends AbstractTaskPlugin { @TaskInput( createRemoteSelectInputDefine({ - title: 'CDN域名', - helper: '请选择域名或输入域名', - typeName: 'HauweiDeployCertToCDN', + title: "CDN域名", + helper: "请选择域名或输入域名", + typeName: "HauweiDeployCertToCDN", action: HauweiDeployCertToCDN.prototype.onGetDomainList.name, }) ) domains!: string[]; - - async execute(): Promise { if (!this.cert) { - throw new Error('域名证书不能为空'); + throw new Error("域名证书不能为空"); } - this.logger.info('开始部署证书到华为云cdn'); + this.logger.info("开始部署证书到华为云cdn"); const { cdn, client } = await this.getCdnClient(); - let httpsConfig = new cdn.HttpPutBody() - .withHttpsStatus('on') - .withCertificateType('server') + let httpsConfig = new cdn.HttpPutBody().withHttpsStatus("on").withCertificateType("server"); - if(typeof this.cert === 'object'){ - httpsConfig= httpsConfig.withCertificateSource(0) - .withCertificateName(this.appendTimeSuffix('certd')) - .withCertificateValue(this.cert.crt) - .withPrivateKey(this.cert.key); - }else{ - this.logger.info('使用已有域名证书:', this.cert); - httpsConfig= httpsConfig.withCertificateSource(2)//scm证书 - .withCertificateName(this.appendTimeSuffix('certd')) - .withScmCertificateId(this.cert) + if (typeof this.cert === "object") { + httpsConfig = httpsConfig.withCertificateSource(0).withCertificateName(this.appendTimeSuffix("certd")).withCertificateValue(this.cert.crt).withPrivateKey(this.cert.key); + } else { + this.logger.info("使用已有域名证书:", this.cert); + httpsConfig = httpsConfig + .withCertificateSource(2) //scm证书 + .withCertificateName(this.appendTimeSuffix("certd")) + .withScmCertificateId(this.cert); } const config = new cdn.Configs().withHttps(httpsConfig); const body = new cdn.ModifyDomainConfigRequestBody().withConfigs(config); if (!this.domains || this.domains.length === 0) { - throw new Error('您还未配置CDN域名'); + throw new Error("您还未配置CDN域名"); } - this.logger.info('部署域名:', JSON.stringify(this.domains)); + this.logger.info("部署域名:", JSON.stringify(this.domains)); for (const domain of this.domains) { - this.logger.info('部署到域名:', domain); + this.logger.info("部署到域名:", domain); - const queryReq = new cdn.ShowDomainDetailByNameRequest(domain); - if(this.enterpriseProjectId){ - queryReq.withEnterpriseProjectId(this.enterpriseProjectId) + const queryReq = new cdn.ShowDomainDetailByNameRequest(domain); + if (this.enterpriseProjectId) { + queryReq.withEnterpriseProjectId(this.enterpriseProjectId); } const domainDetail = await client.showDomainDetailByName(queryReq); //@ts-ignore - const status = domainDetail.domain.domainStatus || domainDetail.domain.domain_status + const status = domainDetail.domain.domainStatus || domainDetail.domain.domain_status; this.logger.info(`当前域名状态:`, status); - let ignoreError = false - if (status === 'offline') { - ignoreError = true + let ignoreError = false; + if (status === "offline") { + ignoreError = true; } - try{ + try { const req = new cdn.UpdateDomainFullConfigRequest().withDomainName(domain).withBody(body); - if(this.enterpriseProjectId){ - req.withEnterpriseProjectId(this.enterpriseProjectId) + if (this.enterpriseProjectId) { + req.withEnterpriseProjectId(this.enterpriseProjectId); } await client.updateDomainFullConfig(req); this.logger.info(`部署到域名${domain}完成:`); - }catch (e) { - if (ignoreError){ + } catch (e) { + if (ignoreError) { this.logger.warn(`部署到域名${domain}失败,由于其处于offline状态,忽略部署错误,继续执行:`, e); - }else{ - throw e + } else { + throw e; } } - } - this.logger.info('部署证书到华为云cdn完成'); + this.logger.info("部署证书到华为云cdn完成"); } async getCdnClient() { const access = await this.getAccess(this.accessId); - const { BasicCredentials } = await import('@huaweicloud/huaweicloud-sdk-core'); - const cdn = await import('@huaweicloud/huaweicloud-sdk-cdn/v2/public-api.js'); + const { BasicCredentials } = await import("@huaweicloud/huaweicloud-sdk-core"); + const cdn = await import("@huaweicloud/huaweicloud-sdk-cdn/v2/public-api.js"); //恢复华为云把log4j的config改了的问题 resetLogConfigure(); const credentials = new BasicCredentials().withAk(access.accessKeyId).withSk(access.accessKeySecret); - const client = cdn.CdnClient.newBuilder().withCredential(credentials).withEndpoint('https://cdn.myhuaweicloud.com').build(); + const client = cdn.CdnClient.newBuilder().withCredential(credentials).withEndpoint("https://cdn.myhuaweicloud.com").build(); return { client, cdn, @@ -148,7 +141,7 @@ export class HauweiDeployCertToCDN extends AbstractTaskPlugin { request.enterpriseProjectId = this.enterpriseProjectId || undefined; const result: any = await client.listDomains(request); if (!result || !result.domains || result.domains.length === 0) { - throw new Error('未找到CDN域名,您可以手动输入'); + throw new Error("未找到CDN域名,您可以手动输入"); } const domains = result.domains.map(domain => { diff --git a/packages/ui/certd-server/src/plugins/plugin-huawei/plugins/deploy-to-elb/index.ts b/packages/ui/certd-server/src/plugins/plugin-huawei/plugins/deploy-to-elb/index.ts index 16c80d97b..ec83ac2a9 100644 --- a/packages/ui/certd-server/src/plugins/plugin-huawei/plugins/deploy-to-elb/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-huawei/plugins/deploy-to-elb/index.ts @@ -1,15 +1,15 @@ -import { AbstractTaskPlugin, IsTaskPlugin, PageSearch, pluginGroups, RunStrategy, TaskInput } from '@certd/pipeline'; -import { HuaweiAccess } from '../../access/index.js'; -import { CertInfo } from '@certd/plugin-cert'; -import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from '@certd/plugin-lib'; -import { resetLogConfigure } from '@certd/basic'; -import { CertApplyPluginNames } from '@certd/plugin-cert'; +import { AbstractTaskPlugin, IsTaskPlugin, PageSearch, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; +import { HuaweiAccess } from "../../access/index.js"; +import { CertInfo } from "@certd/plugin-cert"; +import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from "@certd/plugin-lib"; +import { resetLogConfigure } from "@certd/basic"; +import { CertApplyPluginNames } from "@certd/plugin-cert"; @IsTaskPlugin({ - name: 'HauweiDeployCertToELB', - title: '华为云-部署证书至ELB负载均衡', - icon: 'svg:icon-huawei', + name: "HauweiDeployCertToELB", + title: "华为云-部署证书至ELB负载均衡", + icon: "svg:icon-huawei", group: pluginGroups.huawei.key, - desc: '', + desc: "", default: { strategy: { runStrategy: RunStrategy.SkipWhenSucceed, @@ -18,10 +18,10 @@ import { CertApplyPluginNames } from '@certd/plugin-cert'; }) export class HauweiDeployCertToELB extends AbstractTaskPlugin { @TaskInput({ - title: '域名证书', - helper: '请选择前置任务输出的域名证书\n如果你选择使用ccm证书ID,则需要在[域名管理页面右上角开启SCM授权](https://console.huaweicloud.com/cdn/#/cdn/domain)', + title: "域名证书", + helper: "请选择前置任务输出的域名证书\n如果你选择使用ccm证书ID,则需要在[域名管理页面右上角开启SCM授权](https://console.huaweicloud.com/cdn/#/cdn/domain)", component: { - name: 'output-selector', + name: "output-selector", from: [...CertApplyPluginNames], }, required: true, @@ -31,13 +31,12 @@ export class HauweiDeployCertToELB extends AbstractTaskPlugin { @TaskInput(createCertDomainGetterInputDefine({ props: { required: false } })) certDomains!: string[]; - @TaskInput({ - title: 'Access授权', - helper: '华为云授权AccessKeyId、AccessKeySecret', + title: "Access授权", + helper: "华为云授权AccessKeyId、AccessKeySecret", component: { - name: 'access-selector', - type: 'huawei', + name: "access-selector", + type: "huawei", }, required: true, }) @@ -45,9 +44,9 @@ export class HauweiDeployCertToELB extends AbstractTaskPlugin { @TaskInput( createRemoteSelectInputDefine({ - title: '项目ID', - helper: '请选择项目', - typeName: 'HauweiDeployCertToELB', + title: "项目ID", + helper: "请选择项目", + typeName: "HauweiDeployCertToELB", action: HauweiDeployCertToELB.prototype.onGetProjectList.name, single: true, }) @@ -56,41 +55,36 @@ export class HauweiDeployCertToELB extends AbstractTaskPlugin { @TaskInput( createRemoteSelectInputDefine({ - title: 'ELB已有证书', - helper: '请选择域名或输入域名', - typeName: 'HauweiDeployCertToELB', + title: "ELB已有证书", + helper: "请选择域名或输入域名", + typeName: "HauweiDeployCertToELB", action: HauweiDeployCertToELB.prototype.onGetCertList.name, search: true, }) ) certIds!: string[]; - - async execute(): Promise { if (!this.cert) { - throw new Error('域名证书不能为空'); + throw new Error("域名证书不能为空"); } - this.logger.info('开始部署证书到华为云ELB'); + this.logger.info("开始部署证书到华为云ELB"); const { elb, client } = await this.getElbClient(); for (const certId of this.certIds) { - this.logger.info('开始更新ELB证书,证书ID:' + certId); - let request = new elb.UpdateCertificateRequest(certId); + this.logger.info("开始更新ELB证书,证书ID:" + certId); + const request = new elb.UpdateCertificateRequest(certId); - const certificate = new elb.UpdateCertificateOption() - .withCertificate(this.cert.crt) - .withPrivateKey(this.cert.key); - const body = new elb.UpdateCertificateRequestBody() - .withCertificate(certificate); + const certificate = new elb.UpdateCertificateOption().withCertificate(this.cert.crt).withPrivateKey(this.cert.key); + const body = new elb.UpdateCertificateRequestBody().withCertificate(certificate); request.withBody(body); await client.updateCertificate(request); - this.logger.info('更新ELB证书完成,证书ID:' + certId ); + this.logger.info("更新ELB证书完成,证书ID:" + certId); await this.ctx.utils.sleep(2000); } - this.logger.info('更新ELB证书完成'); + this.logger.info("更新ELB证书完成"); } async onGetProjectList() { @@ -98,7 +92,7 @@ export class HauweiDeployCertToELB extends AbstractTaskPlugin { const projects = await access.getProjectList(); return projects.map(project => { return { - value: project.id+"_"+project.name, + value: project.id + "_" + project.name, label: `${project.name}(${project.id})`, }; }); @@ -106,18 +100,21 @@ export class HauweiDeployCertToELB extends AbstractTaskPlugin { async getElbClient() { if (!this.projectId) { - throw new Error('项目ID不能为空'); + throw new Error("项目ID不能为空"); } const access = await this.getAccess(this.accessId); - const { BasicCredentials } = await import('@huaweicloud/huaweicloud-sdk-core'); - const elb = await import('@huaweicloud/huaweicloud-sdk-elb/v3/public-api.js'); + const { BasicCredentials } = await import("@huaweicloud/huaweicloud-sdk-core"); + const elb = await import("@huaweicloud/huaweicloud-sdk-elb/v3/public-api.js"); //恢复华为云把log4j的config改了的问题 resetLogConfigure(); const projectArr = this.projectId.split("_"); const projectId = projectArr[0]; const region = projectArr[1]; const credentials: any = new BasicCredentials().withAk(access.accessKeyId).withSk(access.accessKeySecret).withProjectId(projectId); - const client = elb.ElbClient.newBuilder().withCredential(credentials).withEndpoint('https://elb.'+region+'.myhuaweicloud.com').build(); + const client = elb.ElbClient.newBuilder() + .withCredential(credentials) + .withEndpoint("https://elb." + region + ".myhuaweicloud.com") + .build(); return { client, elb, @@ -133,15 +130,15 @@ export class HauweiDeployCertToELB extends AbstractTaskPlugin { } const result = await client.listCertificates(request); if (!result || !result.certificates || result.certificates.length === 0) { - throw new Error('未找到ELB证书,您可以手动输入'); + throw new Error("未找到ELB证书,您可以手动输入"); } const certs = result.certificates.map(cert => { return { value: cert.id, //@ts-ignore - label: cert.id + '(' + cert.common_name + ')', - domain: cert.domain.split(','), + label: cert.id + "(" + cert.common_name + ")", + domain: cert.domain.split(","), }; }); diff --git a/packages/ui/certd-server/src/plugins/plugin-huawei/plugins/deploy-to-obs/index.ts b/packages/ui/certd-server/src/plugins/plugin-huawei/plugins/deploy-to-obs/index.ts index 83bff77f6..147c4c656 100644 --- a/packages/ui/certd-server/src/plugins/plugin-huawei/plugins/deploy-to-obs/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-huawei/plugins/deploy-to-obs/index.ts @@ -4,11 +4,11 @@ import { CertApplyPluginNames, CertInfo } from "@certd/plugin-cert"; import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from "@certd/plugin-lib"; @IsTaskPlugin({ - name: 'HauweiDeployCertToOBS', - title: '华为云-部署证书至OBS', - icon: 'svg:icon-huawei', + name: "HauweiDeployCertToOBS", + title: "华为云-部署证书至OBS", + icon: "svg:icon-huawei", group: pluginGroups.huawei.key, - desc: '', + desc: "", default: { strategy: { runStrategy: RunStrategy.SkipWhenSucceed, @@ -17,11 +17,11 @@ import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from }) export class HauweiDeployCertToOBS extends AbstractTaskPlugin { @TaskInput({ - title: '域名证书', - helper: '请选择前置任务输出的域名证书\n如果你选择使用ccm证书ID,则需要在[域名管理页面右上角开启SCM授权](https://console.huaweicloud.com/cdn/#/cdn/domain)', + title: "域名证书", + helper: "请选择前置任务输出的域名证书\n如果你选择使用ccm证书ID,则需要在[域名管理页面右上角开启SCM授权](https://console.huaweicloud.com/cdn/#/cdn/domain)", component: { - name: 'output-selector', - from: [...CertApplyPluginNames,'HauweiUploadToCCM'], + name: "output-selector", + from: [...CertApplyPluginNames, "HauweiUploadToCCM"], }, required: true, }) @@ -31,21 +31,20 @@ export class HauweiDeployCertToOBS extends AbstractTaskPlugin { certDomains!: string[]; @TaskInput({ - title: 'Access授权', - helper: '华为云授权AccessKeyId、AccessKeySecret', + title: "Access授权", + helper: "华为云授权AccessKeyId、AccessKeySecret", component: { - name: 'access-selector', - type: 'huawei', + name: "access-selector", + type: "huawei", }, required: true, }) accessId!: string; - @TaskInput( createRemoteSelectInputDefine({ - title: '存储桶', - helper: '请选择存储桶', + title: "存储桶", + helper: "请选择存储桶", action: HauweiDeployCertToOBS.prototype.onGetBucketList.name, }) ) @@ -53,50 +52,46 @@ export class HauweiDeployCertToOBS extends AbstractTaskPlugin { @TaskInput( createRemoteSelectInputDefine({ - title: '自定义域名', - helper: '请选择自定义域名', + title: "自定义域名", + helper: "请选择自定义域名", action: HauweiDeployCertToOBS.prototype.onGetDomainList.name, - watches: ['bucketList'], + watches: ["bucketList"], }) ) domainList!: string[]; - - async execute(): Promise { if (!this.cert) { - throw new Error('域名证书不能为空'); + throw new Error("域名证书不能为空"); } - this.logger.info('开始部署证书到华为云obs'); + this.logger.info("开始部署证书到华为云obs"); for (const domainStr of this.domainList) { - const [location, bucket,domain] = domainStr.split('_'); + const [location, bucket, domain] = domainStr.split("_"); await this.setDomainCert({ location, bucket, domain, - cert: this.cert + cert: this.cert, }); } - this.logger.info('部署证书到华为云cdn完成'); + this.logger.info("部署证书到华为云cdn完成"); } - checkRet(ret: any){ - if (ret?.CommonMsg?.Status>300){ - + checkRet(ret: any) { + if (ret?.CommonMsg?.Status > 300) { throw new Error(`【${ret?.CommonMsg?.Code}】${ret?.CommonMsg?.Message}`); } } - - async getObsClient(opts:{region?:string,bucket?:string} = {}) { - const { region,bucket } = opts; - const regionStr = region? `${region}.`: 'cn-north-4.'; - const bucketStr = bucket? `${bucket}.` : ''; + async getObsClient(opts: { region?: string; bucket?: string } = {}) { + const { region, bucket } = opts; + const regionStr = region ? `${region}.` : "cn-north-4."; + const bucketStr = bucket ? `${bucket}.` : ""; const access = await this.getAccess(this.accessId); - const sdk = await import('esdk-obs-nodejs'); + const sdk = await import("esdk-obs-nodejs"); const obsClient = new sdk.default({ // 推荐通过环境变量获取AKSK,这里也可以使用其他外部引入方式传入,如果使用硬编码可能会存在泄露风险 // 您可以登录访问管理控制台获取访问密钥AK/SK,获取方式请参见https://support.huaweicloud.com/usermanual-ca/ca_01_0003.html @@ -107,81 +102,81 @@ export class HauweiDeployCertToOBS extends AbstractTaskPlugin { // endpoint填写Bucket对应的Endpoint, 这里以华北-北京四为例,其他地区请按实际情况填写 server: `https://${bucketStr}obs.${regionStr}myhuaweicloud.com`, }); - return obsClient + return obsClient; } async onGetBucketList(data: any) { const obsClient = await this.getObsClient(); const res = await obsClient.listBuckets({ - QueryLocation:true - }) + QueryLocation: true, + }); - this.checkRet(res) + this.checkRet(res); - const list = res.InterfaceResult?.Buckets + const list = res.InterfaceResult?.Buckets; if (!list || list.length === 0) { - return [] + return []; } return list.map(item => { return { value: `${item.Location}_${item.BucketName}`, - label: `${item.BucketName}<${item.Location}>`, + label: `${item.BucketName}<${item.Location}>`, }; }); } - async onGetDomainList(data:any) { + async onGetDomainList(data: any) { if (!this.bucketList || this.bucketList.length === 0) { - return [] + return []; } - const optionList = [] + const optionList = []; for (const item of this.bucketList) { - const [location,bucket] = item.split('_') + const [location, bucket] = item.split("_"); - const obsClient = await this.getObsClient({region:location}); + const obsClient = await this.getObsClient({ region: location }); const res = await obsClient.getBucketCustomDomain({ Bucket: bucket, - }) - this.checkRet(res) + }); + this.checkRet(res); - const list = res.InterfaceResult?.Domains + const list = res.InterfaceResult?.Domains; if (!list || list.length === 0) { - continue + continue; } - const options= list.map(item => { + const options = list.map(item => { return { value: `${location}_${bucket}_${item.DomainName}`, - label: `${item.DomainName}<${bucket}_${location}>`, + label: `${item.DomainName}<${bucket}_${location}>`, domain: item.DomainName, }; }); - optionList.push(...options) + optionList.push(...options); } - return this.ctx.utils.options.buildGroupOptions( optionList,this.certDomains) + return this.ctx.utils.options.buildGroupOptions(optionList, this.certDomains); } - async setDomainCert(opts:{location:string,bucket:string,domain:string,cert:string|CertInfo}){ - const {location,bucket,domain,cert} = opts - const obsClient = await this.getObsClient({region:location}); - const params:any = { + async setDomainCert(opts: { location: string; bucket: string; domain: string; cert: string | CertInfo }) { + const { location, bucket, domain, cert } = opts; + const obsClient = await this.getObsClient({ region: location }); + const params: any = { Bucket: bucket, DomainName: domain, - DomainBody:{ - Name: this.buildCertName( domain), - } + DomainBody: { + Name: this.buildCertName(domain), + }, }; - if (typeof cert === 'string'){ - params.DomainBody.CertificateId= cert - }else{ - params.DomainBody.Certificate= cert.crt - params.DomainBody.PrivateKey = cert.key + if (typeof cert === "string") { + params.DomainBody.CertificateId = cert; + } else { + params.DomainBody.Certificate = cert.crt; + params.DomainBody.PrivateKey = cert.key; } - const res = await obsClient.setBucketCustomDomain(params) - this.checkRet(res) + const res = await obsClient.setBucketCustomDomain(params); + this.checkRet(res); } } new HauweiDeployCertToOBS(); diff --git a/packages/ui/certd-server/src/plugins/plugin-huawei/plugins/index.ts b/packages/ui/certd-server/src/plugins/plugin-huawei/plugins/index.ts index 596d341a8..1af465e1b 100644 --- a/packages/ui/certd-server/src/plugins/plugin-huawei/plugins/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-huawei/plugins/index.ts @@ -1,4 +1,4 @@ -export * from './deploy-to-cdn/index.js' -export * from './upload-to-ccm/index.js' -export * from './deploy-to-obs/index.js' -export * from './deploy-to-elb/index.js' +export * from "./deploy-to-cdn/index.js"; +export * from "./upload-to-ccm/index.js"; +export * from "./deploy-to-obs/index.js"; +export * from "./deploy-to-elb/index.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-huawei/plugins/upload-to-ccm/ccm-client.ts b/packages/ui/certd-server/src/plugins/plugin-huawei/plugins/upload-to-ccm/ccm-client.ts index 7d58dcf68..7a478d8e8 100644 --- a/packages/ui/certd-server/src/plugins/plugin-huawei/plugins/upload-to-ccm/ccm-client.ts +++ b/packages/ui/certd-server/src/plugins/plugin-huawei/plugins/upload-to-ccm/ccm-client.ts @@ -12,12 +12,7 @@ export class HuaweiCcmClient { /** */ - importCertificate(req: { - name: string, - certificate: string, - private_key: string, - duplicate_check: boolean, - }) { + importCertificate(req: { name: string; certificate: string; private_key: string; duplicate_check: boolean }) { const options: any = { method: "POST", url: "/v3/scm/certificates/import", @@ -25,7 +20,7 @@ export class HuaweiCcmClient { queryParams: {}, contentType: "application/json", headers: { - "Content-Type": "application/json" + "Content-Type": "application/json", }, /** * name @@ -48,9 +43,8 @@ export class HuaweiCcmClient { * duplicate_check */ data: { - ...req - } - + ...req, + }, }; // @ts-ignore options["responseHeaders"] = ["X-Request-Id"]; diff --git a/packages/ui/certd-server/src/plugins/plugin-huawei/plugins/upload-to-ccm/index.ts b/packages/ui/certd-server/src/plugins/plugin-huawei/plugins/upload-to-ccm/index.ts index 840f52f75..b180639d3 100644 --- a/packages/ui/certd-server/src/plugins/plugin-huawei/plugins/upload-to-ccm/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-huawei/plugins/upload-to-ccm/index.ts @@ -4,13 +4,12 @@ import { CertApplyPluginNames, CertInfo } from "@certd/plugin-cert"; import { createCertDomainGetterInputDefine } from "@certd/plugin-lib"; import { resetLogConfigure } from "@certd/basic"; - @IsTaskPlugin({ - name: 'HauweiUploadToCCM', - title: '华为云-上传证书至CCM', - icon: 'svg:icon-huawei', + name: "HauweiUploadToCCM", + title: "华为云-上传证书至CCM", + icon: "svg:icon-huawei", group: pluginGroups.huawei.key, - desc: '上传证书到华为云云证书管理(CCM)', + desc: "上传证书到华为云云证书管理(CCM)", default: { strategy: { runStrategy: RunStrategy.SkipWhenSucceed, @@ -23,9 +22,9 @@ export class HauweiUploadToCCM extends AbstractTaskPlugin { helper: "请选择前置任务输出的域名证书", component: { name: "output-selector", - from: [...CertApplyPluginNames] + from: [...CertApplyPluginNames], }, - required: true + required: true, }) cert!: CertInfo; @@ -37,13 +36,13 @@ export class HauweiUploadToCCM extends AbstractTaskPlugin { helper: "华为云授权AccessKeyId、AccessKeySecret", component: { name: "access-selector", - type: "huawei" + type: "huawei", }, - required: true + required: true, }) accessId!: string; @TaskOutput({ - title: '华为云CertId', + title: "华为云CertId", }) huaweiCertId!: string; @@ -55,7 +54,7 @@ export class HauweiUploadToCCM extends AbstractTaskPlugin { name: this.appendTimeSuffix("certd"), certificate: this.cert.crt, private_key: this.cert.key, - duplicate_check: false + duplicate_check: false, }); this.huaweiCertId = res.certificate_id; this.logger.info(`上传证书到华为云ccm完成,certificate_id:${this.huaweiCertId}`); @@ -66,17 +65,20 @@ export class HauweiUploadToCCM extends AbstractTaskPlugin { const { BasicCredentials } = await import("@huaweicloud/huaweicloud-sdk-core"); const { ClientBuilder } = await import("@huaweicloud/huaweicloud-sdk-core/ClientBuilder.js"); //@ts-ignore - const {HuaweiCcmClient} = await import("./ccm-client.js") + const { HuaweiCcmClient } = await import("./ccm-client.js"); //恢复华为云把log4j的config改了的问题 resetLogConfigure(); const credentials = new BasicCredentials().withAk(access.accessKeyId).withSk(access.accessKeySecret); - const client = new ClientBuilder((hcClient) => { + const client = new ClientBuilder(hcClient => { return new HuaweiCcmClient(hcClient); - }).withCredential(credentials).withEndpoint("https://scm.cn-north-4.myhuaweicloud.com").build(); + }) + .withCredential(credentials) + .withEndpoint("https://scm.cn-north-4.myhuaweicloud.com") + .build(); return { - client + client, }; } } diff --git a/packages/ui/certd-server/src/plugins/plugin-jdcloud/access.ts b/packages/ui/certd-server/src/plugins/plugin-jdcloud/access.ts index e7ae541ac..bedffe896 100644 --- a/packages/ui/certd-server/src/plugins/plugin-jdcloud/access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-jdcloud/access.ts @@ -1,68 +1,65 @@ -import { AccessInput, BaseAccess, IsAccess, Pager, PageRes, PageSearch } from '@certd/pipeline'; -import { DomainRecord } from '@certd/plugin-lib'; +import { AccessInput, BaseAccess, IsAccess, Pager, PageRes, PageSearch } from "@certd/pipeline"; +import { DomainRecord } from "@certd/plugin-lib"; /** * 这个注解将注册一个授权配置 * 在certd的后台管理系统中,用户可以选择添加此类型的授权 */ @IsAccess({ - name: 'jdcloud', - title: '京东云', - desc: '', - icon: 'svg:icon-jdcloud', + name: "jdcloud", + title: "京东云", + desc: "", + icon: "svg:icon-jdcloud", order: 1, }) export class JDCloudAccess extends BaseAccess { - @AccessInput({ - title: 'AccessKeyID', + title: "AccessKeyID", component: { - placeholder: 'AccessKeyID', + placeholder: "AccessKeyID", }, helper: "[获取密钥](https://uc.jdcloud.com/account/accesskey)", required: true, }) - accessKeyId = ''; + accessKeyId = ""; @AccessInput({ - title: 'SecretAccessKey', + title: "SecretAccessKey", component: { - placeholder: 'SecretAccessKey', + placeholder: "SecretAccessKey", }, required: true, encrypt: true, }) - secretAccessKey = ''; - + secretAccessKey = ""; @AccessInput({ title: "测试", component: { name: "api-test", - action: "TestRequest" + action: "TestRequest", }, - helper: "点击测试接口是否正常" + helper: "点击测试接口是否正常", }) testRequest = true; - accessToken: { expiresAt: number, token: string } + accessToken: { expiresAt: number; token: string }; async onTestRequest() { await this.getDomainListPage({ pageNo: 1, pageSize: 1, }); - return "ok" + return "ok"; } - async getJDDomainService() { - const { JDDomainService } = await import("@certd/jdcloud") + const { JDDomainService } = await import("@certd/jdcloud"); const service = new JDDomainService({ credentials: { accessKeyId: this.accessKeyId, - secretAccessKey: this.secretAccessKey + secretAccessKey: this.secretAccessKey, }, - regionId: "cn-north-1" //地域信息,某个api调用可以单独传参regionId,如果不传则会使用此配置中的regionId + regionId: "cn-north-1", //地域信息,某个api调用可以单独传参regionId,如果不传则会使用此配置中的regionId }); return service; } @@ -70,12 +67,14 @@ export class JDCloudAccess extends BaseAccess { async getDomainListPage(req: PageSearch): Promise> { const pager = new Pager(req); const service = await this.getJDDomainService(); - const domainRes = await this.catchCall(() => service.describeDomains({ - domainName: req.searchKey, - pageNumber: pager.pageNo, - pageSize: pager.pageSize, - })) - let list = domainRes.result?.dataList || [] + const domainRes = await this.catchCall(() => + service.describeDomains({ + domainName: req.searchKey, + pageNumber: pager.pageNo, + pageSize: pager.pageSize, + }) + ); + let list = domainRes.result?.dataList || []; list = list.map((item: any) => ({ id: item.domainId, domain: item.domainName, @@ -85,15 +84,15 @@ export class JDCloudAccess extends BaseAccess { list, }; } - async catchCall(fn: () => Promise): Promise { + async catchCall(fn: () => Promise): Promise { try { return await fn(); } catch (e) { if (e.error) { - this.ctx.logger.error(JSON.stringify(e.error)) - throw new Error(JSON.stringify(e.error)) + this.ctx.logger.error(JSON.stringify(e.error)); + throw new Error(JSON.stringify(e.error)); } - throw e + throw e; } } } diff --git a/packages/ui/certd-server/src/plugins/plugin-jdcloud/dns-provider.ts b/packages/ui/certd-server/src/plugins/plugin-jdcloud/dns-provider.ts index 9b65b560e..f3ac9031a 100644 --- a/packages/ui/certd-server/src/plugins/plugin-jdcloud/dns-provider.ts +++ b/packages/ui/certd-server/src/plugins/plugin-jdcloud/dns-provider.ts @@ -13,13 +13,10 @@ import { JDCloudAccess } from "./access.js"; export class JDCloudDnsProvider extends AbstractDnsProvider { access!: JDCloudAccess; - async onInstance() { - this.access = this.ctx.access as JDCloudAccess + this.access = this.ctx.access as JDCloudAccess; } - - async createRecord(options: CreateRecordOptions): Promise { const { fullRecord, hostRecord, value, type, domain } = options; this.logger.info("添加域名解析:", fullRecord, value, domain); @@ -29,20 +26,20 @@ export class JDCloudDnsProvider extends AbstractDnsProvider { const domainRes = await service.describeDomains({ domainName: domain, pageNumber: 1, - pageSize: 10 - }) + pageSize: 10, + }); if (!domainRes.result?.dataList?.length) { - throw new Error(`域名${domain}在此京东云账号中不存在`) + throw new Error(`域名${domain}在此京东云账号中不存在`); } - const list = domainRes.result.dataList + const list = domainRes.result.dataList; - const found = list.find((item) => item.domainName === domain) + const found = list.find(item => item.domainName === domain); if (!found) { - throw new Error(`域名${domain}在此京东云账号中不存在`) + throw new Error(`域名${domain}在此京东云账号中不存在`); } - const domainId = found.id - this.logger.info("域名ID:", domainId) + const domainId = found.id; + this.logger.info("域名ID:", domainId); /** * hostRecord String True 主机记录 * hostValue String True 解析记录的值 @@ -54,19 +51,21 @@ export class JDCloudDnsProvider extends AbstractDnsProvider { * weight Integer False 解析记录的权重,目前支持权重的有:A/AAAA/CNAME/JNAME,A/AAAA权重范围:0-100、CNAME/JNAME权重范围:1-100。 * viewValue Integer True 解析线路的ID,请调用describeViewTree接口获取基础解 */ - const res = await this.access.catchCall(() => service.createResourceRecord({ - domainId: domainId, - req: { - hostRecord: hostRecord, - hostValue: value, - type: type, - ttl: 200, - viewValue: -1, - } - })) + const res = await this.access.catchCall(() => + service.createResourceRecord({ + domainId: domainId, + req: { + hostRecord: hostRecord, + hostValue: value, + type: type, + ttl: 200, + viewValue: -1, + }, + }) + ); return { recordId: res.result.dataList.id, - domainId: domainId + domainId: domainId, }; } @@ -74,10 +73,12 @@ export class JDCloudDnsProvider extends AbstractDnsProvider { const record = options.recordRes; const service = await this.getJDDomainService(); - await this.access.catchCall(() => service.deleteResourceRecord({ - domainId: record.domainId, - resourceRecordId: record.recordId - })) + await this.access.catchCall(() => + service.deleteResourceRecord({ + domainId: record.domainId, + resourceRecordId: record.recordId, + }) + ); } private async getJDDomainService() { @@ -87,7 +88,6 @@ export class JDCloudDnsProvider extends AbstractDnsProvider { async getDomainListPage(req: PageSearch): Promise> { return await this.access.getDomainListPage(req); } - } new JDCloudDnsProvider(); diff --git a/packages/ui/certd-server/src/plugins/plugin-jdcloud/index.ts b/packages/ui/certd-server/src/plugins/plugin-jdcloud/index.ts index 1d8d95735..74b6fbc93 100644 --- a/packages/ui/certd-server/src/plugins/plugin-jdcloud/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-jdcloud/index.ts @@ -1,3 +1,3 @@ -export * from './access.js'; -export * from './dns-provider.js'; -export * from './plugins/index.js'; +export * from "./access.js"; +export * from "./dns-provider.js"; +export * from "./plugins/index.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-jdcloud/plugins/index.ts b/packages/ui/certd-server/src/plugins/plugin-jdcloud/plugins/index.ts index 7571a96a4..fd8444b2e 100644 --- a/packages/ui/certd-server/src/plugins/plugin-jdcloud/plugins/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-jdcloud/plugins/index.ts @@ -1,3 +1,3 @@ -export * from './plugin-deploy-to-cdn.js' -export * from './plugin-update-cert.js' -export * from './plugin-upload-cert.js' +export * from "./plugin-deploy-to-cdn.js"; +export * from "./plugin-update-cert.js"; +export * from "./plugin-upload-cert.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-jdcloud/plugins/plugin-deploy-to-cdn.ts b/packages/ui/certd-server/src/plugins/plugin-jdcloud/plugins/plugin-deploy-to-cdn.ts index 3a944b39c..6cc77657c 100644 --- a/packages/ui/certd-server/src/plugins/plugin-jdcloud/plugins/plugin-deploy-to-cdn.ts +++ b/packages/ui/certd-server/src/plugins/plugin-jdcloud/plugins/plugin-deploy-to-cdn.ts @@ -12,9 +12,9 @@ import { JDCloudAccess } from "../access.js"; desc: "京东云内容分发网络", default: { strategy: { - runStrategy: RunStrategy.SkipWhenSucceed - } - } + runStrategy: RunStrategy.SkipWhenSucceed, + }, + }, }) export class JDCloudDeployToCDN extends AbstractTaskPlugin { @TaskInput({ @@ -22,42 +22,38 @@ export class JDCloudDeployToCDN extends AbstractTaskPlugin { helper: "请选择前置任务输出的域名证书", component: { name: "output-selector", - from: [...CertApplyPluginNames, "JDCloudUploadCert"] + from: [...CertApplyPluginNames, "JDCloudUploadCert"], }, - required: true + required: true, }) cert!: CertInfo | number; @TaskInput(createCertDomainGetterInputDefine({ props: { required: false } })) certDomains!: string[]; - @TaskInput({ title: "Access授权", helper: "京东云AccessKeyId、AccessKeySecret", component: { name: "access-selector", - type: "jdcloud" + type: "jdcloud", }, - required: true + required: true, }) accessId!: string; - @TaskInput( createRemoteSelectInputDefine({ title: "CDN加速域名", helper: "你在京东云上配置的CDN加速域名,比如:certd.docmirror.cn", action: JDCloudDeployToCDN.prototype.onGetDomainList.name, watches: ["certDomains", "accessId"], - required: true + required: true, }) ) domainName!: string | string[]; - - async onInstance() { - } + async onInstance() {} async execute(): Promise { this.logger.info("开始部署证书到京东云CDN"); @@ -71,16 +67,18 @@ export class JDCloudDeployToCDN extends AbstractTaskPlugin { this.logger.info(`开始上传证书`); const sslService = await this.getSslClient(access); - const res = await access.catchCall(() => sslService.uploadCert({ - // certName String True 证书名称 - // keyFile String True 私钥 - // certFile String True 证书 - // aliasName String False 证书别名 - certName: certName, - keyFile: certInfo.key, - certFile: certInfo.crt, - aliasName: certName - })); + const res = await access.catchCall(() => + sslService.uploadCert({ + // certName String True 证书名称 + // keyFile String True 私钥 + // certFile String True 证书 + // aliasName String False 证书别名 + certName: certName, + keyFile: certInfo.key, + certFile: certInfo.crt, + aliasName: certName, + }) + ); certId = res.result.certId; } @@ -107,7 +105,7 @@ export class JDCloudDeployToCDN extends AbstractTaskPlugin { certFrom: "ssl", sslCertId: certId, // 不用certId 方式,会报证书已存在错误,目前还没找到怎么查询重复证书 syncToSsl: false, - certName: certName + certName: certName, }); this.logger.info(`部署域名${domain}证书成功:${JSON.stringify(res)}`); await this.ctx.utils.sleep(2000); @@ -116,15 +114,14 @@ export class JDCloudDeployToCDN extends AbstractTaskPlugin { this.logger.info("部署完成"); } - async getClient(access: JDCloudAccess) { const { JDCdnService } = await import("@certd/jdcloud"); const service = new JDCdnService({ credentials: { accessKeyId: access.accessKeyId, - secretAccessKey: access.secretAccessKey + secretAccessKey: access.secretAccessKey, }, - regionId: "cn-north-1" //地域信息,某个api调用可以单独传参regionId,如果不传则会使用此配置中的regionId + regionId: "cn-north-1", //地域信息,某个api调用可以单独传参regionId,如果不传则会使用此配置中的regionId }); return service; } @@ -134,9 +131,9 @@ export class JDCloudDeployToCDN extends AbstractTaskPlugin { const service = new JDSslService({ credentials: { accessKeyId: access.accessKeyId, - secretAccessKey: access.secretAccessKey + secretAccessKey: access.secretAccessKey, }, - regionId: "cn-north-1" //地域信息,某个api调用可以单独传参regionId,如果不传则会使用此配置中的regionId + regionId: "cn-north-1", //地域信息,某个api调用可以单独传参regionId,如果不传则会使用此配置中的regionId }); return service; } @@ -152,10 +149,12 @@ export class JDCloudDeployToCDN extends AbstractTaskPlugin { * pageNumber Integer False 1 pageNumber,默认值1 * pageSize */ - const res = await access.catchCall(() => service.getDomainList({ - pageNumber: 1, - pageSize: 50 - })); + const res = await access.catchCall(() => + service.getDomainList({ + pageNumber: 1, + pageSize: 50, + }) + ); // @ts-ignore const list = res?.result?.domains; if (!list || list.length === 0) { @@ -165,7 +164,7 @@ export class JDCloudDeployToCDN extends AbstractTaskPlugin { return { value: item.domain, label: item.domain, - domain: item.domain + domain: item.domain, }; }); return optionsUtils.buildGroupOptions(options, this.certDomains); diff --git a/packages/ui/certd-server/src/plugins/plugin-jdcloud/plugins/plugin-update-cert.ts b/packages/ui/certd-server/src/plugins/plugin-jdcloud/plugins/plugin-update-cert.ts index c2d3cb4fe..febe4f805 100644 --- a/packages/ui/certd-server/src/plugins/plugin-jdcloud/plugins/plugin-update-cert.ts +++ b/packages/ui/certd-server/src/plugins/plugin-jdcloud/plugins/plugin-update-cert.ts @@ -5,11 +5,11 @@ import { optionsUtils } from "@certd/basic"; import { JDCloudAccess } from "../access.js"; @IsTaskPlugin({ - name: 'JDCloudUpdateCert', - title: '京东云-更新已有证书', - icon: 'svg:icon-jdcloud', + name: "JDCloudUpdateCert", + title: "京东云-更新已有证书", + icon: "svg:icon-jdcloud", group: pluginGroups.jdcloud.key, - desc: '更新SSL数字证书中的证书', + desc: "更新SSL数字证书中的证书", default: { strategy: { runStrategy: RunStrategy.SkipWhenSucceed, @@ -18,11 +18,11 @@ import { JDCloudAccess } from "../access.js"; }) export class JDCloudUpdateCert extends AbstractTaskPlugin { @TaskInput({ - title: '域名证书', - helper: '请选择前置任务输出的域名证书', + title: "域名证书", + helper: "请选择前置任务输出的域名证书", component: { - name: 'output-selector', - from: [...CertApplyPluginNames, 'JDCloudUploadCert'], + name: "output-selector", + from: [...CertApplyPluginNames, "JDCloudUploadCert"], }, required: true, }) @@ -31,38 +31,34 @@ export class JDCloudUpdateCert extends AbstractTaskPlugin { @TaskInput(createCertDomainGetterInputDefine({ props: { required: false } })) certDomains!: string[]; - @TaskInput({ - title: 'Access授权', - helper: '京东云AccessKeyId、AccessKeySecret', + title: "Access授权", + helper: "京东云AccessKeyId、AccessKeySecret", component: { - name: 'access-selector', - type: 'jdcloud', + name: "access-selector", + type: "jdcloud", }, required: true, }) accessId!: string; - - @TaskInput( createRemoteSelectInputDefine({ - title: '要更新的证书id', - helper: '您在京东云上已有的证书Id', + title: "要更新的证书id", + helper: "您在京东云上已有的证书Id", action: JDCloudUpdateCert.prototype.onGetCertList.name, - watches: ['certDomains', 'accessId'], + watches: ["certDomains", "accessId"], required: true, }) ) certIds!: string[]; - async onInstance() {} async execute(): Promise { - this.logger.info('开始部署证书到京东云CDN'); + this.logger.info("开始部署证书到京东云CDN"); const access = await this.getAccess(this.accessId); - const service = await this.getClient(access) + const service = await this.getClient(access); // let certId = this.cert // const certName = this.appendTimeSuffix("certd"); // if (typeof certId !== 'string') { @@ -82,42 +78,43 @@ export class JDCloudUpdateCert extends AbstractTaskPlugin { // certId = res.result.certId // } - const certInfo = this.cert as CertInfo + const certInfo = this.cert as CertInfo; for (const certId of this.certIds) { - this.logger.info(`开始更新证书:${certId}`) - const res = await access.catchCall(() => service.updateCert({ - /* + this.logger.info(`开始更新证书:${certId}`); + const res = await access.catchCall(() => + service.updateCert({ + /* @param {string} opts.certId - 证书Id @param {string} opts.certId - 证书ID @param {string} opts.keyFile - 私钥 @param {string} opts.certFile - 证书 @param {string} callback - callback */ - certId, - certFile: certInfo.crt, - keyFile:certInfo.key, - })) + certId, + certFile: certInfo.crt, + keyFile: certInfo.key, + }) + ); this.logger.info(`更新证书${certId}成功:${JSON.stringify(res)}`); - await this.ctx.utils.sleep(2000) + await this.ctx.utils.sleep(2000); } } - async getClient(access: JDCloudAccess) { - const {JDSslService} = await import("@certd/jdcloud") + const { JDSslService } = await import("@certd/jdcloud"); const service = new JDSslService({ credentials: { accessKeyId: access.accessKeyId, - secretAccessKey: access.secretAccessKey + secretAccessKey: access.secretAccessKey, }, - regionId: "cn-north-1" //地域信息,某个api调用可以单独传参regionId,如果不传则会使用此配置中的regionId + regionId: "cn-north-1", //地域信息,某个api调用可以单独传参regionId,如果不传则会使用此配置中的regionId }); return service; } async onGetCertList(data: any) { if (!this.accessId) { - throw new Error('请选择Access授权'); + throw new Error("请选择Access授权"); } const access = await this.getAccess(this.accessId); @@ -126,14 +123,16 @@ export class JDCloudUpdateCert extends AbstractTaskPlugin { * pageNumber Integer False 1 pageNumber,默认值1 * pageSize */ - const res = await access.catchCall(() => service.describeCerts({ - pageNumber: 1, - pageSize: 100, - })) + const res = await access.catchCall(() => + service.describeCerts({ + pageNumber: 1, + pageSize: 100, + }) + ); // @ts-ignore - const list = res?.result?.certListDetails + const list = res?.result?.certListDetails; if (!list || list.length === 0) { - throw new Error('找不到证书,您可以手动输入证书id'); + throw new Error("找不到证书,您可以手动输入证书id"); } const options = list.map((item: any) => { return { diff --git a/packages/ui/certd-server/src/plugins/plugin-jdcloud/plugins/plugin-upload-cert.ts b/packages/ui/certd-server/src/plugins/plugin-jdcloud/plugins/plugin-upload-cert.ts index e3077ee4b..667393094 100644 --- a/packages/ui/certd-server/src/plugins/plugin-jdcloud/plugins/plugin-upload-cert.ts +++ b/packages/ui/certd-server/src/plugins/plugin-jdcloud/plugins/plugin-upload-cert.ts @@ -10,9 +10,9 @@ import { JDCloudAccess } from "../access.js"; desc: "上传证书到SSL数字证书中心", default: { strategy: { - runStrategy: RunStrategy.SkipWhenSucceed - } - } + runStrategy: RunStrategy.SkipWhenSucceed, + }, + }, }) export class JDCloudUploadCert extends AbstractTaskPlugin { @TaskInput({ @@ -20,39 +20,36 @@ export class JDCloudUploadCert extends AbstractTaskPlugin { helper: "请选择前置任务输出的域名证书", component: { name: "output-selector", - from: [...CertApplyPluginNames, "JDCloudUploadCert"] + from: [...CertApplyPluginNames, "JDCloudUploadCert"], }, - required: true + required: true, }) cert!: CertInfo | string; - @TaskInput({ title: "Access授权", helper: "京东云AccessKeyId、AccessKeySecret", component: { name: "access-selector", - type: "jdcloud" + type: "jdcloud", }, - required: true + required: true, }) accessId!: string; - @TaskInput({ title: "证书名称前缀", helper: "证书形成,默认为certd", - required: false + required: false, }) certName!: string; @TaskOutput({ - title: "上传成功后的京东云CertId" + title: "上传成功后的京东云CertId", }) jdcloudCertId!: number; - async onInstance() { - } + async onInstance() {} async execute(): Promise { this.logger.info("开始上传证书到京东云数字证书中心"); @@ -61,17 +58,19 @@ export class JDCloudUploadCert extends AbstractTaskPlugin { const service = await this.getClient(access); const certInfo = this.cert as CertInfo; - const res = await access.catchCall(() => service.uploadCert({ - /* + const res = await access.catchCall(() => + service.uploadCert({ + /* @param {string} opts.certName - 证书名称 @param {string} opts.keyFile - 私钥 @param {string} opts.certFile - 证书 @param {string} [opts.aliasName] - 证书别名 optional */ - certName: this.appendTimeSuffix(this.certName || "certd"), - certFile: certInfo.crt, - keyFile: certInfo.key - })); + certName: this.appendTimeSuffix(this.certName || "certd"), + certFile: certInfo.crt, + keyFile: certInfo.key, + }) + ); this.jdcloudCertId = res.result.certId; this.logger.info(`上传证书成功:${JSON.stringify(res)}`); } @@ -81,9 +80,9 @@ export class JDCloudUploadCert extends AbstractTaskPlugin { const service = new JDSslService({ credentials: { accessKeyId: access.accessKeyId, - secretAccessKey: access.secretAccessKey + secretAccessKey: access.secretAccessKey, }, - regionId: "cn-north-1" //地域信息,某个api调用可以单独传参regionId,如果不传则会使用此配置中的regionId + regionId: "cn-north-1", //地域信息,某个api调用可以单独传参regionId,如果不传则会使用此配置中的regionId }); return service; } diff --git a/packages/ui/certd-server/src/plugins/plugin-ksyun/access.ts b/packages/ui/certd-server/src/plugins/plugin-ksyun/access.ts index 20c5d5d70..8293b7ab4 100644 --- a/packages/ui/certd-server/src/plugins/plugin-ksyun/access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-ksyun/access.ts @@ -1,6 +1,6 @@ -import {AccessInput, BaseAccess, IsAccess} from "@certd/pipeline"; -import {KsyunClient} from './client.js' -import {CertInfo} from "@certd/plugin-cert"; +import { AccessInput, BaseAccess, IsAccess } from "@certd/pipeline"; +import { KsyunClient } from "./client.js"; +import { CertInfo } from "@certd/plugin-cert"; /** */ @@ -8,60 +8,57 @@ import {CertInfo} from "@certd/plugin-cert"; name: "ksyun", title: "金山云授权", desc: "", - icon: "svg:icon-ksyun" + icon: "svg:icon-ksyun", }) export class KsyunAccess extends BaseAccess { - @AccessInput({ - title: 'AccessKeyID', + title: "AccessKeyID", component: { - placeholder: 'AccessKeyID', + placeholder: "AccessKeyID", }, helper: "[获取密钥](https://uc.console.ksyun.com/pro/iam/#/set/keyManage)", required: true, }) - accessKeyId = ''; + accessKeyId = ""; @AccessInput({ - title: 'AccessKeySecret', + title: "AccessKeySecret", component: { - placeholder: 'AccessKeySecret', + placeholder: "AccessKeySecret", }, required: true, encrypt: true, }) - accessKeySecret = ''; - + accessKeySecret = ""; @AccessInput({ title: "测试", component: { name: "api-test", - action: "TestRequest" + action: "TestRequest", }, - helper: "点击测试接口是否正常" + helper: "点击测试接口是否正常", }) testRequest = true; async onTestRequest() { - const client = await this.getCdnClient() - await this.getCertList({client}) - return "ok" + const client = await this.getCdnClient(); + await this.getCertList({ client }); + return "ok"; } - - async getCertList(opts?:{client:KsyunClient,pageNo?:number;pageSize?:number}) { + async getCertList(opts?: { client: KsyunClient; pageNo?: number; pageSize?: number }) { const res = await opts.client.doRequest({ action: "GetCertificates", version: "2016-09-01", - method:"POST", - url:"/2016-09-01/cert/GetCertificates", - data:{ - PageNum:opts?.pageNo || 1, - PageSize: opts?.pageSize || 30 - } - }) - this.ctx.logger.info(res) - return res + method: "POST", + url: "/2016-09-01/cert/GetCertificates", + data: { + PageNum: opts?.pageNo || 1, + PageSize: opts?.pageSize || 30, + }, + }); + this.ctx.logger.info(res); + return res; } /** @@ -71,58 +68,52 @@ export class KsyunAccess extends BaseAccess { * PrivateKey * @param opts */ - async updateCert(opts:{ - client:KsyunClient, - certId:string, - certName:string, - cert:CertInfo - }){ + async updateCert(opts: { client: KsyunClient; certId: string; certName: string; cert: CertInfo }) { const res = await opts.client.doRequest({ action: "SetCertificate", version: "2016-09-01", - method:"POST", - url:"/2016-09-01/cert/SetCertificate", - data:{ + method: "POST", + url: "/2016-09-01/cert/SetCertificate", + data: { CertificateId: opts.certId, CertificateName: opts.certName, ServerCertificate: opts.cert.crt, - PrivateKey: opts.cert.key - } - }) - this.ctx.logger.info(res) - return res + PrivateKey: opts.cert.key, + }, + }); + this.ctx.logger.info(res); + return res; } - async getCert(opts:{client:KsyunClient,certId:string}){ + async getCert(opts: { client: KsyunClient; certId: string }) { const res = await opts.client.doRequest({ action: "GetCertificates", version: "2016-09-01", - method:"POST", - url:"/2016-09-01/cert/GetCertificates", - data:{ + method: "POST", + url: "/2016-09-01/cert/GetCertificates", + data: { CertificateId: opts.certId, - } - }) - this.ctx.logger.info(res) - const list = res.Certificates + }, + }); + this.ctx.logger.info(res); + const list = res.Certificates; if (list.length > 0) { - return list[0] + return list[0]; } - throw new Error(`未找到证书:${opts.certId}`) + throw new Error(`未找到证书:${opts.certId}`); } async getCdnClient() { return new KsyunClient({ accessKeyId: this.accessKeyId, secretAccessKey: this.accessKeySecret, - region: 'cn-beijing-6', - service: 'cdn', - endpoint: 'cdn.api.ksyun.com', + region: "cn-beijing-6", + service: "cdn", + endpoint: "cdn.api.ksyun.com", logger: this.ctx.logger, - http: this.ctx.http - }) + http: this.ctx.http, + }); } } - new KsyunAccess(); diff --git a/packages/ui/certd-server/src/plugins/plugin-ksyun/client.ts b/packages/ui/certd-server/src/plugins/plugin-ksyun/client.ts index 27bf7952f..19bfabea4 100644 --- a/packages/ui/certd-server/src/plugins/plugin-ksyun/client.ts +++ b/packages/ui/certd-server/src/plugins/plugin-ksyun/client.ts @@ -1,53 +1,50 @@ -import crypto from 'crypto'; -import querystring from 'querystring' -import {HttpClient, HttpRequestConfig, ILogger} from "@certd/basic"; +import crypto from "crypto"; +import querystring from "querystring"; +import { HttpClient, HttpRequestConfig, ILogger } from "@certd/basic"; export class KsyunClient { - accessKeyId: string; secretAccessKey: string; region: string; service: string; endpoint: string; logger: ILogger; - http: HttpClient - constructor(opts:{accessKeyId:string; secretAccessKey:string; region?:string; service :string;endpoint :string,logger:ILogger,http:HttpClient}) { + http: HttpClient; + constructor(opts: { accessKeyId: string; secretAccessKey: string; region?: string; service: string; endpoint: string; logger: ILogger; http: HttpClient }) { this.accessKeyId = opts.accessKeyId; this.secretAccessKey = opts.secretAccessKey; - this.region = opts.region || 'cn-beijing-6'; + this.region = opts.region || "cn-beijing-6"; this.service = opts.service; - this.endpoint =opts.endpoint + this.endpoint = opts.endpoint; this.logger = opts.logger; this.http = opts.http; } - - async doRequest(opts: {action:string;version:string} &HttpRequestConfig){ - const config = this.signRequest({ - method: opts.method || 'GET', - url: opts.url || '/2016-09-01/domain/GetCdnDomains', + async doRequest(opts: { action: string; version: string } & HttpRequestConfig) { + const config = this.signRequest({ + method: opts.method || "GET", + url: opts.url || "/2016-09-01/domain/GetCdnDomains", baseURL: `https://${this.endpoint}`, params: opts.params, headers: { - 'X-Action': opts.action, - 'X-Version': opts.version + "X-Action": opts.action, + "X-Version": opts.version, }, - data: opts.data + data: opts.data, }); - try{ + try { return await this.http.request({ ...config, - data: opts.data - }) - }catch (e) { - this.logger.error(e.request) - if (e.response?.data?.Error?.Message){ - throw new Error(e.response?.data?.Error?.Message) + data: opts.data, + }); + } catch (e) { + this.logger.error(e.request); + if (e.response?.data?.Error?.Message) { + throw new Error(e.response?.data?.Error?.Message); } - throw e + throw e; } - } /** @@ -58,31 +55,31 @@ export class KsyunClient { signRequest(config) { // 确保有必要的配置 if (!this.accessKeyId || !this.secretAccessKey) { - throw new Error('AccessKeyId and SecretAccessKey are required'); + throw new Error("AccessKeyId and SecretAccessKey are required"); } // 设置默认值 - config.method = config.method || 'GET'; + config.method = config.method || "GET"; config.headers = config.headers || {}; // 获取当前时间并设置 X-Amz-Date const requestDate = this.getRequestDate(); - config.headers['x-amz-date'] = requestDate; + config.headers["x-amz-date"] = requestDate; // 处理不同的请求方法 - let canonicalQueryString = ''; - let hashedPayload = this.hashPayload(config.data || ''); + let canonicalQueryString = ""; + let hashedPayload = this.hashPayload(config.data || ""); - if (config.method.toUpperCase() === 'GET') { + if (config.method.toUpperCase() === "GET") { // GET 请求 - 参数在 URL 中 - const urlParts = config.url.split('?'); + const urlParts = config.url.split("?"); const path = urlParts[0]; - const query = urlParts[1] || ''; + const query = urlParts[1] || ""; // 合并现有查询参数和额外参数 const queryParams = { ...querystring.parse(query), - ...(config.params || {}) + ...(config.params || {}), }; // 生成规范查询字符串 @@ -91,8 +88,8 @@ export class KsyunClient { config.params = {}; // 清空 params,因为已经合并到 URL 中 } else { // POST/PUT 等请求 - 参数在 body 中 - canonicalQueryString = ''; - if (config.data && typeof config.data === 'object') { + canonicalQueryString = ""; + if (config.data && typeof config.data === "object") { // 如果 data 是对象,转换为 JSON 字符串 config.data = JSON.stringify(config.data); hashedPayload = this.hashPayload(config.data); @@ -100,13 +97,7 @@ export class KsyunClient { } // 生成规范请求 - const canonicalRequest = this.createCanonicalRequest( - config.method, - config.url, - canonicalQueryString, - config.headers, - hashedPayload - ); + const canonicalRequest = this.createCanonicalRequest(config.method, config.url, canonicalQueryString, config.headers, hashedPayload); // 生成签名字符串 const credentialScope = this.createCredentialScope(requestDate); @@ -117,11 +108,7 @@ export class KsyunClient { // 生成 Authorization 头 const signedHeaders = this.getSignedHeaders(config.headers); - const authorizationHeader = this.createAuthorizationHeader( - credentialScope, - signedHeaders, - signature - ); + const authorizationHeader = this.createAuthorizationHeader(credentialScope, signedHeaders, signature); // 添加 Authorization 头 config.headers.Authorization = authorizationHeader; @@ -136,11 +123,11 @@ export class KsyunClient { getRequestDate() { const now = new Date(); const year = now.getUTCFullYear(); - const month = String(now.getUTCMonth() + 1).padStart(2, '0'); - const day = String(now.getUTCDate()).padStart(2, '0'); - const hours = String(now.getUTCHours()).padStart(2, '0'); - const minutes = String(now.getUTCMinutes()).padStart(2, '0'); - const seconds = String(now.getUTCSeconds()).padStart(2, '0'); + const month = String(now.getUTCMonth() + 1).padStart(2, "0"); + const day = String(now.getUTCDate()).padStart(2, "0"); + const hours = String(now.getUTCHours()).padStart(2, "0"); + const minutes = String(now.getUTCMinutes()).padStart(2, "0"); + const seconds = String(now.getUTCSeconds()).padStart(2, "0"); return `${year}${month}${day}T${hours}${minutes}${seconds}Z`; } @@ -151,10 +138,10 @@ export class KsyunClient { * @returns {string} 哈希后的16进制字符串 */ hashPayload(payload) { - if (typeof payload !== 'string') { - payload = ''; + if (typeof payload !== "string") { + payload = ""; } - return crypto.createHash('sha256').update(payload).digest('hex').toLowerCase(); + return crypto.createHash("sha256").update(payload).digest("hex").toLowerCase(); } /** @@ -177,7 +164,7 @@ export class KsyunClient { const sortedKeys = Object.keys(encodedParams).sort(); // 构建查询字符串 - return sortedKeys.map(key => `${key}=${encodedParams[key]}`).join('&'); + return sortedKeys.map(key => `${key}=${encodedParams[key]}`).join("&"); } /** @@ -186,9 +173,7 @@ export class KsyunClient { * @returns {string} 编码后的字符串 */ uriEncode(str) { - return encodeURIComponent(str) - .replace(/[^A-Za-z0-9\-_.~]/g, c => - '%' + c.charCodeAt(0).toString(16).toUpperCase()); + return encodeURIComponent(str).replace(/[^A-Za-z0-9\-_.~]/g, c => "%" + c.charCodeAt(0).toString(16).toUpperCase()); } /** @@ -202,20 +187,13 @@ export class KsyunClient { */ createCanonicalRequest(method, url, queryString, headers, hashedPayload) { // 获取规范 URI - const urlObj = new URL(url, 'http://dummy.com'); // 使用虚拟基础 URL 来解析路径 - const canonicalUri = this.uriEncodePath(urlObj.pathname) || '/'; + const urlObj = new URL(url, "http://dummy.com"); // 使用虚拟基础 URL 来解析路径 + const canonicalUri = this.uriEncodePath(urlObj.pathname) || "/"; // 获取规范 headers 和 signed headers const { canonicalHeaders, signedHeaders } = this.createCanonicalHeaders(headers); - return [ - method.toUpperCase(), - canonicalUri, - queryString, - canonicalHeaders, - signedHeaders, - hashedPayload - ].join('\n'); + return [method.toUpperCase(), canonicalUri, queryString, canonicalHeaders, signedHeaders, hashedPayload].join("\n"); } /** @@ -225,7 +203,10 @@ export class KsyunClient { */ uriEncodePath(path) { // 分割路径为各个部分,分别编码 - return path.split('/').map(part => this.uriEncode(part)).join('/'); + return path + .split("/") + .map(part => this.uriEncode(part)) + .join("/"); } /** @@ -235,15 +216,15 @@ export class KsyunClient { */ createCanonicalHeaders(headers) { // 处理 headers - const headerMap:any = {}; + const headerMap: any = {}; // 标准化 headers for (const key in headers) { if (headers.hasOwnProperty(key)) { const lowerKey = key.toLowerCase(); - let value = headers[key] + let value = headers[key]; if (value) { - value = value.toString().replace(/\s+/g, ' ').trim(); + value = value.toString().replace(/\s+/g, " ").trim(); headerMap[lowerKey] = value; } } @@ -251,21 +232,21 @@ export class KsyunClient { // 确保 host 和 x-amz-date 存在 if (!headerMap.host) { - const url = headers.host ||this.endpoint || 'cdn.api.ksyun.com'; // 默认值 - headerMap.host = url.replace(/^https?:\/\//, '').split('/')[0]; + const url = headers.host || this.endpoint || "cdn.api.ksyun.com"; // 默认值 + headerMap.host = url.replace(/^https?:\/\//, "").split("/")[0]; } // 按 header 名称排序 const sortedHeaderNames = Object.keys(headerMap).sort(); // 构建规范 headers - let canonicalHeaders = ''; + let canonicalHeaders = ""; for (const name of sortedHeaderNames) { canonicalHeaders += `${name}:${headerMap[name]}\n`; } // 构建 signed headers - const signedHeaders = sortedHeaderNames.join(';'); + const signedHeaders = sortedHeaderNames.join(";"); return { canonicalHeaders, signedHeaders }; } @@ -286,7 +267,7 @@ export class KsyunClient { * @returns {string} 信任状范围字符串 */ createCredentialScope(requestDate) { - const date = requestDate.split('T')[0]; + const date = requestDate.split("T")[0]; return `${date}/${this.region}/${this.service}/aws4_request`; } @@ -298,18 +279,10 @@ export class KsyunClient { * @returns {string} 签名字符串 */ createStringToSign(requestDate, credentialScope, canonicalRequest) { - const algorithm = 'AWS4-HMAC-SHA256'; - const hashedCanonicalRequest = crypto.createHash('sha256') - .update(canonicalRequest) - .digest('hex') - .toLowerCase(); + const algorithm = "AWS4-HMAC-SHA256"; + const hashedCanonicalRequest = crypto.createHash("sha256").update(canonicalRequest).digest("hex").toLowerCase(); - return [ - algorithm, - requestDate, - credentialScope, - hashedCanonicalRequest - ].join('\n'); + return [algorithm, requestDate, credentialScope, hashedCanonicalRequest].join("\n"); } /** @@ -319,13 +292,13 @@ export class KsyunClient { * @returns {string} 签名值 */ calculateSignature(requestDate, stringToSign) { - const date = requestDate.split('T')[0]; + const date = requestDate.split("T")[0]; const kDate = this.hmac(`AWS4${this.secretAccessKey}`, date); const kRegion = this.hmac(kDate, this.region); const kService = this.hmac(kRegion, this.service); - const kSigning = this.hmac(kService, 'aws4_request'); + const kSigning = this.hmac(kService, "aws4_request"); - return this.hmac(kSigning, stringToSign, 'hex'); + return this.hmac(kSigning, stringToSign, "hex"); } /** @@ -336,7 +309,7 @@ export class KsyunClient { * @returns {string|Buffer} HMAC 结果 */ hmac(key, data, encoding = null) { - const hmac = crypto.createHmac('sha256', key); + const hmac = crypto.createHmac("sha256", key); hmac.update(data); return encoding ? hmac.digest(encoding) : hmac.digest(); } @@ -352,6 +325,3 @@ export class KsyunClient { return `AWS4-HMAC-SHA256 Credential=${this.accessKeyId}/${credentialScope}, SignedHeaders=${signedHeaders}, Signature=${signature}`; } } - - - diff --git a/packages/ui/certd-server/src/plugins/plugin-ksyun/plugins/index.ts b/packages/ui/certd-server/src/plugins/plugin-ksyun/plugins/index.ts index 705339de6..a77684b4b 100644 --- a/packages/ui/certd-server/src/plugins/plugin-ksyun/plugins/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-ksyun/plugins/index.ts @@ -1 +1 @@ -import "./plugin-refresh-cert.js" +import "./plugin-refresh-cert.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-ksyun/plugins/plugin-refresh-cert.ts b/packages/ui/certd-server/src/plugins/plugin-ksyun/plugins/plugin-refresh-cert.ts index 1c443a680..3bc7dddd0 100644 --- a/packages/ui/certd-server/src/plugins/plugin-ksyun/plugins/plugin-refresh-cert.ts +++ b/packages/ui/certd-server/src/plugins/plugin-ksyun/plugins/plugin-refresh-cert.ts @@ -1,15 +1,7 @@ -import { - AbstractTaskPlugin, - IsTaskPlugin, - Pager, - PageSearch, - pluginGroups, - RunStrategy, - TaskInput -} from "@certd/pipeline"; -import {CertApplyPluginNames, CertInfo} from "@certd/plugin-cert"; -import {createCertDomainGetterInputDefine, createRemoteSelectInputDefine} from "@certd/plugin-lib"; -import {KsyunAccess} from "../access.js"; +import { AbstractTaskPlugin, IsTaskPlugin, Pager, PageSearch, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; +import { CertApplyPluginNames, CertInfo } from "@certd/plugin-cert"; +import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from "@certd/plugin-lib"; +import { KsyunAccess } from "../access.js"; @IsTaskPlugin({ //命名规范,插件类型+功能(就是目录plugin-demo中的demo),大写字母开头,驼峰命名 @@ -23,9 +15,9 @@ import {KsyunAccess} from "../access.js"; default: { //默认值配置照抄即可 strategy: { - runStrategy: RunStrategy.SkipWhenSucceed - } - } + runStrategy: RunStrategy.SkipWhenSucceed, + }, + }, }) //类名规范,跟上面插件名称(name)一致 export class KsyunRefreshCDNCert extends AbstractTaskPlugin { @@ -35,8 +27,8 @@ export class KsyunRefreshCDNCert extends AbstractTaskPlugin { helper: "请选择前置任务输出的域名证书", component: { name: "output-selector", - from: [...CertApplyPluginNames] - } + from: [...CertApplyPluginNames], + }, // required: true, // 必填 }) cert!: CertInfo; @@ -49,9 +41,9 @@ export class KsyunRefreshCDNCert extends AbstractTaskPlugin { title: "金山云授权", component: { name: "access-selector", - type: "ksyun" //固定授权类型 + type: "ksyun", //固定授权类型 }, - required: true //必填 + required: true, //必填 }) accessId!: string; // @@ -62,14 +54,13 @@ export class KsyunRefreshCDNCert extends AbstractTaskPlugin { helper: "要更新的金山云CDN证书id,如果这里没有,请先给cdn域名手动绑定一次证书", action: KsyunRefreshCDNCert.prototype.onGetCertList.name, pager: false, - search: false + search: false, }) ) certList!: string[]; //插件实例化时执行的方法 - async onInstance() { - } + async onInstance() {} //插件执行方法 async execute(): Promise { @@ -81,14 +72,14 @@ export class KsyunRefreshCDNCert extends AbstractTaskPlugin { const oldCert = await access.getCert({ client, - certId:certId - }) + certId: certId, + }); await access.updateCert({ client, certId: certId, certName: oldCert.CertificateName, - cert: this.cert + cert: this.cert, }); this.logger.info(`----------- 更新证书${certId}成功`); } @@ -100,17 +91,14 @@ export class KsyunRefreshCDNCert extends AbstractTaskPlugin { const access = await this.getAccess(this.accessId); const client = await access.getCdnClient(); - const pager = new Pager(data) - const res = await access.getCertList({client, - pageNo: pager.pageNo , - pageSize: pager.pageSize - }) - const list = res.Certificates + const pager = new Pager(data); + const res = await access.getCertList({ client, pageNo: pager.pageNo, pageSize: pager.pageSize }); + const list = res.Certificates; if (!list || list.length === 0) { throw new Error("没有找到证书,请先在控制台手动上传一次证书"); } - const total = res.TotalCount + const total = res.TotalCount; /** * certificate-id @@ -121,14 +109,14 @@ export class KsyunRefreshCDNCert extends AbstractTaskPlugin { return { label: `${item.CertificateName}<${item.CertificateId}-${item.ConfigDomainNames}>`, value: item.CertificateId, - domain: item.ConfigDomainNames + domain: item.ConfigDomainNames, }; }); return { list: this.ctx.utils.options.buildGroupOptions(options, this.certDomains), total: total, pageNo: pager.pageNo, - pageSize: pager.pageSize + pageSize: pager.pageSize, }; } } diff --git a/packages/ui/certd-server/src/plugins/plugin-lib/aliyun/access/aliesa-access.ts b/packages/ui/certd-server/src/plugins/plugin-lib/aliyun/access/aliesa-access.ts index b2b0053da..6c4732459 100644 --- a/packages/ui/certd-server/src/plugins/plugin-lib/aliyun/access/aliesa-access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-lib/aliyun/access/aliesa-access.ts @@ -43,14 +43,13 @@ export class AliesaAccess extends BaseAccess { }) region = ""; - - @AccessInput({ + @AccessInput({ title: "测试", component: { name: "api-test", - action: "TestRequest" + action: "TestRequest", }, - helper: "点击测试接口是否正常" + helper: "点击测试接口是否正常", }) testRequest = true; @@ -59,51 +58,50 @@ export class AliesaAccess extends BaseAccess { pageNo: 1, pageSize: 1, }); - return "ok" + return "ok"; } - - async getEsaClient(){ - const access: AliesaAccess = this - const aliAccess = await this.ctx.accessService.getById(access.accessId) as AliyunAccess - const endpoint = `esa.${access.region}.aliyuncs.com` - return aliAccess.getClient(endpoint) + async getEsaClient() { + const access: AliesaAccess = this; + const aliAccess = (await this.ctx.accessService.getById(access.accessId)) as AliyunAccess; + const endpoint = `esa.${access.region}.aliyuncs.com`; + return aliAccess.getClient(endpoint); } - async getDomainListPage(req: PageSearch): Promise> { - const pager = new Pager(req) - const client = await this.getEsaClient() - const ret = await client.doRequest({ - // 接口名称 - action: "ListSites", - // 接口版本 - version: "2024-09-10", - // 接口协议 - protocol: "HTTPS", - // 接口 HTTP 方法 - method: "GET", - authType: "AK", - style: "RPC", - data: { - query: { - SiteName: req.searchKey, - // ["SiteSearchType"] = "exact"; - SiteSearchType: "fuzzy", - AccessType: "NS", - PageSize: pager.pageSize, - PageNumber: pager.pageNo, - } - } - }) - const list = ret.Sites?.map(item => ({ - domain: item.SiteName, - id: item.SiteId, - })) - return { - list: list || [], - total: ret.TotalCount, - } - } + async getDomainListPage(req: PageSearch): Promise> { + const pager = new Pager(req); + const client = await this.getEsaClient(); + const ret = await client.doRequest({ + // 接口名称 + action: "ListSites", + // 接口版本 + version: "2024-09-10", + // 接口协议 + protocol: "HTTPS", + // 接口 HTTP 方法 + method: "GET", + authType: "AK", + style: "RPC", + data: { + query: { + SiteName: req.searchKey, + // ["SiteSearchType"] = "exact"; + SiteSearchType: "fuzzy", + AccessType: "NS", + PageSize: pager.pageSize, + PageNumber: pager.pageNo, + }, + }, + }); + const list = ret.Sites?.map(item => ({ + domain: item.SiteName, + id: item.SiteId, + })); + return { + list: list || [], + total: ret.TotalCount, + }; + } } new AliesaAccess(); diff --git a/packages/ui/certd-server/src/plugins/plugin-lib/aliyun/access/alioss-access.ts b/packages/ui/certd-server/src/plugins/plugin-lib/aliyun/access/alioss-access.ts index ee312941e..69c63ef7a 100644 --- a/packages/ui/certd-server/src/plugins/plugin-lib/aliyun/access/alioss-access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-lib/aliyun/access/alioss-access.ts @@ -27,7 +27,7 @@ export class AliossAccess extends BaseAccess { vModel: "value", type: "access", typeName: "alioss", - action: AliossAccess.prototype.onGetRegionList.name + action: AliossAccess.prototype.onGetRegionList.name, }, required: true, }) @@ -49,8 +49,7 @@ export class AliossAccess extends BaseAccess { }) bucket!: string; - - onGetRegionList(){ + onGetRegionList() { return { list: [ { value: "oss-cn-hangzhou", label: "华东1(杭州)" }, @@ -82,8 +81,8 @@ export class AliossAccess extends BaseAccess { { value: "oss-eu-west-1", label: "英国(伦敦)" }, { value: "oss-me-east-1", label: "阿联酋(迪拜)①" }, { value: "oss-rg-china-mainland", label: "无地域属性(中国内地)" }, - ] - } + ], + }; } async onGetBucketList() { diff --git a/packages/ui/certd-server/src/plugins/plugin-lib/aliyun/access/aliyun-access.test.ts b/packages/ui/certd-server/src/plugins/plugin-lib/aliyun/access/aliyun-access.test.ts index f8713bc16..574d7e176 100644 --- a/packages/ui/certd-server/src/plugins/plugin-lib/aliyun/access/aliyun-access.test.ts +++ b/packages/ui/certd-server/src/plugins/plugin-lib/aliyun/access/aliyun-access.test.ts @@ -14,7 +14,7 @@ function createAccess(result: Record) { access.getStsClient = async () => ({ getCallerIdentity: async () => result, - }) as any; + } as any); return access; } diff --git a/packages/ui/certd-server/src/plugins/plugin-lib/aliyun/access/aliyun-access.ts b/packages/ui/certd-server/src/plugins/plugin-lib/aliyun/access/aliyun-access.ts index 1b7857458..33e76da51 100644 --- a/packages/ui/certd-server/src/plugins/plugin-lib/aliyun/access/aliyun-access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-lib/aliyun/access/aliyun-access.ts @@ -33,9 +33,9 @@ export class AliyunAccess extends BaseAccess { title: "测试", component: { name: "api-test", - action: "TestRequest" + action: "TestRequest", }, - helper: "点击测试接口是否正常" + helper: "点击测试接口是否正常", }) testRequest = true; @@ -44,23 +44,20 @@ export class AliyunAccess extends BaseAccess { return "ok"; } - async getStsClient() { - const StsClient = await import('@alicloud/sts-sdk'); + const StsClient = await import("@alicloud/sts-sdk"); // 配置凭证 const sts = new StsClient.default({ - endpoint: 'sts.aliyuncs.com', + endpoint: "sts.aliyuncs.com", accessKeyId: this.accessKeyId, accessKeySecret: this.accessKeySecret, }); - return sts + return sts; } - async getCallerIdentity() { - const sts = await this.getStsClient(); // 调用 GetCallerIdentity 接口 const result = await sts.getCallerIdentity(); @@ -79,22 +76,19 @@ export class AliyunAccess extends BaseAccess { valid: true, accountId: result.AccountId, arn: result.Arn, - userId: result.UserId + userId: result.UserId, }; } - getSslClient({ endpoint }: { endpoint: string }) { const client = new AliyunSslClient({ access: this, logger: this.ctx.logger, endpoint, }); - return client + return client; } - - getClient(endpoint: string) { return new AliyunClientV2({ access: this, diff --git a/packages/ui/certd-server/src/plugins/plugin-lib/aliyun/index.ts b/packages/ui/certd-server/src/plugins/plugin-lib/aliyun/index.ts index 7ee122d1a..37078eeb3 100644 --- a/packages/ui/certd-server/src/plugins/plugin-lib/aliyun/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-lib/aliyun/index.ts @@ -1,3 +1,3 @@ export * from "./access/index.js"; export * from "./lib/index.js"; -export * from "./utils/index.js"; \ No newline at end of file +export * from "./utils/index.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-lib/aliyun/lib/ssl-client.ts b/packages/ui/certd-server/src/plugins/plugin-lib/aliyun/lib/ssl-client.ts index bc2169305..65703e116 100644 --- a/packages/ui/certd-server/src/plugins/plugin-lib/aliyun/lib/ssl-client.ts +++ b/packages/ui/certd-server/src/plugins/plugin-lib/aliyun/lib/ssl-client.ts @@ -38,7 +38,7 @@ export type CasCertId = { certIdentifier: string; certName: string; detail?: SimpleCertDetail; -} +}; export class AliyunSslClient { opts: AliyunSslClientOpts; logger: ILogger; @@ -100,10 +100,10 @@ export class AliyunSslClient { } async uploadCert(req: AliyunSslUploadCertReq) { - const {certId} = await this.uploadCertificate(req); - return certId; + const { certId } = await this.uploadCertificate(req); + return certId; } - async uploadCertificate(req: AliyunSslUploadCertReq) : Promise { + async uploadCertificate(req: AliyunSslUploadCertReq): Promise { const client = await this.getClient(); const params = { Name: req.name, @@ -125,13 +125,12 @@ export class AliyunSslClient { certId: ret.CertId, certName: req.name, certIdentifier: this.getCertIdentifier(ret.CertId), - detail:certReader.getSimpleDetail(), - } + detail: certReader.getSimpleDetail(), + }; } - async uploadCertOrGet(cert: CertInfo | number | CasCertId ) :Promise{ + async uploadCertOrGet(cert: CertInfo | number | CasCertId): Promise { if (typeof cert === "object") { - const casCert = cert as CasCertId; if (casCert.certId) { return casCert; @@ -143,20 +142,20 @@ export class AliyunSslClient { const certName = certReader.buildCertName(); const res = await this.uploadCertificate({ name: certName, - cert: certInfo + cert: certInfo, }); this.logger.info("上传证书成功", JSON.stringify(res)); - return res + return res; } //number类型 const certId = cert as any; - let certName: any = utils.string.appendTimeSuffix(certId); + const certName: any = utils.string.appendTimeSuffix(certId); const certIdentifier = this.getCertIdentifier(certId); return { certId, certIdentifier, certName, - } + }; } async getResourceList(req: AliyunSslGetResourceListReq) { @@ -237,18 +236,18 @@ export class AliyunSslClient { return region; } - getCertDomains(cert: CertInfo | number | CasCertId): string[]{ - const casCert = cert as CasCertId; - const certInfo = cert as CertInfo; - if (casCert.certId) { - if (!casCert.detail){ - throw new Error('未获取到证书域名列表,请尝试强制重新运行一下流水线'); - } - return casCert.detail?.domains || []; - }else if (certInfo.crt){ - return new CertReader(certInfo).getSimpleDetail().domains || []; - }else{ - throw new Error('未获取到证书域名列表,请尝试强制重新运行一下流水线'); + getCertDomains(cert: CertInfo | number | CasCertId): string[] { + const casCert = cert as CasCertId; + const certInfo = cert as CertInfo; + if (casCert.certId) { + if (!casCert.detail) { + throw new Error("未获取到证书域名列表,请尝试强制重新运行一下流水线"); } + return casCert.detail?.domains || []; + } else if (certInfo.crt) { + return new CertReader(certInfo).getSimpleDetail().domains || []; + } else { + throw new Error("未获取到证书域名列表,请尝试强制重新运行一下流水线"); + } } } diff --git a/packages/ui/certd-server/src/plugins/plugin-lib/aliyun/utils/index.ts b/packages/ui/certd-server/src/plugins/plugin-lib/aliyun/utils/index.ts index 4985f5a27..180fb8101 100644 --- a/packages/ui/certd-server/src/plugins/plugin-lib/aliyun/utils/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-lib/aliyun/utils/index.ts @@ -2,31 +2,27 @@ import dayjs from "dayjs"; import { CertInfo, CertReader } from "@certd/plugin-cert"; import { AliyunSslClient } from "../lib/index.js"; -export const ZoneOptions = [{ value: 'cn-hangzhou' }]; +export const ZoneOptions = [{ value: "cn-hangzhou" }]; export function appendTimeSuffix(name: string) { if (name == null) { - name = 'certd'; + name = "certd"; } - return name + '-' + dayjs().format('YYYYMMDD-HHmmss'); + return name + "-" + dayjs().format("YYYYMMDD-HHmmss"); } export function checkRet(ret: any) { if (ret.Code != null) { - throw new Error('执行失败:' + ret.Message); + throw new Error("执行失败:" + ret.Message); } } - -export async function getAliyunCertId(opts:{ - cert: string | CertInfo, - sslClient: AliyunSslClient, -}) { +export async function getAliyunCertId(opts: { cert: string | CertInfo; sslClient: AliyunSslClient }) { const { cert, sslClient } = opts; let certId: any = cert; let certName: any = CertReader.appendTimeSuffix("certd"); if (typeof cert === "object") { - const certReader = new CertReader(cert) - certName = certReader.buildCertName() + const certReader = new CertReader(cert); + certName = certReader.buildCertName(); certId = await sslClient.uploadCert({ name: certName, diff --git a/packages/ui/certd-server/src/plugins/plugin-lib/oss/api.ts b/packages/ui/certd-server/src/plugins/plugin-lib/oss/api.ts index 8dd46f783..c76af524e 100644 --- a/packages/ui/certd-server/src/plugins/plugin-lib/oss/api.ts +++ b/packages/ui/certd-server/src/plugins/plugin-lib/oss/api.ts @@ -34,7 +34,7 @@ export type OssClientContext = { }; export abstract class BaseOssClient implements IOssClient { - rootDir: string = ""; + rootDir = ""; access: A = null; logger: ILogger; utils: typeof utils; diff --git a/packages/ui/certd-server/src/plugins/plugin-lib/oss/impls/scp.ts b/packages/ui/certd-server/src/plugins/plugin-lib/oss/impls/scp.ts index d1e8af7a7..ab12766fb 100644 --- a/packages/ui/certd-server/src/plugins/plugin-lib/oss/impls/scp.ts +++ b/packages/ui/certd-server/src/plugins/plugin-lib/oss/impls/scp.ts @@ -2,6 +2,6 @@ import SftpOssClientImpl from "./sftp.js"; export default class ScpOssClientImpl extends SftpOssClientImpl { getUploaderType() { - return 'scp'; + return "scp"; } } diff --git a/packages/ui/certd-server/src/plugins/plugin-lib/oss/impls/sftp.ts b/packages/ui/certd-server/src/plugins/plugin-lib/oss/impls/sftp.ts index 0c7cff8fb..410835262 100644 --- a/packages/ui/certd-server/src/plugins/plugin-lib/oss/impls/sftp.ts +++ b/packages/ui/certd-server/src/plugins/plugin-lib/oss/impls/sftp.ts @@ -6,7 +6,7 @@ import { SftpAccess, SshAccess, SshClient } from "../../ssh/index.js"; export default class SftpOssClientImpl extends BaseOssClient { getUploaderType() { - return 'sftp'; + return "sftp"; } async download(fileName: string, savePath: string): Promise { const path = this.join(this.rootDir, fileName); diff --git a/packages/ui/certd-server/src/plugins/plugin-lib/qiniu/access.ts b/packages/ui/certd-server/src/plugins/plugin-lib/qiniu/access.ts index 7bf4ffb1e..1d7b81236 100644 --- a/packages/ui/certd-server/src/plugins/plugin-lib/qiniu/access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-lib/qiniu/access.ts @@ -23,7 +23,7 @@ export class QiniuAccess extends BaseAccess { }) secretKey!: string; - @AccessInput({ + @AccessInput({ title: "测试", component: { name: "api-test", @@ -38,18 +38,16 @@ export class QiniuAccess extends BaseAccess { return "ok"; } - - async getDomainList(req: PageSearch = {}) { - const qiniuClient = new QiniuClient({ - http: this.ctx.http, - access:this, - logger: this.ctx.logger, - }); - const url = `https://api.qiniu.com/domain?limit=${req.pageSize || 1000}`; - const res = await qiniuClient.doRequest(url, 'get'); - return res.domains||[] - } + const qiniuClient = new QiniuClient({ + http: this.ctx.http, + access: this, + logger: this.ctx.logger, + }); + const url = `https://api.qiniu.com/domain?limit=${req.pageSize || 1000}`; + const res = await qiniuClient.doRequest(url, "get"); + return res.domains || []; + } } new QiniuAccess(); diff --git a/packages/ui/certd-server/src/plugins/plugin-lib/tencent/access.ts b/packages/ui/certd-server/src/plugins/plugin-lib/tencent/access.ts index fff6933ea..515c04b01 100644 --- a/packages/ui/certd-server/src/plugins/plugin-lib/tencent/access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-lib/tencent/access.ts @@ -55,10 +55,8 @@ export class TencentAccess extends BaseAccess { vModel: "checked", }, }) - closeExpiresNotify: boolean = true; + closeExpiresNotify = true; - - @AccessInput({ title: "测试", component: { @@ -74,7 +72,6 @@ export class TencentAccess extends BaseAccess { return "ok"; } - isIntl() { return this.accountType === "intl"; } @@ -87,28 +84,27 @@ export class TencentAccess extends BaseAccess { return `${this.intlDomain()}${endpoint}`; } - async getCallerIdentity(){ + async getCallerIdentity() { const client = await this.getStsClient(); - // 调用 GetCallerIdentity 接口 + // 调用 GetCallerIdentity 接口 const result = await client.GetCallerIdentity(); - + this.ctx.logger.info("✅ 密钥有效!"); this.ctx.logger.info(` 账户ID: ${result.AccountId}`); this.ctx.logger.info(` ARN: ${result.Arn}`); this.ctx.logger.info(` 用户ID: ${result.UserId}`); - + return { valid: true, accountId: result.AccountId, arn: result.Arn, - userId: result.UserId + userId: result.UserId, }; } - - async getStsClient(){ - const sdk = await import('tencentcloud-sdk-nodejs/tencentcloud/services/sts/v20180813/index.js'); + async getStsClient() { + const sdk = await import("tencentcloud-sdk-nodejs/tencentcloud/services/sts/v20180813/index.js"); const StsClient = sdk.v20180813.Client; const clientConfig = { @@ -116,7 +112,7 @@ export class TencentAccess extends BaseAccess { secretId: this.secretId, secretKey: this.secretKey, }, - region: 'ap-shanghai', + region: "ap-shanghai", profile: { httpProfile: { endpoint: `sts.${this.intlDomain()}tencentcloudapi.com`, diff --git a/packages/ui/certd-server/src/plugins/plugin-namesilo/access.ts b/packages/ui/certd-server/src/plugins/plugin-namesilo/access.ts index 94deda6ba..9a5410bf7 100644 --- a/packages/ui/certd-server/src/plugins/plugin-namesilo/access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-namesilo/access.ts @@ -1,41 +1,39 @@ -import { IsAccess, AccessInput, BaseAccess, PageSearch, PageRes, Pager } from '@certd/pipeline'; -import { DomainRecord } from '@certd/plugin-lib'; -import { merge } from 'lodash-es'; -import qs from 'qs'; +import { IsAccess, AccessInput, BaseAccess, PageSearch, PageRes, Pager } from "@certd/pipeline"; +import { DomainRecord } from "@certd/plugin-lib"; +import { merge } from "lodash-es"; +import qs from "qs"; /** * 这个注解将注册一个授权配置 * 在certd的后台管理系统中,用户可以选择添加此类型的授权 */ @IsAccess({ - name: 'namesilo', - title: 'namesilo授权', - desc: '', - icon: 'simple-icons:namesilo', + name: "namesilo", + title: "namesilo授权", + desc: "", + icon: "simple-icons:namesilo", }) export class NamesiloAccess extends BaseAccess { /** * 授权属性配置 */ @AccessInput({ - title: 'API Key', + title: "API Key", component: { - placeholder: 'api key', + placeholder: "api key", }, - helper: - '前往 [获取API Key](https://www.namesilo.com/account/api-manager)\n不要勾选第一项(Generate key for read-only access)\n勾选第二项(Submitting this form...)\n然后点击Generate按钮', + helper: "前往 [获取API Key](https://www.namesilo.com/account/api-manager)\n不要勾选第一项(Generate key for read-only access)\n勾选第二项(Submitting this form...)\n然后点击Generate按钮", required: true, encrypt: true, }) - apiKey = ''; + apiKey = ""; - - @AccessInput({ + @AccessInput({ title: "测试", component: { name: "api-test", - action: "TestRequest" + action: "TestRequest", }, - helper: "点击测试接口是否正常" + helper: "点击测试接口是否正常", }) testRequest = true; @@ -44,57 +42,53 @@ export class NamesiloAccess extends BaseAccess { pageNo: 1, pageSize: 1, }); - return "ok" + return "ok"; } async getDomainListPage(req: PageSearch): Promise> { - - const pager = new Pager(req); - const ret =await this.doRequest('/api/listDomains', { - key:req.searchKey, - page: pager.pageNo, - pageSize: pager.pageSize, - }); - let list = ret.domains ||[] - // this.logger.info("获取域名列表成功:", ret); - list = list.map((item: any) => ({ - id: item.domain, - domain: item.domain, - })); - return { - total:ret.pager?.total || list.length, - list, - }; + const pager = new Pager(req); + const ret = await this.doRequest("/api/listDomains", { + key: req.searchKey, + page: pager.pageNo, + pageSize: pager.pageSize, + }); + let list = ret.domains || []; + // this.logger.info("获取域名列表成功:", ret); + list = list.map((item: any) => ({ + id: item.domain, + domain: item.domain, + })); + return { + total: ret.pager?.total || list.length, + list, + }; + } + + async doRequest(url: string, params: any = null) { + params = merge( + { + version: 1, + type: "json", + key: this.apiKey, + }, + params + ); + const qsString = qs.stringify(params); + url = `${url}?${qsString}`; + const res = await this.ctx.http.request({ + url, + baseURL: "https://www.namesilo.com", + method: "get", + headers: { + "Content-Type": "application/json", + }, + }); + + if (res.reply?.code !== "300" && res.reply?.code !== 300 && res.reply?.detail !== "success") { + throw new Error(`${JSON.stringify(res.reply.detail)}`); } - - - - async doRequest(url: string, params: any = null) { - params = merge( - { - version: 1, - type: 'json', - key: this.apiKey, - }, - params - ); - const qsString = qs.stringify(params); - url = `${url}?${qsString}`; - const res = await this.ctx.http.request({ - url, - baseURL: 'https://www.namesilo.com', - method: 'get', - headers: { - 'Content-Type': 'application/json', - }, - }); - - if (res.reply?.code !== '300' && res.reply?.code !== 300 && res.reply?.detail!=="success") { - throw new Error(`${JSON.stringify(res.reply.detail)}`); - } - return res.reply; - } - + return res.reply; + } } new NamesiloAccess(); diff --git a/packages/ui/certd-server/src/plugins/plugin-namesilo/dns-provider.ts b/packages/ui/certd-server/src/plugins/plugin-namesilo/dns-provider.ts index 09ec1d017..a20fa9c30 100644 --- a/packages/ui/certd-server/src/plugins/plugin-namesilo/dns-provider.ts +++ b/packages/ui/certd-server/src/plugins/plugin-namesilo/dns-provider.ts @@ -1,6 +1,6 @@ -import { PageRes, PageSearch } from '@certd/pipeline'; -import { AbstractDnsProvider, CreateRecordOptions, DomainRecord, IsDnsProvider, RemoveRecordOptions } from '@certd/plugin-cert'; -import { NamesiloAccess } from './access.js'; +import { PageRes, PageSearch } from "@certd/pipeline"; +import { AbstractDnsProvider, CreateRecordOptions, DomainRecord, IsDnsProvider, RemoveRecordOptions } from "@certd/plugin-cert"; +import { NamesiloAccess } from "./access.js"; export type NamesiloRecord = { record_id: string; @@ -8,12 +8,12 @@ export type NamesiloRecord = { // 这里通过IsDnsProvider注册一个dnsProvider @IsDnsProvider({ - name: 'namesilo', - title: 'namesilo', - desc: 'namesilo dns provider', - icon: 'simple-icons:namesilo', + name: "namesilo", + title: "namesilo", + desc: "namesilo dns provider", + icon: "simple-icons:namesilo", // 这里是对应的 cloudflare的access类型名称 - accessType: 'namesilo', + accessType: "namesilo", }) export class NamesiloDnsProvider extends AbstractDnsProvider { access!: NamesiloAccess; @@ -28,7 +28,6 @@ export class NamesiloDnsProvider extends AbstractDnsProvider { return true; } - /** * 创建dns解析记录,用于验证域名所有权 */ @@ -40,10 +39,10 @@ export class NamesiloDnsProvider extends AbstractDnsProvider { * domain: 'example.com' */ const { fullRecord, hostRecord, value, type, domain } = options; - this.logger.info('添加域名解析:', fullRecord, value, type, domain); + this.logger.info("添加域名解析:", fullRecord, value, type, domain); //domain=namesilo.com&rrtype=A&rrhost=test&rrvalue=55.55.55.55&rrttl=7207 - const record: any = await this.access.doRequest('/api/dnsAddRecord', { + const record: any = await this.access.doRequest("/api/dnsAddRecord", { domain, rrtype: type, rrhost: hostRecord, @@ -62,15 +61,15 @@ export class NamesiloDnsProvider extends AbstractDnsProvider { async removeRecord(options: RemoveRecordOptions): Promise { const { fullRecord, value } = options.recordReq; const record = options.recordRes; - this.logger.info('删除域名解析:', fullRecord, value); + this.logger.info("删除域名解析:", fullRecord, value); if (!record && !record.record_id) { - this.logger.info('record为空,不执行删除'); + this.logger.info("record为空,不执行删除"); return; } //这里调用删除txt dns解析记录接口 const recordId = record.record_id; - await this.access.doRequest('/api/dnsDeleteRecord', { + await this.access.doRequest("/api/dnsDeleteRecord", { domain: options.recordReq.domain, rrid: recordId, }); @@ -78,7 +77,7 @@ export class NamesiloDnsProvider extends AbstractDnsProvider { } async getDomainListPage(req: PageSearch): Promise> { - return await this.access.getDomainListPage(req); + return await this.access.getDomainListPage(req); } } diff --git a/packages/ui/certd-server/src/plugins/plugin-namesilo/index.ts b/packages/ui/certd-server/src/plugins/plugin-namesilo/index.ts index db899c717..d0bc76d38 100644 --- a/packages/ui/certd-server/src/plugins/plugin-namesilo/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-namesilo/index.ts @@ -1,2 +1,2 @@ -export * from './dns-provider.js'; -export * from './access.js'; +export * from "./dns-provider.js"; +export * from "./access.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-next-terminal/access.ts b/packages/ui/certd-server/src/plugins/plugin-next-terminal/access.ts index 9d243c442..50ff5bb8c 100644 --- a/packages/ui/certd-server/src/plugins/plugin-next-terminal/access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-next-terminal/access.ts @@ -1,45 +1,44 @@ -import { AccessInput, BaseAccess, IsAccess, Pager, PageRes, PageSearch } from '@certd/pipeline'; +import { AccessInput, BaseAccess, IsAccess, Pager, PageRes, PageSearch } from "@certd/pipeline"; /** * Next Terminal 授权配置 */ @IsAccess({ - name: 'nextTerminal', - title: 'Next Terminal 授权', - icon: 'clarity:plugin-line', - desc: '用于访问 Next Terminal API 的授权配置', + name: "nextTerminal", + title: "Next Terminal 授权", + icon: "clarity:plugin-line", + desc: "用于访问 Next Terminal API 的授权配置", }) export class NextTerminalAccess extends BaseAccess { - /** * Next Terminal 系统地址 */ @AccessInput({ - title: '系统地址', + title: "系统地址", component: { name: "a-input", allowClear: true, - placeholder: 'https://nt.example.com:8088', + placeholder: "https://nt.example.com:8088", }, required: true, }) - baseUrl = ''; + baseUrl = ""; /** * API 令牌 */ @AccessInput({ - title: 'API 令牌', - helper: '个人中心->授权令牌->创建令牌', + title: "API 令牌", + helper: "个人中心->授权令牌->创建令牌", component: { name: "a-input", allowClear: true, - placeholder: 'NT_xxxxx', + placeholder: "NT_xxxxx", }, required: true, encrypt: true, }) - apiToken = ''; + apiToken = ""; /** * 测试按钮 @@ -48,9 +47,9 @@ export class NextTerminalAccess extends BaseAccess { title: "测试", component: { name: "api-test", - action: "TestRequest" + action: "TestRequest", }, - helper: "点击测试接口是否正常" + helper: "点击测试接口是否正常", }) testRequest = true; @@ -69,66 +68,56 @@ export class NextTerminalAccess extends BaseAccess { this.ctx.logger.info(`获取 Next Terminal 证书列表,req:${JSON.stringify(req)}`); const pager = new Pager(req); const resp = await this.doRequest({ - url: '/api/admin/certificates/paging', - method: 'GET', + url: "/api/admin/certificates/paging", + method: "GET", params: { pageIndex: pager.pageNo, pageSize: pager.pageSize, - sortOrder: 'ascend', - sortField: 'notAfter', - } + sortOrder: "ascend", + sortField: "notAfter", + }, }); - + const total = resp?.total || 0; const list = resp?.items || []; - + return { total, - list + list, }; } /** * 更新证书 */ - async UpdateCertificate(req: { - certId: string; - commonName: string; - crt: string; - key: string; - }) { + async UpdateCertificate(req: { certId: string; commonName: string; crt: string; key: string }) { this.ctx.logger.info(`更新 Next Terminal 证书,certId:${req.certId}, commonName:${req.commonName}`); await this.doRequest({ url: `/api/admin/certificates/${req.certId}`, - method: 'PUT', + method: "PUT", data: { commonName: req.commonName, - type: 'imported', + type: "imported", id: req.certId, certificate: req.crt, privateKey: req.key, renewBefore: 30, - } + }, }); } /** * 通用 API 调用方法 */ - async doRequest(req: { - url: string; - method: 'GET' | 'POST' | 'PUT' | 'DELETE'; - params?: any; - data?: any; - }) { + async doRequest(req: { url: string; method: "GET" | "POST" | "PUT" | "DELETE"; params?: any; data?: any }) { const headers = { - 'X-Auth-Token': `${this.apiToken}`, - 'Content-Type': 'application/json', + "X-Auth-Token": `${this.apiToken}`, + "Content-Type": "application/json", }; const baseUrl = this.normalizeEndpoint(this.baseUrl); this.ctx.logger.debug(`Next Terminal API 请求: ${req.method} ${baseUrl}${req.url}`); - + const resp = await this.ctx.http.request({ url: req.url, baseURL: baseUrl, @@ -139,11 +128,11 @@ export class NextTerminalAccess extends BaseAccess { validateStatus: () => true, // 不自动抛出异常,让我们自己处理 }); - if (resp.code >0) { + if (resp.code > 0) { throw new Error(resp.message); - } - return resp + } + return resp; } } -new NextTerminalAccess() \ No newline at end of file +new NextTerminalAccess(); diff --git a/packages/ui/certd-server/src/plugins/plugin-next-terminal/index.ts b/packages/ui/certd-server/src/plugins/plugin-next-terminal/index.ts index c49d8bf88..21a066db2 100644 --- a/packages/ui/certd-server/src/plugins/plugin-next-terminal/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-next-terminal/index.ts @@ -1,2 +1,2 @@ -export * from './access.js'; -export * from './plugins/index.js'; +export * from "./access.js"; +export * from "./plugins/index.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-next-terminal/plugins/index.ts b/packages/ui/certd-server/src/plugins/plugin-next-terminal/plugins/index.ts index 55ab7cf74..b8237e4f8 100644 --- a/packages/ui/certd-server/src/plugins/plugin-next-terminal/plugins/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-next-terminal/plugins/index.ts @@ -1 +1 @@ -export * from './plugin-refresh-cert.js'; +export * from "./plugin-refresh-cert.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-next-terminal/plugins/plugin-refresh-cert.ts b/packages/ui/certd-server/src/plugins/plugin-next-terminal/plugins/plugin-refresh-cert.ts index fae67134f..69832e539 100644 --- a/packages/ui/certd-server/src/plugins/plugin-next-terminal/plugins/plugin-refresh-cert.ts +++ b/packages/ui/certd-server/src/plugins/plugin-next-terminal/plugins/plugin-refresh-cert.ts @@ -1,12 +1,12 @@ -import { AbstractTaskPlugin, IsTaskPlugin, PageSearch, pluginGroups, RunStrategy, TaskInput } from '@certd/pipeline'; -import { CertInfo } from '@certd/plugin-cert'; -import { CertReader, createRemoteSelectInputDefine } from '@certd/plugin-lib'; +import { AbstractTaskPlugin, IsTaskPlugin, PageSearch, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; +import { CertInfo } from "@certd/plugin-cert"; +import { CertReader, createRemoteSelectInputDefine } from "@certd/plugin-lib"; @IsTaskPlugin({ - name: 'NextTerminalRefreshCert', - title: 'NextTerminal-更新证书', - icon: 'clarity:plugin-line', - desc: '更新 Next Terminal 证书', + name: "NextTerminalRefreshCert", + title: "NextTerminal-更新证书", + icon: "clarity:plugin-line", + desc: "更新 Next Terminal 证书", group: pluginGroups.panel.key, default: { strategy: { @@ -19,11 +19,11 @@ export class NextTerminalRefreshCert extends AbstractTaskPlugin { * 证书选择 */ @TaskInput({ - title: '域名证书', - helper: '请选择前置任务输出的域名证书', + title: "域名证书", + helper: "请选择前置任务输出的域名证书", component: { - name: 'output-selector', - from: ['CertApply'], + name: "output-selector", + from: ["CertApply"], }, required: true, }) @@ -33,11 +33,11 @@ export class NextTerminalRefreshCert extends AbstractTaskPlugin { * Next Terminal 授权 */ @TaskInput({ - title: 'Next Terminal 授权', - helper: '选择 Next Terminal 授权配置', + title: "Next Terminal 授权", + helper: "选择 Next Terminal 授权配置", component: { - name: 'access-selector', - type: 'nextTerminal', + name: "access-selector", + type: "nextTerminal", }, required: true, }) @@ -48,10 +48,10 @@ export class NextTerminalRefreshCert extends AbstractTaskPlugin { */ @TaskInput( createRemoteSelectInputDefine({ - title: '选择证书', - helper: '选择要更新的 Next Terminal 证书(支持多选),如果这里没有列出,需要先前往控制台上传证书,之后就可以自动更新', + title: "选择证书", + helper: "选择要更新的 Next Terminal 证书(支持多选),如果这里没有列出,需要先前往控制台上传证书,之后就可以自动更新", action: NextTerminalRefreshCert.prototype.onGetCertList.name, - watches: ['accessId'], + watches: ["accessId"], required: true, single: false, }) @@ -63,10 +63,10 @@ export class NextTerminalRefreshCert extends AbstractTaskPlugin { */ async onGetCertList(req: PageSearch) { if (!this.accessId) { - throw new Error('请选择 Next Terminal 授权'); + throw new Error("请选择 Next Terminal 授权"); } - const access = await this.getAccess(this.accessId) as any; + const access = (await this.getAccess(this.accessId)) as any; const certList = await access.GetCertificateList(req); const options = certList.list.map((item: any) => { @@ -87,31 +87,31 @@ export class NextTerminalRefreshCert extends AbstractTaskPlugin { const { cert, accessId, certIds } = this; try { - const access = await this.getAccess(accessId) as any; - + const access = (await this.getAccess(accessId)) as any; + // 确保 certIds 是数组 const ids = Array.isArray(certIds) ? certIds : [certIds]; - + const certReader = new CertReader(cert); const mainDomain = certReader.getMainDomain(); - + for (const certId of ids) { this.logger.info(`更新 Next Terminal 证书: ${certId}`); - + await access.UpdateCertificate({ certId, commonName: mainDomain, crt: cert.crt, key: cert.key, }); - + this.logger.info(`证书 ${certId} 更新成功`); } - + this.logger.info(`成功更新 ${ids.length} 个 Next Terminal 证书`); } catch (e) { - this.logger.error('更新 Next Terminal 证书失败', e); + this.logger.error("更新 Next Terminal 证书失败", e); throw e; } } -} \ No newline at end of file +} diff --git a/packages/ui/certd-server/src/plugins/plugin-nginx-proxy-manager/access.ts b/packages/ui/certd-server/src/plugins/plugin-nginx-proxy-manager/access.ts index dde4511bb..df212ad79 100644 --- a/packages/ui/certd-server/src/plugins/plugin-nginx-proxy-manager/access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-nginx-proxy-manager/access.ts @@ -115,9 +115,7 @@ export class NginxProxyManagerAccess extends BaseAccess { } const withoutTrailingSlash = trimmed.replace(/\/+$/, ""); - return withoutTrailingSlash.endsWith("/api") - ? withoutTrailingSlash.slice(0, -4) - : withoutTrailingSlash; + return withoutTrailingSlash.endsWith("/api") ? withoutTrailingSlash.slice(0, -4) : withoutTrailingSlash; } private describeError(error: unknown, action: string): Error { @@ -158,10 +156,7 @@ export class NginxProxyManagerAccess extends BaseAccess { }); } - async getCertificatesWithExpand( - searchQuery?: string, - expand: string[] = [] - ): Promise { + async getCertificatesWithExpand(searchQuery?: string, expand: string[] = []): Promise { return await this.requestWithAuth({ method: "GET", url: "/nginx/certificates", @@ -174,15 +169,12 @@ export class NginxProxyManagerAccess extends BaseAccess { async findCustomCertificateByNiceName(niceName: string): Promise { const certificates = await this.getCertificates(niceName); - return certificates.find((certificate) => { + return certificates.find(certificate => { return certificate.provider === "other" && certificate.nice_name === niceName; }); } - async createCustomCertificate( - niceName: string, - domainNames: string[] = [] - ): Promise { + async createCustomCertificate(niceName: string, domainNames: string[] = []): Promise { return await this.requestWithAuth({ method: "POST", url: "/nginx/certificates", @@ -277,9 +269,7 @@ export class NginxProxyManagerAccess extends BaseAccess { } if (!this.totpSecret) { - throw new Error( - "登录失败:该 Nginx Proxy Manager 账号启用了 2FA,但未配置 totpSecret" - ); + throw new Error("登录失败:该 Nginx Proxy Manager 账号启用了 2FA,但未配置 totpSecret"); } let code: string; @@ -305,13 +295,7 @@ export class NginxProxyManagerAccess extends BaseAccess { return completedLogin.token; } - private async requestWithAuth(config: { - method: string; - url: string; - params?: Record; - data?: unknown; - headers?: Record; - }): Promise { + private async requestWithAuth(config: { method: string; url: string; params?: Record; data?: unknown; headers?: Record }): Promise { const token = await this.login(); const headers = { ...(config.headers ?? {}), @@ -324,13 +308,7 @@ export class NginxProxyManagerAccess extends BaseAccess { }); } - private async request(config: { - method: string; - url: string; - params?: Record; - data?: unknown; - headers?: Record; - }): Promise { + private async request(config: { method: string; url: string; params?: Record; data?: unknown; headers?: Record }): Promise { const action = `${config.method ?? "GET"} ${config.url ?? "/"}`; try { const response = await this.ctx.http.request({ @@ -340,9 +318,11 @@ export class NginxProxyManagerAccess extends BaseAccess { data: config.data, headers: config.headers, timeout: 30000, - httpsAgent: this.ignoreTls ? { - rejectUnauthorized: false - } : undefined, + httpsAgent: this.ignoreTls + ? { + rejectUnauthorized: false, + } + : undefined, }); return response; } catch (error) { @@ -352,9 +332,7 @@ export class NginxProxyManagerAccess extends BaseAccess { async onTestRequest(): Promise { const result = await this.verifyAccess(); - this.ctx.logger.info( - `Nginx Proxy Manager 授权验证成功,找到 ${result.proxyHostCount} 个代理主机` - ); + this.ctx.logger.info(`Nginx Proxy Manager 授权验证成功,找到 ${result.proxyHostCount} 个代理主机`); return `成功(${result.proxyHostCount} 个代理主机)`; } @@ -363,4 +341,4 @@ export class NginxProxyManagerAccess extends BaseAccess { } } -new NginxProxyManagerAccess(); \ No newline at end of file +new NginxProxyManagerAccess(); diff --git a/packages/ui/certd-server/src/plugins/plugin-nginx-proxy-manager/plugins/index.ts b/packages/ui/certd-server/src/plugins/plugin-nginx-proxy-manager/plugins/index.ts index c01421810..3a4017cde 100644 --- a/packages/ui/certd-server/src/plugins/plugin-nginx-proxy-manager/plugins/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-nginx-proxy-manager/plugins/index.ts @@ -1 +1 @@ -export * from "./plugin-deploy-to-proxy-hosts.js"; \ No newline at end of file +export * from "./plugin-deploy-to-proxy-hosts.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-nginx-proxy-manager/plugins/plugin-deploy-to-proxy-hosts.ts b/packages/ui/certd-server/src/plugins/plugin-nginx-proxy-manager/plugins/plugin-deploy-to-proxy-hosts.ts index 25c9da660..6297311ad 100644 --- a/packages/ui/certd-server/src/plugins/plugin-nginx-proxy-manager/plugins/plugin-deploy-to-proxy-hosts.ts +++ b/packages/ui/certd-server/src/plugins/plugin-nginx-proxy-manager/plugins/plugin-deploy-to-proxy-hosts.ts @@ -1,10 +1,4 @@ -import { - AbstractTaskPlugin, - IsTaskPlugin, - pluginGroups, - RunStrategy, - TaskInput, -} from "@certd/pipeline"; +import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; import { CertInfo, CertReader, createCertDomainGetterInputDefine } from "@certd/plugin-cert"; import { NginxProxyManagerAccess, ProxyHost } from "../access.js"; @@ -94,7 +88,9 @@ export class NginxProxyManagerDeploy extends AbstractTaskPlugin { cleanupMatchingCertificates = false; private normalizeDomain(domain: string): string { - return String(domain ?? "").trim().toLowerCase(); + return String(domain ?? "") + .trim() + .toLowerCase(); } private wildcardMatches(pattern: string, candidate: string): boolean { @@ -110,11 +106,7 @@ export class NginxProxyManagerDeploy extends AbstractTaskPlugin { const normalizedLeft = this.normalizeDomain(left); const normalizedRight = this.normalizeDomain(right); - return ( - normalizedLeft === normalizedRight || - this.wildcardMatches(normalizedLeft, normalizedRight) || - this.wildcardMatches(normalizedRight, normalizedLeft) - ); + return normalizedLeft === normalizedRight || this.wildcardMatches(normalizedLeft, normalizedRight) || this.wildcardMatches(normalizedRight, normalizedLeft); } private sanitizeDomainSegment(value: string): string { @@ -147,7 +139,7 @@ export class NginxProxyManagerDeploy extends AbstractTaskPlugin { private resolveCertificateDomains(cert: CertInfo, configuredDomains: string | string[] | null | undefined): string[] { const configured = this.normalizeStringList(configuredDomains) - .map((value) => String(value).trim()) + .map(value => String(value).trim()) .filter(Boolean); if (configured.length > 0) { @@ -168,9 +160,7 @@ export class NginxProxyManagerDeploy extends AbstractTaskPlugin { } const hostDomains = host.domain_names ?? []; - return hostDomains.some((hostDomain) => - certDomains.some((certDomain) => this.isDomainMatch(hostDomain, certDomain)) - ); + return hostDomains.some(hostDomain => certDomains.some(certDomain => this.isDomainMatch(hostDomain, certDomain))); } private buildProxyHostOptions(hosts: ProxyHost[], certDomains: string[]) { @@ -215,19 +205,14 @@ export class NginxProxyManagerDeploy extends AbstractTaskPlugin { return Array.from( new Set( this.normalizeStringList(proxyHostIds as string | string[] | null | undefined) - .map((value) => Number.parseInt(String(value), 10)) - .filter((value) => Number.isInteger(value) && value > 0) + .map(value => Number.parseInt(String(value), 10)) + .filter(value => Number.isInteger(value) && value > 0) ) ); } private certificateHasBindings(certificate: { proxy_hosts?: unknown[]; redirection_hosts?: unknown[]; dead_hosts?: unknown[]; streams?: unknown[] }): boolean { - return ( - (certificate.proxy_hosts?.length ?? 0) > 0 || - (certificate.redirection_hosts?.length ?? 0) > 0 || - (certificate.dead_hosts?.length ?? 0) > 0 || - (certificate.streams?.length ?? 0) > 0 - ); + return (certificate.proxy_hosts?.length ?? 0) > 0 || (certificate.redirection_hosts?.length ?? 0) > 0 || (certificate.dead_hosts?.length ?? 0) > 0 || (certificate.streams?.length ?? 0) > 0; } async execute(): Promise { @@ -238,8 +223,7 @@ export class NginxProxyManagerDeploy extends AbstractTaskPlugin { throw new Error("请至少选择一个 Nginx Proxy Manager 代理主机"); } - const certificateLabel = - this.certificateLabel?.trim() || this.buildDefaultCertificateLabel(this.cert); + const certificateLabel = this.certificateLabel?.trim() || this.buildDefaultCertificateLabel(this.cert); const certificateDomains = this.resolveCertificateDomains(this.cert, this.certDomains); let certificate = await access.findCustomCertificateByNiceName(certificateLabel); @@ -285,13 +269,8 @@ export class NginxProxyManagerDeploy extends AbstractTaskPlugin { } private async cleanupOldCertificates(access: NginxProxyManagerAccess, currentCertificateId: number): Promise { - const certificates = await access.getCertificatesWithExpand(undefined, [ - "proxy_hosts", - "redirection_hosts", - "dead_hosts", - "streams", - ]); - const candidates = certificates.filter((certificate) => { + const certificates = await access.getCertificatesWithExpand(undefined, ["proxy_hosts", "redirection_hosts", "dead_hosts", "streams"]); + const candidates = certificates.filter(certificate => { return certificate.id !== currentCertificateId; }); @@ -321,11 +300,7 @@ export class NginxProxyManagerDeploy extends AbstractTaskPlugin { } if (deletedIds.length > 0) { - this.logger.info( - `自动清理完成,共删除 ${deletedIds.length} 张旧证书:${deletedIds - .map((id) => `#${id}`) - .join(", ")}` - ); + this.logger.info(`自动清理完成,共删除 ${deletedIds.length} 张旧证书:${deletedIds.map(id => `#${id}`).join(", ")}`); } else { this.logger.info("未删除任何旧证书"); } @@ -340,4 +315,4 @@ export class NginxProxyManagerDeploy extends AbstractTaskPlugin { } } -new NginxProxyManagerDeploy(); \ No newline at end of file +new NginxProxyManagerDeploy(); diff --git a/packages/ui/certd-server/src/plugins/plugin-notification/anpush/index.ts b/packages/ui/certd-server/src/plugins/plugin-notification/anpush/index.ts index 455699745..17a3150f7 100644 --- a/packages/ui/certd-server/src/plugins/plugin-notification/anpush/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-notification/anpush/index.ts @@ -1,52 +1,52 @@ -import { BaseNotification, IsNotification, NotificationBody, NotificationInput } from '@certd/pipeline'; +import { BaseNotification, IsNotification, NotificationBody, NotificationInput } from "@certd/pipeline"; @IsNotification({ - name: 'anpush', - title: 'AnPush', - desc: 'https://anpush.com', + name: "anpush", + title: "AnPush", + desc: "https://anpush.com", needPlus: true, }) export class AnPushNotification extends BaseNotification { @NotificationInput({ - title: 'API密钥', + title: "API密钥", component: { - placeholder: '', + placeholder: "", }, - helper: '[获取API密钥](https://anpush.com/push/tool) ', + helper: "[获取API密钥](https://anpush.com/push/tool) ", required: true, }) - token = ''; + token = ""; @NotificationInput({ - title: '通道ID', + title: "通道ID", component: { - placeholder: '', + placeholder: "", }, - helper: '[获取通道ID](https://anpush.com/push/setting)创建通道,复制通道id,填入此处', + helper: "[获取通道ID](https://anpush.com/push/setting)创建通道,复制通道id,填入此处", required: true, }) - channel = ''; + channel = ""; async send(body: NotificationBody) { if (!this.token) { - throw new Error('token不能为空'); + throw new Error("token不能为空"); } const config = { url: `https://api.anpush.com/push/${this.token}`, - method: 'POST', + method: "POST", timeout: 0, headers: { - 'Content-Type': 'application/x-www-form-urlencoded', + "Content-Type": "application/x-www-form-urlencoded", }, data: { title: body.title, - content: body.content + '\n\n[查看详情](' + body.url + ')', + content: body.content + "\n\n[查看详情](" + body.url + ")", channel: this.channel, }, }; const res = await this.http.request(config); if (res.code != 200) { - throw new Error('发送失败:' + res.msg); + throw new Error("发送失败:" + res.msg); } } } diff --git a/packages/ui/certd-server/src/plugins/plugin-notification/bark/index.ts b/packages/ui/certd-server/src/plugins/plugin-notification/bark/index.ts index 370fa6a08..3fa2b72b9 100644 --- a/packages/ui/certd-server/src/plugins/plugin-notification/bark/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-notification/bark/index.ts @@ -13,31 +13,31 @@ * }' */ -import { BaseNotification, IsNotification, NotificationBody, NotificationInput } from '@certd/pipeline'; +import { BaseNotification, IsNotification, NotificationBody, NotificationInput } from "@certd/pipeline"; @IsNotification({ - name: 'bark', - title: 'Bark 通知', - desc: 'Bark 推送通知插件', + name: "bark", + title: "Bark 通知", + desc: "Bark 推送通知插件", needPlus: true, }) export class BarkNotification extends BaseNotification { @NotificationInput({ - title: '服务地址', + title: "服务地址", component: { - placeholder: 'https://api.day.app/your_key', + placeholder: "https://api.day.app/your_key", }, required: true, - helper: '你的bark服务地址+key', + helper: "你的bark服务地址+key", }) - webhook = ''; + webhook = ""; @NotificationInput({ - title: '忽略证书校验', + title: "忽略证书校验", value: false, component: { - name: 'a-switch', - vModel: 'checked', + name: "a-switch", + vModel: "checked", }, required: false, }) @@ -45,7 +45,7 @@ export class BarkNotification extends BaseNotification { async send(body: NotificationBody) { if (!this.webhook) { - throw new Error('服务器地址不能为空'); + throw new Error("服务器地址不能为空"); } const payload = { @@ -55,9 +55,9 @@ export class BarkNotification extends BaseNotification { await this.http.request({ url: `${this.webhook}`, - method: 'POST', + method: "POST", headers: { - 'Content-Type': 'application/json; charset=utf-8', + "Content-Type": "application/json; charset=utf-8", }, data: payload, skipSslVerify: this.skipSslVerify, diff --git a/packages/ui/certd-server/src/plugins/plugin-notification/dingtalk/index.ts b/packages/ui/certd-server/src/plugins/plugin-notification/dingtalk/index.ts index e875f1bd2..b63ebf4ce 100644 --- a/packages/ui/certd-server/src/plugins/plugin-notification/dingtalk/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-notification/dingtalk/index.ts @@ -1,79 +1,76 @@ import { BaseNotification, IsNotification, NotificationBody, NotificationInput } from "@certd/pipeline"; @IsNotification({ - name: 'dingtalk', - title: '钉钉通知', - desc: '钉钉群聊通知', + name: "dingtalk", + title: "钉钉通知", + desc: "钉钉群聊通知", needPlus: true, }) // https://open.dingtalk.com/document/orgapp/the-creation-and-installation-of-the-application-robot-in-the?spm=ding_open_doc.document.0.0.242d1563cDgZz3 export class DingTalkNotification extends BaseNotification { @NotificationInput({ - title: 'webhook地址', + title: "webhook地址", component: { - placeholder: 'https://oapi.dingtalk.com/robot/send?access_token=xxxxxxxxxxxxxxx', + placeholder: "https://oapi.dingtalk.com/robot/send?access_token=xxxxxxxxxxxxxxx", }, - helper: '钉钉APP->群聊->设置->机器人->添加机器人->自定义->[创建机器人->复制webhook地址](https://open.dingtalk.com/document/robots/custom-robot-access)', + helper: "钉钉APP->群聊->设置->机器人->添加机器人->自定义->[创建机器人->复制webhook地址](https://open.dingtalk.com/document/robots/custom-robot-access)", required: true, }) - webhook = ''; + webhook = ""; @NotificationInput({ - title: '加签密钥', + title: "加签密钥", component: { - placeholder: 'SECxxxxxxxxxxxxxxxxxxxxx', + placeholder: "SECxxxxxxxxxxxxxxxxxxxxx", }, - helper: '必须选择一种安全设置,请选择加密密钥', + helper: "必须选择一种安全设置,请选择加密密钥", required: false, }) - secret = ''; - + secret = ""; @NotificationInput({ - title: '@用户ID', + title: "@用户ID", component: { - placeholder: '非必填,填写完一个按回车', - name: 'a-select', - vModel: 'value', - mode: 'tags', + placeholder: "非必填,填写完一个按回车", + name: "a-select", + vModel: "value", + mode: "tags", multiple: true, open: false, }, - helper: '填写要@的用户ID', + helper: "填写要@的用户ID", required: false, }) - atUserIds:string[]; + atUserIds: string[]; @NotificationInput({ - title: '@用户手机号', + title: "@用户手机号", component: { - placeholder: '非必填,填写一个按回车', - name: 'a-select', - vModel: 'value', - mode: 'tags', + placeholder: "非必填,填写一个按回车", + name: "a-select", + vModel: "value", + mode: "tags", multiple: true, open: false, }, - helper: '填写要@的用户的手机号', + helper: "填写要@的用户的手机号", required: false, }) - atMobiles:string[]; - + atMobiles: string[]; @NotificationInput({ - title: '@all', + title: "@all", component: { - placeholder: '非必填', - name: 'a-switch', - vModel:"checked" + placeholder: "非必填", + name: "a-switch", + vModel: "checked", }, - helper: '是否@所有人', + helper: "是否@所有人", required: false, }) - isAtAll:boolean; + isAtAll: boolean; - - async sign(){ + async sign() { const timestamp = Date.now(); const secret = this.secret; const stringToSign = `${timestamp}\n${secret}`; @@ -83,21 +80,20 @@ export class DingTalkNotification extends BaseNotification { * hmac_code = hmac.new(secret_enc, string_to_sign_enc, digestmod=hashlib.sha256).digest() * sign = urllib.parse.quote_plus(base64.b64encode(hmac_code)) */ - const crypto = await import('crypto'); - const hmac = crypto.createHmac('sha256', secret); + const crypto = await import("crypto"); + const hmac = crypto.createHmac("sha256", secret); hmac.update(stringToSign); - const sign = encodeURIComponent(Buffer.from(hmac.digest()).toString('base64')); + const sign = encodeURIComponent(Buffer.from(hmac.digest()).toString("base64")); return { timestamp, sign, }; - } async send(body: NotificationBody) { if (!this.webhook) { - throw new Error('webhook地址不能为空'); + throw new Error("webhook地址不能为空"); } /** * @@ -109,36 +105,36 @@ export class DingTalkNotification extends BaseNotification { */ let webhook = this.webhook; - if(this.secret){ + if (this.secret) { const signRet = await this.sign(); webhook = `${webhook}×tamp=${signRet.timestamp}&sign=${signRet.sign}`; } - const at :any= {} - if(this.atUserIds && this.atUserIds.length>0){ - at.atUserIds = this.atUserIds; + const at: any = {}; + if (this.atUserIds && this.atUserIds.length > 0) { + at.atUserIds = this.atUserIds; } - if(this.atMobiles && this.atMobiles.length>0){ - at.atMobiles = this.atMobiles; + if (this.atMobiles && this.atMobiles.length > 0) { + at.atMobiles = this.atMobiles; } - if(this.isAtAll){ - at.isAtAll = true; + if (this.isAtAll) { + at.isAtAll = true; } - const color = body.errorMessage?'red':'green'; + const color = body.errorMessage ? "red" : "green"; const res = await this.http.request({ url: webhook, - method: 'POST', + method: "POST", data: { at: at, markdown: { title: body.title, text: `${body.title}\n\n\n ${body.content}\n\n\n[查看详情](${body.url})`, }, - msgtype:"markdown" + msgtype: "markdown", }, }); - if(res.errcode>100){ + if (res.errcode > 100) { throw new Error(`发送失败:${res.errmsg}`); } } diff --git a/packages/ui/certd-server/src/plugins/plugin-notification/discord/index.ts b/packages/ui/certd-server/src/plugins/plugin-notification/discord/index.ts index e5c6299d1..14fa99e8a 100644 --- a/packages/ui/certd-server/src/plugins/plugin-notification/discord/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-notification/discord/index.ts @@ -1,51 +1,51 @@ -import { BaseNotification, IsNotification, NotificationBody, NotificationInput } from '@certd/pipeline'; +import { BaseNotification, IsNotification, NotificationBody, NotificationInput } from "@certd/pipeline"; @IsNotification({ - name: 'discord', - title: 'Discord 通知', - desc: 'Discord 机器人通知', + name: "discord", + title: "Discord 通知", + desc: "Discord 机器人通知", needPlus: true, }) export class DiscordNotification extends BaseNotification { @NotificationInput({ - title: 'Webhook URL', + title: "Webhook URL", component: { - placeholder: 'https://discord.com/api/webhooks/xxxxx/xxxx', + placeholder: "https://discord.com/api/webhooks/xxxxx/xxxx", }, - helper: '[Discord Webhook 说明](https://discord.com/developers/docs/resources/webhook#execute-webhook)', + helper: "[Discord Webhook 说明](https://discord.com/developers/docs/resources/webhook#execute-webhook)", required: true, }) - webhook = ''; + webhook = ""; @NotificationInput({ - title: '提醒指定成员', + title: "提醒指定成员", component: { - name: 'a-select', - vModel: 'value', - mode: 'tags', + name: "a-select", + vModel: "value", + mode: "tags", open: false, }, required: false, - helper: '填写成员的Id,或者角色Id(&id),或者everyone', + helper: "填写成员的Id,或者角色Id(&id),或者everyone", }) mentionedList!: string[]; @NotificationInput({ - title: '代理', + title: "代理", component: { - placeholder: 'http://xxxxx:xx', + placeholder: "http://xxxxx:xx", }, - helper: '使用https_proxy', + helper: "使用https_proxy", required: false, }) - httpsProxy = ''; + httpsProxy = ""; @NotificationInput({ - title: '忽略证书校验', + title: "忽略证书校验", value: false, component: { - name: 'a-switch', - vModel: 'checked', + name: "a-switch", + vModel: "checked", }, required: false, }) @@ -53,13 +53,13 @@ export class DiscordNotification extends BaseNotification { async send(body: NotificationBody) { if (!this.webhook) { - throw new Error('Webhook URL 不能为空'); + throw new Error("Webhook URL 不能为空"); } // 创建 Discord 消息体 let content = `${body.title}\n${body.content}\n\n[查看详情](${body.url})`; if (this.mentionedList && this.mentionedList.length > 0) { - content += `\n${this.mentionedList.map(item => `<@${item}> `).join('')}`; + content += `\n${this.mentionedList.map(item => `<@${item}> `).join("")}`; } const json = { @@ -68,7 +68,7 @@ export class DiscordNotification extends BaseNotification { await this.http.request({ url: this.webhook, - method: 'POST', + method: "POST", data: json, httpProxy: this.httpsProxy, skipSslVerify: this.skipSslVerify, diff --git a/packages/ui/certd-server/src/plugins/plugin-notification/email/index.ts b/packages/ui/certd-server/src/plugins/plugin-notification/email/index.ts index bb7e7a71e..2f1f0b59e 100644 --- a/packages/ui/certd-server/src/plugins/plugin-notification/email/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-notification/email/index.ts @@ -1,41 +1,40 @@ -import { BaseNotification, IsNotification, NotificationBody, NotificationInput } from '@certd/pipeline'; +import { BaseNotification, IsNotification, NotificationBody, NotificationInput } from "@certd/pipeline"; @IsNotification({ - name: 'email', - title: '电子邮件', - desc: '电子邮件通知', + name: "email", + title: "电子邮件", + desc: "电子邮件通知", order: -100, }) export class EmailNotification extends BaseNotification { @NotificationInput({ - title: '收件人邮箱', + title: "收件人邮箱", component: { - name: 'email-selector', - vModel: 'value', - mode: 'tags', + name: "email-selector", + vModel: "value", + mode: "tags", // open: false, }, required: true, - helper: '可以填写多个,填写一个按回车键再填写下一个\n需要先[配置邮件服务器](#/sys/settings/email)', + helper: "可以填写多个,填写一个按回车键再填写下一个\n需要先[配置邮件服务器](#/sys/settings/email)", }) receivers!: string[]; async send(body: NotificationBody) { - const templateData = { ...body, - } - const emailSend:any = { + }; + const emailSend: any = { receivers: this.receivers, - } + }; if (body.attachments && body.attachments.length > 0) { emailSend.attachments = body.attachments; } await this.ctx.emailService.sendByTemplate({ type: body.notificationType, data: templateData, - ...emailSend - }) + ...emailSend, + }); // await this.ctx.emailService.send({ // subject: body.title, diff --git a/packages/ui/certd-server/src/plugins/plugin-notification/feishu/index.ts b/packages/ui/certd-server/src/plugins/plugin-notification/feishu/index.ts index 0fed0b1c9..fd14ef0fa 100644 --- a/packages/ui/certd-server/src/plugins/plugin-notification/feishu/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-notification/feishu/index.ts @@ -1,76 +1,73 @@ import { BaseNotification, IsNotification, NotificationBody, NotificationInput } from "@certd/pipeline"; @IsNotification({ - name: 'feishu', - title: '飞书通知', - desc: '飞书群聊webhook通知', + name: "feishu", + title: "飞书通知", + desc: "飞书群聊webhook通知", needPlus: true, }) // https://open.dingtalk.com/document/orgapp/the-creation-and-installation-of-the-application-robot-in-the?spm=ding_open_doc.document.0.0.242d1563cDgZz3 export class FeishuNotification extends BaseNotification { @NotificationInput({ - title: 'webhook地址', + title: "webhook地址", component: { - placeholder: 'https://open.feishu.cn/open-apis/bot/v2/hook/xxxxxxxxxxxxxxxx', + placeholder: "https://open.feishu.cn/open-apis/bot/v2/hook/xxxxxxxxxxxxxxxx", }, - helper: '飞书APP->群聊->设置->机器人->添加机器人->自定义webhook->[创建机器人->复制webhook地址](https://open.feishu.cn/document/client-docs/bot-v3/add-custom-bot?lang=zh-CN)', + helper: "飞书APP->群聊->设置->机器人->添加机器人->自定义webhook->[创建机器人->复制webhook地址](https://open.feishu.cn/document/client-docs/bot-v3/add-custom-bot?lang=zh-CN)", required: true, }) - webhook = ''; + webhook = ""; @NotificationInput({ - title: '加签密钥', + title: "加签密钥", component: { - placeholder: 'SECxxxxxxxxxxxxxxxxxxxxx', + placeholder: "SECxxxxxxxxxxxxxxxxxxxxx", }, - helper: '必须选择一种安全设置,建议选择加密密钥', + helper: "必须选择一种安全设置,建议选择加密密钥", required: false, }) - secret = ''; - + secret = ""; @NotificationInput({ - title: '@用户', + title: "@用户", component: { - placeholder: '非必填,支持多个,填写完一个按回车', - name: 'a-select', - vModel: 'value', - mode: 'tags', + placeholder: "非必填,支持多个,填写完一个按回车", + name: "a-select", + vModel: "value", + mode: "tags", multiple: true, open: false, }, - helper: '填写要@的用户ID:【ou_xxxxxxxxx】\n用户ID获取方法,[查看OpenId获取方法](https://open.feishu.cn/document/home/user-identity-introduction/open-id)', + helper: "填写要@的用户ID:【ou_xxxxxxxxx】\n用户ID获取方法,[查看OpenId获取方法](https://open.feishu.cn/document/home/user-identity-introduction/open-id)", required: false, }) - atUserIds:string[]; - + atUserIds: string[]; @NotificationInput({ - title: '@all', + title: "@all", component: { - placeholder: '非必填', - name: 'a-switch', - vModel:"checked" + placeholder: "非必填", + name: "a-switch", + vModel: "checked", }, - helper: '是否@所有人', + helper: "是否@所有人", required: false, }) - isAtAll:boolean; + isAtAll: boolean; - - async sign(){ - const crypto = await import('crypto'); + async sign() { + const crypto = await import("crypto"); const secret = this.secret; const timestamp = Math.floor(Date.now() / 1000); - const str = Buffer.from(`${timestamp}\n${secret}`, 'utf8'); - const sign = crypto.createHmac('SHA256', str); + const str = Buffer.from(`${timestamp}\n${secret}`, "utf8"); + const sign = crypto.createHmac("SHA256", str); sign.update(Buffer.alloc(0)); - return { timestamp, sign: sign.digest('base64') }; + return { timestamp, sign: sign.digest("base64") }; } async send(body: NotificationBody) { if (!this.webhook) { - throw new Error('webhook地址不能为空'); + throw new Error("webhook地址不能为空"); } /** * @@ -81,8 +78,7 @@ export class FeishuNotification extends BaseNotification { * } */ - let webhook = this.webhook; - + const webhook = this.webhook; /* // @ 单个用户 @@ -90,109 +86,109 @@ export class FeishuNotification extends BaseNotification { // @ 所有人 所有人 */ - let atText = "" - if(this.atUserIds && this.atUserIds.length>0){ - atText = this.atUserIds.map((id:string)=>{ - const nameIndex = id.indexOf("."); - let name = id - if(nameIndex>0){ - name = id.substring(nameIndex+1) - } - return `${name}` - }).join(""); + let atText = ""; + if (this.atUserIds && this.atUserIds.length > 0) { + atText = this.atUserIds + .map((id: string) => { + const nameIndex = id.indexOf("."); + let name = id; + if (nameIndex > 0) { + name = id.substring(nameIndex + 1); + } + return `${name}`; + }) + .join(""); } - if(this.isAtAll){ - atText = `所有人` + if (this.isAtAll) { + atText = `所有人`; } - if (atText){ - atText = `\n${atText}` + if (atText) { + atText = `\n${atText}`; } - let sign:any = {} - if(this.secret){ + let sign: any = {}; + if (this.secret) { const signRet = await this.sign(); sign = { timestamp: signRet.timestamp, - sign: signRet.sign - } + sign: signRet.sign, + }; } const cardBody = { - "msg_type": "interactive", - "card": { - "schema": "2.0", - "config": { - "update_multi": true, - "style": { - "text_size": { - "normal_v2": { - "default": "normal", - "pc": "normal", - "mobile": "heading" - } - } - } - }, - "header": { - "title": { - "tag": "plain_text", - "content": body.title + msg_type: "interactive", + card: { + schema: "2.0", + config: { + update_multi: true, + style: { + text_size: { + normal_v2: { + default: "normal", + pc: "normal", + mobile: "heading", + }, + }, }, - "subtitle": { - "tag": "plain_text", - "content": "" - }, - "template": body.errorMessage?"red":"green", - "padding": "12px 12px 12px 12px" }, - "body": { - "direction": "vertical", - "padding": "12px 12px 12px 12px", - "elements": [ + header: { + title: { + tag: "plain_text", + content: body.title, + }, + subtitle: { + tag: "plain_text", + content: "", + }, + template: body.errorMessage ? "red" : "green", + padding: "12px 12px 12px 12px", + }, + body: { + direction: "vertical", + padding: "12px 12px 12px 12px", + elements: [ { - "tag": "markdown", - "content": body.content+atText, - "text_align": "left", - "text_size": "normal_v2", - "margin": "0px 0px 0px 0px" + tag: "markdown", + content: body.content + atText, + text_align: "left", + text_size: "normal_v2", + margin: "0px 0px 0px 0px", }, { - "tag": "button", - "text": { - "tag": "plain_text", - "content": "查看详情" + tag: "button", + text: { + tag: "plain_text", + content: "查看详情", }, - "type": "default", - "width": "default", - "size": "medium", - "behaviors": [ + type: "default", + width: "default", + size: "medium", + behaviors: [ { - "type": "open_url", - "default_url": body.url, - "pc_url": "", - "ios_url": "", - "android_url": "" - } + type: "open_url", + default_url: body.url, + pc_url: "", + ios_url: "", + android_url: "", + }, ], - "margin": "0px 0px 0px 0px" - } - ] + margin: "0px 0px 0px 0px", + }, + ], }, - - } - } - + }, + }; const res = await this.http.request({ url: webhook, - method: 'POST', + method: "POST", data: { ...sign, - ...cardBody + ...cardBody, }, }); - if(res.code>100){ + if (res.code > 100) { throw new Error(`发送失败:${res.msg}`); } } diff --git a/packages/ui/certd-server/src/plugins/plugin-notification/index.ts b/packages/ui/certd-server/src/plugins/plugin-notification/index.ts index cba9458cc..a331918ea 100644 --- a/packages/ui/certd-server/src/plugins/plugin-notification/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-notification/index.ts @@ -1,16 +1,16 @@ -export * from './qywx/index.js'; -export * from './email/index.js'; -export * from './iyuu/index.js'; -export * from './webhook/index.js'; -export * from './serverchan/index.js'; -export * from './serverchan3/index.js'; -export * from './anpush/index.js'; -export * from './telegram/index.js'; -export * from './discord/index.js'; -export * from './slack/index.js'; -export * from './bark/index.js'; -export * from './feishu/index.js'; -export * from './dingtalk/index.js'; -export * from './vocechat/index.js'; -export * from './onebot/index.js'; -export * from './meow/index.js'; +export * from "./qywx/index.js"; +export * from "./email/index.js"; +export * from "./iyuu/index.js"; +export * from "./webhook/index.js"; +export * from "./serverchan/index.js"; +export * from "./serverchan3/index.js"; +export * from "./anpush/index.js"; +export * from "./telegram/index.js"; +export * from "./discord/index.js"; +export * from "./slack/index.js"; +export * from "./bark/index.js"; +export * from "./feishu/index.js"; +export * from "./dingtalk/index.js"; +export * from "./vocechat/index.js"; +export * from "./onebot/index.js"; +export * from "./meow/index.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-notification/iyuu/index.ts b/packages/ui/certd-server/src/plugins/plugin-notification/iyuu/index.ts index e289b1f4c..3a74407b9 100644 --- a/packages/ui/certd-server/src/plugins/plugin-notification/iyuu/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-notification/iyuu/index.ts @@ -1,32 +1,32 @@ -import { BaseNotification, IsNotification, NotificationBody, NotificationInput } from '@certd/pipeline'; +import { BaseNotification, IsNotification, NotificationBody, NotificationInput } from "@certd/pipeline"; @IsNotification({ - name: 'iyuu', - title: '爱语飞飞微信通知(iyuu)', - desc: 'https://iyuu.cn/', + name: "iyuu", + title: "爱语飞飞微信通知(iyuu)", + desc: "https://iyuu.cn/", needPlus: true, }) export class IyuuNotification extends BaseNotification { @NotificationInput({ - title: 'Token令牌', + title: "Token令牌", component: { - placeholder: '', + placeholder: "", }, - helper: 'https://iyuu.cn/ 微信扫码获取', + helper: "https://iyuu.cn/ 微信扫码获取", required: true, }) - token = ''; + token = ""; async send(body: NotificationBody) { if (!this.token) { - throw new Error('token不能为空'); + throw new Error("token不能为空"); } const res = await this.http.request({ url: `https://iyuu.cn/${this.token}.send`, - method: 'POST', + method: "POST", data: { text: body.title, - desp: body.content + '\n\n[查看详情](' + body.url + ')', + desp: body.content + "\n\n[查看详情](" + body.url + ")", }, }); diff --git a/packages/ui/certd-server/src/plugins/plugin-notification/meow/index.ts b/packages/ui/certd-server/src/plugins/plugin-notification/meow/index.ts index 3cc6f235f..42c9b2c05 100644 --- a/packages/ui/certd-server/src/plugins/plugin-notification/meow/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-notification/meow/index.ts @@ -1,4 +1,4 @@ -import { BaseNotification, IsNotification, NotificationBody, NotificationInput } from '@certd/pipeline'; +import { BaseNotification, IsNotification, NotificationBody, NotificationInput } from "@certd/pipeline"; /** * POST请求 @@ -38,43 +38,42 @@ Content-Type: application/json } */ @IsNotification({ - name: 'meow', - title: 'MeoW通知', - desc: 'https://api.chuckfang.com/', + name: "meow", + title: "MeoW通知", + desc: "https://api.chuckfang.com/", needPlus: false, }) export class MeowNotification extends BaseNotification { - @NotificationInput({ - title: 'MeoW接口地址', + title: "MeoW接口地址", component: { - placeholder: 'https://api.xxxxxx.com', + placeholder: "https://api.xxxxxx.com", }, required: true, }) - endpoint = ''; + endpoint = ""; @NotificationInput({ - title: '昵称', + title: "昵称", component: { - placeholder: '', + placeholder: "", }, required: true, }) - nickName = ''; + nickName = ""; async send(body: NotificationBody) { if (!this.nickName) { - throw new Error('昵称不能为空'); + throw new Error("昵称不能为空"); } let endpoint = this.endpoint; - if (!endpoint.endsWith('/')) { - endpoint += '/'; + if (!endpoint.endsWith("/")) { + endpoint += "/"; } const url = `${endpoint}${this.nickName}/`; const res = await this.http.request({ url: url, - method: 'POST', + method: "POST", data: { text: body.title, msg: body.content, diff --git a/packages/ui/certd-server/src/plugins/plugin-notification/onebot/index.ts b/packages/ui/certd-server/src/plugins/plugin-notification/onebot/index.ts index 300fb4ea4..cca433823 100755 --- a/packages/ui/certd-server/src/plugins/plugin-notification/onebot/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-notification/onebot/index.ts @@ -1,135 +1,131 @@ -import { BaseNotification, IsNotification, NotificationBody, NotificationInput } from "@certd/pipeline"; -import axios from "axios"; - -/** - * 文档: https://github.com/botuniverse/onebot-11 - * 教程: https://ayakasuki.com/ - */ - -@IsNotification({ - name: 'onebot', - title: 'OneBot V11 通知', - desc: '通过动态拼接URL发送 OneBot V11 协议消息', - needPlus: false, -}) -export class OneBotNotification extends BaseNotification { - // 基础服务地址(不含路径) - @NotificationInput({ - title: '服务地址', - component: { - placeholder: 'http://xxxx.xxxx.xxxx', - }, - helper: 'OneBot 服务的基础地址(不包含action路径)', - required: true, - rules: [ - { - type: 'url', - message: '请输入有效的HTTP/HTTPS地址' - } - ] - }) - baseUrl = ''; - - // 目标类型选择 - @NotificationInput({ - title: '目标类型', - component: { - name: 'a-select', - options: [ - { value: 'group', label: '群聊' }, - { value: 'private', label: '私聊' }, - ], - }, - required: true, - helper: '选择消息发送的目标类型', - }) - targetType = 'group'; - - // 目标ID配置 - @NotificationInput({ - title: '目标ID', - component: { - name: 'a-input-number', - placeholder: '123456789', - }, - helper: '群聊ID或用户ID(纯数字)', - required: true, - }) - targetId = ''; - - // 鉴权密钥(非必填) - @NotificationInput({ - title: '鉴权密钥', - component: { - placeholder: 'xxxxxxxxxx', - }, - helper: '(选填)访问API的授权令牌(无token时留空)', - required: false, // 关键修改点 - }) - accessToken = ''; - - // 构建完整请求URL(支持无token场景) - private buildFullUrl(): string { - const action = this.targetType === 'group' - ? 'send_group_msg' - : 'send_private_msg'; - - let url = `${this.baseUrl}/${action}`; - - // 动态添加access_token参数(仅当存在时) - if (this.accessToken) { - url += `?access_token=${encodeURIComponent(this.accessToken)}`; - } - - return url; - } - - // 构建消息内容 - private buildMessage(body: NotificationBody): string { - return body.title - ? `${body.title}\n${body.content}` - : body.content; - } - - // 构建请求体(动态字段) - private buildRequestBody(body: NotificationBody): object { - return { - [this.targetType === 'group' ? 'group_id' : 'user_id']: Number(this.targetId), - message: this.buildMessage(body), - auto_escape: false - }; - } - - // 发送通知主逻辑 - async send(body: NotificationBody) { - const fullUrl = this.buildFullUrl(); - const requestBody = this.buildRequestBody(body); - - try { - console.debug("[ONEBOT] 最终请求URL:", fullUrl); - console.debug("[ONEBOT] 请求体:", JSON.stringify(requestBody)); - console.debug("[ONEBOT] 使用Token:", !!this.accessToken); // 明确token使用状态 - - const response = await axios.post(fullUrl, requestBody, { - timeout: 5000, - headers: { - 'Content-Type': 'application/json', - 'User-Agent': 'Certd-Notification/1.0' - } - }); - - // 响应验证(保持不变) - if (response.data?.retcode !== 0) { - throw new Error(`[${response.data.retcode}] ${response.data.message}`); - } - return response.data; - } catch (error) { - console.error('[ONEBOT] 请求失败:', { - url: fullUrl, - tokenUsed: !!this.accessToken, // 记录token使用状态 - error: error.response?.data || error.message - }); - throw new Error(`OneBot通知发送失败: ${error.message}`); - } - } -} \ No newline at end of file +import { BaseNotification, IsNotification, NotificationBody, NotificationInput } from "@certd/pipeline"; +import axios from "axios"; + +/** + * 文档: https://github.com/botuniverse/onebot-11 + * 教程: https://ayakasuki.com/ + */ + +@IsNotification({ + name: "onebot", + title: "OneBot V11 通知", + desc: "通过动态拼接URL发送 OneBot V11 协议消息", + needPlus: false, +}) +export class OneBotNotification extends BaseNotification { + // 基础服务地址(不含路径) + @NotificationInput({ + title: "服务地址", + component: { + placeholder: "http://xxxx.xxxx.xxxx", + }, + helper: "OneBot 服务的基础地址(不包含action路径)", + required: true, + rules: [ + { + type: "url", + message: "请输入有效的HTTP/HTTPS地址", + }, + ], + }) + baseUrl = ""; + + // 目标类型选择 + @NotificationInput({ + title: "目标类型", + component: { + name: "a-select", + options: [ + { value: "group", label: "群聊" }, + { value: "private", label: "私聊" }, + ], + }, + required: true, + helper: "选择消息发送的目标类型", + }) + targetType = "group"; + + // 目标ID配置 + @NotificationInput({ + title: "目标ID", + component: { + name: "a-input-number", + placeholder: "123456789", + }, + helper: "群聊ID或用户ID(纯数字)", + required: true, + }) + targetId = ""; + + // 鉴权密钥(非必填) + @NotificationInput({ + title: "鉴权密钥", + component: { + placeholder: "xxxxxxxxxx", + }, + helper: "(选填)访问API的授权令牌(无token时留空)", + required: false, // 关键修改点 + }) + accessToken = ""; + + // 构建完整请求URL(支持无token场景) + private buildFullUrl(): string { + const action = this.targetType === "group" ? "send_group_msg" : "send_private_msg"; + + let url = `${this.baseUrl}/${action}`; + + // 动态添加access_token参数(仅当存在时) + if (this.accessToken) { + url += `?access_token=${encodeURIComponent(this.accessToken)}`; + } + + return url; + } + + // 构建消息内容 + private buildMessage(body: NotificationBody): string { + return body.title ? `${body.title}\n${body.content}` : body.content; + } + + // 构建请求体(动态字段) + private buildRequestBody(body: NotificationBody): object { + return { + [this.targetType === "group" ? "group_id" : "user_id"]: Number(this.targetId), + message: this.buildMessage(body), + auto_escape: false, + }; + } + + // 发送通知主逻辑 + async send(body: NotificationBody) { + const fullUrl = this.buildFullUrl(); + const requestBody = this.buildRequestBody(body); + + try { + console.debug("[ONEBOT] 最终请求URL:", fullUrl); + console.debug("[ONEBOT] 请求体:", JSON.stringify(requestBody)); + console.debug("[ONEBOT] 使用Token:", !!this.accessToken); // 明确token使用状态 + + const response = await axios.post(fullUrl, requestBody, { + timeout: 5000, + headers: { + "Content-Type": "application/json", + "User-Agent": "Certd-Notification/1.0", + }, + }); + + // 响应验证(保持不变) + if (response.data?.retcode !== 0) { + throw new Error(`[${response.data.retcode}] ${response.data.message}`); + } + return response.data; + } catch (error) { + console.error("[ONEBOT] 请求失败:", { + url: fullUrl, + tokenUsed: !!this.accessToken, // 记录token使用状态 + error: error.response?.data || error.message, + }); + throw new Error(`OneBot通知发送失败: ${error.message}`); + } + } +} diff --git a/packages/ui/certd-server/src/plugins/plugin-notification/qywx/index.ts b/packages/ui/certd-server/src/plugins/plugin-notification/qywx/index.ts index 025264218..9de2eff5d 100644 --- a/packages/ui/certd-server/src/plugins/plugin-notification/qywx/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-notification/qywx/index.ts @@ -1,58 +1,58 @@ -import { BaseNotification, IsNotification, NotificationBody, NotificationInput } from '@certd/pipeline'; +import { BaseNotification, IsNotification, NotificationBody, NotificationInput } from "@certd/pipeline"; @IsNotification({ - name: 'qywx', - title: '企业微信通知', - desc: '企业微信群聊机器人通知', + name: "qywx", + title: "企业微信通知", + desc: "企业微信群聊机器人通知", needPlus: true, }) export class QywxNotification extends BaseNotification { @NotificationInput({ - title: 'webhook地址', + title: "webhook地址", component: { - placeholder: 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxxxx', + placeholder: "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxxxx", }, - helper: '[企微群聊机器人配置说明](https://developer.work.weixin.qq.com/document/path/91770)', + helper: "[企微群聊机器人配置说明](https://developer.work.weixin.qq.com/document/path/91770)", required: true, }) - webhook = ''; + webhook = ""; @NotificationInput({ - title: '提醒指定成员', + title: "提醒指定成员", component: { - name: 'a-select', - vModel: 'value', - mode: 'tags', + name: "a-select", + vModel: "value", + mode: "tags", open: false, }, required: false, - helper: '填写成员名字,@all 为提醒所有人', + helper: "填写成员名字,@all 为提醒所有人", }) mentionedList!: string[]; @NotificationInput({ - title: '提醒指定手机号成员', + title: "提醒指定手机号成员", component: { - name: 'a-select', - vModel: 'value', - mode: 'tags', + name: "a-select", + vModel: "value", + mode: "tags", open: false, }, required: false, - helper: '填写成员手机号,@all 为提醒所有人', + helper: "填写成员手机号,@all 为提醒所有人", }) mentionedMobileList!: string[]; async send(body: NotificationBody) { if (!this.webhook) { - throw new Error('webhook地址不能为空'); + throw new Error("webhook地址不能为空"); } await this.http.request({ url: this.webhook, - method: 'POST', + method: "POST", data: { - msgtype: 'text', + msgtype: "text", text: { content: `${body.title}\n${body.content}\n查看详情: ${body.url}`, mentioned_list: this.mentionedList, @@ -61,7 +61,6 @@ export class QywxNotification extends BaseNotification { }, }); - //Markdown 模式不支持@ // const color = body.errorMessage?'red':'green'; diff --git a/packages/ui/certd-server/src/plugins/plugin-notification/serverchan/index.ts b/packages/ui/certd-server/src/plugins/plugin-notification/serverchan/index.ts index 496952167..4965fbd06 100644 --- a/packages/ui/certd-server/src/plugins/plugin-notification/serverchan/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-notification/serverchan/index.ts @@ -1,55 +1,55 @@ -import { BaseNotification, IsNotification, NotificationBody, NotificationInput } from '@certd/pipeline'; +import { BaseNotification, IsNotification, NotificationBody, NotificationInput } from "@certd/pipeline"; @IsNotification({ - name: 'serverchan', - title: 'Server酱ᵀ', - desc: 'https://sct.ftqq.com/', + name: "serverchan", + title: "Server酱ᵀ", + desc: "https://sct.ftqq.com/", needPlus: true, }) export class ServerChanNotification extends BaseNotification { @NotificationInput({ - title: '服务地址', - value: 'https://sctapi.ftqq.com', + title: "服务地址", + value: "https://sctapi.ftqq.com", required: true, }) - endpoint = 'https://sctapi.ftqq.com'; + endpoint = "https://sctapi.ftqq.com"; @NotificationInput({ - title: 'SendKey', + title: "SendKey", component: { - placeholder: 'https://sctapi.ftqq.com/.send', + placeholder: "https://sctapi.ftqq.com/.send", }, - helper: 'https://sct.ftqq.com/ 微信扫码获取', + helper: "https://sct.ftqq.com/ 微信扫码获取", required: true, }) - sendKey = ''; + sendKey = ""; @NotificationInput({ - title: '消息通道号', + title: "消息通道号", component: { - placeholder: '9|66', + placeholder: "9|66", }, - helper: '可以不填,最多两个通道,[通道配置说明](https://sct.ftqq.com/sendkey)', + helper: "可以不填,最多两个通道,[通道配置说明](https://sct.ftqq.com/sendkey)", required: false, }) channel: string; @NotificationInput({ - title: '是否隐藏IP', + title: "是否隐藏IP", component: { - name: 'a-switch', - vModel: 'checked', + name: "a-switch", + vModel: "checked", }, required: false, }) noip: boolean; @NotificationInput({ - title: '忽略证书校验', + title: "忽略证书校验", value: false, component: { - name: 'a-switch', - vModel: 'checked', + name: "a-switch", + vModel: "checked", }, required: false, }) @@ -57,14 +57,14 @@ export class ServerChanNotification extends BaseNotification { async send(body: NotificationBody) { if (!this.sendKey) { - throw new Error('sendKey不能为空'); + throw new Error("sendKey不能为空"); } await this.http.request({ url: `${this.endpoint}/${this.sendKey}.send`, - method: 'POST', + method: "POST", data: { text: body.title, - desp: body.content + '\n\n[查看详情](' + body.url + ')', + desp: body.content + "\n\n[查看详情](" + body.url + ")", }, skipSslVerify: this.skipSslVerify, }); diff --git a/packages/ui/certd-server/src/plugins/plugin-notification/serverchan3/index.ts b/packages/ui/certd-server/src/plugins/plugin-notification/serverchan3/index.ts index 50c43fe04..295799b4b 100644 --- a/packages/ui/certd-server/src/plugins/plugin-notification/serverchan3/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-notification/serverchan3/index.ts @@ -1,46 +1,46 @@ -import { BaseNotification, IsNotification, NotificationBody, NotificationInput } from '@certd/pipeline'; +import { BaseNotification, IsNotification, NotificationBody, NotificationInput } from "@certd/pipeline"; @IsNotification({ - name: 'serverchan3', - title: 'Server酱³', - desc: 'https://doc.sc3.ft07.com/serverchan3', + name: "serverchan3", + title: "Server酱³", + desc: "https://doc.sc3.ft07.com/serverchan3", needPlus: true, }) export class ServerChan3Notification extends BaseNotification { @NotificationInput({ - title: 'ApiURL', + title: "ApiURL", component: { - placeholder: 'https://uid.push.ft07.com/send/sendKey.send', + placeholder: "https://uid.push.ft07.com/send/sendKey.send", }, required: true, }) - apiURL = ''; + apiURL = ""; @NotificationInput({ - title: '标签Tags', + title: "标签Tags", component: { - name: 'a-select', - vModel: 'value', - mode: 'tags', + name: "a-select", + vModel: "value", + mode: "tags", open: false, }, - helper: '支持多个,回车后填写下一个', + helper: "支持多个,回车后填写下一个", required: false, }) tags: string[]; @NotificationInput({ - title: 'short', + title: "short", required: false, }) short: string; @NotificationInput({ - title: '忽略证书校验', + title: "忽略证书校验", value: false, component: { - name: 'a-switch', - vModel: 'checked', + name: "a-switch", + vModel: "checked", }, required: false, }) @@ -48,15 +48,15 @@ export class ServerChan3Notification extends BaseNotification { async send(body: NotificationBody) { if (!this.apiURL) { - throw new Error('sendKey不能为空'); + throw new Error("sendKey不能为空"); } await this.http.request({ url: `${this.apiURL}`, - method: 'POST', + method: "POST", data: { text: body.title, - desp: body.content + '\n\n[查看详情](' + body.url + ')', - tags: this.tags?.join('|') || undefined, + desp: body.content + "\n\n[查看详情](" + body.url + ")", + tags: this.tags?.join("|") || undefined, short: this.short, }, skipSslVerify: this.skipSslVerify, diff --git a/packages/ui/certd-server/src/plugins/plugin-notification/slack/index.ts b/packages/ui/certd-server/src/plugins/plugin-notification/slack/index.ts index d985aecb7..9f6846171 100644 --- a/packages/ui/certd-server/src/plugins/plugin-notification/slack/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-notification/slack/index.ts @@ -1,38 +1,38 @@ -import { BaseNotification, IsNotification, NotificationBody, NotificationInput } from '@certd/pipeline'; +import { BaseNotification, IsNotification, NotificationBody, NotificationInput } from "@certd/pipeline"; @IsNotification({ - name: 'slack', - title: 'Slack通知', - desc: 'Slack消息推送通知', + name: "slack", + title: "Slack通知", + desc: "Slack消息推送通知", needPlus: true, }) export class SlackNotification extends BaseNotification { @NotificationInput({ - title: 'webhook地址', + title: "webhook地址", component: { - placeholder: 'https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX', + placeholder: "https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX", }, - helper: '[APPS](https://api.slack.com/apps/)->进入APP->incoming-webhooks->Add New Webhook to Workspace', + helper: "[APPS](https://api.slack.com/apps/)->进入APP->incoming-webhooks->Add New Webhook to Workspace", required: true, }) - webhook = ''; + webhook = ""; @NotificationInput({ - title: '代理', + title: "代理", component: { - placeholder: 'http://xxxxx:xx', + placeholder: "http://xxxxx:xx", }, - helper: '使用https_proxy', + helper: "使用https_proxy", required: false, }) - httpsProxy = ''; + httpsProxy = ""; @NotificationInput({ - title: '忽略证书校验', + title: "忽略证书校验", value: false, component: { - name: 'a-switch', - vModel: 'checked', + name: "a-switch", + vModel: "checked", }, required: false, }) @@ -40,12 +40,12 @@ export class SlackNotification extends BaseNotification { async send(body: NotificationBody) { if (!this.webhook) { - throw new Error('token不能为空'); + throw new Error("token不能为空"); } await this.http.request({ url: this.webhook, - method: 'POST', + method: "POST", data: { text: `${body.title}\n${body.content}\n\n[查看详情](${body.url})`, }, diff --git a/packages/ui/certd-server/src/plugins/plugin-notification/telegram/index.ts b/packages/ui/certd-server/src/plugins/plugin-notification/telegram/index.ts index 59f596847..53e0f2108 100644 --- a/packages/ui/certd-server/src/plugins/plugin-notification/telegram/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-notification/telegram/index.ts @@ -1,58 +1,58 @@ -import { BaseNotification, IsNotification, NotificationBody, NotificationInput } from '@certd/pipeline'; +import { BaseNotification, IsNotification, NotificationBody, NotificationInput } from "@certd/pipeline"; @IsNotification({ - name: 'telegram', - title: 'Telegram通知', - desc: 'Telegram Bot推送通知', + name: "telegram", + title: "Telegram通知", + desc: "Telegram Bot推送通知", needPlus: true, }) export class TelegramNotification extends BaseNotification { @NotificationInput({ - title: 'URL', - value: 'https://api.telegram.org', + title: "URL", + value: "https://api.telegram.org", component: { - placeholder: 'https://api.telegram.org', + placeholder: "https://api.telegram.org", }, required: true, }) - endpoint = 'https://api.telegram.org'; + endpoint = "https://api.telegram.org"; @NotificationInput({ - title: 'Bot Token', + title: "Bot Token", component: { - placeholder: '123456789:ABCdefGhijklmnopqrstUVWXyz', + placeholder: "123456789:ABCdefGhijklmnopqrstUVWXyz", }, - helper: '[token获取](https://core.telegram.org/bots/features#botfather)', + helper: "[token获取](https://core.telegram.org/bots/features#botfather)", required: true, }) - botToken = ''; + botToken = ""; @NotificationInput({ - title: '聊天ID', + title: "聊天ID", component: { - placeholder: '聊天ID,例如 123456789 或 @channelusername', + placeholder: "聊天ID,例如 123456789 或 @channelusername", }, - helper: '用户ID(纯数字)或频道名称(@xxxx)', + helper: "用户ID(纯数字)或频道名称(@xxxx)", required: true, }) - chatId = ''; + chatId = ""; @NotificationInput({ - title: '代理', + title: "代理", component: { - placeholder: 'http://xxxxx:xx', + placeholder: "http://xxxxx:xx", }, - helper: '使用https_proxy', + helper: "使用https_proxy", required: false, }) - httpsProxy = ''; + httpsProxy = ""; @NotificationInput({ - title: '忽略证书校验', + title: "忽略证书校验", value: false, component: { - name: 'a-switch', - vModel: 'checked', + name: "a-switch", + vModel: "checked", }, required: false, }) @@ -60,13 +60,13 @@ export class TelegramNotification extends BaseNotification { replaceText(text: string) { // .*()<> 等都需要用\\进行替换 - return text.replace(/[_*[\]()~`>#\+\-=|{}.!]/g, '\\$&'); + return text.replace(/[_*[\]()~`>#\+\-=|{}.!]/g, "\\$&"); // .replace(/([\\_*`|!.[\](){}>+#=~-])/gm, '\\$1') // return text.replace(/[\\.*()<>]/g, '\\$&'); } async send(body: NotificationBody) { if (!this.botToken || !this.chatId) { - throw new Error('Bot Token 和聊天ID不能为空'); + throw new Error("Bot Token 和聊天ID不能为空"); } // 构建消息内容 @@ -78,11 +78,11 @@ export class TelegramNotification extends BaseNotification { // 发送 HTTP 请求 await this.http.request({ url: url, - method: 'POST', + method: "POST", data: { chat_id: this.chatId, text: messageContent, - parse_mode: 'MarkdownV2', // 或使用 'HTML' 取决于需要的格式 + parse_mode: "MarkdownV2", // 或使用 'HTML' 取决于需要的格式 }, httpProxy: this.httpsProxy, skipSslVerify: this.skipSslVerify, diff --git a/packages/ui/certd-server/src/plugins/plugin-notification/vocechat/index.ts b/packages/ui/certd-server/src/plugins/plugin-notification/vocechat/index.ts index 62dd037ad..643d300c4 100644 --- a/packages/ui/certd-server/src/plugins/plugin-notification/vocechat/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-notification/vocechat/index.ts @@ -1,61 +1,61 @@ -import { BaseNotification, IsNotification, NotificationBody, NotificationInput } from '@certd/pipeline'; +import { BaseNotification, IsNotification, NotificationBody, NotificationInput } from "@certd/pipeline"; @IsNotification({ - name: 'vocechat', - title: 'VoceChat通知', - desc: 'https://voce.chat', + name: "vocechat", + title: "VoceChat通知", + desc: "https://voce.chat", needPlus: true, }) export class VoceChatNotification extends BaseNotification { @NotificationInput({ - title: '服务地址', + title: "服务地址", component: { - placeholder: 'https://replace.your.domain', + placeholder: "https://replace.your.domain", }, required: true, }) - endpoint = ''; + endpoint = ""; @NotificationInput({ - title: 'apiKey', + title: "apiKey", component: { - placeholder: '', + placeholder: "", }, - helper: '[获取APIKEY](https://doc.voce.chat/bot/bot-and-webhook)', + helper: "[获取APIKEY](https://doc.voce.chat/bot/bot-and-webhook)", required: true, }) - apiKey = ''; + apiKey = ""; @NotificationInput({ - title: '目标类型', + title: "目标类型", component: { - name: 'a-select', + name: "a-select", options: [ - { value: 'user', label: '用户' }, - { value: 'channel', label: '频道' }, + { value: "user", label: "用户" }, + { value: "channel", label: "频道" }, ], }, required: true, - helper: '发送消息的目标类型', + helper: "发送消息的目标类型", }) - targetType = ''; + targetType = ""; @NotificationInput({ - title: '目标ID', + title: "目标ID", component: { - placeholder: '发送消息的目标ID', + placeholder: "发送消息的目标ID", }, required: true, - helper: '目标ID可以是用户ID或频道ID', + helper: "目标ID可以是用户ID或频道ID", }) - targetId = ''; + targetId = ""; @NotificationInput({ - title: '忽略证书校验', + title: "忽略证书校验", value: false, component: { - name: 'a-switch', - vModel: 'checked', + name: "a-switch", + vModel: "checked", }, required: false, }) @@ -63,21 +63,21 @@ export class VoceChatNotification extends BaseNotification { async send(body: NotificationBody) { if (!this.apiKey) { - throw new Error('API Key不能为空'); + throw new Error("API Key不能为空"); } if (!this.targetId) { - throw new Error('目标ID不能为空'); + throw new Error("目标ID不能为空"); } - const url = this.targetType === 'user' ? '/api/bot/send_to_user/' : '/api/bot/send_to_group/'; + const url = this.targetType === "user" ? "/api/bot/send_to_user/" : "/api/bot/send_to_group/"; await this.http.request({ url: url + this.targetId, // 这是示例API URL,请根据实际API文档调整 baseURL: this.endpoint, - method: 'POST', + method: "POST", headers: { - 'x-api-key': this.apiKey, - 'Content-Type': 'text/markdown', + "x-api-key": this.apiKey, + "Content-Type": "text/markdown", }, data: `# ${body.title}\n\n${body.content}\n\n[查看详情](${body.url})`, skipSslVerify: this.skipSslVerify, diff --git a/packages/ui/certd-server/src/plugins/plugin-notification/webhook/index.ts b/packages/ui/certd-server/src/plugins/plugin-notification/webhook/index.ts index a173a6ab7..9a1c91c0f 100644 --- a/packages/ui/certd-server/src/plugins/plugin-notification/webhook/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-notification/webhook/index.ts @@ -1,79 +1,79 @@ -import { BaseNotification, IsNotification, NotificationBody, NotificationInput } from '@certd/pipeline'; -import qs from 'qs'; +import { BaseNotification, IsNotification, NotificationBody, NotificationInput } from "@certd/pipeline"; +import qs from "qs"; @IsNotification({ - name: 'webhook', - title: '自定义webhook', - desc: '根据模版自定义http请求', + name: "webhook", + title: "自定义webhook", + desc: "根据模版自定义http请求", order: -100, }) export class WebhookNotification extends BaseNotification { @NotificationInput({ - title: 'webhook地址', + title: "webhook地址", component: { - placeholder: 'https://xxxxx.com/xxxx', + placeholder: "https://xxxxx.com/xxxx", }, col: { span: 24, }, required: true, }) - webhook = ''; + webhook = ""; @NotificationInput({ - title: '请求方式', - value: 'POST', + title: "请求方式", + value: "POST", component: { - name: 'a-select', - placeholder: 'post/put/get', + name: "a-select", + placeholder: "post/put/get", options: [ - { value: 'POST', label: 'POST' }, - { value: 'PUT', label: 'PUT' }, - { value: 'GET', label: 'GET' }, + { value: "POST", label: "POST" }, + { value: "PUT", label: "PUT" }, + { value: "GET", label: "GET" }, ], }, required: true, }) - method = ''; + method = ""; @NotificationInput({ - title: 'ContentType', - value: 'application/json', + title: "ContentType", + value: "application/json", component: { - name: 'a-auto-complete', + name: "a-auto-complete", options: [ - { value: 'application/json', label: 'application/json' }, - { value: 'application/x-www-form-urlencoded', label: 'application/x-www-form-urlencoded' }, + { value: "application/json", label: "application/json" }, + { value: "application/x-www-form-urlencoded", label: "application/x-www-form-urlencoded" }, ], }, - helper: '也可以自定义填写', + helper: "也可以自定义填写", required: true, }) - contentType = ''; + contentType = ""; @NotificationInput({ - title: 'Headers', + title: "Headers", component: { - name: 'a-textarea', - vModel: 'value', + name: "a-textarea", + vModel: "value", rows: 2, }, col: { span: 24, }, - helper: '一行一个,格式为key=value', + helper: "一行一个,格式为key=value", required: false, }) - headers = ''; + headers = ""; @NotificationInput({ - title: '消息body模版', + title: "消息body模版", value: `{ "title":"{title}", "content":"{content}\\n[查看详情]({url})" }`, component: { - name: 'a-textarea', + name: "a-textarea", rows: 4, }, col: { @@ -82,14 +82,14 @@ export class WebhookNotification extends BaseNotification { helper: `根据对应的webhook接口文档,构建一个json对象作为参数(默认值只是一个示例,一般不是正确的参数)\n支持变量:{title}、{content}、{url},变量用{}包裹\n字符串需要双引号,使用\\n换行\n如果是get方式,将作为query参数拼接到url上`, required: true, }) - template = ''; + template = ""; @NotificationInput({ - title: '忽略证书校验', + title: "忽略证书校验", value: false, component: { - name: 'a-switch', - vModel: 'checked', + name: "a-switch", + vModel: "checked", }, required: false, }) @@ -102,17 +102,16 @@ export class WebhookNotification extends BaseNotification { let value = urlEncode ? encodeURIComponent(body[key]) : body[key]; value = value.replaceAll(`\n`, "\\n"); bodyStr = bodyStr.replaceAll(`{${key}}`, value); - } return bodyStr; } async send(body: NotificationBody) { if (!this.template) { - throw new Error('模版不能为空'); + throw new Error("模版不能为空"); } if (!this.webhook) { - throw new Error('webhook不能为空'); + throw new Error("webhook不能为空"); } const replaceBody = { @@ -124,9 +123,9 @@ export class WebhookNotification extends BaseNotification { let data = JSON.parse(bodyStr); let url = this.webhook; - if (this.method.toLowerCase() === 'get') { + if (this.method.toLowerCase() === "get") { const query = qs.stringify(data); - if (url.includes('?')) { + if (url.includes("?")) { url = `${url}&${query}`; } else { url = `${url}?${query}`; @@ -136,12 +135,12 @@ export class WebhookNotification extends BaseNotification { const headers: any = {}; if (this.headers && this.headers.trim()) { - this.headers.split('\n').forEach(item => { + this.headers.split("\n").forEach(item => { item = item.trim(); if (item) { - const eqIndex = item.indexOf('='); + const eqIndex = item.indexOf("="); if (eqIndex <= 0) { - this.logger.warn('header格式错误,请使用=号分割', item); + this.logger.warn("header格式错误,请使用=号分割", item); return; } const key = item.substring(0, eqIndex); @@ -155,16 +154,16 @@ export class WebhookNotification extends BaseNotification { url: url, method: this.method, headers: { - 'Content-Type': `${this.contentType}; charset=UTF-8`, + "Content-Type": `${this.contentType}; charset=UTF-8`, ...headers, }, data: data, skipSslVerify: this.skipSslVerify, }); - return res + return res; } catch (e) { if (e.response?.data) { - throw new Error(e.message + ',' + JSON.stringify(e.response.data)); + throw new Error(e.message + "," + JSON.stringify(e.response.data)); } throw e; } diff --git a/packages/ui/certd-server/src/plugins/plugin-oauth/api.ts b/packages/ui/certd-server/src/plugins/plugin-oauth/api.ts index 89ee026d7..887c46f70 100644 --- a/packages/ui/certd-server/src/plugins/plugin-oauth/api.ts +++ b/packages/ui/certd-server/src/plugins/plugin-oauth/api.ts @@ -1,60 +1,60 @@ export type OnCallbackReq = { - code: string; - state: string; - currentURL: URL; - ticketValue: any; -} + code: string; + state: string; + currentURL: URL; + ticketValue: any; +}; export type OauthToken = { - userInfo: { - openId: string; - nickName: string; - avatar: string; - }, - token: { - accessToken: string; - refreshToken: string; - expiresIn: number; - } -} - -export type OnBindReq = { + userInfo: { + openId: string; + nickName: string; + avatar: string; + }; + token: { accessToken: string; refreshToken: string; expiresIn: number; - idToken: string; - scope: string; - tokenType: string; - bindInfo: any; -} + }; +}; + +export type OnBindReq = { + accessToken: string; + refreshToken: string; + expiresIn: number; + idToken: string; + scope: string; + tokenType: string; + bindInfo: any; +}; export type OnBindReply = { - success: boolean; - message: string; -} + success: boolean; + message: string; +}; export type LoginUrlReply = { - loginUrl: string; - ticketValue: any; -} + loginUrl: string; + ticketValue: any; +}; export type BuildLoginUrlReq = { - redirectUri: string; - forType?: string; - from?:string; - subtype?: string; - state?: string; -} + redirectUri: string; + forType?: string; + from?: string; + subtype?: string; + state?: string; +}; export type BuildLogoutUrlReq = { - subtype?: string; -} + subtype?: string; +}; export type LogoutUrlReply = { - logoutUrl?: string; -} + logoutUrl?: string; +}; export interface IOauthProvider { - buildLoginUrl: (params: BuildLoginUrlReq) => Promise; - onCallback: (params: OnCallbackReq) => Promise; - buildLogoutUrl: (params: BuildLogoutUrlReq) => Promise; + buildLoginUrl: (params: BuildLoginUrlReq) => Promise; + onCallback: (params: OnCallbackReq) => Promise; + buildLogoutUrl: (params: BuildLogoutUrlReq) => Promise; } diff --git a/packages/ui/certd-server/src/plugins/plugin-oauth/iconsets.ts b/packages/ui/certd-server/src/plugins/plugin-oauth/iconsets.ts index 4b062c8e8..e5ba69be2 100644 --- a/packages/ui/certd-server/src/plugins/plugin-oauth/iconsets.ts +++ b/packages/ui/certd-server/src/plugins/plugin-oauth/iconsets.ts @@ -1,13 +1 @@ -export const IconSets = [ - "streamline-logos", - "logos", - "fa-brands", - "fa-solid", - "fa-regular", - "carbon", - "ion", - "ant-design", - "mdi", - "twemoji", - "svg-spinners" -] \ No newline at end of file +export const IconSets = ["streamline-logos", "logos", "fa-brands", "fa-solid", "fa-regular", "carbon", "ion", "ant-design", "mdi", "twemoji", "svg-spinners"]; diff --git a/packages/ui/certd-server/src/plugins/plugin-oauth/index.ts b/packages/ui/certd-server/src/plugins/plugin-oauth/index.ts index 37157bcd7..45db2bb81 100644 --- a/packages/ui/certd-server/src/plugins/plugin-oauth/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-oauth/index.ts @@ -1,8 +1,8 @@ -export * from './api.js' -export * from './oidc/plugin-oidc.js' -export * from './wx/plugin-wx.js' -export * from './oauth2/plugin-gitee.js' -export * from './oauth2/plugin-clogin.js' -export * from './oauth2/plugin-github.js' -export * from './oauth2/plugin-google.js' -export * from './oauth2/plugin-microsoft.js' \ No newline at end of file +export * from "./api.js"; +export * from "./oidc/plugin-oidc.js"; +export * from "./wx/plugin-wx.js"; +export * from "./oauth2/plugin-gitee.js"; +export * from "./oauth2/plugin-clogin.js"; +export * from "./oauth2/plugin-github.js"; +export * from "./oauth2/plugin-google.js"; +export * from "./oauth2/plugin-microsoft.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-oauth/oauth2/plugin-clogin.ts b/packages/ui/certd-server/src/plugins/plugin-oauth/oauth2/plugin-clogin.ts index 7b8e2148c..0c3afed32 100644 --- a/packages/ui/certd-server/src/plugins/plugin-oauth/oauth2/plugin-clogin.ts +++ b/packages/ui/certd-server/src/plugins/plugin-oauth/oauth2/plugin-clogin.ts @@ -29,9 +29,9 @@ function getCloginType(subtype?: string, loginType?: string | string[]) { @IsAddon({ addonType: "oauth", - name: 'clogin', - title: '彩虹聚合登录', - desc: '彩虹聚合登录', + name: "clogin", + title: "彩虹聚合登录", + desc: "彩虹聚合登录", icon: "emojione:rainbow", showTest: false, }) @@ -40,7 +40,7 @@ export class CloginOauthProvider extends BaseAddon implements IOauthProvider { title: "系统地址", helper: "http://clogin.xxxx.com/", required: true, - col:{span:24}, + col: { span: 24 }, }) endpoint = ""; @@ -85,19 +85,17 @@ export class CloginOauthProvider extends BaseAddon implements IOauthProvider { }) appKey = ""; - async buildLoginUrl(params: BuildLoginUrlReq) { - - let redirectUri = params.redirectUri || "" + const redirectUri = params.redirectUri || ""; const loginType = getCloginType(params.subtype, this.loginType); // if(redirectUri.indexOf("localhost:3008")>=0){ // redirectUri = redirectUri.replace("localhost:3008", "certd.handfree.work") // } const res = await this.ctx.http.request({ - url: `${this.endpoint}/connect.php?act=login&appid=${this.appId}&appkey=${this.appKey}&type=${loginType}&redirect_uri=${redirectUri}&state=${params.state}` - }) + url: `${this.endpoint}/connect.php?act=login&appid=${this.appId}&appkey=${this.appKey}&type=${loginType}&redirect_uri=${redirectUri}&state=${params.state}`, + }); - this.checkRes(res) + this.checkRes(res); return { loginUrl: res.url, @@ -107,23 +105,22 @@ export class CloginOauthProvider extends BaseAddon implements IOauthProvider { checkRes(res: any) { if (res.code !== 0) { - throw new Error(res.msg || "请求接口失败") + throw new Error(res.msg || "请求接口失败"); } } async onCallback(req: OnCallbackReq) { - //校验state - const code = req.code || "" + const code = req.code || ""; const loginType = getCloginType(req.ticketValue?.subtype, this.loginType); - const tokenEndpoint = `${this.endpoint}/connect.php?act=callback&appid=${this.appId}&appkey=${this.appKey}&type=${loginType}&code=${code}` + const tokenEndpoint = `${this.endpoint}/connect.php?act=callback&appid=${this.appId}&appkey=${this.appKey}&type=${loginType}&code=${code}`; const res = await this.ctx.utils.http.request({ url: tokenEndpoint, method: "post", - }) - this.checkRes(res) + }); + this.checkRes(res); /** * "access_token": "89DC9691E274D6B596FFCB8D43368234", @@ -135,8 +132,7 @@ export class CloginOauthProvider extends BaseAddon implements IOauthProvider { "ip": "1.12.3.40" */ - const { access_token, faceimg, nickname, social_uid } = res - + const { access_token, faceimg, nickname, social_uid } = res; return { token: { @@ -149,8 +145,8 @@ export class CloginOauthProvider extends BaseAddon implements IOauthProvider { nickName: nickname || "", avatar: faceimg || "", }, - } - }; + }; + } async buildLogoutUrl(params: BuildLogoutUrlReq) { return {}; diff --git a/packages/ui/certd-server/src/plugins/plugin-oauth/oauth2/plugin-gitee.ts b/packages/ui/certd-server/src/plugins/plugin-oauth/oauth2/plugin-gitee.ts index 0f5a61961..9abff7cbf 100644 --- a/packages/ui/certd-server/src/plugins/plugin-oauth/oauth2/plugin-gitee.ts +++ b/packages/ui/certd-server/src/plugins/plugin-oauth/oauth2/plugin-gitee.ts @@ -3,14 +3,13 @@ import { BuildLoginUrlReq, BuildLogoutUrlReq, IOauthProvider, OnCallbackReq } fr @IsAddon({ addonType: "oauth", - name: 'gitee', - title: 'Gitee认证', - desc: 'Gitee OAuth2登录', - icon:"simple-icons:gitee:red", + name: "gitee", + title: "Gitee认证", + desc: "Gitee OAuth2登录", + icon: "simple-icons:gitee:red", showTest: false, }) export class GiteeOauthProvider extends BaseAddon implements IOauthProvider { - @AddonInput({ title: "ClientId", helper: "[gitee 第三方应用管理](https://gitee.com/oauth/applications)创建应用后获取", @@ -74,63 +73,57 @@ gitee.userInfo = https://gitee.com/api/v5/user // }) // scope: string; - - async buildLoginUrl(params: BuildLoginUrlReq) { - - let scope = "user_info" // Scope of the access request - const authorizeEndpoint = "https://gitee.com/oauth/authorize" - const redirectUrl = encodeURIComponent(params.redirectUri) + const scope = "user_info"; // Scope of the access request + const authorizeEndpoint = "https://gitee.com/oauth/authorize"; + const redirectUrl = encodeURIComponent(params.redirectUri); // https://gitee.com/oauth/authorize?client_id=5bb5f4158af41c50c7a17b5d9068244e97d3ee572def6a57ed32fd8c9d760ad1&redirect_uri=http%3A%2F%2Fcasdoor.docmirror.cn%3A8000%2Fcallback&response_type=code - const loginUrl = `${authorizeEndpoint}?client_id=${this.clientId}&redirect_uri=${redirectUrl}&response_type=code&scope=${scope}&state=${params.state}` + const loginUrl = `${authorizeEndpoint}?client_id=${this.clientId}&redirect_uri=${redirectUrl}&response_type=code&scope=${scope}&state=${params.state}`; return { loginUrl, - ticketValue: { - }, + ticketValue: {}, }; } async onCallback(req: OnCallbackReq) { - //校验state - const code = req.code || "" + const code = req.code || ""; - const tokenEndpoint = "https://gitee.com/oauth/token" + const tokenEndpoint = "https://gitee.com/oauth/token"; - const uri = new URL(req.currentURL) - const redirectUri = `${uri.origin}${uri.pathname}` - const res = await this.ctx.utils.http.request( { - url: tokenEndpoint, - method: "post", - data:{ + const uri = new URL(req.currentURL); + const redirectUri = `${uri.origin}${uri.pathname}`; + const res = await this.ctx.utils.http.request({ + url: tokenEndpoint, + method: "post", + data: { // https://gitee.com/oauth/token? // grant_type=authorization_code&code={code}&client_id={client_id}&redirect_uri={redirect_uri}&client_secret={client_secret} - grant_type: "authorization_code", - code, - client_id: this.clientId, - redirect_uri: redirectUri, - client_secret: this.clientSecretKey, - } - }) - - const tokens = res + grant_type: "authorization_code", + code, + client_id: this.clientId, + redirect_uri: redirectUri, + client_secret: this.clientSecretKey, + }, + }); + const tokens = res; - const userInfoEndpoint = "https://gitee.com/api/v5/user" + const userInfoEndpoint = "https://gitee.com/api/v5/user"; // 获取用户信息 - const userInfoRes = await this.ctx.utils.http.request( { - url: userInfoEndpoint, - method: "get", - params:{ - access_token: tokens.access_token, - } - }) - const userInfo = userInfoRes + const userInfoRes = await this.ctx.utils.http.request({ + url: userInfoEndpoint, + method: "get", + params: { + access_token: tokens.access_token, + }, + }); + const userInfo = userInfoRes; return { - token:{ + token: { accessToken: tokens.access_token, refreshToken: tokens.refresh_token, expiresIn: tokens.expires_in, @@ -140,8 +133,8 @@ gitee.userInfo = https://gitee.com/api/v5/user nickName: userInfo.name || userInfo.nick_name || "", avatar: userInfo.avatar_url, }, - } - }; + }; + } async buildLogoutUrl(params: BuildLogoutUrlReq) { return {}; diff --git a/packages/ui/certd-server/src/plugins/plugin-oauth/oauth2/plugin-github.ts b/packages/ui/certd-server/src/plugins/plugin-oauth/oauth2/plugin-github.ts index 019b6dc70..1768bda5b 100644 --- a/packages/ui/certd-server/src/plugins/plugin-oauth/oauth2/plugin-github.ts +++ b/packages/ui/certd-server/src/plugins/plugin-oauth/oauth2/plugin-github.ts @@ -3,14 +3,13 @@ import { BuildLoginUrlReq, BuildLogoutUrlReq, IOauthProvider, OnCallbackReq } fr @IsAddon({ addonType: "oauth", - name: 'github', - title: 'GitHub认证', - desc: 'GitHub OAuth2登录', - icon:"simple-icons:github", + name: "github", + title: "GitHub认证", + desc: "GitHub OAuth2登录", + icon: "simple-icons:github", showTest: false, }) export class GithubOauthProvider extends BaseAddon implements IOauthProvider { - @AddonInput({ title: "ClientId", helper: "[GitHub Developer Settings](https://github.com/settings/developers)创建应用后获取", @@ -28,56 +27,54 @@ export class GithubOauthProvider extends BaseAddon implements IOauthProvider { clientSecretKey = ""; async buildLoginUrl(params: BuildLoginUrlReq) { - - let scope = "user:email" // Scope of the access request - const authorizeEndpoint = "https://github.com/login/oauth/authorize" - const redirectUrl = encodeURIComponent(params.redirectUri) - const loginUrl = `${authorizeEndpoint}?client_id=${this.clientId}&redirect_uri=${redirectUrl}&response_type=code&scope=${scope}&state=${params.state}` + const scope = "user:email"; // Scope of the access request + const authorizeEndpoint = "https://github.com/login/oauth/authorize"; + const redirectUrl = encodeURIComponent(params.redirectUri); + const loginUrl = `${authorizeEndpoint}?client_id=${this.clientId}&redirect_uri=${redirectUrl}&response_type=code&scope=${scope}&state=${params.state}`; return { loginUrl, - ticketValue: { }, + ticketValue: {}, }; } async onCallback(req: OnCallbackReq) { - - const code = req.code || "" + const code = req.code || ""; - const tokenEndpoint = "https://github.com/login/oauth/access_token" + const tokenEndpoint = "https://github.com/login/oauth/access_token"; - const uri = new URL(req.currentURL) - const redirectUri = `${uri.origin}${uri.pathname}` - const res = await this.ctx.utils.http.request( { - url: tokenEndpoint, - method: "post", - headers: { - "Accept": "application/json" - }, - data:{ - client_id: this.clientId, - client_secret: this.clientSecretKey, - code, - redirect_uri: redirectUri - } - }) - - const tokens = res + const uri = new URL(req.currentURL); + const redirectUri = `${uri.origin}${uri.pathname}`; + const res = await this.ctx.utils.http.request({ + url: tokenEndpoint, + method: "post", + headers: { + Accept: "application/json", + }, + data: { + client_id: this.clientId, + client_secret: this.clientSecretKey, + code, + redirect_uri: redirectUri, + }, + }); - const userInfoEndpoint = "https://api.github.com/user" + const tokens = res; + + const userInfoEndpoint = "https://api.github.com/user"; // 获取用户信息 - const userInfoRes = await this.ctx.utils.http.request( { - url: userInfoEndpoint, - method: "get", - headers: { - "Authorization": `Bearer ${tokens.access_token}`, - "Accept": "application/json" - } - }) - const userInfo = userInfoRes + const userInfoRes = await this.ctx.utils.http.request({ + url: userInfoEndpoint, + method: "get", + headers: { + Authorization: `Bearer ${tokens.access_token}`, + Accept: "application/json", + }, + }); + const userInfo = userInfoRes; return { - token:{ + token: { accessToken: tokens.access_token, refreshToken: tokens.refresh_token, expiresIn: tokens.expires_in, @@ -87,10 +84,10 @@ export class GithubOauthProvider extends BaseAddon implements IOauthProvider { nickName: userInfo.login || userInfo.name || "", avatar: userInfo.avatar_url, }, - } - }; + }; + } async buildLogoutUrl(params: BuildLogoutUrlReq) { return {}; } -} \ No newline at end of file +} diff --git a/packages/ui/certd-server/src/plugins/plugin-oauth/oauth2/plugin-google.ts b/packages/ui/certd-server/src/plugins/plugin-oauth/oauth2/plugin-google.ts index 59aea2ad6..7b9efd21d 100644 --- a/packages/ui/certd-server/src/plugins/plugin-oauth/oauth2/plugin-google.ts +++ b/packages/ui/certd-server/src/plugins/plugin-oauth/oauth2/plugin-google.ts @@ -3,14 +3,13 @@ import { BuildLoginUrlReq, BuildLogoutUrlReq, IOauthProvider, OnCallbackReq } fr @IsAddon({ addonType: "oauth", - name: 'google', - title: 'Google认证', - desc: 'Google OAuth2登录', - icon:"simple-icons:google", + name: "google", + title: "Google认证", + desc: "Google OAuth2登录", + icon: "simple-icons:google", showTest: false, }) export class GoogleOauthProvider extends BaseAddon implements IOauthProvider { - @AddonInput({ title: "ClientId", helper: "[Google Cloud Console](https://console.cloud.google.com/apis/credentials)创建应用后获取", @@ -28,58 +27,55 @@ export class GoogleOauthProvider extends BaseAddon implements IOauthProvider { clientSecretKey = ""; async buildLoginUrl(params: BuildLoginUrlReq) { + const scope = "email profile"; // Scope of the access request - let scope = "email profile" // Scope of the access request - - const authorizeEndpoint = "https://accounts.google.com/o/oauth2/auth" - const redirectUrl = encodeURIComponent(params.redirectUri) - const loginUrl = `${authorizeEndpoint}?client_id=${this.clientId}&redirect_uri=${redirectUrl}&response_type=code&scope=${scope}&state=${params.state}` + const authorizeEndpoint = "https://accounts.google.com/o/oauth2/auth"; + const redirectUrl = encodeURIComponent(params.redirectUri); + const loginUrl = `${authorizeEndpoint}?client_id=${this.clientId}&redirect_uri=${redirectUrl}&response_type=code&scope=${scope}&state=${params.state}`; return { loginUrl, - ticketValue: { - }, + ticketValue: {}, }; } async onCallback(req: OnCallbackReq) { - - const code = req.code || "" + const code = req.code || ""; - const tokenEndpoint = "https://oauth2.googleapis.com/token" + const tokenEndpoint = "https://oauth2.googleapis.com/token"; - const uri = new URL(req.currentURL) - const redirectUri = `${uri.origin}${uri.pathname}` - const res = await this.ctx.utils.http.request( { - url: tokenEndpoint, - method: "post", - headers: { - "Content-Type": "application/x-www-form-urlencoded" - }, - data:{ - client_id: this.clientId, - client_secret: this.clientSecretKey, - code, - redirect_uri: redirectUri, - grant_type: "authorization_code" - } - }) - - const tokens = res + const uri = new URL(req.currentURL); + const redirectUri = `${uri.origin}${uri.pathname}`; + const res = await this.ctx.utils.http.request({ + url: tokenEndpoint, + method: "post", + headers: { + "Content-Type": "application/x-www-form-urlencoded", + }, + data: { + client_id: this.clientId, + client_secret: this.clientSecretKey, + code, + redirect_uri: redirectUri, + grant_type: "authorization_code", + }, + }); - const userInfoEndpoint = "https://www.googleapis.com/oauth2/v3/userinfo" + const tokens = res; + + const userInfoEndpoint = "https://www.googleapis.com/oauth2/v3/userinfo"; // 获取用户信息 - const userInfoRes = await this.ctx.utils.http.request( { - url: userInfoEndpoint, - method: "get", - headers: { - "Authorization": `Bearer ${tokens.access_token}` - } - }) - const userInfo = userInfoRes + const userInfoRes = await this.ctx.utils.http.request({ + url: userInfoEndpoint, + method: "get", + headers: { + Authorization: `Bearer ${tokens.access_token}`, + }, + }); + const userInfo = userInfoRes; return { - token:{ + token: { accessToken: tokens.access_token, refreshToken: tokens.refresh_token, expiresIn: tokens.expires_in, @@ -89,10 +85,10 @@ export class GoogleOauthProvider extends BaseAddon implements IOauthProvider { nickName: userInfo.name || userInfo.email || "", avatar: userInfo.picture, }, - } - }; + }; + } async buildLogoutUrl(params: BuildLogoutUrlReq) { return {}; } -} \ No newline at end of file +} diff --git a/packages/ui/certd-server/src/plugins/plugin-oauth/oauth2/plugin-microsoft.ts b/packages/ui/certd-server/src/plugins/plugin-oauth/oauth2/plugin-microsoft.ts index 63a39c877..9ee219c01 100644 --- a/packages/ui/certd-server/src/plugins/plugin-oauth/oauth2/plugin-microsoft.ts +++ b/packages/ui/certd-server/src/plugins/plugin-oauth/oauth2/plugin-microsoft.ts @@ -3,14 +3,13 @@ import { BuildLoginUrlReq, BuildLogoutUrlReq, IOauthProvider, OnCallbackReq } fr @IsAddon({ addonType: "oauth", - name: 'microsoft', - title: 'Microsoft认证', - desc: 'Microsoft OAuth2登录', - icon:"simple-icons:microsoft", + name: "microsoft", + title: "Microsoft认证", + desc: "Microsoft OAuth2登录", + icon: "simple-icons:microsoft", showTest: false, }) export class MicrosoftOauthProvider extends BaseAddon implements IOauthProvider { - @AddonInput({ title: "ClientId", helper: "[Microsoft Entra ID](https://portal.azure.com/#view/Microsoft_AAD_IAM/ActiveDirectoryMenuBlade/~/RegisteredApps)创建应用后获取", @@ -23,7 +22,7 @@ export class MicrosoftOauthProvider extends BaseAddon implements IOauthProvider component: { placeholder: "ClientSecretKey / appSecretKey", }, - helper:"客户端凭据->证书与机密->客户端密码->新客户端密码", + helper: "客户端凭据->证书与机密->客户端密码->新客户端密码", required: true, }) clientSecretKey = ""; @@ -33,72 +32,69 @@ export class MicrosoftOauthProvider extends BaseAddon implements IOauthProvider component: { placeholder: "common 或 租户ID", }, - helper:"根据受支持的账户类型填写 common 或 租户ID,默认为common(Microsoft个人账户)。 \n租户ID获取: 概述 -> 目录(租户) ID ", + helper: "根据受支持的账户类型填写 common 或 租户ID,默认为common(Microsoft个人账户)。 \n租户ID获取: 概述 -> 目录(租户) ID ", value: "common", required: false, }) tenantId = "common"; async buildLoginUrl(params: BuildLoginUrlReq) { - - let scope = "openid profile email User.Read" // Scope of the access request - const authorizeEndpoint = `https://login.microsoftonline.com/${this.tenantId}/oauth2/v2.0/authorize` - const redirectUrl = encodeURIComponent(params.redirectUri) - const loginUrl = `${authorizeEndpoint}?client_id=${this.clientId}&redirect_uri=${redirectUrl}&response_type=code&scope=${scope}&state=${params.state}` + const scope = "openid profile email User.Read"; // Scope of the access request + const authorizeEndpoint = `https://login.microsoftonline.com/${this.tenantId}/oauth2/v2.0/authorize`; + const redirectUrl = encodeURIComponent(params.redirectUri); + const loginUrl = `${authorizeEndpoint}?client_id=${this.clientId}&redirect_uri=${redirectUrl}&response_type=code&scope=${scope}&state=${params.state}`; return { loginUrl, - ticketValue: { - }, + ticketValue: {}, }; } async onCallback(req: OnCallbackReq) { - - const code = req.code || "" + const code = req.code || ""; if (!code) { throw new Error("Missing code parameter"); } - const tokenEndpoint = `https://login.microsoftonline.com/${this.tenantId}/oauth2/v2.0/token` + const tokenEndpoint = `https://login.microsoftonline.com/${this.tenantId}/oauth2/v2.0/token`; + + const uri = new URL(req.currentURL); + const redirectUri = `${uri.origin}${uri.pathname}`; - const uri = new URL(req.currentURL) - const redirectUri = `${uri.origin}${uri.pathname}` - // 构建 form-urlencoded 格式的数据 const formData = new URLSearchParams(); - formData.append('client_id', this.clientId); - formData.append('client_secret', this.clientSecretKey); - formData.append('code', code); - formData.append('redirect_uri', redirectUri); - formData.append('grant_type', 'authorization_code'); + formData.append("client_id", this.clientId); + formData.append("client_secret", this.clientSecretKey); + formData.append("code", code); + formData.append("redirect_uri", redirectUri); + formData.append("grant_type", "authorization_code"); - const res = await this.ctx.utils.http.request( { - url: tokenEndpoint, - method: "post", - headers: { - "Content-Type": "application/x-www-form-urlencoded", - "Accept": "application/json" - }, - data: formData.toString() - }) - - const tokens = res + const res = await this.ctx.utils.http.request({ + url: tokenEndpoint, + method: "post", + headers: { + "Content-Type": "application/x-www-form-urlencoded", + Accept: "application/json", + }, + data: formData.toString(), + }); - const userInfoEndpoint = "https://graph.microsoft.com/v1.0/me" + const tokens = res; + + const userInfoEndpoint = "https://graph.microsoft.com/v1.0/me"; // 获取用户信息 - const userInfoRes = await this.ctx.utils.http.request( { - url: userInfoEndpoint, - method: "get", - headers: { - "Authorization": `Bearer ${tokens.access_token}`, - "Accept": "application/json" - } - }) - const userInfo = userInfoRes + const userInfoRes = await this.ctx.utils.http.request({ + url: userInfoEndpoint, + method: "get", + headers: { + Authorization: `Bearer ${tokens.access_token}`, + Accept: "application/json", + }, + }); + const userInfo = userInfoRes; return { - token:{ + token: { accessToken: tokens.access_token, refreshToken: tokens.refresh_token, expiresIn: tokens.expires_in, @@ -108,10 +104,10 @@ export class MicrosoftOauthProvider extends BaseAddon implements IOauthProvider nickName: userInfo.displayName || userInfo.userPrincipalName || "", avatar: userInfo.avatar || "", }, - } - }; + }; + } async buildLogoutUrl(params: BuildLogoutUrlReq) { return {}; } -} \ No newline at end of file +} diff --git a/packages/ui/certd-server/src/plugins/plugin-oauth/oidc/plugin-oidc.ts b/packages/ui/certd-server/src/plugins/plugin-oauth/oidc/plugin-oidc.ts index d42b61403..1af5a922e 100644 --- a/packages/ui/certd-server/src/plugins/plugin-oauth/oidc/plugin-oidc.ts +++ b/packages/ui/certd-server/src/plugins/plugin-oauth/oidc/plugin-oidc.ts @@ -4,19 +4,18 @@ import { IconSets } from "../iconsets.js"; @IsAddon({ addonType: "oauth", - name: 'oidc', - title: 'OIDC认证', - desc: 'OpenID Connect 认证,统一认证服务', - icon:"simple-icons:fusionauth:#006be6", + name: "oidc", + title: "OIDC认证", + desc: "OpenID Connect 认证,统一认证服务", + icon: "simple-icons:fusionauth:#006be6", showTest: false, }) export class OidcOauthProvider extends BaseAddon implements IOauthProvider { - @AddonInput({ title: "自定义图标", component: { - name:"fs-icon-selector", - vModel:"modelValue", + name: "fs-icon-selector", + vModel: "modelValue", iconSets: IconSets, }, required: false, @@ -49,53 +48,48 @@ export class OidcOauthProvider extends BaseAddon implements IOauthProvider { }) issuerUrl = ""; - async getClient() { - const client = await import('openid-client') - let server = new URL(this.issuerUrl)// Authorization Server's Issuer Identifier + const client = await import("openid-client"); + const server = new URL(this.issuerUrl); // Authorization Server's Issuer Identifier - let config = await client.discovery( - server, - this.clientId, - this.clientSecretKey, - ) + const config = await client.discovery(server, this.clientId, this.clientSecretKey); // console.log(config.serverMetadata()) return { config, - client - } + client, + }; } - - async buildLoginUrl(params: BuildLoginUrlReq) { - const { config, client } = await this.getClient() - let redirect_uri = new URL(params.redirectUri) - let scope = 'openid profile' // Scope of the access request + async buildLoginUrl(params: BuildLoginUrlReq) { + const { config, client } = await this.getClient(); + + const redirect_uri = new URL(params.redirectUri); + const scope = "openid profile"; // Scope of the access request /** * PKCE: The following MUST be generated for every redirect to the * authorization_endpoint. You must store the code_verifier and state in the * end-user session such that it can be recovered as the user gets redirected * from the authorization server back to your application. */ - let code_verifier = client.randomPKCECodeVerifier() - let code_challenge = await client.calculatePKCECodeChallenge(code_verifier) - let state:any = { - forType: params.forType || 'login', - } - state = this.ctx.utils.hash.base64(JSON.stringify(state)) + const code_verifier = client.randomPKCECodeVerifier(); + const code_challenge = await client.calculatePKCECodeChallenge(code_verifier); + let state: any = { + forType: params.forType || "login", + }; + state = this.ctx.utils.hash.base64(JSON.stringify(state)); - let parameters: any = { + const parameters: any = { redirect_uri, scope, code_challenge, - code_challenge_method: 'S256', + code_challenge_method: "S256", state, nonce: client.randomNonce(), - } + }; - let redirectTo = client.buildAuthorizationUrl(config, parameters) + const redirectTo = client.buildAuthorizationUrl(config, parameters); return { loginUrl: redirectTo.href, ticketValue: { @@ -107,22 +101,17 @@ export class OidcOauthProvider extends BaseAddon implements IOauthProvider { } async onCallback(req: OnCallbackReq) { - const { config, client } = await this.getClient() + const { config, client } = await this.getClient(); - - let tokens: any = await client.authorizationCodeGrant( - config, - req.currentURL, - { - expectedState: req.ticketValue.state, - pkceCodeVerifier: req.ticketValue.codeVerifier, - expectedNonce: req.ticketValue.nonce, - } - ) + const tokens: any = await client.authorizationCodeGrant(config, req.currentURL, { + expectedState: req.ticketValue.state, + pkceCodeVerifier: req.ticketValue.codeVerifier, + expectedNonce: req.ticketValue.nonce, + }); - const claims = tokens.claims() + const claims = tokens.claims(); return { - token:{ + token: { accessToken: tokens.access_token, refreshToken: tokens.refresh_token, expiresIn: tokens.expires_in, @@ -133,18 +122,18 @@ export class OidcOauthProvider extends BaseAddon implements IOauthProvider { avatar: claims.picture, email: claims.email || "", }, - } - }; + }; + } async buildLogoutUrl(params: BuildLogoutUrlReq) { - try{ - const { config } = await this.getClient() - let logoutUrl = config.serverMetadata().end_session_endpoint + try { + const { config } = await this.getClient(); + const logoutUrl = config.serverMetadata().end_session_endpoint; return { logoutUrl: logoutUrl, }; - }catch(err){ - this.logger.error(`获取注销地址失败: ${err}`) + } catch (err) { + this.logger.error(`获取注销地址失败: ${err}`); return { logoutUrl: "", }; diff --git a/packages/ui/certd-server/src/plugins/plugin-oauth/wx/plugin-wx.ts b/packages/ui/certd-server/src/plugins/plugin-oauth/wx/plugin-wx.ts index 15d9ffe49..ba83a245b 100644 --- a/packages/ui/certd-server/src/plugins/plugin-oauth/wx/plugin-wx.ts +++ b/packages/ui/certd-server/src/plugins/plugin-oauth/wx/plugin-wx.ts @@ -3,14 +3,13 @@ import { BuildLoginUrlReq, BuildLogoutUrlReq, IOauthProvider, OnCallbackReq } fr @IsAddon({ addonType: "oauth", - name: 'wx', - title: '微信登录', - desc: '微信网站应用登录', + name: "wx", + title: "微信登录", + desc: "微信网站应用登录", icon: "ion:logo-wechat:green", showTest: false, }) export class WxOauthProvider extends BaseAddon implements IOauthProvider { - @AddonInput({ title: "AppId", required: true, @@ -27,24 +26,22 @@ export class WxOauthProvider extends BaseAddon implements IOauthProvider { }) appSecretKey = ""; - - wxAccessToken?: { access_token: string, expires_at: number } + wxAccessToken?: { access_token: string; expires_at: number }; async buildLoginUrl(params: BuildLoginUrlReq) { - const from = params.from || "web"; const appId = this.appId; const redirect_uri = encodeURIComponent(params.redirectUri); let state: any = { forType: params.forType, - from - } - state = this.ctx.utils.hash.base64(JSON.stringify(state)) + from, + }; + state = this.ctx.utils.hash.base64(JSON.stringify(state)); let scope = "snsapi_userinfo"; - let loginUrl = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appId}&redirect_uri=${redirect_uri}&response_type=code&scope=${scope}&state=${state}#wechat_redirect` + let loginUrl = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appId}&redirect_uri=${redirect_uri}&response_type=code&scope=${scope}&state=${state}#wechat_redirect`; if (from === "web") { scope = "snsapi_login"; - loginUrl = `https://open.weixin.qq.com/connect/qrconnect?appid=${appId}&redirect_uri=${redirect_uri}&response_type=code&scope=${scope}&state=${state}#wechat_redirect` + loginUrl = `https://open.weixin.qq.com/connect/qrconnect?appid=${appId}&redirect_uri=${redirect_uri}&response_type=code&scope=${scope}&state=${state}#wechat_redirect`; } return { @@ -78,13 +75,11 @@ export class WxOauthProvider extends BaseAddon implements IOauthProvider { checkRet(res: any) { if (res.errcode) { - throw new Error(res.errmsg) + throw new Error(res.errmsg); } } async onCallback(req: OnCallbackReq) { - - // GET https://api.weixin.qq.com/sns/oauth2/access_token?appid=wx520c15f417810387&secret=SECRET&code=CODE&grant_type=authorization_code const res = await this.http.request({ url: "https://api.weixin.qq.com/sns/oauth2/access_token", @@ -95,22 +90,21 @@ export class WxOauthProvider extends BaseAddon implements IOauthProvider { code: req.code, grant_type: "authorization_code", }, - }) - this.checkRet(res) - const accessToken = res.access_token - + }); + this.checkRet(res); + const accessToken = res.access_token; // GET https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN const userInfoRes = await this.http.request({ url: "https://api.weixin.qq.com/sns/userinfo", method: "GET", params: { - access_token:accessToken, + access_token: accessToken, openid: res.openid, lang: "zh_CN", }, - }) - this.checkRet(userInfoRes) + }); + this.checkRet(userInfoRes); return { token: { @@ -123,9 +117,8 @@ export class WxOauthProvider extends BaseAddon implements IOauthProvider { nickName: userInfoRes.nickname || "", avatar: userInfoRes.headimgurl, }, - } - }; - + }; + } async buildLogoutUrl(params: BuildLogoutUrlReq) { return {}; diff --git a/packages/ui/certd-server/src/plugins/plugin-other/index.ts b/packages/ui/certd-server/src/plugins/plugin-other/index.ts index 4ab82c2d6..68bc642b3 100644 --- a/packages/ui/certd-server/src/plugins/plugin-other/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-other/index.ts @@ -1 +1 @@ -export * from './plugins/index.js'; +export * from "./plugins/index.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-other/plugins/index.ts b/packages/ui/certd-server/src/plugins/plugin-other/plugins/index.ts index e84abfc78..dad79ebc7 100644 --- a/packages/ui/certd-server/src/plugins/plugin-other/plugins/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-other/plugins/index.ts @@ -1,3 +1,3 @@ -export * from './plugin-wait.js'; -export * from './plugin-deploy-to-mail.js'; -export * from './plugin-webhook.js'; +export * from "./plugin-wait.js"; +export * from "./plugin-deploy-to-mail.js"; +export * from "./plugin-webhook.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-other/plugins/plugin-deploy-to-mail.ts b/packages/ui/certd-server/src/plugins/plugin-other/plugins/plugin-deploy-to-mail.ts index b9a944b4d..233134727 100644 --- a/packages/ui/certd-server/src/plugins/plugin-other/plugins/plugin-deploy-to-mail.ts +++ b/packages/ui/certd-server/src/plugins/plugin-other/plugins/plugin-deploy-to-mail.ts @@ -1,13 +1,13 @@ -import { AbstractTaskPlugin, FileItem, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from '@certd/pipeline'; +import { AbstractTaskPlugin, FileItem, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; import { CertInfo, CertReader } from "@certd/plugin-cert"; import dayjs from "dayjs"; -import { get } from 'lodash-es'; +import { get } from "lodash-es"; @IsTaskPlugin({ - name: 'DeployCertToMailPlugin', - title: '邮件发送证书', - icon: 'ion:mail-outline', - desc: '通过邮件发送证书', + name: "DeployCertToMailPlugin", + title: "邮件发送证书", + icon: "ion:mail-outline", + desc: "通过邮件发送证书", group: pluginGroups.other.key, showRunStrategy: false, default: { @@ -17,12 +17,11 @@ import { get } from 'lodash-es'; }, }) export class DeployCertToMailPlugin extends AbstractTaskPlugin { - @TaskInput({ - title: '域名证书', - helper: '请选择前置任务输出的域名证书', + title: "域名证书", + helper: "请选择前置任务输出的域名证书", component: { - name: 'output-selector', + name: "output-selector", from: [":cert:"], }, required: true, @@ -30,10 +29,10 @@ export class DeployCertToMailPlugin extends AbstractTaskPlugin { cert!: CertInfo; @TaskInput({ - title: '证书压缩文件', - helper: '请选择前置任务输出的域名证书压缩文件', + title: "证书压缩文件", + helper: "请选择前置任务输出的域名证书压缩文件", component: { - name: 'output-selector', + name: "output-selector", from: [":certZip:"], }, required: true, @@ -41,17 +40,16 @@ export class DeployCertToMailPlugin extends AbstractTaskPlugin { certZip!: FileItem; @TaskInput({ - title: '接收邮箱', + title: "接收邮箱", component: { - name: 'EmailSelector', - vModel: 'value', + name: "EmailSelector", + vModel: "value", mode: "tags", }, required: true, }) email!: string[]; - /** * title: * title: 邮件标题 @@ -77,60 +75,57 @@ export class DeployCertToMailPlugin extends AbstractTaskPlugin { * required: false */ + // @TaskInput({ + // title: '邮件标题', + // component: { + // name: 'a-input', + // vModel: 'value', + // placeholder: `证书申请成功【$\{mainDomain}】`, + // }, + // helper: '请输入邮件标题否则将使用默认标题\n模板变量:主域名=$\{mainDomain}、全部域名=$\{domains}、过期时间=$\{expiresTime}、备注=$\{remark}、证书PEM=$\{crt}、证书私钥=$\{key}、中间证书/CA证书=$\{ic}', + // required: false, + // }) + // title!: string; -// @TaskInput({ -// title: '邮件标题', -// component: { -// name: 'a-input', -// vModel: 'value', -// placeholder: `证书申请成功【$\{mainDomain}】`, -// }, -// helper: '请输入邮件标题否则将使用默认标题\n模板变量:主域名=$\{mainDomain}、全部域名=$\{domains}、过期时间=$\{expiresTime}、备注=$\{remark}、证书PEM=$\{crt}、证书私钥=$\{key}、中间证书/CA证书=$\{ic}', -// required: false, -// }) -// title!: string; - -// @TaskInput({ -// title: '邮件模版', -// component: { -// name: 'a-textarea', -// vModel: 'value', -// autosize: { -// minRows: 6, -// maxRows: 10, -// }, -// placeholder: ` -//
-//

证书申请成功

-//

域名:$\{domains}

-//

证书有效期:$\{expiresTime}

-//

备注:$\{remark}

-//
-// `, -// }, -// helper: `请输入模版内容否则将使用默认模版,模板变量同上`, -// required: false, -// }) -// template!: string; + // @TaskInput({ + // title: '邮件模版', + // component: { + // name: 'a-textarea', + // vModel: 'value', + // autosize: { + // minRows: 6, + // maxRows: 10, + // }, + // placeholder: ` + //
+ //

证书申请成功

+ //

域名:$\{domains}

+ //

证书有效期:$\{expiresTime}

+ //

备注:$\{remark}

+ //
+ // `, + // }, + // helper: `请输入模版内容否则将使用默认模版,模板变量同上`, + // required: false, + // }) + // template!: string; @TaskInput({ - title: '备注', + title: "备注", component: { - name: 'a-input', - vModel: 'value', + name: "a-input", + vModel: "value", }, required: false, }) remark!: string; - async onInstance() { } + async onInstance() {} async execute(): Promise { - this.logger.info(`开始发送邮件`); - const certReader = new CertReader(this.cert) + const certReader = new CertReader(this.cert); const mainDomain = certReader.getMainDomain(); - const domains = certReader.getAllDomains().join(','); - + const domains = certReader.getAllDomains().join(","); const data: any = { mainDomain, @@ -140,20 +135,20 @@ export class DeployCertToMailPlugin extends AbstractTaskPlugin { crt: this.cert.crt, key: this.cert.key, ic: this.cert.ic, - url: "" - } + url: "", + }; - let title = `证书申请成功【${mainDomain}】`; - let content = `证书申请成功 + const title = `证书申请成功【${mainDomain}】`; + const content = `证书申请成功 域名:${domains} 证书有效期:${data.expiresTime} 备注:${this.remark || ""} `; data.content = content; - data.title = title - const file = this.certZip + data.title = title; + const file = this.certZip; if (!file) { - throw new Error('证书压缩文件还未生成,重新运行证书任务'); + throw new Error("证书压缩文件还未生成,重新运行证书任务"); } await this.ctx.emailService.sendByTemplate({ type: "sendCert", @@ -165,13 +160,13 @@ export class DeployCertToMailPlugin extends AbstractTaskPlugin { path: file.path, }, ], - }) + }); } compile(templateString: string) { return function (data) { return templateString.replace(/\${(.*?)}/g, (match, key) => { - const value = get(data, key, ''); + const value = get(data, key, ""); return String(value); }); }; diff --git a/packages/ui/certd-server/src/plugins/plugin-other/plugins/plugin-wait.ts b/packages/ui/certd-server/src/plugins/plugin-other/plugins/plugin-wait.ts index 41be6f9ce..a7c01dbf9 100644 --- a/packages/ui/certd-server/src/plugins/plugin-other/plugins/plugin-wait.ts +++ b/packages/ui/certd-server/src/plugins/plugin-other/plugins/plugin-wait.ts @@ -1,12 +1,12 @@ -import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from '@certd/pipeline'; +import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; @IsTaskPlugin({ - name: 'WaitPlugin', - title: '等待', - icon: 'ri:rest-time-line', - desc: '等待一段时间', + name: "WaitPlugin", + title: "等待", + icon: "ri:rest-time-line", + desc: "等待一段时间", group: pluginGroups.other.key, - showRunStrategy:true, + showRunStrategy: true, default: { strategy: { runStrategy: RunStrategy.SkipWhenSucceed, @@ -15,13 +15,13 @@ import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput }) export class WaitPlugin extends AbstractTaskPlugin { @TaskInput({ - title: '等待时长', + title: "等待时长", value: 30, component: { - name: 'a-input-number', - vModel: 'value', + name: "a-input-number", + vModel: "value", }, - helper: '单位:秒', + helper: "单位:秒", required: true, }) waitTime!: number; @@ -30,7 +30,7 @@ export class WaitPlugin extends AbstractTaskPlugin { async execute(): Promise { this.logger.info(`等待${this.waitTime}s`); await this.ctx.utils.sleep(this.waitTime * 1000); - this.logger.info('等待结束'); + this.logger.info("等待结束"); } } new WaitPlugin(); diff --git a/packages/ui/certd-server/src/plugins/plugin-other/plugins/plugin-webhook.ts b/packages/ui/certd-server/src/plugins/plugin-other/plugins/plugin-webhook.ts index 950163831..e04545677 100644 --- a/packages/ui/certd-server/src/plugins/plugin-other/plugins/plugin-webhook.ts +++ b/packages/ui/certd-server/src/plugins/plugin-other/plugins/plugin-webhook.ts @@ -1,18 +1,12 @@ -import qs from 'qs'; -import { - AbstractTaskPlugin, - IsTaskPlugin, - pluginGroups, - RunStrategy, - TaskInput -} from '@certd/pipeline'; -import {CertApplyPluginNames, CertInfo, CertReader} from "@certd/plugin-cert"; +import qs from "qs"; +import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; +import { CertApplyPluginNames, CertInfo, CertReader } from "@certd/plugin-cert"; @IsTaskPlugin({ - name: 'WebhookDeployCert', - title: 'webhook方式部署证书', - icon: 'ion:send-sharp', - desc: '调用webhook部署证书', + name: "WebhookDeployCert", + title: "webhook方式部署证书", + icon: "ion:send-sharp", + desc: "调用webhook部署证书", group: pluginGroups.other.key, showRunStrategy: false, default: { @@ -22,85 +16,84 @@ import {CertApplyPluginNames, CertInfo, CertReader} from "@certd/plugin-cert"; }, }) export class WebhookDeployCert extends AbstractTaskPlugin { - @TaskInput({ title: "域名证书", helper: "请选择前置任务输出的域名证书", component: { name: "output-selector", - from: [...CertApplyPluginNames] + from: [...CertApplyPluginNames], }, - required: true + required: true, }) cert!: CertInfo; @TaskInput({ - title: 'webhook地址', + title: "webhook地址", component: { - placeholder: 'https://xxxxx.com/xxxx', + placeholder: "https://xxxxx.com/xxxx", }, col: { span: 24, }, required: true, }) - webhook = ''; + webhook = ""; @TaskInput({ - title: '请求方式', - value: 'POST', + title: "请求方式", + value: "POST", component: { - name: 'a-select', - placeholder: 'post/put/get', + name: "a-select", + placeholder: "post/put/get", options: [ - {value: 'POST', label: 'POST'}, - {value: 'PUT', label: 'PUT'}, - {value: 'GET', label: 'GET'}, + { value: "POST", label: "POST" }, + { value: "PUT", label: "PUT" }, + { value: "GET", label: "GET" }, ], }, required: true, }) - method = ''; + method = ""; @TaskInput({ - title: 'ContentType', - value: 'application/json', + title: "ContentType", + value: "application/json", component: { - name: 'a-auto-complete', + name: "a-auto-complete", options: [ - {value: 'application/json', label: 'application/json'}, - {value: 'application/x-www-form-urlencoded', label: 'application/x-www-form-urlencoded'}, + { value: "application/json", label: "application/json" }, + { value: "application/x-www-form-urlencoded", label: "application/x-www-form-urlencoded" }, ], }, - helper: '也可以自定义填写', + helper: "也可以自定义填写", required: true, }) - contentType = ''; + contentType = ""; @TaskInput({ - title: 'Headers', + title: "Headers", component: { - name: 'a-textarea', - vModel: 'value', + name: "a-textarea", + vModel: "value", rows: 2, }, col: { span: 24, }, - helper: '一行一个,格式为key=value', + helper: "一行一个,格式为key=value", required: false, }) - headers = ''; + headers = ""; @TaskInput({ - title: '消息body模版', + title: "消息body模版", value: `{ "id":"123", "crt":"\${crt}", "key":"\${key}" }`, component: { - name: 'a-textarea', + name: "a-textarea", rows: 4, }, col: { @@ -112,29 +105,28 @@ export class WebhookDeployCert extends AbstractTaskPlugin { 变量列表:\${domain} 主域名、\${domains} 全部域名、\${crt} 证书、\${key} 私钥、\${ic} 中间证书、\${one} 一体证书、\${der} der证书(base64)、\${pfx} pfx证书(base64)、\${jks} jks证书(base64)、`, required: true, }) - template = ''; + template = ""; @TaskInput({ - title: '忽略证书校验', + title: "忽略证书校验", value: false, component: { - name: 'a-switch', - vModel: 'checked', + name: "a-switch", + vModel: "checked", }, required: false, }) skipSslVerify: boolean; - @TaskInput({ - title: '成功判定', + title: "成功判定", helper: "返回结果中包含此字符串则表示部署成功,不填则仅通过statusCode判定", component: { - name: 'a-input', + name: "a-input", placeholder: '例如: status:"success"', }, }) - successStr = ''; + successStr = ""; replaceTemplate(target: string, body: any, urlEncode = false) { let bodyStr = target; @@ -143,34 +135,32 @@ export class WebhookDeployCert extends AbstractTaskPlugin { let value = urlEncode ? encodeURIComponent(body[key]) : body[key]; value = value.replaceAll(`\n`, "\\n"); bodyStr = bodyStr.replaceAll(`\${${key}}`, value); - } return bodyStr; } async send() { if (!this.template) { - throw new Error('模版不能为空'); + throw new Error("模版不能为空"); } if (!this.webhook) { - throw new Error('webhook不能为空'); + throw new Error("webhook不能为空"); } - - const certReader = new CertReader(this.cert) + const certReader = new CertReader(this.cert); const replaceBody = { domain: certReader.getMainDomain(), domains: certReader.getAllDomains().join(","), - ...this.cert + ...this.cert, }; const bodyStr = this.replaceTemplate(this.template, replaceBody); let data = JSON.parse(bodyStr); let url = this.webhook; - if (this.method.toLowerCase() === 'get') { + if (this.method.toLowerCase() === "get") { const query = qs.stringify(data); - if (url.includes('?')) { + if (url.includes("?")) { url = `${url}&${query}`; } else { url = `${url}?${query}`; @@ -180,12 +170,12 @@ export class WebhookDeployCert extends AbstractTaskPlugin { const headers: any = {}; if (this.headers && this.headers.trim()) { - this.headers.split('\n').forEach(item => { + this.headers.split("\n").forEach(item => { item = item.trim(); if (item) { - const eqIndex = item.indexOf('='); + const eqIndex = item.indexOf("="); if (eqIndex <= 0) { - this.logger.warn('header格式错误,请使用=号分割', item); + this.logger.warn("header格式错误,请使用=号分割", item); return; } const key = item.substring(0, eqIndex); @@ -194,23 +184,23 @@ export class WebhookDeployCert extends AbstractTaskPlugin { }); } - let res = null + let res = null; try { res = await this.http.request({ url: url, method: this.method, headers: { - 'Content-Type': `${this.contentType}; charset=UTF-8`, + "Content-Type": `${this.contentType}; charset=UTF-8`, ...headers, }, data: data, skipSslVerify: this.skipSslVerify, responseType: "text", - returnOriginRes: true + returnOriginRes: true, }); } catch (e) { if (e.response?.data) { - throw new Error(e.message + ',' + JSON.stringify(e.response.data)); + throw new Error(e.message + "," + JSON.stringify(e.response.data)); } throw e; } @@ -218,16 +208,15 @@ export class WebhookDeployCert extends AbstractTaskPlugin { if (this.successStr && !res?.data?.includes(this.successStr)) { throw new Error(`请求失败,期望包含:${this.successStr},实际返回:${res.data}`); } - return res + return res; } - async onInstance() { - } + async onInstance() {} async execute(): Promise { this.logger.info(`通过webhook部署开始`); await this.send(); - this.logger.info('部署成功'); + this.logger.info("部署成功"); } } diff --git a/packages/ui/certd-server/src/plugins/plugin-plus/1panel/access.ts b/packages/ui/certd-server/src/plugins/plugin-plus/1panel/access.ts index a1bedc30f..b561b80b4 100644 --- a/packages/ui/certd-server/src/plugins/plugin-plus/1panel/access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-plus/1panel/access.ts @@ -152,7 +152,7 @@ export class OnePanelAccess extends BaseAccess { page: 1, pageSize: 1, order: "ascending", - orderBy: "expire_date" + orderBy: "expire_date", }, }); return "ok"; diff --git a/packages/ui/certd-server/src/plugins/plugin-plus/1panel/client.ts b/packages/ui/certd-server/src/plugins/plugin-plus/1panel/client.ts index e2b1cd89c..cdb5f6093 100644 --- a/packages/ui/certd-server/src/plugins/plugin-plus/1panel/client.ts +++ b/packages/ui/certd-server/src/plugins/plugin-plus/1panel/client.ts @@ -93,8 +93,8 @@ export class OnePanelClient { if (res.code === 200) { return res.data; } - if (res?.message?.includes("record not found")){ - throw new Error("没有找到证书,请确认证书在1panel上是否已被删除,如果被删除请重新选择新的证书id:"+ config.url); + if (res?.message?.includes("record not found")) { + throw new Error("没有找到证书,请确认证书在1panel上是否已被删除,如果被删除请重新选择新的证书id:" + config.url); } throw new Error(res.message); } diff --git a/packages/ui/certd-server/src/plugins/plugin-plus/1panel/plugins/deploy-to-panel.ts b/packages/ui/certd-server/src/plugins/plugin-plus/1panel/plugins/deploy-to-panel.ts index 4dbdc197e..0c0b72480 100644 --- a/packages/ui/certd-server/src/plugins/plugin-plus/1panel/plugins/deploy-to-panel.ts +++ b/packages/ui/certd-server/src/plugins/plugin-plus/1panel/plugins/deploy-to-panel.ts @@ -67,7 +67,7 @@ export class OnePanelDeployToPanelPlugin extends AbstractTaskPlugin { options: [ { label: "启用SSL(旧版本)", value: "enable" }, { label: "Strict模式(>=2.1.x)", value: "Enable" }, - { label: "Mux模式(>=2.1.x)", value: "Mux" } + { label: "Mux模式(>=2.1.x)", value: "Mux" }, ], }, value: "enable", @@ -81,7 +81,6 @@ export class OnePanelDeployToPanelPlugin extends AbstractTaskPlugin { } //http://xxx:xxxx/1panel/swagger/index.html#/App/get_apps__key async execute(): Promise { - const client = new OnePanelClient({ access: this.access, http: this.http, @@ -89,7 +88,6 @@ export class OnePanelDeployToPanelPlugin extends AbstractTaskPlugin { utils: this.ctx.utils, }); - const certReader = new CertReader(this.cert); const domain = certReader.getMainDomain(); @@ -129,7 +127,6 @@ export class OnePanelDeployToPanelPlugin extends AbstractTaskPlugin { await this.ctx.utils.sleep(10000); this.logger.info(`证书更新完成`); - } isNeedUpdate(certRes: any) { @@ -140,8 +137,6 @@ export class OnePanelDeployToPanelPlugin extends AbstractTaskPlugin { return true; } - - async onGetNodes() { const options = [{ label: "主节点", value: "local" }]; if (this.access.apiVersion === "v1") { @@ -166,6 +161,5 @@ export class OnePanelDeployToPanelPlugin extends AbstractTaskPlugin { // console.log('resp', resp) return [...options, ...(resp?.map(item => ({ label: `${item.addr}(${item.name})`, value: item.name })) || [])]; } - } new OnePanelDeployToPanelPlugin(); diff --git a/packages/ui/certd-server/src/plugins/plugin-plus/1panel/plugins/deploy-to-website.ts b/packages/ui/certd-server/src/plugins/plugin-plus/1panel/plugins/deploy-to-website.ts index 6f9806eee..cd937f543 100644 --- a/packages/ui/certd-server/src/plugins/plugin-plus/1panel/plugins/deploy-to-website.ts +++ b/packages/ui/certd-server/src/plugins/plugin-plus/1panel/plugins/deploy-to-website.ts @@ -66,7 +66,7 @@ export class OnePanelDeployToWebsitePlugin extends AbstractTaskPlugin { watches: ["accessId"], helper: "要更新的1Panel证书id,选择授权之后,从下拉框中选择\nIP需要加白名单,如果是同一台机器部署的,可以试试172.16.0.0/12", required: true, - uploadCert: {} + uploadCert: {}, }) ) sslIds!: string[]; @@ -196,7 +196,7 @@ export class OnePanelDeployToWebsitePlugin extends AbstractTaskPlugin { page: 1, pageSize: 99999, order: "ascending", - orderBy: "expire_date" + orderBy: "expire_date", }, currentNode: this.currentNode, }); @@ -215,11 +215,11 @@ export class OnePanelDeployToWebsitePlugin extends AbstractTaskPlugin { return this.ctx.utils.options.buildGroupOptions(list, this.certDomains); } - async onUploadCert(data: { pipelineId: string, certName: string }) { + async onUploadCert(data: { pipelineId: string; certName: string }) { if (!this.access) { throw new Error("请先选择1panel授权"); } - const certInfoGetter = await this.ctx.serviceGetter.get("certInfoGetter") + const certInfoGetter = await this.ctx.serviceGetter.get("certInfoGetter"); const cert = await certInfoGetter.getByPipelineId(Number(data.pipelineId)); const client = new OnePanelClient({ @@ -243,7 +243,6 @@ export class OnePanelDeployToWebsitePlugin extends AbstractTaskPlugin { }, currentNode: this.currentNode, }); - } } new OnePanelDeployToWebsitePlugin(); diff --git a/packages/ui/certd-server/src/plugins/plugin-plus/1panel/plugins/index.ts b/packages/ui/certd-server/src/plugins/plugin-plus/1panel/plugins/index.ts index 85177a80d..59f5aba1f 100644 --- a/packages/ui/certd-server/src/plugins/plugin-plus/1panel/plugins/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-plus/1panel/plugins/index.ts @@ -1,2 +1,2 @@ export * from "./deploy-to-website.js"; -export * from "./deploy-to-panel.js"; \ No newline at end of file +export * from "./deploy-to-panel.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-plus/1panel/util.ts b/packages/ui/certd-server/src/plugins/plugin-plus/1panel/util.ts index c7f20ef79..e5241e0d7 100644 --- a/packages/ui/certd-server/src/plugins/plugin-plus/1panel/util.ts +++ b/packages/ui/certd-server/src/plugins/plugin-plus/1panel/util.ts @@ -41,7 +41,7 @@ function generateAESKey(): string { const randomBytes = new Uint8Array(keyLength); crypto.getRandomValues(randomBytes); return Array.from(randomBytes) - .map((b) => b.toString(16).padStart(2, "0")) + .map(b => b.toString(16).padStart(2, "0")) .join(""); } diff --git a/packages/ui/certd-server/src/plugins/plugin-plus/baidu/plugins/plugin-deploy-to-cce.ts b/packages/ui/certd-server/src/plugins/plugin-plus/baidu/plugins/plugin-deploy-to-cce.ts index 45d251e14..6685d85ba 100644 --- a/packages/ui/certd-server/src/plugins/plugin-plus/baidu/plugins/plugin-deploy-to-cce.ts +++ b/packages/ui/certd-server/src/plugins/plugin-plus/baidu/plugins/plugin-deploy-to-cce.ts @@ -227,7 +227,7 @@ export class DeployCertToBaiduCcePlugin extends AbstractTaskPlugin { secretNames = [secretName]; } for (const secret of secretNames) { - await k8sClient.patchSecret({ namespace, secretName: secret, body ,createOnNotFound: this.createOnNotFound}); + await k8sClient.patchSecret({ namespace, secretName: secret, body, createOnNotFound: this.createOnNotFound }); this.logger.info(`cert secret已更新: ${secret}`); } } @@ -242,4 +242,4 @@ export class DeployCertToBaiduCcePlugin extends AbstractTaskPlugin { } } -new DeployCertToBaiduCcePlugin(); \ No newline at end of file +new DeployCertToBaiduCcePlugin(); diff --git a/packages/ui/certd-server/src/plugins/plugin-plus/baota/index.ts b/packages/ui/certd-server/src/plugins/plugin-plus/baota/index.ts index b755db5ce..6609af663 100644 --- a/packages/ui/certd-server/src/plugins/plugin-plus/baota/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-plus/baota/index.ts @@ -1,4 +1,4 @@ export * from "./plugins/index.js"; export * from "./access.js"; export * from "./waf-access.js"; -export * from "./lib/client.js"; \ No newline at end of file +export * from "./lib/client.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-plus/ctyun/access/ctyun-access.ts b/packages/ui/certd-server/src/plugins/plugin-plus/ctyun/access/ctyun-access.ts index b0e845302..6960d1b3c 100644 --- a/packages/ui/certd-server/src/plugins/plugin-plus/ctyun/access/ctyun-access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-plus/ctyun/access/ctyun-access.ts @@ -30,8 +30,6 @@ export class CtyunAccess extends BaseAccess { }) securityKey = ""; - - @AccessInput({ title: "测试", component: { @@ -43,23 +41,23 @@ export class CtyunAccess extends BaseAccess { testRequest = true; async onTestRequest() { - await this.getCdnDomainList() + await this.getCdnDomainList(); return "ok"; } - async getCdnDomainList() { - const http: HttpClient = this.ctx.http; - const client = new CtyunClient({ - access:this, - http, - logger: this.ctx.logger, - }); - - // 008 是天翼云的CDN加速域名产品码 - const all = await client.getDomainList({ productCode: "008" }); - const list = all || [] - return list - } + async getCdnDomainList() { + const http: HttpClient = this.ctx.http; + const client = new CtyunClient({ + access: this, + http, + logger: this.ctx.logger, + }); + + // 008 是天翼云的CDN加速域名产品码 + const all = await client.getDomainList({ productCode: "008" }); + const list = all || []; + return list; + } } new CtyunAccess(); diff --git a/packages/ui/certd-server/src/plugins/plugin-plus/ctyun/index.ts b/packages/ui/certd-server/src/plugins/plugin-plus/ctyun/index.ts index 87d7259bb..b157264f7 100644 --- a/packages/ui/certd-server/src/plugins/plugin-plus/ctyun/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-plus/ctyun/index.ts @@ -1,3 +1,3 @@ export * from "./plugins/index.js"; export * from "./access/ctyun-access.js"; -export * from "./lib.js"; \ No newline at end of file +export * from "./lib.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-plus/esxi/index.ts b/packages/ui/certd-server/src/plugins/plugin-plus/esxi/index.ts index a32509f31..f43002a60 100644 --- a/packages/ui/certd-server/src/plugins/plugin-plus/esxi/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-plus/esxi/index.ts @@ -1 +1 @@ -export * from "./plugin-deploy-to-esxi.js"; \ No newline at end of file +export * from "./plugin-deploy-to-esxi.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-plus/esxi/plugin-deploy-to-esxi.ts b/packages/ui/certd-server/src/plugins/plugin-plus/esxi/plugin-deploy-to-esxi.ts index 66cd69f2f..abf51c92f 100644 --- a/packages/ui/certd-server/src/plugins/plugin-plus/esxi/plugin-deploy-to-esxi.ts +++ b/packages/ui/certd-server/src/plugins/plugin-plus/esxi/plugin-deploy-to-esxi.ts @@ -43,8 +43,7 @@ export class EsxiDeployCertPlugin extends AbstractPlusTaskPlugin { }) accessId!: string; - - async onInstance() { } + async onInstance() {} async execute(): Promise { const sshConf = await this.getAccess(this.accessId); @@ -56,7 +55,7 @@ export class EsxiDeployCertPlugin extends AbstractPlusTaskPlugin { await certReader.readCertFile({ logger: this.logger, - handle: async (ctx) => { + handle: async ctx => { const crtPath = ctx.tmpCrtPath; const keyPath = ctx.tmpKeyPath; await sshClient.uploadFiles({ @@ -77,7 +76,7 @@ export class EsxiDeployCertPlugin extends AbstractPlusTaskPlugin { }); const cmd = `/etc/init.d/hostd restart -/etc/init.d/vpxa restart` +/etc/init.d/vpxa restart`; await sshClient.exec({ connectConf: sshConf, diff --git a/packages/ui/certd-server/src/plugins/plugin-plus/k8s/access.ts b/packages/ui/certd-server/src/plugins/plugin-plus/k8s/access.ts index 4c951ee90..38a7c1964 100644 --- a/packages/ui/certd-server/src/plugins/plugin-plus/k8s/access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-plus/k8s/access.ts @@ -30,8 +30,6 @@ export class K8sAccess extends BaseAccess { }) skipTLSVerify: boolean; - - @AccessInput({ title: "测试", component: { @@ -43,13 +41,12 @@ export class K8sAccess extends BaseAccess { testRequest = true; async onTestRequest() { - - const k8sClient = await this.getK8sClient() + const k8sClient = await this.getK8sClient(); await k8sClient.getSecrets({ namespace: "default", - }) + }); return "ok"; - } + } async getK8sClient() { const sdk = await import("@certd/lib-k8s"); @@ -62,7 +59,6 @@ export class K8sAccess extends BaseAccess { }); return k8sClient; } - } new K8sAccess(); diff --git a/packages/ui/certd-server/src/plugins/plugin-plus/kuocai/access.ts b/packages/ui/certd-server/src/plugins/plugin-plus/kuocai/access.ts index 9faf37d24..b0e76f669 100644 --- a/packages/ui/certd-server/src/plugins/plugin-plus/kuocai/access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-plus/kuocai/access.ts @@ -31,8 +31,6 @@ export class KuocaiCdnAccess extends BaseAccess { }) password = ""; - - @AccessInput({ title: "测试", component: { @@ -47,9 +45,8 @@ export class KuocaiCdnAccess extends BaseAccess { const loginRes = await this.getLoginToken(); await this.getDomainList(loginRes); return "ok"; - } + } - async getLoginToken() { const url = "https://kuocaicdn.com/login/loginUser"; const data = { @@ -110,7 +107,6 @@ export class KuocaiCdnAccess extends BaseAccess { } return res; } - } new KuocaiCdnAccess(); diff --git a/packages/ui/certd-server/src/plugins/plugin-plus/kuocai/plugins/plugin-deploy-to-cdn.ts b/packages/ui/certd-server/src/plugins/plugin-plus/kuocai/plugins/plugin-deploy-to-cdn.ts index 831fb73ef..97f143df9 100644 --- a/packages/ui/certd-server/src/plugins/plugin-plus/kuocai/plugins/plugin-deploy-to-cdn.ts +++ b/packages/ui/certd-server/src/plugins/plugin-plus/kuocai/plugins/plugin-deploy-to-cdn.ts @@ -83,7 +83,6 @@ export class KuocaiDeployToCDNPlugin extends AbstractTaskPlugin { } } - async onGetDomainList(data: any) { if (!this.accessId) { throw new Error("请选择Access授权"); diff --git a/packages/ui/certd-server/src/plugins/plugin-plus/lecdn/access.ts b/packages/ui/certd-server/src/plugins/plugin-plus/lecdn/access.ts index d52b081ce..3376a003e 100644 --- a/packages/ui/certd-server/src/plugins/plugin-plus/lecdn/access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-plus/lecdn/access.ts @@ -86,7 +86,6 @@ export class LeCDNAccess extends BaseAccess { }) apiToken = ""; - @AccessInput({ title: "测试", component: { @@ -102,11 +101,9 @@ export class LeCDNAccess extends BaseAccess { async onTestRequest() { await this.getCerts(); return "ok"; - } + } - - - async getCerts() { + async getCerts() { // http://cdnadmin.kxfox.com/prod-api/certificate?current_page=1&total=3&page_size=10 return await this.doRequest({ url: `/prod-api/certificate`, @@ -118,8 +115,7 @@ export class LeCDNAccess extends BaseAccess { }); } - async doRequest(config: any) { - + async doRequest(config: any) { const token = await this.getToken(); const access = this; const Authorization = access.type === "token" ? access.apiToken : `Bearer ${token}`; @@ -134,41 +130,39 @@ export class LeCDNAccess extends BaseAccess { return res.data; } - async getToken() { - if (this.type === "token") { - return this.apiToken; - } - if (this._token){ - return this._token; - } - // http://cdnadmin.kxfox.com/prod-api/login - const access = this; - const res = await this.ctx.http.request({ - url: `/prod-api/login`, - baseURL: access.url, - method: "post", - data: { - //新旧版本不一样,旧版本是username,新版本是email - email: access.username, - username: access.username, - password: access.password, - }, - }); - this.checkRes(res); - //新旧版本不一样,旧版本是access_token,新版本是token - const token = res.data.access_token || res.data.token; - - this._token = token; - return token; + if (this.type === "token") { + return this.apiToken; } + if (this._token) { + return this._token; + } + // http://cdnadmin.kxfox.com/prod-api/login + const access = this; + const res = await this.ctx.http.request({ + url: `/prod-api/login`, + baseURL: access.url, + method: "post", + data: { + //新旧版本不一样,旧版本是username,新版本是email + email: access.username, + username: access.username, + password: access.password, + }, + }); + this.checkRes(res); + //新旧版本不一样,旧版本是access_token,新版本是token + const token = res.data.access_token || res.data.token; - private checkRes(res: any) { + this._token = token; + return token; + } + + private checkRes(res: any) { if (res.code !== 0 && res.code !== 200) { throw new Error(res.message || JSON.stringify(res)); } } - } new LeCDNAccess(); diff --git a/packages/ui/certd-server/src/plugins/plugin-plus/lecdn/plugins/plugin-update-cert-v2.ts b/packages/ui/certd-server/src/plugins/plugin-plus/lecdn/plugins/plugin-update-cert-v2.ts index 7c356c800..2468846ff 100644 --- a/packages/ui/certd-server/src/plugins/plugin-plus/lecdn/plugins/plugin-update-cert-v2.ts +++ b/packages/ui/certd-server/src/plugins/plugin-plus/lecdn/plugins/plugin-update-cert-v2.ts @@ -61,8 +61,6 @@ export class LeCDNUpdateCertV2 extends AbstractTaskPlugin { this.access.getToken(); } - - async getCertInfo(id: number) { // http://cdnadmin.kxfox.com/prod-api/certificate/9 // Bearer edGkiOiIJ8 @@ -100,8 +98,6 @@ export class LeCDNUpdateCertV2 extends AbstractTaskPlugin { this.logger.info(`更新证书完成`); } - - async onGetCertList(data: any) { if (!this.accessId) { throw new Error("请选择Access授权"); diff --git a/packages/ui/certd-server/src/plugins/plugin-plus/lucky/access.ts b/packages/ui/certd-server/src/plugins/plugin-plus/lucky/access.ts index 23d599ecb..89730d6a8 100644 --- a/packages/ui/certd-server/src/plugins/plugin-plus/lucky/access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-plus/lucky/access.ts @@ -50,7 +50,6 @@ export class LuckyAccess extends BaseAccess { }) openToken = ""; - @AccessInput({ title: "测试", component: { @@ -66,7 +65,6 @@ export class LuckyAccess extends BaseAccess { return "ok"; } - async doRequest(req: { urlPath: string; data: any; method?: string }) { const { urlPath, data, method } = req; let url = `${this.url}/${this.safePath || ""}${urlPath}?_=${Math.floor(new Date().getTime())}`; @@ -103,7 +101,7 @@ export class LuckyAccess extends BaseAccess { method: "GET", }); const list = res.list || []; - return list + return list; } } diff --git a/packages/ui/certd-server/src/plugins/plugin-plus/maoyun/access.ts b/packages/ui/certd-server/src/plugins/plugin-plus/maoyun/access.ts index def219fb6..d04e126c3 100644 --- a/packages/ui/certd-server/src/plugins/plugin-plus/maoyun/access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-plus/maoyun/access.ts @@ -84,11 +84,8 @@ export class MaoyunAccess extends BaseAccess { method: "GET", }); const list = res.data || []; - return list + return list; } - - - } new MaoyunAccess(); diff --git a/packages/ui/certd-server/src/plugins/plugin-plus/openwrt/plugin-deploy-to-openwrt.ts b/packages/ui/certd-server/src/plugins/plugin-plus/openwrt/plugin-deploy-to-openwrt.ts index 469915ddf..bd6a67cca 100644 --- a/packages/ui/certd-server/src/plugins/plugin-plus/openwrt/plugin-deploy-to-openwrt.ts +++ b/packages/ui/certd-server/src/plugins/plugin-plus/openwrt/plugin-deploy-to-openwrt.ts @@ -1,6 +1,6 @@ import { IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; import { CertApplyPluginNames, CertInfo } from "@certd/plugin-cert"; -import { CertReader } from "@certd/plugin-lib"; +import { CertReader } from "@certd/plugin-lib"; import { SshAccess } from "../../plugin-lib/ssh/ssh-access.js"; import { SshClient } from "../../plugin-lib/ssh/ssh.js"; import { AbstractPlusTaskPlugin } from "@certd/plugin-plus"; @@ -43,8 +43,7 @@ export class OpenwrtDeployCertPlugin extends AbstractPlusTaskPlugin { }) accessId!: string; - - async onInstance() { } + async onInstance() {} async execute(): Promise { const sshConf = await this.getAccess(this.accessId); @@ -56,7 +55,7 @@ export class OpenwrtDeployCertPlugin extends AbstractPlusTaskPlugin { await certReader.readCertFile({ logger: this.logger, - handle: async (ctx) => { + handle: async ctx => { const crtPath = ctx.tmpCrtPath; const keyPath = ctx.tmpKeyPath; await sshClient.uploadFiles({ @@ -77,7 +76,7 @@ export class OpenwrtDeployCertPlugin extends AbstractPlusTaskPlugin { }); this.logger.info(`证书上传完成,准备重启uhttpd生效`); - const cmd = `/etc/init.d/uhttpd restart` + const cmd = `/etc/init.d/uhttpd restart`; await sshClient.exec({ connectConf: sshConf, diff --git a/packages/ui/certd-server/src/plugins/plugin-plus/safeline/access.ts b/packages/ui/certd-server/src/plugins/plugin-plus/safeline/access.ts index 3b44f59d4..30267c2bb 100644 --- a/packages/ui/certd-server/src/plugins/plugin-plus/safeline/access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-plus/safeline/access.ts @@ -64,10 +64,9 @@ export class SafelineAccess extends BaseAccess { data: {}, }); const nodes = res?.nodes || []; - return nodes + return nodes; } - async doRequest(config: HttpRequestConfig) { config.baseURL = this.baseUrl; config.skipSslVerify = this.skipSslVerify ?? false; @@ -82,7 +81,6 @@ export class SafelineAccess extends BaseAccess { } throw new Error(res.msg); } - } new SafelineAccess(); diff --git a/packages/ui/certd-server/src/plugins/plugin-plus/safeline/plugins/deploy-to-website.ts b/packages/ui/certd-server/src/plugins/plugin-plus/safeline/plugins/deploy-to-website.ts index eede0d16b..9f65f92cb 100644 --- a/packages/ui/certd-server/src/plugins/plugin-plus/safeline/plugins/deploy-to-website.ts +++ b/packages/ui/certd-server/src/plugins/plugin-plus/safeline/plugins/deploy-to-website.ts @@ -68,30 +68,28 @@ export class SafelineDeployToWebsitePlugin extends AbstractTaskPlugin { } async uploadCert(certId: number) { - const data:any = { + const data: any = { manual: { crt: this.cert.crt, key: this.cert.key, }, type: 2, }; - let type = "新增" + let type = "新增"; // @ts-ignore - if (certId !== "0" && certId >0) { + if (certId !== "0" && certId > 0) { //@ts-ignore - data.id = parseInt(certId) - type = "更新" + data.id = parseInt(certId); + type = "更新"; } const res = await this.access.doRequest({ url: "/api/open/cert", method: "post", - data:data + data: data, }); this.logger.info(`证书<${certId}>${type}成功,ID:${res}`); } - - // requestHandle async onGetCertIds() { diff --git a/packages/ui/certd-server/src/plugins/plugin-plus/synology/access.ts b/packages/ui/certd-server/src/plugins/plugin-plus/synology/access.ts index 335feab78..edd6a558b 100644 --- a/packages/ui/certd-server/src/plugins/plugin-plus/synology/access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-plus/synology/access.ts @@ -63,7 +63,7 @@ export class SynologyAccess extends BaseAccess { name: "a-switch", vModel: "checked", }, - col:{span:24}, + col: { span: 24 }, helper: "是否启用了双重认证", required: true, }) @@ -77,7 +77,7 @@ export class SynologyAccess extends BaseAccess { type: "access", typeName: "synology", }, - col:{span:24}, + col: { span: 24 }, mergeScript: ` return { component:{ diff --git a/packages/ui/certd-server/src/plugins/plugin-plus/synology/plugins/plugin-deploy-to-panel.ts b/packages/ui/certd-server/src/plugins/plugin-plus/synology/plugins/plugin-deploy-to-panel.ts index cfe1b1b31..b2cb46d79 100644 --- a/packages/ui/certd-server/src/plugins/plugin-plus/synology/plugins/plugin-deploy-to-panel.ts +++ b/packages/ui/certd-server/src/plugins/plugin-plus/synology/plugins/plugin-deploy-to-panel.ts @@ -58,10 +58,10 @@ export class SynologyDeployToPanel extends AbstractPlusTaskPlugin { async onInstance() {} async execute(): Promise { const access: SynologyAccess = await this.getAccess(this.accessId); - if (access.deviceId){ - this.logger.warn(`检测到您开启了二次认证,建议将证书申请任务的更新天数修改为65天,以保证每个月在群辉部署执行一次,刷新二次认证的有效期`); + if (access.deviceId) { + this.logger.warn(`检测到您开启了二次认证,建议将证书申请任务的更新天数修改为65天,以保证每个月在群辉部署执行一次,刷新二次认证的有效期`); } - + const client = new SynologyClient(access as any, this.ctx.http, this.ctx.logger, access.skipSslVerify); // await client.init(); await client.doLogin(); @@ -76,16 +76,14 @@ export class SynologyDeployToPanel extends AbstractPlusTaskPlugin { throw new Error(`未找到证书: ${this.certName}`); } this.logger.info(`找到证书: ${certItem.id}`); - await client.updateCertToPanel(certItem,this.cert); + await client.updateCertToPanel(certItem, this.cert); } else { this.logger.info("开始更新全部证书"); for (const item of certListRes.certificates) { this.logger.info(`更新证书: ${item.id}`); - await client.updateCertToPanel(item,this.cert); + await client.updateCertToPanel(item, this.cert); } } } - - } new SynologyDeployToPanel(); diff --git a/packages/ui/certd-server/src/plugins/plugin-plus/synology/plugins/plugin-keep-alive.ts b/packages/ui/certd-server/src/plugins/plugin-plus/synology/plugins/plugin-keep-alive.ts index a35b2b8d6..496731c8f 100644 --- a/packages/ui/certd-server/src/plugins/plugin-plus/synology/plugins/plugin-keep-alive.ts +++ b/packages/ui/certd-server/src/plugins/plugin-plus/synology/plugins/plugin-keep-alive.ts @@ -17,8 +17,6 @@ import { SynologyAccess } from "../access.js"; needPlus: true, }) export class SynologyKeepAlivePlugin extends AbstractPlusTaskPlugin { - - @TaskInput({ title: "群晖授权", helper: "群晖登录授权,请确保账户是管理员用户组", @@ -30,15 +28,14 @@ export class SynologyKeepAlivePlugin extends AbstractPlusTaskPlugin { }) accessId!: string; - - //授权选择框 + //授权选择框 @TaskInput({ title: "间隔天数", helper: "多少天刷新一次,建议15天以内", value: 15, component: { name: "a-input-number", - vModel:"value", + vModel: "value", }, required: true, }) @@ -46,14 +43,14 @@ export class SynologyKeepAlivePlugin extends AbstractPlusTaskPlugin { @TaskOutput({ title: "上次刷新时间", - type :"SynologyLastRefreshTime" + type: "SynologyLastRefreshTime", }) lastRefreshTime!: number; async onInstance() {} async execute(): Promise { this.logger.info("开始刷新群晖登录有效期"); - const now = dayjs() + const now = dayjs(); const status = this.getLastStatus(); if (status) { let lastRefreshTime = this.getLastOutput("lastRefreshTime"); @@ -61,16 +58,15 @@ export class SynologyKeepAlivePlugin extends AbstractPlusTaskPlugin { this.lastRefreshTime = lastRefreshTime; const lastTime = dayjs(lastRefreshTime); const diffDays = now.diff(lastTime, "day"); - + this.logger.info(`上次刷新时间${lastTime.format("YYYY-MM-DD")}`); if (diffDays < this.intervalDays) { this.logger.info(`距离上次刷新${diffDays}天,不足${this.intervalDays}天,无需刷新`); this.logger.info(`下一次刷新时间${lastTime.add(this.intervalDays, "day").format("YYYY-MM-DD")}`); return "skip"; - }else{ + } else { this.logger.info(`超过${this.intervalDays}天,需要刷新`); } - } const access: SynologyAccess = await this.getAccess(this.accessId); @@ -80,7 +76,5 @@ export class SynologyKeepAlivePlugin extends AbstractPlusTaskPlugin { this.lastRefreshTime = now.valueOf(); this.logger.info("刷新群晖登录有效期成功"); } - - } new SynologyKeepAlivePlugin(); diff --git a/packages/ui/certd-server/src/plugins/plugin-plus/yidun/access-rcdn.ts b/packages/ui/certd-server/src/plugins/plugin-plus/yidun/access-rcdn.ts index 37bef989d..0bce23a83 100644 --- a/packages/ui/certd-server/src/plugins/plugin-plus/yidun/access-rcdn.ts +++ b/packages/ui/certd-server/src/plugins/plugin-plus/yidun/access-rcdn.ts @@ -31,8 +31,7 @@ export class YidunRcdnAccess extends BaseAccess { }) password = ""; - - @AccessInput({ + @AccessInput({ title: "测试", component: { name: "api-test", @@ -81,7 +80,7 @@ export class YidunRcdnAccess extends BaseAccess { } async getLoginToken() { - const access: YidunRcdnAccess = this + const access: YidunRcdnAccess = this; const url = "https://rhcdn.yiduncdn.com/login/loginUser"; const data = { userAccount: access.username, diff --git a/packages/ui/certd-server/src/plugins/plugin-plus/yidun/access.ts b/packages/ui/certd-server/src/plugins/plugin-plus/yidun/access.ts index 6ce4a12ef..0a16ef6f9 100644 --- a/packages/ui/certd-server/src/plugins/plugin-plus/yidun/access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-plus/yidun/access.ts @@ -48,31 +48,30 @@ export class YidunAccess extends BaseAccess { return "ok"; } - async getDomainList(){ + async getDomainList() { const siteUrl = "http://user.yiduncdn.com/v1/sites"; - const res = await this.doRequest(siteUrl, "GET", { }); - return res.data + const res = await this.doRequest(siteUrl, "GET", {}); + return res.data; } async doRequest(url: string, method: string, data: any) { - const access = this - const { apiKey, apiSecret } = access; - const http = this.ctx.http; - const res: any = await http.request({ - url, - method, - headers: { - "api-key": apiKey, - "api-secret": apiSecret, - }, - data, - }); - if (res.code != 0) { - throw new Error(res.msg); - } - return res; + const access = this; + const { apiKey, apiSecret } = access; + const http = this.ctx.http; + const res: any = await http.request({ + url, + method, + headers: { + "api-key": apiKey, + "api-secret": apiSecret, + }, + data, + }); + if (res.code != 0) { + throw new Error(res.msg); } - + return res; + } } new YidunAccess(); diff --git a/packages/ui/certd-server/src/plugins/plugin-plus/yidun/plugins/plugin-deploy-to-cdn.ts b/packages/ui/certd-server/src/plugins/plugin-plus/yidun/plugins/plugin-deploy-to-cdn.ts index e180dd311..763f63623 100644 --- a/packages/ui/certd-server/src/plugins/plugin-plus/yidun/plugins/plugin-deploy-to-cdn.ts +++ b/packages/ui/certd-server/src/plugins/plugin-plus/yidun/plugins/plugin-deploy-to-cdn.ts @@ -91,11 +91,10 @@ export class YidunDeployToCDNPlugin extends AbstractTaskPlugin { }); } - private async updateByDomain(cert: CertInfo) { //查询站点 const siteUrl = "http://user.yiduncdn.com/v1/sites"; - const access = this.access + const access = this.access; const res = await access.doRequest(siteUrl, "GET", { domain: this.domain }); if (res.data.length === 0) { throw new Error(`未找到域名相关站点:${this.domain}`); diff --git a/packages/ui/certd-server/src/plugins/plugin-plus/yidun/plugins/plugin-deploy-to-rcdn.ts b/packages/ui/certd-server/src/plugins/plugin-plus/yidun/plugins/plugin-deploy-to-rcdn.ts index d67775e1e..01c4d4886 100644 --- a/packages/ui/certd-server/src/plugins/plugin-plus/yidun/plugins/plugin-deploy-to-rcdn.ts +++ b/packages/ui/certd-server/src/plugins/plugin-plus/yidun/plugins/plugin-deploy-to-rcdn.ts @@ -83,10 +83,6 @@ export class YidunDeployToRCDNPlugin extends AbstractTaskPlugin { } } - - - - async onGetDomainList(data: any) { if (!this.accessId) { throw new Error("请选择Access授权"); diff --git a/packages/ui/certd-server/src/plugins/plugin-proxmox/access.ts b/packages/ui/certd-server/src/plugins/plugin-proxmox/access.ts index 2a1db8941..c23863435 100644 --- a/packages/ui/certd-server/src/plugins/plugin-proxmox/access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-proxmox/access.ts @@ -1,35 +1,35 @@ -import { IsAccess, AccessInput, BaseAccess } from '@certd/pipeline'; +import { IsAccess, AccessInput, BaseAccess } from "@certd/pipeline"; /** * 这个注解将注册一个授权配置 * 在certd的后台管理系统中,用户可以选择添加此类型的授权 */ @IsAccess({ - name: 'proxmox', - title: 'proxmox', - desc: '', - icon: 'svg:icon-proxmox', + name: "proxmox", + title: "proxmox", + desc: "", + icon: "svg:icon-proxmox", }) export class ProxmoxAccess extends BaseAccess { /** * 授权属性配置 */ @AccessInput({ - title: 'host', + title: "host", component: { - placeholder: 'IP或域名', + placeholder: "IP或域名", }, required: true, encrypt: false, }) - host = ''; + host = ""; @AccessInput({ - title: '端口', + title: "端口", component: { - placeholder: '端口', + placeholder: "端口", component: { - name: 'a-input-number', + name: "a-input-number", }, }, required: true, @@ -40,39 +40,37 @@ export class ProxmoxAccess extends BaseAccess { * 授权属性配置 */ @AccessInput({ - title: '用户名', + title: "用户名", component: { - placeholder: 'username', + placeholder: "username", }, required: true, encrypt: false, }) - username = ''; + username = ""; @AccessInput({ - title: '密码', + title: "密码", component: { - placeholder: 'password', + placeholder: "password", }, required: true, encrypt: true, }) - password = ''; + password = ""; @AccessInput({ - title: '领域', + title: "领域", value: "pam", component: { - placeholder: 'pam、pve。默认值 pam', + placeholder: "pam、pve。默认值 pam", }, - helper:"pam 或 pve。默认值 pam", + helper: "pam 或 pve。默认值 pam", required: false, encrypt: false, }) - realm = ''; + realm = ""; - - @AccessInput({ title: "测试", component: { @@ -88,27 +86,25 @@ export class ProxmoxAccess extends BaseAccess { return "ok"; } - - async getNodeList() { const client = await this.getClient(); const nodesRes = await client.nodes.index(); // this.logger.info('nodes:', nodesRes.response); if (!nodesRes.response?.data) { - return [] + return []; } - return nodesRes.response.data + return nodesRes.response.data; } async getClient() { - const pve = await import('@certd/cv4pve-api-javascript'); + const pve = await import("@certd/cv4pve-api-javascript"); const client = new pve.PveClient(this.host, this.port); - const login = await client.login(this.username, this.password, this.realm || 'pam'); + const login = await client.login(this.username, this.password, this.realm || "pam"); if (!login) { throw new Error(`Login failed:${JSON.stringify(login)}`); } const versionRes = await client.version.version(); - this.ctx.logger.info('Proxmox version:', versionRes.response); + this.ctx.logger.info("Proxmox version:", versionRes.response); return client; } } diff --git a/packages/ui/certd-server/src/plugins/plugin-proxmox/index.ts b/packages/ui/certd-server/src/plugins/plugin-proxmox/index.ts index fdad254fb..02dc3945d 100644 --- a/packages/ui/certd-server/src/plugins/plugin-proxmox/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-proxmox/index.ts @@ -1,2 +1,2 @@ -export * from './plugins/index.js'; -export * from './access.js'; +export * from "./plugins/index.js"; +export * from "./access.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-proxmox/plugins/index.ts b/packages/ui/certd-server/src/plugins/plugin-proxmox/plugins/index.ts index 672a272e9..678f8bc6f 100644 --- a/packages/ui/certd-server/src/plugins/plugin-proxmox/plugins/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-proxmox/plugins/index.ts @@ -1 +1 @@ -export * from './plugin-upload.js'; +export * from "./plugin-upload.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-proxmox/plugins/plugin-upload.ts b/packages/ui/certd-server/src/plugins/plugin-proxmox/plugins/plugin-upload.ts index 40ccbf0d1..6f1e1b06b 100644 --- a/packages/ui/certd-server/src/plugins/plugin-proxmox/plugins/plugin-upload.ts +++ b/packages/ui/certd-server/src/plugins/plugin-proxmox/plugins/plugin-upload.ts @@ -1,14 +1,14 @@ -import { IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from '@certd/pipeline'; -import { CertInfo } from '@certd/plugin-cert'; +import { IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; +import { CertInfo } from "@certd/plugin-cert"; import { AbstractPlusTaskPlugin } from "@certd/plugin-plus"; -import { ProxmoxAccess } from '../access.js'; -import { createRemoteSelectInputDefine } from '@certd/plugin-lib'; -import { CertApplyPluginNames} from '@certd/plugin-cert'; +import { ProxmoxAccess } from "../access.js"; +import { createRemoteSelectInputDefine } from "@certd/plugin-lib"; +import { CertApplyPluginNames } from "@certd/plugin-cert"; @IsTaskPlugin({ //命名规范,插件名称+功能(就是目录plugin-demo中的demo),大写字母开头,驼峰命名 - name: 'ProxmoxUploadCert', - title: 'Proxmox-上传证书到Proxmox', - icon: 'svg:icon-proxmox', + name: "ProxmoxUploadCert", + title: "Proxmox-上传证书到Proxmox", + icon: "svg:icon-proxmox", //插件分组 group: pluginGroups.panel.key, needPlus: true, @@ -23,10 +23,10 @@ import { CertApplyPluginNames} from '@certd/plugin-cert'; export class ProxmoxUploadCert extends AbstractPlusTaskPlugin { //证书选择,此项必须要有 @TaskInput({ - title: '域名证书', - helper: '请选择前置任务输出的域名证书', + title: "域名证书", + helper: "请选择前置任务输出的域名证书", component: { - name: 'output-selector', + name: "output-selector", from: [...CertApplyPluginNames], }, // required: true, // 必填 @@ -39,10 +39,10 @@ export class ProxmoxUploadCert extends AbstractPlusTaskPlugin { //授权选择框 @TaskInput({ - title: 'Proxmox授权', + title: "Proxmox授权", component: { - name: 'access-selector', - type: 'proxmox', //固定授权类型 + name: "access-selector", + type: "proxmox", //固定授权类型 }, required: true, //必填 }) @@ -51,11 +51,11 @@ export class ProxmoxUploadCert extends AbstractPlusTaskPlugin { @TaskInput( createRemoteSelectInputDefine({ - title: '节点', - helper: '要部署证书的节点', - typeName: 'ProxmoxUploadCert', + title: "节点", + helper: "要部署证书的节点", + typeName: "ProxmoxUploadCert", action: ProxmoxUploadCert.prototype.onGetNodeList.name, - watches: ['accessId'], + watches: ["accessId"], }) ) nodes!: string[]; @@ -71,21 +71,19 @@ export class ProxmoxUploadCert extends AbstractPlusTaskPlugin { for (const node of this.nodes) { this.logger.info(`开始上传证书到节点:${node}`); - try{ + try { const res = await client.nodes.get(node).certificates.custom.uploadCustomCert(cert.crt, true, cert.key, true); this.logger.info(`上传结果:${JSON.stringify(res.response)}`); - }catch (e) { + } catch (e) { this.logger.error(`执行失败:${e.message},请检查节点名称是否正确`); - throw e + throw e; } - } - this.logger.info('部署成功'); + this.logger.info("部署成功"); } - async onGetNodeList() { - + async onGetNodeList() { const access = await this.getAccess(this.accessId); const nodesRes = await access.getNodeList(); return nodesRes.map((node: any) => { diff --git a/packages/ui/certd-server/src/plugins/plugin-qiniu/index.ts b/packages/ui/certd-server/src/plugins/plugin-qiniu/index.ts index 640fdbe36..f3e504d6c 100644 --- a/packages/ui/certd-server/src/plugins/plugin-qiniu/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-qiniu/index.ts @@ -1 +1 @@ -export * from './plugin/index.js'; +export * from "./plugin/index.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-qiniu/plugin/deploy-to-cdn/index.ts b/packages/ui/certd-server/src/plugins/plugin-qiniu/plugin/deploy-to-cdn/index.ts index c46ca889f..0457fdf8a 100644 --- a/packages/ui/certd-server/src/plugins/plugin-qiniu/plugin/deploy-to-cdn/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-qiniu/plugin/deploy-to-cdn/index.ts @@ -1,17 +1,17 @@ -import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from '@certd/pipeline'; -import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from '@certd/plugin-lib'; -import { CertInfo } from '@certd/plugin-cert'; -import { optionsUtils } from '@certd/basic'; -import { CertApplyPluginNames} from '@certd/plugin-cert'; -import { QiniuAccess } from '../../../plugin-lib/qiniu/access.js'; -import { QiniuClient } from '../../../plugin-lib/qiniu/index.js'; +import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; +import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from "@certd/plugin-lib"; +import { CertInfo } from "@certd/plugin-cert"; +import { optionsUtils } from "@certd/basic"; +import { CertApplyPluginNames } from "@certd/plugin-cert"; +import { QiniuAccess } from "../../../plugin-lib/qiniu/access.js"; +import { QiniuClient } from "../../../plugin-lib/qiniu/index.js"; @IsTaskPlugin({ - name: 'QiniuDeployCertToCDN', - title: '七牛云-部署证书至CDN/DCDN', - icon: 'svg:icon-qiniuyun', + name: "QiniuDeployCertToCDN", + title: "七牛云-部署证书至CDN/DCDN", + icon: "svg:icon-qiniuyun", group: pluginGroups.qiniu.key, - desc: '自动部署域名证书至七牛云CDN、DCDN', + desc: "自动部署域名证书至七牛云CDN、DCDN", default: { strategy: { runStrategy: RunStrategy.SkipWhenSucceed, @@ -20,11 +20,11 @@ import { QiniuClient } from '../../../plugin-lib/qiniu/index.js'; }) export class QiniuDeployCertToCDN extends AbstractTaskPlugin { @TaskInput({ - title: '域名证书', - helper: '请选择前置任务输出的域名证书,或者上传到七牛云的证书id', + title: "域名证书", + helper: "请选择前置任务输出的域名证书,或者上传到七牛云的证书id", component: { - name: 'output-selector', - from: [...CertApplyPluginNames, 'QiniuCertUpload'], + name: "output-selector", + from: [...CertApplyPluginNames, "QiniuCertUpload"], }, required: true, }) @@ -34,11 +34,11 @@ export class QiniuDeployCertToCDN extends AbstractTaskPlugin { certDomains!: string[]; @TaskInput({ - title: 'Access授权', - helper: '七牛云授权', + title: "Access授权", + helper: "七牛云授权", component: { - name: 'access-selector', - type: 'qiniu', + name: "access-selector", + type: "qiniu", }, required: true, }) @@ -46,9 +46,9 @@ export class QiniuDeployCertToCDN extends AbstractTaskPlugin { @TaskInput( createRemoteSelectInputDefine({ - title: 'CDN加速域名', - helper: '你在七牛云上配置的CDN加速域名,比如:certd.handsfree.work', - rules: [{ type: 'domains', allowDotStart: true }], + title: "CDN加速域名", + helper: "你在七牛云上配置的CDN加速域名,比如:certd.handsfree.work", + rules: [{ type: "domains", allowDotStart: true }], action: QiniuDeployCertToCDN.prototype.onGetDomainList.name, required: true, }) @@ -57,7 +57,7 @@ export class QiniuDeployCertToCDN extends AbstractTaskPlugin { async onInstance() {} async execute(): Promise { - this.logger.info('开始部署证书到七牛云cdn'); + this.logger.info("开始部署证书到七牛云cdn"); const access = await this.getAccess(this.accessId); const qiniuClient = new QiniuClient({ http: this.ctx.http, @@ -66,28 +66,28 @@ export class QiniuDeployCertToCDN extends AbstractTaskPlugin { }); let certId = null; - if (typeof this.cert !== 'string') { + if (typeof this.cert !== "string") { // 是证书id,直接上传即可 - this.logger.info('先上传证书'); - certId = await qiniuClient.uploadCert(this.cert, this.appendTimeSuffix('certd')); + this.logger.info("先上传证书"); + certId = await qiniuClient.uploadCert(this.cert, this.appendTimeSuffix("certd")); } else { certId = this.cert; } - const domains: string[] = typeof this.domainName === 'string' ? [this.domainName] : this.domainName; + const domains: string[] = typeof this.domainName === "string" ? [this.domainName] : this.domainName; for (const domain of domains) { //获取域名详情 const getUrl = `https://api.qiniu.com/domain/${domain}`; - const res = await qiniuClient.doRequest(getUrl, 'get'); + const res = await qiniuClient.doRequest(getUrl, "get"); this.logger.info(`域名https详情:${JSON.stringify(res.https)}`); if (!res.https.certId) { - this.logger.info('未开启https,即将开启https,并设置证书'); + this.logger.info("未开启https,即将开启https,并设置证书"); //未开启https const body = { certId: certId, }; const url = `https://api.qiniu.com/domain/${domain}/sslize`; - await qiniuClient.doRequest(url, 'put', body); + await qiniuClient.doRequest(url, "put", body); this.logger.info(`开启https并设置证书成功,certId:${certId},domain:${domain}`); } else { //开始修改证书 @@ -98,18 +98,18 @@ export class QiniuDeployCertToCDN extends AbstractTaskPlugin { http2Enable: res.https.http2Enable, }; const url = `https://api.qiniu.com/domain/${domain}/httpsconf`; - await qiniuClient.doRequest(url, 'put', body); + await qiniuClient.doRequest(url, "put", body); this.logger.info(`修改证书成功,certId:${certId},domain:${domain}`); } } - this.logger.info('部署完成'); + this.logger.info("部署完成"); } async onGetDomainList() { const access = await this.getAccess(this.accessId); - - const domains = await access.getDomainList() + + const domains = await access.getDomainList(); const options = domains.map((item: any) => { return { diff --git a/packages/ui/certd-server/src/plugins/plugin-qiniu/plugin/index.ts b/packages/ui/certd-server/src/plugins/plugin-qiniu/plugin/index.ts index dff1615ca..6e4e99c19 100644 --- a/packages/ui/certd-server/src/plugins/plugin-qiniu/plugin/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-qiniu/plugin/index.ts @@ -1,3 +1,3 @@ -export * from './deploy-to-cdn/index.js'; -export * from './upload-cert/index.js'; -export * from './plugin-deploy-to-oss.js'; \ No newline at end of file +export * from "./deploy-to-cdn/index.js"; +export * from "./upload-cert/index.js"; +export * from "./plugin-deploy-to-oss.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-qiniu/plugin/upload-cert/index.ts b/packages/ui/certd-server/src/plugins/plugin-qiniu/plugin/upload-cert/index.ts index 0f7fe456f..6ffaec278 100644 --- a/packages/ui/certd-server/src/plugins/plugin-qiniu/plugin/upload-cert/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-qiniu/plugin/upload-cert/index.ts @@ -1,14 +1,14 @@ -import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput, TaskOutput } from '@certd/pipeline'; -import { CertInfo } from '@certd/plugin-cert'; -import { QiniuAccess } from '../../../plugin-lib/qiniu/access.js'; -import { QiniuClient } from '../../../plugin-lib/qiniu/index.js'; -import { CertApplyPluginNames} from '@certd/plugin-cert'; +import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput, TaskOutput } from "@certd/pipeline"; +import { CertInfo } from "@certd/plugin-cert"; +import { QiniuAccess } from "../../../plugin-lib/qiniu/access.js"; +import { QiniuClient } from "../../../plugin-lib/qiniu/index.js"; +import { CertApplyPluginNames } from "@certd/plugin-cert"; @IsTaskPlugin({ - name: 'QiniuCertUpload', - title: '七牛云-上传证书到七牛云', - icon: 'svg:icon-qiniuyun', + name: "QiniuCertUpload", + title: "七牛云-上传证书到七牛云", + icon: "svg:icon-qiniuyun", group: pluginGroups.qiniu.key, - desc: '上传到七牛云', + desc: "上传到七牛云", default: { strategy: { runStrategy: RunStrategy.SkipWhenSucceed, @@ -17,16 +17,16 @@ import { CertApplyPluginNames} from '@certd/plugin-cert'; }) export class QiniuCertUpload extends AbstractTaskPlugin { @TaskInput({ - title: '证书名称', - helper: '上传后将以此名称作为前缀备注', + title: "证书名称", + helper: "上传后将以此名称作为前缀备注", }) certName!: string; @TaskInput({ - title: '域名证书', - helper: '请选择前置任务输出的域名证书', + title: "域名证书", + helper: "请选择前置任务输出的域名证书", component: { - name: 'output-selector', + name: "output-selector", from: [...CertApplyPluginNames], }, required: true, @@ -34,24 +34,24 @@ export class QiniuCertUpload extends AbstractTaskPlugin { cert!: CertInfo; @TaskInput({ - title: 'Access授权', - helper: '七牛云授权', + title: "Access授权", + helper: "七牛云授权", component: { - name: 'access-selector', - type: 'qiniu', + name: "access-selector", + type: "qiniu", }, required: true, }) accessId!: string; @TaskOutput({ - title: '上传成功后的七牛云CertId', + title: "上传成功后的七牛云CertId", }) qiniuCertId!: string; async onInstance() {} async execute(): Promise { - this.logger.info('开始上传证书到七牛云'); + this.logger.info("开始上传证书到七牛云"); const access = await this.getAccess(this.accessId); const qiniuClient = new QiniuClient({ http: this.ctx.http, @@ -59,7 +59,7 @@ export class QiniuCertUpload extends AbstractTaskPlugin { logger: this.logger, }); this.qiniuCertId = await qiniuClient.uploadCert(this.cert, this.appendTimeSuffix(this.certName)); - this.logger.info('上传完成,id:', this.qiniuCertId); + this.logger.info("上传完成,id:", this.qiniuCertId); } } new QiniuCertUpload(); diff --git a/packages/ui/certd-server/src/plugins/plugin-qnap/index.ts b/packages/ui/certd-server/src/plugins/plugin-qnap/index.ts index 4ab82c2d6..68bc642b3 100644 --- a/packages/ui/certd-server/src/plugins/plugin-qnap/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-qnap/index.ts @@ -1 +1 @@ -export * from './plugins/index.js'; +export * from "./plugins/index.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-qnap/plugins/index.ts b/packages/ui/certd-server/src/plugins/plugin-qnap/plugins/index.ts index e8176e73b..cdc959a04 100644 --- a/packages/ui/certd-server/src/plugins/plugin-qnap/plugins/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-qnap/plugins/index.ts @@ -1 +1 @@ -export * from './plugin-qnap.js'; +export * from "./plugin-qnap.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-qnap/plugins/plugin-qnap.ts b/packages/ui/certd-server/src/plugins/plugin-qnap/plugins/plugin-qnap.ts index 8f65c190c..f4615261a 100644 --- a/packages/ui/certd-server/src/plugins/plugin-qnap/plugins/plugin-qnap.ts +++ b/packages/ui/certd-server/src/plugins/plugin-qnap/plugins/plugin-qnap.ts @@ -1,16 +1,16 @@ -import { IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from '@certd/pipeline'; -import { CertInfo } from '@certd/plugin-cert'; +import { IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; +import { CertInfo } from "@certd/plugin-cert"; import { AbstractPlusTaskPlugin } from "@certd/plugin-plus"; -import { tmpdir } from 'node:os'; -import fs from 'fs'; -import { SshAccess, SshClient } from '../../plugin-lib/ssh/index.js'; -import { CertApplyPluginNames} from '@certd/plugin-cert'; +import { tmpdir } from "node:os"; +import fs from "fs"; +import { SshAccess, SshClient } from "../../plugin-lib/ssh/index.js"; +import { CertApplyPluginNames } from "@certd/plugin-cert"; @IsTaskPlugin({ - name: 'QnapDeploy', - title: '威联通-部署证书到威联通', - icon: 'svg:icon-qnap', + name: "QnapDeploy", + title: "威联通-部署证书到威联通", + icon: "svg:icon-qnap", group: pluginGroups.panel.key, - desc: '部署证书到qnap', + desc: "部署证书到qnap", default: { strategy: { runStrategy: RunStrategy.SkipWhenSucceed, @@ -21,10 +21,10 @@ import { CertApplyPluginNames} from '@certd/plugin-cert'; export class QnapDeploy extends AbstractPlusTaskPlugin { //证书选择,此项必须要有 @TaskInput({ - title: '域名证书', - helper: '请选择前置任务输出的域名证书', + title: "域名证书", + helper: "请选择前置任务输出的域名证书", component: { - name: 'output-selector', + name: "output-selector", from: [...CertApplyPluginNames], }, required: true, @@ -33,11 +33,11 @@ export class QnapDeploy extends AbstractPlusTaskPlugin { //授权选择框 @TaskInput({ - title: 'ssh登录授权', - helper: 'ssh登录授权', + title: "ssh登录授权", + helper: "ssh登录授权", component: { - name: 'access-selector', - type: 'ssh', + name: "access-selector", + type: "ssh", }, required: true, }) @@ -48,16 +48,16 @@ export class QnapDeploy extends AbstractPlusTaskPlugin { const { cert, accessId } = this; if (!accessId) { - throw new Error('主机登录授权配置不能为空'); + throw new Error("主机登录授权配置不能为空"); } const connectConf = await this.getAccess(accessId); const sshClient = new SshClient(this.logger); //合并证书 - const newCert = cert.key + '\n' + cert.crt; - const tmpCertPath = tmpdir() + '/certd/cert.pem'; + const newCert = cert.key + "\n" + cert.crt; + const tmpCertPath = tmpdir() + "/certd/cert.pem"; fs.writeFileSync(tmpCertPath, newCert); - const targetPath = '/etc/stunnel/stunnel.pem'; + const targetPath = "/etc/stunnel/stunnel.pem"; this.logger.info(`准备上传证书到服务器:${targetPath}`); const transports: any = []; @@ -65,21 +65,21 @@ export class QnapDeploy extends AbstractPlusTaskPlugin { localPath: tmpCertPath, remotePath: targetPath, }); - this.logger.info('开始上传文件到服务器'); + this.logger.info("开始上传文件到服务器"); await sshClient.uploadFiles({ connectConf, transports, mkdirs: true, }); - this.logger.info('上传文件到服务器成功'); + this.logger.info("上传文件到服务器成功"); //重启服务 - const restartCmd = '/bin/bash /etc/init.d/stunnel.sh restart'; - this.logger.info('重启stunnel服务'); + const restartCmd = "/bin/bash /etc/init.d/stunnel.sh restart"; + this.logger.info("重启stunnel服务"); await sshClient.exec({ connectConf, script: [restartCmd], }); - this.logger.info('执行成功'); + this.logger.info("执行成功"); } } new QnapDeploy(); diff --git a/packages/ui/certd-server/src/plugins/plugin-rainyun/access.ts b/packages/ui/certd-server/src/plugins/plugin-rainyun/access.ts index 7d9d1293f..2ada71280 100644 --- a/packages/ui/certd-server/src/plugins/plugin-rainyun/access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-rainyun/access.ts @@ -1,8 +1,7 @@ -import {AccessInput, BaseAccess, IsAccess} from "@certd/pipeline"; -import {HttpRequestConfig} from "@certd/basic"; +import { AccessInput, BaseAccess, IsAccess } from "@certd/pipeline"; +import { HttpRequestConfig } from "@certd/basic"; import { CertInfo } from "@certd/plugin-cert"; - /** */ @IsAccess({ @@ -10,56 +9,52 @@ import { CertInfo } from "@certd/plugin-cert"; title: "雨云授权", desc: "https://app.rainyun.com/", icon: "svg:icon-rainyun", - order: 100 + order: 100, }) export class RainyunAccess extends BaseAccess { - - @AccessInput({ title: "ApiKey", component: { placeholder: "api-key", name: "a-input", - vModel: "value" + vModel: "value", }, - helper:"https://app.rainyun.com/account/settings/api-key", + helper: "https://app.rainyun.com/account/settings/api-key", encrypt: true, - required: true + required: true, }) apiKey!: string; - - @AccessInput({ title: "测试", component: { name: "api-test", - action: "TestRequest" + action: "TestRequest", }, - helper: "点击测试接口是否正常" + helper: "点击测试接口是否正常", }) testRequest = true; async onTestRequest() { - await this.getDomainList({limit:1}); - return "ok" + await this.getDomainList({ limit: 1 }); + return "ok"; } // {"columnFilters":{"domains.Domain":"domain"},"sort":[],"page":1,"perPage":20} - async getDomainList(req:{offset?:number,limit?:number,query?:string}){ + async getDomainList(req: { offset?: number; limit?: number; query?: string }) { const size = req.limit ?? 20; const offset = req.offset ?? 0; let page = Math.floor(offset / size); - if(offset % size === 0 ){ - page++ + if (offset % size === 0) { + page++; } - const options ={ + const options = { page: page, perPage: size, columnFilters: { - "domains.Domain": req.query??"" + "domains.Domain": req.query ?? "", }, - } + }; const res = await this.doRequest({ url: `/product/domain/?options=${encodeURIComponent(JSON.stringify(options))}`, method: "GET", @@ -69,23 +64,21 @@ export class RainyunAccess extends BaseAccess { total: res.TotalRecords, list: res.Records || [], limit: size, - offset: offset - } + offset: offset, + }; } - - async getCertList(req:{pageNo?:number,pageSize?:number,query?:string}){ + async getCertList(req: { pageNo?: number; pageSize?: number; query?: string }) { const pageNo = req.pageNo ?? 1; const pageSize = req.pageSize ?? 20; - const options ={ + const options = { columnFilters: { - Domain: req.query??"" + Domain: req.query ?? "", }, - sort:[], + sort: [], page: pageNo, perPage: pageSize, - - } + }; const res = await this.doRequest({ url: `product/sslcenter/?options=${encodeURIComponent(JSON.stringify(options))}`, method: "GET", @@ -95,12 +88,11 @@ export class RainyunAccess extends BaseAccess { total: res.TotalRecords, list: res.Records || [], pageNo: pageNo, - pageSize: pageSize - } + pageSize: pageSize, + }; } - async doCertReplace(req:{certId:number,cert:CertInfo}){ - + async doCertReplace(req: { certId: number; cert: CertInfo }) { // /product/sslcenter/{id} return await this.doRequest({ url: `product/sslcenter/${req.certId}`, @@ -108,29 +100,27 @@ export class RainyunAccess extends BaseAccess { data: { cert: req.cert.crt, key: req.cert.key, - } + }, }); - } - - async getDomainId(domain:string){ - const res = await this.getDomainList({query: domain,limit:1}); + async getDomainId(domain: string) { + const res = await this.getDomainList({ query: domain, limit: 1 }); if (res.list.length === 0) { - throw new Error(`域名${domain}不存在` ); + throw new Error(`域名${domain}不存在`); } return res.list[0].id; } - async doRequest(req:HttpRequestConfig){ - const res = await this.ctx.http.request({ + async doRequest(req: HttpRequestConfig) { + const res = await this.ctx.http.request({ url: req.url, - baseURL:"https://api.v2.rainyun.com", - method: req.method|| "POST", + baseURL: "https://api.v2.rainyun.com", + method: req.method || "POST", data: req.data, - params: req.params, - headers:{ - "X-Api-Key": this.apiKey + params: req.params, + headers: { + "X-Api-Key": this.apiKey, }, // httpProxy: this.httpProxy||undefined, }); @@ -142,6 +132,4 @@ export class RainyunAccess extends BaseAccess { } } - - new RainyunAccess(); diff --git a/packages/ui/certd-server/src/plugins/plugin-rainyun/dns-provider.ts b/packages/ui/certd-server/src/plugins/plugin-rainyun/dns-provider.ts index 216da0bfb..49cc63de3 100644 --- a/packages/ui/certd-server/src/plugins/plugin-rainyun/dns-provider.ts +++ b/packages/ui/certd-server/src/plugins/plugin-rainyun/dns-provider.ts @@ -10,15 +10,11 @@ import { Pager, PageRes, PageSearch } from "@certd/pipeline"; icon: "svg:icon-rainyun", }) export class RainyunDnsProvider extends AbstractDnsProvider { - client: any; - async onInstance() { - - } + async onInstance() {} async createRecord(options: CreateRecordOptions): Promise { - const access: RainyunAccess = this.ctx.access as RainyunAccess; const domainId = await access.getDomainId(options.domain); @@ -38,18 +34,16 @@ export class RainyunDnsProvider extends AbstractDnsProvider { level: 1, type: type, line: "DEFAULT", - ttl: 60 - } + ttl: 60, + }, }); this.logger.info("添加域名解析成功:", JSON.stringify(options), ret); return { recordId: ret, - domainId: domainId + domainId: domainId, }; - } - async removeRecord(options: RemoveRecordOptions): Promise { const { fullRecord, value } = options.recordReq; const access: RainyunAccess = this.ctx.access as RainyunAccess; @@ -69,14 +63,14 @@ export class RainyunDnsProvider extends AbstractDnsProvider { offset: pager.getOffset(), limit: pager.pageSize, query: req.searchKey, - }) + }); // this.logger.info("获取域名列表成功:", ret); const list = ret.list.map((item: any) => ({ id: item.id, domain: item.domain, })); return { - total:ret.total || list.length, + total: ret.total || list.length, list, }; } diff --git a/packages/ui/certd-server/src/plugins/plugin-rainyun/plugins/index.ts b/packages/ui/certd-server/src/plugins/plugin-rainyun/plugins/index.ts index 3ce4f30c7..b8237e4f8 100644 --- a/packages/ui/certd-server/src/plugins/plugin-rainyun/plugins/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-rainyun/plugins/index.ts @@ -1 +1 @@ -export * from './plugin-refresh-cert.js' +export * from "./plugin-refresh-cert.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-rainyun/plugins/plugin-refresh-cert.ts b/packages/ui/certd-server/src/plugins/plugin-rainyun/plugins/plugin-refresh-cert.ts index b2f9ae25f..4f25484ac 100644 --- a/packages/ui/certd-server/src/plugins/plugin-rainyun/plugins/plugin-refresh-cert.ts +++ b/packages/ui/certd-server/src/plugins/plugin-rainyun/plugins/plugin-refresh-cert.ts @@ -15,9 +15,9 @@ import { RainyunAccess } from "../access.js"; default: { //默认值配置照抄即可 strategy: { - runStrategy: RunStrategy.SkipWhenSucceed - } - } + runStrategy: RunStrategy.SkipWhenSucceed, + }, + }, }) //类名规范,跟上面插件名称(name)一致 export class RainyunRefreshCert extends AbstractTaskPlugin { @@ -27,8 +27,8 @@ export class RainyunRefreshCert extends AbstractTaskPlugin { helper: "请选择前置任务输出的域名证书", component: { name: "output-selector", - from: [...CertApplyPluginNames] - } + from: [...CertApplyPluginNames], + }, // required: true, // 必填 }) cert!: CertInfo; @@ -41,9 +41,9 @@ export class RainyunRefreshCert extends AbstractTaskPlugin { title: "雨云授权", component: { name: "access-selector", - type: "rainyun" //固定授权类型 + type: "rainyun", //固定授权类型 }, - required: true //必填 + required: true, //必填 }) accessId!: string; // @@ -53,14 +53,13 @@ export class RainyunRefreshCert extends AbstractTaskPlugin { title: "证书Id", helper: "要更新的rainyun证书id", - action: RainyunRefreshCert.prototype.onGetCertList.name + action: RainyunRefreshCert.prototype.onGetCertList.name, }) ) certList!: number[]; //插件实例化时执行的方法 - async onInstance() { - } + async onInstance() {} //插件执行方法 async execute(): Promise { @@ -70,7 +69,7 @@ export class RainyunRefreshCert extends AbstractTaskPlugin { this.logger.info(`----------- 开始更新证书:${item}`); await access.doCertReplace({ certId: item, - cert: this.cert + cert: this.cert, }); this.logger.info(`----------- 更新证书${item}成功`); } @@ -85,7 +84,7 @@ export class RainyunRefreshCert extends AbstractTaskPlugin { const pageSize = req.pageSize ?? 100; const res = await access.getCertList({ pageNo, - pageSize + pageSize, }); const total = res.total; const list = res.list; @@ -97,14 +96,14 @@ export class RainyunRefreshCert extends AbstractTaskPlugin { return { label: `${item.Domain}<${item.ID}>`, value: item.ID, - domain: item.Domain.split(",").map(item => item.trim()) + domain: item.Domain.split(",").map(item => item.trim()), }; }); return { list: this.ctx.utils.options.buildGroupOptions(options, this.certDomains), total: total, pageNo: pageNo, - pageSize: pageSize + pageSize: pageSize, }; } } diff --git a/packages/ui/certd-server/src/plugins/plugin-spaceship/access.ts b/packages/ui/certd-server/src/plugins/plugin-spaceship/access.ts index ac84f0569..22ab5b486 100644 --- a/packages/ui/certd-server/src/plugins/plugin-spaceship/access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-spaceship/access.ts @@ -4,18 +4,17 @@ import { IsAccess, AccessInput, BaseAccess, PageSearch } from "@certd/pipeline"; name: "spaceship", title: "Spaceship.com 授权", icon: "clarity:plugin-line", - desc: "Spaceship.com API 授权插件" + desc: "Spaceship.com API 授权插件", }) export class SpaceshipAccess extends BaseAccess { - @AccessInput({ title: "API Key", component: { - placeholder: "请输入 API Key" + placeholder: "请输入 API Key", }, required: true, encrypt: true, - helper: "前往 [获取 API Key](https://www.spaceship.com/application/api-manager/)" + helper: "前往 [获取 API Key](https://www.spaceship.com/application/api-manager/)", }) apiKey = ""; @@ -24,10 +23,10 @@ export class SpaceshipAccess extends BaseAccess { component: { name: "a-input-password", vModel: "value", - placeholder: "请输入 API Secret" + placeholder: "请输入 API Secret", }, required: true, - encrypt: true + encrypt: true, }) apiSecret = ""; @@ -35,9 +34,9 @@ export class SpaceshipAccess extends BaseAccess { title: "测试", component: { name: "api-test", - action: "TestRequest" + action: "TestRequest", }, - helper: "测试 API 连接是否正常,需要域名查询权限" + helper: "测试 API 连接是否正常,需要域名查询权限", }) testRequest = true; @@ -46,24 +45,19 @@ export class SpaceshipAccess extends BaseAccess { return "ok"; } - async doRequest(options: { - url: string; - method: 'GET' | 'POST' | 'DELETE' | 'PUT'; - params?: any; - data?: any; - }) { + async doRequest(options: { url: string; method: "GET" | "POST" | "DELETE" | "PUT"; params?: any; data?: any }) { const headers = { "X-Api-Key": this.apiKey, - "X-Api-Secret": this.apiSecret + "X-Api-Secret": this.apiSecret, }; - + try { const res = await this.ctx.http.request({ url: options.url, method: options.method, headers, params: options.params, - data: options.data + data: options.data, }); return res; } catch (error: any) { @@ -72,22 +66,22 @@ export class SpaceshipAccess extends BaseAccess { if (error.response) { const headers = error.response.headers; const data = error.response.data; - + errorMsg.push(`API 请求失败: ${status}`); - - if (headers['spaceship-error-code']) { - errorMsg.push(`错误代码: ${headers['spaceship-error-code']}`); + + if (headers["spaceship-error-code"]) { + errorMsg.push(`错误代码: ${headers["spaceship-error-code"]}`); } - - if (headers['spaceship-operation-id']) { - errorMsg.push(`操作ID: ${headers['spaceship-operation-id']}`); + + if (headers["spaceship-operation-id"]) { + errorMsg.push(`操作ID: ${headers["spaceship-operation-id"]}`); } - + if (data && data.detail) { errorMsg.push(`错误详情: ${data.detail}`); } - - this.ctx.logger.error(`Spaceship API 错误: ${errorMsg.join(' | ')}`); + + this.ctx.logger.error(`Spaceship API 错误: ${errorMsg.join(" | ")}`); } else if (error.request) { errorMsg.push(`请求发送失败: ${error.message}`); this.ctx.logger.error(`Spaceship API 请求发送失败: ${error.message}`); @@ -95,8 +89,8 @@ export class SpaceshipAccess extends BaseAccess { errorMsg.push(`请求配置错误: ${error.message}`); this.ctx.logger.error(`Spaceship API 请求配置错误: ${error.message}`); } - - const error2 = new Error(errorMsg.join(' | ')); + + const error2 = new Error(errorMsg.join(" | ")); //@ts-ignore error2.status = status; throw error2; @@ -106,19 +100,19 @@ export class SpaceshipAccess extends BaseAccess { async GetDomainList(req: PageSearch) { const take = req.pageSize || 100; const skip = ((req.pageNo || 1) - 1) * take; - + const res = await this.doRequest({ url: "https://spaceship.dev/api/v1/domains", method: "GET", params: { take, - skip - } + skip, + }, }); - + return { total: res.total || 0, - list: res.items || [] + list: res.items || [], }; } @@ -126,7 +120,7 @@ export class SpaceshipAccess extends BaseAccess { try { const res = await this.doRequest({ url: `https://spaceship.dev/api/v1/domains/${domain}`, - method: "GET" + method: "GET", }); return res; } catch (error: any) { @@ -142,7 +136,6 @@ export class SpaceshipAccess extends BaseAccess { const hashCode = this.ctx.utils.hash.sha256(hashStr); return `spaceship-${hashCode}`; } - } -new SpaceshipAccess(); \ No newline at end of file +new SpaceshipAccess(); diff --git a/packages/ui/certd-server/src/plugins/plugin-spaceship/dns-provider.ts b/packages/ui/certd-server/src/plugins/plugin-spaceship/dns-provider.ts index 54938c165..4e3722ff5 100644 --- a/packages/ui/certd-server/src/plugins/plugin-spaceship/dns-provider.ts +++ b/packages/ui/certd-server/src/plugins/plugin-spaceship/dns-provider.ts @@ -12,7 +12,7 @@ export type SpaceshipRecord = { desc: "Spaceship 域名解析", icon: "clarity:plugin-line", accessType: "spaceship", - order: 99 + order: 99, }) export class SpaceshipProvider extends AbstractDnsProvider { access!: SpaceshipAccess; @@ -38,10 +38,10 @@ export class SpaceshipProvider extends AbstractDnsProvider { type: type, value: value, name: hostRecord, - ttl: 60 - } - ] - } + ttl: 60, + }, + ], + }, }); return recordRes; @@ -59,9 +59,9 @@ export class SpaceshipProvider extends AbstractDnsProvider { { type: recordReq.type, value: recordReq.value, - name: recordReq.hostRecord - } - ] + name: recordReq.hostRecord, + }, + ], }); this.logger.info("删除域名解析成功:", JSON.stringify(recordReq)); @@ -69,17 +69,17 @@ export class SpaceshipProvider extends AbstractDnsProvider { async getDomainListPage(req: PageSearch): Promise> { const res = await this.access.GetDomainList(req); - + const list = res.list.map((item: any) => ({ domain: item.name, - id: item.name + id: item.name, })); - + return { total: res.total || 0, - list: list || [] + list: list || [], }; } } -new SpaceshipProvider(); \ No newline at end of file +new SpaceshipProvider(); diff --git a/packages/ui/certd-server/src/plugins/plugin-spaceship/index.ts b/packages/ui/certd-server/src/plugins/plugin-spaceship/index.ts index eeb902d6b..f333fc2d2 100644 --- a/packages/ui/certd-server/src/plugins/plugin-spaceship/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-spaceship/index.ts @@ -1,2 +1,2 @@ import "./access.js"; -import "./dns-provider.js"; \ No newline at end of file +import "./dns-provider.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-technitium/access.ts b/packages/ui/certd-server/src/plugins/plugin-technitium/access.ts index ca7ed96b0..d967ab5f4 100644 --- a/packages/ui/certd-server/src/plugins/plugin-technitium/access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-technitium/access.ts @@ -1,65 +1,60 @@ -import { AccessInput, BaseAccess, IsAccess, Pager, PageRes, PageSearch } from '@certd/pipeline'; -import { DomainRecord } from '@certd/plugin-lib'; +import { AccessInput, BaseAccess, IsAccess, Pager, PageRes, PageSearch } from "@certd/pipeline"; +import { DomainRecord } from "@certd/plugin-lib"; /** * Technitium DNS Server 授权配置 */ @IsAccess({ - name: 'technitium', - title: 'Technitium DNS Server', - icon: 'clarity:server-line', - desc: 'Technitium DNS Server 自建DNS服务器授权', + name: "technitium", + title: "Technitium DNS Server", + icon: "clarity:server-line", + desc: "Technitium DNS Server 自建DNS服务器授权", }) export class TechnitiumAccess extends BaseAccess { - /** * API地址 */ @AccessInput({ - title: 'API地址', - value: 'http://localhost:5380', + title: "API地址", + value: "http://localhost:5380", component: { name: "a-input", allowClear: true, - placeholder: 'http://localhost:5380', + placeholder: "http://localhost:5380", }, required: true, }) - apiUrl = 'http://localhost:5380'; - - - - + apiUrl = "http://localhost:5380"; /** * 用户名 */ @AccessInput({ - title: '用户名', + title: "用户名", component: { name: "a-input", allowClear: true, - placeholder: 'admin', + placeholder: "admin", }, required: false, }) - username = 'admin'; + username = "admin"; /** * 密码 */ @AccessInput({ - title: '密码', + title: "密码", component: { name: "a-input", type: "password", allowClear: true, - placeholder: '密码', + placeholder: "密码", }, required: false, encrypt: true, }) - password = ''; + password = ""; /** * 测试按钮 @@ -68,43 +63,43 @@ export class TechnitiumAccess extends BaseAccess { title: "测试", component: { name: "api-test", - action: "TestRequest" + action: "TestRequest", }, - helper: "点击测试接口是否正常" + helper: "点击测试接口是否正常", }) testRequest = true; - token = ''; + token = ""; /** * 通用API调用方法 */ - async doRequest(options: { url: string; method: 'get' | 'post'; params?: URLSearchParams }) { + async doRequest(options: { url: string; method: "get" | "post"; params?: URLSearchParams }) { // 每次请求前都获取最新的token - if (!options.url.includes('/api/user/login')) { + if (!options.url.includes("/api/user/login")) { await this.getToken(); } - + // 复制参数并添加token - const params = new URLSearchParams(options.params || ''); - if (this.token && !options.url.includes('/api/user/login')) { - params.append('token', this.token); + const params = new URLSearchParams(options.params || ""); + if (this.token && !options.url.includes("/api/user/login")) { + params.append("token", this.token); } - + let fullUrl = options.url; if (params.toString()) { fullUrl = `${options.url}?${params.toString()}`; } - + const response = await this.ctx.http.request({ url: fullUrl, method: options.method, }); - - if (response.status !== 'ok') { - throw new Error(`${response.errorMessage || 'API调用失败'}`); + + if (response.status !== "ok") { + throw new Error(`${response.errorMessage || "API调用失败"}`); } - + return response; } @@ -123,34 +118,34 @@ export class TechnitiumAccess extends BaseAccess { async GetDomainList(req: PageSearch): Promise> { this.ctx.logger.info(`获取域名列表,req:${JSON.stringify(req)}`); const pager = new Pager(req); - + // 规范API地址 this.apiUrl = this.normalizeEndpoint(this.apiUrl); - + // 构建API URL const apiUrl = `${this.apiUrl}/api/zones/list`; - + // 构建查询参数 const params = new URLSearchParams(); - + // 调用API获取区域列表 - const response = await this.doRequest({ url: apiUrl, method: 'get', params: params }); - + const response = await this.doRequest({ url: apiUrl, method: "get", params: params }); + const zones = response.response.zones || []; const total = zones.length; - + // 转换为DomainRecord格式 let list = zones.map((zone: any) => ({ id: zone.name, domain: zone.name, })); - + // 应用分页 list = list.slice(pager.getOffset(), pager.getOffset() + pager.pageSize); - + return { total, - list + list, }; } @@ -159,24 +154,23 @@ export class TechnitiumAccess extends BaseAccess { */ async getToken() { const apiUrl = `${this.apiUrl}/api/user/login`; - + const params = new URLSearchParams({ user: this.username, pass: this.password, }); - + // 直接使用ctx.http.request,避免递归调用doRequest const response = await this.ctx.http.request({ url: `${apiUrl}?${params.toString()}`, - method: 'post', + method: "post", }); - - if (response.status !== 'ok') { - throw new Error(`登录失败: ${response.errorMessage || '未知错误'}`); + + if (response.status !== "ok") { + throw new Error(`登录失败: ${response.errorMessage || "未知错误"}`); } - + this.token = response.token; return this.token; } - } diff --git a/packages/ui/certd-server/src/plugins/plugin-technitium/dns-provider.ts b/packages/ui/certd-server/src/plugins/plugin-technitium/dns-provider.ts index f872865aa..d2f70f99e 100644 --- a/packages/ui/certd-server/src/plugins/plugin-technitium/dns-provider.ts +++ b/packages/ui/certd-server/src/plugins/plugin-technitium/dns-provider.ts @@ -1,6 +1,6 @@ -import { AbstractDnsProvider, CreateRecordOptions, IsDnsProvider, RemoveRecordOptions } from '@certd/plugin-cert'; +import { AbstractDnsProvider, CreateRecordOptions, IsDnsProvider, RemoveRecordOptions } from "@certd/plugin-cert"; -import { TechnitiumAccess } from "./access.js" +import { TechnitiumAccess } from "./access.js"; type TechnitiumRecord = { // 记录创建时返回的数据结构 @@ -26,11 +26,11 @@ type TechnitiumRecord = { // 注册Technitium DNS Server的DNS提供商 @IsDnsProvider({ - name: 'technitium', - title: 'Technitium DNS Server', - desc: 'Technitium DNS Server 自建DNS服务器', - icon: 'clarity:server-line', - accessType: 'technitium', + name: "technitium", + title: "Technitium DNS Server", + desc: "Technitium DNS Server 自建DNS服务器", + icon: "clarity:server-line", + accessType: "technitium", order: 10, }) export class TechnitiumDnsProvider extends AbstractDnsProvider { @@ -38,7 +38,7 @@ export class TechnitiumDnsProvider extends AbstractDnsProvider async onInstance() { this.access = this.ctx.access as TechnitiumAccess; - this.logger.debug('access', this.access); + this.logger.debug("access", this.access); } /** @@ -46,11 +46,11 @@ export class TechnitiumDnsProvider extends AbstractDnsProvider */ async createRecord(options: CreateRecordOptions): Promise { const { fullRecord, value, type, domain } = options; - this.logger.info('添加域名解析:', fullRecord, value, type, domain); + this.logger.info("添加域名解析:", fullRecord, value, type, domain); // 构建API URL const apiUrl = `${this.access.apiUrl}/api/zones/records/add`; - + // 构建查询参数 const params = new URLSearchParams({ zone: domain, @@ -61,9 +61,9 @@ export class TechnitiumDnsProvider extends AbstractDnsProvider }); // 调用Technitium API创建TXT记录 - const response = await this.access.doRequest({ url: apiUrl, method: 'post', params: params }); + const response = await this.access.doRequest({ url: apiUrl, method: "post", params: params }); - this.logger.info('创建域名解析成功:', fullRecord, value); + this.logger.info("创建域名解析成功:", fullRecord, value); return response as TechnitiumRecord; } @@ -73,23 +73,23 @@ export class TechnitiumDnsProvider extends AbstractDnsProvider async removeRecord(options: RemoveRecordOptions): Promise { const { fullRecord, value, domain } = options.recordReq; const record = options.recordRes; - this.logger.info('删除域名解析:', domain, fullRecord, value, record); + this.logger.info("删除域名解析:", domain, fullRecord, value, record); // 构建API URL const apiUrl = `${this.access.apiUrl}/api/zones/records/delete`; - + // 构建查询参数 const params = new URLSearchParams({ zone: domain, domain: fullRecord, - type: 'TXT', + type: "TXT", text: value, }); // 调用Technitium API删除TXT记录 - await this.access.doRequest({ url: apiUrl, method: 'post', params: params }); + await this.access.doRequest({ url: apiUrl, method: "post", params: params }); - this.logger.info('删除域名解析成功:', fullRecord, value); + this.logger.info("删除域名解析成功:", fullRecord, value); } } diff --git a/packages/ui/certd-server/src/plugins/plugin-technitium/index.ts b/packages/ui/certd-server/src/plugins/plugin-technitium/index.ts index db899c717..d0bc76d38 100644 --- a/packages/ui/certd-server/src/plugins/plugin-technitium/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-technitium/index.ts @@ -1,2 +1,2 @@ -export * from './dns-provider.js'; -export * from './access.js'; +export * from "./dns-provider.js"; +export * from "./access.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-template/api.ts b/packages/ui/certd-server/src/plugins/plugin-template/api.ts index b38c48ab7..dfa8ee4f2 100644 --- a/packages/ui/certd-server/src/plugins/plugin-template/api.ts +++ b/packages/ui/certd-server/src/plugins/plugin-template/api.ts @@ -1,18 +1,15 @@ - export type BuildContentReq = { - data: any; + data: any; +}; + +export interface ITemplateProvider { + buildContent: (params: BuildContentReq) => Promise; + + buildDefaultContent: (params: BuildContentReq) => Promise; } - -export interface ITemplateProvider { - buildContent: (params: BuildContentReq) => Promise; - - buildDefaultContent:(params: BuildContentReq) => Promise; -} - - export type EmailContent = { - subject:string, - content?:string, - html?:string + subject: string; + content?: string; + html?: string; }; diff --git a/packages/ui/certd-server/src/plugins/plugin-template/email/index.ts b/packages/ui/certd-server/src/plugins/plugin-template/email/index.ts index be4697ab2..d764a3b5d 100644 --- a/packages/ui/certd-server/src/plugins/plugin-template/email/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-template/email/index.ts @@ -1,5 +1,5 @@ -export * from './plugin-common.js' -export * from './plugin-register-code.js' -export * from './plugin-forgot-password.js' -export * from './plugin-pipeline-result.js' -export * from './plugin-send-cert.js' \ No newline at end of file +export * from "./plugin-common.js"; +export * from "./plugin-register-code.js"; +export * from "./plugin-forgot-password.js"; +export * from "./plugin-pipeline-result.js"; +export * from "./plugin-send-cert.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-template/email/plugin-base.ts b/packages/ui/certd-server/src/plugins/plugin-template/email/plugin-base.ts index 1481a9c81..3c1f1bd0f 100644 --- a/packages/ui/certd-server/src/plugins/plugin-template/email/plugin-base.ts +++ b/packages/ui/certd-server/src/plugins/plugin-template/email/plugin-base.ts @@ -9,14 +9,13 @@ export class BaseEmailTemplateProvider extends BaseAddon implements ITemplatePro props: { type: "info", message: "在标题和内容模版中,通过${name}引用参数,例如: 感谢注册,您的注册验证码为:${code}", - } + }, }, order: -9, col: { span: 24 }, }) useIntro = ""; - @AddonInput({ title: "邮件格式", component: { @@ -25,8 +24,8 @@ export class BaseEmailTemplateProvider extends BaseAddon implements ITemplatePro options: [ { label: "HTML", value: "html" }, { label: "TEXT", value: "text" }, - ] - } + ], + }, }, order: 9, col: { span: 24 }, @@ -42,7 +41,7 @@ export class BaseEmailTemplateProvider extends BaseAddon implements ITemplatePro name: "a-input", props: { placeholder: "邮件标题模版", - } + }, }, col: { span: 24 }, }) @@ -60,30 +59,29 @@ export class BaseEmailTemplateProvider extends BaseAddon implements ITemplatePro }) contentTemplate = ""; - async buildContent(params: BuildContentReq): Promise { const data = { - title:"", - content:"", - url:"", + title: "", + content: "", + url: "", ...params.data, - } - const title = this.compile(this.titleTemplate)(data) - const content = this.compile(this.contentTemplate)(data) + }; + const title = this.compile(this.titleTemplate)(data); + const content = this.compile(this.contentTemplate)(data); const body: any = { subject: title, - } + }; if (this.formatType === "html") { - body.html = content + body.html = content; } else { - body.content = content + body.content = content; } - return body - }; + return body; + } async buildDefaultContent(params: BuildContentReq): Promise { - throw new Error("请实现 buildDefaultContent 方法") + throw new Error("请实现 buildDefaultContent 方法"); } // compile(templateString: string) { @@ -95,11 +93,13 @@ export class BaseEmailTemplateProvider extends BaseAddon implements ITemplatePro // }; // } - compile(templateString:string) { - return new Function('data', ` with(data || {}) { + compile(templateString: string) { + return new Function( + "data", + ` with(data || {}) { return \`${templateString}\`; } - `); + ` + ); } - } diff --git a/packages/ui/certd-server/src/plugins/plugin-template/email/plugin-common.ts b/packages/ui/certd-server/src/plugins/plugin-template/email/plugin-common.ts index f77b84dad..34e3816c1 100644 --- a/packages/ui/certd-server/src/plugins/plugin-template/email/plugin-common.ts +++ b/packages/ui/certd-server/src/plugins/plugin-template/email/plugin-common.ts @@ -4,9 +4,9 @@ import { BaseEmailTemplateProvider } from "./plugin-base.js"; @IsAddon({ addonType: "emailTemplate", - name: 'common', - title: '通用邮件模版', - desc: '使用通用的邮件标题和内容,内容外部可以自定义html进行美化', + name: "common", + title: "通用邮件模版", + desc: "使用通用的邮件标题和内容,内容外部可以自定义html进行美化", icon: "simple-icons:email:blue", showTest: false, }) @@ -15,25 +15,22 @@ export class CommonEmailTemplateProvider extends BaseEmailTemplateProvider imple title: "可用参数", component: { name: "ParamsShow", - params:[ - {label:"标题",value:"title"}, - {label:"内容",value:"content"}, - {label:"URL",value:"url"} - ] + params: [ + { label: "标题", value: "title" }, + { label: "内容", value: "content" }, + { label: "URL", value: "url" }, + ], }, - helper:"html格式下${content}建议使用pre标签包裹:例如:<pre>${content}</pre>", + helper: "html格式下${content}建议使用pre标签包裹:例如:<pre>${content}</pre>", col: { span: 24 }, }) paramIntro = ""; - - async buildDefaultContent(req:BuildContentReq) { - const defaultTemplate = new CommonEmailTemplateProvider() - defaultTemplate.titleTemplate = "${title}" - defaultTemplate.contentTemplate = "${content} \n\n ${url?'查看详情:'+url:''}" - defaultTemplate.formatType = "text" - return await defaultTemplate.buildContent(req) + async buildDefaultContent(req: BuildContentReq) { + const defaultTemplate = new CommonEmailTemplateProvider(); + defaultTemplate.titleTemplate = "${title}"; + defaultTemplate.contentTemplate = "${content} \n\n ${url?'查看详情:'+url:''}"; + defaultTemplate.formatType = "text"; + return await defaultTemplate.buildContent(req); } - - } diff --git a/packages/ui/certd-server/src/plugins/plugin-template/email/plugin-forgot-password.ts b/packages/ui/certd-server/src/plugins/plugin-template/email/plugin-forgot-password.ts index 38773da71..aa85e805f 100644 --- a/packages/ui/certd-server/src/plugins/plugin-template/email/plugin-forgot-password.ts +++ b/packages/ui/certd-server/src/plugins/plugin-template/email/plugin-forgot-password.ts @@ -4,9 +4,9 @@ import { BaseEmailTemplateProvider } from "./plugin-base.js"; @IsAddon({ addonType: "emailTemplate", - name: 'forgotPassword', - title: '忘记密码邮件模版', - desc: '您正在重置密码,您的验证码为xxxx,请勿泄露', + name: "forgotPassword", + title: "忘记密码邮件模版", + desc: "您正在重置密码,您的验证码为xxxx,请勿泄露", icon: "simple-icons:email:blue", showTest: false, }) @@ -15,21 +15,17 @@ export class ForgotPasswordEmailTemplateProvider extends BaseEmailTemplateProvid title: "可用参数", component: { name: "ParamsShow", - params:[ - {label:"验证码",value:"code"} - ] + params: [{ label: "验证码", value: "code" }], }, col: { span: 24 }, }) paramIntro = ""; - - async buildDefaultContent(req:BuildContentReq) { - const defaultTemplate = new ForgotPasswordEmailTemplateProvider() - defaultTemplate.titleTemplate = "忘记密码" - defaultTemplate.contentTemplate = "您的验证码是:${code},请勿泄露" - defaultTemplate.formatType = "text" - return await defaultTemplate.buildContent(req) + async buildDefaultContent(req: BuildContentReq) { + const defaultTemplate = new ForgotPasswordEmailTemplateProvider(); + defaultTemplate.titleTemplate = "忘记密码"; + defaultTemplate.contentTemplate = "您的验证码是:${code},请勿泄露"; + defaultTemplate.formatType = "text"; + return await defaultTemplate.buildContent(req); } - } diff --git a/packages/ui/certd-server/src/plugins/plugin-template/email/plugin-pipeline-result.ts b/packages/ui/certd-server/src/plugins/plugin-template/email/plugin-pipeline-result.ts index 8dc2c678c..10e2c8ecc 100644 --- a/packages/ui/certd-server/src/plugins/plugin-template/email/plugin-pipeline-result.ts +++ b/packages/ui/certd-server/src/plugins/plugin-template/email/plugin-pipeline-result.ts @@ -4,9 +4,9 @@ import { BaseEmailTemplateProvider } from "./plugin-base.js"; @IsAddon({ addonType: "emailTemplate", - name: 'pipelineResult', - title: '流水线执行结果邮件模版', - desc: '执行失败,xxxx自动化【流水线id】;运行ID:xxx,错误信息:xxxx', + name: "pipelineResult", + title: "流水线执行结果邮件模版", + desc: "执行失败,xxxx自动化【流水线id】;运行ID:xxx,错误信息:xxxx", icon: "simple-icons:email:blue", showTest: false, }) @@ -15,29 +15,27 @@ export class PipelineResultEmailTemplateProvider extends BaseEmailTemplateProvid title: "可用参数", component: { name: "ParamsShow", - params:[ - {label:"运行结果",value:"pipelineResult"}, - {label:"流水线标题",value:"pipelineTitle"}, - {label:"流水线ID",value:"pipelineId"}, - {label:"运行Id",value:"historyId"}, - {label:"错误信息",value:"errors"}, - {label:"URL",value:"url"}, - ] + params: [ + { label: "运行结果", value: "pipelineResult" }, + { label: "流水线标题", value: "pipelineTitle" }, + { label: "流水线ID", value: "pipelineId" }, + { label: "运行Id", value: "historyId" }, + { label: "错误信息", value: "errors" }, + { label: "URL", value: "url" }, + ], }, col: { span: 24 }, }) paramIntro = ""; - - async buildDefaultContent(req:BuildContentReq) { - const defaultTemplate = new PipelineResultEmailTemplateProvider() + async buildDefaultContent(req: BuildContentReq) { + const defaultTemplate = new PipelineResultEmailTemplateProvider(); const subject = "${result},${pipelineTitle}【${pipelineId}】"; const content = "流水线ID:${pipelineId},运行ID:${runtimeId} \n\n ${errors}"; - defaultTemplate.titleTemplate = subject - defaultTemplate.contentTemplate = content - defaultTemplate.formatType = "text" - return await defaultTemplate.buildContent(req) + defaultTemplate.titleTemplate = subject; + defaultTemplate.contentTemplate = content; + defaultTemplate.formatType = "text"; + return await defaultTemplate.buildContent(req); } - } diff --git a/packages/ui/certd-server/src/plugins/plugin-template/email/plugin-register-code.ts b/packages/ui/certd-server/src/plugins/plugin-template/email/plugin-register-code.ts index 613a02345..ad3f1f5fa 100644 --- a/packages/ui/certd-server/src/plugins/plugin-template/email/plugin-register-code.ts +++ b/packages/ui/certd-server/src/plugins/plugin-template/email/plugin-register-code.ts @@ -4,9 +4,9 @@ import { BaseEmailTemplateProvider } from "./plugin-base.js"; @IsAddon({ addonType: "emailTemplate", - name: 'registerCode', - title: '注册验证码邮件模版', - desc: '您的注册验证码为:xxxx,请勿泄露', + name: "registerCode", + title: "注册验证码邮件模版", + desc: "您的注册验证码为:xxxx,请勿泄露", icon: "simple-icons:email:blue", showTest: false, }) @@ -15,22 +15,17 @@ export class RegisterCodeEmailTemplateProvider extends BaseEmailTemplateProvider title: "可用参数", component: { name: "ParamsShow", - params:[ - {label:"验证码",value:"code"} - ] + params: [{ label: "验证码", value: "code" }], }, col: { span: 24 }, }) paramIntro = ""; - - async buildDefaultContent(req:BuildContentReq) { - const defaultTemplate = new RegisterCodeEmailTemplateProvider() - defaultTemplate.titleTemplate = "注册验证码" - defaultTemplate.contentTemplate = "您的注册验证码是:${code},请勿泄露" - defaultTemplate.formatType = "text" - return await defaultTemplate.buildContent(req) + async buildDefaultContent(req: BuildContentReq) { + const defaultTemplate = new RegisterCodeEmailTemplateProvider(); + defaultTemplate.titleTemplate = "注册验证码"; + defaultTemplate.contentTemplate = "您的注册验证码是:${code},请勿泄露"; + defaultTemplate.formatType = "text"; + return await defaultTemplate.buildContent(req); } - - } diff --git a/packages/ui/certd-server/src/plugins/plugin-template/email/plugin-send-cert.ts b/packages/ui/certd-server/src/plugins/plugin-template/email/plugin-send-cert.ts index dccac8cc0..26f5e0d29 100644 --- a/packages/ui/certd-server/src/plugins/plugin-template/email/plugin-send-cert.ts +++ b/packages/ui/certd-server/src/plugins/plugin-template/email/plugin-send-cert.ts @@ -4,9 +4,9 @@ import { BaseEmailTemplateProvider } from "./plugin-base.js"; @IsAddon({ addonType: "emailTemplate", - name: 'sendCert', - title: '发送证书邮件模版', - desc: '邮件发送证书插件的邮件模版', + name: "sendCert", + title: "发送证书邮件模版", + desc: "邮件发送证书插件的邮件模版", icon: "simple-icons:email:blue", showTest: false, }) @@ -15,7 +15,7 @@ export class SendCertEmailTemplateProvider extends BaseEmailTemplateProvider imp title: "可用参数", component: { name: "ParamsShow", - params:[ + params: [ /** * mainDomain, domains, @@ -25,26 +25,24 @@ export class SendCertEmailTemplateProvider extends BaseEmailTemplateProvider imp key: this.cert.key, ic: this.cert.ic, */ - {label:"主域名",value:"mainDomain"}, - {label:"全部域名",value:"domains"}, - {label:"过期时间",value:"expiresTime"}, - {label:"备注",value:"remark"}, - {label:"证书内容",value:"crt"}, - {label:"私钥内容",value:"key"}, - {label:"中间证书",value:"ic"}, - ] + { label: "主域名", value: "mainDomain" }, + { label: "全部域名", value: "domains" }, + { label: "过期时间", value: "expiresTime" }, + { label: "备注", value: "remark" }, + { label: "证书内容", value: "crt" }, + { label: "私钥内容", value: "key" }, + { label: "中间证书", value: "ic" }, + ], }, col: { span: 24 }, }) paramIntro = ""; - - async buildDefaultContent(req:BuildContentReq) { - const defaultTemplate = new SendCertEmailTemplateProvider() - defaultTemplate.titleTemplate = "${title}" - defaultTemplate.contentTemplate = "${content}" - defaultTemplate.formatType = "text" - return await defaultTemplate.buildContent(req) + async buildDefaultContent(req: BuildContentReq) { + const defaultTemplate = new SendCertEmailTemplateProvider(); + defaultTemplate.titleTemplate = "${title}"; + defaultTemplate.contentTemplate = "${content}"; + defaultTemplate.formatType = "text"; + return await defaultTemplate.buildContent(req); } - } diff --git a/packages/ui/certd-server/src/plugins/plugin-template/index.ts b/packages/ui/certd-server/src/plugins/plugin-template/index.ts index 1bcdf51cf..d712e2b99 100644 --- a/packages/ui/certd-server/src/plugins/plugin-template/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-template/index.ts @@ -1 +1 @@ -export * from "./email/index.js" \ No newline at end of file +export * from "./email/index.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-tencent/access/dnspod-access.ts b/packages/ui/certd-server/src/plugins/plugin-tencent/access/dnspod-access.ts index f3f5c63c1..c9b2be0b3 100644 --- a/packages/ui/certd-server/src/plugins/plugin-tencent/access/dnspod-access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-tencent/access/dnspod-access.ts @@ -1,46 +1,46 @@ -import { IsAccess, AccessInput, BaseAccess } from '@certd/pipeline'; +import { IsAccess, AccessInput, BaseAccess } from "@certd/pipeline"; @IsAccess({ - name: 'dnspod', - title: 'dnspod(已废弃)', - desc: '腾讯云的域名解析接口已迁移到dnspod', - deprecated: 'dnspod已废弃,请换成腾讯云', - icon: 'svg:icon-tencentcloud', + name: "dnspod", + title: "dnspod(已废弃)", + desc: "腾讯云的域名解析接口已迁移到dnspod", + deprecated: "dnspod已废弃,请换成腾讯云", + icon: "svg:icon-tencentcloud", }) export class DnspodAccess extends BaseAccess { @AccessInput({ - title: '端点', + title: "端点", component: { - placeholder: 'endpoint', - name: 'a-auto-complete', - vModel: 'value', + placeholder: "endpoint", + name: "a-auto-complete", + vModel: "value", options: [ - { value: 'https://dnsapi.cn', label: '中国站' }, - { value: 'https://api.dnspod.com', label: '国际站' }, + { value: "https://dnsapi.cn", label: "中国站" }, + { value: "https://api.dnspod.com", label: "国际站" }, ], }, - rules: [{ required: true, message: '该项必填' }], + rules: [{ required: true, message: "该项必填" }], }) - endpoint = ''; + endpoint = ""; @AccessInput({ - title: 'ID', + title: "ID", component: { - placeholder: 'dnspod token 的 id', + placeholder: "dnspod token 的 id", }, - rules: [{ required: true, message: '该项必填' }], + rules: [{ required: true, message: "该项必填" }], }) - id = ''; + id = ""; @AccessInput({ - title: 'token', + title: "token", component: { - placeholder: '开放接口token', + placeholder: "开放接口token", }, encrypt: true, - rules: [{ required: true, message: '该项必填' }], + rules: [{ required: true, message: "该项必填" }], }) - token = ''; + token = ""; } new DnspodAccess(); diff --git a/packages/ui/certd-server/src/plugins/plugin-tencent/access/index.ts b/packages/ui/certd-server/src/plugins/plugin-tencent/access/index.ts index 293c06ce2..c1d7bee1e 100644 --- a/packages/ui/certd-server/src/plugins/plugin-tencent/access/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-tencent/access/index.ts @@ -1 +1 @@ -export * from './dnspod-access.js'; +export * from "./dnspod-access.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-tencent/dns-provider/dnspod-dns-provider.ts b/packages/ui/certd-server/src/plugins/plugin-tencent/dns-provider/dnspod-dns-provider.ts index e83c75da4..9aba107b4 100644 --- a/packages/ui/certd-server/src/plugins/plugin-tencent/dns-provider/dnspod-dns-provider.ts +++ b/packages/ui/certd-server/src/plugins/plugin-tencent/dns-provider/dnspod-dns-provider.ts @@ -1,37 +1,37 @@ -import { AbstractDnsProvider, CreateRecordOptions, IsDnsProvider, RemoveRecordOptions } from '@certd/plugin-cert'; -import * as _ from 'lodash-es'; -import { DnspodAccess } from '../access/index.js'; +import { AbstractDnsProvider, CreateRecordOptions, IsDnsProvider, RemoveRecordOptions } from "@certd/plugin-cert"; +import * as _ from "lodash-es"; +import { DnspodAccess } from "../access/index.js"; @IsDnsProvider({ - name: 'dnspod', - title: 'dnspod(已过时,请尽快换成腾讯云)', - desc: '已废弃,请尽快换成腾讯云类型', - accessType: 'dnspod', - deprecated: 'dnspod已废弃,请换成腾讯云', - icon: 'svg:icon-tencentcloud', + name: "dnspod", + title: "dnspod(已过时,请尽快换成腾讯云)", + desc: "已废弃,请尽快换成腾讯云类型", + accessType: "dnspod", + deprecated: "dnspod已废弃,请换成腾讯云", + icon: "svg:icon-tencentcloud", }) export class DnspodDnsProvider extends AbstractDnsProvider { access!: DnspodAccess; loginToken: any; - endpoint = ''; + endpoint = ""; async onInstance() { - this.access = this.ctx.access as DnspodAccess + this.access = this.ctx.access as DnspodAccess; const access: DnspodAccess = this.access as DnspodAccess; - this.loginToken = access.id + ',' + access.token; - this.endpoint = access.endpoint || 'https://dnsapi.cn'; + this.loginToken = access.id + "," + access.token; + this.endpoint = access.endpoint || "https://dnsapi.cn"; } async doRequest(options: any, successCodes: string[] = []) { const config: any = { // @ts-ignore - method: 'post', + method: "post", formData: { login_token: this.loginToken, - format: 'json', - lang: 'cn', - error_on_empty: 'no', + format: "json", + lang: "cn", + error_on_empty: "no", }, timeout: 10000, }; @@ -40,8 +40,8 @@ export class DnspodDnsProvider extends AbstractDnsProvider { const ret: any = await this.http.request(config); if (!ret || !ret.status) { const code = ret.status.code; - if (code !== '1' || !successCodes.includes(code)) { - throw new Error('请求失败:' + ret.status.message + ',api=' + config.url); + if (code !== "1" || !successCodes.includes(code)) { + throw new Error("请求失败:" + ret.status.message + ",api=" + config.url); } } return ret; @@ -49,34 +49,34 @@ export class DnspodDnsProvider extends AbstractDnsProvider { async getDomainList() { const ret = await this.doRequest({ - url: this.access.endpoint + '/Domain.List', + url: this.access.endpoint + "/Domain.List", }); - this.logger.info('dnspod 域名列表:', ret.domains); + this.logger.info("dnspod 域名列表:", ret.domains); return ret.domains; } async createRecord(options: CreateRecordOptions): Promise { const { fullRecord, value, type } = options; - this.logger.info('添加域名解析:', fullRecord, value); + this.logger.info("添加域名解析:", fullRecord, value); const domainItem = await this.matchDomain(fullRecord); const domain = domainItem.name; - const rr = fullRecord.replace('.' + domain, ''); + const rr = fullRecord.replace("." + domain, ""); const ret = await this.doRequest( { - url: this.access.endpoint + '/Record.Create', + url: this.access.endpoint + "/Record.Create", formData: { domain, sub_domain: rr, record_type: type, - record_line: '默认', + record_line: "默认", value: value, mx: 1, }, }, - ['104'] + ["104"] ); // 104错误码为记录已存在,无需再次添加 - this.logger.info('添加域名解析成功:', fullRecord, value, JSON.stringify(ret.record)); + this.logger.info("添加域名解析成功:", fullRecord, value, JSON.stringify(ret.record)); return ret.record; } @@ -86,30 +86,30 @@ export class DnspodDnsProvider extends AbstractDnsProvider { const domain = await this.matchDomain(fullRecord); const ret = await this.doRequest({ - url: this.access.endpoint + '/Record.Remove', + url: this.access.endpoint + "/Record.Remove", formData: { domain, record_id: record.id, }, }); - this.logger.info('删除域名解析成功:', fullRecord, value); + this.logger.info("删除域名解析成功:", fullRecord, value); return ret.RecordId; } async matchDomain(dnsRecord: any) { const list = await this.getDomainList(); if (list == null) { - throw new Error('域名列表不能为空'); + throw new Error("域名列表不能为空"); } let domain = null; for (const item of list) { - if (_.endsWith(dnsRecord, '.' + item.name)) { + if (_.endsWith(dnsRecord, "." + item.name)) { domain = item; break; } } if (!domain) { - throw new Error('找不到域名,请检查域名是否正确:' + dnsRecord); + throw new Error("找不到域名,请检查域名是否正确:" + dnsRecord); } return domain; } diff --git a/packages/ui/certd-server/src/plugins/plugin-tencent/dns-provider/index.ts b/packages/ui/certd-server/src/plugins/plugin-tencent/dns-provider/index.ts index 658355b5b..63781a914 100644 --- a/packages/ui/certd-server/src/plugins/plugin-tencent/dns-provider/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-tencent/dns-provider/index.ts @@ -1,3 +1,3 @@ -import './dnspod-dns-provider.js'; -import './tencent-dns-provider.js'; -import './teo-dns-provider.js'; +import "./dnspod-dns-provider.js"; +import "./tencent-dns-provider.js"; +import "./teo-dns-provider.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-tencent/dns-provider/tencent-dns-provider.ts b/packages/ui/certd-server/src/plugins/plugin-tencent/dns-provider/tencent-dns-provider.ts index 85aeeafc9..fb826919f 100644 --- a/packages/ui/certd-server/src/plugins/plugin-tencent/dns-provider/tencent-dns-provider.ts +++ b/packages/ui/certd-server/src/plugins/plugin-tencent/dns-provider/tencent-dns-provider.ts @@ -1,33 +1,33 @@ -import { AbstractDnsProvider, CreateRecordOptions, DomainRecord, IsDnsProvider, RemoveRecordOptions } from '@certd/plugin-cert'; -import { TencentAccess } from '../../plugin-lib/tencent/index.js'; -import { Pager, PageRes, PageSearch } from '@certd/pipeline'; +import { AbstractDnsProvider, CreateRecordOptions, DomainRecord, IsDnsProvider, RemoveRecordOptions } from "@certd/plugin-cert"; +import { TencentAccess } from "../../plugin-lib/tencent/index.js"; +import { Pager, PageRes, PageSearch } from "@certd/pipeline"; @IsDnsProvider({ - name: 'tencent', - title: '腾讯云', - desc: '腾讯云域名DNS解析提供者', - accessType: 'tencent', - icon: 'svg:icon-tencentcloud', + name: "tencent", + title: "腾讯云", + desc: "腾讯云域名DNS解析提供者", + accessType: "tencent", + icon: "svg:icon-tencentcloud", }) export class TencentDnsProvider extends AbstractDnsProvider { access!: TencentAccess; client!: any; - endpoint = 'dnspod.tencentcloudapi.com'; + endpoint = "dnspod.tencentcloudapi.com"; async onInstance() { - this.access = this.ctx.access as TencentAccess + this.access = this.ctx.access as TencentAccess; const clientConfig = { credential: this.access, - region: '', + region: "", profile: { httpProfile: { endpoint: this.endpoint, }, }, }; - const dnspodSdk = await import('tencentcloud-sdk-nodejs/tencentcloud/services/dnspod/v20210323/index.js'); + const dnspodSdk = await import("tencentcloud-sdk-nodejs/tencentcloud/services/dnspod/v20210323/index.js"); const DnspodClient = dnspodSdk.v20210323.Client; // 实例化要请求产品的client对象,clientProfile是可选的 this.client = new DnspodClient(clientConfig); @@ -35,20 +35,20 @@ export class TencentDnsProvider extends AbstractDnsProvider { async createRecord(options: CreateRecordOptions): Promise { const { fullRecord, value, type, domain } = options; - this.logger.info('添加域名解析:', fullRecord, value); - const rr = fullRecord.replace('.' + domain, ''); + this.logger.info("添加域名解析:", fullRecord, value); + const rr = fullRecord.replace("." + domain, ""); const params = { Domain: domain, RecordType: type, - RecordLine: '默认', + RecordLine: "默认", Value: value, SubDomain: rr, }; try { const ret = await this.client.CreateRecord(params); - this.logger.info('添加域名解析成功:', fullRecord, value, JSON.stringify(ret)); + this.logger.info("添加域名解析成功:", fullRecord, value, JSON.stringify(ret)); /* { "RecordId": 162, @@ -57,8 +57,8 @@ export class TencentDnsProvider extends AbstractDnsProvider { */ return ret; } catch (e: any) { - if (e?.code === 'InvalidParameter.DomainRecordExist') { - this.logger.info('域名解析已存在,无需重复添加:', fullRecord, value); + if (e?.code === "InvalidParameter.DomainRecordExist") { + this.logger.info("域名解析已存在,无需重复添加:", fullRecord, value); return await this.findRecord(options); } throw e; @@ -74,7 +74,7 @@ export class TencentDnsProvider extends AbstractDnsProvider { }; const ret = await this.client.DescribeRecordFilterList(params); if (ret.RecordList && ret.RecordList.length > 0) { - this.logger.info('已存在解析记录:', ret.RecordList); + this.logger.info("已存在解析记录:", ret.RecordList); return ret.RecordList[0]; } return {}; @@ -84,22 +84,21 @@ export class TencentDnsProvider extends AbstractDnsProvider { const { fullRecord, value, domain } = options.recordReq; const record = options.recordRes; if (!record) { - this.logger.info('解析记录recordId为空,不执行删除', fullRecord, value); + this.logger.info("解析记录recordId为空,不执行删除", fullRecord, value); } const params = { Domain: domain, RecordId: record.RecordId, }; const ret = await this.client.DeleteRecord(params); - this.logger.info('删除域名解析成功:', fullRecord, value); + this.logger.info("删除域名解析成功:", fullRecord, value); return ret; } async getDomainListPage(req: PageSearch): Promise> { - const pager = new Pager(req); - - const params:any = { + + const params: any = { Offset: pager.getOffset(), Limit: pager.pageSize, }; @@ -108,12 +107,12 @@ export class TencentDnsProvider extends AbstractDnsProvider { } const ret = await this.client.DescribeDomainList(params); let list = ret.DomainList || []; - list = list.map((item) => ({ + list = list.map(item => ({ id: item.DomainId, domain: item.Name, })); - const total = ret.DomainCountInfo?.AllTotal || list.length - return {total,list,}; + const total = ret.DomainCountInfo?.AllTotal || list.length; + return { total, list }; } } new TencentDnsProvider(); diff --git a/packages/ui/certd-server/src/plugins/plugin-tencent/dns-provider/teo-dns-provider.ts b/packages/ui/certd-server/src/plugins/plugin-tencent/dns-provider/teo-dns-provider.ts index 39c3b734e..bf7be1202 100644 --- a/packages/ui/certd-server/src/plugins/plugin-tencent/dns-provider/teo-dns-provider.ts +++ b/packages/ui/certd-server/src/plugins/plugin-tencent/dns-provider/teo-dns-provider.ts @@ -1,145 +1,131 @@ -import { AbstractDnsProvider, CreateRecordOptions, IsDnsProvider, RemoveRecordOptions } from '@certd/plugin-cert'; -import { TencentAccess } from '../../plugin-lib/tencent/access.js'; +import { AbstractDnsProvider, CreateRecordOptions, IsDnsProvider, RemoveRecordOptions } from "@certd/plugin-cert"; +import { TencentAccess } from "../../plugin-lib/tencent/access.js"; @IsDnsProvider({ - name: 'tencent-eo', - title: '腾讯云EO DNS', - desc: '腾讯云EO DNS解析提供者', - accessType: 'tencent', - icon: 'svg:icon-tencentcloud', + name: "tencent-eo", + title: "腾讯云EO DNS", + desc: "腾讯云EO DNS解析提供者", + accessType: "tencent", + icon: "svg:icon-tencentcloud", }) export class TencentEoDnsProvider extends AbstractDnsProvider { - access!: TencentAccess; + access!: TencentAccess; - client!: any; + client!: any; + async onInstance() { + this.access = this.ctx.access as TencentAccess; + const clientConfig = { + credential: this.access, + region: "", + profile: { + httpProfile: { + endpoint: this.access.buildEndpoint("teo.tencentcloudapi.com"), + }, + }, + }; + const teosdk = await import("tencentcloud-sdk-nodejs/tencentcloud/services/teo/v20220901/index.js"); + const TeoClient = teosdk.v20220901.Client; + // 实例化要请求产品的client对象,clientProfile是可选的 + this.client = new TeoClient(clientConfig); + } - async onInstance() { - this.access = this.ctx.access as TencentAccess - const clientConfig = { - credential: this.access, - region: '', - profile: { - httpProfile: { - endpoint: this.access.buildEndpoint("teo.tencentcloudapi.com"), - }, - }, - }; - const teosdk = await import('tencentcloud-sdk-nodejs/tencentcloud/services/teo/v20220901/index.js'); - const TeoClient = teosdk.v20220901.Client; - // 实例化要请求产品的client对象,clientProfile是可选的 - this.client = new TeoClient(clientConfig); + async getZoneId(domain: string) { + const params = { + Filters: [ + { + Name: "zone-name", + Values: [domain], + }, + ], + }; + const res = await this.client.DescribeZones(params); + if (res.Zones && res.Zones.length > 0) { + return res.Zones[0].ZoneId; } + throw new Error("未找到对应的ZoneId"); + } + async createRecord(options: CreateRecordOptions): Promise { + const { fullRecord, value, type, domain } = options; + this.logger.info("添加域名解析:", fullRecord, value); - async getZoneId(domain: string) { + const zoneId = await this.getZoneId(domain); + const params = { + ZoneId: zoneId, + Name: fullRecord, + Type: type, + Content: value, + TTL: 60, + }; - const params = { - "Filters": [ - { - "Name": "zone-name", - "Values": [ - domain - ] - } - ] - }; - const res = await this.client.DescribeZones(params); - if (res.Zones && res.Zones.length > 0) { - return res.Zones[0].ZoneId; - } - throw new Error('未找到对应的ZoneId'); - } - - async createRecord(options: CreateRecordOptions): Promise { - const { fullRecord, value, type, domain } = options; - this.logger.info('添加域名解析:', fullRecord, value); - - const zoneId = await this.getZoneId(domain); - const params = { - "ZoneId": zoneId, - "Name": fullRecord, - "Type": type, - "Content": value, - "TTL": 60, - }; - - try { - const ret = await this.client.CreateDnsRecord(params); - this.logger.info('添加域名解析成功:', fullRecord, value, JSON.stringify(ret)); - /* + try { + const ret = await this.client.CreateDnsRecord(params); + this.logger.info("添加域名解析成功:", fullRecord, value, JSON.stringify(ret)); + /* { "RecordId": 162, "RequestId": "ab4f1426-ea15-42ea-8183-dc1b44151166" } */ - return { - RecordId: ret.RecordId, - ZoneId: zoneId, - }; - } catch (e: any) { - if (e?.code === 'ResourceInUse.DuplicateName') { - this.logger.info('域名解析已存在,无需重复添加:', fullRecord, value); - return await this.findRecord({ - ...options, - zoneId, - }); - } - throw e; - } + return { + RecordId: ret.RecordId, + ZoneId: zoneId, + }; + } catch (e: any) { + if (e?.code === "ResourceInUse.DuplicateName") { + this.logger.info("域名解析已存在,无需重复添加:", fullRecord, value); + return await this.findRecord({ + ...options, + zoneId, + }); + } + throw e; + } + } + + async findRecord(options: CreateRecordOptions & { zoneId: string }): Promise { + const { zoneId } = options; + const params = { + ZoneId: zoneId, + Filters: [ + { + Name: "name", + Values: [options.fullRecord], + }, + { + Name: "content", + Values: [options.value], + }, + { + Name: "type", + Values: [options.type], + }, + ], + }; + const ret = await this.client.DescribeRecordFilterList(params); + if (ret.DnsRecords && ret.DnsRecords.length > 0) { + this.logger.info("已存在解析记录:", ret.DnsRecords); + return ret.DnsRecords[0]; + } + return {}; + } + + async removeRecord(options: RemoveRecordOptions) { + const { fullRecord, value } = options.recordReq; + const record = options.recordRes; + if (!record) { + this.logger.info("解析记录recordId为空,不执行删除", fullRecord, value); } - async findRecord(options: CreateRecordOptions & { zoneId: string }): Promise { + const params = { + ZoneId: record.ZoneId, + RecordIds: [record.RecordId], + }; - const { zoneId } = options; - const params = { - "ZoneId": zoneId, - "Filters": [ - { - "Name": "name", - "Values": [ - options.fullRecord - ] - }, - { - "Name": "content", - "Values": [ - options.value - ] - }, - { - "Name": "type", - "Values": [ - options.type - ] - } - ] - }; - const ret = await this.client.DescribeRecordFilterList(params); - if (ret.DnsRecords && ret.DnsRecords.length > 0) { - this.logger.info('已存在解析记录:', ret.DnsRecords); - return ret.DnsRecords[0]; - } - return {}; - } - - async removeRecord(options: RemoveRecordOptions) { - const { fullRecord, value } = options.recordReq; - const record = options.recordRes; - if (!record) { - this.logger.info('解析记录recordId为空,不执行删除', fullRecord, value); - } - - const params = { - "ZoneId": record.ZoneId, - "RecordIds": [ - record.RecordId - ] - }; - - const ret = await this.client.DeleteDnsRecords(params); - this.logger.info('删除域名解析成功:', fullRecord, value); - return ret; - } + const ret = await this.client.DeleteDnsRecords(params); + this.logger.info("删除域名解析成功:", fullRecord, value); + return ret; + } } new TencentEoDnsProvider(); diff --git a/packages/ui/certd-server/src/plugins/plugin-tencent/index.ts b/packages/ui/certd-server/src/plugins/plugin-tencent/index.ts index 6f484ab7b..ef88c7587 100644 --- a/packages/ui/certd-server/src/plugins/plugin-tencent/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-tencent/index.ts @@ -1,3 +1,3 @@ -export * from './access/index.js'; -export * from './plugin/index.js'; -export * from './dns-provider/index.js'; +export * from "./access/index.js"; +export * from "./plugin/index.js"; +export * from "./dns-provider/index.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-tencent/plugin/delete-expiring-cert/index.ts b/packages/ui/certd-server/src/plugins/plugin-tencent/plugin/delete-expiring-cert/index.ts index f1b1753c8..25570003b 100644 --- a/packages/ui/certd-server/src/plugins/plugin-tencent/plugin/delete-expiring-cert/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-tencent/plugin/delete-expiring-cert/index.ts @@ -1,15 +1,15 @@ -import { IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from '@certd/pipeline'; +import { IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; import { AbstractPlusTaskPlugin } from "@certd/plugin-plus"; -import dayjs from 'dayjs'; -import { remove } from 'lodash-es'; -import { TencentAccess, TencentSslClient } from '../../../plugin-lib/tencent/index.js'; +import dayjs from "dayjs"; +import { remove } from "lodash-es"; +import { TencentAccess, TencentSslClient } from "../../../plugin-lib/tencent/index.js"; @IsTaskPlugin({ - name: 'TencentDeleteExpiringCert', - title: '腾讯云-删除即将过期证书', - icon: 'svg:icon-tencentcloud', + name: "TencentDeleteExpiringCert", + title: "腾讯云-删除即将过期证书", + icon: "svg:icon-tencentcloud", group: pluginGroups.tencent.key, - desc: '仅删除未使用的证书', + desc: "仅删除未使用的证书", default: { strategy: { runStrategy: RunStrategy.AlwaysRun, @@ -19,58 +19,57 @@ import { TencentAccess, TencentSslClient } from '../../../plugin-lib/tencent/ind }) export class TencentDeleteExpiringCert extends AbstractPlusTaskPlugin { @TaskInput({ - title: 'Access提供者', - helper: 'access 授权', + title: "Access提供者", + helper: "access 授权", component: { - name: 'access-selector', - type: 'tencent', + name: "access-selector", + type: "tencent", }, required: true, }) accessId!: string; @TaskInput({ - title: '关键字筛选', - helper: '仅匹配ID、备注名称、域名包含关键字的证书,可以不填', + title: "关键字筛选", + helper: "仅匹配ID、备注名称、域名包含关键字的证书,可以不填", required: false, component: { - name: 'a-input', + name: "a-input", }, }) searchKey!: string; @TaskInput({ - title: '最大删除数量', - helper: '单次运行最大删除数量', + title: "最大删除数量", + helper: "单次运行最大删除数量", value: 100, component: { - name: 'a-input-number', - vModel: 'value', + name: "a-input-number", + vModel: "value", }, required: true, }) maxCount!: number; @TaskInput({ - title: '即将过期天数', - helper: - '仅删除有效期小于此天数的证书', + title: "即将过期天数", + helper: "仅删除有效期小于此天数的证书", value: 18, component: { - name: 'a-input-number', - vModel: 'value', + name: "a-input-number", + vModel: "value", }, required: true, }) expiringDays!: number; @TaskInput({ - title: '检查超时时间', - helper: '检查删除任务结果超时时间,单位分钟', + title: "检查超时时间", + helper: "检查删除任务结果超时时间,单位分钟", value: 10, component: { - name: 'a-input-number', - vModel: 'value', + name: "a-input-number", + vModel: "value", }, required: true, }) @@ -88,18 +87,18 @@ export class TencentDeleteExpiringCert extends AbstractPlusTaskPlugin { const params = { Limit: this.maxCount ?? 100, SearchKey: this.searchKey, - ExpirationSort: 'ASC', - FilterSource: 'upload', + ExpirationSort: "ASC", + FilterSource: "upload", // FilterExpiring: 1, }; const res = await sslClient.DescribeCertificates(params); let certificates = res?.Certificates; if (!certificates && certificates.length === 0) { - this.logger.info('没有找到证书'); + this.logger.info("没有找到证书"); return; } - const lastDay = dayjs().add(this.expiringDays, 'day'); + const lastDay = dayjs().add(this.expiringDays, "day"); certificates = certificates.filter((item: any) => { const endTime = item.CertEndTime; return dayjs(endTime).isBefore(lastDay); @@ -109,19 +108,19 @@ export class TencentDeleteExpiringCert extends AbstractPlusTaskPlugin { } this.logger.info(`即将过期的证书数量:${certificates.length}`); if (certificates.length === 0) { - this.logger.info('没有即将过期的证书, 无需删除'); + this.logger.info("没有即将过期的证书, 无需删除"); return; } const certIds = certificates.map((cert: any) => cert.CertificateId); - const deleteRes = await sslClient.doRequest('DeleteCertificates', { + const deleteRes = await sslClient.doRequest("DeleteCertificates", { CertificateIds: certIds, IsSync: true, }); - this.logger.info('删除任务已提交: ', JSON.stringify(deleteRes)); + this.logger.info("删除任务已提交: ", JSON.stringify(deleteRes)); const ids = deleteRes?.CertTaskIds; if (!ids && !ids.length) { - this.logger.error('没有找到任务ID'); + this.logger.error("没有找到任务ID"); return; } const taskIds = ids.map((id: any) => id.TaskId); @@ -139,12 +138,12 @@ export class TencentDeleteExpiringCert extends AbstractPlusTaskPlugin { while (Date.now() < startTime + this.checkTimeout * 60 * 1000) { this.checkSignal(); - const taskResultRes = await sslClient.doRequest('DescribeDeleteCertificatesTaskResult', { + const taskResultRes = await sslClient.doRequest("DescribeDeleteCertificatesTaskResult", { TaskIds: taskIds, }); const result = taskResultRes.DeleteTaskResult; if (!result || result.length === 0) { - this.logger.info('暂未获取到有效的任务结果'); + this.logger.info("暂未获取到有效的任务结果"); continue; } for (const item of result) { @@ -158,23 +157,23 @@ export class TencentDeleteExpiringCert extends AbstractPlusTaskPlugin { this.logger.info(`任务${item.TaskId}<${item.CertId}>: 进行中`); } else if (status === 1) { this.logger.info(`任务${item.TaskId}<${item.CertId}>: 成功`); - results[item.TaskId] = '成功'; + results[item.TaskId] = "成功"; statusCount.success++; } else if (status === 2) { this.logger.error(`任务${item.TaskId}<${item.CertId}>: 失败`); - results[item.TaskId] = '失败'; + results[item.TaskId] = "失败"; statusCount.failed++; } else if (status === 3) { this.logger.error(`任务${item.TaskId}<${item.CertId}>: 未授权服务角色导致任务失败`); - results[item.TaskId] = '未授权服务角色导致任务失败'; + results[item.TaskId] = "未授权服务角色导致任务失败"; statusCount.unauthorized++; } else if (status === 4) { this.logger.error(`任务${item.TaskId}<${item.CertId}>: 有未解绑的云资源导致任务失败`); - results[item.TaskId] = '有未解绑的云资源导致任务失败'; + results[item.TaskId] = "有未解绑的云资源导致任务失败"; statusCount.unbind++; } else if (status === 5) { this.logger.error(`任务${item.TaskId}<${item.CertId}>: 查询关联云资源超时导致任务失败`); - results[item.TaskId] = '查询关联云资源超时导致任务失败'; + results[item.TaskId] = "查询关联云资源超时导致任务失败"; statusCount.timeout++; } else { this.logger.info(`任务${item.TaskId}<${item.CertId}>: 未知状态:${status}`); @@ -186,17 +185,17 @@ export class TencentDeleteExpiringCert extends AbstractPlusTaskPlugin { `任务总数:${total}, 进行中:${taskIds.length}, 成功:${statusCount.success}, 未授权服务角色导致失败:${statusCount.unauthorized}, 未解绑关联资源失败:${statusCount.unbind}, 查询关联资源超时:${statusCount.timeout},未知原因失败:${statusCount.failed}` ); if (taskIds.length === 0) { - this.logger.info('任务已全部完成'); + this.logger.info("任务已全部完成"); if (statusCount.unauthorized > 0) { - throw new Error('有未授权服务角色导致任务失败,需给Access授权服务角色SSL_QCSLinkedRoleInReplaceLoadCertificate'); + throw new Error("有未授权服务角色导致任务失败,需给Access授权服务角色SSL_QCSLinkedRoleInReplaceLoadCertificate"); } return; } await this.ctx.utils.sleep(10000); } - this.logger.error('检查任务结果超时', JSON.stringify(results)); + this.logger.error("检查任务结果超时", JSON.stringify(results)); } } diff --git a/packages/ui/certd-server/src/plugins/plugin-tencent/plugin/deploy-to-all/index.ts b/packages/ui/certd-server/src/plugins/plugin-tencent/plugin/deploy-to-all/index.ts index f4d13c931..e3d603c30 100644 --- a/packages/ui/certd-server/src/plugins/plugin-tencent/plugin/deploy-to-all/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-tencent/plugin/deploy-to-all/index.ts @@ -1,14 +1,14 @@ -import {AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput} from '@certd/pipeline'; +import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; import { CertApplyPluginNames, CertInfo } from "@certd/plugin-cert"; -import { TencentSslClient } from '../../../plugin-lib/tencent/index.js'; +import { TencentSslClient } from "../../../plugin-lib/tencent/index.js"; @IsTaskPlugin({ - name: 'DeployCertToTencentAll', - title: '腾讯云-部署证书到任意云资源', + name: "DeployCertToTencentAll", + title: "腾讯云-部署证书到任意云资源", needPlus: false, - icon: 'svg:icon-tencentcloud', + icon: "svg:icon-tencentcloud", group: pluginGroups.tencent.key, - desc: '支持负载均衡、CDN、DDoS、直播、点播、Web应用防火墙、API网关、TEO、容器服务、对象存储、轻应用服务器、云原生微服务、云开发', + desc: "支持负载均衡、CDN、DDoS、直播、点播、Web应用防火墙、API网关、TEO、容器服务、对象存储、轻应用服务器、云原生微服务、云开发", default: { strategy: { runStrategy: RunStrategy.SkipWhenSucceed, @@ -20,35 +20,32 @@ export class DeployCertToTencentAll extends AbstractTaskPlugin { * AccessProvider的key,或者一个包含access的具体的对象 */ @TaskInput({ - title: 'Access授权', - helper: 'access授权', + title: "Access授权", + helper: "access授权", component: { - name: 'access-selector', - type: 'tencent', + name: "access-selector", + type: "tencent", }, required: true, }) accessId!: string; @TaskInput({ - title: '证书', + title: "证书", helper: '请选择"证书申请任务"或“上传证书到腾讯云”前置任务的输出', component: { - name: 'output-selector', - from: [...CertApplyPluginNames,'UploadCertToTencent'], + name: "output-selector", + from: [...CertApplyPluginNames, "UploadCertToTencent"], }, required: true, }) tencentCertId!: string | CertInfo; - - - @TaskInput({ - title: '资源类型', + title: "资源类型", component: { - name: 'a-select', - vModel: 'value', + name: "a-select", + vModel: "value", allowClear: true, //- clb // - cdn @@ -64,47 +61,46 @@ export class DeployCertToTencentAll extends AbstractTaskPlugin { // - tse // - tcb options: [ - { value: 'clb',label: '负载均衡'}, - { value: 'cdn',label: 'CDN'}, - { value: 'ddos',label: 'DDoS'}, - { value: 'live',label: '直播'}, - { value: 'vod',label: '点播'}, - { value: 'waf',label: 'Web应用防火墙'}, - { value: 'apigateway',label: 'API网关'}, - { value: 'teo',label: 'TEO'}, - { value: 'tke',label: '容器服务'}, - { value: 'cos',label: '对象存储'}, - { value: 'lighthouse',label: '轻应用服务器'}, - { value: 'tse',label: '云原生微服务'}, - { value: 'tcb',label: '云开发'}, - ] + { value: "clb", label: "负载均衡" }, + { value: "cdn", label: "CDN" }, + { value: "ddos", label: "DDoS" }, + { value: "live", label: "直播" }, + { value: "vod", label: "点播" }, + { value: "waf", label: "Web应用防火墙" }, + { value: "apigateway", label: "API网关" }, + { value: "teo", label: "TEO" }, + { value: "tke", label: "容器服务" }, + { value: "cos", label: "对象存储" }, + { value: "lighthouse", label: "轻应用服务器" }, + { value: "tse", label: "云原生微服务" }, + { value: "tcb", label: "云开发" }, + ], }, - helper: '', + helper: "", required: true, }) resourceType!: string; @TaskInput({ - title: 'Region', + title: "Region", component: { - name: 'a-input', - vModel: 'value', + name: "a-input", + vModel: "value", allowClear: true, }, - helper: '当云资源类型传入clb、waf、apigateway、cos、lighthouse、tke、tse、tcb 时,公共参数Region必传。[参考文档](https://cloud.tencent.com/document/product/400/91667)', + helper: "当云资源类型传入clb、waf、apigateway、cos、lighthouse、tke、tse、tcb 时,公共参数Region必传。[参考文档](https://cloud.tencent.com/document/product/400/91667)", }) region!: string; - @TaskInput({ - title: '云资源实例Id列表', + title: "云资源实例Id列表", component: { - name: 'a-select', - vModel: 'value', + name: "a-select", + vModel: "value", open: false, - mode: 'tags', + mode: "tags", }, - helper: '[参考文档](https://cloud.tencent.com/document/product/400/91667)', + helper: "[参考文档](https://cloud.tencent.com/document/product/400/91667)", }) instanceIdList!: string[]; @@ -112,7 +108,7 @@ export class DeployCertToTencentAll extends AbstractTaskPlugin { async execute(): Promise { const access = await this.getAccess(this.accessId); - const sdk = await import('tencentcloud-sdk-nodejs/tencentcloud/services/ssl/v20191205/index.js'); + const sdk = await import("tencentcloud-sdk-nodejs/tencentcloud/services/ssl/v20191205/index.js"); const Client = sdk.v20191205.Client; const client = new Client({ credential: { @@ -127,31 +123,31 @@ export class DeployCertToTencentAll extends AbstractTaskPlugin { }, }); - let certId:string = null - if (typeof this.tencentCertId === 'string') { + let certId: string = null; + if (typeof this.tencentCertId === "string") { certId = this.tencentCertId as string; - } else if (this.tencentCertId && typeof this.tencentCertId === 'object') { + } else if (this.tencentCertId && typeof this.tencentCertId === "object") { certId = await this.uploadToTencent(access, this.tencentCertId as CertInfo); } else { - throw new Error('无效的证书输入类型'); + throw new Error("无效的证书输入类型"); } const params = { CertificateId: certId, ResourceType: this.resourceType, InstanceIdList: this.instanceIdList, - IsCache:0, + IsCache: 0, }; const res = await client.DeployCertificateInstance(params); this.checkRet(res); - this.logger.info('部署成功,等待5s:',JSON.stringify(res)); + this.logger.info("部署成功,等待5s:", JSON.stringify(res)); await this.ctx.utils.sleep(5000); } checkRet(ret: any) { if (!ret || ret.Error) { - throw new Error('执行失败:' + ret.Error.Code + ',' + ret.Error.Message); + throw new Error("执行失败:" + ret.Error.Code + "," + ret.Error.Message); } } @@ -161,8 +157,8 @@ export class DeployCertToTencentAll extends AbstractTaskPlugin { logger: this.logger, }); - return await sslClient.uploadToTencent({ - certName: this.appendTimeSuffix('certd'), + return await sslClient.uploadToTencent({ + certName: this.appendTimeSuffix("certd"), cert: cert, }); } diff --git a/packages/ui/certd-server/src/plugins/plugin-tencent/plugin/deploy-to-cdn-v2/index.ts b/packages/ui/certd-server/src/plugins/plugin-tencent/plugin/deploy-to-cdn-v2/index.ts index 4f972b7a7..3ae9763f1 100644 --- a/packages/ui/certd-server/src/plugins/plugin-tencent/plugin/deploy-to-cdn-v2/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-tencent/plugin/deploy-to-cdn-v2/index.ts @@ -1,14 +1,14 @@ -import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from '@certd/pipeline'; -import { CertInfo ,CertReader} from '@certd/plugin-cert'; +import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; +import { CertInfo, CertReader } from "@certd/plugin-cert"; import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from "@certd/plugin-lib"; -import { TencentAccess, TencentSslClient } from '../../../plugin-lib/tencent/index.js'; -import { CertApplyPluginNames} from '@certd/plugin-cert'; +import { TencentAccess, TencentSslClient } from "../../../plugin-lib/tencent/index.js"; +import { CertApplyPluginNames } from "@certd/plugin-cert"; @IsTaskPlugin({ - name: 'TencentDeployCertToCDNv2', - title: '腾讯云-部署到CDN-v2', - icon: 'svg:icon-tencentcloud', + name: "TencentDeployCertToCDNv2", + title: "腾讯云-部署到CDN-v2", + icon: "svg:icon-tencentcloud", group: pluginGroups.tencent.key, - desc: '推荐使用,支持CDN域名以及COS加速域名', + desc: "推荐使用,支持CDN域名以及COS加速域名", default: { strategy: { runStrategy: RunStrategy.SkipWhenSucceed, @@ -16,13 +16,12 @@ import { CertApplyPluginNames} from '@certd/plugin-cert'; }, }) export class TencentDeployCertToCDNv2 extends AbstractTaskPlugin { - @TaskInput({ - title: '域名证书', - helper: '请选择前置任务输出的域名证书,或者选择前置任务“上传证书到腾讯云”任务的证书ID', + title: "域名证书", + helper: "请选择前置任务输出的域名证书,或者选择前置任务“上传证书到腾讯云”任务的证书ID", component: { - name: 'output-selector', - from: [...CertApplyPluginNames, 'UploadCertToTencent'], + name: "output-selector", + from: [...CertApplyPluginNames, "UploadCertToTencent"], }, required: true, }) @@ -32,31 +31,28 @@ export class TencentDeployCertToCDNv2 extends AbstractTaskPlugin { certDomains!: string[]; @TaskInput({ - title: 'Access提供者', - helper: 'access 授权', + title: "Access提供者", + helper: "access 授权", component: { - name: 'access-selector', - type: 'tencent', + name: "access-selector", + type: "tencent", }, required: true, }) accessId!: string; - @TaskInput( createRemoteSelectInputDefine({ - title: 'CDN域名', - helper: '请选择域名或输入域名', - typeName: 'TencentDeployCertToCDNv2', + title: "CDN域名", + helper: "请选择域名或输入域名", + typeName: "TencentDeployCertToCDNv2", action: TencentDeployCertToCDNv2.prototype.onGetDomainList.name, }) ) domains!: string | string[]; - async onInstance() {} - async execute(): Promise { const access = await this.getAccess(this.accessId); const sslClient = new TencentSslClient({ @@ -65,7 +61,7 @@ export class TencentDeployCertToCDNv2 extends AbstractTaskPlugin { }); let tencentCertId = this.cert as string; - if (typeof this.cert !== 'string') { + if (typeof this.cert !== "string") { const certReader = new CertReader(this.cert); tencentCertId = await sslClient.uploadToTencent({ certName: certReader.buildCertName(), @@ -75,25 +71,25 @@ export class TencentDeployCertToCDNv2 extends AbstractTaskPlugin { const res = await sslClient.deployCertificateInstance({ CertificateId: tencentCertId, - ResourceType: 'cdn', + ResourceType: "cdn", Status: 1, InstanceIdList: this.domains, }); - await this.ctx.utils.sleep(3000) + await this.ctx.utils.sleep(3000); - this.logger.info('部署成功', res); + this.logger.info("部署成功", res); } checkRet(ret: any) { if (!ret || ret.Error) { - throw new Error('执行失败:' + ret.Error.Code + ',' + ret.Error.Message); + throw new Error("执行失败:" + ret.Error.Code + "," + ret.Error.Message); } } async getCdnClient() { const accessProvider = await this.getAccess(this.accessId); - const sdk = await import('tencentcloud-sdk-nodejs/tencentcloud/services/cdn/v20180606/index.js'); + const sdk = await import("tencentcloud-sdk-nodejs/tencentcloud/services/cdn/v20180606/index.js"); const CdnClient = sdk.v20180606.Client; const clientConfig = { @@ -101,7 +97,7 @@ export class TencentDeployCertToCDNv2 extends AbstractTaskPlugin { secretId: accessProvider.secretId, secretKey: accessProvider.secretKey, }, - region: '', + region: "", profile: { httpProfile: { endpoint: `cdn.${accessProvider.intlDomain()}tencentcloudapi.com`, @@ -122,9 +118,9 @@ export class TencentDeployCertToCDNv2 extends AbstractTaskPlugin { return { label: item.Domain, value: item.Domain, - domain: item.Domain + domain: item.Domain, }; }); - return this.ctx.utils.options.buildGroupOptions(options, this.certDomains); + return this.ctx.utils.options.buildGroupOptions(options, this.certDomains); } } diff --git a/packages/ui/certd-server/src/plugins/plugin-tencent/plugin/deploy-to-cdn/index.ts b/packages/ui/certd-server/src/plugins/plugin-tencent/plugin/deploy-to-cdn/index.ts index 33d5b8c9e..67a13793f 100644 --- a/packages/ui/certd-server/src/plugins/plugin-tencent/plugin/deploy-to-cdn/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-tencent/plugin/deploy-to-cdn/index.ts @@ -1,13 +1,13 @@ -import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from '@certd/pipeline'; -import { CertInfo } from '@certd/plugin-cert'; -import { TencentAccess } from '../../../plugin-lib/tencent/index.js'; -import { CertApplyPluginNames} from '@certd/plugin-cert'; +import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; +import { CertInfo } from "@certd/plugin-cert"; +import { TencentAccess } from "../../../plugin-lib/tencent/index.js"; +import { CertApplyPluginNames } from "@certd/plugin-cert"; @IsTaskPlugin({ - name: 'DeployCertToTencentCDN', - title: '腾讯云-部署到CDN(废弃)', - icon: 'svg:icon-tencentcloud', + name: "DeployCertToTencentCDN", + title: "腾讯云-部署到CDN(废弃)", + icon: "svg:icon-tencentcloud", group: pluginGroups.tencent.key, - desc: '已废弃,请使用v2版', + desc: "已废弃,请使用v2版", default: { strategy: { runStrategy: RunStrategy.SkipWhenSucceed, @@ -16,10 +16,10 @@ import { CertApplyPluginNames} from '@certd/plugin-cert'; }) export class DeployToCdnPlugin extends AbstractTaskPlugin { @TaskInput({ - title: '域名证书', - helper: '请选择前置任务输出的域名证书', + title: "域名证书", + helper: "请选择前置任务输出的域名证书", component: { - name: 'output-selector', + name: "output-selector", from: [...CertApplyPluginNames], }, required: true, @@ -27,25 +27,25 @@ export class DeployToCdnPlugin extends AbstractTaskPlugin { cert!: CertInfo; @TaskInput({ - title: 'Access提供者', - helper: 'access 授权', + title: "Access提供者", + helper: "access 授权", component: { - name: 'access-selector', - type: 'tencent', + name: "access-selector", + type: "tencent", }, required: true, }) accessId!: string; @TaskInput({ - title: '证书名称', - helper: '证书上传后将以此参数作为名称前缀', + title: "证书名称", + helper: "证书上传后将以此参数作为名称前缀", }) certName!: string; @TaskInput({ - title: 'cdn加速域名', - rules: [{ required: true, message: '该项必填' }], + title: "cdn加速域名", + rules: [{ required: true, message: "该项必填" }], }) domainName!: string; @@ -63,7 +63,7 @@ export class DeployToCdnPlugin extends AbstractTaskPlugin { Client: any; async onInstance() { - const sdk = await import('tencentcloud-sdk-nodejs/tencentcloud/services/cdn/v20180606/index.js'); + const sdk = await import("tencentcloud-sdk-nodejs/tencentcloud/services/cdn/v20180606/index.js"); this.Client = sdk.v20180606.Client; } @@ -77,7 +77,7 @@ export class DeployToCdnPlugin extends AbstractTaskPlugin { secretId: accessProvider.secretId, secretKey: accessProvider.secretKey, }, - region: '', + region: "", profile: { httpProfile: { endpoint: `cdn.${accessProvider.intlDomain()}tencentcloudapi.com`, @@ -96,7 +96,7 @@ export class DeployToCdnPlugin extends AbstractTaskPlugin { buildParams() { return { Domain: this.domainName, - Route: 'Https.CertInfo', + Route: "Https.CertInfo", Value: JSON.stringify({ update: { Certificate: this.cert.crt, @@ -110,13 +110,13 @@ export class DeployToCdnPlugin extends AbstractTaskPlugin { const client = await this.getClient(); const ret = await client.ModifyDomainConfig(params); this.checkRet(ret); - this.logger.info('设置腾讯云CDN证书成功:', ret.RequestId); + this.logger.info("设置腾讯云CDN证书成功:", ret.RequestId); return ret.RequestId; } checkRet(ret: any) { if (!ret || ret.Error) { - throw new Error('执行失败:' + ret.Error.Code + ',' + ret.Error.Message); + throw new Error("执行失败:" + ret.Error.Code + "," + ret.Error.Message); } } } diff --git a/packages/ui/certd-server/src/plugins/plugin-tencent/plugin/deploy-to-clb/index.ts b/packages/ui/certd-server/src/plugins/plugin-tencent/plugin/deploy-to-clb/index.ts index 82fd2efee..933e0e558 100644 --- a/packages/ui/certd-server/src/plugins/plugin-tencent/plugin/deploy-to-clb/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-tencent/plugin/deploy-to-clb/index.ts @@ -1,13 +1,13 @@ -import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from '@certd/pipeline'; -import dayjs from 'dayjs'; -import { TencentAccess } from '../../../plugin-lib/tencent/index.js'; -import { CertApplyPluginNames, CertInfo } from '@certd/plugin-cert'; +import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; +import dayjs from "dayjs"; +import { TencentAccess } from "../../../plugin-lib/tencent/index.js"; +import { CertApplyPluginNames, CertInfo } from "@certd/plugin-cert"; @IsTaskPlugin({ - name: 'DeployCertToTencentCLB', - title: '腾讯云-部署到CLB', - icon: 'svg:icon-tencentcloud', + name: "DeployCertToTencentCLB", + title: "腾讯云-部署到CLB", + icon: "svg:icon-tencentcloud", group: pluginGroups.tencent.key, - desc: '暂时只支持单向认证证书,暂时只支持通用负载均衡', + desc: "暂时只支持单向认证证书,暂时只支持通用负载均衡", default: { strategy: { runStrategy: RunStrategy.SkipWhenSucceed, @@ -15,104 +15,98 @@ import { CertApplyPluginNames, CertInfo } from '@certd/plugin-cert'; }, }) export class DeployCertToTencentCLB extends AbstractTaskPlugin { - @TaskInput({ - title: '域名证书', - helper: '请选择前置任务输出的域名证书', + title: "域名证书", + helper: "请选择前置任务输出的域名证书", component: { - name: 'output-selector', - from: [...CertApplyPluginNames, 'UploadCertToTencent'], + name: "output-selector", + from: [...CertApplyPluginNames, "UploadCertToTencent"], }, required: true, }) cert!: string | CertInfo; - - @TaskInput({ - title: 'Access提供者', - helper: 'access授权', + title: "Access提供者", + helper: "access授权", component: { - name: 'access-selector', - type: 'tencent', + name: "access-selector", + type: "tencent", }, required: true, }) accessId!: string; @TaskInput({ - title: '大区', + title: "大区", component: { - name: 'a-auto-complete', - vModel: 'value', + name: "a-auto-complete", + vModel: "value", options: [ - { value: 'ap-guangzhou' }, - { value: 'ap-beijing' }, - { value: 'ap-chengdu' }, - { value: 'ap-chongqing' }, - { value: 'ap-hongkong' }, - { value: 'ap-jakarta' }, - { value: 'ap-mumbai' }, - { value: 'ap-nanjing' }, - { value: 'ap-seoul' }, - { value: 'ap-shanghai' }, - { value: 'ap-shanghai-fsi' }, - { value: 'ap-shenzhen-fsi' }, - { value: 'ap-singapore' }, - { value: 'ap-tokyo' }, - { value: 'eu-frankfurt' }, - { value: 'na-ashburn' }, - { value: 'na-siliconvalley' }, - { value: 'na-toronto' }, - { value: 'sa-saopaulo' }, - { value: 'ap-taipei' }, + { value: "ap-guangzhou" }, + { value: "ap-beijing" }, + { value: "ap-chengdu" }, + { value: "ap-chongqing" }, + { value: "ap-hongkong" }, + { value: "ap-jakarta" }, + { value: "ap-mumbai" }, + { value: "ap-nanjing" }, + { value: "ap-seoul" }, + { value: "ap-shanghai" }, + { value: "ap-shanghai-fsi" }, + { value: "ap-shenzhen-fsi" }, + { value: "ap-singapore" }, + { value: "ap-tokyo" }, + { value: "eu-frankfurt" }, + { value: "na-ashburn" }, + { value: "na-siliconvalley" }, + { value: "na-toronto" }, + { value: "sa-saopaulo" }, + { value: "ap-taipei" }, ], - helper: '如果列表中没有,您可以手动输入', + helper: "如果列表中没有,您可以手动输入", }, required: true, }) region!: string; - - @TaskInput({ - title: '负载均衡ID', + title: "负载均衡ID", required: true, }) loadBalancerId!: string; @TaskInput({ - title: '监听器ID', + title: "监听器ID", required: true, }) listenerId!: string; @TaskInput({ - title: '域名', + title: "域名", required: false, component: { - name: 'a-select', - vModel: 'value', + name: "a-select", + vModel: "value", open: false, - mode: 'tags', + mode: "tags", }, - helper: '如果开启了sni,则此项必须填写,未开启,则不要填写', + helper: "如果开启了sni,则此项必须填写,未开启,则不要填写", }) domain!: string | string[]; @TaskInput({ - title: '证书名称前缀', + title: "证书名称前缀", }) certName!: string; - client: any; async onInstance() { this.client = await this.getClient(); } async getClient() { - const sdk = await import('tencentcloud-sdk-nodejs/tencentcloud/services/clb/v20180317/index.js'); + const sdk = await import("tencentcloud-sdk-nodejs/tencentcloud/services/clb/v20180317/index.js"); const ClbClient = sdk.v20180317.Client; const accessProvider = (await this.getAccess(this.accessId)) as TencentAccess; @@ -204,7 +198,7 @@ export class DeployCertToTencentCLB extends AbstractTaskPlugin { const params = this.buildProps(); const ret = await client.ModifyListener(params); this.checkRet(ret); - this.logger.info('设置腾讯云CLB证书成功:', ret.RequestId, '->loadBalancerId:', this.loadBalancerId, 'listenerId', this.listenerId); + this.logger.info("设置腾讯云CLB证书成功:", ret.RequestId, "->loadBalancerId:", this.loadBalancerId, "listenerId", this.listenerId); return ret; } @@ -214,9 +208,7 @@ export class DeployCertToTencentCLB extends AbstractTaskPlugin { params.Domain = domain; const ret = await client.ModifyDomainAttributes(params); this.checkRet(ret); - this.logger.info( - `[${domain}] 设置腾讯云CLB证书(sni)任务已提交:taskId:${ret.RequestId},loadBalancerId:${this.loadBalancerId},listenerId:${this.listenerId}` - ); + this.logger.info(`[${domain}] 设置腾讯云CLB证书(sni)任务已提交:taskId:${ret.RequestId},loadBalancerId:${this.loadBalancerId},listenerId:${this.listenerId}`); const requestId = ret.RequestId; while (true) { @@ -236,17 +228,17 @@ export class DeployCertToTencentCLB extends AbstractTaskPlugin { } appendTimeSuffix(name: string) { if (name == null) { - name = 'certd'; + name = "certd"; } - return name + '-' + dayjs().format('YYYYMMDD-HHmmss'); + return name + "-" + dayjs().format("YYYYMMDD-HHmmss"); } buildProps() { const certId = this.cert as string; const certInfo = this.cert as CertInfo; - if (typeof this.cert === 'string') { + if (typeof this.cert === "string") { return { Certificate: { - SSLMode: 'UNIDIRECTIONAL', // 单向认证 + SSLMode: "UNIDIRECTIONAL", // 单向认证 CertId: certId, }, LoadBalancerId: this.loadBalancerId, @@ -255,7 +247,7 @@ export class DeployCertToTencentCLB extends AbstractTaskPlugin { } return { Certificate: { - SSLMode: 'UNIDIRECTIONAL', // 单向认证 + SSLMode: "UNIDIRECTIONAL", // 单向认证 CertName: this.appendTimeSuffix(this.certName || "certd"), CertKey: certInfo.key, CertContent: certInfo.crt, @@ -268,7 +260,7 @@ export class DeployCertToTencentCLB extends AbstractTaskPlugin { async getCLBList(client: any) { const params = { Limit: 100, // 最大暂时只支持100个,暂时没做翻页 - OrderBy: 'CreateTime', + OrderBy: "CreateTime", OrderType: 0, // ...this.DescribeLoadBalancers, }; @@ -281,7 +273,7 @@ export class DeployCertToTencentCLB extends AbstractTaskPlugin { // HTTPS const params = { LoadBalancerId: balancerId, - Protocol: 'HTTPS', + Protocol: "HTTPS", ListenerIds: listenerIds, }; const ret = await client.DescribeListeners(params); @@ -291,7 +283,7 @@ export class DeployCertToTencentCLB extends AbstractTaskPlugin { checkRet(ret: any) { if (!ret || ret.Error) { - throw new Error('执行失败:' + ret.Error.Code + ',' + ret.Error.Message); + throw new Error("执行失败:" + ret.Error.Code + "," + ret.Error.Message); } } } diff --git a/packages/ui/certd-server/src/plugins/plugin-tencent/plugin/deploy-to-cos/index.ts b/packages/ui/certd-server/src/plugins/plugin-tencent/plugin/deploy-to-cos/index.ts index 2480d5960..9321a7379 100644 --- a/packages/ui/certd-server/src/plugins/plugin-tencent/plugin/deploy-to-cos/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-tencent/plugin/deploy-to-cos/index.ts @@ -1,15 +1,15 @@ -import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from '@certd/pipeline'; -import { CertInfo } from '@certd/plugin-cert'; -import { createRemoteSelectInputDefine } from '@certd/plugin-lib'; -import { TencentSslClient } from '../../../plugin-lib/tencent/index.js'; -import { CertApplyPluginNames} from '@certd/plugin-cert'; +import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; +import { CertInfo } from "@certd/plugin-cert"; +import { createRemoteSelectInputDefine } from "@certd/plugin-lib"; +import { TencentSslClient } from "../../../plugin-lib/tencent/index.js"; +import { CertApplyPluginNames } from "@certd/plugin-cert"; @IsTaskPlugin({ - name: 'DeployCertToTencentCosPlugin', - title: '腾讯云-部署证书到COS', + name: "DeployCertToTencentCosPlugin", + title: "腾讯云-部署证书到COS", needPlus: false, - icon: 'svg:icon-tencentcloud', + icon: "svg:icon-tencentcloud", group: pluginGroups.tencent.key, - desc: '部署到腾讯云COS源站域名证书,注意是源站域名,加速域名请使用腾讯云CDN v2插件【注意:很不稳定,需要重试很多次偶尔才能成功一次】', + desc: "部署到腾讯云COS源站域名证书,注意是源站域名,加速域名请使用腾讯云CDN v2插件【注意:很不稳定,需要重试很多次偶尔才能成功一次】", default: { strategy: { runStrategy: RunStrategy.SkipWhenSucceed, @@ -21,52 +21,52 @@ export class DeployCertToTencentCosPlugin extends AbstractTaskPlugin { * AccessProvider的id */ @TaskInput({ - title: 'Access授权', - helper: 'access授权', + title: "Access授权", + helper: "access授权", component: { - name: 'access-selector', - type: 'tencent', + name: "access-selector", + type: "tencent", }, required: true, }) accessId!: string; @TaskInput({ - title: '存储桶名称', - helper: '请输入存储桶名称', + title: "存储桶名称", + helper: "请输入存储桶名称", }) bucket!: string; @TaskInput({ - title: '所在地域', - helper: '存储桶所在地域', + title: "所在地域", + helper: "存储桶所在地域", component: { - name: 'a-auto-complete', - vModel: 'value', + name: "a-auto-complete", + vModel: "value", options: [ - { value: '', label: '--------中国大陆地区-------', disabled: true }, - { value: 'ap-beijing-1', label: '北京1区' }, - { value: 'ap-beijing', label: '北京' }, - { value: 'ap-nanjing', label: '南京' }, - { value: 'ap-shanghai', label: '上海' }, - { value: 'ap-guangzhou', label: '广州' }, - { value: 'ap-chengdu', label: '成都' }, - { value: 'ap-chongqing', label: '重庆' }, - { value: 'ap-shenzhen-fsi', label: '深圳金融' }, - { value: 'ap-shanghai-fsi', label: '上海金融' }, - { value: 'ap-beijing-fsi', label: '北京金融' }, - { value: '', label: '--------中国香港及境外-------', disabled: true }, - { value: 'ap-hongkong', label: '中国香港' }, - { value: 'ap-singapore', label: '新加坡' }, - { value: 'ap-mumbai', label: '孟买' }, - { value: 'ap-jakarta', label: '雅加达' }, - { value: 'ap-seoul', label: '首尔' }, - { value: 'ap-bangkok', label: '曼谷' }, - { value: 'ap-tokyo', label: '东京' }, - { value: 'na-siliconvalley', label: '硅谷' }, - { value: 'na-ashburn', label: '弗吉尼亚' }, - { value: 'sa-saopaulo', label: '圣保罗' }, - { value: 'eu-frankfurt', label: '法兰克福' }, + { value: "", label: "--------中国大陆地区-------", disabled: true }, + { value: "ap-beijing-1", label: "北京1区" }, + { value: "ap-beijing", label: "北京" }, + { value: "ap-nanjing", label: "南京" }, + { value: "ap-shanghai", label: "上海" }, + { value: "ap-guangzhou", label: "广州" }, + { value: "ap-chengdu", label: "成都" }, + { value: "ap-chongqing", label: "重庆" }, + { value: "ap-shenzhen-fsi", label: "深圳金融" }, + { value: "ap-shanghai-fsi", label: "上海金融" }, + { value: "ap-beijing-fsi", label: "北京金融" }, + { value: "", label: "--------中国香港及境外-------", disabled: true }, + { value: "ap-hongkong", label: "中国香港" }, + { value: "ap-singapore", label: "新加坡" }, + { value: "ap-mumbai", label: "孟买" }, + { value: "ap-jakarta", label: "雅加达" }, + { value: "ap-seoul", label: "首尔" }, + { value: "ap-bangkok", label: "曼谷" }, + { value: "ap-tokyo", label: "东京" }, + { value: "na-siliconvalley", label: "硅谷" }, + { value: "na-ashburn", label: "弗吉尼亚" }, + { value: "sa-saopaulo", label: "圣保罗" }, + { value: "eu-frankfurt", label: "法兰克福" }, ], }, }) @@ -77,21 +77,21 @@ export class DeployCertToTencentCosPlugin extends AbstractTaskPlugin { @TaskInput( createRemoteSelectInputDefine({ - title: 'COS域名', - helper: '请选择域名', - typeName: 'DeployCertToTencentCosPlugin', + title: "COS域名", + helper: "请选择域名", + typeName: "DeployCertToTencentCosPlugin", action: DeployCertToTencentCosPlugin.prototype.onGetDomainList.name, - watches: ['bucket', 'region'], + watches: ["bucket", "region"], }) ) domains!: string | string[]; @TaskInput({ - title: '域名证书', - helper: '请选择前置任务输出的域名证书,或者选择前置任务“上传证书到腾讯云”任务的证书ID', + title: "域名证书", + helper: "请选择前置任务输出的域名证书,或者选择前置任务“上传证书到腾讯云”任务的证书ID", component: { - name: 'output-selector', - from: [...CertApplyPluginNames, 'UploadCertToTencent'], + name: "output-selector", + from: [...CertApplyPluginNames, "UploadCertToTencent"], }, required: true, }) @@ -109,9 +109,9 @@ export class DeployCertToTencentCosPlugin extends AbstractTaskPlugin { }); let tencentCertId: string = this.cert as string; - if (typeof this.cert !== 'string') { + if (typeof this.cert !== "string") { tencentCertId = await client.uploadToTencent({ - certName: this.appendTimeSuffix('certd'), + certName: this.appendTimeSuffix("certd"), cert: this.cert, }); } @@ -119,7 +119,7 @@ export class DeployCertToTencentCosPlugin extends AbstractTaskPlugin { for (const domain of this.domains) { const params = { CertificateId: tencentCertId, - ResourceType: 'cos', + ResourceType: "cos", Status: 1, InstanceIdList: [`${this.region}#${this.bucket}#${domain}`], }; @@ -127,22 +127,22 @@ export class DeployCertToTencentCosPlugin extends AbstractTaskPlugin { const res = await client.deployCertificateInstance(params); this.logger.info(`域名${domain}部署成功:`, res); } - this.logger.info('部署完成'); + this.logger.info("部署完成"); } async onGetDomainList(data: any) { const access = await this.getAccess(this.accessId); - const cosv5 = await import('cos-nodejs-sdk-v5'); + const cosv5 = await import("cos-nodejs-sdk-v5"); const cos = new cosv5.default({ SecretId: access.secretId, SecretKey: access.secretKey, }); if (!this.bucket) { - throw new Error('存储桶名称不能为空'); + throw new Error("存储桶名称不能为空"); } if (!this.region) { - throw new Error('所在地域不能为空'); + throw new Error("所在地域不能为空"); } const res = await cos.getBucketDomain({ @@ -151,7 +151,7 @@ export class DeployCertToTencentCosPlugin extends AbstractTaskPlugin { Region: this.region, }); - this.ctx.logger.info('获取域名列表:', res); + this.ctx.logger.info("获取域名列表:", res); return res.DomainRule.map((item: any) => { return { diff --git a/packages/ui/certd-server/src/plugins/plugin-tencent/plugin/deploy-to-eo/index.ts b/packages/ui/certd-server/src/plugins/plugin-tencent/plugin/deploy-to-eo/index.ts index 25dfc3d1f..6aca80027 100644 --- a/packages/ui/certd-server/src/plugins/plugin-tencent/plugin/deploy-to-eo/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-tencent/plugin/deploy-to-eo/index.ts @@ -1,18 +1,15 @@ -import {AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput} from "@certd/pipeline"; -import { - createCertDomainGetterInputDefine, - createRemoteSelectInputDefine, -} from "@certd/plugin-lib"; +import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; +import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from "@certd/plugin-lib"; -import {CertApplyPluginNames, CertInfo, CertReader} from "@certd/plugin-cert"; +import { CertApplyPluginNames, CertInfo, CertReader } from "@certd/plugin-cert"; import { TencentAccess } from "../../../plugin-lib/tencent/access.js"; import { TencentSslClient } from "../../../plugin-lib/tencent/index.js"; @IsTaskPlugin({ - name: 'DeployCertToTencentEO', - title: '腾讯云-部署到腾讯云EO', - icon: 'svg:icon-tencentcloud', - desc: '腾讯云边缘安全加速平台EdgeOne(EO)', + name: "DeployCertToTencentEO", + title: "腾讯云-部署到腾讯云EO", + icon: "svg:icon-tencentcloud", + desc: "腾讯云边缘安全加速平台EdgeOne(EO)", group: pluginGroups.tencent.key, default: { strategy: { @@ -21,63 +18,60 @@ import { TencentSslClient } from "../../../plugin-lib/tencent/index.js"; }, }) export class DeployCertToTencentEO extends AbstractTaskPlugin { - @TaskInput({ - title: '域名证书', - helper: '请选择前置任务输出的域名证书,或者选择前置任务“上传证书到腾讯云”任务的证书ID', + title: "域名证书", + helper: "请选择前置任务输出的域名证书,或者选择前置任务“上传证书到腾讯云”任务的证书ID", component: { - name: 'output-selector', - from: [...CertApplyPluginNames, 'UploadCertToTencent'], + name: "output-selector", + from: [...CertApplyPluginNames, "UploadCertToTencent"], }, required: true, }) cert!: CertInfo | string; - @TaskInput(createCertDomainGetterInputDefine({ props: { required: false } })) certDomains!: string[]; @TaskInput({ - title: 'Access提供者', - helper: 'access 授权', + title: "Access提供者", + helper: "access 授权", component: { - name: 'access-selector', - type: 'tencent', + name: "access-selector", + type: "tencent", }, required: true, }) accessId!: string; - @TaskInput(createRemoteSelectInputDefine({ - title: '站点ID', - helper: '类似于zone-xxxx的字符串,在站点概览页面左上角,或者,站点列表页面站点名称下方', - action: DeployCertToTencentEO.prototype.onGetZoneList.name, - watches: ['certDomains', 'accessId'], - required: true, - component:{ - name:"remote-auto-complete" - } - })) + @TaskInput( + createRemoteSelectInputDefine({ + title: "站点ID", + helper: "类似于zone-xxxx的字符串,在站点概览页面左上角,或者,站点列表页面站点名称下方", + action: DeployCertToTencentEO.prototype.onGetZoneList.name, + watches: ["certDomains", "accessId"], + required: true, + component: { + name: "remote-auto-complete", + }, + }) + ) zoneId!: string; @TaskInput( createRemoteSelectInputDefine({ - title: '加速域名', - helper: '请选择域名或输入域名', + title: "加速域名", + helper: "请选择域名或输入域名", action: DeployCertToTencentEO.prototype.onGetDomainList.name, }) ) domainNames!: string[]; - @TaskInput({ - title: '证书名称', - helper: '证书上传后将以此参数作为名称前缀', + title: "证书名称", + helper: "证书上传后将以此参数作为名称前缀", }) certName!: string; - - // @TaskInput({ // title: "CDN接口", // helper: "CDN接口端点", @@ -91,25 +85,25 @@ export class DeployCertToTencentEO extends AbstractTaskPlugin { Client: any; async onInstance() { - const sdk = await import('tencentcloud-sdk-nodejs/tencentcloud/services/teo/v20220901/index.js'); + const sdk = await import("tencentcloud-sdk-nodejs/tencentcloud/services/teo/v20220901/index.js"); this.Client = sdk.v20220901.Client; } async execute(): Promise { - const accessProvider = await this.getAccess(this.accessId) + const accessProvider = await this.getAccess(this.accessId); const client = this.getClient(accessProvider); const sslClient = new TencentSslClient({ - access:accessProvider, + access: accessProvider, logger: this.logger, }); - if (this.cert == null){ - throw new Error('请选择域名证书'); + if (this.cert == null) { + throw new Error("请选择域名证书"); } let tencentCertId = this.cert as string; - if (typeof this.cert !== 'string') { + if (typeof this.cert !== "string") { const certReader = new CertReader(this.cert); tencentCertId = await sslClient.uploadToTencent({ certName: certReader.buildCertName(), @@ -117,17 +111,17 @@ export class DeployCertToTencentEO extends AbstractTaskPlugin { }); } - const params:any = { + const params: any = { ZoneId: this.zoneId, Hosts: this.domainNames, - Mode: 'sslcert', + Mode: "sslcert", ServerCertInfo: [ { CertId: tencentCertId, }, ], }; - this.logger.info('设置腾讯云EO证书参数:', JSON.stringify(params)); + this.logger.info("设置腾讯云EO证书参数:", JSON.stringify(params)); await this.doRequest(client, params); } @@ -141,7 +135,7 @@ export class DeployCertToTencentEO extends AbstractTaskPlugin { secretId: accessProvider.secretId, secretKey: accessProvider.secretKey, }, - region: '', + region: "", profile: { httpProfile: { endpoint, @@ -152,27 +146,22 @@ export class DeployCertToTencentEO extends AbstractTaskPlugin { return new TeoClient(clientConfig); } - async doRequest(client: any, params: any) { const ret = await client.ModifyHostsCertificate(params); this.checkRet(ret); - this.logger.info('设置腾讯云EO证书成功:', ret.RequestId); + this.logger.info("设置腾讯云EO证书成功:", ret.RequestId); return ret.RequestId; } checkRet(ret: any) { if (!ret || ret.Error) { - throw new Error('执行失败:' + ret.Error.Code + ',' + ret.Error.Message); + throw new Error("执行失败:" + ret.Error.Code + "," + ret.Error.Message); } } - - - - async onGetZoneList(data: any) { - if (!this.accessId){ - throw new Error('请选择授权'); + if (!this.accessId) { + throw new Error("请选择授权"); } const access: TencentAccess = await this.getAccess(this.accessId); const client = await this.getClient(access); @@ -193,8 +182,8 @@ export class DeployCertToTencentEO extends AbstractTaskPlugin { } async onGetDomainList(data: any) { - if (!this.accessId){ - throw new Error('请选择授权'); + if (!this.accessId) { + throw new Error("请选择授权"); } const access: TencentAccess = await this.getAccess(this.accessId); const client = await this.getClient(access); @@ -203,7 +192,7 @@ export class DeployCertToTencentEO extends AbstractTaskPlugin { ZoneId: this.zoneId, }); this.checkRet(res); - const list = res.AccelerationDomains + const list = res.AccelerationDomains; if (!list || list.length === 0) { return []; } @@ -211,10 +200,10 @@ export class DeployCertToTencentEO extends AbstractTaskPlugin { return { label: item.DomainName, value: item.DomainName, - domain: item.DomainName + domain: item.DomainName, }; }); - return this.ctx.utils.options.buildGroupOptions(options, this.certDomains); + return this.ctx.utils.options.buildGroupOptions(options, this.certDomains); } } diff --git a/packages/ui/certd-server/src/plugins/plugin-tencent/plugin/deploy-to-live/index.ts b/packages/ui/certd-server/src/plugins/plugin-tencent/plugin/deploy-to-live/index.ts index 0dc81142b..1adb85a52 100644 --- a/packages/ui/certd-server/src/plugins/plugin-tencent/plugin/deploy-to-live/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-tencent/plugin/deploy-to-live/index.ts @@ -5,10 +5,10 @@ import { TencentAccess } from "../../../plugin-lib/tencent/access.js"; import { TencentSslClient } from "../../../plugin-lib/tencent/index.js"; @IsTaskPlugin({ - name: 'TencentDeployCertToLive', - title: '腾讯云-部署到腾讯云直播', - icon: 'svg:icon-tencentcloud', - desc: 'https://console.cloud.tencent.com/live/', + name: "TencentDeployCertToLive", + title: "腾讯云-部署到腾讯云直播", + icon: "svg:icon-tencentcloud", + desc: "https://console.cloud.tencent.com/live/", group: pluginGroups.tencent.key, needPlus: false, default: { @@ -19,11 +19,11 @@ import { TencentSslClient } from "../../../plugin-lib/tencent/index.js"; }) export class TencentDeployCertToLive extends AbstractTaskPlugin { @TaskInput({ - title: 'Access提供者', - helper: 'access 授权', + title: "Access提供者", + helper: "access 授权", component: { - name: 'access-selector', - type: 'tencent', + name: "access-selector", + type: "tencent", }, required: true, }) @@ -31,20 +31,20 @@ export class TencentDeployCertToLive extends AbstractTaskPlugin { @TaskInput( createRemoteSelectInputDefine({ - title: '直播域名', - helper: '请选择域名或输入域名', - typeName: 'TencentDeployCertToLive', + title: "直播域名", + helper: "请选择域名或输入域名", + typeName: "TencentDeployCertToLive", action: TencentDeployCertToLive.prototype.onGetDomainList.name, }) ) domains!: string[]; @TaskInput({ - title: '域名证书', - helper: '请选择前置任务输出的域名证书,或者选择前置任务“上传证书到腾讯云”任务的证书ID', + title: "域名证书", + helper: "请选择前置任务输出的域名证书,或者选择前置任务“上传证书到腾讯云”任务的证书ID", component: { - name: 'output-selector', - from: [...CertApplyPluginNames, 'UploadCertToTencent'], + name: "output-selector", + from: [...CertApplyPluginNames, "UploadCertToTencent"], }, required: true, }) @@ -56,13 +56,13 @@ export class TencentDeployCertToLive extends AbstractTaskPlugin { const access = await this.getAccess(this.accessId); let tencentCertId = this.cert as string; - if (typeof this.cert !== 'string') { + if (typeof this.cert !== "string") { const sslClient = new TencentSslClient({ access, logger: this.logger, }); tencentCertId = await sslClient.uploadToTencent({ - certName: this.appendTimeSuffix('certd'), + certName: this.appendTimeSuffix("certd"), cert: this.cert, }); } @@ -81,18 +81,18 @@ export class TencentDeployCertToLive extends AbstractTaskPlugin { const res = await client.ModifyLiveDomainCertBindings(params); this.checkRet(res); - this.logger.info('部署完成', JSON.stringify(res)); + this.logger.info("部署完成", JSON.stringify(res)); } checkRet(ret: any) { if (!ret || ret.Error) { - throw new Error('执行失败:' + ret.Error.Code + ',' + ret.Error.Message); + throw new Error("执行失败:" + ret.Error.Code + "," + ret.Error.Message); } } async getLiveClient() { const accessProvider = await this.getAccess(this.accessId); - const sdk = await import('tencentcloud-sdk-nodejs/tencentcloud/services/live/v20180801/index.js'); + const sdk = await import("tencentcloud-sdk-nodejs/tencentcloud/services/live/v20180801/index.js"); const CssClient = sdk.v20180801.Client; const clientConfig = { @@ -100,7 +100,7 @@ export class TencentDeployCertToLive extends AbstractTaskPlugin { secretId: accessProvider.secretId, secretKey: accessProvider.secretKey, }, - region: '', + region: "", profile: { httpProfile: { endpoint: `live.${accessProvider.intlDomain()}tencentcloudapi.com`, diff --git a/packages/ui/certd-server/src/plugins/plugin-tencent/plugin/deploy-to-tke-ingress/index.ts b/packages/ui/certd-server/src/plugins/plugin-tencent/plugin/deploy-to-tke-ingress/index.ts index 950a01452..13ca15940 100644 --- a/packages/ui/certd-server/src/plugins/plugin-tencent/plugin/deploy-to-tke-ingress/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-tencent/plugin/deploy-to-tke-ingress/index.ts @@ -13,12 +13,11 @@ import yaml from "js-yaml"; desc: "修改TKE集群密钥配置,支持Opaque和TLS证书类型。注意:\n1. serverless集群请使用K8S部署插件;\n2. Opaque类型需要【上传到腾讯云】作为前置任务;\n3. ApiServer需要开通公网访问(或者certd可访问),实际上底层仍然是通过KubeClient进行部署", default: { strategy: { - runStrategy: RunStrategy.SkipWhenSucceed - } - } + runStrategy: RunStrategy.SkipWhenSucceed, + }, + }, }) export class DeployCertToTencentTKEIngressPlugin extends AbstractTaskPlugin { - @TaskInput({ title: "ingress证书类型", component: { @@ -26,11 +25,11 @@ export class DeployCertToTencentTKEIngressPlugin extends AbstractTaskPlugin { vModel: "value", options: [ { value: "nginx", label: "TLS证书格式(Nginx可用)" }, - { value: "qcloud",label: "Opaque格式(CLB可用,原qcloud)"} - ] + { value: "qcloud", label: "Opaque格式(CLB可用,原qcloud)" }, + ], }, helper: "clb将部署Opaque类型的证书,nginx类型将部署TLS证书格式", - required: true + required: true, }) ingressClass!: string; @@ -39,7 +38,7 @@ export class DeployCertToTencentTKEIngressPlugin extends AbstractTaskPlugin { helper: "请选择“上传证书到腾讯云”前置任务的输出", component: { name: "output-selector", - from: "UploadCertToTencent" + from: "UploadCertToTencent", }, mergeScript: ` return { @@ -48,17 +47,16 @@ export class DeployCertToTencentTKEIngressPlugin extends AbstractTaskPlugin { }) } `, - required: true + required: true, }) tencentCertId!: string; - @TaskInput({ title: "域名证书", helper: "请选择前置任务输出的域名证书", component: { name: "output-selector", - from: [...CertApplyPluginNames] + from: [...CertApplyPluginNames], }, mergeScript: ` return { @@ -67,13 +65,10 @@ export class DeployCertToTencentTKEIngressPlugin extends AbstractTaskPlugin { }) } `, - required: true + required: true, }) cert!: any; - - - /** * AccessProvider的key,或者一个包含access的具体的对象 */ @@ -82,14 +77,12 @@ export class DeployCertToTencentTKEIngressPlugin extends AbstractTaskPlugin { helper: "access授权", component: { name: "access-selector", - type: "tencent" + type: "tencent", }, - required: true + required: true, }) accessId!: string; - - @TaskInput({ title: "大区", value: "ap-guangzhou", required: true }) region!: string; @@ -97,7 +90,7 @@ export class DeployCertToTencentTKEIngressPlugin extends AbstractTaskPlugin { title: "集群ID", required: true, desc: "例如:cls-6lbj1vee", - request: true + request: true, }) clusterId!: string; @@ -112,8 +105,8 @@ export class DeployCertToTencentTKEIngressPlugin extends AbstractTaskPlugin { name: "a-select", vModel: "value", mode: "tags", - open: false - } + open: false, + }, }) secretName!: string | string[]; @@ -121,12 +114,11 @@ export class DeployCertToTencentTKEIngressPlugin extends AbstractTaskPlugin { title: "集群域名", helper: "ApiServer需要开通公网访问,填写`ApiServer公网IP:443`\n默认为:[clusterId].ccs.tencent-cloud.com,可能访问不通", component: { - placeholder: "xx.xxx.xx.xx:443" - } + placeholder: "xx.xxx.xx.xx:443", + }, }) clusterDomain!: string; - @TaskInput({ title: "ingress名称", required: false, @@ -135,12 +127,11 @@ export class DeployCertToTencentTKEIngressPlugin extends AbstractTaskPlugin { name: "a-select", vModel: "value", mode: "tags", - open: false - } + open: false, + }, }) ingressName!: string | string[]; - @TaskInput({ title: "忽略证书校验", required: false, @@ -148,9 +139,9 @@ export class DeployCertToTencentTKEIngressPlugin extends AbstractTaskPlugin { component: { name: "a-switch", vModel: "checked", - } + }, }) - skipTLSVerify!:boolean + skipTLSVerify!: boolean; @TaskInput({ title: "Secret自动创建", @@ -163,11 +154,9 @@ export class DeployCertToTencentTKEIngressPlugin extends AbstractTaskPlugin { }) createOnNotFound: boolean; - // @TaskInput({ title: "集群内网ip", helper: "如果开启了外网的话,无需设置" }) // clusterIp!: string; - K8sClient: any; async onInstance() { @@ -181,7 +170,6 @@ export class DeployCertToTencentTKEIngressPlugin extends AbstractTaskPlugin { const tkeClient = await this.getTkeClient(accessProvider, this.region); let kubeConfigStr = await this.getTkeKubeConfig(tkeClient, this.clusterId); - if (this.clusterDomain) { const kubeConfig = yaml.load(kubeConfigStr); kubeConfig.clusters[0].cluster.server = `https://${this.clusterDomain}`; @@ -212,7 +200,6 @@ export class DeployCertToTencentTKEIngressPlugin extends AbstractTaskPlugin { this.logger.info("正在重启ingress:", this.ingressName); await this.restartIngress({ k8sClient }); } - } async getTkeClient(accessProvider: any, region = "ap-guangzhou") { @@ -221,14 +208,14 @@ export class DeployCertToTencentTKEIngressPlugin extends AbstractTaskPlugin { const clientConfig = { credential: { secretId: accessProvider.secretId, - secretKey: accessProvider.secretKey + secretKey: accessProvider.secretKey, }, region, profile: { httpProfile: { - endpoint: `tke.${accessProvider.intlDomain()}tencentcloudapi.com` - } - } + endpoint: `tke.${accessProvider.intlDomain()}tencentcloudapi.com`, + }, + }, }; return new TkeClient(clientConfig); @@ -237,7 +224,7 @@ export class DeployCertToTencentTKEIngressPlugin extends AbstractTaskPlugin { async getTkeKubeConfig(client: any, clusterId: string) { // Depends on tencentcloud-sdk-nodejs version 4.0.3 or higher const params = { - ClusterId: clusterId + ClusterId: clusterId, }; const ret = await client.DescribeClusterKubeconfig(params); this.checkRet(ret); @@ -256,13 +243,13 @@ export class DeployCertToTencentTKEIngressPlugin extends AbstractTaskPlugin { const body = { data: { - qcloud_cert_id: certIdBase64 + qcloud_cert_id: certIdBase64, }, metadata: { labels: { - certd: this.appendTimeSuffix("certd") - } - } + certd: this.appendTimeSuffix("certd"), + }, + }, }; let secretNames: any = secretName; if (typeof secretName === "string") { @@ -272,7 +259,7 @@ export class DeployCertToTencentTKEIngressPlugin extends AbstractTaskPlugin { await options.k8sClient.patchSecret({ namespace, secretName: secret, - body + body, }); this.logger.info(`CertSecret已更新:${secret}`); } @@ -291,20 +278,20 @@ export class DeployCertToTencentTKEIngressPlugin extends AbstractTaskPlugin { const body = { data: { "tls.crt": crtBase64, - "tls.key": keyBase64 + "tls.key": keyBase64, }, metadata: { labels: { - certd: this.appendTimeSuffix("certd") - } - } + certd: this.appendTimeSuffix("certd"), + }, + }, }; let secretNames = secretName; if (typeof secretName === "string") { secretNames = [secretName]; } for (const secret of secretNames) { - await k8sClient.patchSecret({ namespace, secretName: secret, body , createOnNotFound: this.createOnNotFound}); + await k8sClient.patchSecret({ namespace, secretName: secret, body, createOnNotFound: this.createOnNotFound }); this.logger.info(`CertSecret已更新:${secret}`); } } @@ -316,9 +303,9 @@ export class DeployCertToTencentTKEIngressPlugin extends AbstractTaskPlugin { const body = { metadata: { labels: { - certd: this.appendTimeSuffix("certd") - } - } + certd: this.appendTimeSuffix("certd"), + }, + }, }; let ingressNames = this.ingressName || []; if (typeof ingressName === "string") { @@ -335,5 +322,4 @@ export class DeployCertToTencentTKEIngressPlugin extends AbstractTaskPlugin { throw new Error("执行失败:" + ret.Error.Code + "," + ret.Error.Message); } } - } diff --git a/packages/ui/certd-server/src/plugins/plugin-tencent/plugin/index.ts b/packages/ui/certd-server/src/plugins/plugin-tencent/plugin/index.ts index b8f9220da..4f8933540 100644 --- a/packages/ui/certd-server/src/plugins/plugin-tencent/plugin/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-tencent/plugin/index.ts @@ -1,12 +1,12 @@ -export * from './deploy-to-all/index.js'; -export * from './deploy-to-clb/index.js'; -export * from './deploy-to-cdn/index.js'; -export * from './deploy-to-cdn-v2/index.js'; -export * from './upload-to-tencent/index.js'; -export * from './deploy-to-cos/index.js'; -export * from './deploy-to-eo/index.js'; -export * from './delete-expiring-cert/index.js'; -export * from './deploy-to-tke-ingress/index.js'; -export * from './deploy-to-live/index.js'; -export * from './start-instances/index.js'; -export * from './refresh-cert/index.js'; +export * from "./deploy-to-all/index.js"; +export * from "./deploy-to-clb/index.js"; +export * from "./deploy-to-cdn/index.js"; +export * from "./deploy-to-cdn-v2/index.js"; +export * from "./upload-to-tencent/index.js"; +export * from "./deploy-to-cos/index.js"; +export * from "./deploy-to-eo/index.js"; +export * from "./delete-expiring-cert/index.js"; +export * from "./deploy-to-tke-ingress/index.js"; +export * from "./deploy-to-live/index.js"; +export * from "./start-instances/index.js"; +export * from "./refresh-cert/index.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-tencent/plugin/refresh-cert/index.ts b/packages/ui/certd-server/src/plugins/plugin-tencent/plugin/refresh-cert/index.ts index 6c55532e2..237ac19d8 100644 --- a/packages/ui/certd-server/src/plugins/plugin-tencent/plugin/refresh-cert/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-tencent/plugin/refresh-cert/index.ts @@ -1,12 +1,4 @@ -import { - AbstractTaskPlugin, - IsTaskPlugin, - Pager, - PageSearch, - pluginGroups, - RunStrategy, - TaskInput -} from "@certd/pipeline"; +import { AbstractTaskPlugin, IsTaskPlugin, Pager, PageSearch, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; import { CertApplyPluginNames, CertInfo } from "@certd/plugin-cert"; import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from "@certd/plugin-lib"; import { TencentAccess } from "../../../plugin-lib/tencent/access.js"; @@ -25,9 +17,9 @@ import { omit } from "lodash-es"; default: { //默认值配置照抄即可 strategy: { - runStrategy: RunStrategy.SkipWhenSucceed - } - } + runStrategy: RunStrategy.SkipWhenSucceed, + }, + }, }) //类名规范,跟上面插件名称(name)一致 export class TencentRefreshCert extends AbstractTaskPlugin { @@ -37,8 +29,8 @@ export class TencentRefreshCert extends AbstractTaskPlugin { helper: "请选择前置任务输出的域名证书", component: { name: "output-selector", - from: [...CertApplyPluginNames] - } + from: [...CertApplyPluginNames], + }, // required: true, // 必填 }) cert!: CertInfo; @@ -51,9 +43,9 @@ export class TencentRefreshCert extends AbstractTaskPlugin { title: "腾讯云授权", component: { name: "access-selector", - type: "tencent" //固定授权类型 + type: "tencent", //固定授权类型 }, - required: true //必填 + required: true, //必填 }) accessId!: string; // @@ -64,7 +56,7 @@ export class TencentRefreshCert extends AbstractTaskPlugin { helper: "要更新的证书id,如果这里没有,请先给手动绑定一次证书", action: TencentRefreshCert.prototype.onGetCertList.name, pager: false, - search: false + search: false, }) ) certList!: string[]; @@ -98,110 +90,109 @@ export class TencentRefreshCert extends AbstractTaskPlugin { // resourceTypes!: string[]; @TaskInput({ - title: '资源区域', - helper:"如果云资源类型区分区域,请选择区域,如果区域在选项中不存在,请手动输入(注意:当前仅支持CLB)", + title: "资源区域", + helper: "如果云资源类型区分区域,请选择区域,如果区域在选项中不存在,请手动输入(注意:当前仅支持CLB)", component: { - name: 'remote-tree-select', - vModel: 'value', + name: "remote-tree-select", + vModel: "value", action: TencentRefreshCert.prototype.onGetRegionsTree.name, pager: false, search: false, - watches: ['certList'], + watches: ["certList"], }, required: false, }) resourceTypesRegions!: string[]; //插件实例化时执行的方法 - async onInstance() { - } + async onInstance() {} //插件执行方法 async execute(): Promise { const access = await this.getAccess(this.accessId); const sslClient = new TencentSslClient({ - access:access, + access: access, logger: this.logger, }); // await access.createCert({cert:this.cert}) - let resourceTypes = [] - const resourceTypesRegions = [] - if(!this.resourceTypesRegions){ - this.resourceTypesRegions = [] + const resourceTypes = []; + const resourceTypesRegions = []; + if (!this.resourceTypesRegions) { + this.resourceTypesRegions = []; } for (const item of this.resourceTypesRegions) { - const [type,region] = item.split("_") - if (!resourceTypes.includes( type)){ - resourceTypes.push(type) + const [type, region] = item.split("_"); + if (!resourceTypes.includes(type)) { + resourceTypes.push(type); } - if (!region){ + if (!region) { continue; } - const resourceType = resourceTypesRegions.find(item => item.ResourceType == type) - if (!resourceType){ + const resourceType = resourceTypesRegions.find(item => item.ResourceType == type); + if (!resourceType) { resourceTypesRegions.push({ ResourceType: type, - Regions: [region] - }) - }else{ - resourceType.Regions.push(region) + Regions: [region], + }); + } else { + resourceType.Regions.push(region); } } // resourceTypes = ["clb"] //固定clb - const maxRetry = 10 + const maxRetry = 10; for (const certId of this.certList) { this.logger.info(`----------- 开始更新证书:${certId}`); - let deployRes = null + let deployRes = null; - let retryCount = 0 - while(true){ - if (retryCount>maxRetry){ + let retryCount = 0; + while (true) { + if (retryCount > maxRetry) { this.logger.error(`任务创建失败`); break; } - retryCount++ + retryCount++; const params = { - "OldCertificateId": certId, - "ResourceTypes": resourceTypes, - "CertificatePublicKey": "xxx", - "CertificatePrivateKey": "xxx", - "ResourceTypesRegions":resourceTypesRegions - } + OldCertificateId: certId, + ResourceTypes: resourceTypes, + CertificatePublicKey: "xxx", + CertificatePrivateKey: "xxx", + ResourceTypesRegions: resourceTypesRegions, + }; this.logger.info(`请求参数:${JSON.stringify(params)}`); - params.CertificatePublicKey = this.cert.crt - params.CertificatePrivateKey = this.cert.key + params.CertificatePublicKey = this.cert.crt; + params.CertificatePrivateKey = this.cert.key; deployRes = await sslClient.UploadUpdateCertificateInstance(params); - if (deployRes && deployRes.DeployRecordId>0){ + if (deployRes && deployRes.DeployRecordId > 0) { this.logger.info(`任务创建成功,开始检查结果:${JSON.stringify(deployRes)}`); break; - }else{ + } else { this.logger.info(`任务创建中,稍后查询:${JSON.stringify(deployRes)}`); } await this.ctx.utils.sleep(3000); } this.logger.info(`开始查询部署结果`); - retryCount=0 - while(true){ - if (retryCount>maxRetry){ + retryCount = 0; + while (true) { + if (retryCount > maxRetry) { this.logger.error(`任务结果检查失败`); break; } - retryCount++ + retryCount++; //查询部署状态 const deployStatus = await sslClient.DescribeHostUploadUpdateRecordDetail({ - "DeployRecordId":deployRes.DeployRecordId - }) - const details = deployStatus.DeployRecordDetail - let allSuccess = true + DeployRecordId: deployRes.DeployRecordId, + }); + const details = deployStatus.DeployRecordDetail; + let allSuccess = true; for (const item of details) { - this.logger.info(`查询结果:${JSON.stringify(omit(item,"RecordDetailList"))}`); + this.logger.info(`查询结果:${JSON.stringify(omit(item, "RecordDetailList"))}`); if (item.Status === 2) { - throw new Error(`任务失败:${JSON.stringify(item.RecordDetailList)}`) - }else if (item.Status !== 1) { + throw new Error(`任务失败:${JSON.stringify(item.RecordDetailList)}`); + } else if (item.Status !== 1) { //如果不是成功状态 - allSuccess = false + allSuccess = false; } } if (allSuccess) { @@ -211,11 +202,9 @@ export class TencentRefreshCert extends AbstractTaskPlugin { } this.logger.info(`----------- 更新证书${certId}成功`); } - } - async onGetRegionsTree(data: PageSearch = {}){ - + async onGetRegionsTree(data: PageSearch = {}) { const commonRegions = [ /** * 华南地区(广州) waf.ap-guangzhou.tencentcloudapi.com @@ -235,42 +224,42 @@ export class TencentRefreshCert extends AbstractTaskPlugin { * 南美地区(圣保罗) waf.sa-saopaulo.tencentcloudapi.com * 欧洲地区(法兰克福) waf.eu-frankfurt.tencentcloudapi.com */ - {value:"ap-guangzhou", label:"广州"}, - {value:"ap-shanghai", label:"上海"}, - {value:"ap-nanjing", label:"南京"}, - {value:"ap-beijing", label:"北京"}, - {value:"ap-chengdu", label:"成都"}, - {value:"ap-chongqing", label:"重庆"}, - {value:"ap-hongkong", label:"香港"}, - {value:"ap-singapore", label:"新加坡"}, - {value:"ap-jakarta", label:"雅加达"}, - {value:"ap-bangkok", label:"曼谷"}, - {value:"ap-tokyo", label:"东京"}, - {value:"ap-seoul", label:"首尔"}, - {value:"na-ashburn", label:"弗吉尼亚"}, - {value:"na-siliconvalley", label:"硅谷"}, - {value:"sa-saopaulo", label:"圣保罗"}, - {value:"eu-frankfurt", label:"法兰克福"}, - ] + { value: "ap-guangzhou", label: "广州" }, + { value: "ap-shanghai", label: "上海" }, + { value: "ap-nanjing", label: "南京" }, + { value: "ap-beijing", label: "北京" }, + { value: "ap-chengdu", label: "成都" }, + { value: "ap-chongqing", label: "重庆" }, + { value: "ap-hongkong", label: "香港" }, + { value: "ap-singapore", label: "新加坡" }, + { value: "ap-jakarta", label: "雅加达" }, + { value: "ap-bangkok", label: "曼谷" }, + { value: "ap-tokyo", label: "东京" }, + { value: "ap-seoul", label: "首尔" }, + { value: "na-ashburn", label: "弗吉尼亚" }, + { value: "na-siliconvalley", label: "硅谷" }, + { value: "sa-saopaulo", label: "圣保罗" }, + { value: "eu-frankfurt", label: "法兰克福" }, + ]; function buildTypeRegions(type: string) { - const options :any[]= [] + const options: any[] = []; for (const region of commonRegions) { options.push({ - label: type + "_" + region.label, + label: type + "_" + region.label, value: type + "_" + region.value, }); } - return options + return options; } return [ - { value: 'cdn',label: 'CDN'}, - { value: 'ddos',label: 'DDoS'}, - { value: 'live',label: '直播'}, - { value: 'vod',label: '点播'}, - { value: 'teo',label: 'TEO'}, - { value: 'lighthouse',label: '轻应用服务器'}, + { value: "cdn", label: "CDN" }, + { value: "ddos", label: "DDoS" }, + { value: "live", label: "直播" }, + { value: "vod", label: "点播" }, + { value: "teo", label: "TEO" }, + { value: "lighthouse", label: "轻应用服务器" }, { label: "负载均衡(clb)", value: "clb", @@ -306,27 +295,25 @@ export class TencentRefreshCert extends AbstractTaskPlugin { value: "tcb", children: buildTypeRegions("tcb"), }, - ] + ]; } async onGetCertList(data: PageSearch = {}) { - - const access = await this.getAccess(this.accessId) + const access = await this.getAccess(this.accessId); const sslClient = new TencentSslClient({ - access:access, + access: access, logger: this.logger, }); const pager = new Pager(data); const offset = pager.getOffset(); - const limit = pager.pageSize - const res = await sslClient.DescribeCertificates({Limit:limit,Offset:offset,SearchKey:data.searchKey}) - const list = res.Certificates + const limit = pager.pageSize; + const res = await sslClient.DescribeCertificates({ Limit: limit, Offset: offset, SearchKey: data.searchKey }); + const list = res.Certificates; if (!list || list.length === 0) { throw new Error("没有找到证书,你可以直接手动输入id"); } - /** * certificate-id * name diff --git a/packages/ui/certd-server/src/plugins/plugin-tencent/plugin/start-instances/index.ts b/packages/ui/certd-server/src/plugins/plugin-tencent/plugin/start-instances/index.ts index 1a90e6b8c..c980fc069 100644 --- a/packages/ui/certd-server/src/plugins/plugin-tencent/plugin/start-instances/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-tencent/plugin/start-instances/index.ts @@ -3,11 +3,11 @@ import { createRemoteSelectInputDefine } from "@certd/plugin-lib"; import { TencentAccess } from "../../../plugin-lib/tencent/access.js"; @IsTaskPlugin({ - name: 'TencentActionInstancesPlugin', - title: '腾讯云-实例开关机', - icon: 'svg:icon-tencentcloud', + name: "TencentActionInstancesPlugin", + title: "腾讯云-实例开关机", + icon: "svg:icon-tencentcloud", group: pluginGroups.tencent.key, - desc: '腾讯云实例开关机', + desc: "腾讯云实例开关机", default: { strategy: { runStrategy: RunStrategy.AlwaysRun, @@ -17,46 +17,46 @@ import { TencentAccess } from "../../../plugin-lib/tencent/access.js"; }) export class TencentActionInstancesPlugin extends AbstractTaskPlugin { @TaskInput({ - title: 'Access提供者', - helper: 'access 授权', + title: "Access提供者", + helper: "access 授权", component: { - name: 'access-selector', - type: 'tencent', + name: "access-selector", + type: "tencent", }, required: true, }) accessId!: string; @TaskInput({ - title: '所在地域', - helper: '实例所在地域', + title: "所在地域", + helper: "实例所在地域", component: { - name: 'a-auto-complete', - vModel: 'value', + name: "a-auto-complete", + vModel: "value", options: [ - { value: '', label: '--------中国大陆地区-------', disabled: true }, - { value: 'ap-beijing-1', label: '北京1区' }, - { value: 'ap-beijing', label: '北京' }, - { value: 'ap-nanjing', label: '南京' }, - { value: 'ap-shanghai', label: '上海' }, - { value: 'ap-guangzhou', label: '广州' }, - { value: 'ap-chengdu', label: '成都' }, - { value: 'ap-chongqing', label: '重庆' }, - { value: 'ap-shenzhen-fsi', label: '深圳金融' }, - { value: 'ap-shanghai-fsi', label: '上海金融' }, - { value: 'ap-beijing-fsi', label: '北京金融' }, - { value: '', label: '--------中国香港及境外-------', disabled: true }, - { value: 'ap-hongkong', label: '中国香港' }, - { value: 'ap-singapore', label: '新加坡' }, - { value: 'ap-mumbai', label: '孟买' }, - { value: 'ap-jakarta', label: '雅加达' }, - { value: 'ap-seoul', label: '首尔' }, - { value: 'ap-bangkok', label: '曼谷' }, - { value: 'ap-tokyo', label: '东京' }, - { value: 'na-siliconvalley', label: '硅谷' }, - { value: 'na-ashburn', label: '弗吉尼亚' }, - { value: 'sa-saopaulo', label: '圣保罗' }, - { value: 'eu-frankfurt', label: '法兰克福' }, + { value: "", label: "--------中国大陆地区-------", disabled: true }, + { value: "ap-beijing-1", label: "北京1区" }, + { value: "ap-beijing", label: "北京" }, + { value: "ap-nanjing", label: "南京" }, + { value: "ap-shanghai", label: "上海" }, + { value: "ap-guangzhou", label: "广州" }, + { value: "ap-chengdu", label: "成都" }, + { value: "ap-chongqing", label: "重庆" }, + { value: "ap-shenzhen-fsi", label: "深圳金融" }, + { value: "ap-shanghai-fsi", label: "上海金融" }, + { value: "ap-beijing-fsi", label: "北京金融" }, + { value: "", label: "--------中国香港及境外-------", disabled: true }, + { value: "ap-hongkong", label: "中国香港" }, + { value: "ap-singapore", label: "新加坡" }, + { value: "ap-mumbai", label: "孟买" }, + { value: "ap-jakarta", label: "雅加达" }, + { value: "ap-seoul", label: "首尔" }, + { value: "ap-bangkok", label: "曼谷" }, + { value: "ap-tokyo", label: "东京" }, + { value: "na-siliconvalley", label: "硅谷" }, + { value: "na-ashburn", label: "弗吉尼亚" }, + { value: "sa-saopaulo", label: "圣保罗" }, + { value: "eu-frankfurt", label: "法兰克福" }, ], }, required: true, @@ -65,23 +65,23 @@ export class TencentActionInstancesPlugin extends AbstractTaskPlugin { @TaskInput( createRemoteSelectInputDefine({ - title: '实列ID', - helper: '请选择实列', - typeName: 'TencentStartInstancesPlugin', + title: "实列ID", + helper: "请选择实列", + typeName: "TencentStartInstancesPlugin", action: TencentActionInstancesPlugin.prototype.onGetInstanceList.name, - watches: ['region'], + watches: ["region"], }) ) instanceId!: string[]; @TaskInput({ - title: '操作', + title: "操作", component: { - name: 'a-radio-group', - vModel: 'value', + name: "a-radio-group", + vModel: "value", options: [ - { value: 'start', label: '开机' }, - { value: 'stop', label: '关机' }, + { value: "start", label: "开机" }, + { value: "stop", label: "关机" }, ], }, required: true, @@ -89,11 +89,11 @@ export class TencentActionInstancesPlugin extends AbstractTaskPlugin { action!: string; @TaskInput({ - title: '实例关机不收费', + title: "实例关机不收费", value: true, component: { - name: 'a-switch', - vModel: 'checked', + name: "a-switch", + vModel: "checked", placeholder: `按量计费实例关机不收费`, }, required: false, @@ -115,13 +115,13 @@ export class TencentActionInstancesPlugin extends AbstractTaskPlugin { InstanceIds: this.instanceId, }; let res: any; - if (this.action === 'start') { + if (this.action === "start") { res = await cvmClient.StartInstances(params); } else { res = await cvmClient.StopInstances( Object.assign(params, { - StopType: 'SOFT_FIRST', - StoppedMode: this.charging ? 'STOP_CHARGING' : 'KEEP_CHARGING', + StopType: "SOFT_FIRST", + StoppedMode: this.charging ? "STOP_CHARGING" : "KEEP_CHARGING", }) ); } @@ -131,17 +131,17 @@ export class TencentActionInstancesPlugin extends AbstractTaskPlugin { checkRet(ret: any) { if (!ret || ret.Error) { - throw new Error('执行失败:' + ret.Error.Code + ',' + ret.Error.Message); + throw new Error("执行失败:" + ret.Error.Code + "," + ret.Error.Message); } } async getCvmClient() { const accessProvider = await this.getAccess(this.accessId); - const sdk = await import('tencentcloud-sdk-nodejs/tencentcloud/services/cvm/v20170312/index.js'); + const sdk = await import("tencentcloud-sdk-nodejs/tencentcloud/services/cvm/v20170312/index.js"); const CvmClient = sdk.v20170312.Client; if (!this.region) { - throw new Error('所在地域不能为空'); + throw new Error("所在地域不能为空"); } const clientConfig = { @@ -167,7 +167,7 @@ export class TencentActionInstancesPlugin extends AbstractTaskPlugin { }); this.checkRet(res); - this.ctx.logger.info('获取实列列表:', res); + this.ctx.logger.info("获取实列列表:", res); return res.InstanceSet.map((item: any) => { return { label: item.InstanceName, diff --git a/packages/ui/certd-server/src/plugins/plugin-tencent/plugin/upload-to-tencent/index.ts b/packages/ui/certd-server/src/plugins/plugin-tencent/plugin/upload-to-tencent/index.ts index 530f0c720..c8f5ed284 100644 --- a/packages/ui/certd-server/src/plugins/plugin-tencent/plugin/upload-to-tencent/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-tencent/plugin/upload-to-tencent/index.ts @@ -4,10 +4,10 @@ import { TencentAccess } from "../../../plugin-lib/tencent/access.js"; import { TencentSslClient } from "../../../plugin-lib/tencent/index.js"; @IsTaskPlugin({ - name: 'UploadCertToTencent', - title: '腾讯云-上传证书到腾讯云', - icon: 'svg:icon-tencentcloud', - desc: '上传成功后输出:tencentCertId', + name: "UploadCertToTencent", + title: "腾讯云-上传证书到腾讯云", + icon: "svg:icon-tencentcloud", + desc: "上传成功后输出:tencentCertId", group: pluginGroups.tencent.key, default: { strategy: { @@ -20,21 +20,21 @@ export class UploadCertToTencent extends AbstractTaskPlugin { // name!: string; @TaskInput({ - title: 'Access授权', - helper: 'access授权', + title: "Access授权", + helper: "access授权", component: { - name: 'access-selector', - type: 'tencent', + name: "access-selector", + type: "tencent", }, required: true, }) accessId!: string; @TaskInput({ - title: '域名证书', - helper: '请选择前置任务输出的域名证书', + title: "域名证书", + helper: "请选择前置任务输出的域名证书", component: { - name: 'output-selector', + name: "output-selector", from: [...CertApplyPluginNames], }, required: true, @@ -42,13 +42,13 @@ export class UploadCertToTencent extends AbstractTaskPlugin { cert!: any; @TaskOutput({ - title: '上传成功后的腾讯云CertId', + title: "上传成功后的腾讯云CertId", }) tencentCertId?: string; Client: any; async onInstance() { - const sdk = await import('tencentcloud-sdk-nodejs/tencentcloud/services/ssl/v20191205/index.js'); + const sdk = await import("tencentcloud-sdk-nodejs/tencentcloud/services/ssl/v20191205/index.js"); this.Client = sdk.v20191205.Client; } @@ -68,11 +68,9 @@ export class UploadCertToTencent extends AbstractTaskPlugin { this.tencentCertId = tencentCertId; } - - checkRet(ret: any) { if (!ret || ret.Error) { - throw new Error('执行失败:' + ret.Error.Code + ',' + ret.Error.Message); + throw new Error("执行失败:" + ret.Error.Code + "," + ret.Error.Message); } } } diff --git a/packages/ui/certd-server/src/plugins/plugin-ucloud/access.ts b/packages/ui/certd-server/src/plugins/plugin-ucloud/access.ts index 6ddff3054..0571b9a8e 100644 --- a/packages/ui/certd-server/src/plugins/plugin-ucloud/access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-ucloud/access.ts @@ -1,68 +1,64 @@ -import { IsAccess, AccessInput, BaseAccess } from '@certd/pipeline'; -import { CertInfo, CertReader } from '@certd/plugin-cert'; +import { IsAccess, AccessInput, BaseAccess } from "@certd/pipeline"; +import { CertInfo, CertReader } from "@certd/plugin-cert"; /** * 这个注解将注册一个授权配置 * 在certd的后台管理系统中,用户可以选择添加此类型的授权 */ @IsAccess({ - name: 'ucloud', - title: 'UCloud授权', - icon: 'svg:icon-ucloud', - desc: '优刻得授权', + name: "ucloud", + title: "UCloud授权", + icon: "svg:icon-ucloud", + desc: "优刻得授权", }) export class UCloudAccess extends BaseAccess { - /** * 授权属性配置 */ @AccessInput({ - title: '项目Id', + title: "项目Id", component: { - placeholder: '项目Id', + placeholder: "项目Id", }, helper: "[项目管理](https://console.ucloud.cn/uaccount/iam/project_manage)项目ID列获取", required: true, encrypt: false, }) - projectId = ''; - + projectId = ""; /** * 授权属性配置 */ @AccessInput({ - title: '公钥', + title: "公钥", component: { - placeholder: '公钥', + placeholder: "公钥", }, helper: "[Api管理](https://console.ucloud.cn/uaccount/api_manage)获取", required: true, encrypt: false, }) - publicKey = ''; + publicKey = ""; @AccessInput({ - title: '私钥', + title: "私钥", component: { name: "a-input-password", vModel: "value", - placeholder: '私钥', + placeholder: "私钥", }, required: true, encrypt: true, }) - privateKey = ''; - - + privateKey = ""; @AccessInput({ title: "测试", component: { name: "api-test", - action: "TestRequest" + action: "TestRequest", }, - helper: "点击测试接口是否正常" + helper: "点击测试接口是否正常", }) testRequest = true; @@ -73,31 +69,30 @@ export class UCloudAccess extends BaseAccess { return "ok"; } - - async getClient(region?:string) { + async getClient(region?: string) { if (this.client) { return this.client; } - const { Client } = await import('@ucloud-sdks/ucloud-sdk-js'); + const { Client } = await import("@ucloud-sdks/ucloud-sdk-js"); const client = new Client({ config: { - region: region || 'cn-bj2', + region: region || "cn-bj2", projectId: this.projectId || "", - baseUrl: "https://api.ucloud.cn" + baseUrl: "https://api.ucloud.cn", }, credential: { publicKey: this.publicKey, privateKey: this.privateKey, - } + }, }); this.client = client; - return client + return client; } async ProjectList() { const client = await this.getClient(); const resp = await client.uaccount().getProjectList({ - "Action": "GetProjectList" + Action: "GetProjectList", }); // this.ctx.logger.info(`获取到项目列表:${JSON.stringify(resp)}`); return resp; @@ -106,81 +101,77 @@ export class UCloudAccess extends BaseAccess { async GetRegion() { const client = await this.getClient(); const res = await client.uaccount().getRegion({ - "Action": "GetRegion" + Action: "GetRegion", }); // this.ctx.logger.info(`获取到区域列表:${JSON.stringify(res)}`); return res; } - async CdnDominList(req: { PageNo: number, PageSize: number }) { + async CdnDominList(req: { PageNo: number; PageSize: number }) { const client = await this.getClient(); const resp = await client.ucdn().getUcdnDomainInfoList({ - "Action": "GetUcdnDomainInfoList", - "ProjectId": this.projectId || "", - "PageNo": req.PageNo, - "PageSize": req.PageSize, + Action: "GetUcdnDomainInfoList", + ProjectId: this.projectId || "", + PageNo: req.PageNo, + PageSize: req.PageSize, }); // this.ctx.logger.info(`获取到CDN域名列表:${JSON.stringify(resp)}`); return resp; } - async CdnAddCert(req: { certName: string, cert: CertInfo }) { + async CdnAddCert(req: { certName: string; cert: CertInfo }) { const client = await this.getClient(); const resp = await client.ucdn().addCertificate({ - "Action": "AddCertificate", - "ProjectId": this.projectId || "", - "CertName": req.certName, - "UserCert": req.cert.crt, - "PrivateKey": req.cert.key + Action: "AddCertificate", + ProjectId: this.projectId || "", + CertName: req.certName, + UserCert: req.cert.crt, + PrivateKey: req.cert.key, }); this.ctx.logger.info(`添加CDN证书:${JSON.stringify(resp)}`); return resp; } - async SslUploadCert(req: { cert: CertInfo }) { - const { cert } = req + const { cert } = req; /** &SslPublicKey=lXUzWbSR &SslCaKey=lXUzWbSR &SslMD5=lXUzWbSR &CertificateName=GoodCertcification */ - const certReader = new CertReader(cert) - const certName = certReader.buildCertName() - const crtBase64 = this.ctx.utils.hash.base64(cert.crt) - const keyBase64 = this.ctx.utils.hash.base64(cert.key) - const allDomains = certReader.getAllDomains().join(",") + const certReader = new CertReader(cert); + const certName = certReader.buildCertName(); + const crtBase64 = this.ctx.utils.hash.base64(cert.crt); + const keyBase64 = this.ctx.utils.hash.base64(cert.key); + const allDomains = certReader.getAllDomains().join(","); this.ctx.logger.info(`----------- 上传USSL证书,certName:${certName},domains:${allDomains}`); try { const resp = await this.invoke({ Action: "UploadNormalCertificate", - "SslPublicKey": crtBase64, - "SslPrivateKey": keyBase64, - "CertificateName": certName, - "SslMD5": this.ctx.utils.hash.md5(crtBase64 + keyBase64) + SslPublicKey: crtBase64, + SslPrivateKey: keyBase64, + CertificateName: certName, + SslMD5: this.ctx.utils.hash.md5(crtBase64 + keyBase64), }); this.ctx.logger.info(`----------- 上传USSL证书成功,certId:${resp.CertificateID}`); - return { type: "ussl", id: resp.CertificateID, name: certName, resourceId: resp.LongResourceID, domains: allDomains } + return { type: "ussl", id: resp.CertificateID, name: certName, resourceId: resp.LongResourceID, domains: allDomains }; } catch (err) { - if (err.message.includes("重复上传证书")) { //查找证书 const certList = await this.SslGetCertList(certReader.getMainDomain()); - const cert = certList.find((item: any) => item.Domains === allDomains) + const cert = certList.find((item: any) => item.Domains === allDomains); if (cert) { this.ctx.logger.info(`----------- 找到已存在证书,certId:${cert.CertificateID}`); - return { type: "ussl", id: cert.CertificateID, name: certName, domains: cert.Domains } + return { type: "ussl", id: cert.CertificateID, name: certName, domains: cert.Domains }; } } this.ctx.logger.error(`上传USSL证书失败:${err}`); throw err; } - - } async SslGetCertList(domain: string) { @@ -188,39 +179,39 @@ export class UCloudAccess extends BaseAccess { Action: "GetCertificateList", Mode: "trust", Domain: domain, - Sort: "2" + Sort: "2", }); return resp.CertificateList || []; } - async WafSiteList(req: { PageNo: number, PageSize: number , FullDomain?: string }):Promise<{DomainHostList?:{RecordId:string,FullDomain:string}[],TotalCount:number}> { + async WafSiteList(req: { PageNo: number; PageSize: number; FullDomain?: string }): Promise<{ DomainHostList?: { RecordId: string; FullDomain: string }[]; TotalCount: number }> { const resp = await this.invoke({ - "Action": "DescribeWafDomainHostInfo", - "ProjectId": this.projectId, - "Limit": req.PageSize, - "Offset": (req.PageNo - 1) * req.PageSize, - "FullDomain": req.FullDomain || undefined + Action: "DescribeWafDomainHostInfo", + ProjectId: this.projectId, + Limit: req.PageSize, + Offset: (req.PageNo - 1) * req.PageSize, + FullDomain: req.FullDomain || undefined, }); this.ctx.logger.info(`获取到WAF站点列表:${JSON.stringify(resp)}`); return resp; } - - async invoke(req: { Action: string, [key: string]: any }) { - const { Request } = await import('@ucloud-sdks/ucloud-sdk-js'); + async invoke(req: { Action: string; [key: string]: any }) { + const { Request } = await import("@ucloud-sdks/ucloud-sdk-js"); const client = await this.getClient(); - const resp = await client.invoke(new Request({ - ...req - })); + const resp = await client.invoke( + new Request({ + ...req, + }) + ); // this.ctx.logger.info(`请求UCloud API:${JSON.stringify(resp)}`); - const res = resp.data || {} + const res = resp.data || {}; if (res.RetCode !== 0) { - throw new Error(res.Message) + throw new Error(res.Message); } return res; } - } new UCloudAccess(); diff --git a/packages/ui/certd-server/src/plugins/plugin-ucloud/index.ts b/packages/ui/certd-server/src/plugins/plugin-ucloud/index.ts index c49d8bf88..21a066db2 100644 --- a/packages/ui/certd-server/src/plugins/plugin-ucloud/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-ucloud/index.ts @@ -1,2 +1,2 @@ -export * from './access.js'; -export * from './plugins/index.js'; +export * from "./access.js"; +export * from "./plugins/index.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-ucloud/plugins/constants.ts b/packages/ui/certd-server/src/plugins/plugin-ucloud/plugins/constants.ts index 6ca79f232..3cd24cdc0 100644 --- a/packages/ui/certd-server/src/plugins/plugin-ucloud/plugins/constants.ts +++ b/packages/ui/certd-server/src/plugins/plugin-ucloud/plugins/constants.ts @@ -34,37 +34,37 @@ kz-ala 哈萨克斯坦(阿拉木图) mx-qro 墨西哥(克雷塔罗) */ export const UCloudRegions = [ - {label: "华北(北京)",value: "cn-bj1" }, - {label: "华北(北京2)",value: "cn-bj2" }, - {label: "华北(乌兰察布)",value: "cn-wlcb" }, - {label: "华北(乌兰察布2)",value: "cn-wlcb2" }, - {label: "华东(上海2)",value: "cn-sh2" }, - {label: "华东(嘉兴)",value: "cn-jx" }, - {label: "金融云-华东(上海)",value: "cn-sh" }, - {label: "华南(广州2)",value: "cn-gd2" }, - {label: "华南(广州)",value: "cn-gd" }, - {label: "西南(贵阳)",value: "cn-guiyang1" }, - {label: "香港",value: "hk" }, - {label: "台湾(台北)",value: "tw-tp" }, - {label: "新加坡",value: "sg" }, - {label: "日本(东京)",value: "jpn-tky" }, - {label: "韩国(首尔)",value: "kr-seoul" }, - {label: "泰国(曼谷)",value: "th-bkk" }, - {label: "印度尼西亚(雅加达)",value: "idn-jakarta" }, - {label: "越南(胡志明)",value: "vn-sng" }, - {label: "菲律宾(马尼拉)",value: "ph-mnl" }, - {label: "印度(孟买)",value: "ind-mumbai" }, - {label: "巴基斯坦(卡拉奇)",value: "pk-khi" }, - {label: "美国(丹佛)",value: "us-den" }, - {label: "美国(洛杉矶)",value: "us-ca" }, - {label: "美国(华盛顿)",value: "us-ws" }, - {label: "巴西(圣保罗)",value: "bra-saopaulo" }, - {label: "俄罗斯(莫斯科)",value: "rus-mosc" }, - {label: "德国(法兰克福)",value: "ge-fra" }, - {label: "英国(伦敦)",value: "uk-london" }, - {label: "阿联酋(迪拜)",value: "uae-dubai" }, - {label: "尼日利亚(拉各斯)",value: "afr-nigeria" }, - {label: "乌兹别克斯坦(塔什干)",value: "uz-tas" }, - {label: "哈萨克斯坦(阿拉木图)",value: "kz-ala" }, - {label: "墨西哥(克雷塔罗)",value: "mx-qro" }, -] \ No newline at end of file + { label: "华北(北京)", value: "cn-bj1" }, + { label: "华北(北京2)", value: "cn-bj2" }, + { label: "华北(乌兰察布)", value: "cn-wlcb" }, + { label: "华北(乌兰察布2)", value: "cn-wlcb2" }, + { label: "华东(上海2)", value: "cn-sh2" }, + { label: "华东(嘉兴)", value: "cn-jx" }, + { label: "金融云-华东(上海)", value: "cn-sh" }, + { label: "华南(广州2)", value: "cn-gd2" }, + { label: "华南(广州)", value: "cn-gd" }, + { label: "西南(贵阳)", value: "cn-guiyang1" }, + { label: "香港", value: "hk" }, + { label: "台湾(台北)", value: "tw-tp" }, + { label: "新加坡", value: "sg" }, + { label: "日本(东京)", value: "jpn-tky" }, + { label: "韩国(首尔)", value: "kr-seoul" }, + { label: "泰国(曼谷)", value: "th-bkk" }, + { label: "印度尼西亚(雅加达)", value: "idn-jakarta" }, + { label: "越南(胡志明)", value: "vn-sng" }, + { label: "菲律宾(马尼拉)", value: "ph-mnl" }, + { label: "印度(孟买)", value: "ind-mumbai" }, + { label: "巴基斯坦(卡拉奇)", value: "pk-khi" }, + { label: "美国(丹佛)", value: "us-den" }, + { label: "美国(洛杉矶)", value: "us-ca" }, + { label: "美国(华盛顿)", value: "us-ws" }, + { label: "巴西(圣保罗)", value: "bra-saopaulo" }, + { label: "俄罗斯(莫斯科)", value: "rus-mosc" }, + { label: "德国(法兰克福)", value: "ge-fra" }, + { label: "英国(伦敦)", value: "uk-london" }, + { label: "阿联酋(迪拜)", value: "uae-dubai" }, + { label: "尼日利亚(拉各斯)", value: "afr-nigeria" }, + { label: "乌兹别克斯坦(塔什干)", value: "uz-tas" }, + { label: "哈萨克斯坦(阿拉木图)", value: "kz-ala" }, + { label: "墨西哥(克雷塔罗)", value: "mx-qro" }, +]; diff --git a/packages/ui/certd-server/src/plugins/plugin-ucloud/plugins/index.ts b/packages/ui/certd-server/src/plugins/plugin-ucloud/plugins/index.ts index 0dfa01f67..a57efc9ff 100644 --- a/packages/ui/certd-server/src/plugins/plugin-ucloud/plugins/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-ucloud/plugins/index.ts @@ -1,5 +1,5 @@ -export * from './plugin-deploy-to-cdn.js'; -export * from './plugin-upload-to-ussl.js'; -export * from './plugin-deploy-to-waf.js'; -export * from './plugin-deploy-to-ulb.js'; -export * from './plugin-deploy-to-us3.js'; +export * from "./plugin-deploy-to-cdn.js"; +export * from "./plugin-upload-to-ussl.js"; +export * from "./plugin-deploy-to-waf.js"; +export * from "./plugin-deploy-to-ulb.js"; +export * from "./plugin-deploy-to-us3.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-ucloud/plugins/plugin-deploy-to-cdn.ts b/packages/ui/certd-server/src/plugins/plugin-ucloud/plugins/plugin-deploy-to-cdn.ts index 5d6b04ecc..53bc7c0e6 100644 --- a/packages/ui/certd-server/src/plugins/plugin-ucloud/plugins/plugin-deploy-to-cdn.ts +++ b/packages/ui/certd-server/src/plugins/plugin-ucloud/plugins/plugin-deploy-to-cdn.ts @@ -15,9 +15,9 @@ import { UCloudAccess } from "../access.js"; default: { //默认值配置照抄即可 strategy: { - runStrategy: RunStrategy.SkipWhenSucceed - } - } + runStrategy: RunStrategy.SkipWhenSucceed, + }, + }, }) //类名规范,跟上面插件名称(name)一致 export class UCloudDeployToCDN extends AbstractTaskPlugin { @@ -27,11 +27,11 @@ export class UCloudDeployToCDN extends AbstractTaskPlugin { helper: "请选择前置任务输出的域名证书", component: { name: "output-selector", - from: [...CertApplyPluginNames, ":UCloudCertId:"] - } + from: [...CertApplyPluginNames, ":UCloudCertId:"], + }, // required: true, // 必填 }) - cert!: CertInfo | { type: string, id: number, name: string }; + cert!: CertInfo | { type: string; id: number; name: string }; @TaskInput(createCertDomainGetterInputDefine({ props: { required: false } })) certDomains!: string[]; @@ -41,9 +41,9 @@ export class UCloudDeployToCDN extends AbstractTaskPlugin { title: "UCloud授权", component: { name: "access-selector", - type: "ucloud" //固定授权类型 + type: "ucloud", //固定授权类型 }, - required: true //必填 + required: true, //必填 }) accessId!: string; // @@ -53,35 +53,33 @@ export class UCloudDeployToCDN extends AbstractTaskPlugin { title: "域名列表", helper: "要更新的UCloud域名列表", - action: UCloudDeployToCDN.prototype.onGetDomainList.name + action: UCloudDeployToCDN.prototype.onGetDomainList.name, }) ) domainList!: string[]; //插件实例化时执行的方法 - async onInstance() { - } + async onInstance() {} //插件执行方法 async execute(): Promise { const access = await this.getAccess(this.accessId); - let certType = "ussl" - let certId = 0 - let certName = this.appendTimeSuffix("certd") + const certType = "ussl"; + let certId = 0; + let certName = this.appendTimeSuffix("certd"); // @ts-ignore if (this.cert?.id) { //从上一步传过来的ssl证书 // @ts-ignore - certId = this.cert.id + certId = this.cert.id; // @ts-ignore - certName = this.cert.name - + certName = this.cert.name; } else { const cert = await access.SslUploadCert({ - cert: this.cert as CertInfo + cert: this.cert as CertInfo, }); - certId = cert.id - certName = cert.name + certId = cert.id; + certName = cert.name; } for (const item of this.domainList) { @@ -91,7 +89,7 @@ export class UCloudDeployToCDN extends AbstractTaskPlugin { certName: certName, domain: item, certId: certId, - certType: certType + certType: certType, }); this.logger.info(`----------- 更新域名证书${item}成功`); } @@ -99,16 +97,13 @@ export class UCloudDeployToCDN extends AbstractTaskPlugin { this.logger.info("部署完成"); } - - async deployToCdn(req: { access: any, domain: string, certId: number, certType: string, certName: string }) { - const { access, domain, certId, certType, certName } = req + async deployToCdn(req: { access: any; domain: string; certId: number; certType: string; certName: string }) { + const { access, domain, certId, certType, certName } = req; const domainsRes = await access.invoke({ - "Action": "GetUcdnDomainConfig", - "ProjectId": access.projectId, - "Domain": [ - domain - ] + Action: "GetUcdnDomainConfig", + ProjectId: access.projectId, + Domain: [domain], }); const domainList = domainsRes.DomainList || []; @@ -122,20 +117,19 @@ export class UCloudDeployToCDN extends AbstractTaskPlugin { let httpsStatusCn = domainConf.HttpsStatusCn; if (httpsStatusAbroad === "disable" && httpsStatusCn === "disable") { this.logger.info(`原CDN域名HTTPS未开启,将开启国内加速`); - httpsStatusCn = "enable" + httpsStatusCn = "enable"; } - const body: any = { - "Action": "UpdateUcdnDomainHttpsConfigV2", - "DomainId": domainId, - "CertName": certName, - "CertId": certId, - "CertType": certType, - EnableHttp2: domainConf.EnableHttp2 ||"0", + Action: "UpdateUcdnDomainHttpsConfigV2", + DomainId: domainId, + CertName: certName, + CertId: certId, + CertType: certType, + EnableHttp2: domainConf.EnableHttp2 || "0", RedirectHttp2Https: domainConf.RedirectHttp2Https || "0", - TlsVersion: domainConf.TlsVersion || "tlsv1.0,tlsv1.1,tlsv1.2,tlsv1.3" - } + TlsVersion: domainConf.TlsVersion || "tlsv1.0,tlsv1.1,tlsv1.2,tlsv1.3", + }; if (httpsStatusAbroad === "enable") { body.HttpsStatusAbroad = httpsStatusAbroad; } @@ -152,12 +146,10 @@ export class UCloudDeployToCDN extends AbstractTaskPlugin { const pageNo = req.pageNo ?? 1; const pageSize = req.pageSize ?? 100; - const res = await access.CdnDominList( - { - PageNo: pageNo, - PageSize: pageSize - } - ); + const res = await access.CdnDominList({ + PageNo: pageNo, + PageSize: pageSize, + }); const total = res.TotalCount; const list = res.DomainInfoList || []; if (!list || list.length === 0) { @@ -172,17 +164,16 @@ export class UCloudDeployToCDN extends AbstractTaskPlugin { return { label: `${item.Domain}<${item.DomainId}>`, value: `${item.Domain}`, - domain: item.Domain + domain: item.Domain, }; }); return { list: this.ctx.utils.options.buildGroupOptions(options, this.certDomains), total: total, pageNo: pageNo, - pageSize: pageSize + pageSize: pageSize, }; } - } //实例化一下,注册插件 diff --git a/packages/ui/certd-server/src/plugins/plugin-ucloud/plugins/plugin-deploy-to-ulb.ts b/packages/ui/certd-server/src/plugins/plugin-ucloud/plugins/plugin-deploy-to-ulb.ts index 4dccff0dc..c44dd0b1b 100644 --- a/packages/ui/certd-server/src/plugins/plugin-ucloud/plugins/plugin-deploy-to-ulb.ts +++ b/packages/ui/certd-server/src/plugins/plugin-ucloud/plugins/plugin-deploy-to-ulb.ts @@ -13,9 +13,9 @@ import { UCloudRegions } from "./constants.js"; needPlus: false, default: { strategy: { - runStrategy: RunStrategy.SkipWhenSucceed - } - } + runStrategy: RunStrategy.SkipWhenSucceed, + }, + }, }) export class UCloudDeployToULB extends AbstractTaskPlugin { @TaskInput({ @@ -23,8 +23,8 @@ export class UCloudDeployToULB extends AbstractTaskPlugin { helper: "请选择前置任务输出的域名证书", component: { name: "output-selector", - from: [...CertApplyPluginNames] - } + from: [...CertApplyPluginNames], + }, }) cert!: CertInfo; @@ -35,9 +35,9 @@ export class UCloudDeployToULB extends AbstractTaskPlugin { title: "UCloud授权", component: { name: "access-selector", - type: "ucloud" + type: "ucloud", }, - required: true + required: true, }) accessId!: string; @@ -46,7 +46,7 @@ export class UCloudDeployToULB extends AbstractTaskPlugin { title: "地域", helper: "选择UCloud地域", action: UCloudDeployToULB.prototype.onGetRegionList.name, - single: true + single: true, }) ) region!: string; @@ -60,9 +60,7 @@ export class UCloudDeployToULB extends AbstractTaskPlugin { ) certNameList!: string[]; - - async onInstance() { - } + async onInstance() {} async onGetRegionList(req: PageSearch = {}) { const access = await this.getAccess(this.accessId); @@ -74,7 +72,7 @@ export class UCloudDeployToULB extends AbstractTaskPlugin { throw new Error("没有获取到UCloud地域列表"); } - const haveSet = {} + const haveSet = {}; list = list.filter((item: any) => { const region = item.Region; if (haveSet[region]) { @@ -82,13 +80,13 @@ export class UCloudDeployToULB extends AbstractTaskPlugin { } haveSet[region] = true; return true; - }) - let options = list.map((item: any) => { + }); + const options = list.map((item: any) => { const region = item.Region; - const name = UCloudRegions.find((r) => r.value === region)?.label || item.RegionName; + const name = UCloudRegions.find(r => r.value === region)?.label || item.RegionName; return { label: `${name}(${item.Region})`, - value: item.Region + value: item.Region, }; }); @@ -96,21 +94,20 @@ export class UCloudDeployToULB extends AbstractTaskPlugin { list: options, total: options.length, pageNo: 1, - pageSize: options.length + pageSize: options.length, }; } - async execute(): Promise { const access = await this.getAccess(this.accessId); const allCertList = await this.getAllCert(access); - const certMap = {} - allCertList.forEach((item) => { + const certMap = {}; + allCertList.forEach(item => { if (!item.name) { return; } certMap[item.name] = item; - }) + }); for (const certName of this.certNameList) { this.logger.info(`----------- 开始更新证书:${certName}`); @@ -126,10 +123,10 @@ export class UCloudDeployToULB extends AbstractTaskPlugin { continue; } - const bakCertName = `${certName}_${oldCert.id}_${Date.now()}` - let certId = await this.uploadCertToULB({ + const bakCertName = `${certName}_${oldCert.id}_${Date.now()}`; + const certId = await this.uploadCertToULB({ access, - certName:bakCertName, + certName: bakCertName, }); this.logger.info(`----------- 上传证书${bakCertName}完成`); @@ -140,7 +137,6 @@ export class UCloudDeployToULB extends AbstractTaskPlugin { certName, }); this.logger.info(`----------- 证书${certName}部署完成`); - } await this.ctx.utils.sleep(2000); @@ -151,13 +147,13 @@ export class UCloudDeployToULB extends AbstractTaskPlugin { } async clearExpiredCert(access: UCloudAccess, allCertList: any[]) { - const now = Date.now()/1000; - const expiredCertList = allCertList.filter((item) => { + const now = Date.now() / 1000; + const expiredCertList = allCertList.filter(item => { if (!item.notAfter) { return false; } return item.notAfter < now; - }) + }); if (!expiredCertList || expiredCertList.length === 0) { this.logger.info(`----------- 没有过期证书需要清理`); return; @@ -166,10 +162,10 @@ export class UCloudDeployToULB extends AbstractTaskPlugin { this.logger.info(`----------- 清理过期证书:${cert.name} ${cert.id}`); try { await access.invoke({ - "Action": "DeleteSSL", - "Region": this.region, - "ProjectId": access.projectId, - "SSLId": cert.id, + Action: "DeleteSSL", + Region: this.region, + ProjectId: access.projectId, + SSLId: cert.id, }); this.logger.info(`----------- 清理过期证书成功:${cert.name} ${cert.id}`); } catch (error) { @@ -177,12 +173,7 @@ export class UCloudDeployToULB extends AbstractTaskPlugin { } } } - async updateSSLBinding(req: { - access: UCloudAccess, - oldSSL: any, - newSSLId: string, - certName: string, - }) { + async updateSSLBinding(req: { access: UCloudAccess; oldSSL: any; newSSLId: string; certName: string }) { const access = req.access; const oldSSLId = req.oldSSL.id; const newSSLId = req.newSSLId; @@ -192,11 +183,11 @@ export class UCloudDeployToULB extends AbstractTaskPlugin { } else { this.logger.info(`----------- 更新ULB证书绑定:${oldSSLId} -> ${newSSLId}`); await access.invoke({ - "Action": "UpdateSSLBinding", - "Region": this.region, - "ProjectId": access.projectId, - "OldSSLId": oldSSLId, - "NewSSLId": newSSLId, + Action: "UpdateSSLBinding", + Region: this.region, + ProjectId: access.projectId, + OldSSLId: oldSSLId, + NewSSLId: newSSLId, }); this.logger.info(`----------- 更新ULB证书绑定成功: ${newSSLId}`); } @@ -204,52 +195,47 @@ export class UCloudDeployToULB extends AbstractTaskPlugin { // 更新证书名称 this.logger.info(`----------- 更新ULB证书名称:${newSSLId} -> ${req.certName}`); await access.invoke({ - "Action": "UpdateSSLAttribute", - "Region": this.region, - "ProjectId": access.projectId, - "SSLId": newSSLId, - "SSLName": req.certName, + Action: "UpdateSSLAttribute", + Region: this.region, + ProjectId: access.projectId, + SSLId: newSSLId, + SSLName: req.certName, }); this.logger.info(`----------- 更新ULB证书名称成功:${req.certName}`); await this.ctx.utils.sleep(5000); try { this.logger.info(`----------- 删除ULB旧证书:${oldSSLId}`); await access.invoke({ - "Action": "DeleteSSL", - "Region": this.region, - "ProjectId": access.projectId, - "SSLId": oldSSLId, + Action: "DeleteSSL", + Region: this.region, + ProjectId: access.projectId, + SSLId: oldSSLId, }); this.logger.info(`----------- 删除ULB旧证书成功:${oldSSLId}`); } catch (error) { this.logger.error(`----------- 删除ULB旧证书失败:${oldSSLId}`, error); } - } - async uploadCertToULB(req: { - access: UCloudAccess, - certName: string, - }) { + async uploadCertToULB(req: { access: UCloudAccess; certName: string }) { const access = req.access; const certName = req.certName; - const certContent = `${this.cert.crt}\n${this.cert.key}` + const certContent = `${this.cert.crt}\n${this.cert.key}`; const res = await access.invoke({ - "Action": "CreateSSL", - "Region": this.region, - "ProjectId": access.projectId, - "SSLName": certName, - "SSLContent": certContent, + Action: "CreateSSL", + Region: this.region, + ProjectId: access.projectId, + SSLName: certName, + SSLContent: certContent, }); if (res.RetCode !== 0) { - throw new Error(`创建ULB证书失败: ${res.Message || '未知错误'}`); + throw new Error(`创建ULB证书失败: ${res.Message || "未知错误"}`); } return res.SSLId; } - async getAllCert(access: UCloudAccess) { const certList = [] as any[]; const pager = { @@ -268,27 +254,23 @@ export class UCloudDeployToULB extends AbstractTaskPlugin { return certList; } - async getCertPage(access: UCloudAccess, req: PageSearch = {}) { const pageNo = req.pageNo ?? 1; const pageSize = req.pageSize ?? 100; const res = await access.invoke({ - "Action": "DescribeSSLV2", - "Region": this.region, - "ProjectId": access.projectId, - "Offset": (pageNo - 1) * pageSize, - "Limit": pageSize + Action: "DescribeSSLV2", + Region: this.region, + ProjectId: access.projectId, + Offset: (pageNo - 1) * pageSize, + Limit: pageSize, }); let list = res.DataSet || []; const total = res.TotalCount || list.length; list = list.map((item: any) => { - const domains = [ - ...item.Domains.split(','), - ...item.DNSNames.split(',') - ] + const domains = [...item.Domains.split(","), ...item.DNSNames.split(",")]; return { id: item.SSLId, name: item.SSLName, @@ -298,7 +280,7 @@ export class UCloudDeployToULB extends AbstractTaskPlugin { createTime: item.CreateTime, relations: item.Relations, }; - }) + }); return { list: list, total: total, @@ -327,7 +309,6 @@ export class UCloudDeployToULB extends AbstractTaskPlugin { total: total, }; } - } new UCloudDeployToULB(); diff --git a/packages/ui/certd-server/src/plugins/plugin-ucloud/plugins/plugin-deploy-to-us3.ts b/packages/ui/certd-server/src/plugins/plugin-ucloud/plugins/plugin-deploy-to-us3.ts index 72e16a508..354f4a554 100644 --- a/packages/ui/certd-server/src/plugins/plugin-ucloud/plugins/plugin-deploy-to-us3.ts +++ b/packages/ui/certd-server/src/plugins/plugin-ucloud/plugins/plugin-deploy-to-us3.ts @@ -12,9 +12,9 @@ import { UCloudAccess } from "../access.js"; needPlus: false, default: { strategy: { - runStrategy: RunStrategy.SkipWhenSucceed - } - } + runStrategy: RunStrategy.SkipWhenSucceed, + }, + }, }) export class UCloudDeployToUS3 extends AbstractTaskPlugin { @TaskInput({ @@ -22,10 +22,10 @@ export class UCloudDeployToUS3 extends AbstractTaskPlugin { helper: "请选择前置任务输出的域名证书", component: { name: "output-selector", - from: [...CertApplyPluginNames] - } + from: [...CertApplyPluginNames], + }, }) - cert!: CertInfo ; + cert!: CertInfo; @TaskInput(createCertDomainGetterInputDefine({ props: { required: false } })) certDomains!: string[]; @@ -34,9 +34,9 @@ export class UCloudDeployToUS3 extends AbstractTaskPlugin { title: "UCloud授权", component: { name: "access-selector", - type: "ucloud" + type: "ucloud", }, - required: true + required: true, }) accessId!: string; @@ -44,7 +44,7 @@ export class UCloudDeployToUS3 extends AbstractTaskPlugin { createRemoteSelectInputDefine({ title: "存储桶", helper: "要更新的UCloud存储桶", - action: UCloudDeployToUS3.prototype.onGetBucketList.name + action: UCloudDeployToUS3.prototype.onGetBucketList.name, }) ) bucket!: string; @@ -53,17 +53,16 @@ export class UCloudDeployToUS3 extends AbstractTaskPlugin { createRemoteSelectInputDefine({ title: "域名列表", helper: "要更新的UCloud域名列表", - action: UCloudDeployToUS3.prototype.onGetDomainList.name + action: UCloudDeployToUS3.prototype.onGetDomainList.name, }) ) domainList!: string[]; - async onInstance() { - } + async onInstance() {} async execute(): Promise { const access = await this.getAccess(this.accessId); - let certName = this.appendTimeSuffix("certd") + const certName = this.appendTimeSuffix("certd"); let cert: CertInfo; for (const domain of this.domainList) { @@ -73,7 +72,7 @@ export class UCloudDeployToUS3 extends AbstractTaskPlugin { bucket: this.bucket, domain: domain, cert: cert, - certName: certName + certName: certName, }); this.logger.info(`----------- 更新存储桶${this.bucket}的域名${domain}证书成功`); } @@ -81,17 +80,17 @@ export class UCloudDeployToUS3 extends AbstractTaskPlugin { this.logger.info("部署完成"); } - async deployToUS3(req: { access: any, bucket: string, domain: string, cert: CertInfo, certName: string }) { - const { access, bucket, domain, cert, certName } = req + async deployToUS3(req: { access: any; bucket: string; domain: string; cert: CertInfo; certName: string }) { + const { access, bucket, domain, cert, certName } = req; const body: any = { - "Action": "UpdateUFileSSLCert", - "BucketName": bucket, - "Domain": domain, - "CertificateName": certName, - "Certificate": cert.crt, - "CertificateKey": cert.key - } + Action: "UpdateUFileSSLCert", + BucketName: bucket, + Domain: domain, + CertificateName: certName, + Certificate: cert.crt, + CertificateKey: cert.key, + }; this.logger.info(`----------- 更新对象存储SSL证书${bucket}:${domain},${JSON.stringify(body)}`); const resp = await access.invoke(body); @@ -103,20 +102,20 @@ export class UCloudDeployToUS3 extends AbstractTaskPlugin { const pageNo = req.pageNo ?? 1; const pageSize = req.pageSize ?? 100; - + try { const resp = await access.invoke({ - "Action": "DescribeBucket", - "ProjectId": access.projectId, - "Offset": (pageNo - 1) * pageSize, - "Limit": pageSize + Action: "DescribeBucket", + ProjectId: access.projectId, + Offset: (pageNo - 1) * pageSize, + Limit: pageSize, }); this.logger.info(`获取到存储桶列表:${JSON.stringify(resp)}`); - + const buckets = resp.DataSet || []; const total = buckets.length; - + if (!buckets || buckets.length === 0) { throw new Error("没有找到存储桶,请先在控制台创建存储桶"); } @@ -125,15 +124,15 @@ export class UCloudDeployToUS3 extends AbstractTaskPlugin { return { label: `${item.BucketName}<${item.Region}>`, value: `${item.BucketName}`, - bucket: item.BucketName + bucket: item.BucketName, }; }); - + return { list: this.ctx.utils.options.buildGroupOptions(options, this.certDomains), total: total, pageNo: pageNo, - pageSize: pageSize + pageSize: pageSize, }; } catch (err) { this.logger.error(`获取存储桶列表失败:${err}`); @@ -143,35 +142,30 @@ export class UCloudDeployToUS3 extends AbstractTaskPlugin { async onGetDomainList(req: PageSearch = {}) { const access = await this.getAccess(this.accessId); - + if (!this.bucket) { throw new Error("请先选择存储桶"); } - + try { const resp = await access.invoke({ - "Action": "DescribeBucket", - "ProjectId": access.projectId, - "BucketName": this.bucket + Action: "DescribeBucket", + ProjectId: access.projectId, + BucketName: this.bucket, }); this.logger.info(`获取到存储桶域名列表:${JSON.stringify(resp)}`); - + const buckets = resp.DataSet || []; if (!buckets || buckets.length === 0) { throw new Error(`没有找到存储桶${this.bucket}`); } - + const bucketInfo = buckets[0]; const domainSet = bucketInfo.Domain || {}; - - const allDomains = [ - ...(domainSet.Src || []), - ...(domainSet.Cdn || []), - ...(domainSet.CustomSrc || []), - ...(domainSet.CustomCdn || []) - ]; - + + const allDomains = [...(domainSet.Src || []), ...(domainSet.Cdn || []), ...(domainSet.CustomSrc || []), ...(domainSet.CustomCdn || [])]; + if (!allDomains || allDomains.length === 0) { throw new Error(`没有找到存储桶${this.bucket}的域名,请先在控制台为存储桶添加域名`); } @@ -180,15 +174,15 @@ export class UCloudDeployToUS3 extends AbstractTaskPlugin { return { label: domain, value: domain, - domain: domain + domain: domain, }; }); - + return { list: this.ctx.utils.options.buildGroupOptions(options, this.certDomains), total: allDomains.length, pageNo: 1, - pageSize: allDomains.length + pageSize: allDomains.length, }; } catch (err) { this.logger.error(`获取存储桶域名列表失败:${err}`); diff --git a/packages/ui/certd-server/src/plugins/plugin-ucloud/plugins/plugin-deploy-to-waf.ts b/packages/ui/certd-server/src/plugins/plugin-ucloud/plugins/plugin-deploy-to-waf.ts index e431b58ae..41e0c6302 100644 --- a/packages/ui/certd-server/src/plugins/plugin-ucloud/plugins/plugin-deploy-to-waf.ts +++ b/packages/ui/certd-server/src/plugins/plugin-ucloud/plugins/plugin-deploy-to-waf.ts @@ -15,9 +15,9 @@ import { UCloudAccess } from "../access.js"; default: { //默认值配置照抄即可 strategy: { - runStrategy: RunStrategy.SkipWhenSucceed - } - } + runStrategy: RunStrategy.SkipWhenSucceed, + }, + }, }) //类名规范,跟上面插件名称(name)一致 export class UCloudDeployToWaf extends AbstractTaskPlugin { @@ -27,11 +27,11 @@ export class UCloudDeployToWaf extends AbstractTaskPlugin { helper: "请选择前置任务输出的域名证书", component: { name: "output-selector", - from: [...CertApplyPluginNames] - } + from: [...CertApplyPluginNames], + }, // required: true, // 必填 }) - cert!: CertInfo ; + cert!: CertInfo; @TaskInput(createCertDomainGetterInputDefine({ props: { required: false } })) certDomains!: string[]; @@ -41,9 +41,9 @@ export class UCloudDeployToWaf extends AbstractTaskPlugin { title: "UCloud授权", component: { name: "access-selector", - type: "ucloud" //固定授权类型 + type: "ucloud", //固定授权类型 }, - required: true //必填 + required: true, //必填 }) accessId!: string; // @@ -53,14 +53,13 @@ export class UCloudDeployToWaf extends AbstractTaskPlugin { title: "域名列表", helper: "要更新的UCloud域名列表", - action: UCloudDeployToWaf.prototype.onGetDomainList.name + action: UCloudDeployToWaf.prototype.onGetDomainList.name, }) ) domainList!: string[]; //插件实例化时执行的方法 - async onInstance() { - } + async onInstance() {} //插件执行方法 async execute(): Promise { @@ -68,7 +67,7 @@ export class UCloudDeployToWaf extends AbstractTaskPlugin { const res = await this.addWafDomainCertificateInfo({ access: access, - cert: this.cert + cert: this.cert, }); this.logger.info(`----------- 上传证书成功:${JSON.stringify(res)}`); const certId = res.Id; @@ -76,47 +75,43 @@ export class UCloudDeployToWaf extends AbstractTaskPlugin { for (const item of this.domainList) { this.logger.info(`----------- 开始更新域名:${item}`); - const domainInfo =await access.WafSiteList({ + const domainInfo = await access.WafSiteList({ PageNo: 1, PageSize: 10, - FullDomain: item - }) - const list = domainInfo.DomainHostList || [] - if(!list || list.length === 0){ - throw new Error(`没有找到WAF域名${item}`) + FullDomain: item, + }); + const list = domainInfo.DomainHostList || []; + if (!list || list.length === 0) { + throw new Error(`没有找到WAF域名${item}`); } - const oldDomainInfo = list[0] as any + const oldDomainInfo = list[0] as any; - - const srcIpList = oldDomainInfo.SrcIPInfo.map((item: any) => item.SrcIP) + const srcIpList = oldDomainInfo.SrcIPInfo.map((item: any) => item.SrcIP); await access.invoke({ - "Action": "UpdateWafDomainHostInfo", - "ProjectId": access.projectId, - "WorkRegions": oldDomainInfo.WorkRegions, - "FullDomain": item, - "CertificateID": certId , - "SrcIP":srcIpList - }) - + Action: "UpdateWafDomainHostInfo", + ProjectId: access.projectId, + WorkRegions: oldDomainInfo.WorkRegions, + FullDomain: item, + CertificateID: certId, + SrcIP: srcIpList, + }); + this.logger.info(`----------- 更新域名证书${item}成功`); } this.logger.info("部署完成"); } - async onGetDomainList(req: PageSearch = {}) { const access = await this.getAccess(this.accessId); const pageNo = req.pageNo ?? 1; const pageSize = req.pageSize ?? 100; - const res = await access.WafSiteList( - { - PageNo: pageNo, - PageSize: pageSize - } - ); + const res = await access.WafSiteList({ + PageNo: pageNo, + PageSize: pageSize, + }); const total = res.TotalCount; const list = res.DomainHostList || []; if (!list || list.length === 0) { @@ -131,28 +126,26 @@ export class UCloudDeployToWaf extends AbstractTaskPlugin { return { label: `${item.FullDomain}<${item.RecordId}>`, value: `${item.FullDomain}`, - domain: item.FullDomain + domain: item.FullDomain, }; }); return { list: this.ctx.utils.options.buildGroupOptions(options, this.certDomains), total: total, pageNo: pageNo, - pageSize: pageSize + pageSize: pageSize, }; } - async addWafDomainCertificateInfo(req: { access: UCloudAccess, cert: CertInfo }) { - - const certReader = new CertReader(req.cert) - const certName = certReader.buildCertName() - const crtBase64 = this.ctx.utils.hash.base64(req.cert.crt) - const keyBase64 = this.ctx.utils.hash.base64(req.cert.key) - const allDomains = certReader.getAllDomains().join(",") - + async addWafDomainCertificateInfo(req: { access: UCloudAccess; cert: CertInfo }) { + const certReader = new CertReader(req.cert); + const certName = certReader.buildCertName(); + const crtBase64 = this.ctx.utils.hash.base64(req.cert.crt); + const keyBase64 = this.ctx.utils.hash.base64(req.cert.key); + const allDomains = certReader.getAllDomains().join(","); const resp = await req.access.invoke({ - "Action": "AddWafDomainCertificateInfo", + Action: "AddWafDomainCertificateInfo", /** * Domain string 域名 Yes CertificateName string 证书名称 Yes @@ -161,17 +154,16 @@ export class UCloudDeployToWaf extends AbstractTaskPlugin { SslKeyless string keyless开关,默认关闭;可选值:开启(on),关闭(off) Yes */ - "Domain": allDomains, - "CertificateName": certName, - "SslPublicKey": crtBase64, - "SslPrivateKey": keyBase64, - "SslMD": this.ctx.utils.hash.md5(crtBase64), - "SslKeyless": "off" + Domain: allDomains, + CertificateName: certName, + SslPublicKey: crtBase64, + SslPrivateKey: keyBase64, + SslMD: this.ctx.utils.hash.md5(crtBase64), + SslKeyless: "off", }); this.ctx.logger.info(`----------- 添加WAF域名证书信息成功,${JSON.stringify(resp)}`); return resp; } - } //实例化一下,注册插件 diff --git a/packages/ui/certd-server/src/plugins/plugin-ucloud/plugins/plugin-upload-to-ussl.ts b/packages/ui/certd-server/src/plugins/plugin-ucloud/plugins/plugin-upload-to-ussl.ts index 60f7c6369..46273272a 100644 --- a/packages/ui/certd-server/src/plugins/plugin-ucloud/plugins/plugin-upload-to-ussl.ts +++ b/packages/ui/certd-server/src/plugins/plugin-ucloud/plugins/plugin-upload-to-ussl.ts @@ -14,9 +14,9 @@ import { UCloudAccess } from "../access.js"; default: { //默认值配置照抄即可 strategy: { - runStrategy: RunStrategy.SkipWhenSucceed - } - } + runStrategy: RunStrategy.SkipWhenSucceed, + }, + }, }) //类名规范,跟上面插件名称(name)一致 export class UCloudUploadToUSSL extends AbstractTaskPlugin { @@ -26,22 +26,20 @@ export class UCloudUploadToUSSL extends AbstractTaskPlugin { helper: "请选择前置任务输出的域名证书", component: { name: "output-selector", - from: [...CertApplyPluginNames] - } + from: [...CertApplyPluginNames], + }, // required: true, // 必填 }) cert!: CertInfo; - - //授权选择框 @TaskInput({ title: "UCloud授权", component: { name: "access-selector", - type: "ucloud" //固定授权类型 + type: "ucloud", //固定授权类型 }, - required: true //必填 + required: true, //必填 }) accessId!: string; // @@ -50,23 +48,18 @@ export class UCloudUploadToUSSL extends AbstractTaskPlugin { title: "证书ID", type: "UCloudCertId", }) - certId!: {type:string,id:number,name:string}; - + certId!: { type: string; id: number; name: string }; //插件实例化时执行的方法 - async onInstance() { - } + async onInstance() {} //插件执行方法 async execute(): Promise { const access = await this.getAccess(this.accessId); - const certId = await access.SslUploadCert({cert:this.cert}); + const certId = await access.SslUploadCert({ cert: this.cert }); this.certId = certId; this.logger.info("部署完成"); } - - - } //实例化一下,注册插件 diff --git a/packages/ui/certd-server/src/plugins/plugin-upyun/access.ts b/packages/ui/certd-server/src/plugins/plugin-upyun/access.ts index 1878b3933..720fa6da4 100644 --- a/packages/ui/certd-server/src/plugins/plugin-upyun/access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-upyun/access.ts @@ -1,36 +1,34 @@ -import { AccessInput, BaseAccess, IsAccess } from '@certd/pipeline'; -import { UpyunClient } from './client.js'; +import { AccessInput, BaseAccess, IsAccess } from "@certd/pipeline"; +import { UpyunClient } from "./client.js"; /** * 这个注解将注册一个授权配置 * 在certd的后台管理系统中,用户可以选择添加此类型的授权 */ @IsAccess({ - name: 'upyun', - title: '又拍云', - desc: '', - icon: 'svg:icon-upyun', + name: "upyun", + title: "又拍云", + desc: "", + icon: "svg:icon-upyun", }) export class UpyunAccess extends BaseAccess { - @AccessInput({ - title: '账号', + title: "账号", component: { - placeholder: '又拍云账号', + placeholder: "又拍云账号", }, required: true, }) - username = ''; + username = ""; @AccessInput({ - title: '密码', + title: "密码", component: { - placeholder: '又拍云密码', + placeholder: "又拍云密码", }, required: true, encrypt: true, }) - password = ''; - + password = ""; @AccessInput({ title: "测试", @@ -47,24 +45,22 @@ export class UpyunAccess extends BaseAccess { return "ok"; } - async getCdnList() { const upyunClient = new UpyunClient({ access: this, logger: this.ctx.logger, - http: this.ctx.http + http: this.ctx.http, }); const cookie = await upyunClient.getLoginToken(); const req = { cookie, url: "https://console.upyun.com/api/account/domains/?limit=1000&business_type=file&security_cdn=false&websocket=false&key=&domain=", method: "GET", - data: {} + data: {}, }; const res = await upyunClient.doRequest(req); const domains = res.data?.domains || []; - return domains - + return domains; } } diff --git a/packages/ui/certd-server/src/plugins/plugin-upyun/client.ts b/packages/ui/certd-server/src/plugins/plugin-upyun/client.ts index 5d33c1811..88595d28b 100644 --- a/packages/ui/certd-server/src/plugins/plugin-upyun/client.ts +++ b/packages/ui/certd-server/src/plugins/plugin-upyun/client.ts @@ -3,10 +3,10 @@ import { HttpClient, ILogger } from "@certd/basic"; import { CertInfo } from "@certd/plugin-cert"; export type UpyunClientOptions = { - access: UpyunAccess + access: UpyunAccess; logger: ILogger; - http: HttpClient -} + http: HttpClient; +}; export class UpyunClient { opts: UpyunClientOptions; @@ -15,7 +15,7 @@ export class UpyunClient { this.opts = opts; } - async uploadCert(cookie: string,cert:CertInfo) { + async uploadCert(cookie: string, cert: CertInfo) { // https://console.upyun.com/api/https/certificate/ const res = await this.doRequest({ cookie: cookie, @@ -23,8 +23,8 @@ export class UpyunClient { method: "POST", data: { certificate: cert.crt, - private_key: cert.key - } + private_key: cert.key, + }, }); if (!res.data?.result) { throw new Error("upload cert failed: " + JSON.stringify(res.data)); @@ -34,51 +34,45 @@ export class UpyunClient { } async getLoginToken() { - const access = this.opts.access + const access = this.opts.access; const http = this.opts.http; const res = await http.request({ url: "https://console.upyun.com/accounts/signin/", method: "POST", data: { username: access.username, - password: access.password + password: access.password, }, logRes: false, - returnOriginRes: true + returnOriginRes: true, }); - if (res.data?.errors?.length > 0 ) { + if (res.data?.errors?.length > 0) { throw new Error(JSON.stringify(res.data.msg)); } - if (res.data?.data?.error_code ) { - throw new Error( "登录失败:"+res.data.data.message); + if (res.data?.data?.error_code) { + throw new Error("登录失败:" + res.data.data.message); } const cookie = res.headers["set-cookie"]; return cookie; } - async doRequest(req: { - cookie: string, - url: string, - method: string, - data: any - }) { - + async doRequest(req: { cookie: string; url: string; method: string; data: any }) { const res = await this.opts.http.request({ url: req.url, method: req.method, data: req.data, headers: { - Cookie: req.cookie - } + Cookie: req.cookie, + }, }); let errorMessage = null; if (res.msg?.errors?.length > 0) { errorMessage = JSON.stringify(res.msg); } - if(res.data?.error_code){ + if (res.data?.error_code) { errorMessage = res.data?.message; } - if(errorMessage){ + if (errorMessage) { if (errorMessage.includes("domain has been bound to this certificate")) { return res; } @@ -86,5 +80,4 @@ export class UpyunClient { } return res; } - } diff --git a/packages/ui/certd-server/src/plugins/plugin-upyun/index.ts b/packages/ui/certd-server/src/plugins/plugin-upyun/index.ts index a5edb84e0..09ca4f9f1 100644 --- a/packages/ui/certd-server/src/plugins/plugin-upyun/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-upyun/index.ts @@ -1,3 +1,3 @@ -export * from './plugins/index.js'; -export * from './access.js'; -export * from './client.js'; +export * from "./plugins/index.js"; +export * from "./access.js"; +export * from "./client.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-upyun/plugins/index.ts b/packages/ui/certd-server/src/plugins/plugin-upyun/plugins/index.ts index 50deb7242..6999b0c38 100644 --- a/packages/ui/certd-server/src/plugins/plugin-upyun/plugins/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-upyun/plugins/index.ts @@ -1 +1 @@ -export * from './plugin-depoy-to-cdn.js'; +export * from "./plugin-depoy-to-cdn.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-upyun/plugins/plugin-depoy-to-cdn.ts b/packages/ui/certd-server/src/plugins/plugin-upyun/plugins/plugin-depoy-to-cdn.ts index 4bea3c4e4..1fae44ac9 100644 --- a/packages/ui/certd-server/src/plugins/plugin-upyun/plugins/plugin-depoy-to-cdn.ts +++ b/packages/ui/certd-server/src/plugins/plugin-upyun/plugins/plugin-depoy-to-cdn.ts @@ -10,16 +10,16 @@ import { UpyunClient } from "../client.js"; name: "UpyunDeployToCdn", title: "又拍云-部署证书到CDN/USS", icon: "svg:icon-upyun", - desc:"支持又拍云CDN,又拍云云存储USS", + desc: "支持又拍云CDN,又拍云云存储USS", //插件分组 group: pluginGroups.cdn.key, needPlus: false, default: { //默认值配置照抄即可 strategy: { - runStrategy: RunStrategy.SkipWhenSucceed - } - } + runStrategy: RunStrategy.SkipWhenSucceed, + }, + }, }) //类名规范,跟上面插件名称(name)一致 export class UpyunDeployToCdn extends AbstractTaskPlugin { @@ -29,8 +29,8 @@ export class UpyunDeployToCdn extends AbstractTaskPlugin { helper: "请选择前置任务输出的域名证书", component: { name: "output-selector", - from: [...CertApplyPluginNames] - } + from: [...CertApplyPluginNames], + }, // required: true, // 必填 }) cert!: CertInfo; @@ -42,60 +42,58 @@ export class UpyunDeployToCdn extends AbstractTaskPlugin { title: "Upyun授权", component: { name: "access-selector", - type: "upyun" //固定授权类型 + type: "upyun", //固定授权类型 }, - required: true //必填 + required: true, //必填 }) accessId!: string; // - @TaskInput( createRemoteSelectInputDefine({ title: "加速域名", helper: "选择加速域名,可以手动输入", typeName: "UpyunDeployToCdn", action: UpyunDeployToCdn.prototype.onGetCdnList.name, - watches: ["accessId"] + watches: ["accessId"], }) ) cdnList!: string[]; @TaskInput({ title: "强制HTTPS", - value:"keep", + value: "keep", component: { name: "a-select", - vModel:"value", - options:[ - {value:"true","label":"强制HTTPS"}, - {value:"false","label":"不强制HTTPS"}, - {value:"keep","label":"保持原样"} - ] + vModel: "value", + options: [ + { value: "true", label: "强制HTTPS" }, + { value: "false", label: "不强制HTTPS" }, + { value: "keep", label: "保持原样" }, + ], }, - required: true //必填 + required: true, //必填 }) forceHttps!: string; @TaskInput({ title: "开启HTTPS", - value:"true", + value: "true", component: { name: "a-select", - vModel:"value", - options:[ - {value:"true","label":"开启HTTPS"}, - {value:"false","label":"关闭HTTPS"}, - {value:"keep","label":"保持原样"} - ] + vModel: "value", + options: [ + { value: "true", label: "开启HTTPS" }, + { value: "false", label: "关闭HTTPS" }, + { value: "keep", label: "保持原样" }, + ], }, - required: true //必填 + required: true, //必填 }) https!: string; //插件实例化时执行的方法 - async onInstance() { - } + async onInstance() {} //插件执行方法 async execute(): Promise { @@ -104,39 +102,38 @@ export class UpyunDeployToCdn extends AbstractTaskPlugin { const upyunClient = new UpyunClient({ access, logger: this.logger, - http: this.ctx.http + http: this.ctx.http, }); const cookie = await upyunClient.getLoginToken(); this.logger.info(`登录成功`); const certId = await upyunClient.uploadCert(cookie, this.cert); this.logger.info(`上传证书成功:${certId}`); for (const item of this.cdnList) { - this.logger.info(`开始部署证书:${item}`); - const data1 :any= { + const data1: any = { crt_id: certId, domain_name: item, - } + }; - const res1=await upyunClient.doRequest({ + const res1 = await upyunClient.doRequest({ cookie: cookie, url: "https://console.upyun.com/api/https/migrate/domain", method: "POST", - data: data1 + data: data1, }); this.logger.info(`设置证书成功:${JSON.stringify(res1)}`); - const data2 :any= { + const data2: any = { certificate_id: certId, domain: item, - } + }; - if (this.forceHttps !== 'keep') { + if (this.forceHttps !== "keep") { data2.force_https = Boolean(this.forceHttps); } - if (this.https !=='keep') { + if (this.https !== "keep") { data2.https = Boolean(this.https); } @@ -145,7 +142,7 @@ export class UpyunDeployToCdn extends AbstractTaskPlugin { cookie: cookie, url: "https://console.upyun.com/api/https/certificate/manager", method: "POST", - data: data2 + data: data2, }); this.logger.info(`设置证书参数成功:${JSON.stringify(res2)}`); } @@ -153,7 +150,6 @@ export class UpyunDeployToCdn extends AbstractTaskPlugin { this.logger.info("部署成功"); } - async onGetCdnList() { if (!this.accessId) { throw new Error("accessId不能为空"); @@ -168,7 +164,7 @@ export class UpyunDeployToCdn extends AbstractTaskPlugin { for (const domain of domains) { list.push({ domain: domain.domain, - bucket: domain.bucket_name + bucket: domain.bucket_name, }); } @@ -176,12 +172,10 @@ export class UpyunDeployToCdn extends AbstractTaskPlugin { return { value: item.domain, label: `${item.domain}<${item.bucket}>`, - domain: item.domain + domain: item.domain, }; }); return optionsUtils.buildGroupOptions(options, this.certDomains); - - } } diff --git a/packages/ui/certd-server/src/plugins/plugin-volcengine/access.ts b/packages/ui/certd-server/src/plugins/plugin-volcengine/access.ts index d66d45742..8c1a3ae96 100644 --- a/packages/ui/certd-server/src/plugins/plugin-volcengine/access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-volcengine/access.ts @@ -1,38 +1,36 @@ -import { AccessInput, BaseAccess, IsAccess } from '@certd/pipeline'; -import { VolcengineClient } from './ve-client.js'; +import { AccessInput, BaseAccess, IsAccess } from "@certd/pipeline"; +import { VolcengineClient } from "./ve-client.js"; /** * 这个注解将注册一个授权配置 * 在certd的后台管理系统中,用户可以选择添加此类型的授权 */ @IsAccess({ - name: 'volcengine', - title: '火山引擎', - desc: '', - icon: 'svg:icon-volcengine', + name: "volcengine", + title: "火山引擎", + desc: "", + icon: "svg:icon-volcengine", order: 1, }) export class VolcengineAccess extends BaseAccess { - @AccessInput({ - title: 'AccessKeyID', + title: "AccessKeyID", component: { - placeholder: 'AccessKeyID', + placeholder: "AccessKeyID", }, helper: "[获取密钥](https://console.volcengine.com/iam/keymanage/)", required: true, }) - accessKeyId = ''; + accessKeyId = ""; @AccessInput({ - title: 'SecretAccessKey', + title: "SecretAccessKey", component: { - placeholder: 'SecretAccessKey', + placeholder: "SecretAccessKey", }, required: true, encrypt: true, }) - secretAccessKey = ''; - + secretAccessKey = ""; @AccessInput({ title: "测试", @@ -71,12 +69,9 @@ export class VolcengineAccess extends BaseAccess { valid: true, accountId: result.AccountId, arn: result.Trn, - userId: result.IdentityId + userId: result.IdentityId, }; - } - - } new VolcengineAccess(); diff --git a/packages/ui/certd-server/src/plugins/plugin-volcengine/cdn-client.ts b/packages/ui/certd-server/src/plugins/plugin-volcengine/cdn-client.ts index 93c80c386..5e3b2f4d1 100644 --- a/packages/ui/certd-server/src/plugins/plugin-volcengine/cdn-client.ts +++ b/packages/ui/certd-server/src/plugins/plugin-volcengine/cdn-client.ts @@ -10,7 +10,6 @@ export class VolcengineCdnClient { this.opts = opts; } - async getCdnClient() { if (this.service) { return this.service; @@ -34,15 +33,15 @@ export class VolcengineCdnClient { PrivateKey: cert.key, EncryType: "inter_cert", Repeatable: false, - Desc: certName + Desc: certName, }); if (res.ResponseMetadata?.Error) { if (res.ResponseMetadata?.Error?.Code?.includes("Duplicated")) { // 证书已存在,ID为 cert-16293a8524844a3e8e30ed62f8e5bc94。 - const message = res.ResponseMetadata?.Error?.Message + const message = res.ResponseMetadata?.Error?.Message; const reg = /ID为 (\S+)。/; - const certId = message.match(reg)?.[1] + const certId = message.match(reg)?.[1]; if (certId) { this.opts.logger.info(`证书已存在,ID为 ${certId}`); return certId; @@ -51,10 +50,8 @@ export class VolcengineCdnClient { throw new Error(JSON.stringify(res.ResponseMetadata?.Error)); } - const certId = res.Result.CertId - this.opts.logger.info(`上传证书成功:${certId}`) + const certId = res.Result.CertId; + this.opts.logger.info(`上传证书成功:${certId}`); return certId; - - } } diff --git a/packages/ui/certd-server/src/plugins/plugin-volcengine/dns-client.ts b/packages/ui/certd-server/src/plugins/plugin-volcengine/dns-client.ts index c6349c646..f99fb694e 100644 --- a/packages/ui/certd-server/src/plugins/plugin-volcengine/dns-client.ts +++ b/packages/ui/certd-server/src/plugins/plugin-volcengine/dns-client.ts @@ -1,18 +1,17 @@ -import {http} from "@certd/basic"; +import { http } from "@certd/basic"; import querystring from "querystring"; -import {VolcengineOpts} from "./ve-client.js"; +import { VolcengineOpts } from "./ve-client.js"; import { Pager, PageSearch } from "@certd/pipeline"; - export type VolcengineReq = { method?: string; path?: string; headers?: any; body?: any; query?: any; - service?: string, // 替换为实际服务名称 - region?: string, // 替换为实际区域名称 -} + service?: string; // 替换为实际服务名称 + region?: string; // 替换为实际区域名称 +}; export class VolcengineDnsClient { opts: VolcengineOpts; @@ -21,11 +20,10 @@ export class VolcengineDnsClient { this.opts = opts; } - async doRequest(req: VolcengineReq) { - const {Signer} =await import('@volcengine/openapi') ; + const { Signer } = await import("@volcengine/openapi"); -// http request data + // http request data const openApiRequestData: any = { region: req.region, method: req.method, @@ -39,47 +37,42 @@ export class VolcengineDnsClient { }, // [optional] http request body body: req.body, - } + }; const signer = new Signer(openApiRequestData, req.service); -// sign - signer.addAuthorization({accessKeyId:this.opts.access.accessKeyId, secretKey:this.opts.access.secretAccessKey}); + // sign + signer.addAuthorization({ accessKeyId: this.opts.access.accessKeyId, secretKey: this.opts.access.secretAccessKey }); -// Print signed headers + // Print signed headers console.log(openApiRequestData.headers); + const url = `https://open.volcengineapi.com/?${querystring.stringify(req.query)}`; - const url = `https://open.volcengineapi.com/?${querystring.stringify(req.query)}` - - try{ + try { const res = await http.request({ url: url, method: req.method, headers: openApiRequestData.headers, - data:req.body + data: req.body, }); if (res?.ResponseMetadata?.Error) { const err = new Error(JSON.stringify(res.ResponseMetadata.Error)); // @ts-ignore err.detail = res.ResponseMetadata.Error; - throw err + throw err; } - return res - }catch (e) { - if(e.response){ + return res; + } catch (e) { + if (e.response) { const err = new Error(JSON.stringify(e.response.data.ResponseMetadata.Error)); // @ts-ignore err.detail = e.response.data.ResponseMetadata.Error; - throw err + throw err; } } - - - } - async findDomain(domain: string) { const req: VolcengineReq = { method: "POST", @@ -89,24 +82,24 @@ export class VolcengineDnsClient { Action: "ListZones", Version: "2018-08-01", }, - body:{ + body: { Key: domain, - SearchMode: "exact" - } + SearchMode: "exact", + }, }; return this.doRequest(req); } - async getDomainList(page: PageSearch) { - const pager = new Pager(page) - const body:any = { - SearchMode: "like", - PageNumber: pager.pageNo, - PageSize: pager.pageSize, - } + async getDomainList(page: PageSearch) { + const pager = new Pager(page); + const body: any = { + SearchMode: "like", + PageNumber: pager.pageNo, + PageSize: pager.pageSize, + }; if (page.searchKey) { - body.Key = page.searchKey + body.Key = page.searchKey; } const req: VolcengineReq = { method: "POST", @@ -116,22 +109,21 @@ export class VolcengineDnsClient { Action: "ListZones", Version: "2018-08-01", }, - body:body + body: body, }; const res = await this.doRequest(req); - let list = res.Result?.Zones || [] - list = list.map((item:any) => { + let list = res.Result?.Zones || []; + list = list.map((item: any) => { return { id: item.ZID, domain: item.ZoneName, - } - }) - const total = res.Result?.Total|| list.length + }; + }); + const total = res.Result?.Total || list.length; return { list, - total - } + total, + }; } } - diff --git a/packages/ui/certd-server/src/plugins/plugin-volcengine/index.ts b/packages/ui/certd-server/src/plugins/plugin-volcengine/index.ts index 04bb40478..e3584b629 100644 --- a/packages/ui/certd-server/src/plugins/plugin-volcengine/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-volcengine/index.ts @@ -1,6 +1,6 @@ -export * from './plugins/index.js'; -export * from './access.js'; -export * from './volcengine-dns-provider.js'; -export * from './ve-client.js'; -export * from './dns-client.js'; -export * from './cdn-client.js'; +export * from "./plugins/index.js"; +export * from "./access.js"; +export * from "./volcengine-dns-provider.js"; +export * from "./ve-client.js"; +export * from "./dns-client.js"; +export * from "./cdn-client.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/index.ts b/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/index.ts index a521132a2..fec482fec 100644 --- a/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/index.ts @@ -1,9 +1,9 @@ -export * from './plugin-deploy-to-cdn.js' -export * from './plugin-deploy-to-clb.js' -export * from './plugin-upload-to-cert-center.js' -export * from './plugin-deploy-to-alb.js' -export * from './plugin-deploy-to-live.js' -export * from './plugin-deploy-to-dcdn.js' -export * from './plugin-deploy-to-vod.js' -export * from './plugin-deploy-to-tos.js' -export * from './plugin-deploy-to-vke.js' +export * from "./plugin-deploy-to-cdn.js"; +export * from "./plugin-deploy-to-clb.js"; +export * from "./plugin-upload-to-cert-center.js"; +export * from "./plugin-deploy-to-alb.js"; +export * from "./plugin-deploy-to-live.js"; +export * from "./plugin-deploy-to-dcdn.js"; +export * from "./plugin-deploy-to-vod.js"; +export * from "./plugin-deploy-to-tos.js"; +export * from "./plugin-deploy-to-vke.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-alb.ts b/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-alb.ts index 0329d71b5..81181164c 100644 --- a/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-alb.ts +++ b/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-alb.ts @@ -13,9 +13,9 @@ import dayjs from "dayjs"; desc: "部署至火山引擎应用负载均衡", default: { strategy: { - runStrategy: RunStrategy.SkipWhenSucceed - } - } + runStrategy: RunStrategy.SkipWhenSucceed, + }, + }, }) export class VolcengineDeployToALB extends AbstractTaskPlugin { @TaskInput({ @@ -23,25 +23,23 @@ export class VolcengineDeployToALB extends AbstractTaskPlugin { helper: "请选择前置任务输出的域名证书", component: { name: "output-selector", - from: [...CertApplyPluginNames, "VolcengineUploadToCertCenter"] + from: [...CertApplyPluginNames, "VolcengineUploadToCertCenter"], }, - required: true + required: true, }) cert!: CertInfo | string; @TaskInput(createCertDomainGetterInputDefine({ props: { required: false } })) certDomains!: string[]; - - @TaskInput({ title: "Access授权", helper: "火山引擎AccessKeyId、AccessKeySecret", component: { name: "access-selector", - type: "volcengine" + type: "volcengine", }, - required: true + required: true, }) accessId!: string; @@ -106,28 +104,25 @@ export class VolcengineDeployToALB extends AbstractTaskPlugin { { label: "广州", value: "cn-guangzhou" }, { label: "香港", value: "cn-hongkong" }, { label: "柔佛", value: "ap-southeast-1" }, - { label: "雅加达", value: "ap-southeast-3" } - - ] + { label: "雅加达", value: "ap-southeast-3" }, + ], }, value: "cn-beijing", - required: true + required: true, }) regionId!: string; - @TaskInput( createRemoteSelectInputDefine({ title: "监听器列表", helper: "选择要部署证书的监听器\n需要在监听器中选择证书中心,进行跨服务访问授权", action: VolcengineDeployToALB.prototype.onGetListenerList.name, watches: ["certDomains", "accessId", "regionId"], - required: true + required: true, }) ) listenerList!: string | string[]; - @TaskInput({ title: "证书部署类型", helper: "选择部署默认证书还是扩展证书", @@ -135,17 +130,15 @@ export class VolcengineDeployToALB extends AbstractTaskPlugin { name: "a-select", options: [ { label: "默认证书", value: "default" }, - { label: "扩展证书", value: "extension" } - ] + { label: "扩展证书", value: "extension" }, + ], }, value: "default", - required: true + required: true, }) certType!: string; - - async onInstance() { - } + async onInstance() {} async execute(): Promise { this.logger.info("开始部署证书到火山引擎ALB"); @@ -156,8 +149,8 @@ export class VolcengineDeployToALB extends AbstractTaskPlugin { const certInfo = this.cert as CertInfo; this.logger.info(`开始上传证书`); certId = await certService.ImportCertificate({ - certName:this.appendTimeSuffix("certd"), - cert:certInfo + certName: this.appendTimeSuffix("certd"), + cert: certInfo, }); this.logger.info(`上传证书成功:${certId}`); } else { @@ -174,8 +167,8 @@ export class VolcengineDeployToALB extends AbstractTaskPlugin { query: { ListenerId: listener, CertificateSource: "cert_center", - CertCenterCertificateId: certId - } + CertCenterCertificateId: certId, + }, }); this.logger.info(`部署监听器${listener}默认证书成功,res:${JSON.stringify(res)}`); } else { @@ -191,12 +184,12 @@ export class VolcengineDeployToALB extends AbstractTaskPlugin { private async deployExtensionCertificate(service: any, listenerId: string, certId: string) { // 获取监听器当前的扩展证书列表 const domainExtensions = await this.getListenerDomainExtensions(service, listenerId); - + // 删除过期的扩展证书 try { await this.deleteExpiredExtensions(service, listenerId, domainExtensions); } catch (error) { - this.logger.error(`删除过期扩展证书失败:${error.message ||error}`); + this.logger.error(`删除过期扩展证书失败:${error.message || error}`); } // 新增扩展证书 @@ -204,7 +197,7 @@ export class VolcengineDeployToALB extends AbstractTaskPlugin { ListenerId: listenerId, "DomainExtensions.1.Action": "create", "DomainExtensions.1.CertificateSource": "cert_center", - "DomainExtensions.1.CertCenterCertificateId": certId + "DomainExtensions.1.CertCenterCertificateId": certId, }; // 如果有证书域名信息,添加到扩展证书中 @@ -214,7 +207,7 @@ export class VolcengineDeployToALB extends AbstractTaskPlugin { await service.request({ action: "ModifyListenerAttributes", - query: query + query: query, }); this.logger.info(`部署监听器${listenerId}扩展证书成功`); } @@ -224,17 +217,17 @@ export class VolcengineDeployToALB extends AbstractTaskPlugin { action: "DescribeListenerAttributes", method: "GET", query: { - ListenerId: listenerId - } + ListenerId: listenerId, + }, }); - + return res.Result.DomainExtensions || []; } private async deleteExpiredExtensions(service: any, listenerId: string, domainExtensions: any[]) { const expiredExtensions = []; for (const ext of domainExtensions) { - if (!await this.isCertificateExpired(ext)) { + if (!(await this.isCertificateExpired(ext))) { expiredExtensions.push(ext); } } @@ -244,30 +237,29 @@ export class VolcengineDeployToALB extends AbstractTaskPlugin { } const query: any = { - ListenerId: listenerId + ListenerId: listenerId, }; expiredExtensions.forEach((ext, index) => { const idx = index + 1; query[`DomainExtensions.${idx}.Action`] = "delete"; query[`DomainExtensions.${idx}.DomainExtensionId`] = ext.DomainExtensionId; }); - + this.logger.info(`准备删除过期扩展证书,数量:${expiredExtensions.length}个,query:${JSON.stringify(query)}`); await service.request({ action: "ModifyListenerAttributes", - query: query + query: query, }); this.logger.info(`删除${expiredExtensions.length}个过期扩展证书成功`); - await this.ctx.utils.sleep(5000); + await this.ctx.utils.sleep(5000); } - private async getCertService(access: VolcengineAccess) { const client = new VolcengineClient({ logger: this.logger, access, - http: this.http + http: this.http, }); return await client.getCertCenterService(); @@ -279,11 +271,11 @@ export class VolcengineDeployToALB extends AbstractTaskPlugin { const client = new VolcengineClient({ logger: this.logger, access, - http: this.http + http: this.http, }); const service = await client.getAlbService({ - region: this.regionId + region: this.regionId, }); return service; } @@ -291,7 +283,7 @@ export class VolcengineDeployToALB extends AbstractTaskPlugin { private async isCertificateExpired(extension: any): Promise { try { let certificateId: string; - + // 根据证书来源获取证书ID if (extension.CertificateSource === "cert_center") { certificateId = extension.CertCenterCertificateId; @@ -305,19 +297,19 @@ export class VolcengineDeployToALB extends AbstractTaskPlugin { this.logger.warn(`未知的证书来源: ${extension.CertificateSource},跳过`); return false; } - + if (!certificateId) { this.logger.warn(`证书ID为空,跳过`); return false; } - + // 获取证书服务 const access = await this.getAccess(this.accessId); const certService = await this.getCertService(access); - + // 获取证书详情 const certDetail = await certService.GetCertificateDetail(certificateId); - + // 判断证书是否过期 if (certDetail.NotAfter) { const expireTime = dayjs(certDetail.NotAfter); @@ -328,7 +320,7 @@ export class VolcengineDeployToALB extends AbstractTaskPlugin { } return isExpired; } - + return false; } catch (error) { this.logger.error(`检查证书是否过期失败: ${error.message || error}`); @@ -347,7 +339,7 @@ export class VolcengineDeployToALB extends AbstractTaskPlugin { method: "GET", query: { PageSize: 100, - Protocol: "HTTPS" + Protocol: "HTTPS", }, }); @@ -358,7 +350,7 @@ export class VolcengineDeployToALB extends AbstractTaskPlugin { return list.map((item: any) => { return { value: item.ListenerId, - label: `${item.ListenerName}<${item.Description}:${item.ListenerId}>` + label: `${item.ListenerName}<${item.Description}:${item.ListenerId}>`, }; }); } diff --git a/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-cdn.ts b/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-cdn.ts index edac3338f..7ad386642 100644 --- a/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-cdn.ts +++ b/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-cdn.ts @@ -6,11 +6,11 @@ import { VolcengineAccess } from "../access.js"; import { VolcengineCdnClient } from "../cdn-client.js"; @IsTaskPlugin({ - name: 'VolcengineDeployToCDN', - title: '火山引擎-部署证书至CDN', - icon: 'svg:icon-volcengine', + name: "VolcengineDeployToCDN", + title: "火山引擎-部署证书至CDN", + icon: "svg:icon-volcengine", group: pluginGroups.volcengine.key, - desc: '支持网页,文件下载,音视频点播', + desc: "支持网页,文件下载,音视频点播", default: { strategy: { runStrategy: RunStrategy.SkipWhenSucceed, @@ -19,11 +19,11 @@ import { VolcengineCdnClient } from "../cdn-client.js"; }) export class VolcengineDeployToCDN extends AbstractTaskPlugin { @TaskInput({ - title: '域名证书', - helper: '请选择前置任务输出的域名证书', + title: "域名证书", + helper: "请选择前置任务输出的域名证书", component: { - name: 'output-selector', - from: [...CertApplyPluginNames, 'VolcengineUploadToCertCenter'], + name: "output-selector", + from: [...CertApplyPluginNames, "VolcengineUploadToCertCenter"], }, required: true, }) @@ -32,111 +32,105 @@ export class VolcengineDeployToCDN extends AbstractTaskPlugin { @TaskInput(createCertDomainGetterInputDefine({ props: { required: false } })) certDomains!: string[]; - @TaskInput({ - title: 'Access授权', - helper: '火山引擎AccessKeyId、AccessKeySecret', + title: "Access授权", + helper: "火山引擎AccessKeyId、AccessKeySecret", component: { - name: 'access-selector', - type: 'volcengine', + name: "access-selector", + type: "volcengine", }, required: true, }) accessId!: string; @TaskInput({ - title: '服务类型', - helper: '网页,文件下载,音视频点播', + title: "服务类型", + helper: "网页,文件下载,音视频点播", component: { - name: 'a-select', - options:[ + name: "a-select", + options: [ { label: "网页", value: "web" }, { label: "文件下载", value: "download" }, - { label: "音视频点播", value: 'video'}, - ] + { label: "音视频点播", value: "video" }, + ], }, - value: 'web', + value: "web", required: true, }) - serviceType:string = "web" - - - + serviceType = "web"; @TaskInput( createRemoteSelectInputDefine({ - title: 'CDN加速域名', - helper: '你在火山引擎上配置的CDN加速域名,比如:certd.docmirror.cn', + title: "CDN加速域名", + helper: "你在火山引擎上配置的CDN加速域名,比如:certd.docmirror.cn", action: VolcengineDeployToCDN.prototype.onGetDomainList.name, - watches: ['certDomains', 'accessId', 'serviceType'], + watches: ["certDomains", "accessId", "serviceType"], required: true, }) ) domainName!: string | string[]; - async onInstance() {} async execute(): Promise { - this.logger.info('开始部署证书到火山引擎CDN'); + this.logger.info("开始部署证书到火山引擎CDN"); const access = await this.getAccess(this.accessId); - const client = await this.getClient(access) - const service = await client.getCdnClient() + const client = await this.getClient(access); + const service = await client.getCdnClient(); if (!this.cert) { - throw new Error('你还未选择证书'); + throw new Error("你还未选择证书"); } - let certId = this.cert - if (typeof certId !== 'string') { - const certInfo = this.cert as CertInfo - this.logger.info(`开始上传证书`) - certId = await client.uploadCert(certInfo, this.appendTimeSuffix('certd')) + let certId = this.cert; + if (typeof certId !== "string") { + const certInfo = this.cert as CertInfo; + this.logger.info(`开始上传证书`); + certId = await client.uploadCert(certInfo, this.appendTimeSuffix("certd")); this.logger.info(`上传证书成功:${certId}`); - }else{ + } else { this.logger.info(`使用已有证书ID:${certId}`); } for (const domain of this.domainName) { - this.logger.info(`开始部署域名${domain}证书`) + this.logger.info(`开始部署域名${domain}证书`); await service.UpdateCdnConfig({ Domain: domain, HTTPS: { CertInfo: { CertId: certId as string }, Switch: true, - } - }) + }, + }); this.logger.info(`部署域名${domain}证书成功`); - await this.ctx.utils.sleep(1000) + await this.ctx.utils.sleep(1000); } - this.logger.info('部署完成'); + this.logger.info("部署完成"); } - async getClient(access: VolcengineAccess) { - return new VolcengineCdnClient({ + return new VolcengineCdnClient({ logger: this.logger, access, - http:this.http - }) + http: this.http, + }); } async onGetDomainList(data: any) { if (!this.accessId) { - throw new Error('请选择Access授权'); + throw new Error("请选择Access授权"); } const access = await this.getAccess(this.accessId); const client = await this.getClient(access); - const service = await client.getCdnClient() + const service = await client.getCdnClient(); const res = await service.ListCdnDomains({ ServiceType: this.serviceType, PageNum: 1, PageSize: 100, - }) + }); // @ts-ignore - const list = res?.Result?.Data + const list = res?.Result?.Data; if (!list || list.length === 0) { - throw new Error('找不到加速域名,您可以手动输入'); + throw new Error("找不到加速域名,您可以手动输入"); } const options = list.map((item: any) => { return { diff --git a/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-clb.ts b/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-clb.ts index 312c8be6a..6f7621ce4 100644 --- a/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-clb.ts +++ b/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-clb.ts @@ -12,9 +12,9 @@ import { VolcengineClient } from "../ve-client.js"; desc: "部署至火山引擎负载均衡", default: { strategy: { - runStrategy: RunStrategy.SkipWhenSucceed - } - } + runStrategy: RunStrategy.SkipWhenSucceed, + }, + }, }) export class VolcengineDeployToCLB extends AbstractTaskPlugin { @TaskInput({ @@ -22,24 +22,23 @@ export class VolcengineDeployToCLB extends AbstractTaskPlugin { helper: "请选择前置任务输出的域名证书", component: { name: "output-selector", - from: [...CertApplyPluginNames, "VolcengineUploadToCertCenter"] + from: [...CertApplyPluginNames, "VolcengineUploadToCertCenter"], }, - required: true + required: true, }) cert!: CertInfo | string; @TaskInput(createCertDomainGetterInputDefine({ props: { required: false } })) certDomains!: string[]; - @TaskInput({ title: "Access授权", helper: "火山引擎AccessKeyId、AccessKeySecret", component: { name: "access-selector", - type: "volcengine" + type: "volcengine", }, - required: true + required: true, }) accessId!: string; @@ -109,30 +108,26 @@ export class VolcengineDeployToCLB extends AbstractTaskPlugin { { label: "重庆", value: "cn-chengdu" }, { label: "香港", value: "cn-hongkong" }, { label: "柔佛", value: "ap-southeast-1" }, - { label: "雅加达", value: "ap-southeast-3" } - - ] + { label: "雅加达", value: "ap-southeast-3" }, + ], }, value: "cn-beijing", - required: true + required: true, }) regionId!: string; - @TaskInput( createRemoteSelectInputDefine({ title: "监听器列表", helper: "选择要部署证书的监听器\n需要在监听器中选择证书中心,进行跨服务访问授权", action: VolcengineDeployToCLB.prototype.onGetListenerList.name, watches: ["certDomains", "accessId", "regionId"], - required: true + required: true, }) ) listenerList!: string | string[]; - - async onInstance() { - } + async onInstance() {} async execute(): Promise { this.logger.info("开始部署证书到火山引擎CLB"); @@ -143,8 +138,8 @@ export class VolcengineDeployToCLB extends AbstractTaskPlugin { const certInfo = this.cert as CertInfo; this.logger.info(`开始上传证书`); certId = await certService.ImportCertificate({ - certName:this.appendTimeSuffix("certd"), - cert:certInfo + certName: this.appendTimeSuffix("certd"), + cert: certInfo, }); this.logger.info(`上传证书成功:${certId}`); } else { @@ -159,8 +154,8 @@ export class VolcengineDeployToCLB extends AbstractTaskPlugin { query: { ListenerId: listener, CertificateSource: "cert_center", - CertCenterCertificateId: certId - } + CertCenterCertificateId: certId, + }, }); this.logger.info(`部署监听器${listener}证书成功`); } @@ -168,12 +163,11 @@ export class VolcengineDeployToCLB extends AbstractTaskPlugin { this.logger.info("部署完成"); } - private async getCertService(access: VolcengineAccess) { const client = new VolcengineClient({ logger: this.logger, access, - http: this.http + http: this.http, }); return await client.getCertCenterService(); @@ -188,7 +182,7 @@ export class VolcengineDeployToCLB extends AbstractTaskPlugin { action: "DescribeLoadBalancers", method: "GET", query: { - PageSize: 100 + PageSize: 100, }, }); @@ -197,7 +191,7 @@ export class VolcengineDeployToCLB extends AbstractTaskPlugin { return list.map((item: any) => { return { value: item.LoadBalancerId, - label: `${item.LoadBalancerName}<${item.Description}>` + label: `${item.LoadBalancerName}<${item.Description}>`, }; }); } @@ -208,11 +202,11 @@ export class VolcengineDeployToCLB extends AbstractTaskPlugin { const client = new VolcengineClient({ logger: this.logger, access, - http: this.http + http: this.http, }); const service = await client.getClbService({ - region: this.regionId + region: this.regionId, }); return service; } @@ -228,7 +222,7 @@ export class VolcengineDeployToCLB extends AbstractTaskPlugin { method: "GET", query: { PageSize: 100, - Protocol: "HTTPS" + Protocol: "HTTPS", }, }); @@ -239,7 +233,7 @@ export class VolcengineDeployToCLB extends AbstractTaskPlugin { return list.map((item: any) => { return { value: item.ListenerId, - label: `${item.ListenerName}<${item.Description}:${item.ListenerId}>` + label: `${item.ListenerName}<${item.Description}:${item.ListenerId}>`, }; }); } diff --git a/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-dcdn.ts b/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-dcdn.ts index c6f492cbe..4704678c8 100644 --- a/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-dcdn.ts +++ b/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-dcdn.ts @@ -1,204 +1,196 @@ -import {AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput} from "@certd/pipeline"; -import {createCertDomainGetterInputDefine, createRemoteSelectInputDefine} from "@certd/plugin-lib"; -import {CertApplyPluginNames, CertInfo, CertReader} from "@certd/plugin-cert"; -import {VolcengineAccess} from "../access.js"; -import {VolcengineClient} from "../ve-client.js"; +import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; +import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from "@certd/plugin-lib"; +import { CertApplyPluginNames, CertInfo, CertReader } from "@certd/plugin-cert"; +import { VolcengineAccess } from "../access.js"; +import { VolcengineClient } from "../ve-client.js"; @IsTaskPlugin({ - name: "VolcengineDeployToDCDN", - title: "火山引擎-部署证书至DCDN", - icon: "svg:icon-volcengine", - group: pluginGroups.volcengine.key, - desc: "部署至火山引擎全站加速", - // showRunStrategy: true, - default: { - strategy: { - runStrategy: RunStrategy.SkipWhenSucceed - } - } + name: "VolcengineDeployToDCDN", + title: "火山引擎-部署证书至DCDN", + icon: "svg:icon-volcengine", + group: pluginGroups.volcengine.key, + desc: "部署至火山引擎全站加速", + // showRunStrategy: true, + default: { + strategy: { + runStrategy: RunStrategy.SkipWhenSucceed, + }, + }, }) export class VolcengineDeployToDCDN extends AbstractTaskPlugin { - @TaskInput({ - title: "域名证书", - helper: "请选择前置任务输出的域名证书", - component: { - name: "output-selector", - from: [...CertApplyPluginNames] - }, - required: true - }) - cert!: CertInfo; + @TaskInput({ + title: "域名证书", + helper: "请选择前置任务输出的域名证书", + component: { + name: "output-selector", + from: [...CertApplyPluginNames], + }, + required: true, + }) + cert!: CertInfo; - @TaskInput(createCertDomainGetterInputDefine({props: {required: false}})) - certDomains!: string[]; + @TaskInput(createCertDomainGetterInputDefine({ props: { required: false } })) + certDomains!: string[]; - @TaskInput({ - title: "自动匹配", - helper: "是否根据证书自动匹配合适的DCDN域名进行部署", - value: false, - component: { - name: "a-switch", - type: "checked" - }, - required: true - }) - autoMatch!: boolean; + @TaskInput({ + title: "自动匹配", + helper: "是否根据证书自动匹配合适的DCDN域名进行部署", + value: false, + component: { + name: "a-switch", + type: "checked", + }, + required: true, + }) + autoMatch!: boolean; - @TaskInput({ - title: "Access授权", - helper: "火山引擎AccessKeyId、AccessKeySecret", - component: { - name: "access-selector", - type: "volcengine" - }, - required: true - }) - accessId!: string; + @TaskInput({ + title: "Access授权", + helper: "火山引擎AccessKeyId、AccessKeySecret", + component: { + name: "access-selector", + type: "volcengine", + }, + required: true, + }) + accessId!: string; - - @TaskInput( - createRemoteSelectInputDefine({ - title: "DCDN域名", - helper: "选择要部署证书的DCDN域名", - action: VolcengineDeployToDCDN.prototype.onGetDomainList.name, - watches: ["certDomains", "accessId"], - required: true, - mergeScript: ` + @TaskInput( + createRemoteSelectInputDefine({ + title: "DCDN域名", + helper: "选择要部署证书的DCDN域名", + action: VolcengineDeployToDCDN.prototype.onGetDomainList.name, + watches: ["certDomains", "accessId"], + required: true, + mergeScript: ` return { show: ctx.compute(({form})=>{ return !form.autoMatch }) } - ` - }) - ) - domainList!: string | string[]; + `, + }) + ) + domainList!: string | string[]; + async onInstance() {} - async onInstance() { + async uploadCert(client: VolcengineClient) { + const certService = await client.getCertCenterService(); + let certId = this.cert; + if (typeof certId !== "string") { + const certInfo = this.cert as CertInfo; + this.logger.info(`开始上传证书`); + certId = await certService.ImportCertificate({ + certName: this.appendTimeSuffix("certd"), + cert: certInfo, + }); + this.logger.info(`上传证书成功:${certId}`); + } else { + this.logger.info(`使用已有证书ID:${certId}`); + } + return certId; + } + + async execute(): Promise { + this.logger.info("开始部署证书到火山引擎DCDN"); + + const client = await this.getClient(); + const certId = await this.uploadCert(client); + + const service = await client.getDCDNService(); + + this.certDomains = new CertReader(this.cert).getAllDomains(); + + let domainList = this.domainList; + if (!this.autoMatch) { + //手动根据域名部署 + if (!this.domainList || this.domainList.length === 0) { + throw new Error("域名列表不能为空"); + } + } else { + //自动匹配 + const options = await this.getDomainOptions(service); + const grouped = this.ctx.utils.options.groupByDomain(options, this.certDomains); + + const matched = grouped.matched; + + domainList = matched.map(item => item.domain); + + if (domainList.length === 0) { + this.logger.warn("没有匹配到域名,跳过部署"); + this.logger.info("当前证书域名:", this.certDomains); + this.logger.info( + "当前DCDN域名:", + grouped.notMatched.map(item => item.domain) + ); + return; + } } - async uploadCert(client: VolcengineClient) { - const certService = await client.getCertCenterService(); - let certId = this.cert; - if (typeof certId !== "string") { - const certInfo = this.cert as CertInfo; - this.logger.info(`开始上传证书`); - certId = await certService.ImportCertificate({ - certName: this.appendTimeSuffix("certd"), - cert: certInfo - }); - this.logger.info(`上传证书成功:${certId}`); - } else { - this.logger.info(`使用已有证书ID:${certId}`); - } - return certId + //域名十个十个的分割 + for (let i = 0; i < domainList.length; i += 10) { + const batch = domainList.slice(i, i + 10); + this.logger.info(`开始部署证书到域名:${batch}`); + const res = await service.request({ + action: "CreateCertBind", + method: "POST", + body: { + DomainNames: batch, + CertSource: "volc", + CertId: certId, + }, + version: "2021-04-01", + }); + this.logger.info(`部署证书到域名成功:`, JSON.stringify(res)); } + this.logger.info("部署完成"); + } - async execute(): Promise { - this.logger.info("开始部署证书到火山引擎DCDN"); + async getClient() { + const access = await this.getAccess(this.accessId); - const client = await this.getClient(); - let certId = await this.uploadCert(client); - - const service = await client.getDCDNService(); - - this.certDomains = new CertReader(this.cert).getAllDomains() - - - let domainList = this.domainList - if (!this.autoMatch) { - //手动根据域名部署 - if (!this.domainList || this.domainList.length === 0) { - throw new Error("域名列表不能为空"); - } - } else { - //自动匹配 - const options = await this.getDomainOptions(service); - const grouped = this.ctx.utils.options.groupByDomain(options, this.certDomains); - - const matched = grouped.matched - - domainList = matched.map(item => item.domain) - - if (domainList.length === 0) { - this.logger.warn("没有匹配到域名,跳过部署") - this.logger.info("当前证书域名:", this.certDomains) - this.logger.info("当前DCDN域名:", grouped.notMatched.map(item => item.domain)) - return - } - } - - - //域名十个十个的分割 - for (let i = 0; i < domainList.length; i += 10) { - const batch = domainList.slice(i, i + 10); - this.logger.info(`开始部署证书到域名:${batch}`); - const res = await service.request({ - action: "CreateCertBind", - method: "POST", - body: { - "DomainNames": batch, - "CertSource": "volc", - "CertId": certId - }, - version: "2021-04-01" - }); - this.logger.info(`部署证书到域名成功:`,JSON.stringify(res)); - } - - this.logger.info("部署完成"); + return new VolcengineClient({ + logger: this.logger, + access, + http: this.http, + }); + } + async onGetDomainList(data: any) { + if (!this.accessId) { + throw new Error("请选择Access授权"); } + const client = await this.getClient(); + const service = await client.getDCDNService(); + const options = await this.getDomainOptions(service); + return this.ctx.utils.options.buildGroupOptions(options, this.certDomains); + } - async getClient() { - const access = await this.getAccess(this.accessId); + private async getDomainOptions(service: any) { + const res = await service.request({ + method: "POST", + action: "DescribeUserDomains", + body: { + PageSize: 1000, + }, + }); - return new VolcengineClient({ - logger: this.logger, - access, - http: this.http - }) + const list = res.Result?.Domains; + if (!list || list.length === 0) { + throw new Error("找不到DCDN域名,您也可以手动输入域名"); } - - async onGetDomainList(data: any) { - if (!this.accessId) { - throw new Error("请选择Access授权"); - } - - const client = await this.getClient(); - const service = await client.getDCDNService(); - const options = await this.getDomainOptions(service); - return this.ctx.utils.options.buildGroupOptions(options, this.certDomains); - } - - private async getDomainOptions(service: any) { - const res = await service.request({ - method: "POST", - action: "DescribeUserDomains", - body: { - "PageSize": 1000 - } - }) - - - const list = res.Result?.Domains; - if (!list || list.length === 0) { - throw new Error("找不到DCDN域名,您也可以手动输入域名"); - } - const options = list.map((item: any) => { - return { - value: item.Domain, - label: `${item.Domain}<${item.Scope}>`, - domain: item.Domain - }; - }); - return options; - } - - + const options = list.map((item: any) => { + return { + value: item.Domain, + label: `${item.Domain}<${item.Scope}>`, + domain: item.Domain, + }; + }); + return options; + } } new VolcengineDeployToDCDN(); diff --git a/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-live.ts b/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-live.ts index 908e44f0c..e3fa491cd 100644 --- a/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-live.ts +++ b/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-live.ts @@ -12,9 +12,9 @@ import { VolcengineClient } from "../ve-client.js"; desc: "部署至火山引擎视频直播", default: { strategy: { - runStrategy: RunStrategy.SkipWhenSucceed - } - } + runStrategy: RunStrategy.SkipWhenSucceed, + }, + }, }) export class VolcengineDeployToLive extends AbstractTaskPlugin { @TaskInput({ @@ -22,48 +22,43 @@ export class VolcengineDeployToLive extends AbstractTaskPlugin { helper: "请选择前置任务输出的域名证书", component: { name: "output-selector", - from: [...CertApplyPluginNames] + from: [...CertApplyPluginNames], }, - required: true + required: true, }) cert!: CertInfo; @TaskInput(createCertDomainGetterInputDefine({ props: { required: false } })) certDomains!: string[]; - @TaskInput({ title: "Access授权", helper: "火山引擎AccessKeyId、AccessKeySecret", component: { name: "access-selector", - type: "volcengine" + type: "volcengine", }, - required: true + required: true, }) accessId!: string; - @TaskInput( createRemoteSelectInputDefine({ title: "直播域名", helper: "选择要部署证书的直播域名", action: VolcengineDeployToLive.prototype.onGetDomainList.name, watches: ["certDomains", "accessId"], - required: true + required: true, }) ) domainList!: string | string[]; - - async onInstance() { - } + async onInstance() {} async execute(): Promise { this.logger.info("开始部署证书到火山引擎视频直播"); const service = await this.getLiveService(); - let certId = await this.uploadCert(service); - + const certId = await this.uploadCert(service); for (const item of this.domainList) { this.logger.info(`开始部署直播域名${item}证书`); @@ -72,8 +67,8 @@ export class VolcengineDeployToLive extends AbstractTaskPlugin { body: { Domain: item, HTTPS: true, - ChainID: certId - } + ChainID: certId, + }, }); this.logger.info(`部署直播域名${item}证书成功`); } @@ -81,17 +76,16 @@ export class VolcengineDeployToLive extends AbstractTaskPlugin { this.logger.info("部署完成"); } - private async uploadCert(liveService: any) { const res = await liveService.request({ action: "CreateCert", body: { Rsa: { Pubkey: this.cert.crt, - Prikey: this.cert.key + Prikey: this.cert.key, }, - UseWay: "https" - } + UseWay: "https", + }, }); const certId = res.Result.ChainID; @@ -99,14 +93,13 @@ export class VolcengineDeployToLive extends AbstractTaskPlugin { return certId; } - private async getLiveService() { const access = await this.getAccess(this.accessId); const client = new VolcengineClient({ logger: this.logger, access, - http: this.http + http: this.http, }); return await client.getLiveService(); @@ -121,9 +114,9 @@ export class VolcengineDeployToLive extends AbstractTaskPlugin { const res = await service.request({ action: "ListDomainDetail", body: { - "PageNum": 1, - "PageSize": 100 - } + PageNum: 1, + PageSize: 100, + }, }); const list = res.Result?.DomainList; @@ -134,7 +127,7 @@ export class VolcengineDeployToLive extends AbstractTaskPlugin { return { value: item.Domain, label: `${item.Domain}<${item.Type}>`, - domain: item.Domain + domain: item.Domain, }; }); return this.ctx.utils.options.buildGroupOptions(options, this.certDomains); diff --git a/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-tos.ts b/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-tos.ts index d4ef42fbb..ac4a62410 100644 --- a/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-tos.ts +++ b/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-tos.ts @@ -6,11 +6,11 @@ import { VolcengineAccess } from "../access.js"; import { VolcengineClient } from "../ve-client.js"; @IsTaskPlugin({ - name: 'VolcengineDeployToTOS', - title: '火山引擎-部署证书至TOS自定义域名', - icon: 'svg:icon-volcengine', + name: "VolcengineDeployToTOS", + title: "火山引擎-部署证书至TOS自定义域名", + icon: "svg:icon-volcengine", group: pluginGroups.volcengine.key, - desc: '仅限TOS自定义域名,加速域名请选择火山引擎的CDN插件', + desc: "仅限TOS自定义域名,加速域名请选择火山引擎的CDN插件", default: { strategy: { runStrategy: RunStrategy.SkipWhenSucceed, @@ -19,11 +19,11 @@ import { VolcengineClient } from "../ve-client.js"; }) export class VolcengineDeployToTOS extends AbstractTaskPlugin { @TaskInput({ - title: '域名证书', - helper: '请选择前置任务输出的域名证书', + title: "域名证书", + helper: "请选择前置任务输出的域名证书", component: { - name: 'output-selector', - from: [...CertApplyPluginNames, 'VolcengineUploadToCertCenter'], + name: "output-selector", + from: [...CertApplyPluginNames, "VolcengineUploadToCertCenter"], }, required: true, }) @@ -32,48 +32,47 @@ export class VolcengineDeployToTOS extends AbstractTaskPlugin { @TaskInput(createCertDomainGetterInputDefine({ props: { required: false } })) certDomains!: string[]; - @TaskInput({ - title: 'Access授权', - helper: '火山引擎AccessKeyId、AccessKeySecret', + title: "Access授权", + helper: "火山引擎AccessKeyId、AccessKeySecret", component: { - name: 'access-selector', - type: 'volcengine', + name: "access-selector", + type: "volcengine", }, required: true, }) accessId!: string; @TaskInput({ - title: '地域', - helper: 'TOS服务所在地域', + title: "地域", + helper: "TOS服务所在地域", component: { - name: 'a-select', - options:[ + name: "a-select", + options: [ { label: "华北2(北京)", value: "cn-beijing" }, { label: "华东2(上海)", value: "cn-shanghai" }, { label: "华南1(广州)", value: "cn-guangzhou" }, { label: "中国香港", value: "cn-hongkong" }, { label: "亚太东南(柔佛)", value: "ap-southeast-1" }, { label: "亚太东南(雅加达)", value: "ap-southeast-3" }, - ] + ], }, - value: 'cn-beijing', + value: "cn-beijing", required: true, }) - region:string = "cn-beijing" + region = "cn-beijing"; @TaskInput({ - title: 'Bucket', - helper: '存储桶名称', + title: "Bucket", + helper: "存储桶名称", component: { - name: 'remote-auto-complete', - vModel: 'value', - type: 'plugin', - action: 'onGetBucketList', + name: "remote-auto-complete", + vModel: "value", + type: "plugin", + action: "onGetBucketList", search: false, pager: false, - watches: ['accessId', 'region'] + watches: ["accessId", "region"], }, required: true, }) @@ -81,87 +80,86 @@ export class VolcengineDeployToTOS extends AbstractTaskPlugin { @TaskInput( createRemoteSelectInputDefine({ - title: 'TOS自定义域名', - helper: '你在火山引擎上配置的TOS自定义域名,比如:example.com', + title: "TOS自定义域名", + helper: "你在火山引擎上配置的TOS自定义域名,比如:example.com", action: VolcengineDeployToTOS.prototype.onGetDomainList.name, - watches: ['certDomains', 'accessId', 'region', 'bucket'], + watches: ["certDomains", "accessId", "region", "bucket"], required: true, }) ) domainName!: string | string[]; - async onInstance() {} async execute(): Promise { - this.logger.info('开始部署证书到火山引擎TOS自定义域名'); + this.logger.info("开始部署证书到火山引擎TOS自定义域名"); const access = await this.getAccess(this.accessId); this.logger.info(`bucket: ${this.bucket}, region: ${this.region}, domainName: ${this.domainName}`); - + const client = new VolcengineClient({ logger: this.logger, access, - http: this.http + http: this.http, }); - + const tosService = await client.getTOSService({ region: this.region }); - + if (!this.cert) { - throw new Error('你还未选择证书'); + throw new Error("你还未选择证书"); } - let certId = this.cert - if (typeof certId !== 'string') { - const certInfo = this.cert as CertInfo - this.logger.info(`开始上传证书`) + let certId = this.cert; + if (typeof certId !== "string") { + const certInfo = this.cert as CertInfo; + this.logger.info(`开始上传证书`); const certService = await client.getCertCenterService(); certId = await certService.ImportCertificate({ - certName: this.appendTimeSuffix('certd'), - cert: certInfo - }) + certName: this.appendTimeSuffix("certd"), + cert: certInfo, + }); this.logger.info(`上传证书成功:${certId}`); - }else{ + } else { this.logger.info(`使用已有证书ID:${certId}`); } for (const domain of this.domainName) { - this.logger.info(`开始部署域名${domain}证书`) + this.logger.info(`开始部署域名${domain}证书`); await tosService.putBucketCustomDomain({ bucket: this.bucket, customDomainRule: { Domain: domain, - CertId: certId as string - } - }) + CertId: certId as string, + }, + }); this.logger.info(`部署域名${domain}证书成功`); - await this.ctx.utils.sleep(1000) + await this.ctx.utils.sleep(1000); } - this.logger.info('部署完成'); + this.logger.info("部署完成"); } async onGetDomainList(data: any) { if (!this.accessId || !this.bucket) { - throw new Error('请选择Access授权和Bucket'); + throw new Error("请选择Access授权和Bucket"); } const access = await this.getAccess(this.accessId); const client = new VolcengineClient({ logger: this.logger, access, - http: this.http + http: this.http, }); - + const tosService = await client.getTOSService({ region: this.region }); - + const res = await tosService.getBucketCustomDomain({ - bucket: this.bucket + bucket: this.bucket, }); - + const list = res?.data?.CustomDomainRules || []; if (!list || list.length === 0) { - throw new Error('找不到TOS自定义域名,您可以手动输入'); + throw new Error("找不到TOS自定义域名,您可以手动输入"); } - + const options = list.map((item: any) => { return { value: item.Domain, @@ -169,31 +167,31 @@ export class VolcengineDeployToTOS extends AbstractTaskPlugin { domain: item.Domain, }; }); - + return optionsUtils.buildGroupOptions(options, this.certDomains); } async onGetBucketList(data: any) { if (!this.accessId) { - throw new Error('请选择Access授权'); + throw new Error("请选择Access授权"); } const access = await this.getAccess(this.accessId); const client = new VolcengineClient({ logger: this.logger, access, - http: this.http + http: this.http, }); - + const tosService = await client.getTOSService({ region: this.region }); - + const res = await tosService.listBuckets(); - + const buckets = res?.data?.Buckets || []; return buckets.map((bucket: any) => ({ label: `${bucket.Name}<${bucket.Location}>`, - value: bucket.Name + value: bucket.Name, })); } } -new VolcengineDeployToTOS(); \ No newline at end of file +new VolcengineDeployToTOS(); diff --git a/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-vke.test.ts b/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-vke.test.ts index 508654f9e..748ca73dc 100644 --- a/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-vke.test.ts +++ b/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-vke.test.ts @@ -23,7 +23,7 @@ describe("VolcengineDeployToVKE", () => { request: async (req: any) => { requestBody = req.body; return { Result: { Id: "kc-123" } }; - } + }, }); assert.equal(kubeconfigId, "kc-123"); @@ -35,23 +35,15 @@ describe("VolcengineDeployToVKE", () => { plugin.clusterId = "cc1234567890123456789"; plugin.kubeconfigType = "Public"; - const kubeconfig = [ - "apiVersion: v1", - "clusters:", - "- cluster:", - " server: https://example.com", - " name: vke", - "contexts: []", - "current-context: vke" - ].join("\n"); + const kubeconfig = ["apiVersion: v1", "clusters:", "- cluster:", " server: https://example.com", " name: vke", "contexts: []", "current-context: vke"].join("\n"); const result = await (plugin as any).getKubeconfig( { request: async () => ({ Result: { - Items: [{ Id: "kc-123", Kubeconfig: Buffer.from(kubeconfig).toString("base64") }] - } - }) + Items: [{ Id: "kc-123", Kubeconfig: Buffer.from(kubeconfig).toString("base64") }], + }, + }), }, "kc-123" ); @@ -66,11 +58,10 @@ describe("VolcengineDeployToVKE", () => { const message = (plugin as any).formatK8sError({ status: "Failure", - message: - 'secrets "aaaa" is forbidden: User "2100656669-kd7ubde6lsvqbdgsa40t0" cannot get resource "secrets" in API group "" in the namespace "default"', + message: 'secrets "aaaa" is forbidden: User "2100656669-kd7ubde6lsvqbdgsa40t0" cannot get resource "secrets" in API group "" in the namespace "default"', reason: "Forbidden", details: { name: "aaaa", kind: "secrets" }, - code: 403 + code: 403, }); assert.match(message, /VKE集群RBAC权限不足/); @@ -89,8 +80,8 @@ describe("VolcengineDeployToVKE", () => { () => (plugin as any).getTargetSecretNames({ getIngressList: async () => ({ - items: [{ metadata: { name: "app-web" } }, { metadata: { name: "api-web" } }] - }) + items: [{ metadata: { name: "app-web" } }, { metadata: { name: "api-web" } }], + }), }), /当前命名空间可用Ingress:app-web,api-web/ ); diff --git a/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-vke.ts b/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-vke.ts index 060845802..35377e1b0 100644 --- a/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-vke.ts +++ b/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-vke.ts @@ -11,7 +11,7 @@ const regionOptions = [ { label: "广州", value: "cn-guangzhou" }, { label: "香港", value: "cn-hongkong" }, { label: "柔佛", value: "ap-southeast-1" }, - { label: "雅加达", value: "ap-southeast-3" } + { label: "雅加达", value: "ap-southeast-3" }, ]; @IsTaskPlugin({ @@ -22,9 +22,9 @@ const regionOptions = [ desc: "替换火山引擎VKE集群中的TLS Secret证书", default: { strategy: { - runStrategy: RunStrategy.SkipWhenSucceed - } - } + runStrategy: RunStrategy.SkipWhenSucceed, + }, + }, }) export class VolcengineDeployToVKE extends AbstractTaskPlugin { @TaskInput({ @@ -32,9 +32,9 @@ export class VolcengineDeployToVKE extends AbstractTaskPlugin { helper: "请选择前置任务输出的域名证书", component: { name: "output-selector", - from: [...CertApplyPluginNames] + from: [...CertApplyPluginNames], }, - required: true + required: true, }) cert!: CertInfo; @@ -46,9 +46,9 @@ export class VolcengineDeployToVKE extends AbstractTaskPlugin { helper: "火山引擎AccessKeyId、AccessKeySecret", component: { name: "access-selector", - type: "volcengine" + type: "volcengine", }, - required: true + required: true, }) accessId!: string; @@ -57,10 +57,10 @@ export class VolcengineDeployToVKE extends AbstractTaskPlugin { helper: "VKE集群所在地域", component: { name: "a-select", - options: regionOptions + options: regionOptions, }, value: "cn-beijing", - required: true + required: true, }) regionId!: string; @@ -71,7 +71,7 @@ export class VolcengineDeployToVKE extends AbstractTaskPlugin { action: VolcengineDeployToVKE.prototype.onGetClusterList.name, watches: ["accessId", "regionId"], single: true, - required: true + required: true, }) ) clusterId!: string; @@ -83,11 +83,11 @@ export class VolcengineDeployToVKE extends AbstractTaskPlugin { name: "a-select", options: [ { label: "公网", value: "Public" }, - { label: "私网", value: "Private" } - ] + { label: "私网", value: "Private" }, + ], }, value: "Public", - required: true + required: true, }) kubeconfigType!: "Public" | "Private"; @@ -95,9 +95,9 @@ export class VolcengineDeployToVKE extends AbstractTaskPlugin { title: "命名空间", value: "default", component: { - placeholder: "命名空间" + placeholder: "命名空间", }, - required: true + required: true, }) namespace!: string; @@ -108,11 +108,11 @@ export class VolcengineDeployToVKE extends AbstractTaskPlugin { name: "a-select", options: [ { label: "按Ingress替换", value: "ingress" }, - { label: "按Secret替换", value: "secret" } - ] + { label: "按Secret替换", value: "secret" }, + ], }, value: "ingress", - required: true + required: true, }) targetType!: "ingress" | "secret"; @@ -125,7 +125,7 @@ export class VolcengineDeployToVKE extends AbstractTaskPlugin { show: ctx.compute(({form}) => form.targetType === 'ingress'), required: ctx.compute(({form}) => form.targetType === 'ingress') } - ` + `, }) ingressName!: string; @@ -137,14 +137,14 @@ export class VolcengineDeployToVKE extends AbstractTaskPlugin { name: "a-select", vModel: "value", mode: "tags", - open: false + open: false, }, mergeScript: ` return { show: ctx.compute(({form}) => form.targetType === 'secret'), required: ctx.compute(({form}) => form.targetType === 'secret') } - ` + `, }) secretName!: string | string[]; @@ -154,8 +154,8 @@ export class VolcengineDeployToVKE extends AbstractTaskPlugin { value: false, component: { name: "a-switch", - vModel: "checked" - } + vModel: "checked", + }, }) createOnNotFound!: boolean; @@ -165,8 +165,8 @@ export class VolcengineDeployToVKE extends AbstractTaskPlugin { value: false, component: { name: "a-switch", - vModel: "checked" - } + vModel: "checked", + }, }) skipTLSVerify!: boolean; @@ -188,7 +188,7 @@ export class VolcengineDeployToVKE extends AbstractTaskPlugin { const k8sClient = new this.K8sClient({ kubeConfigStr: kubeconfig, logger: this.logger, - skipTLSVerify: this.skipTLSVerify + skipTLSVerify: this.skipTLSVerify, }); const secretNames = await this.getTargetSecretNames(k8sClient); await this.patchCertSecret({ cert: this.cert, k8sClient, secretNames }); @@ -209,7 +209,7 @@ export class VolcengineDeployToVKE extends AbstractTaskPlugin { const client = new VolcengineClient({ logger: this.logger, access, - http: this.http + http: this.http, }); return await client.getVkeService({ region: this.regionId }); } @@ -222,8 +222,8 @@ export class VolcengineDeployToVKE extends AbstractTaskPlugin { body: { ClusterId: clusterId, Type: this.kubeconfigType, - ValidDuration: 3600 - } + ValidDuration: 3600, + }, }); const kubeconfigId = res.Result?.Id || res.Id; if (!kubeconfigId) { @@ -242,11 +242,11 @@ export class VolcengineDeployToVKE extends AbstractTaskPlugin { Filter: { ClusterIds: [clusterId], Ids: [kubeconfigId], - Types: [this.kubeconfigType] + Types: [this.kubeconfigType], }, PageNumber: 1, - PageSize: 10 - } + PageSize: 10, + }, }); const items = res.Result?.Items || res.Items || []; const item = items.find((it: any) => it.Id === kubeconfigId) || items[0]; @@ -268,8 +268,8 @@ export class VolcengineDeployToVKE extends AbstractTaskPlugin { method: "POST", body: { ClusterId: clusterId, - Ids: [kubeconfigId] - } + Ids: [kubeconfigId], + }, }); this.logger.info(`已删除临时Kubeconfig:${kubeconfigId}`); } catch (e) { @@ -303,7 +303,9 @@ export class VolcengineDeployToVKE extends AbstractTaskPlugin { const resource = message.match(/resource "([^"]+)"/)?.[1] || body.details?.kind || "目标资源"; const namespace = message.match(/namespace "([^"]+)"/)?.[1] || this.namespace; const userText = granteeId ? `,用户ID:${granteeId}` : ""; - return `VKE集群RBAC权限不足:当前火山引擎授权${userText}在集群:${this.getClusterId()} 的命名空间:${namespace} 没有操作 ${resource} 的权限。请在火山引擎 VKE 集群权限管理中,为该用户授予此命名空间的管理员权限,或授予包含 secrets get/create/update/patch 的自定义角色。原始错误:${JSON.stringify(body)}`; + return `VKE集群RBAC权限不足:当前火山引擎授权${userText}在集群:${this.getClusterId()} 的命名空间:${namespace} 没有操作 ${resource} 的权限。请在火山引擎 VKE 集群权限管理中,为该用户授予此命名空间的管理员权限,或授予包含 secrets get/create/update/patch 的自定义角色。原始错误:${JSON.stringify( + body + )}`; } private async getTargetSecretNames(k8sClient: any) { @@ -315,7 +317,7 @@ export class VolcengineDeployToVKE extends AbstractTaskPlugin { } const ingressList = await k8sClient.getIngressList({ - namespace: this.namespace + namespace: this.namespace, }); const ingress = ingressList.items.find((item: any) => item.metadata.name === this.ingressName); if (!ingress) { @@ -341,13 +343,13 @@ export class VolcengineDeployToVKE extends AbstractTaskPlugin { const body: any = { data: { "tls.crt": Buffer.from(cert.crt).toString("base64"), - "tls.key": Buffer.from(cert.key).toString("base64") + "tls.key": Buffer.from(cert.key).toString("base64"), }, metadata: { labels: { - certd: this.appendTimeSuffix("certd") - } - } + certd: this.appendTimeSuffix("certd"), + }, + }, }; for (const secretName of secretNames) { @@ -357,7 +359,7 @@ export class VolcengineDeployToVKE extends AbstractTaskPlugin { namespace: this.namespace, secretName, body, - createOnNotFound: this.createOnNotFound + createOnNotFound: this.createOnNotFound, }); this.logger.info(`VKE Secret已更新:${secretName}`); } @@ -378,13 +380,13 @@ export class VolcengineDeployToVKE extends AbstractTaskPlugin { method: "POST", body: { PageNumber: 1, - PageSize: 100 - } + PageSize: 100, + }, }); const list = res.Result?.Items || res.Items || []; return list.map((item: any) => ({ label: `${item.Name || item.Id}<${item.Id}>`, - value: item.Id + value: item.Id, })); } } diff --git a/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-vod.ts b/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-vod.ts index 96079350f..d0401a054 100644 --- a/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-vod.ts +++ b/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-vod.ts @@ -12,9 +12,9 @@ import { VolcengineClient } from "../ve-client.js"; desc: "部署至火山引擎视频点播", default: { strategy: { - runStrategy: RunStrategy.SkipWhenSucceed - } - } + runStrategy: RunStrategy.SkipWhenSucceed, + }, + }, }) export class VolcengineDeployToVOD extends AbstractTaskPlugin { @TaskInput({ @@ -22,28 +22,26 @@ export class VolcengineDeployToVOD extends AbstractTaskPlugin { helper: "请选择前置任务输出的域名证书", component: { name: "output-selector", - from: [...CertApplyPluginNames, "VolcengineUploadToCertCenter"] + from: [...CertApplyPluginNames, "VolcengineUploadToCertCenter"], }, - required: true + required: true, }) cert!: CertInfo | string; @TaskInput(createCertDomainGetterInputDefine({ props: { required: false } })) certDomains!: string[]; - @TaskInput({ title: "Access授权", helper: "火山引擎AccessKeyId、AccessKeySecret", component: { name: "access-selector", - type: "volcengine" + type: "volcengine", }, - required: true + required: true, }) accessId!: string; - @TaskInput({ title: "区域", helper: "选择火山引擎区域", @@ -51,11 +49,11 @@ export class VolcengineDeployToVOD extends AbstractTaskPlugin { name: "select", options: [ { value: "cn-north-1", label: "华北1(北京)" }, - { value: "ap-southeast-1", label: "东南亚1(新加坡)" } - ] + { value: "ap-southeast-1", label: "东南亚1(新加坡)" }, + ], }, default: "cn-north-1", - required: true + required: true, }) regionId!: string; @@ -65,8 +63,8 @@ export class VolcengineDeployToVOD extends AbstractTaskPlugin { helper: "选择要部署证书的点播空间", action: VolcengineDeployToVOD.prototype.onGetSpaceList.name, watches: ["accessId", "regionId"], - single:true, - required: true + single: true, + required: true, }) ) spaceName!: string; @@ -79,11 +77,11 @@ export class VolcengineDeployToVOD extends AbstractTaskPlugin { vModel: "value", options: [ { value: "play", label: "点播加速域名" }, - { value: "image", label: "封面加速域名" } - ] + { value: "image", label: "封面加速域名" }, + ], }, value: "play", - required: true + required: true, }) domainType!: string; @@ -93,24 +91,22 @@ export class VolcengineDeployToVOD extends AbstractTaskPlugin { helper: "选择要部署证书的域名\n需要先在域名管理页面进行证书中心访问授权(即点击去配置SSL证书)", action: VolcengineDeployToVOD.prototype.onGetDomainList.name, watches: ["certDomains", "accessId", "spaceName", "domainType"], - required: true + required: true, }) ) domainList!: string | string[]; - - async onInstance() { - } + async onInstance() {} async execute(): Promise { this.logger.info("开始部署证书到火山引擎VOD"); - + if (!this.spaceName) { throw new Error("SpaceName不能为空"); } - + const access = await this.getAccess(this.accessId); - let certId = await this.uploadOrGetCertId(access); + const certId = await this.uploadOrGetCertId(access); const service = await this.getVodService({ version: "2023-07-01", region: this.regionId }); const domains = Array.isArray(this.domainList) ? this.domainList : [this.domainList]; @@ -127,11 +123,11 @@ export class VolcengineDeployToVOD extends AbstractTaskPlugin { HTTPS: { Switch: true, CertInfo: { - CertId: certId - } - } - } - } + CertId: certId, + }, + }, + }, + }, }); this.logger.info(`部署域名${domain}证书成功`); } @@ -139,7 +135,6 @@ export class VolcengineDeployToVOD extends AbstractTaskPlugin { this.logger.info("部署完成"); } - private async uploadOrGetCertId(access: VolcengineAccess) { const certService = await this.getCertService(access); let certId = this.cert; @@ -148,7 +143,7 @@ export class VolcengineDeployToVOD extends AbstractTaskPlugin { this.logger.info(`开始上传证书`); certId = await certService.ImportCertificate({ certName: this.appendTimeSuffix("certd"), - cert: certInfo + cert: certInfo, }); this.logger.info(`上传证书成功:${certId}`); } else { @@ -161,20 +156,19 @@ export class VolcengineDeployToVOD extends AbstractTaskPlugin { const client = new VolcengineClient({ logger: this.logger, access, - http: this.http + http: this.http, }); return await client.getCertCenterService(); } - - private async getVodService(req?: { version?: string, region?: string }) { + private async getVodService(req?: { version?: string; region?: string }) { const access = await this.getAccess(this.accessId); const client = new VolcengineClient({ logger: this.logger, access, - http: this.http + http: this.http, }); return await client.getVodService(req); @@ -188,7 +182,7 @@ export class VolcengineDeployToVOD extends AbstractTaskPlugin { const res = await service.request({ action: "ListSpace", - body: {} + body: {}, }); const list = res.Result; @@ -198,7 +192,7 @@ export class VolcengineDeployToVOD extends AbstractTaskPlugin { return list.map((item: any) => { return { value: item.SpaceName, - label: `${item.SpaceName} (${item.Region})` + label: `${item.SpaceName} (${item.Region})`, }; }); } @@ -216,8 +210,8 @@ export class VolcengineDeployToVOD extends AbstractTaskPlugin { action: "ListDomain", query: { SpaceName: this.spaceName, - DomainType: this.domainType - } + DomainType: this.domainType, + }, }); const instances = res.Result?.PlayInstanceInfo?.ByteInstances; @@ -231,7 +225,7 @@ export class VolcengineDeployToVOD extends AbstractTaskPlugin { if (domain.Domain) { list.push({ value: domain.Domain, - label: domain.Domain + label: domain.Domain, }); } } diff --git a/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-upload-to-cert-center.ts b/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-upload-to-cert-center.ts index b289ae702..7d1c0c035 100644 --- a/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-upload-to-cert-center.ts +++ b/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-upload-to-cert-center.ts @@ -5,11 +5,11 @@ import { VolcengineAccess } from "../access.js"; import { VolcengineClient } from "../ve-client.js"; @IsTaskPlugin({ - name: 'VolcengineUploadToCertCenter', - title: '火山引擎-上传证书至证书中心', - icon: 'svg:icon-volcengine', + name: "VolcengineUploadToCertCenter", + title: "火山引擎-上传证书至证书中心", + icon: "svg:icon-volcengine", group: pluginGroups.volcengine.key, - desc: '上传证书至火山引擎证书中心', + desc: "上传证书至火山引擎证书中心", default: { strategy: { runStrategy: RunStrategy.SkipWhenSucceed, @@ -18,10 +18,10 @@ import { VolcengineClient } from "../ve-client.js"; }) export class VolcengineUploadToCertCenter extends AbstractTaskPlugin { @TaskInput({ - title: '域名证书', - helper: '请选择前置任务输出的域名证书', + title: "域名证书", + helper: "请选择前置任务输出的域名证书", component: { - name: 'output-selector', + name: "output-selector", from: [...CertApplyPluginNames], }, required: true, @@ -31,47 +31,44 @@ export class VolcengineUploadToCertCenter extends AbstractTaskPlugin { @TaskInput(createCertDomainGetterInputDefine({ props: { required: false } })) certDomains!: string[]; - @TaskInput({ - title: 'Access授权', - helper: '火山引擎AccessKeyId、AccessKeySecret', + title: "Access授权", + helper: "火山引擎AccessKeyId、AccessKeySecret", component: { - name: 'access-selector', - type: 'volcengine', + name: "access-selector", + type: "volcengine", }, required: true, }) accessId!: string; - @TaskOutput({ - title: '上传成功后的火山引擎证书Id', + title: "上传成功后的火山引擎证书Id", }) volcengineCertId?: string; async onInstance() {} async execute(): Promise { - this.logger.info('开始上传证书到证书中心'); + this.logger.info("开始上传证书到证书中心"); const access = await this.getAccess(this.accessId); - const client = await this.getClient(access) - const service = await client.getCertCenterService() - const certInfo = this.cert - this.logger.info(`开始上传证书`) + const client = await this.getClient(access); + const service = await client.getCertCenterService(); + const certInfo = this.cert; + this.logger.info(`开始上传证书`); this.volcengineCertId = await service.ImportCertificate({ - certName: this.appendTimeSuffix('certd'), - cert: certInfo - }) + certName: this.appendTimeSuffix("certd"), + cert: certInfo, + }); this.logger.info(`上传完成:${this.volcengineCertId}`); } - async getClient(access: VolcengineAccess) { - return new VolcengineClient({ + return new VolcengineClient({ logger: this.logger, access, - http:this.http - }) + http: this.http, + }); } } new VolcengineUploadToCertCenter(); diff --git a/packages/ui/certd-server/src/plugins/plugin-volcengine/ve-client.ts b/packages/ui/certd-server/src/plugins/plugin-volcengine/ve-client.ts index 09a2827dc..2e96ed3cf 100644 --- a/packages/ui/certd-server/src/plugins/plugin-volcengine/ve-client.ts +++ b/packages/ui/certd-server/src/plugins/plugin-volcengine/ve-client.ts @@ -2,10 +2,10 @@ import { VolcengineAccess } from "./access.js"; import { HttpClient, ILogger } from "@certd/basic"; export type VolcengineOpts = { - access: VolcengineAccess - logger: ILogger - http: HttpClient -} + access: VolcengineAccess; + logger: ILogger; + http: HttpClient; +}; export class VolcengineClient { opts: VolcengineOpts; @@ -20,13 +20,13 @@ export class VolcengineClient { const service = new CommonService({ serviceName: "certificate_service", - defaultVersion: "2024-10-01" + defaultVersion: "2024-10-01", }); service.setAccessKeyId(this.opts.access.accessKeyId); service.setSecretKey(this.opts.access.secretAccessKey); service.setRegion("cn-beijing"); - service.ImportCertificate = async (body: { certName: string, cert: any }) => { + service.ImportCertificate = async (body: { certName: string; cert: any }) => { const { certName, cert } = body; const res = await service.request({ action: "ImportCertificate", @@ -36,9 +36,9 @@ export class VolcengineClient { Repeatable: false, CertificateInfo: { CertificateChain: cert.crt, - PrivateKey: cert.key - } - } + PrivateKey: cert.key, + }, + }, }); return res.Result.InstanceId || res.Result.RepeatId; }; @@ -48,8 +48,8 @@ export class VolcengineClient { action: "CertificateGetInstance", method: "POST", body: { - InstanceId: certificateId - } + InstanceId: certificateId, + }, }); return res.Result; }; @@ -61,7 +61,7 @@ export class VolcengineClient { const service = new CommonService({ serviceName: "clb", - defaultVersion: "2020-04-01" + defaultVersion: "2020-04-01", }); service.setAccessKeyId(this.opts.access.accessKeyId); service.setSecretKey(this.opts.access.secretAccessKey); @@ -75,7 +75,7 @@ export class VolcengineClient { const service = new CommonService({ serviceName: "live", - defaultVersion: "2023-01-01" + defaultVersion: "2023-01-01", }); service.setAccessKeyId(this.opts.access.accessKeyId); service.setSecretKey(this.opts.access.secretAccessKey); @@ -84,12 +84,12 @@ export class VolcengineClient { return service; } - async getVodService(opts?: { version?: string, region?: string }) { + async getVodService(opts?: { version?: string; region?: string }) { const CommonService = await this.getServiceCls(); const service = new CommonService({ serviceName: "vod", - defaultVersion: opts?.version || "2021-01-01" + defaultVersion: opts?.version || "2021-01-01", }); service.setAccessKeyId(this.opts.access.accessKeyId); service.setSecretKey(this.opts.access.secretAccessKey); @@ -103,7 +103,7 @@ export class VolcengineClient { const service = new CommonService({ serviceName: "alb", - defaultVersion: "2020-04-01" + defaultVersion: "2020-04-01", }); service.setAccessKeyId(this.opts.access.accessKeyId); service.setSecretKey(this.opts.access.secretAccessKey); @@ -117,7 +117,7 @@ export class VolcengineClient { const service = new CommonService({ serviceName: "vke", - defaultVersion: "2022-05-12" + defaultVersion: "2022-05-12", }); service.setAccessKeyId(this.opts.access.accessKeyId); service.setSecretKey(this.opts.access.secretAccessKey); @@ -126,12 +126,12 @@ export class VolcengineClient { return service; } - async getDCDNService( opts?: { }) { + async getDCDNService(opts?: {}) { const CommonService = await this.getServiceCls(); const service = new CommonService({ serviceName: "dcdn", - defaultVersion: "2023-01-01" + defaultVersion: "2023-01-01", }); service.setAccessKeyId(this.opts.access.accessKeyId); service.setSecretKey(this.opts.access.secretAccessKey); @@ -141,14 +141,14 @@ export class VolcengineClient { async getTOSService(opts: { region?: string }) { const { TosClient } = await import("@volcengine/tos-sdk"); - + const client = new TosClient({ accessKeyId: this.opts.access.accessKeyId, accessKeySecret: this.opts.access.secretAccessKey, region: opts.region, - endpoint: `tos-${opts.region}.volces.com` + endpoint: `tos-${opts.region}.volces.com`, }); - + return client; } @@ -157,7 +157,7 @@ export class VolcengineClient { const service = new CommonService({ serviceName: "sts", - defaultVersion: "2018-01-01" + defaultVersion: "2018-01-01", }); service.setAccessKeyId(this.opts.access.accessKeyId); service.setSecretKey(this.opts.access.secretAccessKey); @@ -174,29 +174,26 @@ export class VolcengineClient { class CommonService extends Service { Generic: any; - constructor(options: { - serviceName: string; - defaultVersion: string; - }) { + constructor(options: { serviceName: string; defaultVersion: string }) { super(Object.assign({ host: "open.volcengineapi.com" }, options)); - this.Generic = async (req: { action: string, body?: any, method?: string, query?: any ,version?:string}) => { - const { action, method, body, query,version } = req; + this.Generic = async (req: { action: string; body?: any; method?: string; query?: any; version?: string }) => { + const { action, method, body, query, version } = req; return await this.fetchOpenAPI({ Action: action, - Version: version||options.defaultVersion, + Version: version || options.defaultVersion, method: method as any, headers: { - "content-type": "application/json" + "content-type": "application/json", }, query: query || {}, - data: body + data: body, }); }; } - async request(req: { action: string, body?: any, method?: string, query?: any,version?:string }) { + async request(req: { action: string; body?: any; method?: string; query?: any; version?: string }) { const res = await this.Generic(req); - if (res ==="Not Found"){ + if (res === "Not Found") { throw new Error(`${res} (检查method)`); } if (res.errorcode) { @@ -212,7 +209,4 @@ export class VolcengineClient { this.CommonService = CommonService; return CommonService; } - - - } diff --git a/packages/ui/certd-server/src/plugins/plugin-volcengine/volcengine-dns-provider.ts b/packages/ui/certd-server/src/plugins/plugin-volcengine/volcengine-dns-provider.ts index 3cd27eca3..3bf5b35ee 100644 --- a/packages/ui/certd-server/src/plugins/plugin-volcengine/volcengine-dns-provider.ts +++ b/packages/ui/certd-server/src/plugins/plugin-volcengine/volcengine-dns-provider.ts @@ -10,19 +10,18 @@ import { PageSearch } from "@certd/pipeline"; desc: "火山引擎DNS解析提供商", accessType: "volcengine", icon: "svg:icon-volcengine", - order:2, + order: 2, }) export class VolcengineDnsProvider extends AbstractDnsProvider { client: VolcengineDnsClient; access!: VolcengineAccess; - async onInstance() { - this.access = this.ctx.access as VolcengineAccess + this.access = this.ctx.access as VolcengineAccess; this.client = new VolcengineDnsClient({ access: this.access, logger: this.logger, - http: this.http + http: this.http, }); } @@ -30,7 +29,7 @@ export class VolcengineDnsProvider extends AbstractDnsProvider { * @param domain */ async getDomain(domain: string) { - const res = await this.client.findDomain(domain) + const res = await this.client.findDomain(domain); if (res.Result.Zones && res.Result.Zones.length > 0) { return res.Result.Zones[0]; @@ -38,7 +37,6 @@ export class VolcengineDnsProvider extends AbstractDnsProvider { throw new Error(`域名${domain}不存在`); } - async createRecord(options: CreateRecordOptions): Promise { const { fullRecord, hostRecord, value, type, domain } = options; this.logger.info("添加域名解析:", fullRecord, value, domain); @@ -48,9 +46,9 @@ export class VolcengineDnsProvider extends AbstractDnsProvider { const body = { ZID, - "Host": hostRecord, - "Type": type, - "Value": value + Host: hostRecord, + Type: type, + Value: value, }; const res = await this.client.doRequest({ @@ -59,23 +57,22 @@ export class VolcengineDnsProvider extends AbstractDnsProvider { region: "cn-beijing", query: { Action: "CreateRecord", - Version: "2018-08-01" + Version: "2018-08-01", }, - body + body, }); return { RecordID: res.Result.RecordID, - ZID: ZID + ZID: ZID, }; } - async removeRecord(options: RemoveRecordOptions): Promise { const record = options.recordRes; const body = { - RecordID: record.RecordID + RecordID: record.RecordID, }; await this.client.doRequest({ @@ -84,14 +81,14 @@ export class VolcengineDnsProvider extends AbstractDnsProvider { region: "cn-beijing", query: { Action: "DeleteRecord", - Version: "2018-08-01" + Version: "2018-08-01", }, - body + body, }); } - + async getDomainListPage(page: PageSearch) { - return await this.client.getDomainList(page) + return await this.client.getDomainList(page); } } diff --git a/packages/ui/certd-server/src/plugins/plugin-wangsu/access.ts b/packages/ui/certd-server/src/plugins/plugin-wangsu/access.ts index ee6fc08aa..e228f08c1 100644 --- a/packages/ui/certd-server/src/plugins/plugin-wangsu/access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-wangsu/access.ts @@ -2,30 +2,27 @@ import { AccessInput, BaseAccess, IsAccess } from "@certd/pipeline"; import { HttpRequestConfig } from "@certd/basic"; import { CertInfo } from "@certd/plugin-cert"; - - /** */ @IsAccess({ name: "wangsu", title: "网宿授权", desc: "", - icon: "svg:icon-wangsu" + icon: "svg:icon-wangsu", }) export class WangsuAccess extends BaseAccess { - @AccessInput({ title: "accessKeyId", component: { placeholder: "accessKeyId", component: { name: "a-input", - vModel: "value" - } + vModel: "value", + }, }, helper: "[点击前往获取AccessKey](https://console.wangsu.com/account/accessKey?rsr=ws)", encrypt: false, - required: true + required: true, }) accessKeyId!: string; @@ -35,31 +32,30 @@ export class WangsuAccess extends BaseAccess { placeholder: "accessKeySecret", component: { name: "a-input", - vModel: "value" - } + vModel: "value", + }, }, encrypt: true, - required: true + required: true, }) accessKeySecret!: string; - @AccessInput({ title: "测试", component: { name: "api-test", - action: "TestRequest" + action: "TestRequest", }, - helper: "点击测试接口是否正常" + helper: "点击测试接口是否正常", }) testRequest = true; async onTestRequest() { - await this.getCertList({ }); + await this.getCertList({}); return "ok"; } - async getCertList(req: { }) { + async getCertList(req: {}) { /** * certificate-id * name @@ -70,28 +66,24 @@ export class WangsuAccess extends BaseAccess { method: "GET", }); - return res["ssl-certificate"] + return res["ssl-certificate"]; } - async getCertInfo(req:{certId:string}){ + async getCertInfo(req: { certId: string }) { return await this.doRequest({ url: `/api/certificate/${req.certId}`, - method:"GET", + method: "GET", }); } - async updateCert(req: { - certId: string, - cert: CertInfo, - }) { - - const certInfo= await this.getCertInfo({certId:req.certId}); + async updateCert(req: { certId: string; cert: CertInfo }) { + const certInfo = await this.getCertInfo({ certId: req.certId }); const name = certInfo.name; - const {cert,certId} = req; + const { cert, certId } = req; return await this.doRequest({ url: `/api/certificate/${certId}`, - method:"PUT", + method: "PUT", data: { /** * name: string; @@ -102,24 +94,20 @@ export class WangsuAccess extends BaseAccess { * csrId?: number; * comment?: string; */ - name:name, + name: name, certificate: cert.crt, privateKey: cert.key, - autoRenew:"false", - isNeedAlarm:"false", - comment: "certd" - } + autoRenew: "false", + isNeedAlarm: "false", + comment: "certd", + }, }); } - - - async doRequest(req: HttpRequestConfig) { - const data: any = req.data; - const {AkSkConfig,AkSkAuth} = await import("./lib/index.js"); + const { AkSkConfig, AkSkAuth } = await import("./lib/index.js"); const akskConfig = new AkSkConfig(); akskConfig.accessKey = this.accessKeyId; @@ -128,34 +116,32 @@ export class WangsuAccess extends BaseAccess { akskConfig.uri = req.url; akskConfig.method = req.method; - const requestMsg = AkSkAuth.transferHttpRequestMsg(akskConfig,data?JSON.stringify(data):""); + const requestMsg = AkSkAuth.transferHttpRequestMsg(akskConfig, data ? JSON.stringify(data) : ""); AkSkAuth.getAuthAndSetHeaders(requestMsg, akskConfig.accessKey, akskConfig.secretKey); - let response = undefined - try{ - response = await this.ctx.http.request({ + let response = undefined; + try { + response = await this.ctx.http.request({ method: requestMsg.method, url: requestMsg.url, headers: requestMsg.headers, - data: requestMsg.body + data: requestMsg.body, }); - }catch (e) { + } catch (e) { if (e.response?.data?.result) { throw new Error(e.response?.data?.result); } throw e; } - if (response.code != null && response.code != 0){ + if (response.code != null && response.code != 0) { throw new Error(response.message); } - if (response.data != null && response.code!==null){ + if (response.data != null && response.code !== null) { return response.data; } return response; - } } - new WangsuAccess(); diff --git a/packages/ui/certd-server/src/plugins/plugin-wangsu/lib/auth/AkSkAuth.ts b/packages/ui/certd-server/src/plugins/plugin-wangsu/lib/auth/AkSkAuth.ts index c3cd2ca88..5f1f4967e 100644 --- a/packages/ui/certd-server/src/plugins/plugin-wangsu/lib/auth/AkSkAuth.ts +++ b/packages/ui/certd-server/src/plugins/plugin-wangsu/lib/auth/AkSkAuth.ts @@ -5,83 +5,87 @@ import { HttpUtils } from "../util/HttpUtils.js"; import { Constant } from "../common/Constant.js"; export class AkSkAuth { + public static invoke(akSkConfig: AkSkConfig, jsonBody: string): Promise { + const requestMsg = AkSkAuth.transferHttpRequestMsg(akSkConfig, jsonBody); + AkSkAuth.getAuthAndSetHeaders(requestMsg, akSkConfig.accessKey, akSkConfig.secretKey); + return HttpUtils.call(requestMsg); + } - public static invoke(akSkConfig: AkSkConfig, jsonBody: string): Promise { - const requestMsg = AkSkAuth.transferHttpRequestMsg(akSkConfig, jsonBody); - AkSkAuth.getAuthAndSetHeaders(requestMsg, akSkConfig.accessKey, akSkConfig.secretKey); - return HttpUtils.call(requestMsg); + static transferHttpRequestMsg(akSkConfig: AkSkConfig, jsonBody: string): HttpRequestMsg { + const requestMsg = new HttpRequestMsg(); + requestMsg.uri = akSkConfig.uri; + if (akSkConfig.endPoint && akSkConfig.endPoint !== Constant.END_POINT) { + requestMsg.host = akSkConfig.endPoint; + requestMsg.url = `${Constant.HTTPS_REQUEST_PREFIX}${akSkConfig.endPoint}${requestMsg.uri}`; + } else { + requestMsg.host = Constant.HTTP_DOMAIN; + requestMsg.url = `${Constant.HTTP_REQUEST_PREFIX}${requestMsg.uri}`; } - - static transferHttpRequestMsg(akSkConfig: AkSkConfig, jsonBody: string): HttpRequestMsg { - const requestMsg = new HttpRequestMsg(); - requestMsg.uri = akSkConfig.uri; - if (akSkConfig.endPoint && akSkConfig.endPoint !== Constant.END_POINT) { - requestMsg.host = akSkConfig.endPoint; - requestMsg.url = `${Constant.HTTPS_REQUEST_PREFIX}${akSkConfig.endPoint}${requestMsg.uri}`; - } else { - requestMsg.host = Constant.HTTP_DOMAIN; - requestMsg.url = `${Constant.HTTP_REQUEST_PREFIX}${requestMsg.uri}`; - } - requestMsg.method = akSkConfig.method; - requestMsg.signedHeaders = AkSkAuth.getSignedHeaders(akSkConfig.signedHeaders); - if (['POST', 'PUT', 'PATCH', 'DELETE'].indexOf(akSkConfig.method) !== -1) { - requestMsg.body = jsonBody; - } - return requestMsg; + requestMsg.method = akSkConfig.method; + requestMsg.signedHeaders = AkSkAuth.getSignedHeaders(akSkConfig.signedHeaders); + if (["POST", "PUT", "PATCH", "DELETE"].indexOf(akSkConfig.method) !== -1) { + requestMsg.body = jsonBody; } + return requestMsg; + } - static getAuthAndSetHeaders(requestMsg: HttpRequestMsg, accessKey: string, secretKey: string): void { - const timeStamp = (Date.now() / 1000 | 0).toString(); - requestMsg.headers['Host'] = requestMsg.host; - requestMsg.headers[Constant.HEAD_SIGN_ACCESS_KEY] = accessKey; - requestMsg.headers[Constant.HEAD_SIGN_TIMESTAMP] = timeStamp; - requestMsg.headers["Accept"] = Constant.APPLICATION_JSON; - const signature = AkSkAuth.getSignature(requestMsg, secretKey, timeStamp); - requestMsg.headers['Authorization'] = AkSkAuth.genAuthorization(accessKey, AkSkAuth.getSignedHeaders(requestMsg.signedHeaders), signature); + static getAuthAndSetHeaders(requestMsg: HttpRequestMsg, accessKey: string, secretKey: string): void { + const timeStamp = ((Date.now() / 1000) | 0).toString(); + requestMsg.headers["Host"] = requestMsg.host; + requestMsg.headers[Constant.HEAD_SIGN_ACCESS_KEY] = accessKey; + requestMsg.headers[Constant.HEAD_SIGN_TIMESTAMP] = timeStamp; + requestMsg.headers["Accept"] = Constant.APPLICATION_JSON; + const signature = AkSkAuth.getSignature(requestMsg, secretKey, timeStamp); + requestMsg.headers["Authorization"] = AkSkAuth.genAuthorization(accessKey, AkSkAuth.getSignedHeaders(requestMsg.signedHeaders), signature); + } + + private static genAuthorization(accessKey: string, signedHeaders: string, signature: string): string { + return `${Constant.HEAD_SIGN_ALGORITHM} Credential=${accessKey}, SignedHeaders=${signedHeaders}, Signature=${signature}`; + } + + private static getSignature(requestMsg: HttpRequestMsg, secretKey: string, timestamp: string): string { + const bodyStr = requestMsg.body || ""; + const hashedRequestPayload = CryptoUtils.sha256Hex(bodyStr); + const canonicalRequest = `${requestMsg.method}\n${requestMsg.uri.split("?")[0]}\n${decodeURIComponent(requestMsg.getQueryString())}\n${AkSkAuth.getCanonicalHeaders( + requestMsg.headers, + AkSkAuth.getSignedHeaders(requestMsg.signedHeaders) + )}\n${AkSkAuth.getSignedHeaders(requestMsg.signedHeaders)}\n${hashedRequestPayload}`; + const stringToSign = `${Constant.HEAD_SIGN_ALGORITHM}\n${timestamp}\n${CryptoUtils.sha256Hex(canonicalRequest)}`; + return CryptoUtils.hmac256(secretKey, stringToSign).toLowerCase(); + } + + private static getCanonicalHeaders(headers: Record, signedHeaders: string): string { + const headerNames = signedHeaders.split(";"); + let canonicalHeaders = ""; + for (const headerName of headerNames) { + const headerValue = AkSkAuth.getValueByHeader(headerName, headers); + if (headerValue !== null) { + canonicalHeaders += `${headerName}:${headerValue.toLowerCase()}\n`; + } else { + // Handle missing headers if necessary, e.g., log a warning or skip + console.warn(`Header ${headerName} not found in provided headers.`); + } } + return canonicalHeaders; + } - private static genAuthorization(accessKey: string, signedHeaders: string, signature: string): string { - return `${Constant.HEAD_SIGN_ALGORITHM} Credential=${accessKey}, SignedHeaders=${signedHeaders}, Signature=${signature}`; + private static getSignedHeaders(signedHeaders: string): string { + if (!signedHeaders) { + return "content-type;host"; } + const headers = signedHeaders.split(";"); + return headers + .map(header => header.toLowerCase()) + .sort() + .join(";"); + } - private static getSignature(requestMsg: HttpRequestMsg, secretKey: string, timestamp: string): string { - let bodyStr = requestMsg.body || ""; - const hashedRequestPayload = CryptoUtils.sha256Hex(bodyStr); - const canonicalRequest = `${requestMsg.method}\n${requestMsg.uri.split("?")[0]}\n${decodeURIComponent(requestMsg.getQueryString())}\n${AkSkAuth.getCanonicalHeaders(requestMsg.headers, AkSkAuth.getSignedHeaders(requestMsg.signedHeaders))}\n${AkSkAuth.getSignedHeaders(requestMsg.signedHeaders)}\n${hashedRequestPayload}`; - const stringToSign = `${Constant.HEAD_SIGN_ALGORITHM}\n${timestamp}\n${CryptoUtils.sha256Hex(canonicalRequest)}`; - return CryptoUtils.hmac256(secretKey, stringToSign).toLowerCase(); - } - - private static getCanonicalHeaders(headers: Record, signedHeaders: string): string { - const headerNames = signedHeaders.split(";"); - let canonicalHeaders = ""; - for (const headerName of headerNames) { - const headerValue = AkSkAuth.getValueByHeader(headerName, headers); - if (headerValue !== null) { - canonicalHeaders += `${headerName}:${headerValue.toLowerCase()}\n`; - } else { - // Handle missing headers if necessary, e.g., log a warning or skip - console.warn(`Header ${headerName} not found in provided headers.`); - } - } - return canonicalHeaders; - } - - - private static getSignedHeaders(signedHeaders: string): string { - if (!signedHeaders) { - return "content-type;host"; - } - const headers = signedHeaders.split(";"); - return headers.map(header => header.toLowerCase()).sort().join(";"); - } - - private static getValueByHeader(name: string, customHeaderMap: { [key: string]: string }): string | null { - for (const key in customHeaderMap) { - if (key.toLowerCase() === name.toLowerCase()) { - return customHeaderMap[key]; - } - } - return null; + private static getValueByHeader(name: string, customHeaderMap: { [key: string]: string }): string | null { + for (const key in customHeaderMap) { + if (key.toLowerCase() === name.toLowerCase()) { + return customHeaderMap[key]; + } } + return null; + } } diff --git a/packages/ui/certd-server/src/plugins/plugin-wangsu/lib/common/Constant.ts b/packages/ui/certd-server/src/plugins/plugin-wangsu/lib/common/Constant.ts index 6d8605092..4771efb75 100644 --- a/packages/ui/certd-server/src/plugins/plugin-wangsu/lib/common/Constant.ts +++ b/packages/ui/certd-server/src/plugins/plugin-wangsu/lib/common/Constant.ts @@ -1,19 +1,19 @@ export class Constant { - private constructor() {} + private constructor() {} - public static readonly HTTP_REQUEST_PREFIX: string = "https://open.chinanetcenter.com"; - public static readonly HTTPS_REQUEST_PREFIX: string = "https://"; - public static readonly HTTP_DOMAIN: string = "open.chinanetcenter.com"; + public static readonly HTTP_REQUEST_PREFIX: string = "https://open.chinanetcenter.com"; + public static readonly HTTPS_REQUEST_PREFIX: string = "https://"; + public static readonly HTTP_DOMAIN: string = "open.chinanetcenter.com"; - public static readonly APPLICATION_JSON: string = "application/json"; + public static readonly APPLICATION_JSON: string = "application/json"; - public static readonly HEAD_SIGN_ACCESS_KEY: string = "x-cnc-accessKey"; - public static readonly HEAD_SIGN_TIMESTAMP: string = "x-cnc-timestamp"; - public static readonly HEAD_SIGN_ALGORITHM: string = "CNC-HMAC-SHA256"; + public static readonly HEAD_SIGN_ACCESS_KEY: string = "x-cnc-accessKey"; + public static readonly HEAD_SIGN_TIMESTAMP: string = "x-cnc-timestamp"; + public static readonly HEAD_SIGN_ALGORITHM: string = "CNC-HMAC-SHA256"; - public static readonly X_CNC_AUTH_METHOD: string = "x-cnc-auth-method"; + public static readonly X_CNC_AUTH_METHOD: string = "x-cnc-auth-method"; - public static readonly AUTH_METHOD: string = "AKSK"; + public static readonly AUTH_METHOD: string = "AKSK"; - public static readonly END_POINT: string = "{endPoint}"; + public static readonly END_POINT: string = "{endPoint}"; } diff --git a/packages/ui/certd-server/src/plugins/plugin-wangsu/lib/exception/ApiAuthException.ts b/packages/ui/certd-server/src/plugins/plugin-wangsu/lib/exception/ApiAuthException.ts index 5117760d4..c2089c3ab 100644 --- a/packages/ui/certd-server/src/plugins/plugin-wangsu/lib/exception/ApiAuthException.ts +++ b/packages/ui/certd-server/src/plugins/plugin-wangsu/lib/exception/ApiAuthException.ts @@ -1,9 +1,9 @@ export class ApiAuthException extends Error { - public cause?: any; + public cause?: any; - constructor(message: string, cause?: any) { - super(message); - this.cause = cause; - this.name = 'ApiAuthException'; - } + constructor(message: string, cause?: any) { + super(message); + this.cause = cause; + this.name = "ApiAuthException"; + } } diff --git a/packages/ui/certd-server/src/plugins/plugin-wangsu/lib/index.ts b/packages/ui/certd-server/src/plugins/plugin-wangsu/lib/index.ts index ebdf314ea..fd9b83026 100644 --- a/packages/ui/certd-server/src/plugins/plugin-wangsu/lib/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-wangsu/lib/index.ts @@ -1,4 +1,4 @@ import { AkSkConfig } from "./model/AkSkConfig.js"; import { AkSkAuth } from "./auth/AkSkAuth.js"; -export { AkSkAuth, AkSkConfig} +export { AkSkAuth, AkSkConfig }; diff --git a/packages/ui/certd-server/src/plugins/plugin-wangsu/lib/model/AkSkConfig.ts b/packages/ui/certd-server/src/plugins/plugin-wangsu/lib/model/AkSkConfig.ts index ab41c4af6..6ad27bf10 100644 --- a/packages/ui/certd-server/src/plugins/plugin-wangsu/lib/model/AkSkConfig.ts +++ b/packages/ui/certd-server/src/plugins/plugin-wangsu/lib/model/AkSkConfig.ts @@ -1,56 +1,56 @@ export class AkSkConfig { - private _accessKey: string | undefined; - private _secretKey: string | undefined; - private _uri: string | undefined; - private _endPoint: string | undefined; - private _method: string | undefined; - private _signedHeaders: string | undefined; + private _accessKey: string | undefined; + private _secretKey: string | undefined; + private _uri: string | undefined; + private _endPoint: string | undefined; + private _method: string | undefined; + private _signedHeaders: string | undefined; - public get accessKey(): string { - return this._accessKey; - } + public get accessKey(): string { + return this._accessKey; + } - public set accessKey(value: string) { - this._accessKey = value; - } + public set accessKey(value: string) { + this._accessKey = value; + } - public get secretKey(): string { - return this._secretKey; - } + public get secretKey(): string { + return this._secretKey; + } - public set secretKey(value: string) { - this._secretKey = value; - } + public set secretKey(value: string) { + this._secretKey = value; + } - public get uri(): string { - return this._uri; - } + public get uri(): string { + return this._uri; + } - public set uri(value: string) { - this._uri = value; - } + public set uri(value: string) { + this._uri = value; + } - public get endPoint(): string { - return this._endPoint; - } + public get endPoint(): string { + return this._endPoint; + } - public set endPoint(value: string) { - this._endPoint = value; - } + public set endPoint(value: string) { + this._endPoint = value; + } - public get method(): string { - return this._method; - } + public get method(): string { + return this._method; + } - public set method(value: string) { - this._method = value; - } + public set method(value: string) { + this._method = value; + } - public get signedHeaders(): string { - return this._signedHeaders; - } + public get signedHeaders(): string { + return this._signedHeaders; + } - public set signedHeaders(value: string) { - this._signedHeaders = value; - } + public set signedHeaders(value: string) { + this._signedHeaders = value; + } } diff --git a/packages/ui/certd-server/src/plugins/plugin-wangsu/lib/model/HttpRequestMsg.ts b/packages/ui/certd-server/src/plugins/plugin-wangsu/lib/model/HttpRequestMsg.ts index 89c761ef2..603f5f00b 100644 --- a/packages/ui/certd-server/src/plugins/plugin-wangsu/lib/model/HttpRequestMsg.ts +++ b/packages/ui/certd-server/src/plugins/plugin-wangsu/lib/model/HttpRequestMsg.ts @@ -1,75 +1,74 @@ -import { Constant } from '../common/Constant.js'; // Assuming you have a TypeScript version of this +import { Constant } from "../common/Constant.js"; // Assuming you have a TypeScript version of this export class HttpRequestMsg { - uri: string ; - url: string; - host: string; - method: string; - protocol: string; - params: Record; - headers: Record; - body: string; - signedHeaders: string; - msg: any; + uri: string; + url: string; + host: string; + method: string; + protocol: string; + params: Record; + headers: Record; + body: string; + signedHeaders: string; + msg: any; - constructor() { - this.params = {}; - this.headers = {}; - this.putHeader('Content-Type', Constant.APPLICATION_JSON); - this.putHeader(Constant.X_CNC_AUTH_METHOD, Constant.AUTH_METHOD); - } + constructor() { + this.params = {}; + this.headers = {}; + this.putHeader("Content-Type", Constant.APPLICATION_JSON); + this.putHeader(Constant.X_CNC_AUTH_METHOD, Constant.AUTH_METHOD); + } - putParam(name: string, value: string): void { - this.params[name] = value; - } + putParam(name: string, value: string): void { + this.params[name] = value; + } - getParam(name: string): string | null { - const value = this.params[name]; - return value && value.trim() !== '' ? value : null; - } + getParam(name: string): string | null { + const value = this.params[name]; + return value && value.trim() !== "" ? value : null; + } - getQueryString(): string { - if(this.uri == undefined) - return ""; - const index = this.uri.indexOf("?"); - if (this.method === 'POST' || index === -1) { - return ""; - } - return this.uri.substring(index + 1); + getQueryString(): string { + if (this.uri == undefined) return ""; + const index = this.uri.indexOf("?"); + if (this.method === "POST" || index === -1) { + return ""; } + return this.uri.substring(index + 1); + } - putHeader(name: string, value: string): void { - this.headers[name] = value; - } + putHeader(name: string, value: string): void { + this.headers[name] = value; + } - getHeader(name: string): string | null { - for (const key in this.headers) { - if (key.toLowerCase() === name.toLowerCase()) { - return this.headers[key]; - } - } - return null; + getHeader(name: string): string | null { + for (const key in this.headers) { + if (key.toLowerCase() === name.toLowerCase()) { + return this.headers[key]; + } } + return null; + } - getHeaderByNames(...names: string[]): string | null { - for (const name of names) { - const value = this.getHeader(name); - if (value) { - return value; - } - } - return null; + getHeaderByNames(...names: string[]): string | null { + for (const name of names) { + const value = this.getHeader(name); + if (value) { + return value; + } } + return null; + } - removeHeader(name: string): void { - for (const key in this.headers) { - if (key.toLowerCase() === name.toLowerCase()) { - delete this.headers[key]; - } - } + removeHeader(name: string): void { + for (const key in this.headers) { + if (key.toLowerCase() === name.toLowerCase()) { + delete this.headers[key]; + } } + } - setJsonBody(object: any): void { - this.body = JSON.stringify(object); - } + setJsonBody(object: any): void { + this.body = JSON.stringify(object); + } } diff --git a/packages/ui/certd-server/src/plugins/plugin-wangsu/lib/util/CryptoUtils.ts b/packages/ui/certd-server/src/plugins/plugin-wangsu/lib/util/CryptoUtils.ts index 11a310e78..78a022b18 100644 --- a/packages/ui/certd-server/src/plugins/plugin-wangsu/lib/util/CryptoUtils.ts +++ b/packages/ui/certd-server/src/plugins/plugin-wangsu/lib/util/CryptoUtils.ts @@ -1,23 +1,23 @@ -import CryptoJS from 'crypto-js'; +import CryptoJS from "crypto-js"; export class CryptoUtils { - private constructor() {} + private constructor() {} - /** - * hmac+sha256+hex - */ - public static sha256Hex(s: string): string { - const hash = CryptoJS.SHA256(s); - return hash.toString(CryptoJS.enc.Hex).toLowerCase(); - } + /** + * hmac+sha256+hex + */ + public static sha256Hex(s: string): string { + const hash = CryptoJS.SHA256(s); + return hash.toString(CryptoJS.enc.Hex).toLowerCase(); + } - /** - * hmac+sha256 - */ - public static hmac256(secretKey: string, message: string): string { - const keyWordArray = CryptoJS.enc.Utf8.parse(secretKey); - const messageWordArray = CryptoJS.enc.Utf8.parse(message); - const hash = CryptoJS.HmacSHA256(messageWordArray, keyWordArray); - return hash.toString(CryptoJS.enc.Hex).toLowerCase(); - } + /** + * hmac+sha256 + */ + public static hmac256(secretKey: string, message: string): string { + const keyWordArray = CryptoJS.enc.Utf8.parse(secretKey); + const messageWordArray = CryptoJS.enc.Utf8.parse(message); + const hash = CryptoJS.HmacSHA256(messageWordArray, keyWordArray); + return hash.toString(CryptoJS.enc.Hex).toLowerCase(); + } } diff --git a/packages/ui/certd-server/src/plugins/plugin-wangsu/lib/util/HttpUtils.ts b/packages/ui/certd-server/src/plugins/plugin-wangsu/lib/util/HttpUtils.ts index 81c332491..e3187bca6 100644 --- a/packages/ui/certd-server/src/plugins/plugin-wangsu/lib/util/HttpUtils.ts +++ b/packages/ui/certd-server/src/plugins/plugin-wangsu/lib/util/HttpUtils.ts @@ -1,30 +1,30 @@ -import { HttpRequestMsg } from '../model/HttpRequestMsg.js'; // Assuming you have a TypeScript version of this -import { ApiAuthException } from '../exception/ApiAuthException.js'; // Assuming you have a TypeScript version of this -import axios, { AxiosError } from 'axios'; +import { HttpRequestMsg } from "../model/HttpRequestMsg.js"; // Assuming you have a TypeScript version of this +import { ApiAuthException } from "../exception/ApiAuthException.js"; // Assuming you have a TypeScript version of this +import axios, { AxiosError } from "axios"; export class HttpUtils { - private constructor() { } - public static async call(requestMsg: HttpRequestMsg): Promise { - var response; - try { - response = await axios({ - method: requestMsg.method, - url: requestMsg.url, - headers: requestMsg.headers, - data: requestMsg.body - }); - console.info("API invoke success. Response:", response.data); - return response.data; - } catch (error) { - if (error instanceof AxiosError) { - // Handle AxiosError specifically - console.error('API invoke failed. Response:', error.response.data); - return error.response.data; - } else { - // Handle other types of errors - console.error('API invoke failed.', error); - } - throw new ApiAuthException('API invoke failed.'); - } + private constructor() {} + public static async call(requestMsg: HttpRequestMsg): Promise { + let response; + try { + response = await axios({ + method: requestMsg.method, + url: requestMsg.url, + headers: requestMsg.headers, + data: requestMsg.body, + }); + console.info("API invoke success. Response:", response.data); + return response.data; + } catch (error) { + if (error instanceof AxiosError) { + // Handle AxiosError specifically + console.error("API invoke failed. Response:", error.response.data); + return error.response.data; + } else { + // Handle other types of errors + console.error("API invoke failed.", error); + } + throw new ApiAuthException("API invoke failed."); } + } } diff --git a/packages/ui/certd-server/src/plugins/plugin-wangsu/plugins/plugin-refresh-cert.ts b/packages/ui/certd-server/src/plugins/plugin-wangsu/plugins/plugin-refresh-cert.ts index 86b3bc218..c8ce7356e 100644 --- a/packages/ui/certd-server/src/plugins/plugin-wangsu/plugins/plugin-refresh-cert.ts +++ b/packages/ui/certd-server/src/plugins/plugin-wangsu/plugins/plugin-refresh-cert.ts @@ -1,11 +1,4 @@ -import { - AbstractTaskPlugin, - IsTaskPlugin, - PageSearch, - pluginGroups, - RunStrategy, - TaskInput -} from "@certd/pipeline"; +import { AbstractTaskPlugin, IsTaskPlugin, PageSearch, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; import { CertApplyPluginNames, CertInfo } from "@certd/plugin-cert"; import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from "@certd/plugin-lib"; import { WangsuAccess } from "../access.js"; @@ -22,9 +15,9 @@ import { WangsuAccess } from "../access.js"; default: { //默认值配置照抄即可 strategy: { - runStrategy: RunStrategy.SkipWhenSucceed - } - } + runStrategy: RunStrategy.SkipWhenSucceed, + }, + }, }) //类名规范,跟上面插件名称(name)一致 export class WangsuRefreshCert extends AbstractTaskPlugin { @@ -34,8 +27,8 @@ export class WangsuRefreshCert extends AbstractTaskPlugin { helper: "请选择前置任务输出的域名证书", component: { name: "output-selector", - from: [...CertApplyPluginNames] - } + from: [...CertApplyPluginNames], + }, // required: true, // 必填 }) cert!: CertInfo; @@ -48,9 +41,9 @@ export class WangsuRefreshCert extends AbstractTaskPlugin { title: "网宿授权", component: { name: "access-selector", - type: "wangsu" //固定授权类型 + type: "wangsu", //固定授权类型 }, - required: true //必填 + required: true, //必填 }) accessId!: string; // @@ -61,14 +54,13 @@ export class WangsuRefreshCert extends AbstractTaskPlugin { helper: "要更新的网宿证书id", action: WangsuRefreshCert.prototype.onGetCertList.name, pager: false, - search: false + search: false, }) ) certList!: string[]; //插件实例化时执行的方法 - async onInstance() { - } + async onInstance() {} //插件执行方法 async execute(): Promise { @@ -78,7 +70,7 @@ export class WangsuRefreshCert extends AbstractTaskPlugin { this.logger.info(`----------- 开始更新证书:${item}`); await access.updateCert({ certId: item, - cert: this.cert + cert: this.cert, }); this.logger.info(`----------- 更新证书${item}成功`); } @@ -100,19 +92,19 @@ export class WangsuRefreshCert extends AbstractTaskPlugin { * dns-names */ const options = list.map((item: any) => { - const domains = item["dns-names"] + const domains = item["dns-names"]; const certId = item["certificate-id"]; return { label: `${item.name}<${certId}-${domains[0]}>`, value: certId, - domain: item["dns-names"] + domain: item["dns-names"], }; }); return { list: this.ctx.utils.options.buildGroupOptions(options, this.certDomains), total: list.length, pageNo: 1, - pageSize: list.length + pageSize: list.length, }; } } diff --git a/packages/ui/certd-server/src/plugins/plugin-west/access.ts b/packages/ui/certd-server/src/plugins/plugin-west/access.ts index 4f269f606..d45a75722 100644 --- a/packages/ui/certd-server/src/plugins/plugin-west/access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-west/access.ts @@ -1,42 +1,42 @@ -import { HttpRequestConfig } from '@certd/basic'; -import { IsAccess, AccessInput, BaseAccess, PageSearch, Pager } from '@certd/pipeline'; -import qs from 'qs'; -import iconv from 'iconv-lite'; +import { HttpRequestConfig } from "@certd/basic"; +import { IsAccess, AccessInput, BaseAccess, PageSearch, Pager } from "@certd/pipeline"; +import qs from "qs"; +import iconv from "iconv-lite"; /** * 这个注解将注册一个授权配置 * 在certd的后台管理系统中,用户可以选择添加此类型的授权 */ @IsAccess({ - name: 'west', - title: '西部数码授权', - desc: '', - icon: 'tabler:map-west', + name: "west", + title: "西部数码授权", + desc: "", + icon: "tabler:map-west", }) export class WestAccess extends BaseAccess { /** * 授权属性配置 */ @AccessInput({ - title: '权限范围', + title: "权限范围", component: { - name: 'a-select', - vModel: 'value', + name: "a-select", + vModel: "value", options: [ - { value: 'account', label: '账户级别,对所有域名都有权限管理' }, - { value: 'domain', label: '域名级别,仅能管理单个域名' }, + { value: "account", label: "账户级别,对所有域名都有权限管理" }, + { value: "domain", label: "域名级别,仅能管理单个域名" }, ], }, - helper: '选择权限范围', + helper: "选择权限范围", required: true, }) - scope = ''; + scope = ""; /** * 授权属性配置 */ @AccessInput({ - title: '账号', - helper: '你的登录账号', + title: "账号", + helper: "你的登录账号", encrypt: false, required: false, mergeScript: ` @@ -47,17 +47,17 @@ export class WestAccess extends BaseAccess { } `, }) - username = ''; + username = ""; /** * 授权属性配置 */ @AccessInput({ - title: 'ApiKey', + title: "ApiKey", component: { - placeholder: '账户级别的key,对整个账户都有管理权限', + placeholder: "账户级别的key,对整个账户都有管理权限", }, - helper: '账户级别的key,对整个账户都有管理权限\n前往[API接口配置](https://www.west.cn/manager/API/APIconfig.asp),手动设置“api连接密码”', + helper: "账户级别的key,对整个账户都有管理权限\n前往[API接口配置](https://www.west.cn/manager/API/APIconfig.asp),手动设置“api连接密码”", encrypt: true, required: false, mergeScript: ` @@ -68,17 +68,17 @@ export class WestAccess extends BaseAccess { } `, }) - apikey = ''; + apikey = ""; /** * 授权属性配置 */ @AccessInput({ - title: 'apidomainkey', + title: "apidomainkey", component: { - placeholder: '域名级别的key,仅对单个域名有权限', + placeholder: "域名级别的key,仅对单个域名有权限", }, - helper: '域名级别的key,仅对单个域名有权限。 \n前往[西部数据域名管理](https://www.west.cn/manager/domain/),点击域名,右上方点击ApiKey获取密钥', + helper: "域名级别的key,仅对单个域名有权限。 \n前往[西部数据域名管理](https://www.west.cn/manager/domain/),点击域名,右上方点击ApiKey获取密钥", encrypt: true, required: false, mergeScript: ` @@ -89,16 +89,15 @@ export class WestAccess extends BaseAccess { } `, }) - apidomainkey = ''; + apidomainkey = ""; - - /** + /** * 授权属性配置 */ @AccessInput({ - title: '域名', + title: "域名", component: { - placeholder: '域名级别的key对应的域名', + placeholder: "域名级别的key对应的域名", }, encrypt: false, required: false, @@ -110,55 +109,52 @@ export class WestAccess extends BaseAccess { } `, }) - domain = ''; - + domain = ""; @AccessInput({ title: "测试", component: { name: "api-test", - action: "TestRequest" + action: "TestRequest", }, - helper: "点击测试接口是否正常" + helper: "点击测试接口是否正常", }) testRequest = true; async onTestRequest() { - - if(this.scope === 'domain'){ - if(!this.domain){ - throw new Error('domain 必填'); + if (this.scope === "domain") { + if (!this.domain) { + throw new Error("domain 必填"); } - await this.getDomainRecordList({limit:1}); + await this.getDomainRecordList({ limit: 1 }); return "ok"; } - await this.getDomainList({pageNo:1,pageSize:1}); + await this.getDomainList({ pageNo: 1, pageSize: 1 }); return "ok"; } - async getDomainRecordList(req:{limit:number}){ - // 获取域名解析记录列表 - return await this.doDoimainApiRequest('https://api.west.cn/API/v2/domain/dns/',{ - act:'dnsrec.list', - domain:this.domain, + async getDomainRecordList(req: { limit: number }) { + // 获取域名解析记录列表 + return await this.doDoimainApiRequest("https://api.west.cn/API/v2/domain/dns/", { + act: "dnsrec.list", + domain: this.domain, limit: req.limit || 10, - }) + }); } - - async doDoimainApiRequest(url: string, data: any = null, method = 'post') { + async doDoimainApiRequest(url: string, data: any = null, method = "post") { data.apidomainkey = this.apidomainkey; const res = await this.ctx.http.request({ url, method, data, headers: { - 'Content-Type': 'application/x-www-form-urlencoded', + "Content-Type": "application/x-www-form-urlencoded", }, }); - if (res.msg !== 'success') { - if(res.msg.includes('500 already exists')){ + if (res.msg !== "success") { + if (res.msg.includes("500 already exists")) { return res; } throw new Error(`${JSON.stringify(res.msg)}`); @@ -167,31 +163,29 @@ export class WestAccess extends BaseAccess { } async getDomainList(req: PageSearch) { - const pager = new Pager(req) + const pager = new Pager(req); const res = await this.doRequest({ - url: '/v2/domain', - method: 'GET', - data:{ - act:'getdomains', + url: "/v2/domain", + method: "GET", + data: { + act: "getdomains", limit: pager.pageSize, page: pager.pageNo, - } + }, }); return res; } - - public async doRequest(req: HttpRequestConfig) { let { url, method, data } = req; if (data == null) { data = {}; } if (!method) { - method = 'POST'; + method = "POST"; } - if (this.scope === 'account') { + if (this.scope === "account") { /** * token text 身份验证字符串,取值为:md5(username+api_password+timestamp),其中: username:您在我司注册的用户名。 @@ -214,58 +208,56 @@ token=md5(zhangsan + 5dh232kfg!* + 1554691950854)=cfcd208495d565ef66e7dff9f98764 data.apidomainkey = this.apidomainkey; } - - const headers = {} - const body: any = {} - if (method.toUpperCase() === 'POST') { - headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8'; - body.data = data - } else if (method.toUpperCase() === 'GET') { - let queryString = ''; - if (method.toUpperCase() === 'GET') { + const headers = {}; + const body: any = {}; + if (method.toUpperCase() === "POST") { + headers["Content-Type"] = "application/x-www-form-urlencoded; charset=UTF-8"; + body.data = data; + } else if (method.toUpperCase() === "GET") { + let queryString = ""; + if (method.toUpperCase() === "GET") { queryString = qs.stringify(data); } - url = `${url}?${queryString}` + url = `${url}?${queryString}`; } - const res = await this.ctx.http.request({ - baseURL: 'https://api.west.cn/api', + baseURL: "https://api.west.cn/api", url, method, ...body, headers, - responseType: 'arraybuffer', // 关键:获取原始二进制数据 + responseType: "arraybuffer", // 关键:获取原始二进制数据 transformResponse: [ - function(data, headers) { // headers 参数包含响应头 + function (data, headers) { + // headers 参数包含响应头 try { - const contentType = headers['content-type'] || ''; + const contentType = headers["content-type"] || ""; // 判断是否是 GB2312/GBK 编码 //@ts-ignore - if (contentType.includes('gb2312') || contentType.includes('gbk')) { + if (contentType.includes("gb2312") || contentType.includes("gbk")) { // 使用 iconv-lite 解码 - data = iconv.decode(data, 'gb2312'); - }else{ + data = iconv.decode(data, "gb2312"); + } else { // 默认按 UTF-8 处理 - data = data.toString('utf-8'); + data = data.toString("utf-8"); } } catch (error) { - console.error('解码失败:', error); + console.error("解码失败:", error); } return JSON.parse(data); - } - ] + }, + ], }); this.ctx.logger.info(`request ${url} ${method} res:${JSON.stringify(res)}`); - if (res.msg !== 'success' && res.result!= 200) { - if(res.msg.includes('500 already exists')){ + if (res.msg !== "success" && res.result != 200) { + if (res.msg.includes("500 already exists")) { return res; } throw new Error(`${JSON.stringify(res.msg)}`); } return res; } - } new WestAccess(); diff --git a/packages/ui/certd-server/src/plugins/plugin-west/dns-provider-domain.ts b/packages/ui/certd-server/src/plugins/plugin-west/dns-provider-domain.ts index 5f99e10cb..a658fc39c 100644 --- a/packages/ui/certd-server/src/plugins/plugin-west/dns-provider-domain.ts +++ b/packages/ui/certd-server/src/plugins/plugin-west/dns-provider-domain.ts @@ -1,6 +1,6 @@ -import { AbstractDnsProvider, CreateRecordOptions, RemoveRecordOptions } from '@certd/plugin-cert'; +import { AbstractDnsProvider, CreateRecordOptions, RemoveRecordOptions } from "@certd/plugin-cert"; -import { WestAccess } from './access.js'; +import { WestAccess } from "./access.js"; type westRecord = { // 这里定义Record记录的数据结构,跟对应云平台接口返回值一样即可,一般是拿到id就行,用于删除txt解析记录,清理申请痕迹 @@ -11,14 +11,13 @@ type westRecord = { }; }; - export class WestDnsProviderDomain extends AbstractDnsProvider { access!: WestAccess; async onInstance() { - this.access = this.ctx.access as WestAccess + this.access = this.ctx.access as WestAccess; // 也可以通过ctx成员变量传递context - this.logger.debug('access:', this.access); + this.logger.debug("access:", this.access); //初始化的操作 //... } @@ -35,26 +34,26 @@ export class WestDnsProviderDomain extends AbstractDnsProvider { * domain: 'example.com' */ const { fullRecord, value, type, domain } = options; - this.logger.info('添加域名解析:', fullRecord, value, type, domain); + this.logger.info("添加域名解析:", fullRecord, value, type, domain); // 准备要发送到API的请求体 const requestBody = { - act: 'dnsrec.add', // API动作类型 + act: "dnsrec.add", // API动作类型 domain: domain, // 域名 - record_type: 'TXT', // DNS记录类型 + record_type: "TXT", // DNS记录类型 hostname: fullRecord, // 完整的记录名 record_value: value, // 记录的值 - record_line: '', // 记录线路 + record_line: "", // 记录线路 record_ttl: 60, // TTL (生存时间),设置为60秒 }; - const url = 'https://api.west.cn/API/v2/domain/dns/'; + const url = "https://api.west.cn/API/v2/domain/dns/"; const res = await this.access.doDoimainApiRequest(url, requestBody); const record = res as westRecord; this.logger.info(`添加域名解析成功:fullRecord=${fullRecord},value=${value}`); this.logger.info(`dns解析记录:${JSON.stringify(record)}`); // 西部数码生效较慢 增加90秒等待 提高成功率 - this.logger.info('等待解析生效:wait 90s'); + this.logger.info("等待解析生效:wait 90s"); await new Promise(resolve => setTimeout(resolve, 90000)); return record; } @@ -66,31 +65,31 @@ export class WestDnsProviderDomain extends AbstractDnsProvider { async removeRecord(options: RemoveRecordOptions): Promise { const { fullRecord, value, domain } = options.recordReq; const record = options.recordRes; - this.logger.info('删除域名解析:', fullRecord, value, record); + this.logger.info("删除域名解析:", fullRecord, value, record); if (!record) { - this.logger.info('record不存在'); + this.logger.info("record不存在"); return; } //这里调用删除txt dns解析记录接口 const record_id = record?.body?.record_id; if (!record_id) { - this.logger.info('record_id不存在'); + this.logger.info("record_id不存在"); return; } // 准备要发送到API的请求体 const requestBody = { - act: 'dnsrec.remove', // API动作类型 + act: "dnsrec.remove", // API动作类型 domain: domain, // 域名 record_id: record_id, hostname: fullRecord, // 完整的记录名 - record_type: 'TXT', // DNS记录类型 - record_line: '', // 记录线路 + record_type: "TXT", // DNS记录类型 + record_line: "", // 记录线路 }; - const url = 'https://api.west.cn/API/v2/domain/dns/'; + const url = "https://api.west.cn/API/v2/domain/dns/"; const res = await this.access.doDoimainApiRequest(url, requestBody); const result = res.result; - this.logger.info('删除域名解析成功:', fullRecord, value, JSON.stringify(result)); + this.logger.info("删除域名解析成功:", fullRecord, value, JSON.stringify(result)); } } diff --git a/packages/ui/certd-server/src/plugins/plugin-west/dns-provider.ts b/packages/ui/certd-server/src/plugins/plugin-west/dns-provider.ts index c067d15a4..0807c9eef 100644 --- a/packages/ui/certd-server/src/plugins/plugin-west/dns-provider.ts +++ b/packages/ui/certd-server/src/plugins/plugin-west/dns-provider.ts @@ -1,7 +1,7 @@ -import { PageRes, PageSearch } from '@certd/pipeline'; -import { AbstractDnsProvider, CreateRecordOptions, DomainRecord, IsDnsProvider, RemoveRecordOptions } from '@certd/plugin-cert'; -import { WestAccess } from './access.js'; -import { WestDnsProviderDomain } from './dns-provider-domain.js'; +import { PageRes, PageSearch } from "@certd/pipeline"; +import { AbstractDnsProvider, CreateRecordOptions, DomainRecord, IsDnsProvider, RemoveRecordOptions } from "@certd/plugin-cert"; +import { WestAccess } from "./access.js"; +import { WestDnsProviderDomain } from "./dns-provider-domain.js"; type westRecord = { // 这里定义Record记录的数据结构,跟对应云平台接口返回值一样即可,一般是拿到id就行,用于删除txt解析记录,清理申请痕迹 @@ -14,25 +14,25 @@ type westRecord = { // 这里通过IsDnsProvider注册一个dnsProvider @IsDnsProvider({ - name: 'west', - title: '西部数码', - desc: 'west dns provider', - icon: 'svg:icon-xibushuma', + name: "west", + title: "西部数码", + desc: "west dns provider", + icon: "svg:icon-xibushuma", // 这里是对应的云平台的access类型名称 - accessType: 'west', + accessType: "west", }) export class WestDnsProvider extends AbstractDnsProvider { access!: WestAccess; async onInstance() { - this.access = this.ctx.access as WestAccess + this.access = this.ctx.access as WestAccess; // 也可以通过ctx成员变量传递context - this.logger.debug('access:', this.access); + this.logger.debug("access:", this.access); //初始化的操作 //... } - getDomainProvider(){ + getDomainProvider() { const provider = new WestDnsProviderDomain(); provider.access = this.access; provider.logger = this.logger; @@ -45,8 +45,7 @@ export class WestDnsProvider extends AbstractDnsProvider { * 创建dns解析记录,用于验证域名所有权 */ async createRecord(options: CreateRecordOptions): Promise { - - if(this.access.scope === 'domain'){ + if (this.access.scope === "domain") { //如果是域名级别的,走老接口 const provider = this.getDomainProvider(); return provider.createRecord(options); @@ -59,31 +58,31 @@ export class WestDnsProvider extends AbstractDnsProvider { * type: 'TXT', * domain: 'example.com' */ - const { fullRecord, value, type, domain,hostRecord } = options; - this.logger.info('添加域名解析:', fullRecord, value, type, domain); + const { fullRecord, value, type, domain, hostRecord } = options; + this.logger.info("添加域名解析:", fullRecord, value, type, domain); // 准备要发送到API的请求体 const requestBody = { - act: 'adddnsrecord', // API动作类型 + act: "adddnsrecord", // API动作类型 domain: domain, // 域名 - type: 'TXT', // DNS记录类型 + type: "TXT", // DNS记录类型 host: hostRecord, // 完整的记录名 value: value, // 记录的值 - line: '', // 记录线路 + line: "", // 记录线路 ttl: 60, // TTL (生存时间),设置为60秒 }; - const url = '/v2/domain/'; + const url = "/v2/domain/"; const res = await this.access.doRequest({ url, - method:'POST', + method: "POST", data: requestBody, }); const record = res as westRecord; this.logger.info(`添加域名解析成功:fullRecord=${fullRecord},value=${value}`); this.logger.info(`dns解析记录:${JSON.stringify(record)}`); // 西部数码生效较慢 增加90秒等待 提高成功率 - this.logger.info('等待解析生效:wait 90s'); + this.logger.info("等待解析生效:wait 90s"); await new Promise(resolve => setTimeout(resolve, 90000)); return record; } @@ -94,7 +93,7 @@ export class WestDnsProvider extends AbstractDnsProvider { * @param options */ async removeRecord(options: RemoveRecordOptions): Promise { - if(this.access.scope === 'domain'){ + if (this.access.scope === "domain") { //如果是域名级别的,走老接口 const provider = this.getDomainProvider(); return provider.removeRecord(options as any); @@ -102,32 +101,32 @@ export class WestDnsProvider extends AbstractDnsProvider { const { fullRecord, value, domain } = options.recordReq; const record = options.recordRes; - this.logger.info('删除域名解析:', fullRecord, value, record); + this.logger.info("删除域名解析:", fullRecord, value, record); if (!record) { - this.logger.info('record不存在'); + this.logger.info("record不存在"); return; } //这里调用删除txt dns解析记录接口 const record_id = record.data?.id; if (!record_id) { - this.logger.info('record_id不存在'); + this.logger.info("record_id不存在"); return; } // 准备要发送到API的请求体 const requestBody = { - act: 'deldnsrecord', // API动作类型 + act: "deldnsrecord", // API动作类型 domain: domain, // 域名 id: record_id, }; - const url = '/v2/domain/'; + const url = "/v2/domain/"; const res = await this.access.doRequest({ url, - method:'POST', + method: "POST", data: requestBody, }); const result = res.result; - this.logger.info('删除域名解析成功:', fullRecord, value, JSON.stringify(result)); + this.logger.info("删除域名解析成功:", fullRecord, value, JSON.stringify(result)); } async getDomainListPage(req: PageSearch): Promise> { diff --git a/packages/ui/certd-server/src/plugins/plugin-west/index.ts b/packages/ui/certd-server/src/plugins/plugin-west/index.ts index 8f767a7cc..9c5ac8009 100644 --- a/packages/ui/certd-server/src/plugins/plugin-west/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-west/index.ts @@ -1,3 +1,3 @@ -export * from './dns-provider.js'; -export * from './access.js'; -export * from './plugins/deploy-to-vhost.js'; \ No newline at end of file +export * from "./dns-provider.js"; +export * from "./access.js"; +export * from "./plugins/deploy-to-vhost.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-west/plugins/deploy-to-vhost.ts b/packages/ui/certd-server/src/plugins/plugin-west/plugins/deploy-to-vhost.ts index b55c357a2..a673fe97c 100644 --- a/packages/ui/certd-server/src/plugins/plugin-west/plugins/deploy-to-vhost.ts +++ b/packages/ui/certd-server/src/plugins/plugin-west/plugins/deploy-to-vhost.ts @@ -1,11 +1,4 @@ -import { - AbstractTaskPlugin, - IsTaskPlugin, - PageSearch, - pluginGroups, - RunStrategy, - TaskInput -} from "@certd/pipeline"; +import { AbstractTaskPlugin, IsTaskPlugin, PageSearch, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; import { CertApplyPluginNames, CertInfo } from "@certd/plugin-cert"; import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from "@certd/plugin-lib"; import { WestAccess } from "../access.js"; @@ -22,9 +15,9 @@ import { WestAccess } from "../access.js"; default: { //默认值配置照抄即可 strategy: { - runStrategy: RunStrategy.SkipWhenSucceed - } - } + runStrategy: RunStrategy.SkipWhenSucceed, + }, + }, }) //类名规范,跟上面插件名称(name)一致 export class WestDeployToVhost extends AbstractTaskPlugin { @@ -34,8 +27,8 @@ export class WestDeployToVhost extends AbstractTaskPlugin { helper: "请选择前置任务输出的域名证书", component: { name: "output-selector", - from: [...CertApplyPluginNames] - } + from: [...CertApplyPluginNames], + }, // required: true, // 必填 }) cert!: CertInfo; @@ -43,27 +36,25 @@ export class WestDeployToVhost extends AbstractTaskPlugin { @TaskInput(createCertDomainGetterInputDefine({ props: { required: false } })) certDomains!: string[]; - //授权选择框 @TaskInput({ title: "西数授权", component: { name: "access-selector", - type: "west" //固定授权类型 + type: "west", //固定授权类型 }, - required: true //必填 + required: true, //必填 }) accessId!: string; // - @TaskInput( createRemoteSelectInputDefine({ title: "虚拟主机列表", helper: "虚拟主机列表", action: WestDeployToVhost.prototype.onGetVhostList.name, pager: false, - search: false + search: false, }) ) vhostList!: string[]; @@ -80,8 +71,7 @@ export class WestDeployToVhost extends AbstractTaskPlugin { // certList!: string[]; //插件实例化时执行的方法 - async onInstance() { - } + async onInstance() {} //插件执行方法 async execute(): Promise { @@ -91,9 +81,9 @@ export class WestDeployToVhost extends AbstractTaskPlugin { this.logger.info(`----------- 开始更新证书到虚拟主机:${item}`); const arr = item.split("_"); const sitename = arr[1]; - await this.uploadCert({access,sitename}); + await this.uploadCert({ access, sitename }); await this.ctx.utils.sleep(2000); - const res = await this.getVhostSslInfo({access,sitename}); + const res = await this.getVhostSslInfo({ access, sitename }); this.logger.info(`----------- 虚拟主机${sitename}证书信息:${JSON.stringify(res)}`); this.logger.info(`----------- 更新证书${item}成功`); } @@ -131,10 +121,10 @@ export class WestDeployToVhost extends AbstractTaskPlugin { // }; // } - async uploadCert(req:{access:any,sitename:string}){ - const {access,sitename} = req; - const data = { - /** + async uploadCert(req: { access: any; sitename: string }) { + const { access, sitename } = req; + const data = { + /** * act vhostssl 是 @@ -154,50 +144,50 @@ String 私匙 certcontent */ - act:"vhostssl", - sitename:sitename, - westly:"1", - cmd:"import", - opensslclosessl:"openssl", - keycontent:this.cert.key, - certcontent:this.cert.crt, - } + act: "vhostssl", + sitename: sitename, + westly: "1", + cmd: "import", + opensslclosessl: "openssl", + keycontent: this.cert.key, + certcontent: this.cert.crt, + }; - const res = await access.doRequest({ - url: `/v2/vhost/`, - method:"POST", - data:data - }); - return res; - } - - async getVhostSslInfo(req:{access:any,sitename:string}){ - const {access,sitename} = req; - const data = { - act:"vhostssl", - sitename:sitename, - cmd:"info", - } const res = await access.doRequest({ url: `/v2/vhost/`, - method:"POST", - data:data + method: "POST", + data: data, }); return res; } - async onGetVhostList(data: PageSearch = {}) { + async getVhostSslInfo(req: { access: any; sitename: string }) { + const { access, sitename } = req; + const data = { + act: "vhostssl", + sitename: sitename, + cmd: "info", + }; + const res = await access.doRequest({ + url: `/v2/vhost/`, + method: "POST", + data: data, + }); + return res; + } + + async onGetVhostList(data: PageSearch = {}) { const access = await this.getAccess(this.accessId); const res = await access.doRequest({ url: `/v2/vhost/`, - method:"POST", - data:{ - act:"sync", + method: "POST", + data: { + act: "sync", westid: 1, - } + }, }); - const list = res.data + const list = res.data; if (!list || list.length === 0) { throw new Error("没有找到虚拟主机"); } @@ -211,14 +201,14 @@ certcontent return { label: `${item.sitename}<${item.westid}-${item.bindings}>`, value: `${item.westid}_${item.sitename}`, - domain: item.bindings.split(",") + domain: item.bindings.split(","), }; }); return { list: this.ctx.utils.options.buildGroupOptions(options, this.certDomains), total: list.length, pageNo: 1, - pageSize: list.length + pageSize: list.length, }; } } diff --git a/packages/ui/certd-server/src/plugins/plugin-woai/access.ts b/packages/ui/certd-server/src/plugins/plugin-woai/access.ts index a7d12d7bd..946fd5ad1 100644 --- a/packages/ui/certd-server/src/plugins/plugin-woai/access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-woai/access.ts @@ -1,29 +1,29 @@ -import { AccessInput, BaseAccess, IsAccess } from '@certd/pipeline'; +import { AccessInput, BaseAccess, IsAccess } from "@certd/pipeline"; @IsAccess({ - name: 'woai', - title: '我爱云授权', - desc: '我爱云CDN', - icon: 'clarity:plugin-line', + name: "woai", + title: "我爱云授权", + desc: "我爱云CDN", + icon: "clarity:plugin-line", }) export class WoaiAccess extends BaseAccess { @AccessInput({ - title: '账号', + title: "账号", component: { - placeholder: '我爱云的账号', + placeholder: "我爱云的账号", }, required: true, }) - username = ''; + username = ""; @AccessInput({ - title: '密码', + title: "密码", component: { - placeholder: '我爱云的密码', + placeholder: "我爱云的密码", }, required: true, encrypt: true, }) - password = ''; + password = ""; } new WoaiAccess(); diff --git a/packages/ui/certd-server/src/plugins/plugin-woai/index.ts b/packages/ui/certd-server/src/plugins/plugin-woai/index.ts index fdad254fb..02dc3945d 100644 --- a/packages/ui/certd-server/src/plugins/plugin-woai/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-woai/index.ts @@ -1,2 +1,2 @@ -export * from './plugins/index.js'; -export * from './access.js'; +export * from "./plugins/index.js"; +export * from "./access.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-woai/plugins/index.ts b/packages/ui/certd-server/src/plugins/plugin-woai/plugins/index.ts index cd1308a9c..c1300473f 100644 --- a/packages/ui/certd-server/src/plugins/plugin-woai/plugins/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-woai/plugins/index.ts @@ -1 +1 @@ -export * from './plugin-deploy-to-cdn.js'; +export * from "./plugin-deploy-to-cdn.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-woai/plugins/plugin-deploy-to-cdn.ts b/packages/ui/certd-server/src/plugins/plugin-woai/plugins/plugin-deploy-to-cdn.ts index fdbda6d7f..fe0197100 100644 --- a/packages/ui/certd-server/src/plugins/plugin-woai/plugins/plugin-deploy-to-cdn.ts +++ b/packages/ui/certd-server/src/plugins/plugin-woai/plugins/plugin-deploy-to-cdn.ts @@ -1,12 +1,12 @@ -import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from '@certd/pipeline'; +import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; import { CertApplyPluginNames, CertInfo } from "@certd/plugin-cert"; -import { WoaiAccess } from '../access.js'; +import { WoaiAccess } from "../access.js"; @IsTaskPlugin({ - name: 'WoaiCDN', - title: '我爱云-部署证书到我爱云CDN', - desc: '部署证书到我爱云CDN', - icon: 'clarity:plugin-line', + name: "WoaiCDN", + title: "我爱云-部署证书到我爱云CDN", + desc: "部署证书到我爱云CDN", + icon: "clarity:plugin-line", group: pluginGroups.cdn.key, default: { strategy: { @@ -16,35 +16,35 @@ import { WoaiAccess } from '../access.js'; }) export class WoaiCdnPlugin extends AbstractTaskPlugin { @TaskInput({ - title: '接口地址(可留空)', - helper: '请填写我爱云的地址, 默认为 [API](https://console.edeg.ttzi.cn) 末尾请不要携带`/`', - component: { name: 'a-input' }, + title: "接口地址(可留空)", + helper: "请填写我爱云的地址, 默认为 [API](https://console.edeg.ttzi.cn) 末尾请不要携带`/`", + component: { name: "a-input" }, required: false, }) baseApi?: string; @TaskInput({ - title: '证书ID', - helper: '请填写 [证书列表](https://console.edge.ttzi.cn/site/certificate) 中的证书的ID', - component: { name: 'a-input' }, + title: "证书ID", + helper: "请填写 [证书列表](https://console.edge.ttzi.cn/site/certificate) 中的证书的ID", + component: { name: "a-input" }, required: true, }) certId!: string; @TaskInput({ - title: '域名证书', - helper: '请选择前置任务输出的域名证书', + title: "域名证书", + helper: "请选择前置任务输出的域名证书", component: { - name: 'output-selector', + name: "output-selector", from: [...CertApplyPluginNames], }, required: true, }) cert!: CertInfo; @TaskInput({ - title: 'Access授权', - helper: '我爱云的用户、密码授权', + title: "Access授权", + helper: "我爱云的用户、密码授权", component: { - name: 'access-selector', - type: 'woai', + name: "access-selector", + type: "woai", }, required: true, }) @@ -52,9 +52,9 @@ export class WoaiCdnPlugin extends AbstractTaskPlugin { async onInstance() {} - private async doRequestApi(url: string, data: any = null, method = 'post', token: string | null = null) { + private async doRequestApi(url: string, data: any = null, method = "post", token: string | null = null) { const headers = { - 'Content-Type': 'application/json', + "Content-Type": "application/json", ...(token ? { Token: token } : {}), }; const res = await this.http.request({ @@ -73,14 +73,14 @@ export class WoaiCdnPlugin extends AbstractTaskPlugin { const { baseApi, certId, cert, accessId } = this; const access = (await this.getAccess(accessId)) as WoaiAccess; // 使用默认值或用户输入的值 - const apiBase = baseApi || 'https://console.edeg.ttzi.cn'; + const apiBase = baseApi || "https://console.edeg.ttzi.cn"; // 登录获取token const loginResponse = await this.doRequestApi(`${apiBase}/account/login`, { username: access.username, password: access.password, }); const token = loginResponse.data.token; - this.logger.info('登录成功,获取到Token:', token); + this.logger.info("登录成功,获取到Token:", token); // 更新证书 const editCertResponse = await this.doRequestApi( `${apiBase}/certificate/edit`, @@ -89,10 +89,10 @@ export class WoaiCdnPlugin extends AbstractTaskPlugin { cert: cert.crt, key: cert.key, }, - 'post', + "post", token ); - this.logger.info('证书更新成功:', editCertResponse.message); + this.logger.info("证书更新成功:", editCertResponse.message); } } diff --git a/packages/ui/certd-server/src/plugins/plugin-xinnet/access-agent.ts b/packages/ui/certd-server/src/plugins/plugin-xinnet/access-agent.ts index 836c83c3f..720eff2c8 100644 --- a/packages/ui/certd-server/src/plugins/plugin-xinnet/access-agent.ts +++ b/packages/ui/certd-server/src/plugins/plugin-xinnet/access-agent.ts @@ -8,20 +8,19 @@ import crypto from "crypto"; name: "xinnetagent", title: "新网授权(代理方式)", icon: "svg:icon-xinnet", - desc: "" + desc: "", }) export class XinnetAgentAccess extends BaseAccess { - /** * 授权属性配置 */ @AccessInput({ title: "代理账号", component: { - placeholder: "代理账号,如:agent0001" + placeholder: "代理账号,如:agent0001", }, required: true, - encrypt: false + encrypt: false, }) agentCode = ""; @@ -30,10 +29,10 @@ export class XinnetAgentAccess extends BaseAccess { component: { name: "a-input-password", vModel: "value", - placeholder: "API密钥" + placeholder: "API密钥", }, required: true, - encrypt: true + encrypt: true, }) appSecret = ""; @@ -41,14 +40,13 @@ export class XinnetAgentAccess extends BaseAccess { title: "测试", component: { name: "api-test", - action: "TestRequest" + action: "TestRequest", }, - helper: "点击测试接口是否正常" + helper: "点击测试接口是否正常", }) testRequest = true; async onTestRequest() { - // const client = new XinnetClient({ // access: this, // logger: this.ctx.logger, @@ -59,51 +57,52 @@ export class XinnetAgentAccess extends BaseAccess { return "ok"; } - - - async getDomainList(req:PageSearch) { + async getDomainList(req: PageSearch) { const pager = new Pager(req); const conf = { url: "/api/domain/list", data: { pageNo: String(pager.pageNo), - pageSize: String(pager.pageSize) - } - } + pageSize: String(pager.pageSize), + }, + }; return await this.doRequest(conf); } - /** * 生成 UTC 0 时区的时间戳 */ generateTimestamp() { - const timestamp = new Date().toISOString().replace(/\.\d{3}Z$/, "Z").replaceAll(":", "").replaceAll("-", ""); + const timestamp = new Date() + .toISOString() + .replace(/\.\d{3}Z$/, "Z") + .replaceAll(":", "") + .replaceAll("-", ""); return timestamp; } /** * 字节转16进制字符串 */ - bytesToHex(bytes:any) { - return bytes.toString('hex'); + bytesToHex(bytes: any) { + return bytes.toString("hex"); } /** * 生成签名 */ generateSignature(timestamp, urlPath, requestBody) { - const algorithm = 'HMAC-SHA256'; - const requestMethod = 'POST'; - + const algorithm = "HMAC-SHA256"; + const requestMethod = "POST"; + // 构建待签名字符串 const stringToSign = `${algorithm}\n${timestamp}\n${requestMethod}\n${urlPath}\n${requestBody}`; - + // 使用 HMAC-SHA256 计算签名 - const hmac = crypto.createHmac('sha256', this.appSecret); + const hmac = crypto.createHmac("sha256", this.appSecret); hmac.update(stringToSign); const signatureBytes = hmac.digest(); - + // 转换为16进制字符串 return this.bytesToHex(signatureBytes); } @@ -119,39 +118,37 @@ export class XinnetAgentAccess extends BaseAccess { /** * 查询域名分页列表 */ - async doRequest(req:any) { - - const baseURL = 'https://apiv2.xinnet.com'; + async doRequest(req: any) { + const baseURL = "https://apiv2.xinnet.com"; const urlPath = req.url; const requestURL = baseURL + urlPath; // 实际请求URL去掉最后的斜杠 - + // 请求体 const requestBody = JSON.stringify(req.data); // 生成时间戳和授权头 const timestamp = this.generateTimestamp(); - const authorization = this.generateAuthorization(timestamp, urlPath+"/", requestBody); + const authorization = this.generateAuthorization(timestamp, urlPath + "/", requestBody); // 请求配置 const config = { - method: 'POST', + method: "POST", url: requestURL, headers: { - 'Content-Type': 'application/json', - 'timestamp': timestamp, - 'authorization': authorization + "Content-Type": "application/json", + timestamp: timestamp, + authorization: authorization, }, data: requestBody, }; - const res = await this.ctx.http.request(config); - - if (res.code !="0"){ - throw new Error(`API Error: ${res.code} ${res.requestId} - ${JSON.stringify(res.msg)}`); - } - return res.data; - } + const res = await this.ctx.http.request(config); + if (res.code != "0") { + throw new Error(`API Error: ${res.code} ${res.requestId} - ${JSON.stringify(res.msg)}`); + } + return res.data; + } } new XinnetAgentAccess(); diff --git a/packages/ui/certd-server/src/plugins/plugin-xinnet/access.ts b/packages/ui/certd-server/src/plugins/plugin-xinnet/access.ts index ed760db15..ef141852b 100644 --- a/packages/ui/certd-server/src/plugins/plugin-xinnet/access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-xinnet/access.ts @@ -9,20 +9,19 @@ import { XinnetClient } from "@certd/plugin-plus"; name: "xinnet", title: "新网授权", icon: "svg:icon-xinnet", - desc: "" + desc: "", }) export class XinnetAccess extends BaseAccess { - /** * 授权属性配置 */ @AccessInput({ title: "用户名", component: { - placeholder: "手机号/用户名" + placeholder: "手机号/用户名", }, required: true, - encrypt: true + encrypt: true, }) username = ""; @@ -31,10 +30,10 @@ export class XinnetAccess extends BaseAccess { component: { name: "a-input-password", vModel: "value", - placeholder: "登录密码" + placeholder: "登录密码", }, required: true, - encrypt: true + encrypt: true, }) password = ""; @@ -42,18 +41,17 @@ export class XinnetAccess extends BaseAccess { title: "测试", component: { name: "api-test", - action: "TestRequest" + action: "TestRequest", }, - helper: "测试前请务必先在新网后台关闭异地登录保护、关闭动态口令验证\n如果提示需要短信验证码,请等几个小时后再试" + helper: "测试前请务必先在新网后台关闭异地登录保护、关闭动态口令验证\n如果提示需要短信验证码,请等几个小时后再试", }) testRequest = true; async onTestRequest() { - const client = new XinnetClient({ access: this, logger: this.ctx.logger, - http: this.ctx.http + http: this.ctx.http, }); await client.getDomainList({ pageNo: 1, pageSize: 1 }); @@ -61,9 +59,8 @@ export class XinnetAccess extends BaseAccess { return "ok"; } - - getCacheKey () { - let hashStr = "" + getCacheKey() { + let hashStr = ""; for (const key in this) { if (Object.prototype.hasOwnProperty.call(this, key)) { const element = this[key]; @@ -73,7 +70,6 @@ export class XinnetAccess extends BaseAccess { const hashCode = this.ctx.utils.hash.sha256(hashStr); return `xinnet-${hashCode}`; } - } new XinnetAccess(); diff --git a/packages/ui/certd-server/src/plugins/plugin-xinnet/dns-provider-agent.ts b/packages/ui/certd-server/src/plugins/plugin-xinnet/dns-provider-agent.ts index 272d32453..d18b6bbe6 100644 --- a/packages/ui/certd-server/src/plugins/plugin-xinnet/dns-provider-agent.ts +++ b/packages/ui/certd-server/src/plugins/plugin-xinnet/dns-provider-agent.ts @@ -15,7 +15,7 @@ export type XinnetAgentRecord = { icon: "svg:icon-xinnet", // 这里是对应的 cloudflare的access类型名称 accessType: "xinnetagent", - order: 7 + order: 7, }) export class XinnetAgentProvider extends AbstractDnsProvider { access!: XinnetAgentAccess; @@ -39,7 +39,6 @@ export class XinnetAgentProvider extends AbstractDnsProvider const { fullRecord, value, type, domain } = options; this.logger.info("添加域名解析:", fullRecord, value, type, domain); - /** * /api/dns/create * domainName 是 string 域名名称 test-xinnet-0516-ceshi.cn @@ -50,52 +49,48 @@ line 是 string 线路 只能传"默认" */ const res = await this.access.doRequest({ - url:"/api/dns/create", - data:{ + url: "/api/dns/create", + data: { domainName: domain, recordName: fullRecord, type: type, value: value, - line: "默认" - } + line: "默认", + }, }); - return { - recordId:res, - domainName: domain + recordId: res, + domainName: domain, }; } - /** * 删除dns解析记录,清理申请痕迹 * @param options */ async removeRecord(options: RemoveRecordOptions): Promise { - - const {domainName,recordId} = options.recordRes; + const { domainName, recordId } = options.recordRes; await this.access.doRequest({ - url:"/api/dns/delete", - data:{ + url: "/api/dns/delete", + data: { recordId: recordId, - domainName: domainName - } + domainName: domainName, + }, }); } async getDomainListPage(req: PageSearch): Promise> { const res = await this.access.getDomainList(req); - const list = res.list.map((item) => ({ + const list = res.list.map(item => ({ domain: item.domainName, - id: item.domainName + id: item.domainName, })); return { list: list || [], - total: res.totalRows || 0 - } + total: res.totalRows || 0, + }; } - } //实例化这个provider,将其自动注册到系统中 diff --git a/packages/ui/certd-server/src/plugins/plugin-xinnet/dns-provider.ts b/packages/ui/certd-server/src/plugins/plugin-xinnet/dns-provider.ts index 9dc77e211..5684729cb 100644 --- a/packages/ui/certd-server/src/plugins/plugin-xinnet/dns-provider.ts +++ b/packages/ui/certd-server/src/plugins/plugin-xinnet/dns-provider.ts @@ -20,7 +20,7 @@ export type XinnetRecord = { icon: "svg:icon-xinnet", // 这里是对应的 cloudflare的access类型名称 accessType: "xinnet", - order: 7 + order: 7, }) export class XinnetProvider extends AbstractDnsProvider { access!: XinnetAccess; @@ -47,24 +47,24 @@ export class XinnetProvider extends AbstractDnsProvider { const client = new XinnetClient({ logger: this.logger, access: this.access, - http: this.http + http: this.http, }); const res = await client.getDomainList({ - searchKey: domain + searchKey: domain, }); if (!res.list || res.list.length == 0) { throw new Error("域名不存在"); } - let list = res.list.map((item) => ({ + const list = res.list.map(item => ({ domainName: item.domainName, - serviceCode: item.serviceCode + serviceCode: item.serviceCode, })); this.logger.info("域名列表:", JSON.stringify(list)); - const domainItem = list.find((item) => item.domainName === domain); + const domainItem = list.find(item => item.domainName === domain); if (!domainItem) { throw new Error("域名(" + domain + ")不存在"); } @@ -72,25 +72,27 @@ export class XinnetProvider extends AbstractDnsProvider { const serviceCode = domainItem.serviceCode; const dcpCookie = await client.getDcpCookie({ - serviceCode + serviceCode, }); - const recordRes = await client.addDomainDnsRecord({ - recordName: hostRecord, - type: type, - recordValue: value - }, { - dcpCookie, - serviceCode - }); + const recordRes = await client.addDomainDnsRecord( + { + recordName: hostRecord, + type: type, + recordValue: value, + }, + { + dcpCookie, + serviceCode, + } + ); return { ...recordRes, serviceCode, - dcpCookie + dcpCookie, }; } - /** * 删除dns解析记录,清理申请痕迹 * @param options @@ -99,43 +101,40 @@ export class XinnetProvider extends AbstractDnsProvider { const client = new XinnetClient({ logger: this.logger, access: this.access, - http: this.http + http: this.http, }); const recordRes = options.recordRes; let dcpCookie = recordRes.dcpCookie; if (!dcpCookie) { dcpCookie = await client.getDcpCookie({ - serviceCode: recordRes.serviceCode + serviceCode: recordRes.serviceCode, }); } await client.deleteDomainDnsRecord(recordRes, { dcpCookie, - serviceCode: recordRes.serviceCode + serviceCode: recordRes.serviceCode, }); - - } async getDomainListPage(req: PageSearch): Promise> { - const client = new XinnetClient({ logger: this.logger, access: this.access, - http: this.http + http: this.http, }); - - const res = await client.getDomainList(req); - const list = res.list.map((item) => ({ + const res = await client.getDomainList(req); + + const list = res.list.map(item => ({ domain: item.domainName, - id: item.domainName + id: item.domainName, })); return { list: list || [], - total: res.totalRows || 0 - } + total: res.totalRows || 0, + }; } } diff --git a/packages/ui/certd-server/src/plugins/plugin-xinnet/index.ts b/packages/ui/certd-server/src/plugins/plugin-xinnet/index.ts index 871ad2050..f18c74ae9 100644 --- a/packages/ui/certd-server/src/plugins/plugin-xinnet/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-xinnet/index.ts @@ -1,5 +1,5 @@ -export * from './dns-provider.js'; -export * from './access.js'; +export * from "./dns-provider.js"; +export * from "./access.js"; -export * from './access-agent.js'; -export * from './dns-provider-agent.js'; +export * from "./access-agent.js"; +export * from "./dns-provider-agent.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-xinnetconnet/access.ts b/packages/ui/certd-server/src/plugins/plugin-xinnetconnet/access.ts index 89700788d..81c48faf4 100644 --- a/packages/ui/certd-server/src/plugins/plugin-xinnetconnet/access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-xinnetconnet/access.ts @@ -1,135 +1,128 @@ -import { AccessInput, BaseAccess, IsAccess, PageSearch } from '@certd/pipeline'; +import { AccessInput, BaseAccess, IsAccess, PageSearch } from "@certd/pipeline"; /** 管理页面地址:https://www.dns.com.cn/login/toLogin.do 是否有API接口,接口地址:https://api.bizcn.com/rrpservices */ @IsAccess({ - name: 'xinnetconnect', - title: '新网互联授权', - icon: 'svg:icon-xinnet', - desc: '仅支持代理账号,ip需要加入白名单', + name: "xinnetconnect", + title: "新网互联授权", + icon: "svg:icon-xinnet", + desc: "仅支持代理账号,ip需要加入白名单", }) export class XinnetConnectAccess extends BaseAccess { /** * 授权属性配置 */ @AccessInput({ - title: '用户名', + title: "用户名", component: { - placeholder: '代理用户名,如:agent001', - help: '新网互联的代理用户名', + placeholder: "代理用户名,如:agent001", + help: "新网互联的代理用户名", }, required: true, encrypt: false, }) - username = ''; + username = ""; @AccessInput({ - title: '密码', + title: "密码", component: { name: "a-input-password", vModel: "value", - placeholder: '密码', + placeholder: "密码", }, required: true, encrypt: true, }) - password = ''; - - @AccessInput({ - title: "测试", - component: { - name: "api-test", - action: "onTestRequest", - }, - helper: "点击测试接口看是否正常", - }) - testRequest = true; - - async onTestRequest() { - await this.getDomainList({ - pageNo: 1, - pageSize: 10, - }); - return "ok"; - } + password = ""; + @AccessInput({ + title: "测试", + component: { + name: "api-test", + action: "onTestRequest", + }, + helper: "点击测试接口看是否正常", + }) + testRequest = true; + async onTestRequest() { + await this.getDomainList({ + pageNo: 1, + pageSize: 10, + }); + return "ok"; + } async getDomainList(req: PageSearch): Promise { - let bodyXml =` + let bodyXml = ` ${req.pageSize} ${req.pageNo} - ` - if(req.searchKey){ - bodyXml += `${req.searchKey}` + `; + if (req.searchKey) { + bodyXml += `${req.searchKey}`; } const res = await this.doRequest({ url: "/domainService", bodyXml: bodyXml, service: "getDomainList", - }) - return res + }); + return res; } - - async addDnsRecord(req: {domain:string,hostRecord:string, value:string, type:string}): Promise { - const { domain,hostRecord, value, type } = req; - const bodyXml =` + async addDnsRecord(req: { domain: string; hostRecord: string; value: string; type: string }): Promise { + const { domain, hostRecord, value, type } = req; + const bodyXml = ` ${domain} ${type} ${hostRecord} ${value} 10 - ` + `; const res = await this.doRequest({ url: "/addDnsRecordService", bodyXml: bodyXml, service: "addDnsRecord", - }) - return res + }); + return res; } - async delDnsRecord(req: {domain:string,hostRecord:string, type:string,value:string}): Promise { - const { domain,hostRecord, type,value } = req; - const bodyXml =` + async delDnsRecord(req: { domain: string; hostRecord: string; type: string; value: string }): Promise { + const { domain, hostRecord, type, value } = req; + const bodyXml = ` ${domain} ${type} ${hostRecord} ${value} 10 - ` + `; const res = await this.doRequest({ url: "/delDnsRecordService", bodyXml: bodyXml, service: "delDnsRecord", - }) - return res + }); + return res; } - - - buildUserXml(){ - return ` + buildUserXml() { + return ` ${this.username} ${this.password} - ` + `; } + async doRequest(req: { bodyXml: string; service: string; url: string }) { + const xml2js = await import("xml2js"); - async doRequest(req: {bodyXml:string,service:string,url:string}) { - - const xml2js = await import('xml2js'); - - const soapRequest = ` + const soapRequest = ` @@ -141,39 +134,37 @@ export class XinnetConnectAccess extends BaseAccess { `; - const response = await this.ctx.http.request({ url: req.url, baseURL: "https://api.bizcn.com/rrpservices", data: soapRequest, headers: { - 'Content-Type': 'text/xml; charset=utf-8', - 'SOAPAction': '' // 根据WSDL,soapAction为空 + "Content-Type": "text/xml; charset=utf-8", + SOAPAction: "", // 根据WSDL,soapAction为空 }, method: "POST", returnOriginRes: true, - }) - + }); // 解析SOAP响应 const parser = new xml2js.Parser({ explicitArray: false }); const result = await parser.parseStringPromise(response.data); // 提取返回结果 - const soapBody = result['soap:Envelope']['soap:Body']; + const soapBody = result["soap:Envelope"]["soap:Body"]; const keys = Object.keys(soapBody); if (keys.length === 0) { - throw new Error('SOAP响应体为空'); + throw new Error("SOAP响应体为空"); } const addDnsRecordResponse = soapBody[keys[0]]; - this.ctx.logger.info(addDnsRecordResponse) + this.ctx.logger.info(addDnsRecordResponse); const resultData = addDnsRecordResponse.response.result; const res = { code: resultData.$.code, - msg: resultData.msg - } - this.ctx.logger.info('操作结果:', res); + msg: resultData.msg, + }; + this.ctx.logger.info("操作结果:", res); if (res.code != "200") { throw new Error(res.msg + " code:" + res.code); @@ -181,7 +172,6 @@ export class XinnetConnectAccess extends BaseAccess { return resultData; } - } new XinnetConnectAccess(); diff --git a/packages/ui/certd-server/src/plugins/plugin-xinnetconnet/dns-provider.ts b/packages/ui/certd-server/src/plugins/plugin-xinnetconnet/dns-provider.ts index 7af0cc9a4..6b92f469a 100644 --- a/packages/ui/certd-server/src/plugins/plugin-xinnetconnet/dns-provider.ts +++ b/packages/ui/certd-server/src/plugins/plugin-xinnetconnet/dns-provider.ts @@ -2,7 +2,6 @@ import { PageRes, PageSearch } from "@certd/pipeline"; import { AbstractDnsProvider, CreateRecordOptions, DomainRecord, IsDnsProvider, RemoveRecordOptions } from "@certd/plugin-cert"; import { XinnetConnectAccess } from "./access.js"; - export type XinnetConnectRecord = { domain: string; hostRecord: string; @@ -12,13 +11,13 @@ export type XinnetConnectRecord = { // 这里通过IsDnsProvider注册一个dnsProvider @IsDnsProvider({ - name: 'xinnetconnect', - title: '新网互联', - desc: '新网互联', - icon: 'svg:icon-xinnet', + name: "xinnetconnect", + title: "新网互联", + desc: "新网互联", + icon: "svg:icon-xinnet", // 这里是对应的 cloudflare的access类型名称 - accessType: 'xinnetconnect', - order:999, + accessType: "xinnetconnect", + order: 999, }) export class XinnetConnectDnsProvider extends AbstractDnsProvider { access!: XinnetConnectAccess; @@ -27,27 +26,25 @@ export class XinnetConnectDnsProvider extends AbstractDnsProvider { - const { fullRecord,hostRecord, value, type, domain } = options; - this.logger.info('添加域名解析:', fullRecord, value, type, domain); + const { fullRecord, hostRecord, value, type, domain } = options; + this.logger.info("添加域名解析:", fullRecord, value, type, domain); const recordReq = { domain: domain, - type: 'TXT', + type: "TXT", hostRecord: hostRecord, value: value, - } - await this.access.addDnsRecord(recordReq) + }; + await this.access.addDnsRecord(recordReq); return recordReq; } - /** * 删除dns解析记录,清理申请痕迹 * @param options @@ -55,28 +52,28 @@ export class XinnetConnectDnsProvider extends AbstractDnsProvider): Promise { const { fullRecord, value } = options.recordReq; const record = options.recordRes; - this.logger.info('删除域名解析:', fullRecord, value); + this.logger.info("删除域名解析:", fullRecord, value); if (!record) { - this.logger.info('record为空,不执行删除'); + this.logger.info("record为空,不执行删除"); return; } - await this.access.delDnsRecord(record) + await this.access.delDnsRecord(record); this.logger.info(`删除域名解析成功:fullRecord=${fullRecord}`); } async getDomainListPage(req: PageSearch): Promise> { - const res = await this.access.getDomainList(req) - let list = res.domainlist || [] + const res = await this.access.getDomainList(req); + let list = res.domainlist || []; list = list.map(item => ({ domain: item.domain, id: item.domain, - })) + })); return { pageNo: req.pageNo, pageSize: req.pageSize, total: res.total || 0, list, - } + }; } } diff --git a/packages/ui/certd-server/src/plugins/plugin-xinnetconnet/index.ts b/packages/ui/certd-server/src/plugins/plugin-xinnetconnet/index.ts index db899c717..d0bc76d38 100644 --- a/packages/ui/certd-server/src/plugins/plugin-xinnetconnet/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-xinnetconnet/index.ts @@ -1,2 +1,2 @@ -export * from './dns-provider.js'; -export * from './access.js'; +export * from "./dns-provider.js"; +export * from "./access.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-zenlayer/access.ts b/packages/ui/certd-server/src/plugins/plugin-zenlayer/access.ts index 256d873a9..0a72d5fde 100644 --- a/packages/ui/certd-server/src/plugins/plugin-zenlayer/access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-zenlayer/access.ts @@ -1,61 +1,56 @@ -import { HttpRequestConfig } from '@certd/basic'; -import { IsAccess, AccessInput, BaseAccess, PageSearch } from '@certd/pipeline'; -import qs from 'qs'; +import { HttpRequestConfig } from "@certd/basic"; +import { IsAccess, AccessInput, BaseAccess, PageSearch } from "@certd/pipeline"; +import qs from "qs"; export type ZenlayerRequest = HttpRequestConfig & { action: string; version?: string; -} +}; /** * 这个注解将注册一个授权配置 * 在certd的后台管理系统中,用户可以选择添加此类型的授权 */ @IsAccess({ - name: 'zenlayer', - title: 'Zenlayer授权', - icon: 'svg:icon-lucky', - desc: 'Zenlayer授权', + name: "zenlayer", + title: "Zenlayer授权", + icon: "svg:icon-lucky", + desc: "Zenlayer授权", }) export class ZenlayerAccess extends BaseAccess { - /** * 授权属性配置 */ @AccessInput({ - title: 'AccessKeyId', + title: "AccessKeyId", component: { - placeholder: '访问密钥ID', + placeholder: "访问密钥ID", }, helper: "[访问密钥管理](https://console.zenlayer.com/accessKey)获取", required: true, encrypt: false, }) - accessKeyId = ''; - + accessKeyId = ""; /** * 授权属性配置 */ @AccessInput({ - title: 'AccessKey Password', + title: "AccessKey Password", component: { - placeholder: '访问密钥密码', + placeholder: "访问密钥密码", }, required: true, encrypt: true, }) - accessKeyPassword = ''; - - - + accessKeyPassword = ""; @AccessInput({ title: "测试", component: { name: "api-test", - action: "TestRequest" + action: "TestRequest", }, - helper: "点击测试接口是否正常" + helper: "点击测试接口是否正常", }) testRequest = true; @@ -67,8 +62,7 @@ export class ZenlayerAccess extends BaseAccess { return "ok"; } - - async getCertList(req: PageSearch = {}):Promise<{totalCount:number,dataSet:{sans:string[],certificateId:string,certificateLabel:string,common:string}[]}> { + async getCertList(req: PageSearch = {}): Promise<{ totalCount: number; dataSet: { sans: string[]; certificateId: string; certificateLabel: string; common: string }[] }> { const pageNo = req.pageNo ?? 1; const pageSize = req.pageSize ?? 100; const res = await this.doRequest({ @@ -76,14 +70,13 @@ export class ZenlayerAccess extends BaseAccess { action: "DescribeCertificates", data: { PageNum: pageNo, - PageSize: pageSize - } + PageSize: pageSize, + }, }); return res; } async getAuthorizationHeaders(req: ZenlayerRequest) { - /** * CanonicalRequest = HTTPRequestMethod + '\n' + @@ -96,11 +89,11 @@ export class ZenlayerAccess extends BaseAccess { if (!req.headers) { req.headers = {}; } - if (!req.headers['content-type']) { - req.headers['content-type'] = "application/json; charset=utf-8"; + if (!req.headers["content-type"]) { + req.headers["content-type"] = "application/json; charset=utf-8"; } - if (!req.headers['host']) { - req.headers['host'] = "console.zenlayer.com"; + if (!req.headers["host"]) { + req.headers["host"] = "console.zenlayer.com"; } if (!req.method) { @@ -108,12 +101,12 @@ export class ZenlayerAccess extends BaseAccess { } // this.accessKeyPassword="Gu5t9xGARNpq86cd98joQYCN3" // req.data = {"pageSize":10,"pageNum":1,"zoneId":"HKG-A"} - const CanonicalQueryString = req.method === 'POST' ? '' : qs.stringify(req.params); + const CanonicalQueryString = req.method === "POST" ? "" : qs.stringify(req.params); const SignedHeaders = "content-type;host"; - const CanonicalHeaders = `content-type:${req.headers['content-type']}\nhost:${req.headers['host']}\n`; + const CanonicalHeaders = `content-type:${req.headers["content-type"]}\nhost:${req.headers["host"]}\n`; const HashedRequestPayload = this.ctx.utils.hash.sha256(JSON.stringify(req.data || {}), "hex"); const CanonicalRequest = `${req.method}\n/\n${CanonicalQueryString}\n${CanonicalHeaders}\n${SignedHeaders}\n${HashedRequestPayload}`; - let HashedCanonicalRequest = this.ctx.utils.hash.sha256(CanonicalRequest, "hex"); + const HashedCanonicalRequest = this.ctx.utils.hash.sha256(CanonicalRequest, "hex"); // HashedCanonicalRequest = "29396f9dfa0f03820b931e8aa06e20cda197e73285ebd76aceb83f7dede493ee" const timestamp = Math.floor(Date.now() / 1000); // const timestamp= 1673361177 @@ -122,7 +115,6 @@ export class ZenlayerAccess extends BaseAccess { const signature = this.ctx.utils.hash.hmacSha256WithKey(this.accessKeyPassword, StringToSign, "hex"); const authorization = `${signMethod} Credential=${this.accessKeyId}, SignedHeaders=${SignedHeaders}, Signature=${signature}`; - /** * X-ZC-Timestamp @@ -154,41 +146,39 @@ Authorization */ return { ...req.headers, - 'X-ZC-Timestamp': timestamp.toString(), - 'X-ZC-Action': req.action, - 'X-ZC-Version': req.version || "2022-11-20", - 'X-ZC-Signature-Method': signMethod, - 'Authorization': authorization, + "X-ZC-Timestamp": timestamp.toString(), + "X-ZC-Action": req.action, + "X-ZC-Version": req.version || "2022-11-20", + "X-ZC-Signature-Method": signMethod, + Authorization: authorization, }; } async doRequest(req: ZenlayerRequest) { const headers = await this.getAuthorizationHeaders(req); - req.headers = headers - let res :any = undefined; - try{ + req.headers = headers; + let res: any = undefined; + try { res = await this.ctx.http.request({ baseURL: req.baseURL || "https://console.zenlayer.com", - ...req + ...req, }); } catch (error) { const resData = error.response?.data; - if (resData){ - let desc = "" - if (resData.code === "CERTIFICATE_NOT_COVER_ALL_DOMAIN"){ + if (resData) { + let desc = ""; + if (resData.code === "CERTIFICATE_NOT_COVER_ALL_DOMAIN") { desc = `证书未覆盖所有域名`; } throw new Error(`[code=${resData.code}] ${desc} ${resData.message} [requestId:${resData.requestId}]`); } - throw error + throw error; } if (res.code) { throw new Error(`[${res.code}]:${res.message} [requestId:${res.requestId}]`); } return res.response; } - - } new ZenlayerAccess(); diff --git a/packages/ui/certd-server/src/plugins/plugin-zenlayer/index.ts b/packages/ui/certd-server/src/plugins/plugin-zenlayer/index.ts index c49d8bf88..21a066db2 100644 --- a/packages/ui/certd-server/src/plugins/plugin-zenlayer/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-zenlayer/index.ts @@ -1,2 +1,2 @@ -export * from './access.js'; -export * from './plugins/index.js'; +export * from "./access.js"; +export * from "./plugins/index.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-zenlayer/plugins/index.ts b/packages/ui/certd-server/src/plugins/plugin-zenlayer/plugins/index.ts index 55ab7cf74..b8237e4f8 100644 --- a/packages/ui/certd-server/src/plugins/plugin-zenlayer/plugins/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-zenlayer/plugins/index.ts @@ -1 +1 @@ -export * from './plugin-refresh-cert.js'; +export * from "./plugin-refresh-cert.js"; diff --git a/packages/ui/certd-server/src/plugins/plugin-zenlayer/plugins/plugin-refresh-cert.ts b/packages/ui/certd-server/src/plugins/plugin-zenlayer/plugins/plugin-refresh-cert.ts index 60ecb4ccb..35538f6b0 100644 --- a/packages/ui/certd-server/src/plugins/plugin-zenlayer/plugins/plugin-refresh-cert.ts +++ b/packages/ui/certd-server/src/plugins/plugin-zenlayer/plugins/plugin-refresh-cert.ts @@ -15,9 +15,9 @@ import { ZenlayerAccess } from "../access.js"; default: { //默认值配置照抄即可 strategy: { - runStrategy: RunStrategy.SkipWhenSucceed - } - } + runStrategy: RunStrategy.SkipWhenSucceed, + }, + }, }) //类名规范,跟上面插件名称(name)一致 export class ZenlayerRefreshCert extends AbstractTaskPlugin { @@ -27,8 +27,8 @@ export class ZenlayerRefreshCert extends AbstractTaskPlugin { helper: "请选择前置任务输出的域名证书", component: { name: "output-selector", - from: [...CertApplyPluginNames] - } + from: [...CertApplyPluginNames], + }, // required: true, // 必填 }) cert!: CertInfo; @@ -41,9 +41,9 @@ export class ZenlayerRefreshCert extends AbstractTaskPlugin { title: "Zenlayer授权", component: { name: "access-selector", - type: "zenlayer" //固定授权类型 + type: "zenlayer", //固定授权类型 }, - required: true //必填 + required: true, //必填 }) accessId!: string; // @@ -53,14 +53,13 @@ export class ZenlayerRefreshCert extends AbstractTaskPlugin { title: "证书ID列表", helper: "要更新的Zenlayer证书ID列表", - action: ZenlayerRefreshCert.prototype.onGetCertList.name + action: ZenlayerRefreshCert.prototype.onGetCertList.name, }) ) certList!: string[]; //插件实例化时执行的方法 - async onInstance() { - } + async onInstance() {} //插件执行方法 async execute(): Promise { @@ -70,7 +69,7 @@ export class ZenlayerRefreshCert extends AbstractTaskPlugin { await this.updateCert({ access: access, certId: certId, - cert: this.cert + cert: this.cert, }); this.logger.info(`刷新证书${certId}成功`); await this.ctx.utils.sleep(1000); @@ -79,8 +78,8 @@ export class ZenlayerRefreshCert extends AbstractTaskPlugin { this.logger.info("部署完成"); } - async updateCert(req:{access:ZenlayerAccess,certId:string, cert: CertInfo}){ - const {access,certId, cert} = req; + async updateCert(req: { access: ZenlayerAccess; certId: string; cert: CertInfo }) { + const { access, certId, cert } = req; // ModifyCertificate await access.doRequest({ url: "/api/v2/cdn", @@ -94,7 +93,7 @@ certificateKey certificateId: certId, certificateContent: cert.crt, certificateKey: cert.key, - } + }, }); } async onGetCertList(req: PageSearch = {}) { @@ -102,12 +101,10 @@ certificateKey const pageNo = req.pageNo ?? 1; const pageSize = req.pageSize ?? 100; - const res = await access.getCertList( - { - pageNo: pageNo, - pageSize: pageSize - } - ); + const res = await access.getCertList({ + pageNo: pageNo, + pageSize: pageSize, + }); const total = res.totalCount; const list = res.dataSet || []; if (!list || list.length === 0) { @@ -122,17 +119,16 @@ certificateKey return { label: `${item.certificateLabel}<${item.certificateId}-${item.common}>`, value: `${item.certificateId}`, - domain: item.sans + domain: item.sans, }; }); return { list: this.ctx.utils.options.buildGroupOptions(options, this.certDomains), total: total, pageNo: pageNo, - pageSize: pageSize + pageSize: pageSize, }; } - } //实例化一下,注册插件 diff --git a/packages/ui/certd-server/src/utils/env.ts b/packages/ui/certd-server/src/utils/env.ts index 17e4b6bfd..83f87a589 100644 --- a/packages/ui/certd-server/src/utils/env.ts +++ b/packages/ui/certd-server/src/utils/env.ts @@ -1 +1 @@ -export { isDev } from '@certd/basic'; +export { isDev } from "@certd/basic"; diff --git a/packages/ui/certd-server/src/utils/http.ts b/packages/ui/certd-server/src/utils/http.ts index 73c54364d..13c47bcd6 100644 --- a/packages/ui/certd-server/src/utils/http.ts +++ b/packages/ui/certd-server/src/utils/http.ts @@ -1,4 +1,4 @@ -import { utils } from '@certd/basic'; +import { utils } from "@certd/basic"; export async function request(config: any): Promise { try { diff --git a/packages/ui/certd-server/src/utils/version.ts b/packages/ui/certd-server/src/utils/version.ts index 4ef3653e3..8c1762474 100644 --- a/packages/ui/certd-server/src/utils/version.ts +++ b/packages/ui/certd-server/src/utils/version.ts @@ -1,13 +1,13 @@ -import { logger } from '@certd/basic'; -import fs from 'fs'; +import { logger } from "@certd/basic"; +import fs from "fs"; export async function getVersion() { try { - const pkg = await fs.promises.readFile('./package.json'); + const pkg = await fs.promises.readFile("./package.json"); const pkgJson = JSON.parse(pkg.toString()); return pkgJson.version; } catch (e) { logger.error(e); - return 'unknown'; + return "unknown"; } } diff --git a/packages/ui/certd-server/test/controller/api.test.ts b/packages/ui/certd-server/test/controller/api.test.ts index b18554a55..ffc54359a 100755 --- a/packages/ui/certd-server/test/controller/api.test.ts +++ b/packages/ui/certd-server/test/controller/api.test.ts @@ -1,16 +1,16 @@ -import { createHttpRequest } from '@midwayjs/mock'; -import { Application } from '@midwayjs/koa'; -import assert from 'assert'; -import { getApp } from '../setup.js'; +import { createHttpRequest } from "@midwayjs/mock"; +import { Application } from "@midwayjs/koa"; +import assert from "assert"; +import { getApp } from "../setup.js"; -describe('test/controller/home.test.ts', () => { - it('should POST /api/get_user', async function (this: any) { +describe("test/controller/home.test.ts", () => { + it("should POST /api/get_user", async function (this: any) { const app: Application = getApp(); // make request - const result = await createHttpRequest(app).get('/api/get_user').query({ uid: 123 }); + const result = await createHttpRequest(app).get("/api/get_user").query({ uid: 123 }); // use expect by jest assert(result.status === 200); - assert(result.body.message === 'OK'); + assert(result.body.message === "OK"); }); }); diff --git a/packages/ui/certd-server/test/controller/home.test.ts b/packages/ui/certd-server/test/controller/home.test.ts index dad9b6295..81d20c390 100755 --- a/packages/ui/certd-server/test/controller/home.test.ts +++ b/packages/ui/certd-server/test/controller/home.test.ts @@ -1,18 +1,16 @@ -import { createHttpRequest } from '@midwayjs/mock'; -import { Application } from '@midwayjs/koa'; -import assert from 'assert'; -import { getApp } from '../setup.js'; +import { createHttpRequest } from "@midwayjs/mock"; +import { Application } from "@midwayjs/koa"; +import assert from "assert"; +import { getApp } from "../setup.js"; -describe('test/controller/home.test.ts', () => { - - it('should GET /', async () => { +describe("test/controller/home.test.ts", () => { + it("should GET /", async () => { const app: Application = getApp(); // make request - const result = await createHttpRequest(app).get('/'); + const result = await createHttpRequest(app).get("/"); // use expect by jest assert(result.status === 200); - assert(result.text === 'Hello Midwayjs!'); + assert(result.text === "Hello Midwayjs!"); }); - });