diff --git a/src/modules/domains/DTO/create-dns-record.dto.ts b/src/modules/domains/DTO/create-dns-record.dto.ts index d74dd13..5039055 100644 --- a/src/modules/domains/DTO/create-dns-record.dto.ts +++ b/src/modules/domains/DTO/create-dns-record.dto.ts @@ -10,6 +10,12 @@ export class CreateDnsRecordDto { @ApiProperty({ description: "The name of the DNS record", example: "mail" }) name!: string; + @IsNotEmpty() + @IsString() + @MaxLength(255) + @ApiProperty({ description: "The name of the DNS record", example: "mail" }) + fullName: string; + @IsEnum(DNSRecordType) @ApiProperty({ description: "The type of the DNS record", example: "MX" }) type!: DNSRecordType; diff --git a/src/modules/domains/entities/dns-record.entity.ts b/src/modules/domains/entities/dns-record.entity.ts index 9b951a7..7bfcb89 100644 --- a/src/modules/domains/entities/dns-record.entity.ts +++ b/src/modules/domains/entities/dns-record.entity.ts @@ -13,6 +13,9 @@ export class DnsRecord extends BaseEntity { @Property({ type: "varchar", length: 255, nullable: false }) name!: string; + @Property({ type: "varchar", length: 255, nullable: false }) + fullName!: string; + @Enum({ items: () => DNSRecordType, nativeEnumName: "dns_record_type_enum" }) type!: DNSRecordType; diff --git a/src/modules/domains/services/dns.service.ts b/src/modules/domains/services/dns.service.ts index 95fcbd7..953eed3 100644 --- a/src/modules/domains/services/dns.service.ts +++ b/src/modules/domains/services/dns.service.ts @@ -90,8 +90,8 @@ export class DnsService { // MX Record requiredRecords.push({ - // name: domain.name, name: "@", + fullName: domain.name, type: DNSRecordType.MX, value: this.mailServerDomain, priority: 10, @@ -101,8 +101,8 @@ export class DnsService { // SPF Record requiredRecords.push({ - // name: domain.name, name: "@", + fullName: domain.name, type: DNSRecordType.TXT, value: this.spfRecord, isRequired: true, @@ -112,8 +112,8 @@ export class DnsService { // DMARC Record const dmarcRecord = `v=DMARC1; p=quarantine; rua=mailto:dmarc@${domain.name}; ruf=mailto:dmarc@${domain.name}`; requiredRecords.push({ - // name: `_dmarc.${domain.name}`, name: `_dmarc`, + fullName: `_dmarc.${domain.name}`, type: DNSRecordType.TXT, value: dmarcRecord, isRequired: true, @@ -125,6 +125,7 @@ export class DnsService { for (const recordData of requiredRecords) { const dnsRecord = this.dnsRecordRepository.create({ name: recordData.name!, + fullName: recordData.fullName!, type: recordData.type!, value: recordData.value!, domain, @@ -145,9 +146,10 @@ export class DnsService { /** * Create DKIM record */ - async createDKIMRecord(domain: Domain, selector: string, dkimName: string, dkimValue: string, wildduckId: string) { + async createDKIMRecord(domain: Domain, selector: string, dkimName: string, dkimFullName: string, dkimValue: string, wildduckId: string) { const dkimRecord = this.dnsRecordRepository.create({ name: dkimName, + fullName: dkimFullName, type: DNSRecordType.TXT, value: dkimValue, domain, @@ -261,7 +263,7 @@ export class DnsService { dnsRecord.errorMessage = error instanceof Error ? error.message : "Unknown error"; await this.em.persistAndFlush(dnsRecord); - this.logger.error(`DNS verification failed for ${dnsRecord.name}:`, error); + this.logger.error(`DNS verification failed for ${dnsRecord.fullName}:`, error); return false; } } @@ -271,7 +273,7 @@ export class DnsService { */ private async verifyTxtRecord(dnsRecord: DnsRecord) { try { - const txtRecords = await this.resolveTxt(dnsRecord.name); + const txtRecords = await this.resolveTxt(dnsRecord.fullName); const flatRecords = txtRecords.flat(); // Join all TXT record parts together (handles multi-part TXT records like DKIM) @@ -290,7 +292,7 @@ export class DnsService { */ private async verifyMxRecord(dnsRecord: DnsRecord) { try { - const mxRecords = await this.resolveMx(dnsRecord.name); + const mxRecords = await this.resolveMx(dnsRecord.fullName); return mxRecords.some((mx) => mx.exchange === dnsRecord.value && mx.priority === (dnsRecord.priority || 10)); } catch (error) { @@ -304,7 +306,7 @@ export class DnsService { */ private async verifyCnameRecord(dnsRecord: DnsRecord) { try { - const cnameRecords = await this.resolveCname(dnsRecord.name); + const cnameRecords = await this.resolveCname(dnsRecord.fullName); return cnameRecords.includes(dnsRecord.value); } catch (error) { diff --git a/src/modules/domains/services/domains.service.ts b/src/modules/domains/services/domains.service.ts index c2c86d5..7afa18b 100644 --- a/src/modules/domains/services/domains.service.ts +++ b/src/modules/domains/services/domains.service.ts @@ -144,7 +144,14 @@ export class DomainsService { // const dkimSelector = dkimNameParts.slice(0, 2).join("."); // Takes first two parts: "default._domainkey" // Create DKIM DNS record - await this.dnsService.createDKIMRecord(domain, selector, this.dkimSelectorName, dkimKeys.dnsTxt.value, dkimKeys.wildduckId); + await this.dnsService.createDKIMRecord( + domain, + selector, + this.dkimSelectorName, + dkimKeys.dnsTxt.name, + dkimKeys.dnsTxt.value, + dkimKeys.wildduckId, + ); this.logger.log(`DKIM automatically enabled for domain ${domain.name}`); } catch (error) {