Mario Chacon
Mario Chacon

Reputation: 98

Middleware authentification with a condition not working Express. Node.js

I am currently developing a website with an API that I built with node.js, express and MongoDb for the database.

I am curretly learning node and express and cant find my way to create a middleware to verify that the USER ID matches the POSTED BY ID from a COMMENT. That way the USER can only delete his own comments.

My middleware looks like this

verifyUserIdPostedBy.js

const Comment = require('../models/Comment');

var userId
var postedById
module.exports = { 
    verfyUserIdPostedBy: function (req, res, next) {
        userId = req.header('userId')
        postedById = Comment.findOne({ _id: req.params.commentId}).populate('postedBy') .exec( function (error, body) {
            if (error) throw new Error(error);
            req.postedById = body.postedBy._id // assign the ID to the req object
            console.log(req.postedById);
        });      
        console.log(userId);
        if(userId !== req.postedById)
        return  res.status(500).json({message: 'Stopped'})
        return next();
  },
} 

My console.log() in the middleware show me exactly the 2 values that I want to compare but I get the error 'Stopped' and my verification never happens. I tried accesing the route with the comment owner and also with not the comment owner and none works

and my route looks like this comments.js

const express = require('express');
const router = express.Router();
const Comment = require('../models/Comment');
const verify = require('./verifyToken');
const {verfyUserIdPostedBy} = require('./verfyUserIdPostedBy')



// DELETE COMMENT
router.delete('/:commentId', verify, verfyUserIdPostedBy, async (req, res) => {
    try {
        const removedComment = await Comment.deleteOne({ _id: req.params.commentId });
        res.json(removedComment);
    } catch(err){
        res.json({message:err});
    }
})

Like I said I am new at this but cant find a way to do it properly.

Appretiate in advance any help and advice.

Mario

Upvotes: 1

Views: 65

Answers (1)

Đăng Khoa Đinh
Đăng Khoa Đinh

Reputation: 5411

I add comments in your code to explain how it works :

 verfyUserIdPostedBy: function (req, res, next) {
        userId = req.header('userId')
        postedById = Comment.findOne({ _id: req.params.commentId}).populate('postedBy') .exec( function (error, body) { 

            /* -----this is a callback function------ */
            /* the code inside the callback function is executed only when findOne finish and **after** the code outside */
            if (error) throw new Error(error);
            req.postedById = body.postedBy._id // assign the ID to the req object
            console.log(req.postedById);
        });      

        /* this code is executed before the code inside the callback function */
        console.log(req.postedById); // undefined, you can check
        console.log(userId);
        if(userId !== req.postedById) // this is always true 
           return  res.status(500).json({message: 'Stopped'}) // and this line always executes
        return next(); // and this line never execute
  },

The concept is callback. I strongly advise you to research this keyword, callback is used massively in NodeJS. Nowadays, there are Promise and async/await that allow developers to write asynchronous code in a "synchronous way", but callback is the base.

In order for your code works, 1 simple solution (there are many solutions!) is put comparison code into the callback block, something like :

const Comment = require('../models/Comment');

var userId
var postedById
module.exports = { 
    verfyUserIdPostedBy: function (req, res, next) {
        userId = req.header('userId')
        postedById = Comment.findOne({ _id: req.params.commentId}).populate('postedBy') .exec( function (error, body) {
            if (error) throw new Error(error);
            req.postedById = body.postedBy._id // assign the ID to the req object
            console.log(req.postedById);
            console.log(userId);
            if(userId !== req.postedById)
               return  res.status(500).json({message: 'Stopped'})
            return next();
        });      
       
  },
} 
 

Upvotes: 1

Related Questions