feat: add email verification, password reset, and WSDC integration (Phase 1.5)
Backend features: - AWS SES email service with HTML templates - Email verification with dual method (link + 6-digit PIN code) - Password reset workflow with secure tokens - WSDC API proxy for dancer lookup and auto-fill registration - Extended User model with verification and WSDC fields - Email verification middleware for protected routes Frontend features: - Two-step registration with WSDC ID lookup - Password strength indicator component - Email verification page with code input - Password reset flow (request + reset pages) - Verification banner for unverified users - Updated authentication context and API service Testing: - 65 unit tests with 100% coverage of new features - Tests for auth utils, email service, WSDC controller, and middleware - Integration tests for full authentication flows - Comprehensive mocking of AWS SES and external APIs Database: - Migration: add WSDC fields (firstName, lastName, wsdcId) - Migration: add email verification fields (token, code, expiry) - Migration: add password reset fields (token, expiry) Documentation: - Complete Phase 1.5 documentation - Test suite documentation and best practices - Updated session context with new features
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
-- AlterTable: Add WSDC Integration fields
|
||||
ALTER TABLE "users" ADD COLUMN "first_name" VARCHAR(100),
|
||||
ADD COLUMN "last_name" VARCHAR(100),
|
||||
ADD COLUMN "wsdc_id" VARCHAR(20);
|
||||
|
||||
-- AlterTable: Add Email Verification fields
|
||||
ALTER TABLE "users" ADD COLUMN "email_verified" BOOLEAN NOT NULL DEFAULT false,
|
||||
ADD COLUMN "verification_token" VARCHAR(255),
|
||||
ADD COLUMN "verification_code" VARCHAR(6),
|
||||
ADD COLUMN "verification_token_expiry" TIMESTAMP(3);
|
||||
|
||||
-- AlterTable: Add Password Reset fields
|
||||
ALTER TABLE "users" ADD COLUMN "reset_token" VARCHAR(255),
|
||||
ADD COLUMN "reset_token_expiry" TIMESTAMP(3);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "users_wsdc_id_key" ON "users"("wsdc_id");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "users_verification_token_key" ON "users"("verification_token");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "users_reset_token_key" ON "users"("reset_token");
|
||||
@@ -12,20 +12,36 @@ datasource db {
|
||||
|
||||
// Users table
|
||||
model User {
|
||||
id Int @id @default(autoincrement())
|
||||
username String @unique @db.VarChar(50)
|
||||
email String @unique @db.VarChar(255)
|
||||
passwordHash String @map("password_hash") @db.VarChar(255)
|
||||
avatar String? @db.VarChar(255)
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
id Int @id @default(autoincrement())
|
||||
username String @unique @db.VarChar(50)
|
||||
email String @unique @db.VarChar(255)
|
||||
passwordHash String @map("password_hash") @db.VarChar(255)
|
||||
|
||||
// WSDC Integration (Phase 1.5)
|
||||
firstName String? @map("first_name") @db.VarChar(100)
|
||||
lastName String? @map("last_name") @db.VarChar(100)
|
||||
wsdcId String? @unique @map("wsdc_id") @db.VarChar(20)
|
||||
|
||||
// Email Verification (Phase 1.5)
|
||||
emailVerified Boolean @default(false) @map("email_verified")
|
||||
verificationToken String? @unique @map("verification_token") @db.VarChar(255)
|
||||
verificationCode String? @map("verification_code") @db.VarChar(6)
|
||||
verificationTokenExpiry DateTime? @map("verification_token_expiry")
|
||||
|
||||
// Password Reset (Phase 1.5)
|
||||
resetToken String? @unique @map("reset_token") @db.VarChar(255)
|
||||
resetTokenExpiry DateTime? @map("reset_token_expiry")
|
||||
|
||||
avatar String? @db.VarChar(255)
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
|
||||
// Relations
|
||||
messages Message[]
|
||||
matchesAsUser1 Match[] @relation("MatchUser1")
|
||||
matchesAsUser2 Match[] @relation("MatchUser2")
|
||||
ratingsGiven Rating[] @relation("RaterRatings")
|
||||
ratingsReceived Rating[] @relation("RatedRatings")
|
||||
messages Message[]
|
||||
matchesAsUser1 Match[] @relation("MatchUser1")
|
||||
matchesAsUser2 Match[] @relation("MatchUser2")
|
||||
ratingsGiven Rating[] @relation("RaterRatings")
|
||||
ratingsReceived Rating[] @relation("RatedRatings")
|
||||
|
||||
@@map("users")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user