-- Additional domain tables for VLANs, devices, and user metadata -- VLAN catalog (acts as enum of available VLANs) CREATE TABLE IF NOT EXISTS vlans ( id INTEGER PRIMARY KEY, nombre TEXT NOT NULL, descripcion TEXT ); -- Devices table: store individual device information CREATE TABLE IF NOT EXISTS dispositivos ( id SERIAL PRIMARY KEY, mac VARCHAR(32) UNIQUE NOT NULL, nombre TEXT, descripcion TEXT, vendor TEXT, first_seen TIMESTAMPTZ NOT NULL DEFAULT NOW(), last_seen TIMESTAMPTZ, notas TEXT ); CREATE INDEX IF NOT EXISTS dispositivos_mac_idx ON dispositivos (mac); -- Users metadata table (separate from radcheck/radreply for FreeRADIUS) CREATE TABLE IF NOT EXISTS users ( username VARCHAR(64) PRIMARY KEY, etiquetas TEXT[] NOT NULL DEFAULT '{}', created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), habilitado_since TIMESTAMPTZ, dispositivos_utilizados INTEGER[] NOT NULL DEFAULT '{}', -- references dispositivos.id dispositivos_conectados INTEGER[] NOT NULL DEFAULT '{}' -- references dispositivos.id ); -- updated_at trigger helper DO $$ BEGIN IF NOT EXISTS ( SELECT 1 FROM pg_proc WHERE proname = 'set_updated_at' ) THEN CREATE FUNCTION set_updated_at() RETURNS TRIGGER AS $$ BEGIN NEW.updated_at = NOW(); RETURN NEW; END; $$ LANGUAGE plpgsql; END IF; END$$; DO $$ BEGIN IF NOT EXISTS ( SELECT 1 FROM pg_trigger WHERE tgname = 'trg_users_updated' ) THEN CREATE TRIGGER trg_users_updated BEFORE UPDATE ON users FOR EACH ROW EXECUTE FUNCTION set_updated_at(); END IF; END$$;