Files
mailadmin/backend/migrations/001_init.sql
2026-04-26 16:05:04 -05:00

147 lines
3.8 KiB
SQL

CREATE TABLE IF NOT EXISTS nodes (
id SERIAL PRIMARY KEY,
name TEXT UNIQUE NOT NULL,
hostname TEXT NOT NULL,
created_at TIMESTAMPTZ DEFAULT now()
);
CREATE TABLE IF NOT EXISTS domains (
id SERIAL PRIMARY KEY,
domain TEXT UNIQUE NOT NULL,
node_name TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'active',
first_seen_at TIMESTAMPTZ DEFAULT now(),
last_seen_at TIMESTAMPTZ DEFAULT now()
);
CREATE TABLE IF NOT EXISTS mailboxes (
id SERIAL PRIMARY KEY,
email_address TEXT UNIQUE NOT NULL,
domain TEXT NOT NULL,
node_name TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'active',
used_bytes BIGINT DEFAULT 0,
last_usage_scan_at TIMESTAMPTZ,
first_seen_at TIMESTAMPTZ DEFAULT now(),
last_seen_at TIMESTAMPTZ DEFAULT now()
);
CREATE TABLE IF NOT EXISTS admin_users (
id SERIAL PRIMARY KEY,
email TEXT UNIQUE NOT NULL,
password_hash TEXT NOT NULL,
role TEXT NOT NULL DEFAULT 'super_admin',
created_at TIMESTAMPTZ DEFAULT now()
);
CREATE TABLE IF NOT EXISTS audit_log (
id SERIAL PRIMARY KEY,
actor_email TEXT,
action TEXT NOT NULL,
target TEXT,
details JSONB,
created_at TIMESTAMPTZ DEFAULT now()
);
-- ============================================================
-- Upgrade existing MVP database
-- ============================================================
ALTER TABLE nodes
ADD COLUMN IF NOT EXISTS updated_at TIMESTAMPTZ DEFAULT now();
ALTER TABLE nodes
ADD COLUMN IF NOT EXISTS is_current BOOLEAN DEFAULT false;
ALTER TABLE domains
ADD COLUMN IF NOT EXISTS updated_at TIMESTAMPTZ DEFAULT now();
ALTER TABLE domains
ADD COLUMN IF NOT EXISTS last_synced_at TIMESTAMPTZ;
ALTER TABLE domains
ADD COLUMN IF NOT EXISTS notes TEXT DEFAULT '';
ALTER TABLE mailboxes
ADD COLUMN IF NOT EXISTS local_part TEXT;
ALTER TABLE mailboxes
ADD COLUMN IF NOT EXISTS quota_bytes BIGINT;
ALTER TABLE mailboxes
ADD COLUMN IF NOT EXISTS quota_percent NUMERIC(8,3);
ALTER TABLE mailboxes
ADD COLUMN IF NOT EXISTS message_count BIGINT;
ALTER TABLE mailboxes
ADD COLUMN IF NOT EXISTS message_limit BIGINT;
ALTER TABLE mailboxes
ADD COLUMN IF NOT EXISTS usage_scanned_at TIMESTAMPTZ;
ALTER TABLE mailboxes
ADD COLUMN IF NOT EXISTS updated_at TIMESTAMPTZ DEFAULT now();
ALTER TABLE mailboxes
ADD COLUMN IF NOT EXISTS deleted_at TIMESTAMPTZ;
ALTER TABLE admin_users
ADD COLUMN IF NOT EXISTS allowed_domains TEXT[] NOT NULL DEFAULT '{}';
ALTER TABLE admin_users
ADD COLUMN IF NOT EXISTS active BOOLEAN NOT NULL DEFAULT true;
ALTER TABLE admin_users
ADD COLUMN IF NOT EXISTS updated_at TIMESTAMPTZ DEFAULT now();
ALTER TABLE audit_log
ADD COLUMN IF NOT EXISTS target_type TEXT;
ALTER TABLE audit_log
ADD COLUMN IF NOT EXISTS target_id TEXT;
ALTER TABLE audit_log
ADD COLUMN IF NOT EXISTS ip_address TEXT;
-- details existed already, but make it safer for newer code
ALTER TABLE audit_log
ALTER COLUMN details SET DEFAULT '{}';
-- Fill local_part for existing rows
UPDATE mailboxes
SET local_part = split_part(email_address, '@', 1)
WHERE local_part IS NULL
AND email_address LIKE '%@%';
-- Keep old and new usage timestamp columns in sync initially
UPDATE mailboxes
SET usage_scanned_at = last_usage_scan_at
WHERE usage_scanned_at IS NULL
AND last_usage_scan_at IS NOT NULL;
-- Backfill new audit target columns from old target column
UPDATE audit_log
SET target_id = target
WHERE target_id IS NULL
AND target IS NOT NULL;
UPDATE audit_log
SET target_type = 'unknown'
WHERE target_type IS NULL;
-- Useful indexes
CREATE INDEX IF NOT EXISTS idx_domains_node_name
ON domains(node_name);
CREATE INDEX IF NOT EXISTS idx_mailboxes_domain
ON mailboxes(domain);
CREATE INDEX IF NOT EXISTS idx_mailboxes_node_name
ON mailboxes(node_name);
CREATE INDEX IF NOT EXISTS idx_audit_created
ON audit_log(created_at DESC);
CREATE INDEX IF NOT EXISTS idx_admin_users_allowed_domains
ON admin_users USING GIN(allowed_domains);