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 Login, NodeJS 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();
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
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 file
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='https://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
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
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.
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.
User needs to agree with terms 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"});
If you open mongo interactive shell. Type the command
db.users.find().pretty()
You can view the data saved into the database.
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.
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:
- Nodejs MongoDB CRUD tutorial
- NodeJS PassportJS Login
- Socketio with nodejs
- NodeJs MongoDB Tutorial
- NodeJS MongoDB RESTful API
- NodeJS send email tutorial
Previous Article: