Reputation: 98
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
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