feat: password reset flow and email verification

- Add forgot-password and reset-password pages and API routes
- Add email verification with token generation on registration
- Add resend-verification endpoint with 60s rate limit
- Add shared email utility (nodemailer, Migadu SMTP)
- Add VerificationBanner in dashboard layout
- Add PasswordResetToken and EmailVerificationToken models
- Add emailVerified field to User model
- Extend NextAuth session with isEmailVerified
- Add forgot-password link to login page
- Wire EMAIL_PASSWORD env var in docker-compose
This commit is contained in:
Vectry
2026-02-10 16:47:06 +00:00
parent 0e4ffce4fa
commit 539d35b649
16 changed files with 1026 additions and 6 deletions

View File

@@ -12,6 +12,7 @@ declare module "next-auth" {
email: string;
name?: string | null;
image?: string | null;
isEmailVerified: boolean;
};
}
}
@@ -19,6 +20,7 @@ declare module "next-auth" {
declare module "@auth/core/jwt" {
interface JWT {
id: string;
isEmailVerified: boolean;
}
}
@@ -58,14 +60,24 @@ export const { handlers, auth, signIn, signOut } = NextAuth({
}),
],
callbacks: {
jwt({ token, user }) {
async jwt({ token, user, trigger }) {
if (user) {
token.id = user.id as string;
}
if (trigger === "update" || user) {
const dbUser = await prisma.user.findUnique({
where: { id: token.id },
select: { emailVerified: true },
});
if (dbUser) {
token.isEmailVerified = dbUser.emailVerified;
}
}
return token;
},
session({ session, token }) {
session.user.id = token.id;
session.user.isEmailVerified = token.isEmailVerified;
return session;
},
},