Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't I access a mongoose schema's method?

I have this Mongoose schema in a Nodejs application:

const mongoose = require('mongoose'),
    Schema = mongoose.Schema,
    sodium = require('sodium').api;

const UserSchema = new Schema({
    username: {
        type: String,
        required: true,
        index: { unique: true }
    },
    salt: {
        type: String,
        required: false
    },
    password: {
        type: String,
        required: true
    }
});

UserSchema.methods.comparePassword = function(candidatePassword, targetUser) {
    let saltedCandidate = candidatePassword + targetUser.salt;
    if (sodium.crypto_pwhash_str_verify(saltedCandidate, targetUser.password)) {
        return true;
    };
    return false;
};

module.exports = mongoose.model('User', UserSchema);

And I created this routes file.

const _ = require('lodash');
const User = require('../models/user.js'); // yes, this is the correct location

module.exports = function(app) {
    app.post('/user/isvalid', function(req, res) {
        User.find({ username: req.body.username }, function(err, user) {
            if (err) {
                res.json({ info: 'that user name or password is invalid. Maybe both.' });
            };
            if (user) {
                if (User.comparePassword(req.body.password, user)) {
                    // user login
                    res.json({ info: 'login successful' });
                };
                // login fail
                res.json({ info: 'that user name or password is invalid Maybe both.' });
            } else {
                res.json({ info: 'that user name or password is invalid. Maybe both.' });
            };
        });
    });
};

I then use Postman to make a call to 127.0.0.1:3001/user/isvalid with an appropriate Body content. The terminal says tell me TypeError: User.comparePassword is not a function and crashes the app.

Since the if (user) bit passes, that indicates to me that I have properly retrieved a document from Mongo and have an instance of the User schema. Why is the method not valid?

eta: the module export I failed to copy/paste originally

like image 423
The E Avatar asked Jan 04 '23 12:01

The E


1 Answers

This creates instance method:

UserSchema.methods.comparePassword = function(candidatePassword, targetUser) {
    // ...
};

If you want a static method use this:

UserSchema.statics.comparePassword = function(candidatePassword, targetUser) {
    // ...
};

Static methods are when you want to call it as User.comparePassword().

Instance methods are when you want to call it as someUser.comparePassword() (which in this case would make a lot of sense so that you wouldn't have to pass the user instance explicitly).

See the documentation:

  • http://mongoosejs.com/docs/guide.html#methods
  • http://mongoosejs.com/docs/guide.html#statics
like image 142
rsp Avatar answered Jan 16 '23 20:01

rsp