Building Whinst Part 24: Adding email and password editing functionality

An important feature in any application that has user accounts is the ability for users to change their emails and passwords. In this article, I'll walk you through how I setup this essential functionality in the Whinst web app.

Email editing📧

To set up email editing functionality, I first setup a form using Formik where the user types in their new email. For the new email to be saved into the database, the user has to first verify it via an email sent to them. I did this by generating and sending a random code to the backend together with the new email. On the backend this random code is saved in the user model then an email with a link that contains the new email and random code is sent to the users email using the Nodemailer package. When the user clicks on the link sent to their email, it goes to a verification page with a verify button that when clicked saves the new email. The code below shows how the backend part of this process is done

const sendMail =async(email,random_code)=>{
  var transporter = nodemailer.createTransport({
      service: "random service",
      auth: {
          user: 'randomemail@email',
          pass: 'a password',
      },
    });

    var mailOptions = {
      from: 'randomemail@email',
      to: email,
      subject: 'NEW EMAIL CONFIRMATION',
      text: `http://a-random-link/confirm-email/${email}/${random_code}`,
    };

    transporter.sendMail(mailOptions, function (error, info) {
      if (error) {
        throw new Error(error);
      } else {
        console.log("Email Sent");
        return true;
      }
    });

}

app.put("/change-email",async(req,res)=>{
  try{
       const {new_email,random_code,model_id} = req.body;
       await pool.query("UPDATE database_model SET random_code = $1 WHERE model_id = $2",
       [random_code,model_id]
       );
       sendMail(new_email,random_code)
  }
  catch(err){
      console.log(err)
  }
})

Password editing🔐

To set up password editing functionality, I first setup a form using Formik with a current password, new password and confirm new password field. When the user enters the required input in these fields, Formik via a validation schema checks to see if the input in the new password and confirm new password fields match. If the passwords match they are then sent to the backend. On the backend the current password entered is checked to see if it matches the password that is saved in the database. If it is a match, the new password is then hashed using the Bcrypt library and is saved to the database. The code below shows how this is done.

app.put("/change-password",async(req,res)=>{
  try{
    const {old_password,new_password,model_id} = req.body;
   result = await pool.query("SELECT * FROM database_model WHERE model_id = $1",[model_id])
    const doesPasswordMatch = await bcrypt.compare(old_password,result.rows[0].password)
    if(doesPasswordMatch){
      const hashPassword = await bcrypt.hash(new_password,11)
      await pool.query("UPDATE database_model SET password = $1 WHERE model_id = $2",
      [hashPassword,model_id]
      );
      res.json('success')
    }else{
      res.json('password does not match')
    }
  }catch(err){
    console.log(err)
  }
})

With this crucial functionality completed I've moved a major step closer to completing the Whinst web app. Thank you for reading🙏.