From cf3a78e1145ff0505c87fbc485d9e731b1aa88a8 Mon Sep 17 00:00:00 2001 From: xiaojunnuo Date: Mon, 22 Sep 2025 23:30:28 +0800 Subject: [PATCH] =?UTF-8?q?perf:=20dns=E6=94=AF=E6=8C=81=E6=96=B0=E7=BD=91?= =?UTF-8?q?=E5=9F=9F=E5=90=8D=E8=A7=A3=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/core/basic/src/utils/util.hash.ts | 16 +++ .../src/plugins/plugin-xinnet/access.ts | 40 ++++++++ .../src/plugins/plugin-xinnet/dns-provider.ts | 98 +++++++++++++++++++ .../src/plugins/plugin-xinnet/index.ts | 3 + 4 files changed, 157 insertions(+) create mode 100644 packages/ui/certd-server/src/plugins/plugin-xinnet/access.ts create mode 100644 packages/ui/certd-server/src/plugins/plugin-xinnet/dns-provider.ts create mode 100644 packages/ui/certd-server/src/plugins/plugin-xinnet/index.ts diff --git a/packages/core/basic/src/utils/util.hash.ts b/packages/core/basic/src/utils/util.hash.ts index 303ffa1d7..3b3452bea 100644 --- a/packages/core/basic/src/utils/util.hash.ts +++ b/packages/core/basic/src/utils/util.hash.ts @@ -17,10 +17,26 @@ function base64(data: string) { function base64Decode(data: string) { return Buffer.from(data, "base64").toString("utf8"); } + +function toHex(data: number | string) { + if (typeof data === "number") { + return data.toString(16); + } + return Buffer.from(data).toString("hex"); +} +function hexToStr(data: string) { + return Buffer.from(data, "hex").toString("utf8"); +} +function hexToNumber(data: string) { + return parseInt(data, 16); +} export const hashUtils = { md5, sha256, base64, base64Decode, hmacSha256, + toHex, + hexToStr, + hexToNumber, }; diff --git a/packages/ui/certd-server/src/plugins/plugin-xinnet/access.ts b/packages/ui/certd-server/src/plugins/plugin-xinnet/access.ts new file mode 100644 index 000000000..f4b136371 --- /dev/null +++ b/packages/ui/certd-server/src/plugins/plugin-xinnet/access.ts @@ -0,0 +1,40 @@ +import { IsAccess, AccessInput, BaseAccess } from '@certd/pipeline'; + +/** + * 这个注解将注册一个授权配置 + * 在certd的后台管理系统中,用户可以选择添加此类型的授权 + */ +@IsAccess({ + name: 'xinnet', + title: '新网授权', + icon: 'arcticons:dns-changer-3', + desc: '', +}) +export class XinnetAccess extends BaseAccess { + /** + * 授权属性配置 + */ + @AccessInput({ + title: '用户名', + component: { + placeholder: '用户名或手机号', + }, + required: true, + encrypt: false, + }) + username = ''; + + @AccessInput({ + title: '登录密码', + component: { + name:"a-input-password", + vModel:"value", + placeholder: '密码', + }, + required: true, + encrypt: true, + }) + password = ''; +} + +new XinnetAccess(); 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 new file mode 100644 index 000000000..633db7a93 --- /dev/null +++ b/packages/ui/certd-server/src/plugins/plugin-xinnet/dns-provider.ts @@ -0,0 +1,98 @@ +import { AbstractDnsProvider, CreateRecordOptions, IsDnsProvider, RemoveRecordOptions } from "@certd/plugin-cert"; +import { XinnetAccess } from "./access.js"; +import { XinnetClient } from "@certd/plugin-plus"; + +export type XinnetRecord = { + id: number; + domainId: number, +}; + +// 这里通过IsDnsProvider注册一个dnsProvider +@IsDnsProvider({ + name: 'xinnet', + title: '新网', + desc: '新网域名解析', + icon: 'arcticons:dns-changer-3', + // 这里是对应的 cloudflare的access类型名称 + accessType: 'xinnet', + order:7, +}) +export class XinnetProvider extends AbstractDnsProvider { + access!: XinnetAccess; + + client!:XinnetClient; + async onInstance() { + //一些初始化的操作 + // 也可以通过ctx成员变量传递context + this.access = this.ctx.access as XinnetAccess; + this.client = new XinnetClient({ + logger: this.logger, + access: this.access, + http: this.http + }); + } + + /** + * 创建dns解析记录,用于验证域名所有权 + */ + async createRecord(options: CreateRecordOptions): Promise { + /** + * fullRecord: '_acme-challenge.test.example.com', + * value: 一串uuid + * type: 'TXT', + * domain: 'example.com' + */ + 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); + + const res = await this.client.createRecord({ + domain: domain, + domainId: domainId, + type: 'TXT', + host: hostRecord, + data: value, + ttl: 300, + }) + return { + id: res.id, + domainId: domainId, + }; + } + + + /** + * 删除dns解析记录,清理申请痕迹 + * @param options + */ + async removeRecord(options: RemoveRecordOptions): Promise { + const { fullRecord, value } = options.recordReq; + const record = options.recordRes; + this.logger.info('删除域名解析:', fullRecord, value); + if (!record) { + this.logger.info('record为空,不执行删除'); + return; + } + //这里调用删除txt dns解析记录接口 + /** + * 请求示例 + * DELETE /api/record?id=85371689655342080 HTTP/1.1 + * Authorization: Basic {token} + * 请求参数 + */ + const {id,domainId} = record + await this.client.deleteRecord({ + id, + domainId + }) + this.logger.info(`删除域名解析成功:fullRecord=${fullRecord},id=${id}`); + } +} + +//实例化这个provider,将其自动注册到系统中 +new Dns51DnsProvider(); diff --git a/packages/ui/certd-server/src/plugins/plugin-xinnet/index.ts b/packages/ui/certd-server/src/plugins/plugin-xinnet/index.ts new file mode 100644 index 000000000..3a9e17436 --- /dev/null +++ b/packages/ui/certd-server/src/plugins/plugin-xinnet/index.ts @@ -0,0 +1,3 @@ +export * from './dns-provider.js'; +export * from './access.js'; +export * from './client.js';