Thinkster node.js tutorial - node.js

Question about the profile route, why do we have 2 methods that presumably do the same thing: User.findOne and User.findById? Also what is the order of execution for the router.param and router.get?
router.param('username', function(req, res, next, username){
User.findOne({username: username}).then(function(user){
if(!user) { return res.sendStatus(404); }
req.profile = user;
return next();
}).catch(next);
});
router.get('/:username', auth.optional, function(req, res, next){
if(req.payload){
User.findById(req.payload.id).then(function(user){
if(!user) { return res.json({profile: req.profile.toProfileJSONFor(false)}); }
return res.json({profile: req.profile.toProfileJSONFor(user)});
});
} else {
return res.json({profile: req.profile.toProfileJSONFor(false)});
}
});

Very simply put:
FindOne queries the database to match against custom identifiers whereas findById queries the database to match a unique identifier.
Also in Express, the routes you define are matched sequentially in the order that they are defined.

Related

Difference between the 2 passport.authenticate methods

It is the same login route.
Just 2 different approaches.
First route
router.post('/login', passport.authenticate('local',{session:false}),async (req,res) => {
console.log("\n\n\n ------------------------222222")
console.log(req.user);
});
and the request object has the user & is displayed.
Whereas in the second route
router.post('/login', (req, res, next) => {
passport.authenticate('local', async (err, user, info) =>{
if(err){
console.log(err);
}
console.log("\n\n\n ------------------------")
console.log(req.user); //undefined
if(user){
// it works here
}
else{
res.status(422).json(info);
}
})(req, res, next);
});
console.log(req.user); shows undefined.
but the user has the user details fetched from the mongo db.
Can someone explain me please.
In the second function, you get the user in the user key. However, you ll have to add it to req object. It can be done like this
if(user){
// it works here
req.user = user;
}
In the first case, it is already added to the req object since it has already executed passport.authenticate before getting into the next async function.
If you print the req.user after the if else, it will give you the exact details.

Passport Js custom callback function not calling next middleware

I am trying to authenticate a user with custom callback in passport js. I have written my code based on the passport documentation.
router.post("/signin/email", function (req, res, next) {
passport.authenticate("email-local", function (err, user, info) {
if (err) {
return res.send("err");
}
if (!user) {
return res.send(info);
}
req.logIn(user, function (err) {
if (err) {
return res.send(err);
}
next(user);
});
})(req, res, next),
UsersController.getToken;
});
I want to pass the user to the next middleware i.e UsersController.getToken ,but it is not being passed. How can i solve this issue?
Passport will add the user data to req.user after login is called so you don't need to pass it with next.
I would recommend simplifying the req.logIn call to the following:
return req.logIn(user, next)
Then within you UsersController.getToken middleware you can access the user data through the req object.

MEAN stack application - querying by userId

I have built an API to GET and POST values into a database(MongoDB) using NodeJS and Express.
I am able to get only a single comment by the userid
(localhost:3000/comments/userid/3)
But I want to get all comments by a single user
/* GET /comments/userid/userid */
router.get('/userid/:userid', function(req, res, next) {
Comments.findOne({userId:req.params.userid}, function (err, post) {
if (err) return next(err);
res.json(post);
})
});
Is there any method to do this? Like the findOne method?
just do find with the query
router.get('/userid/:userid', function(req, res, next) {
Comments.find({userId:req.params.userid}, function (err, post) {
if (err) return next(err);
res.json(post);
})
});

Mongoosedb: query by username

Problem Question: I am using MongooseDB with Nodejs and I have user schema
var UserSchema = new mongoose.Schema({
userEmail: String
});
how would I query using the userEmail?
I tried following but no result. On my postman i get cast to ObjectId failed error
router.get('/:userEmail', function(req, res, next) {
User.find(req.params.userEmail, function (err, userDetails) {
if(err){
return next(err);
}res.json(userDetails);
})
});
You need to create a query object or document that has the userEmail property and a value from the req.params object. In your case, this would be:
router.get('/:userEmail', function(req, res, next) {
User.find({ "userEmail": req.params.userEmail }, function(err, userDetails) {
if(err){
return next(err);
}
res.json(userDetails);
});
});
Please try this syntax
router.get('/:userEmail', function(req, res, next) {
User.find({"userEmail":req.params.userEmail}, function (err, userDetails) {
if(err){
return next(err);
}res.json(userDetails);
})
});
You have to put condition on which field you want to query data.
I am unable to reproduce your error "ObjectId failed error". However, I am adding another answer to give you more options.
The following things are slightly different from other answers:-
1) "lean()" is used to ensure that you will be returned a plain JavaScript object
2) Excluded the "_id" from JSON response though I am not sure whether you need the "Id" in the response. This is just to check whether "id" in response is causing the problem.
router.get('/:userEmail', function(req, res, next) {
User.find({"userEmail": req.params.userEmail}, {"_id":false}).lean().exec(function(err, users) {
if (err) {
return next(err);
}
console.log(users);
res.json(users);
});
});

Node.js / Express.js Removing user from request, removes it from database

Here is the code:
exports.delete = function (req, res, next) {
console.log(req.user);
req.user.remove(function (err) {
if(err) {
return next(err);
} else {
res.json(req.user);
}
})
};
Of course this function is callback of delete method, what I don't understand is that, why removing req.user also deletes the specific user from MongoDB, as it is just a request.
Edit:
I have another callback(GET) which is executed on the same route:
exports.userByID = function (req, res, next, id) {
User.findOne({
_id: id
}, function (err, user) {
if (err) {
return next(err);
} else {
req.user = user;
next();
}
});
};
User is MongoDB model.
Where you do your req.user = user you're setting the value of req.user to the instance of your mongodb model.
So, calling req.user.remove is in fact calling your mongodb model remove function.
Change your delete function to:
exports.delete = function (req, res, next) {
console.log(req.user);
delete req.user
//etc...
};
delete req.user will remove the user object from your request object

Resources