User Registration in Node JS
Tags: javascript, node
Published: 2023-03-12 19:43:21

### Prerequisites

- Basic understanding of Javascript, Node, Express and MongoDB.
- Knowledge of how to set up a server using Express and Node

## Getting started

Often times you need users to register on your app to access different resources.

In this post we will explore how to register users using Node,Express and MongoDB.

Create a directory `api`

```bash
mkdir api
cd api
```
Run `npm init`to initialize the project.

Install bycrypt,express,joi,mongodb and mongoose as dependencies using:
```bash
npm install bcrypt dotenv express joi mongodb mongoose
```
## Set up server and connect to database
Create a `.env` file and add the Port and Database URL variables.

```bash
DATABASE_URL = mongodb://127.0.0.1/users
PORT = 5000
```
Create `index .js` and update as follows. 
```javascript
require('dotenv').config()
const registerRouter = require('./routes/register')
const express = require('express')
const mongoose = require('mongoose')
const db = mongoose.connection
const PORT = process.env.PORT || 5010
const app = express()
app.use(express.json())

mongoose.connect(process.env.DATABASE_URL,
    {
        useNewUrlParser: true,
        useUnifiedTopology: true
    })
mongoose.set('strictQuery', true)

db.on('error', (error) => console.error(error))
db.once('open', () => console.log('Connected to Database'))
app.listen(PORT, () => console.log(`Server Started on port ${PORT}`))
```
The file contains boilerplate code used to set up a server and connect to the database.
You can find a detailed explanation on what each section does [here](https://www.section.io/engineering-education/build-mern-stack-application-to-manage-isp/).

## Create User Model
During registration, the user provides a name,email and password which will be saved on the database allowing them to sign in later.

We will create a schema to define how the data is stored in the database.

Inside the `api` directory,create a `models` folder and add `user.js` file in this folder.

```javascript
//models/user.js
const mongoose = require('mongoose')
const Joi = require('joi')

const userSchema = new mongoose.Schema({
    name: {
        type: String,
        required: true,
        min: 3,
        max: 100
    },
    email: {
        type: String,
        required: true,
        unique: true,
        min: 5,
        max: 255
    },
    password: {
        type: String,
        required: true,
        min: 8,
        max: 100

    }
})

function validateUser(user) {
    const schema = Joi.object({
        name: Joi.string().min(3).max(100).required(),
        email: Joi.string().min(5).max(255).required().email(),
        password: Joi.string().min(8).max(100).required()
    })
    return schema.validate(user)
}
const User = mongoose.model('User', userSchema)
module.exports.validate = validateUser
module.exports.User = User

```
In `user.js` we import mongoose for creating the User Schema which has the requirements for the name, email and password fields.

We use the [Joi package](https://www.npmjs.com/package/joi) to validate the user input to ensure it meets the requirements defined in the schema.

Since we will need the User model and the validateUser function elsewhere we have to export them make them accessible to other modules. 

## Create Registration Route

We need to create routes that define how the application's endpoints (URIs) respond to client requests. 
You can learn more about routing in express [here](https://expressjs.com/en/guide/routing.html).

Create `routes` folder inside the `api`directory and add `register.js` file in the routes folder.

The register endpoint will:

- Receive user details from client request
- Hash the password to ensure passwords are not stored in the database as plain text.
- Send the information to our database
- Return the registered user as a response object.

```javascript
//routes/register.js
const { User, validate } = require('../models/user')
const bcrypt = require('bcrypt')
const express = require('express')
const router = express.Router()


const registerRouter = router.post('/register', async (req, res) => {
    const { error } = validate(req.body);
    if (error) {
        return res.status(400).send(error.details[0].message);
    }
    let user = await User.findOne({ email: req.body.email })
    if (user) {
        return res.status(400).send('User already exisits. Please sign in')
    } else {
        try {
            const salt = await bcrypt.genSalt(10);
            const password = await bcrypt.hash(req.body.password, salt);
            const user = new User({
                name: req.body.name,
                email: req.body.email,
                password: password
            })
            await user.save()
            return res.status(201).json(user)
        } catch (err) {
            return res.status(400).json({ message: err.message })
        }
    }
})

module.exports = registerRouter
```

The user input is first validated based on the schema passed to Joi ensuring the user enters the expected input.
If the request contains invalid input, the user is prompted to make changes accordingly.

After ensuring that this user does not exist in the database,we use the bcrypt package to encrypt the password.

The user is saved on the database and a response containing user details.

> You can make modifications to the functionality of the register router such as redirecting the user to the sign in page.

We export the registerRouter which will be used in `index.js` as the callback function when the application receives requests that match the specified route(api/register) and method(post).

Explore more on middleware [here](https://expressjs.com/en/guide/using-middleware.html)

Add the followimg code to the `index.js` file.
``` javascript
const registerRouter = require('./routes/register')
app.use('/api', registerRouter)
```
Run the application using:
`node index.js`

![server output](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/20pi257uzar9zpsh4ent.jpg)

Here is an example of a post request to the api/register endpoint.

![Post request to register user](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ip0hkoblzogy88ydwign.jpg)

We have successfully registered a user and saved them in the database.
Find the full code [here](https://github.com/wanguiwaweru/Authenticate).
Happy coding!!!