import * as plugins from '../../plugins.js'; import type { OpsServer } from '../classes.opsserver.js'; import * as interfaces from '../../../ts_interfaces/index.js'; /** * CRUD handler for the singleton `AcmeConfigDoc`. * * Auth: same dual-mode pattern as other handlers — admin JWT or API token * with `acme-config:read` / `acme-config:write` scope. */ export class AcmeConfigHandler { 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 current ACME config this.typedrouter.addTypedHandler( new plugins.typedrequest.TypedHandler( 'getAcmeConfig', async (dataArg) => { await this.requireAuth(dataArg, 'acme-config:read'); const mgr = this.opsServerRef.dcRouterRef.acmeConfigManager; if (!mgr) return { config: null }; return { config: mgr.getConfig() }; }, ), ); // Update (upsert) the ACME config this.typedrouter.addTypedHandler( new plugins.typedrequest.TypedHandler( 'updateAcmeConfig', async (dataArg) => { const userId = await this.requireAuth(dataArg, 'acme-config:write'); const mgr = this.opsServerRef.dcRouterRef.acmeConfigManager; if (!mgr) { return { success: false, message: 'AcmeConfigManager not initialized (DB disabled?)', }; } try { const updated = await mgr.updateConfig( { accountEmail: dataArg.accountEmail, enabled: dataArg.enabled, useProduction: dataArg.useProduction, autoRenew: dataArg.autoRenew, renewThresholdDays: dataArg.renewThresholdDays, }, userId, ); return { success: true, config: updated }; } catch (err: unknown) { return { success: false, message: (err as Error).message }; } }, ), ); } }