import * as plugins from '../plugins.js'; import { DnsManager } from './classes.dnsmanager.js'; export class DnsEntry extends plugins.smartdata.SmartDataDbDoc< DnsEntry, plugins.servezoneInterfaces.data.IDnsEntry, DnsManager > { // STATIC public static async getDnsEntryById(dnsEntryIdArg: string) { const dnsEntry = await this.getInstance({ id: dnsEntryIdArg, }); return dnsEntry; } public static async getDnsEntries(filterArg?: { zone?: string }) { const filter: any = {}; if (filterArg?.zone) { filter['data.zone'] = filterArg.zone; } const dnsEntries = await this.getInstances(filter); return dnsEntries; } public static async getDnsZones() { const dnsEntries = await this.getInstances({}); const zones = new Set(); for (const entry of dnsEntries) { if (entry.data.zone) { zones.add(entry.data.zone); } } return Array.from(zones).sort(); } public static async createDnsEntry(dnsEntryDataArg: plugins.servezoneInterfaces.data.IDnsEntry['data']) { const dnsEntry = new DnsEntry(); dnsEntry.id = await DnsEntry.getNewId(); dnsEntry.data = { ...dnsEntryDataArg, ttl: dnsEntryDataArg.ttl || 3600, // Default TTL: 1 hour active: dnsEntryDataArg.active !== false, // Default to active createdAt: Date.now(), updatedAt: Date.now(), }; await dnsEntry.save(); return dnsEntry; } public static async updateDnsEntry( dnsEntryIdArg: string, dnsEntryDataArg: Partial ) { const dnsEntry = await this.getInstance({ id: dnsEntryIdArg, }); if (!dnsEntry) { throw new Error(`DNS entry with id ${dnsEntryIdArg} not found`); } Object.assign(dnsEntry.data, dnsEntryDataArg, { updatedAt: Date.now(), }); await dnsEntry.save(); return dnsEntry; } public static async deleteDnsEntry(dnsEntryIdArg: string) { const dnsEntry = await this.getInstance({ id: dnsEntryIdArg, }); if (!dnsEntry) { throw new Error(`DNS entry with id ${dnsEntryIdArg} not found`); } await dnsEntry.delete(); return true; } // INSTANCE @plugins.smartdata.svDb() public id: string; @plugins.smartdata.svDb() public data: plugins.servezoneInterfaces.data.IDnsEntry['data']; /** * Validates the DNS entry data */ public validateData(): boolean { const { type, name, value, zone } = this.data; // Basic validation if (!type || !name || !value || !zone) { return false; } // Type-specific validation switch (type) { case 'A': // Validate IPv4 address return /^(\d{1,3}\.){3}\d{1,3}$/.test(value); case 'AAAA': // Validate IPv6 address (simplified) return /^([0-9a-fA-F]{0,4}:){7}[0-9a-fA-F]{0,4}$/.test(value); case 'MX': // MX records must have priority return this.data.priority !== undefined && this.data.priority >= 0; case 'SRV': // SRV records must have priority, weight, and port return ( this.data.priority !== undefined && this.data.weight !== undefined && this.data.port !== undefined ); case 'CNAME': case 'NS': case 'PTR': // These should point to valid domain names return /^[a-zA-Z0-9.-]+$/.test(value); case 'TXT': case 'CAA': case 'SOA': // These can contain any text return true; default: return false; } } /** * Get a formatted string representation of the DNS entry */ public toFormattedString(): string { const { type, name, value, ttl, priority } = this.data; let result = `${name} ${ttl} IN ${type}`; if (priority !== undefined) { result += ` ${priority}`; } if (type === 'SRV' && this.data.weight !== undefined && this.data.port !== undefined) { result += ` ${this.data.weight} ${this.data.port}`; } result += ` ${value}`; return result; } }