import { zValidator } from "@hono/zod-validator"; import HonoEnv from "../../types/HonoEnv"; import { z } from "zod"; import { and, eq, isNull } from "drizzle-orm"; import { Hono } from "hono"; import db from "../../drizzle"; import { users } from "../../drizzle/schema/users"; import { notFound, unauthorized } from "../../errors/DashboardError"; import { generateResetPasswordToken, verifyResetPasswordToken } from "../../utils/authUtils"; import { sendResetPasswordEmail } from "../../utils/mailerUtils"; import { hashPassword } from "../../utils/passwordUtils"; const forgotPasswordRoutes = new Hono() /** * Forgot Password * * Checking emails in the database, generating tokens, and sending emails occurs. */ .post( '/', zValidator( 'json', z.object({ email: z.string().email(), }) ), async (c) => { const { email } = c.req.valid('json'); const user = await db .select() .from(users) .where( and( isNull(users.deletedAt), eq(users.email, email) ) ); if (!user.length) throw notFound(); // Generate reset password token const resetPasswordToken = await generateResetPasswordToken({ uid: user[0].id, }); await db .update(users) .set({ resetPasswordToken: resetPasswordToken }) .where(eq(users.email, email)); // Send email with reset password token await sendResetPasswordEmail(email, resetPasswordToken); return c.json({ message: 'Email has been sent successfully', }); } ) /** * Reset Password */ .patch( '/verify', zValidator( 'json', z.object({ password: z.string(), confirm_password: z.string() }) ), async (c) => { const formData = c.req.valid('json'); const token = c.req.query('token') // Token validation if (!token) { return c.json({ message: 'Token is required' }, 400); } // Password validation if (formData.password !== formData.confirm_password) { return c.json({ message: 'Passwords do not match' }, 400); } const decoded = await verifyResetPasswordToken(token); if (!decoded) { return c.json({ message: 'Invalid or expired token' }, 401); } if (!decoded) throw unauthorized(); // Hash the password const hashedPassword = await hashPassword(formData.password); await db .update(users) .set({ password: hashedPassword, updatedAt: new Date(), }) .where(eq(users.id, decoded.uid)); return c.json({ message: 'Password has been reset successfully' }); }); export default forgotPasswordRoutes;