Phase1
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
-- 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;
|
||||
3
packages/database/prisma/migrations/migration_lock.toml
Normal file
3
packages/database/prisma/migrations/migration_lock.toml
Normal file
@@ -0,0 +1,3 @@
|
||||
# Please do not edit this file manually
|
||||
# It should be added in your version-control system (i.e. Git)
|
||||
provider = "postgresql"
|
||||
@@ -40,18 +40,25 @@ enum JobStatus {
|
||||
}
|
||||
|
||||
model User {
|
||||
id String @id @default(uuid())
|
||||
email String @unique
|
||||
username String @unique
|
||||
status UserStatus @default(ACTIVE)
|
||||
createdAt DateTime @default(now()) @db.Timestamptz(3)
|
||||
updatedAt DateTime @updatedAt @db.Timestamptz(3)
|
||||
id String @id @default(uuid())
|
||||
email String @unique
|
||||
username String @unique
|
||||
displayName String?
|
||||
status UserStatus @default(ACTIVE)
|
||||
emailVerifiedAt DateTime? @db.Timestamptz(3)
|
||||
failedLoginAttempts Int @default(0)
|
||||
lockedUntil DateTime? @db.Timestamptz(3)
|
||||
createdAt DateTime @default(now()) @db.Timestamptz(3)
|
||||
updatedAt DateTime @updatedAt @db.Timestamptz(3)
|
||||
|
||||
credentials UserCredential[]
|
||||
sessions UserSession[]
|
||||
platformRoles UserPlatformRole[]
|
||||
gameServers GameServer[]
|
||||
auditEvents AuditEvent[]
|
||||
credentials UserCredential[]
|
||||
sessions UserSession[]
|
||||
platformRoles UserPlatformRole[]
|
||||
gameServers GameServer[]
|
||||
auditEvents AuditEvent[]
|
||||
emailVerificationTokens EmailVerificationToken[]
|
||||
passwordResetTokens PasswordResetToken[]
|
||||
totpCredential TotpCredential?
|
||||
|
||||
@@map("users")
|
||||
}
|
||||
@@ -87,6 +94,63 @@ model UserSession {
|
||||
@@map("user_sessions")
|
||||
}
|
||||
|
||||
model EmailVerificationToken {
|
||||
id String @id @default(uuid())
|
||||
userId String
|
||||
tokenHash String @unique
|
||||
expiresAt DateTime @db.Timestamptz(3)
|
||||
usedAt DateTime? @db.Timestamptz(3)
|
||||
createdAt DateTime @default(now()) @db.Timestamptz(3)
|
||||
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([userId])
|
||||
@@index([expiresAt])
|
||||
@@map("email_verification_tokens")
|
||||
}
|
||||
|
||||
model PasswordResetToken {
|
||||
id String @id @default(uuid())
|
||||
userId String
|
||||
tokenHash String @unique
|
||||
expiresAt DateTime @db.Timestamptz(3)
|
||||
usedAt DateTime? @db.Timestamptz(3)
|
||||
createdAt DateTime @default(now()) @db.Timestamptz(3)
|
||||
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([userId])
|
||||
@@index([expiresAt])
|
||||
@@map("password_reset_tokens")
|
||||
}
|
||||
|
||||
model TotpCredential {
|
||||
id String @id @default(uuid())
|
||||
userId String @unique
|
||||
secret String
|
||||
enabledAt DateTime? @db.Timestamptz(3)
|
||||
createdAt DateTime @default(now()) @db.Timestamptz(3)
|
||||
updatedAt DateTime @updatedAt @db.Timestamptz(3)
|
||||
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
recoveryCodes RecoveryCode[]
|
||||
|
||||
@@map("totp_credentials")
|
||||
}
|
||||
|
||||
model RecoveryCode {
|
||||
id String @id @default(uuid())
|
||||
totpCredentialId String
|
||||
codeHash String
|
||||
usedAt DateTime? @db.Timestamptz(3)
|
||||
createdAt DateTime @default(now()) @db.Timestamptz(3)
|
||||
|
||||
totpCredential TotpCredential @relation(fields: [totpCredentialId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([totpCredentialId])
|
||||
@@map("recovery_codes")
|
||||
}
|
||||
|
||||
model PlatformRole {
|
||||
id String @id @default(uuid())
|
||||
name String @unique
|
||||
|
||||
Reference in New Issue
Block a user