-- Initial migration for RayLab Core (PostgreSQL) -- Requires: CREATE EXTENSION IF NOT EXISTS pgcrypto; (for gen_random_uuid()) BEGIN; -- Extension for UUID generation CREATE EXTENSION IF NOT EXISTS "pgcrypto"; -- Enum types DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'userrolesource') THEN CREATE TYPE "UserRoleSource" AS ENUM ('AUTHENTIK', 'SYSTEM'); END IF; END $$; -- Users CREATE TABLE IF NOT EXISTS "User" ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), authentik_id text UNIQUE, authentik_user_id text UNIQUE, authentik_subject text UNIQUE, username varchar(255) UNIQUE, email varchar(320) UNIQUE, name varchar(255), picture text, is_active boolean NOT NULL DEFAULT true, deleted_at timestamptz, last_seen_at timestamptz, last_synced_at timestamptz, sync_status text, storage_quota bigint DEFAULT 10737418240, storage_used bigint DEFAULT 0, metadata jsonb, last_group_hash text, created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now() ); CREATE INDEX IF NOT EXISTS idx_user_authentik_id ON "User" (authentik_id); CREATE INDEX IF NOT EXISTS idx_user_username ON "User" (username); CREATE INDEX IF NOT EXISTS idx_user_email ON "User" (email); -- Roles CREATE TABLE IF NOT EXISTS "Role" ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), code varchar(100) NOT NULL UNIQUE, name varchar(255) NOT NULL, display_name varchar(255), description text, is_default boolean NOT NULL DEFAULT false, created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now() ); -- Permissions CREATE TABLE IF NOT EXISTS "Permission" ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), code varchar(150) NOT NULL UNIQUE, name varchar(255) NOT NULL, display_name varchar(255), description text, created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now() ); -- RolePermission CREATE TABLE IF NOT EXISTS "RolePermission" ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), role_id uuid NOT NULL REFERENCES "Role"(id) ON DELETE CASCADE, permission_id uuid NOT NULL REFERENCES "Permission"(id) ON DELETE CASCADE, created_at timestamptz NOT NULL DEFAULT now(), CONSTRAINT uq_role_permission UNIQUE (role_id, permission_id) ); CREATE INDEX IF NOT EXISTS idx_rolepermission_role_id ON "RolePermission" (role_id); CREATE INDEX IF NOT EXISTS idx_rolepermission_permission_id ON "RolePermission" (permission_id); -- UserRole CREATE TABLE IF NOT EXISTS "UserRole" ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), user_id uuid NOT NULL REFERENCES "User"(id) ON DELETE CASCADE, role_id uuid NOT NULL REFERENCES "Role"(id) ON DELETE CASCADE, source "UserRoleSource" NOT NULL DEFAULT 'AUTHENTIK', synced_at timestamptz NOT NULL DEFAULT now(), created_at timestamptz NOT NULL DEFAULT now(), CONSTRAINT uq_user_role UNIQUE (user_id, role_id) ); CREATE INDEX IF NOT EXISTS idx_userrole_user_id ON "UserRole" (user_id); CREATE INDEX IF NOT EXISTS idx_userrole_role_id ON "UserRole" (role_id); -- AuthGroupRoleMapping CREATE TABLE IF NOT EXISTS "AuthGroupRoleMapping" ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), auth_group varchar(255) NOT NULL, role_id uuid NOT NULL REFERENCES "Role"(id) ON DELETE CASCADE, created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now() ); CREATE INDEX IF NOT EXISTS idx_authgroup_name ON "AuthGroupRoleMapping" (auth_group); -- AuditLog CREATE TABLE IF NOT EXISTS "AuditLog" ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), user_id uuid REFERENCES "User"(id) ON DELETE SET NULL, action varchar(200) NOT NULL, resource varchar(200), resource_id text, details jsonb, created_at timestamptz NOT NULL DEFAULT now() ); CREATE INDEX IF NOT EXISTS idx_auditlog_user_id ON "AuditLog" (user_id); CREATE INDEX IF NOT EXISTS idx_auditlog_action ON "AuditLog" (action); COMMIT;