148 lines
4.0 KiB
TypeScript
148 lines
4.0 KiB
TypeScript
|
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<string>();
|
||
|
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<plugins.servezoneInterfaces.data.IDnsEntry['data']>
|
||
|
) {
|
||
|
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;
|
||
|
}
|
||
|
}
|