Build an E-Commerce Website with MERN Stack - Part 3 (Authentication and Items)
Tags: react, node, javascript, webdev
Published: 2021-01-28 15:08:34

Hello friends! So, this is the third part of the MERN Stack series we have recently started. In the first part, we all learnt how to set up the project and had explanations about various things we are going to use in the project and we developed all our models for the project in the second part with the help of Mongoose and MongoDB.

> **Notice**: I will publish the complete detailed version of all the articles on the Medium website. Here I will give an overview and give the codes for the various pages part by part. It would be a 6-7 part series.
So, [please click here to go to Medium and read it in completion](https://shubhamstudent5.medium.com/lets-build-a-mern-stack-e-commerce-web-app-d619f3374d73?sk=1b22611944c6ff1e6360fecfbcb74e1a). *(These are friend links so do not worry about paywall)*

Now, in the third part, we will build the backend part which would handle the authentication and items in our web application by building out the APIs with the help of Express Router and we will also be defining a custom middleware function to check whether a user is authenticated or not.


To keep things clean and simple, we would create a new folder named routes in our root folder. This folder would contain all the routes we need for this project.

We will also create a folder named controllers in which we would put all the function we would be calling once we hit an API endpoint. So, we would separate the function in a different folder and import them in routes folder to use them.

Inside the routes folder, we would create four files — auth, item, cart and order. These four files would contain the routes relevant to the authentication, items, cart and orders respectively.

Similarly, we would create four files inside the controllers' folder, one each for each file of routes folder. Those would be — authControllers, itemControllers, cartControllers and orderControllers respectively.

So, we would now start building our Routes folder which would be simple since we will put all the logic in the controllers' folder and not directly in the routes folder.

###Routes
####Auth Routes
```js
const { Router } = require('express');
const authController = require('../controllers/authControllers');
const router = Router();
const auth = require('../middleware/auth');

router.post('/register', authController.signup);
router.post('/login', authController.login);
router.get('/user', auth, authController.get_user);

module.exports = router;
```

####Item Routes
```js
const { Router } = require('express');
const itemController = require('../controllers/itemControllers');
const router = Router();

router.get('/items', itemController.get_items);
router.post('/items',itemController.post_item);
router.put('/items/:id',itemController.update_item);
router.delete('/items/:id',itemController.delete_item);

module.exports = router;
```

###Controllers
####Auth Controller
```js
const User = require('../models/User');
const jwt = require('jsonwebtoken');
const config = require('config');
const bcrypt = require('bcrypt');

module.exports.signup = (req,res) => {
    const { name, email, password } = req.body;

    if(!name || !email || !password){
        res.status(400).json({msg: 'Please enter all fields'});
    }

    User.findOne({email})
    .then(user => {
        if(user) return res.status(400).json({msg: 'User already exists'});

        const newUser = new User({ name, email, password });

        // Create salt and hash
        bcrypt.genSalt(10, (err, salt) => {
            bcrypt.hash(password, salt, (err, hash) => {
                if(err) throw err;
                newUser.password = hash;
                newUser.save()
                    .then(user => {
                        jwt.sign(
                            { id: user._id },
                            config.get('jwtsecret'),
                            { expiresIn: 3600 },
                            (err, token) => {
                                if(err) throw err;
                                res.json({
                                    token,
                                    user: {
                                        id: user._id,
                                        name: user.name,
                                        email: user.email
                                    }
                                });
                            }
                        )
                    });
            })
        })
    })
}

module.exports.login = async (req,res) => {
    const { email, password } = req.body;
    if(!email || !password){
        res.status(400).json({msg: 'Please enter all fields'});
    }
    User.findOne({email})
        .then(user => {
            if(!user) return res.status(400).json({msg: 'User does not exist'});

            // Validate password
            bcrypt.compare(password, user.password)
                .then(isMatch => {
                    if(!isMatch) return res.status(400).json({ msg: 'Invalid credentials'});

                    jwt.sign(
                        { id: user._id },
                        config.get('jwtsecret'),
                        { expiresIn: 3600 },
                        (err, token) => {
                            if(err) throw err;
                            res.json({
                                token,
                                user: {
                                    id: user._id,
                                    name: user.name,
                                    email: user.email
                                }
                            });
                        }
                    )
                })
        })
}

module.exports.get_user = (req,res) => {
    User.findById(req.user.id)
        .select('-password')
        .then(user => res.json(user));
}
```

####Item Controller
```js
const Item = require('../models/Item');

module.exports.get_items = (req,res) => {
    Item.find().sort({date:-1}).then(items => res.json(items));
}

module.exports.post_item = (req,res) => {
    const newItem = new Item(req.body);
    newItem.save().then(item => res.json(item));
}

module.exports.update_item = (req,res) => {
    Item.findByIdAndUpdate({_id: req.params.id},req.body).then(function(item){
        Item.findOne({_id: req.params.id}).then(function(item){
            res.json(item);
        });
    });
}

module.exports.delete_item = (req,res) => {
    Item.findByIdAndDelete({_id: req.params.id}).then(function(item){
        res.json({success: true});
    });
}
```

###Auth Middleware function
```js
const config = require('config');
const jwt = require('jsonwebtoken');

function auth(req, res, next) {
    const token = req.header('x-auth-token');

    // Check for token
    if(!token){
        return res.status(401).json({ msg: 'No token, authorization denied'});
    }
    
    try{
        // Verify token
        const decoded = jwt.verify(token, config.get('jwtsecret'));
        //Add user from payload
        req.user = decoded;
    next();
    } catch(e){
        res.status(400).json({ msg:'Token is not valid'});
    }
}

module.exports = auth;
```

So, that was all about the middleware function. We have now covered everything we wanted to cover in the third part. In the fourth part, we will deal with the routes and controllers of Cart and the Order. We will handle the payments using Stripe Checkout in the next part of the series.

Thank you, everyone, for reading this. Hope you gained some real knowledge and learnt something new today.

To read the complete tutorial, please [move to Medium and read the complete article](https://shubhamstudent5.medium.com/lets-build-a-mern-stack-e-commerce-web-app-d619f3374d73?sk=1b22611944c6ff1e6360fecfbcb74e1a).