Ports zone/record management across Cloudflare, Loopia, Pi-hole, Azure DNS, cPanel, and Technitium onto the new stack. Unlike the original (one instance per provider configured via env vars), providers are now configured through the UI and support multiple named instances per type, with API credentials encrypted at rest via the integration_credentials table. - server/src/dns/adapters/*: each provider ported to a config-based factory (no more process.env reads), preserving each provider's original quirks (Pi-hole session auth, Azure record-set merging, Loopia XML-RPC, cPanel UAPI/API2 fallbacks, Technitium composite record IDs). - server/src/routes/dns.ts: provider CRUD (admin), a "test connection" endpoint, and zone/record browsing+sync+CRUD (operator+), all audit-logged. - dns_zones_cache/dns_records_cache tables replace Sloth Manager's dns-cache.json file, keeping the same "cache is the source of truth for display, sync fetches fresh from the provider" behavior. - web: a DNS page with provider management, zone browsing, and a record editor, plus a reusable dynamic provider-config form. Verified: full build (tsc + vite) passes; a scripted HTTP-layer test against a running server exercises auth, role gating (403 for viewer), validation (400 on missing config fields), provider CRUD, credential non-leakage in list responses, and adapter error propagation (502 against an unreachable host) — all passing. Real provider connectivity still needs to be checked against the user's actual DNS accounts. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
138 lines
4.6 KiB
SQL
138 lines
4.6 KiB
SQL
CREATE TABLE `audit_log` (
|
|
`id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
|
|
`actor_user_id` integer,
|
|
`actor_label` text,
|
|
`category` text NOT NULL,
|
|
`action` text NOT NULL,
|
|
`target_type` text,
|
|
`target_id` text,
|
|
`detail` text,
|
|
`created_at` text DEFAULT (current_timestamp) NOT NULL,
|
|
FOREIGN KEY (`actor_user_id`) REFERENCES `users`(`id`) ON UPDATE no action ON DELETE set null
|
|
);
|
|
--> statement-breakpoint
|
|
CREATE TABLE `dns_providers` (
|
|
`id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
|
|
`provider_type` text NOT NULL,
|
|
`name` text NOT NULL,
|
|
`credential_id` integer,
|
|
`config` text,
|
|
`enabled` integer DEFAULT true NOT NULL,
|
|
`created_at` text DEFAULT (current_timestamp) NOT NULL,
|
|
FOREIGN KEY (`credential_id`) REFERENCES `integration_credentials`(`id`) ON UPDATE no action ON DELETE set null
|
|
);
|
|
--> statement-breakpoint
|
|
CREATE TABLE `dns_records_cache` (
|
|
`id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
|
|
`provider_id` integer NOT NULL,
|
|
`zone_id` text NOT NULL,
|
|
`record_id` text NOT NULL,
|
|
`type` text NOT NULL,
|
|
`name` text NOT NULL,
|
|
`content` text NOT NULL,
|
|
`ttl` integer,
|
|
`priority` integer,
|
|
`proxied` integer,
|
|
FOREIGN KEY (`provider_id`) REFERENCES `dns_providers`(`id`) ON UPDATE no action ON DELETE cascade
|
|
);
|
|
--> statement-breakpoint
|
|
CREATE TABLE `dns_zones_cache` (
|
|
`id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
|
|
`provider_id` integer NOT NULL,
|
|
`zone_id` text NOT NULL,
|
|
`zone_name` text NOT NULL,
|
|
`synced_at` text,
|
|
FOREIGN KEY (`provider_id`) REFERENCES `dns_providers`(`id`) ON UPDATE no action ON DELETE cascade
|
|
);
|
|
--> statement-breakpoint
|
|
CREATE UNIQUE INDEX `dns_zones_cache_provider_zone_idx` ON `dns_zones_cache` (`provider_id`,`zone_id`);--> statement-breakpoint
|
|
CREATE TABLE `integration_credentials` (
|
|
`id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
|
|
`name` text NOT NULL,
|
|
`encrypted_secret` text NOT NULL,
|
|
`created_at` text DEFAULT (current_timestamp) NOT NULL
|
|
);
|
|
--> statement-breakpoint
|
|
CREATE TABLE `integrations` (
|
|
`id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
|
|
`type` text NOT NULL,
|
|
`name` text NOT NULL,
|
|
`base_url` text NOT NULL,
|
|
`credential_id` integer,
|
|
`config` text,
|
|
`enabled` integer DEFAULT true NOT NULL,
|
|
`created_at` text DEFAULT (current_timestamp) NOT NULL,
|
|
FOREIGN KEY (`credential_id`) REFERENCES `integration_credentials`(`id`) ON UPDATE no action ON DELETE set null
|
|
);
|
|
--> statement-breakpoint
|
|
CREATE TABLE `ipam_entries` (
|
|
`id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
|
|
`ip_address` text NOT NULL,
|
|
`label` text,
|
|
`vendor` text,
|
|
`location` text,
|
|
`notes` text,
|
|
`created_at` text DEFAULT (current_timestamp) NOT NULL,
|
|
`updated_at` text DEFAULT (current_timestamp) NOT NULL
|
|
);
|
|
--> statement-breakpoint
|
|
CREATE UNIQUE INDEX `ipam_entries_ip_address_unique` ON `ipam_entries` (`ip_address`);--> statement-breakpoint
|
|
CREATE TABLE `scheduled_tasks` (
|
|
`id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
|
|
`server_id` integer NOT NULL,
|
|
`schedule_type` text NOT NULL,
|
|
`origin` text DEFAULT 'agent' NOT NULL,
|
|
`name` text NOT NULL,
|
|
`command` text,
|
|
`schedule_expression` text,
|
|
`source` text,
|
|
`enabled` integer DEFAULT true NOT NULL,
|
|
`next_run_at` text,
|
|
`raw_metadata` text,
|
|
`is_stale` integer DEFAULT false NOT NULL,
|
|
`first_seen_at` text DEFAULT (current_timestamp) NOT NULL,
|
|
`last_seen_at` text DEFAULT (current_timestamp) NOT NULL,
|
|
FOREIGN KEY (`server_id`) REFERENCES `servers`(`id`) ON UPDATE no action ON DELETE cascade
|
|
);
|
|
--> statement-breakpoint
|
|
CREATE TABLE `secrets` (
|
|
`id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
|
|
`name` text NOT NULL,
|
|
`type` text DEFAULT 'generic' NOT NULL,
|
|
`description` text,
|
|
`expiry_date` text NOT NULL,
|
|
`warn_days` integer DEFAULT 30 NOT NULL,
|
|
`notes` text,
|
|
`created_at` text DEFAULT (current_timestamp) NOT NULL,
|
|
`updated_at` text DEFAULT (current_timestamp) NOT NULL
|
|
);
|
|
--> statement-breakpoint
|
|
CREATE TABLE `servers` (
|
|
`id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
|
|
`name` text NOT NULL,
|
|
`hostname` text,
|
|
`os_type` text DEFAULT 'linux' NOT NULL,
|
|
`description` text,
|
|
`api_token_hash` text NOT NULL,
|
|
`api_token_prefix` text NOT NULL,
|
|
`created_at` text DEFAULT (current_timestamp) NOT NULL,
|
|
`last_seen_at` text
|
|
);
|
|
--> statement-breakpoint
|
|
CREATE TABLE `settings` (
|
|
`key` text PRIMARY KEY NOT NULL,
|
|
`value` text NOT NULL,
|
|
`updated_at` text DEFAULT (current_timestamp) NOT NULL
|
|
);
|
|
--> statement-breakpoint
|
|
CREATE TABLE `users` (
|
|
`id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
|
|
`oidc_sub` text NOT NULL,
|
|
`email` text,
|
|
`name` text,
|
|
`role` text DEFAULT 'viewer' NOT NULL,
|
|
`created_at` text DEFAULT (current_timestamp) NOT NULL,
|
|
`last_login_at` text
|
|
);
|
|
--> statement-breakpoint
|
|
CREATE UNIQUE INDEX `users_oidc_sub_unique` ON `users` (`oidc_sub`); |