f40ef6b7c0
Align Cloudly with the current typedserver, smartconfig, smartstate, and Docker tooling releases so builds and Docker output stay compatible with the upgraded stack.
150 lines
4.0 KiB
TypeScript
150 lines
4.0 KiB
TypeScript
import * as plugins from '../plugins.js';
|
|
import { DnsManager } from './classes.dnsmanager.js';
|
|
|
|
@plugins.smartdata.managed()
|
|
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;
|
|
}
|
|
}
|