nodejs user registration tutorial with mongodb

nodejs user registration tutorial

Many of our readers requested to publish a NodeJs user registration tutorial with MongoDB. In some previous NodeJs tutorials, we explored NodeJS PassportJS LoginNodeJS send email tutorial and many others. In this tutorial, you are going to learn nodejs user registration with MongoDB. You can find the source code of this tutorial on this GitHub repository. Following tasks are performed in this tutorial.

 

1. Create a MongoDB database for users

2. Generate a NodeJs, ExpressJS application skeleton

3. Create form for user registration using bootstrap

4. Create an ExpressJS route to register user

5. Validate user input using express-validate plugin

6. Save user information in MongoDB database using mongoose

 

Create a MongoDB database for users

To create a database in MongoDB, first, you need to install MongoDB on your system.

Installing MongoDB

You can install MongoDB community edition on Windows, Mac or Linux. Please go to MongoDB downloads.  After downloading, install MongoDB on your system.

How to run MongoDB

If you are running MongoDB first time, create data directory because the mongod process needs to write to the data directory. If you are using Windows create a directory data in C drive. Then create a directory db inside it or on command line create a directory using command mkdir -p /data/db.

On command line open mongdb directory. Then go into bin directory. If system path variable is set, type mongod or  ./mongod otherwise type

mongod –dbpath /path/to/data/directory.

Access interactive mongo shell

Open a second command prompt window to access interactive mongo shell. After setting system path, type mongo or ./bin/mongo. By default, MongoDB connects to localhost on port 27017.

Display All databases.

To show all the databases, type command

show dbs

Create MongoDB database

To create dbusers database,

> use dbusers

The current database is switched to dbusers database.

To view data in users collection.

db.users.find.pretty();

nodejs user registration - mongo db records

Generate a NodeJS user registration app skeleton

To create a nodejs application first install nodejs on your system.

Installing NodeJS

To download and install NodeJS visit nodejs download page. Download and run the installer. After installation completes, open command prompt and type

node -v. The currently installed version of NodeJS is displayed. NodeJS installation also installs NPM or Node Package Manager

Install Express Generator

Now using NPM,  install the express generator. This module is used to create a NodeJS, Express JS app.

npm install express-generator -g

Generate Nodejs User registration application

After installation, open the directory where you want to create the application. Like on windows type cd c:\ and then type the following command.

express --view=pug nodejs-user-registration-mongodb

nodejs user registration - express app skeleton

A NodeJS, Express application is generated. Next to install required packages and dependencies.

> cd nodejs-user-registration-mongodb && npm install

To View running application

To run this application, type command below.

> SET DEBUG=nodejs-user-registration-mongodb:* & npm start

Add model for Users using Mongoose

To model MongoDB collections, mongoose is used. Install mongoose package using npm.

npm i mongoose --save

After installation of mongoose, open the project in your favorite IDE such as Atom or Sublime text. Create a new folder and name it as Models. Add a file User.js in this folder. Add the code below to this filenodejs user registration - mongodb editor

var mongoose = require('mongoose');

var Schema = mongoose.Schema;

var validateEmail = function(email) {

    var re = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/;

    return re.test(email)

};

var userSchema = new Schema({

  full_name: { type: String,  required: [true, 'Full name must be provided'] },

  email:    { 
    
    type: String,     

    Required:  'Email address cannot be left blank.',
    
    validate: [validateEmail, 'Please fill a valid email address'],
         match: [/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/, 'Please fill a valid email address'],
    index: {unique: true, dropDups: true}
    
    },

  password: { type: String , required: [true,  'Password cannot be left blank']},

  dob: { type: Date , required: [true, 'Date of birth must be provided']},

  country: { type: String , required: [true, 'Country cannot be left blank.']},

  gender: { type: String , required: [true, 'Gender must be provided']},

  calorie: { type: String },

  salt: { type: String },


});

module.exports = mongoose.model('Users', userSchema);

Mongoose is included using require. A schema is created using mongoose.schma. Next, there is an email validation utility method. After this method, UserSchma is created.

Inside user schema fields like full_name, email. password, date of birth, country, gender, food preference like calorie and salt are added as string data types with validations and messages. In the last, userSchema is exported using modules.export so other modules can use it.

