All files / src/app/api/auth/verify-email route.ts

98.71% Statements 77/78
84.61% Branches 11/13
100% Functions 1/1
98.71% Lines 77/78

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 791x 1x 1x 1x 1x 1x 1x 1x 1x 1x 12x 12x 12x 12x 12x 12x 2x 2x 2x 2x 10x 10x 10x 10x 9x 12x 4x 4x 4x 4x 4x 5x 12x 1x 1x 1x 1x 1x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 3x 3x 3x 3x 3x 3x 3x 3x 12x   12x 12x 12x 12x 12x 12x 2x 2x 2x 2x 2x 2x 12x  
import { NextRequest, NextResponse } from "next/server";
import { prisma } from "@/lib/prisma";
import { logger } from "@/lib/logging";
import { emailService } from "@/lib/email/emailService";
 
/**
 * GET /api/auth/verify-email?token=xxx
 * Verifies user email address
 */
export async function GET(request: NextRequest) {
  try {
    const { searchParams } = new URL(request.url);
    const token = searchParams.get("token");
    const baseUrl = process.env.NEXTAUTH_URL || "http://localhost:3000";
 
    if (!token) {
      return NextResponse.redirect(
        `${baseUrl}/verify-email?error=missing-token`
      );
    }
 
    // Find user with this verification token
    const user = await prisma.user.findUnique({
      where: { verificationToken: token }});
 
    if (!user) {
      logger.warn("Invalid email verification token used", { category: "API" });
      return NextResponse.redirect(
        `${baseUrl}/verify-email?error=invalid-token`
      );
    }
 
    if (user.emailVerified) {
      // Already verified
      return NextResponse.redirect(
        `${baseUrl}/signin?verified=already`
      );
    }
 
    // Mark email as verified and create default email preferences
    await prisma.$transaction([
      prisma.user.update({
        where: { id: user.id },
        data: {
          emailVerified: new Date(),
          verificationToken: null
        }
      }),
      // Create default email preferences for new user
      prisma.emailPreference.upsert({
        where: { userId: user.id },
        create: { userId: user.id },
        update: {}
      })
    ]);
 
    logger.info(`Email verified for user ${user.id}`, { category: "API" });
 
    // Send welcome email (async, don't wait)
    emailService.sendWelcome({
      id: user.id,
      email: user.email,
      name: user.name || 'there'
    }).catch((err) => {
      logger.error("Failed to queue welcome email", err instanceof Error ? err : new Error(String(err)), { category: "API" });
    });
 
    return NextResponse.redirect(
      `${baseUrl}/signin?verified=true`
    );
  } catch (error) {
    logger.error("Email verification error", error instanceof Error ? error : new Error(String(error)), { category: "API" });
    const baseUrl = process.env.NEXTAUTH_URL || "http://localhost:3000";
    return NextResponse.redirect(
      `${baseUrl}/verify-email?error=server-error`
    );
  }
}