"TypeError: undefined is not a function" for method in schema representing user

"TypeError: undefined is not a function" for method in schema representing user

我正在尝试 'Mean Machine' 书中的练习,创建 API 并验证用户并提供令牌。我在 comparePassword() 上收到 'TypeError: undefined is not a function'。我做错了什么?

这是我的错误。

  server.js:69
  var validPassword = user.comparePassword(req.body.password);
                               ^
TypeError: undefined is not a function

这里是似乎导致问题的代码(一半):

 // more routes for our API will happen here
apiRouter.post('/authenticate', function(req, res){
    // find the user
    // select the name username explicitly
    User.findOne({
        username: req.body.username
    }).select('name username password').exec(function(err, user){

        if(err) throw err;

        // no user with that username was found
        if (!user){
            res.json({ 
                success: false, 
                message: 'Authentication failed. User not found'
            });

        }else if (user) {
            // check if password matches
            var validPassword = user.comparePassword(req.body.password);
            if(!validPassword){
                res.json({ 
                    success: false, 
                    message: 'Authentication failed. wrong password'
                });
            } else {

            // if user is found and password is right
            // create a token   
            var token = jwt.sign({
                name: user.name,
                username: user.username
            }, superSecret, {
                expiresInMinutes: 1440 // expires after 24 hours
            });

            // return the information including token as JSON
            res.json({
                success: true,
                message: 'enjoy your token!',
                token: token
            }); 
        }
      } 

    });
});

以上内容与 server.js 文件的其余部分相关联:

// Base Setup
// ======================================

// CALL THE PACKAGES
var express     = require('express'); // call express
var app         = express(); // define our app using express
var bodyParser  = require('body-parser'); // get body-parser
var morgan      = require('morgan'); // used to see requests
var mongoose    = require('mongoose'); // for working w/ our database
var User        = require('./app/models/user');
var port        = process.env.PORT || 8080; // Set the port for our app
var jwt = require('jsonwebtoken');

// super secret for creating tokens
var superSecret = 'rockabyezebra';

//APP CONFIGURATION 
// Use body-parser so we can grab information from post requests
app.use(bodyParser.urlencoded({extended: true }));
app.use(bodyParser.json());

// configure our app to handle CORS requests
app.use(function(req, res, next){
    res.setHeader('Access-Control-Allow-Origin', '*');
    res.setHeader('Access-Control-Allow-Methods', 'GET', 'POST');
    res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type, \ Authorization');
    next();
});


// log all requests to the console
app.use(morgan('dev'));

// connect to our database (hosted on mongolab.com)
mongoose.connect('mongodb://blah:blahblah@ds031852.mongolab.com:31852/app42');

// ROUTES FOR OUR API
// ================================
var apiRouter = express.Router();  // get an instance of the express Router


// basic route for the homepage
app.get('/', function(req, res){
    res.send('Welcome to the home page');
});

// get an instance of the express router
var apiRouter = express.Router();

// more routes for our API will happen here
apiRouter.post('/authenticate', function(req, res){
    // find the user
    // select the name username explicitly
    User.findOne({
        username: req.body.username
    }).select('name username password').exec(function(err, user){

        if(err) throw err;

        // no user with that username was found
        if (!user){
            res.json({ 
                success: false, 
                message: 'Authentication failed. User not found'
            });

        }else if (user) {
            // check if password matches
            var validPassword = user.comparePassword(req.body.password);
            if(!validPassword){
                res.json({ 
                    success: false, 
                    message: 'Authentication failed. wrong password'
                });
            } else {

            // if user is found and password is right
            // create a token   
            var token = jwt.sign({
                name: user.name,
                username: user.username
            }, superSecret, {
                expiresInMinutes: 1440 // expires after 24 hours
            });

            // return the information including token as JSON
            res.json({
                success: true,
                message: 'enjoy your token!',
                token: token
            }); 
        }
      } 

    });
});


// middleware to use for all requests
apiRouter.use(function(req, res, next){
    // do logging   
    console.log('Somebody just visited our app');
    // we'll add more to the middleware in Chapter 10
    // this is where we will authenticate users
    next();  // make sure we go to the next routes and don't stop here
});





// test route to make sure everything is working
// accessed at GET http://localhost:8080/api
apiRouter.get('/', function(req, res){
        res.json({ message: 'hooray! welcome to our api'});
});



// on routes that end in /users
// ---------------------------------------------------
apiRouter.route('/users')

    // create a user (accessed at POST http://localhost:8080/users)
    .post(function(req, res){

        // create a new instance of the user model
        var user = new User();

        // set the users information (comes from the request)
        user.name = req.body.name;
        user.username = req.body.username;
        user.password = req.body.password;

        // save the user and check for errors
        user.save(function (err) {
            if (err){
            // duplicate entry  
            if (err.code ==11000)
                return res.json({ success: false, message: 'A user with that username already exists. '});
            else
                return res.send(err);
            }
            res.json ({ message: 'User created'});
        });
    })

    // get all the users (accessed at GET http://localhost:8080/api/users)
    .get(function(req,res) {
        User.find(function(err, users) {
            if (err) return res.send(err);

            // return the users
            res.json(users);
        });
    });

// on routes that end in /users/:user_id
// ----------------------------------------------------
apiRouter.route('/users/:user_id')

    // get the user with that id
    .get(function(req, res) {
        User.findById(req.params.user_id, function(err, user) {
            if (err) return res.send(err);

            // return that user
            res.json(user);
        });
    })

// update the user with this id
    .put(function(req, res){
        User.findById(req.params.user_id, function(err, user) {
            if (err) return res.send(err);

            // set the new user information if it exists in the request
            if(req.body.name) user.name = req.body.name;
            if(req.body.username) user.username = req.body.username;
            if(req.body.password) user.password = req.body.password;

            // save the user
            user.save(function(err){
                if (err) return res.send(err);

            // return a message
            res.json({ message: 'user updated'});   
            });
        });
    })  

    .delete(function(req, res){
        User.remove({
            _id: req.params.user_id
            }, function(err, user) {
                if (err) res.send(err);

            res.json({ message: 'Successfully deleted'});
        });
    });




// REGISTER OUR ROUTES ----------------------------------
// all of our routes will be prefixed with  /api
app.use('/api', apiRouter);

// START THE SERVER
// ================================
app.listen(port);
console.log('rockin\' on port ' + port + ' y\'all');

我假设您正在使用 mongoose 模块处理您的数据。看起来您从未在 UserSchema 中定义方法 comparePasswordUser 模型来自哪里)。您可以像这样在模式中定义方法。文档 here:

var AnimalSchema = new Schema({
  name: String,
  type: String
});

AnimalSchema.methods.findSimilarType = function findSimilarType(cb) {
  return this.model('Animal').find({
    type: this.type
  }, cb);
};
// Now when we have an instance of Animal we can call our // findSimilarType method and find all animals with a matching type.

var Animal = mongoose.model('Animal', AnimalSchema);
var dog = new Animal({
  name: 'Rover',
  type: 'dog'
});

dog.findSimilarType(function(err, dogs) {
  if (err) return ...
  dogs.forEach(..);
})