Update layout.js file in views

Before coding part let us first create HTML form to take user data. Open Views folder, open layout.pug file, replace existing code with the code below.

doctype html

html

  head

    title= title

    link(rel='stylesheet', href='/stylesheets/style.css')

    link(rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css")

  body

    block content

    script(src='http://code.jquery.com/jquery-3.3.1.min.js')

    script(src='/javascripts/app.js')

In this code above bootstrap file is included so we can create an HTML form using bootstrap.

Create a form for nodejs user registration

Open index.pug file in views folder. Replace the code below block content.

.container
      
      h2.text-center.top-buffer NodeJS User Registration Tutorial
      form.form-horizontal(role="form", method="post")
        .form-group
          .alert.alert-danger(role='alert', id="msgDiv")

        .form-group
          label.col-sm-3.control-label(for="fullname") 
           strong Full Name
          .col-sm-9
            input#fullname.form-control(type="text" placeholder="Full Name" autofocus="" value="")
        .form-group
          label.col-sm-3.control-label(for="email") 
           strong Email
          .col-sm-9
            input#email.form-control(type="email" placeholder="Email")
        .form-group
          label.col-sm-3.control-label(for="password") 
           strong Password
          .col-sm-9
            input#password.form-control(type="password" placeholder="Password")
        .form-group
          label.col-sm-3.control-label(for="cpassword") 
           strong Confirm Password
          .col-sm-9
            input#cpassword.form-control(type="password" placeholder="Confirm password")
        .form-group
          label.col-sm-9.control-label(for="dob") 
           strong Date of Birth
          .col-sm-9
            input#dob.form-control(type="date")
        .form-group
          label.col-sm-3.control-label(for="country") 
           strong Country
          .col-sm-9
            select#country.form-control
              option(value='') Please Select
              option USA
              option United Kingdom	
              option Germany
              option Denmark
              option Ecuador
              option Canada
              option France
              option Others
        .form-group
          label.control-label.col-sm-3 
           strong Gender
          .col-sm-6
            .row
              .col-sm-6
                label.radio-inline
                  input#femaleRadio(name="gender" type="radio" value="Female")
                  |  Female
              .col-sm-4
                label.radio-inline
                  input#maleRadio(name="gender" type="radio" value="Male")
                  |  Male              
        .form-group
          label.control-label.col-sm-9 
           strong Meal Preference
          .col-sm-9
            .checkbox
              label
                input#calorieCheckbox(type="checkbox" value="Calorie" name="calorie")
                |  Low calorie
            .checkbox
              label
                input#saltCheckbox(type="checkbox" value="Salt"  name="salt")
                |  Low salt
        .form-group
          .col-sm-9.col-sm-offset-3
            .checkbox
              label
                input#terms(type="checkbox" value="yes" name="terms")
                |  I accept 
                a(href="#") terms
        .form-group
          .col-sm-9.col-sm-offset-3
            button#register.btn.btn-primary.btn-block(type="e") Register

Above code will create a form as shown below in mage. CSS styles are included in source

nodejs user registration - user form

After the user fills in the form and clicks Register button, data is sent to the server.

Nodejs user registration – client side AJAX code

Open javascripts folder inside public folder and add a file app.js.

$(function(){

    $("#register").on('click', function(event){
        event.preventDefault();

        var fullname   = $("#fullname").val();
        var email      = $("#email").val();
        var password   = $("#password").val();
        var cpassword  = $("#cpassword").val();
        var dob        = $("#dob").val();
        var country    = $("#country").val();
        var gender     = $('input[name="gender"]:checked').val(); 
        var calorie    = $('input[name="calorie"]:checked').val(); 
        var salt       = $('input[name="salt"]:checked').val();
        var terms      = $('input[name="terms"]:checked').val();

        if(!fullname || !email || !password || !cpassword || !dob || !country || !gender){ 

            $("#msgDiv").show().html("All fields are required.");

        } else if(cpassword != password){

            $("#msgDiv").show().html("Passowrds should match.");

        } else if (!terms){

            $("#msgDiv").show().html("Please agree to terms and conditions.");
        }
        else{ 

            $.ajax({
                url: "/register",
                method: "POST",

                data: { full_name: fullname, email: email, password: password, cpassword: cpassword, dob: dob, country: country, gender: gender, calorie:calorie ,salt: salt, terms: terms }

            }).done(function( data ) {

                if ( data ) {
                    if(data.status == 'error'){

                        var errors = '<ul>';
                        $.each( data.message, function( key, value ) {
                            errors = errors +'<li>'+value.msg+'</li>';
                        });

                        errors = errors+ '</ul>';
                        $("#msgDiv").html(errors).show();
                    }else{
                        $("#msgDiv").removeClass('alert-danger').addClass('alert-success').html(data.message).show(); 
                    }
                }
            });
        }
    });
});

First, inside jQuery ready method a click event handler method of register button is created. Name, email, password, country, gender, calories, and salt values are assigned to variables. A checkbox for accepting terms and conditions is also added and its value is assigned to a variable.

Client-side validation of values

Validation is performed on user entered data. User needs to accept terms and conditions. If user enters all values correctly. An Ajax request with data is posted to the server.  In .done method, the response is sent back from the server to the client. On successful insertion of data, a message is displayed otherwise errors are displayed

nodejs user registration - client validation

Express route  for nodejs user registration

Open index.js file in routes folder. To validate data, express-validate module is installed. Open command line and run the command.

npm install express-validator --save

Open index.js file and add the code. First mongoose is included and after that users, model is included.

var mongoose  = require('mongoose');

var User      = mongoose.model('Users');

var crypto    = require('crypto'), hmac, signature;

const { check, validationResult } = require('express-validator/check');

const { matchedData, sanitize }   = require('express-validator/filter');

To validate data entered data, express-validator is included. Add the code below, after ‘/’ route.

 /* POST user registration page. */
  router.post('/register',[ 
   
    check('full_name','Name cannot be left blank')
    .isLength({ min: 1 }),
   
    check('email')
    .isEmail().withMessage('Please enter a valid email address')
    .trim()
    .normalizeEmail()
    .custom(value => {
        return findUserByEmail(value).then(User => {
          //if user email already exists throw an error
      })
    }),

    check('password')
    .isLength({ min: 5 }).withMessage('Password must be at least 5 chars long')
    .matches(/\d/).withMessage('Password must contain one number')
    .custom((value,{req, loc, path}) => {
      if (value !== req.body.cpassword) {
          // throw error if passwords do not match
          throw new Error("Passwords don't match");
      } else {
          return value;
      }
  }),

  check('gender','Please select gender')
    .isLength({ min: 1 }),

    check('dob','Date of birth cannot be left blank')
    .isLength({ min: 1 }),
    
    check('country','Country cannot be left blank')
    .isLength({ min: 1 }),
    
    check('terms','Please accept our terms and conditions').equals('yes'),

   ], function(req, res, next) {

      const errors = validationResult(req);

    if (!errors.isEmpty()) {     
        
       res.json({status : "error", message : errors.array()});

    } else {

        hmac = crypto.createHmac("sha1", 'auth secret');
        var encpassword = '';

        if(req.body.password){
          hmac.update(req.body.password);
          encpassword = hmac.digest("hex");
        }
        var document = {
            full_name:   req.body.full_name, 
            email:       req.body.email, 
            password:    encpassword, 
            dob:         req.body.dob, 
            country:     req.body.country, 
            gender:      req.body.gender, 
            calorie:     req.body.calorie, 
            salt:        req.body.salt 
          };
        
        var user = new User(document); 
        user.save(function(error){
          console.log(user);
          if(error){ 
            throw error;
          }
          res.json({message : "Data saved successfully.", status : "success"});
       });    
    }
});

function findUserByEmail(email){

  if(email){
      return new Promise((resolve, reject) => {
        User.findOne({ email: email })
          .exec((err, doc) => {
            if (err) return reject(err)
            if (doc) return reject(new Error('This email already exists. Please enter another email.'))
            else return resolve(email)
          })
      })
    }
 }


module.exports = router;

Register route validation rules

Inside router.post(‘/register’,…)  route, an array is added with validation rules that are explained as below.

Validate full name

To validate full name  code added below

check('full_name','Name cannot be left blank')
   .isLength({ min: 1 }),

Validation code is added to check full name field value. Check method contains name and message. isLength method checks if the value is entered for full name field.

Email validation with custom validator

To validate email inside .isEmail method is used. Custom method contains a call to a promise method that receives user email as parameter.

check('email')
    .isEmail().withMessage('Please enter a valid email address')
    .trim()
    .normalizeEmail()
    .custom(value => {
        return findUserByEmail(value).then(User => {
          //if user email already exists throw an error
      })
    }),

Check if email already exists in database

When a user registers, we need to make sure that user email does not exist in database. Custom rule calls findUserbyEmail method. If email already exists in the database a message is displayed to user.

nodejs user registration - email already exists

Email validation using custom validate method

Email validation call back method is added using promises. In promise construct resolve and reject callbacks are passed.  In case of error, an error is thrown in reject, if email exists in database a message is sent back to calling method. If email does not exist resolve method is called.

function findUserByEmail(email){

  if(email){
      return new Promise((resolve, reject) => {
        User.findOne({ email: email })
          .exec((err, doc) => {
            if (err) return reject(err)
            if (doc) return reject(new Error('This email already exists. Please enter another email.'))
            else return resolve(email)
          })
      })
    }
 }


module.exports = router;

Password validation

The password is validated in last with .isLength method. In .matches method validates that there must be one integer in password. Password field is compared with confirm password field.

check('password')

    .isLength({ min: 5 }).withMessage('Password must be at least 5 chars long')

    .matches(/\d/).withMessage('Password must contain one number')

    .custom((value,{req, loc, path}) => {

      if (value !== req.body.cpassword) {
          // throw error if passwords do not match
          throw new Error("Passwords don't match");
      } else {
          return value;
      }

  }),

After password, other fields are validated.

nodejs user registration - server side validationUser needs to agree with terms and conditions

nodejs user registration - term and conditions

Callback method to save user data

After validation, a callback method is added

function(req, res, next) {

      const errors = validationResult(req);

    if (!errors.isEmpty()) {     
        
       res.json({status : "error", message : errors.array()});
.....

In callback method request, response and next parameters are passed. validateResult method is called and request object is passed to it. If there are validation errors then errors array is sent back to the user. If there are no errors in Else block, the password is encrypted using crypto module. Password is encrypted using sha1 and is assigned to encpassword variable.

hmac = crypto.createHmac("sha1", 'auth secret');
        var encpassword = '';

        if(req.body.password){
          hmac.update(req.body.password);
          encpassword = hmac.digest("hex");
        }

Create a JSON document and save to database

A JSON document is created and passed to Mongoose User Model. User data is saved to the database.  In case of error, an error is thrown otherwise a success message is shown to the user.

var document = {
           full_name:   req.body.full_name, 
           email:       req.body.email, 
           password:    encpassword, 
           dob:         req.body.dob, 
           country:     req.body.country, 
           gender:      req.body.gender, 
           calorie:     req.body.calorie, 
           salt:        req.body.salt 
         };
       
       var user = new User(document); 
       user.save(function(error){
         console.log(user);
         if(error){ 
           throw error;
         }
         res.json({message : "Data saved successfully.", status : "success"});

nodejs user registration - form filled

nodejs user registration - success

If you open mongo interactive shell. Type the command

db.users.find().pretty()

You can view the data saved into the database.

nodejs user registration - new record mongodb

Running the nodejs user registration application

After you have completed the code. It is time to run the application.

Open command line, go to the project folder and type,

SET DEBUG=nodejs-user-registration-mongodb:* & npm start

Now open the browser and type the address below and you can see the running project.

http://localhost:3000

Summary

To summarize, in the tutorial above you have learned to create a nodejs user registration. A NodeJS, ExpressJS application is generated, required modules are installed. A form is created. After the user enters data into the form and clicks the register button. Data is validated and saved to the database.

Source code download

You can find the source code of the tutorial on GitHub. When you visit this the link, there is a button on right-hand side, it says, “Clone or download“. You can download the complete source code as a zip file or clone it using Git clone command.nodejs user registration - user registration

Thanks for reading tutorial, Please leave your valuable feedback.  Please follow us on twitter, like our Facebook page or subscribe to our newsletter to stay updated on tutorials.

 

Related Articles:

 

Previous Article:

 

Next Article: