175 lines
5.7 KiB
TypeScript
175 lines
5.7 KiB
TypeScript
/**
|
|
* Stable ID for the built-in DcRouter pseudo-provider. The Providers list
|
|
* surfaces this as the first, non-deletable row so operators see a uniform
|
|
* "who serves this?" answer for every domain. The ID is magic — it never
|
|
* exists in the DnsProviderDoc collection; handlers inject it at read time
|
|
* and reject any mutation that targets it.
|
|
*/
|
|
export const DCROUTER_BUILTIN_PROVIDER_ID = '__dcrouter__';
|
|
|
|
/**
|
|
* Supported DNS provider types.
|
|
*
|
|
* - 'cloudflare' → Cloudflare account (API token-based). Provider stays
|
|
* authoritative; dcrouter pushes record changes via API.
|
|
* - 'dcrouter' → Built-in pseudo-provider for dcrouter-hosted zones.
|
|
* dcrouter itself is the authoritative DNS server. No
|
|
* credentials, cannot be created/edited/deleted through
|
|
* the provider CRUD — the Providers view renders it from
|
|
* a handler-level synthetic row.
|
|
*
|
|
* The abstraction is designed so additional providers (Route53, Gandi,
|
|
* DigitalOcean, foreign dcrouters…) can be added by implementing the
|
|
* IDnsProvider class interface in ts/dns/providers/.
|
|
*/
|
|
export type TDnsProviderType = 'cloudflare' | 'dcrouter';
|
|
|
|
/**
|
|
* Status of the last connection test against a provider.
|
|
*/
|
|
export type TDnsProviderStatus = 'untested' | 'ok' | 'error';
|
|
|
|
/**
|
|
* Cloudflare-specific credential shape.
|
|
*/
|
|
export interface ICloudflareCredentials {
|
|
apiToken: string;
|
|
}
|
|
|
|
/**
|
|
* Discriminated union of all supported provider credential shapes.
|
|
* Persisted opaquely on `IDnsProvider.credentials`.
|
|
*/
|
|
export type TDnsProviderCredentials =
|
|
| ({ type: 'cloudflare' } & ICloudflareCredentials);
|
|
|
|
/**
|
|
* A registered DNS provider account. Holds the credentials needed to
|
|
* call the provider's API and a snapshot of its last health check.
|
|
*/
|
|
export interface IDnsProvider {
|
|
id: string;
|
|
name: string;
|
|
type: TDnsProviderType;
|
|
/** Opaque credentials object — shape depends on `type`. */
|
|
credentials: TDnsProviderCredentials;
|
|
status: TDnsProviderStatus;
|
|
lastTestedAt?: number;
|
|
lastError?: string;
|
|
createdAt: number;
|
|
updatedAt: number;
|
|
createdBy: string;
|
|
}
|
|
|
|
/**
|
|
* A redacted view of IDnsProvider safe to send to the UI / over the wire.
|
|
* Strips secret fields from `credentials` while preserving the rest.
|
|
*/
|
|
export interface IDnsProviderPublic {
|
|
id: string;
|
|
name: string;
|
|
type: TDnsProviderType;
|
|
status: TDnsProviderStatus;
|
|
lastTestedAt?: number;
|
|
lastError?: string;
|
|
createdAt: number;
|
|
updatedAt: number;
|
|
createdBy: string;
|
|
/** Whether credentials are configured (true after creation). Never the secret itself. */
|
|
hasCredentials: boolean;
|
|
/**
|
|
* True for the built-in DcRouter pseudo-provider — read-only, cannot be
|
|
* created / edited / deleted. Injected by the handler layer, never
|
|
* persisted in the DnsProviderDoc collection.
|
|
*/
|
|
builtIn?: boolean;
|
|
}
|
|
|
|
/**
|
|
* A domain reported by a provider's API (not yet imported into dcrouter).
|
|
*/
|
|
export interface IProviderDomainListing {
|
|
/** FQDN of the zone (e.g. 'example.com'). */
|
|
name: string;
|
|
/** Provider's internal zone identifier (zone_id for Cloudflare). */
|
|
externalId: string;
|
|
/** Authoritative nameservers reported by the provider. */
|
|
nameservers: string[];
|
|
}
|
|
|
|
/**
|
|
* Schema entry for a single credential field, used by the OpsServer UI to
|
|
* render a provider's credential form dynamically.
|
|
*/
|
|
export interface IDnsProviderCredentialField {
|
|
/** Key under which the value is stored in the credentials object. */
|
|
key: string;
|
|
/** Label shown to the user. */
|
|
label: string;
|
|
/** Optional inline help text. */
|
|
helpText?: string;
|
|
/** Whether the field must be filled. */
|
|
required: boolean;
|
|
/** True for secret fields (rendered as password input, never echoed back). */
|
|
secret: boolean;
|
|
}
|
|
|
|
/**
|
|
* Metadata describing a DNS provider type. Drives:
|
|
* - the OpsServer UI's provider type picker + credential form,
|
|
* - documentation of which credentials each provider needs,
|
|
* - end-to-end consistency between the type union, the discriminated
|
|
* credentials union, the runtime factory, and the form rendering.
|
|
*
|
|
* To add a new provider, append a new entry to `dnsProviderTypeDescriptors`
|
|
* below — and follow the checklist in `ts/dns/providers/factory.ts`.
|
|
*/
|
|
export interface IDnsProviderTypeDescriptor {
|
|
type: TDnsProviderType;
|
|
/** Human-readable name for the UI. */
|
|
displayName: string;
|
|
/** One-line description shown next to the type picker. */
|
|
description: string;
|
|
/** Schema for the credentials form. */
|
|
credentialFields: IDnsProviderCredentialField[];
|
|
}
|
|
|
|
/**
|
|
* Single source of truth for which DNS provider types exist and what
|
|
* credentials each one needs. Used by both backend and frontend.
|
|
*/
|
|
export const dnsProviderTypeDescriptors: ReadonlyArray<IDnsProviderTypeDescriptor> = [
|
|
{
|
|
type: 'dcrouter',
|
|
displayName: 'DcRouter (built-in)',
|
|
description:
|
|
'Built-in authoritative DNS. Records are served directly by dcrouter — delegate the domain\'s NS records to make this effective.',
|
|
credentialFields: [],
|
|
},
|
|
{
|
|
type: 'cloudflare',
|
|
displayName: 'Cloudflare',
|
|
description:
|
|
'Manages records via the Cloudflare API. Provider stays authoritative; dcrouter pushes record changes.',
|
|
credentialFields: [
|
|
{
|
|
key: 'apiToken',
|
|
label: 'API Token',
|
|
helpText:
|
|
'A Cloudflare API token with Zone:Read and DNS:Edit permissions for the target zones.',
|
|
required: true,
|
|
secret: true,
|
|
},
|
|
],
|
|
},
|
|
];
|
|
|
|
/**
|
|
* Look up the descriptor for a given provider type.
|
|
*/
|
|
export function getDnsProviderTypeDescriptor(
|
|
type: TDnsProviderType,
|
|
): IDnsProviderTypeDescriptor | undefined {
|
|
return dnsProviderTypeDescriptors.find((d) => d.type === type);
|
|
}
|