From 277ee0c9b6f96c9dab2012f13f908c89e6fb9c39 Mon Sep 17 00:00:00 2001 From: alphaeusmote <41258468-alphaeusmote@users.noreply.replit.com> Date: Thu, 10 Apr 2025 02:53:35 +0000 Subject: [PATCH] Update database schema to use UUIDs for primary keys Replit-Commit-Author: Agent Replit-Commit-Session-Id: 9111ef36-26c8-4085-84ca-a35dc1fec1b5 Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/7083d608-d6d3-4a6a-9a27-6286c5109627/c3b7d9a5-de8b-4951-8fe9-8c111686d08e.jpg --- migrations/uuid-migration-revised.sql | 240 ++++++++++++++++++++++++++ server/auth.ts | 2 +- 2 files changed, 241 insertions(+), 1 deletion(-) create mode 100644 migrations/uuid-migration-revised.sql diff --git a/migrations/uuid-migration-revised.sql b/migrations/uuid-migration-revised.sql new file mode 100644 index 0000000..30a80aa --- /dev/null +++ b/migrations/uuid-migration-revised.sql @@ -0,0 +1,240 @@ +-- Enable uuid-ossp extension if not already enabled +CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; + +-- Drop existing tables with a clean slate approach +-- We'll save data first, then recreate the schema with UUIDs + +-- Create temporary tables to store data +CREATE TEMP TABLE tmp_organizations AS SELECT * FROM organizations; +CREATE TEMP TABLE tmp_users AS SELECT * FROM users; +CREATE TEMP TABLE tmp_domains AS SELECT * FROM domains; +CREATE TEMP TABLE tmp_dns_records AS SELECT * FROM dns_records; +CREATE TEMP TABLE tmp_providers AS SELECT * FROM providers; +CREATE TEMP TABLE tmp_api_tokens AS SELECT * FROM api_tokens; +CREATE TEMP TABLE tmp_dns_history AS SELECT * FROM dns_history; +CREATE TEMP TABLE tmp_dns_metrics AS SELECT * FROM dns_metrics; + +-- Drop all tables (in reverse order of dependencies) +DROP TABLE IF EXISTS dns_metrics; +DROP TABLE IF EXISTS dns_history; +DROP TABLE IF EXISTS dns_records; +DROP TABLE IF EXISTS api_tokens; +DROP TABLE IF EXISTS domains; +DROP TABLE IF EXISTS users; +DROP TABLE IF EXISTS providers; +DROP TABLE IF EXISTS organizations; + +-- Now recreate tables with UUID fields +CREATE TABLE organizations ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + name TEXT NOT NULL, + is_active BOOLEAN NOT NULL DEFAULT true, + created_at TIMESTAMP NOT NULL DEFAULT now() +); + +CREATE TABLE providers ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + name TEXT NOT NULL, + type TEXT NOT NULL, + credentials JSONB, + is_active BOOLEAN NOT NULL DEFAULT true, + created_at TIMESTAMP NOT NULL DEFAULT now() +); + +CREATE TABLE users ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + username TEXT NOT NULL UNIQUE, + password TEXT NOT NULL, + email TEXT NOT NULL UNIQUE, + full_name TEXT, + role TEXT NOT NULL DEFAULT 'user', + organization_id UUID REFERENCES organizations(id) ON DELETE CASCADE, + created_at TIMESTAMP NOT NULL DEFAULT now() +); + +CREATE TABLE domains ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + name TEXT NOT NULL, + organization_id UUID NOT NULL REFERENCES organizations(id) ON DELETE CASCADE, + provider_id UUID REFERENCES providers(id) ON DELETE SET NULL, + provider_domain_id TEXT, + is_active BOOLEAN NOT NULL DEFAULT true, + auto_update BOOLEAN NOT NULL DEFAULT false, + created_at TIMESTAMP NOT NULL DEFAULT now(), + last_checked TIMESTAMP +); + +CREATE TABLE dns_records ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + domain_id UUID NOT NULL REFERENCES domains(id) ON DELETE CASCADE, + name TEXT NOT NULL, + type TEXT NOT NULL, + content TEXT NOT NULL, + ttl INTEGER NOT NULL DEFAULT 3600, + priority INTEGER, + provider_record_id TEXT, + notes TEXT, + is_active BOOLEAN NOT NULL DEFAULT true, + auto_update BOOLEAN NOT NULL DEFAULT false, + created_at TIMESTAMP NOT NULL DEFAULT now(), + last_updated TIMESTAMP +); + +CREATE TABLE api_tokens ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + organization_id UUID NOT NULL REFERENCES organizations(id) ON DELETE CASCADE, + name TEXT NOT NULL, + token TEXT NOT NULL UNIQUE, + permissions TEXT[] NOT NULL, + created_by UUID REFERENCES users(id) ON DELETE SET NULL, + expires_at TIMESTAMP, + is_active BOOLEAN NOT NULL DEFAULT true, + created_at TIMESTAMP NOT NULL DEFAULT now(), + last_used TIMESTAMP +); + +CREATE TABLE dns_history ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + record_id UUID NOT NULL REFERENCES dns_records(id) ON DELETE CASCADE, + action TEXT NOT NULL, + previous_value TEXT, + new_value TEXT, + user_id UUID REFERENCES users(id) ON DELETE SET NULL, + timestamp TIMESTAMP NOT NULL DEFAULT now() +); + +CREATE TABLE dns_metrics ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + metric_type TEXT NOT NULL, + domain_id UUID REFERENCES domains(id) ON DELETE CASCADE, + record_id UUID REFERENCES dns_records(id) ON DELETE CASCADE, + value DOUBLE PRECISION NOT NULL, + timestamp TIMESTAMP NOT NULL DEFAULT now() +); + +-- Create new tables for the features that were missing +CREATE TABLE webhooks ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + name TEXT NOT NULL, + url TEXT NOT NULL, + organization_id UUID NOT NULL REFERENCES organizations(id) ON DELETE CASCADE, + secret TEXT, + events TEXT[] NOT NULL, + is_active BOOLEAN NOT NULL DEFAULT true, + last_triggered TIMESTAMP, + created_by UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE, + created_at TIMESTAMP NOT NULL DEFAULT now() +); + +CREATE TABLE webhook_delivery_logs ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + webhook_id UUID NOT NULL REFERENCES webhooks(id) ON DELETE CASCADE, + payload JSONB NOT NULL, + response TEXT, + status_code INTEGER, + status BOOLEAN NOT NULL, + error TEXT, + timestamp TIMESTAMP NOT NULL DEFAULT now(), + duration_ms INTEGER NOT NULL +); + +CREATE TABLE custom_roles ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + name TEXT NOT NULL UNIQUE, + description TEXT, + permissions TEXT[] NOT NULL, + is_active BOOLEAN NOT NULL DEFAULT true, + created_at TIMESTAMP NOT NULL DEFAULT now(), + created_by UUID NOT NULL REFERENCES users(id) ON DELETE SET NULL +); + +CREATE TABLE groups ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + name TEXT NOT NULL, + description TEXT, + created_at TIMESTAMP NOT NULL DEFAULT now(), + is_active BOOLEAN NOT NULL DEFAULT true, + created_by UUID NOT NULL REFERENCES users(id) ON DELETE SET NULL +); + +CREATE TABLE group_memberships ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + group_id UUID NOT NULL REFERENCES groups(id) ON DELETE CASCADE, + entity_type TEXT NOT NULL, + entity_id UUID NOT NULL, + created_at TIMESTAMP NOT NULL DEFAULT now(), + conditions JSONB +); + +-- Helper function to generate a UUID from an integer +CREATE OR REPLACE FUNCTION int_to_uuid(id INTEGER) RETURNS UUID AS $$ +BEGIN + RETURN uuid_generate_v5('11111111-1111-1111-1111-111111111111'::UUID, id::TEXT); +END; +$$ LANGUAGE plpgsql; + +-- Insert data back into the tables with UUIDs +-- Organizations +INSERT INTO organizations (id, name, is_active, created_at) +SELECT int_to_uuid(id), name, is_active, created_at +FROM tmp_organizations; + +-- Providers +INSERT INTO providers (id, name, type, credentials, is_active, created_at) +SELECT int_to_uuid(id), name, type, credentials, is_active, created_at +FROM tmp_providers; + +-- Users +INSERT INTO users (id, username, password, email, full_name, role, organization_id, created_at) +SELECT int_to_uuid(id), username, password, email, full_name, role, int_to_uuid(organization_id), created_at +FROM tmp_users; + +-- Domains +INSERT INTO domains (id, name, organization_id, provider_id, provider_domain_id, is_active, auto_update, created_at, last_checked) +SELECT int_to_uuid(id), name, int_to_uuid(organization_id), + CASE WHEN provider_id IS NOT NULL THEN int_to_uuid(provider_id) ELSE NULL END, + provider_domain_id, is_active, auto_update, created_at, last_checked +FROM tmp_domains; + +-- DNS Records +INSERT INTO dns_records (id, domain_id, name, type, content, ttl, priority, provider_record_id, notes, is_active, auto_update, created_at, last_updated) +SELECT int_to_uuid(id), int_to_uuid(domain_id), name, type, content, ttl, priority, provider_record_id, notes, is_active, auto_update, created_at, last_updated +FROM tmp_dns_records; + +-- API Tokens +INSERT INTO api_tokens (id, organization_id, name, token, permissions, created_by, expires_at, is_active, created_at, last_used) +SELECT int_to_uuid(id), int_to_uuid(organization_id), name, token, permissions, + CASE WHEN created_by IS NOT NULL THEN int_to_uuid(created_by) ELSE NULL END, + expires_at, is_active, created_at, last_used +FROM tmp_api_tokens; + +-- DNS History +INSERT INTO dns_history (id, record_id, action, previous_value, new_value, user_id, timestamp) +SELECT int_to_uuid(id), int_to_uuid(record_id), action, previous_value, new_value, + CASE WHEN user_id IS NOT NULL THEN int_to_uuid(user_id) ELSE NULL END, + timestamp +FROM tmp_dns_history; + +-- DNS Metrics +INSERT INTO dns_metrics (id, metric_type, domain_id, record_id, value, timestamp) +SELECT int_to_uuid(id), metric_type, + CASE WHEN domain_id IS NOT NULL THEN int_to_uuid(domain_id) ELSE NULL END, + CASE WHEN record_id IS NOT NULL THEN int_to_uuid(record_id) ELSE NULL END, + value, timestamp +FROM tmp_dns_metrics; + +-- Drop the conversion function +DROP FUNCTION int_to_uuid; + +-- Clean up session table if it exists +DROP TABLE IF EXISTS session; + +-- Recreate session table for auth +CREATE TABLE IF NOT EXISTS "session" ( + "sid" varchar NOT NULL COLLATE "default", + "sess" json NOT NULL, + "expire" timestamp(6) NOT NULL, + CONSTRAINT "session_pkey" PRIMARY KEY ("sid") +); + +CREATE INDEX IF NOT EXISTS "IDX_session_expire" ON "session" ("expire"); \ No newline at end of file diff --git a/server/auth.ts b/server/auth.ts index 436984b..fb016d7 100644 --- a/server/auth.ts +++ b/server/auth.ts @@ -116,7 +116,7 @@ export function setupAuth(app: Express) { ); passport.serializeUser((user, done) => done(null, user.id)); - passport.deserializeUser(async (id: number, done) => { + passport.deserializeUser(async (id: string, done) => { try { const user = await storage.getUser(id); done(null, user);