0
votes

I've gone through this article https://ahrjarrett.com/posts/2019-02-08-resetting-user-passwords-with-node-and-jwt to see how to reset password in express.

mailer.js


const nodemailer = require("nodemailer")

export const transporter = nodemailer.createTransport({
    service: "gmail",
    auth: {
        user: process.env.EMAIL,
        pass: process.env.PASSWORD
    }
})

export const getPasswordResetURL = (user, token) => {
    `http://localhost:3000/password/reset/${user._id}/${token}`
}

export const resetPasswordTemplate = (user, url) => {
    const from = process.env.EMAIL
    const to = user.email
    const subject = "Password Reset"
    const html = `
        <p>Hey ${user.name || user.email},</p>
        <p>We heard that you forgot your password. Sorry about that!</p>
        <p>But don’t worry! You can use the following link to reset your password:</p>
        <a href=${url}>${url}</a>
        <p>If you don’t use this link within 1 hour, it will expire.</p>
    `
}

return { from, to, subject, html }
emailController.js


const jwt = require("jsonwebtoken")
const bcrypt = require("bcrypt")
const User = require("../models/User")
import { transporter, getPasswordResetURL, resetPasswordTemplate } from "../utils/mailer"

export const usePasswordHashToMakeToken = ({
    password: passwordHash,
    _id: userId,
    createdAt
  }) => {
    const secret = passwordHash + "-" + createdAt
    const token = jwt.sign({ userId }, secret, {
      expiresIn: 3600 // 1 hour
    })
    return token
  }

  export const sendPasswordResetEmail = async (req, res) => {
    const { email } = req.params
    let user
    try {
      user = await User.findOne({ email }).exec()
    } catch (err) {
      res.status(404).json("No user with that email")
    }
    const token = usePasswordHashToMakeToken(user)
    const url = getPasswordResetURL(user, token)
    const emailTemplate = resetPasswordTemplate(user, url)

    const sendEmail = () => {
      transporter.sendMail(emailTemplate, (err, info) => {
        if (err) {
          res.status(500).json("Error sending email")
        }
        console.log(`** Email sent **`, info.response)
      })
    }
    sendEmail()
  }

  export const receiveNewPassword = (req, res) => {
    const { userId, token } = req.params
    const { password } = req.body

    User.findOne({ _id: userId })

      .then(user => {
        const secret = user.password + "-" + user.createdAt
        const payload = jwt.decode(token, secret)
        if (payload.userId === user.id) {
          bcrypt.genSalt(10, function(err, salt) {
            if (err) return
            bcrypt.hash(password, salt, function(err, hash) {
              if (err) return
              User.findOneAndUpdate({ _id: userId }, { password: hash })
                .then(() => res.status(202).json("Password changed accepted"))
                .catch(err => res.status(500).json(err))
            })
          })
        }
      })

      .catch(() => {
        res.status(404).json("Invalid user")
      })
  }

users.js

const express = require('express');
const router = express.Router();
const userController = require("../controllers/userController")
const emailController = require("../controllers/emailController")

router.post("/register", userController.registerUser)
router.post("/login", userController.loginUser)
router.get("/:userId", userController.getUser)
router.post("/user/:email", emailController.sendPasswordResetEmail)
router.post("/receive_new_password/:userId/:token", emailController.receiveNewPassword)


module.exports = router;

It's giving me an error of unexpected token { in this line

import { transporter, getPasswordResetURL, resetPasswordTemplate } from "../utils/mailer"

Can I convert this export const into module.exports and require the above by:

const { transporter, getPasswordResetURL, resetPasswordTemplate } = require("../utils/mailer")

1
import { transporter, getPasswordResetURL, resetPasswordTemplate } from "../utils/mailer" this is es6 syntax. change it to es5Pratap Sharma
return { from, to, subject, html }. Why are we returning like this?metalHeadDev
Most probably example you've taken from he's using es6 and es5 syntax together(He must have configured babel). But in your case, I don't think you have configured babel. So I'll suggest you to either configure babel or change all the es6 syntax to es5. In es6 you can use es5 but in es5 you cannot use es6.Pratap Sharma
Alright, I have babel configured though.metalHeadDev
can you configure the same in codesandbox.io and then we'll work on it.Pratap Sharma

1 Answers

2
votes

As you mentioned in the question replace all export const and replace it to

module.exports = {transporter, getPasswordResetURL, resetPasswordTemplate}

Also replace the line

import { transporter, getPasswordResetURL, resetPasswordTemplate } from "../utils/mailer"

to

const { transporter, getPasswordResetURL, resetPasswordTemplate } = require("../utils/mailer")

As import, export is es6 syntax and require, module.exports is es5 syntax. If you want to use import then you need to configure Babel.

Suggestions

Most probably example you've taken from he's using es6 and es5 syntax together(He must have configured babel). But in your case, I don't think you have configured babel. So I'll suggest you to either configure babel or change all the es6 syntax to es5. In es6 you can use es5 but in es5 you cannot use es6