I have this code :
user.findOne( { 'email' : email }, function( err, User )
{
if ( err )
{
return done(err);
}
if ( !User )
{
return done(null, false, { error : "User not found"});
}
if ( !User.hasOwnProperty('local') || !User.local.hasOwnProperty('password') )
{
console.log("here: " + User.hasOwnProperty('local')); // displays here: false
}
if ( !User.validPass(password) )
{
return done(null, false, { error : "Incorrect Password"});
}
return done(null, User);
});
Since the app supports other kinds of authentication, I have a user model that has nested object called local which looks like
local : { password : "USERS_PASSWORD" }
So during login I want to check whether the user has provided a password but I encountered this interesting problem. My test object looks like this:
{ _id: 5569ac206afebed8d2d9e11e,
email: 'test@example.com',
phno: '1234567890',
gender: 'female',
dob: Wed May 20 2015 05:30:00 GMT+0530 (IST),
name: 'Test Account',
__v: 0,
local: { password: '$2a$07$gytktl7BsmhM8mkuh6JVc3Bs/my7Jz9D0KBcDuKh01S' } }
but console.log("here: " + User.hasOwnProperty('local'));
prints here: false
Where did I go wrong?
It's because the document object you get back from mongoose doesn't access the properties directly. It uses the prototype chain hence hasOwnProperty
returning false (I am simplifying this greatly).
You can do one of two things: use toObject()
to convert it to a plain object and then your checks will work as is:
var userPOJO = User.toObject();
if ( !(userPOJO.hasOwnProperty('local') && userPOJO.local.hasOwnProperty('password')) ) {...}
OR you can just check for values directly:
if ( !(User.local && User.local.password) ) {...}
Since neither properties can have a falsy value it should work for testing if they are populated.
EDIT: Another check I forgot to mention is to use Mongoose's built in get
method:
if (!User.get('local.password')) {...}