diff --git a/packages/plugins/plugin-lib/src/cert/dns-provider/api.ts b/packages/plugins/plugin-lib/src/cert/dns-provider/api.ts index 424548946..cde0c26f8 100644 --- a/packages/plugins/plugin-lib/src/cert/dns-provider/api.ts +++ b/packages/plugins/plugin-lib/src/cert/dns-provider/api.ts @@ -62,6 +62,7 @@ export interface IDnsProvider { export interface ISubDomainsGetter { getSubDomains(): Promise; + hasSubDomain(domain: string): Promise; } export interface IDomainParser { diff --git a/packages/plugins/plugin-lib/src/cert/dns-provider/domain-parser.ts b/packages/plugins/plugin-lib/src/cert/dns-provider/domain-parser.ts index 59d7d4262..0641c7ecc 100644 --- a/packages/plugins/plugin-lib/src/cert/dns-provider/domain-parser.ts +++ b/packages/plugins/plugin-lib/src/cert/dns-provider/domain-parser.ts @@ -38,20 +38,28 @@ export class DomainParser implements IDomainParser { return value; } - const subDomains = await this.subDomainsGetter.getSubDomains(); - if (subDomains && subDomains.length > 0) { - const fullDomainDot = "." + fullDomain; - for (const subDomain of subDomains) { - if (fullDomainDot.endsWith("." + subDomain)) { - //找到子域名托管 - utils.cache.set(cacheKey, subDomain, { - ttl: 60 * 1000, - }); - this.logger.info(`获取到子域名托管域名:${fullDomain}->${subDomain}`); - return subDomain; - } - } + //检查是否有子域名托管 + const subDomain = await this.subDomainsGetter.hasSubDomain(fullDomain); + if (subDomain) { + utils.cache.set(cacheKey, subDomain, { + ttl: 60 * 1000, + }); + this.logger.info(`获取到托管域名:${fullDomain}->${subDomain}`); + return subDomain; } + // if (subDomains && subDomains.length > 0) { + // const fullDomainDot = "." + fullDomain; + // for (const subDomain of subDomains) { + // if (fullDomainDot.endsWith("." + subDomain)) { + // //找到子域名托管 + // utils.cache.set(cacheKey, subDomain, { + // ttl: 60 * 1000, + // }); + // this.logger.info(`获取到子域名托管域名:${fullDomain}->${subDomain}`); + // return subDomain; + // } + // } + // } const res = this.parseDomainByPsl(fullDomain); this.logger.info(`从psl获取主域名:${fullDomain}->${res}`); diff --git a/packages/ui/certd-server/src/controller/user/pipeline/sub-domain-controller.ts b/packages/ui/certd-server/src/controller/user/pipeline/sub-domain-controller.ts index 63a55c553..f4ae320a3 100644 --- a/packages/ui/certd-server/src/controller/user/pipeline/sub-domain-controller.ts +++ b/packages/ui/certd-server/src/controller/user/pipeline/sub-domain-controller.ts @@ -1,8 +1,8 @@ -import {ALL, Body, Controller, Inject, Post, Provide, Query} from '@midwayjs/core'; -import {Constants, CrudController} from '@certd/lib-server'; -import {SubDomainService} from "../../../modules/pipeline/service/sub-domain-service.js"; -import {DomainParser} from '@certd/plugin-cert'; -import { SubDomainsGetter } from '../../../modules/pipeline/service/getter/sub-domain-getter.js'; +import { Constants, CrudController } from '@certd/lib-server'; +import { DomainParser } from '@certd/plugin-cert'; +import { ALL, Body, Controller, Inject, Post, Provide, Query } from '@midwayjs/core'; +import { SubDomainService } from "../../../modules/pipeline/service/sub-domain-service.js"; +import { TaskServiceBuilder } from '../../../modules/pipeline/service/getter/task-service-getter.js'; /** * 子域名托管 @@ -13,6 +13,9 @@ export class SubDomainController extends CrudController { @Inject() service: SubDomainService; + @Inject() + taskServiceBuilder: TaskServiceBuilder; + getService() { return this.service; } @@ -20,7 +23,8 @@ export class SubDomainController extends CrudController { @Post('/parseDomain', { summary: Constants.per.authOnly }) async parseDomain(@Body("fullDomain") fullDomain:string) { const userId = this.getUserId() - const subDomainGetter = new SubDomainsGetter(userId, this.service) + const taskService = this.taskServiceBuilder.create({ userId: userId }); + const subDomainGetter = await taskService.getSubDomainsGetter(); const domainParser = new DomainParser(subDomainGetter) const domain = await domainParser.parse(fullDomain) return this.ok(domain); 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 4fccf8059..a181e598b 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 @@ -12,7 +12,6 @@ import { CnameRecordEntity } from "../../cname/entity/cname-record.js"; import { CnameRecordService } from '../../cname/service/cname-record-service.js'; import { UserDomainImportSetting } from '../../mine/service/models.js'; import { UserSettingsService } from '../../mine/service/user-settings-service.js'; -import { SubDomainsGetter } from '../../pipeline/service/getter/sub-domain-getter.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'; @@ -112,7 +111,8 @@ export class DomainService extends BaseService { async getDomainVerifiers(userId: number, domains: string[]): Promise { const mainDomainMap: Record = {} - const subDomainGetter = new SubDomainsGetter(userId, this.subDomainService) + const taskService = this.taskServiceBuilder.create({ userId: userId }); + const subDomainGetter = await taskService.getSubDomainsGetter(); const domainParser = new DomainParser(subDomainGetter) const mainDomains = [] @@ -215,7 +215,7 @@ export class DomainService extends BaseService { } - async startDomainImportTask(req: {userId:number,key:string}) { + async startDomainImportTask(req: { userId: number, key: string }) { const key = req.key const setting = await this.userSettingService.getSetting(req.userId, UserDomainImportSetting) @@ -223,10 +223,10 @@ export class DomainService extends BaseService { if (!item) { throw new Error(`域名导入任务配置(${key})还未注册`) } - const { dnsProviderType, dnsProviderAccessId,title } = item + const { dnsProviderType, dnsProviderAccessId, title } = item taskExecutor.start(new BackTask({ - type: DOMAIN_IMPORT_TASK_TYPE, + type: DOMAIN_IMPORT_TASK_TYPE, key, title: title, run: async (task: BackTask) => { @@ -241,9 +241,11 @@ export class DomainService extends BaseService { private async _syncFromProvider(req: SyncFromProviderReq, task: BackTask) { const { userId, dnsProviderType, dnsProviderAccessId } = req; - const subDomainGetter = new SubDomainsGetter(userId, this.subDomainService) - const domainParser = new DomainParser(subDomainGetter) + const serviceGetter = this.taskServiceBuilder.create({ userId }); + const subDomainGetter = await serviceGetter.getSubDomainsGetter(); + const domainParser = new DomainParser(subDomainGetter) + const access = await this.accessService.getById(dnsProviderAccessId, userId); const context = { access, logger, http, utils, domainParser, serviceGetter }; // 翻页查询dns的记录 @@ -312,30 +314,30 @@ export class DomainService extends BaseService { logger.info(`从域名提供商${dnsProviderType}导入域名完成(${key}),共导入${task.total}个域名,跳过${task.getSkipCount()}个域名,成功${task.getSuccessCount()}个域名,失败${task.getErrorCount()}个域名`) } - async getDomainImportTaskStatus(req:{userId?:number}) { + async getDomainImportTaskStatus(req: { userId?: number }) { const userId = req.userId || 0 const setting = await this.userSettingService.getSetting(userId, UserDomainImportSetting) - const list= setting?.domainImportList || [] + const list = setting?.domainImportList || [] - const taskList:any = [] + const taskList: any = [] for (const item of list) { - const { key } = item - - const task = taskExecutor.get(DOMAIN_IMPORT_TASK_TYPE,key) + const { key } = item + + const task = taskExecutor.get(DOMAIN_IMPORT_TASK_TYPE, key) taskList.push({ ...item, - task:task, + task: task, }) } return taskList } - async getProviderTitle(req:{userId?:number,dnsProviderType:string,dnsProviderAccessId:number}) { + async getProviderTitle(req: { userId?: number, dnsProviderType: string, dnsProviderAccessId: number }) { const userId = req.userId || 0 - const { dnsProviderType, dnsProviderAccessId} = req + const { dnsProviderType, dnsProviderAccessId } = req const dnsProviderDefine = dnsProviderRegistry.getDefine(dnsProviderType) if (!dnsProviderDefine) { throw new Error(`该域名提供商(${dnsProviderType})不存在,请检查是否已被注册`) @@ -351,12 +353,12 @@ export class DomainService extends BaseService { } } - async addDomainImportTask(req:{userId?:number,dnsProviderType:string,dnsProviderAccessId:number,index?:number}) { + async addDomainImportTask(req: { userId?: number, dnsProviderType: string, dnsProviderAccessId: number, index?: number }) { const userId = req.userId || 0 - const { dnsProviderType, dnsProviderAccessId,index=0 } = req + 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, UserDomainImportSetting) @@ -383,7 +385,7 @@ export class DomainService extends BaseService { return item } - async deleteDomainImportTask(req:{userId?:number,key:string}) { + async deleteDomainImportTask(req: { userId?: number, key: string }) { const userId = req.userId || 0 const { key } = req @@ -394,13 +396,13 @@ export class DomainService extends BaseService { throw new Error(`该域名导入任务${key}不存在`) } setting.domainImportList.splice(index, 1) - taskExecutor.clear(DOMAIN_IMPORT_TASK_TYPE,key) + taskExecutor.clear(DOMAIN_IMPORT_TASK_TYPE, key) await this.userSettingService.saveSetting(userId, setting) } - async saveDomainImportTask(req:{userId?:number,dnsProviderType:string,dnsProviderAccessId:number,key?:string}) { + async saveDomainImportTask(req: { userId?: number, dnsProviderType: string, dnsProviderAccessId: number, key?: string }) { const userId = req.userId || 0 - const { dnsProviderType, dnsProviderAccessId,key } = req + const { dnsProviderType, dnsProviderAccessId, key } = req const setting = await this.userSettingService.getSetting(userId, UserDomainImportSetting) setting.domainImportList = setting.domainImportList || [] @@ -410,19 +412,19 @@ export class DomainService extends BaseService { if (index === -1) { throw new Error(`该域名导入任务${key}不存在`) } - await this.deleteDomainImportTask({userId,key}) + await this.deleteDomainImportTask({ userId, key }) } - return await this.addDomainImportTask({userId,dnsProviderType,dnsProviderAccessId,index}) + return await this.addDomainImportTask({ userId, dnsProviderType, dnsProviderAccessId, index }) } - - async getSyncExpirationTaskStatus(req:{userId?:number}) { + + async getSyncExpirationTaskStatus(req: { userId?: number }) { const userId = req.userId ?? 'all' const key = `user_${userId}` - const task = taskExecutor.get(DOMAIN_EXPIRE_TASK_TYPE,key) + const task = taskExecutor.get(DOMAIN_EXPIRE_TASK_TYPE, key) return task } @@ -544,8 +546,8 @@ export class DomainService extends BaseService { await doPageTurn({ pager, getPage: getDomainPage, itemHandle: itemHandle }) const key = `user_${req.userId || 'all'}` - logger.info(`同步用户(${key})注册域名过期时间完成(${req.task.getSuccessCount()}个成功,${req.task.getErrorCount()}个失败)` ) + logger.info(`同步用户(${key})注册域名过期时间完成(${req.task.getSuccessCount()}个成功,${req.task.getErrorCount()}个失败)`) } - + } 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 131d2e1fc..cb1764ce2 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,6 +1,5 @@ -import { Inject, Provide, Scope, ScopeEnum } from "@midwayjs/core"; -import { InjectEntityModel } from "@midwayjs/typeorm"; -import { Repository } from "typeorm"; +import { createChallengeFn, getAuthoritativeDnsResolver } from "@certd/acme-client"; +import { cache, http, isDev, logger, utils } from "@certd/basic"; import { AccessService, BaseService, @@ -9,20 +8,19 @@ import { SysSettingsService, ValidateException } from "@certd/lib-server"; -import { CnameRecordEntity, CnameRecordStatusType } from "../entity/cname-record.js"; -import { createDnsProvider, IDnsProvider } from "@certd/plugin-cert"; import { CnameProvider, CnameRecord } from "@certd/pipeline"; -import { cache, http, isDev, logger, utils } from "@certd/basic"; -import { getAuthoritativeDnsResolver, createChallengeFn } from "@certd/acme-client"; -import { CnameProviderService } from "./cname-provider-service.js"; -import { CnameProviderEntity } from "../entity/cname-provider.js"; -import { CommonDnsProvider } from "./common-provider.js"; -import { DomainParser } from "@certd/plugin-cert"; +import { createDnsProvider, DomainParser, IDnsProvider } from "@certd/plugin-cert"; +import { Inject, Provide, Scope, ScopeEnum } from "@midwayjs/core"; +import { InjectEntityModel } from "@midwayjs/typeorm"; import punycode from "punycode.js"; -import { SubDomainService } from "../../pipeline/service/sub-domain-service.js"; -import { SubDomainsGetter } from "../../pipeline/service/getter/sub-domain-getter.js"; -import { TaskServiceBuilder } from "../../pipeline/service/getter/task-service-getter.js"; +import { Repository } from "typeorm"; import { BackTask, taskExecutor } from "../../basic/service/task-executor.js"; +import { TaskServiceBuilder } from "../../pipeline/service/getter/task-service-getter.js"; +import { SubDomainService } from "../../pipeline/service/sub-domain-service.js"; +import { CnameProviderEntity } from "../entity/cname-provider.js"; +import { CnameRecordEntity, CnameRecordStatusType } from "../entity/cname-record.js"; +import { CnameProviderService } from "./cname-provider-service.js"; +import { CommonDnsProvider } from "./common-provider.js"; type CnameCheckCacheValue = { validating: boolean; @@ -106,7 +104,8 @@ export class CnameRecordService extends BaseService { private async cnameProviderChanged(userId: number, param: any, cnameProvider: CnameProviderEntity) { param.cnameProviderId = cnameProvider.id; - const subDomainGetter = new SubDomainsGetter(userId, this.subDomainService); + const taskService = this.taskServiceBuilder.create({ userId: userId }); + const subDomainGetter = await taskService.getSubDomainsGetter(); const domainParser = new DomainParser(subDomainGetter); const realDomain = await domainParser.parse(param.domain); @@ -254,7 +253,8 @@ export class CnameRecordService extends BaseService { await this.getByDomain(bean.domain, bean.userId); - const subDomainGetter = new SubDomainsGetter(bean.userId, this.subDomainService); + const taskService = this.taskServiceBuilder.create({ userId: bean.userId }); + const subDomainGetter = await taskService.getSubDomainsGetter(); const domainParser = new DomainParser(subDomainGetter); const cacheKey = `cname.record.verify.${bean.id}`; 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 bb0615cbd..87092264e 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 @@ -1,17 +1,49 @@ import {ISubDomainsGetter} from "@certd/plugin-cert"; import {SubDomainService} from "../sub-domain-service.js"; +import { DomainService } from "../../../cert/service/domain-service.js"; export class SubDomainsGetter implements ISubDomainsGetter { userId: number; subDomainService: SubDomainService; + domainService: DomainService; - constructor(userId: number, subDomainService: SubDomainService) { + constructor(userId: number, subDomainService: SubDomainService, domainService: DomainService) { this.userId = userId; this.subDomainService = subDomainService; + this.domainService = domainService; } async getSubDomains() { return await this.subDomainService.getListByUserId(this.userId) } + async hasSubDomain(fullDomain: string) { + const subDomains = await this.getSubDomains() + if (subDomains && subDomains.length > 0) { + const fullDomainDot = "." + fullDomain; + for (const subDomain of subDomains) { + if (fullDomainDot.endsWith("." + subDomain)) { + //找到子域名托管 + return subDomain; + } + } + } + let arr = fullDomain.split(".") + while(arr.length>0){ + const subDomain = arr.join(".") + const domain = await this.domainService.findOne({ + where: { + userId: this.userId, + domain: subDomain, + challengeType: "dns", + } + }) + if(domain){ + return subDomain + } + arr = arr.slice(1) + } + 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 c72542adf..5fdffb3f0 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 @@ -45,7 +45,8 @@ export class TaskServiceGetter implements IServiceGetter{ async getSubDomainsGetter(): Promise { const subDomainsService:SubDomainService = await this.appCtx.getAsync("subDomainService") - return new SubDomainsGetter(this.userId, subDomainsService) + const domainService:DomainService = await this.appCtx.getAsync("domainService") + return new SubDomainsGetter(this.userId, subDomainsService,domainService) } async getAccessService(): Promise {