diff --git a/packages/ui/certd-server/src/plugins/index.ts b/packages/ui/certd-server/src/plugins/index.ts index e8cfc47d7..c00a82601 100644 --- a/packages/ui/certd-server/src/plugins/index.ts +++ b/packages/ui/certd-server/src/plugins/index.ts @@ -44,4 +44,5 @@ // export * from './plugin-lib/index.js' // export * from './plugin-plus/index.js' // export * from './plugin-cert/index.js' -// export * from './plugin-zenlayer/index.js' \ No newline at end of file +// export * from './plugin-zenlayer/index.js' +export * from './plugin-dnsmgr/index.js' \ No newline at end of file diff --git a/packages/ui/certd-server/src/plugins/plugin-dnsmgr/access.ts b/packages/ui/certd-server/src/plugins/plugin-dnsmgr/access.ts new file mode 100644 index 000000000..a647ad9e8 --- /dev/null +++ b/packages/ui/certd-server/src/plugins/plugin-dnsmgr/access.ts @@ -0,0 +1,143 @@ +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管理系统授权', +}) +export class DnsmgrAccess extends BaseAccess { + @AccessInput({ + title: '系统地址', + component: { + name: "a-input", + allowClear: true, + placeholder: 'https://dnsmgr.example.com', + }, + required: true, + }) + endpoint = ''; + + @AccessInput({ + title: '用户ID', + component: { + name: "a-input", + allowClear: true, + placeholder: '123456', + }, + required: true, + }) + uid = ''; + + @AccessInput({ + title: 'API密钥', + required: true, + encrypt: true, + }) + key = ''; + + @AccessInput({ + title: "测试", + component: { + name: "api-test", + action: "TestRequest" + }, + helper: "点击测试接口是否正常" + }) + testRequest = true; + + async onTestRequest() { + await this.GetDomainList({}); + return "ok"; + } + + async GetDomainList(req: PageSearch): Promise> { + this.ctx.logger.info(`获取域名列表,req:${JSON.stringify(req)}`); + const pager = new Pager(req); + const resp = await this.doRequest({ + url: '/api/domain', + data: { + offset: pager.getOffset(), + limit: pager.pageSize, + kw: req.searchKey, + }, + }); + const total = resp?.total || 0; + let list = resp?.rows?.map((item: any) => { + return { + id: item.id, + domain: item.name, + ...item, + }; + }); + return { + total, + list, + }; + } + + 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}`, ''), + type, + value, + line: 'default', + ttl: 600, + }, + }); + return resp; + } + + async getDnsRecords(domainId: string, type?: string, name?: string, value?: string) { + this.ctx.logger.info(`获取DNS记录列表:domainId=${domainId}, type=${type}, name=${name}`); + const resp = await this.doRequest({ + url: `/api/record/data/${domainId}`, + data: { + type, + subdomain: name, + value, + }, + }); + return resp; + } + + async deleteDnsRecord(domainId: string, recordId: string) { + this.ctx.logger.info(`删除DNS记录:domainId=${domainId}, recordId=${recordId}`); + const resp = await this.doRequest({ + url: `/api/record/delete/${domainId}`, + data: { + recordid: recordId, + }, + }); + return resp; + } + + async doRequest(req: { url: string; data?: any }) { + 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', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + data: { + uid: this.uid, + timestamp, + sign, + ...req.data, + }, + }); + + if (res.code !== undefined && res.code !== 0) { + 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 new file mode 100644 index 000000000..2a1b4aed7 --- /dev/null +++ b/packages/ui/certd-server/src/plugins/plugin-dnsmgr/dns-provider.ts @@ -0,0 +1,59 @@ +import { AbstractDnsProvider, CreateRecordOptions, IsDnsProvider, RemoveRecordOptions } from '@certd/plugin-cert'; +import { DnsmgrAccess } from './access.js'; + +type DnsmgrRecord = { + domainId: string; + name: string; + value: string; +}; + +@IsDnsProvider({ + name: 'dnsmgr', + title: '彩虹DNS', + desc: '彩虹DNS管理系统', + icon: 'clarity:plugin-line', + accessType: 'dnsmgr', + order: 99, +}) +export class DnsmgrDnsProvider extends AbstractDnsProvider { + access!: DnsmgrAccess; + + async onInstance() { + this.access = this.ctx.access as DnsmgrAccess; + this.logger.debug('access', this.access); + } + + async createRecord(options: CreateRecordOptions): Promise { + const { fullRecord, value, type, domain } = options; + this.logger.info('添加域名解析:', fullRecord, value, type, domain); + + const domainList = await this.access.GetDomainList({ searchKey: domain }); + const domainInfo = domainList.list?.find((item: any) => item.domain === domain); + + if (!domainInfo) { + throw new Error(`未找到域名:${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 }; + } + + async removeRecord(options: RemoveRecordOptions): Promise { + const { fullRecord, value } = options.recordReq; + const record = options.recordRes; + this.logger.info('删除域名解析:', fullRecord, value, record); + + if (record && record.domainId) { + 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); + } +} + +new DnsmgrDnsProvider(); diff --git a/packages/ui/certd-server/src/plugins/plugin-dnsmgr/index.ts b/packages/ui/certd-server/src/plugins/plugin-dnsmgr/index.ts new file mode 100644 index 000000000..35fce2541 --- /dev/null +++ b/packages/ui/certd-server/src/plugins/plugin-dnsmgr/index.ts @@ -0,0 +1,2 @@ +export * from './access.js'; +export * from './dns-provider.js';