import mongoose from "mongoose" ; import crypto from "crypto" ; import { getUserByEmail } from "../services/users" ; import { APP_ORIGIN } from "../util/secrets" ; import { sendResetPasswordEmail } from "../services/email" ; export interface ForgotPasswordInterface { token : string ; userId : string ; createdAt : Date ; } const forgotPasswordSchema = new mongoose . Schema ( { token : { type : String , unique : true , } , userId : String , createdAt : { type : Date , expires : 30 * 60 , } , } ) ; export type ForgotPasswordDocument = mongoose . Document & ForgotPasswordInterface ; export const ForgotPasswordModel = mongoose . model < ForgotPasswordDocument > ( "ForgotPassword" , forgotPasswordSchema ) ; export async function createForgotPasswordToken ( email ) { const user = await getUserByEmail ( email ) ; if ( ! user ) { throw new Error ( "Could not find a user with that email address" ) ; } const token = crypto . randomBytes ( 32 ) . toString ( "hex" ) ; const doc = { userId : user . id , token , createdAt : new Date ( ) , } ; await ForgotPasswordModel . create ( doc ) ; const resetUrl = `${ APP_ORIGIN }/reset-password?token=${ token }` ; try { await sendResetPasswordEmail ( email , resetUrl ) ; } catch ( e ) { console . error ( "Failed to send reset password email. The reset password link for " + email + " is: " + resetUrl ) ; throw e ; } } export async function getUserIdFromForgotPasswordToken ( token ) { const doc = await ForgotPasswordModel . findOne ( { token , } ) ; return doc ?. userId || "" ; } export async function deleteForgotPasswordToken ( token ) { return ForgotPasswordModel . deleteOne ( { token , } ) ; }