Files
HexaHost-GameCloud/packages/database/prisma/migrations/20260626120000_phase1_auth/migration.sql
smueller 58961000eb
Some checks failed
CI / Node — lint, typecheck, test, build (push) Failing after 9s
CI / Go — node-agent tests (push) Failing after 21s
CI / Go — edge-gateway build (push) Successful in 13s
Phase1
2026-06-26 11:31:54 +02:00

96 lines
4.0 KiB
SQL

-- Phase 1: Authentication models and user extensions
-- AlterTable
ALTER TABLE "users" ADD COLUMN IF NOT EXISTS "displayName" TEXT;
ALTER TABLE "users" ADD COLUMN IF NOT EXISTS "emailVerifiedAt" TIMESTAMPTZ(3);
ALTER TABLE "users" ADD COLUMN IF NOT EXISTS "failedLoginAttempts" INTEGER NOT NULL DEFAULT 0;
ALTER TABLE "users" ADD COLUMN IF NOT EXISTS "lockedUntil" TIMESTAMPTZ(3);
-- CreateTable
CREATE TABLE IF NOT EXISTS "email_verification_tokens" (
"id" TEXT NOT NULL,
"userId" TEXT NOT NULL,
"tokenHash" TEXT NOT NULL,
"expiresAt" TIMESTAMPTZ(3) NOT NULL,
"usedAt" TIMESTAMPTZ(3),
"createdAt" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "email_verification_tokens_pkey" PRIMARY KEY ("id")
);
CREATE TABLE IF NOT EXISTS "password_reset_tokens" (
"id" TEXT NOT NULL,
"userId" TEXT NOT NULL,
"tokenHash" TEXT NOT NULL,
"expiresAt" TIMESTAMPTZ(3) NOT NULL,
"usedAt" TIMESTAMPTZ(3),
"createdAt" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "password_reset_tokens_pkey" PRIMARY KEY ("id")
);
CREATE TABLE IF NOT EXISTS "totp_credentials" (
"id" TEXT NOT NULL,
"userId" TEXT NOT NULL,
"secret" TEXT NOT NULL,
"enabledAt" TIMESTAMPTZ(3),
"createdAt" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMPTZ(3) NOT NULL,
CONSTRAINT "totp_credentials_pkey" PRIMARY KEY ("id")
);
CREATE TABLE IF NOT EXISTS "recovery_codes" (
"id" TEXT NOT NULL,
"totpCredentialId" TEXT NOT NULL,
"codeHash" TEXT NOT NULL,
"usedAt" TIMESTAMPTZ(3),
"createdAt" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "recovery_codes_pkey" PRIMARY KEY ("id")
);
-- CreateIndex
CREATE UNIQUE INDEX IF NOT EXISTS "email_verification_tokens_tokenHash_key" ON "email_verification_tokens"("tokenHash");
CREATE INDEX IF NOT EXISTS "email_verification_tokens_userId_idx" ON "email_verification_tokens"("userId");
CREATE INDEX IF NOT EXISTS "email_verification_tokens_expiresAt_idx" ON "email_verification_tokens"("expiresAt");
CREATE UNIQUE INDEX IF NOT EXISTS "password_reset_tokens_tokenHash_key" ON "password_reset_tokens"("tokenHash");
CREATE INDEX IF NOT EXISTS "password_reset_tokens_userId_idx" ON "password_reset_tokens"("userId");
CREATE INDEX IF NOT EXISTS "password_reset_tokens_expiresAt_idx" ON "password_reset_tokens"("expiresAt");
CREATE UNIQUE INDEX IF NOT EXISTS "totp_credentials_userId_key" ON "totp_credentials"("userId");
CREATE INDEX IF NOT EXISTS "recovery_codes_totpCredentialId_idx" ON "recovery_codes"("totpCredentialId");
-- AddForeignKey
DO $$ BEGIN
ALTER TABLE "email_verification_tokens" ADD CONSTRAINT "email_verification_tokens_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
EXCEPTION WHEN duplicate_object THEN NULL;
END $$;
DO $$ BEGIN
ALTER TABLE "password_reset_tokens" ADD CONSTRAINT "password_reset_tokens_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
EXCEPTION WHEN duplicate_object THEN NULL;
END $$;
DO $$ BEGIN
ALTER TABLE "totp_credentials" ADD CONSTRAINT "totp_credentials_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
EXCEPTION WHEN duplicate_object THEN NULL;
END $$;
DO $$ BEGIN
ALTER TABLE "recovery_codes" ADD CONSTRAINT "recovery_codes_totpCredentialId_fkey" FOREIGN KEY ("totpCredentialId") REFERENCES "totp_credentials"("id") ON DELETE CASCADE ON UPDATE CASCADE;
EXCEPTION WHEN duplicate_object THEN NULL;
END $$;
-- Seed platform roles
INSERT INTO "platform_roles" ("id", "name", "description", "createdAt", "updatedAt")
VALUES
(gen_random_uuid()::text, 'USER', 'Standard platform user', NOW(), NOW()),
(gen_random_uuid()::text, 'SUPPORT', 'Support staff', NOW(), NOW()),
(gen_random_uuid()::text, 'MODERATOR', 'Content moderator', NOW(), NOW()),
(gen_random_uuid()::text, 'ADMIN', 'Platform administrator', NOW(), NOW()),
(gen_random_uuid()::text, 'SUPER_ADMIN', 'Super administrator', NOW(), NOW())
ON CONFLICT ("name") DO NOTHING;