import * as plugins from '../../plugins.js'; import type { OpsServer } from '../classes.opsserver.js'; import * as interfaces from '../../../ts_interfaces/index.js'; /** * CRUD handlers for DnsRecordDoc. */ export class DnsRecordHandler { public typedrouter = new plugins.typedrequest.TypedRouter(); constructor(private opsServerRef: OpsServer) { this.opsServerRef.typedrouter.addTypedRouter(this.typedrouter); this.registerHandlers(); } private async requireAuth( request: { identity?: interfaces.data.IIdentity; apiToken?: string }, requiredScope?: interfaces.data.TApiTokenScope, ): Promise { if (request.identity?.jwt) { try { const isAdmin = await this.opsServerRef.adminHandler.adminIdentityGuard.exec({ identity: request.identity, }); if (isAdmin) return request.identity.userId; } catch { /* fall through */ } } if (request.apiToken) { const tokenManager = this.opsServerRef.dcRouterRef.apiTokenManager; if (tokenManager) { const token = await tokenManager.validateToken(request.apiToken); if (token) { if (!requiredScope || tokenManager.hasScope(token, requiredScope)) { return token.createdBy; } throw new plugins.typedrequest.TypedResponseError('insufficient scope'); } } } throw new plugins.typedrequest.TypedResponseError('unauthorized'); } private registerHandlers(): void { // Get records by domain this.typedrouter.addTypedHandler( new plugins.typedrequest.TypedHandler( 'getDnsRecords', async (dataArg) => { await this.requireAuth(dataArg, 'dns-records:read'); const dnsManager = this.opsServerRef.dcRouterRef.dnsManager; if (!dnsManager) return { records: [] }; const docs = await dnsManager.listRecordsForDomain(dataArg.domainId); return { records: docs.map((d) => dnsManager.toPublicRecord(d)) }; }, ), ); // Get single record this.typedrouter.addTypedHandler( new plugins.typedrequest.TypedHandler( 'getDnsRecord', async (dataArg) => { await this.requireAuth(dataArg, 'dns-records:read'); const dnsManager = this.opsServerRef.dcRouterRef.dnsManager; if (!dnsManager) return { record: null }; const doc = await dnsManager.getRecord(dataArg.id); return { record: doc ? dnsManager.toPublicRecord(doc) : null }; }, ), ); // Create record this.typedrouter.addTypedHandler( new plugins.typedrequest.TypedHandler( 'createDnsRecord', async (dataArg) => { const userId = await this.requireAuth(dataArg, 'dns-records:write'); const dnsManager = this.opsServerRef.dcRouterRef.dnsManager; if (!dnsManager) return { success: false, message: 'DnsManager not initialized' }; return await dnsManager.createRecord({ domainId: dataArg.domainId, name: dataArg.name, type: dataArg.type, value: dataArg.value, ttl: dataArg.ttl, proxied: dataArg.proxied, createdBy: userId, }); }, ), ); // Update record this.typedrouter.addTypedHandler( new plugins.typedrequest.TypedHandler( 'updateDnsRecord', async (dataArg) => { await this.requireAuth(dataArg, 'dns-records:write'); const dnsManager = this.opsServerRef.dcRouterRef.dnsManager; if (!dnsManager) return { success: false, message: 'DnsManager not initialized' }; return await dnsManager.updateRecord({ id: dataArg.id, name: dataArg.name, value: dataArg.value, ttl: dataArg.ttl, proxied: dataArg.proxied, }); }, ), ); // Delete record this.typedrouter.addTypedHandler( new plugins.typedrequest.TypedHandler( 'deleteDnsRecord', async (dataArg) => { await this.requireAuth(dataArg, 'dns-records:write'); const dnsManager = this.opsServerRef.dcRouterRef.dnsManager; if (!dnsManager) return { success: false, message: 'DnsManager not initialized' }; return await dnsManager.deleteRecord(dataArg.id); }, ), ); } }