20

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: '[email protected]', 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?

15
  • 1
    How are User and user defined? Are you assuming they are the same? Commented Jun 18, 2015 at 18:49
  • Nope, they are not same One is var user = require('../models/user'); which is the mongoose model The other one is the callback argument in the above code Commented Jun 18, 2015 at 18:53
  • ok, this is a bit confusing. Usually you should only use things that start with a capital letter for constructors. Commented Jun 18, 2015 at 18:54
  • 2
    even more confusing is user actually is a constructor, while User is not. ;) Commented Jun 18, 2015 at 18:55
  • Oh, didnt know that.. Sorry. Commented Jun 18, 2015 at 18:56

3 Answers 3

28

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')) {...} 
Sign up to request clarification or add additional context in comments.

3 Comments

Second method did not work (returned false even for defined properties), but using .toObject() then .hasOwnProperty(...) was Ok. Thanks !
@FrostyZ I am a bit confused by that. Another check I forgot to mention is to use Mongoose's built in get method: if (!User.get('local.password')) {...}. Maybe that would be better for you?
Works as expected with .get(...) (and even better than hasOwnProperty() because get() is able to detect properties containing empty objects, whereas hasOwnProperty() method isn't, probably due to the .toObject() conversion). Thanks again ;-)
1

If you only need the data and not the other Mongoose magic such as .save(), .remove() etc then the most simple way would be to use .lean():

user.findOne( { 'email' : email }, function( err, User ).lean() { 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')); // Should now be "here: true" } if ( !User.validPass(password) ) { return done(null, false, { error : "Incorrect Password"}); } return done(null, User); }); 

Comments

0

You can also detach the returned JSON from MongoDB Schema - JSONuser = JSON.parse(JSON.stringify(User)) - and then use JSONuser freely getting, changing or adding, any of its properties.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.