'use server'; import { signIn } from '@/auth'; import { AuthError } from 'next-auth'; import bcrypt from 'bcryptjs'; import prisma from '@/lib/prisma'; export async function authenticate( prevState: string | undefined, formData: FormData, ) { const emailRaw = formData.get('email'); const passwordRaw = formData.get('password'); const email = typeof emailRaw === 'string' ? emailRaw.toLowerCase().trim() : ''; const password = typeof passwordRaw === 'string' ? passwordRaw : ''; // Surface a clear message when credentials are valid but email is unverified. if (email && password.length >= 6) { try { const user = await prisma.user.findUnique({ where: { email } }); if (user?.password) { const match = await bcrypt.compare(password, user.password); if (match && !user.emailVerified) { return 'EMAIL_NOT_VERIFIED'; } } } catch (preCheckErr) { console.error('[authenticate] emailVerified pre-check failed:', preCheckErr); } } try { await signIn('credentials', { email, password, redirectTo: '/home', }); } catch (error) { if (error instanceof AuthError) { console.error('AuthError details:', error.type, error.message); if ( error.type === 'CredentialsSignin' && (error.message?.includes('EMAIL_NOT_VERIFIED') || (error.cause as { err?: Error } | undefined)?.err?.message === 'EMAIL_NOT_VERIFIED') ) { return 'EMAIL_NOT_VERIFIED'; } switch (error.type) { case 'CredentialsSignin': return 'Invalid credentials.'; default: return `Auth error: ${error.type}`; } } // IMPORTANT: Next.js redirects throw a special error that must be rethrown throw error; } }