express - user.setPassword 不是函数 - Passport 本地 Mongoose

标签 express mongoose passport.js

我正在为我的网站的用户实现重置密码功能。但是,当用户在reset.ejs页面确认新密码时,似乎会抛出此错误。

以下步骤正在正确执行:

  • 通过邮件发送 token
  • 单击 token 后,将打开新密码页面

当用户输入新密码并确认新密码并单击按钮保存新密码时,users.js user.setPassword 中的函数不起作用,因为下面提到的错误。它是 Passport-local-mongoose 的内置函数。

ERROR: user.savePassword is not a function

包括以下所有代码文件:

users.js:

var express = require('express');
var router = express.Router();
var multer = require('multer');
var upload = multer({dest: './uploads'});
var passport = require('passport');
var mongoose  = require('mongoose');
var LocalStrategy = require('passport-local').Strategy;
var randomstring = require("randomstring");
var User = require('../models/user');
var data=require('../models/data');
var checklist=require("../models/checklist");
var async = require("async");
var crypto = require("crypto");
var passportLocalMongoose=require("passport-local-mongoose");

// "use strict";
const nodemailer = require("nodemailer");

var transporter = nodemailer.createTransport({
    service: 'gmail',
    auth: {
      user: '<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="d9bdb8adb8aabcbcbdb5adbd99beb4b8b0b5f7bab6b4" rel="noreferrer noopener nofollow">[email protected]</a>',
      pass: 'mypassword'
    }
  });  


/* GET users listing. */
router.get('/', function(req, res, next) {
  res.send('respond with a resource');
});


router.get('/register/:type', function(req, res, next) {

  res.render('user/register.ejs',{title:'Register',type:req.params.type});
});

router.get('/login', function(req, res, next) {
  res.render('user/login.ejs', {title:'Login'});
});

router.post('/login',
  passport.authenticate('local',{failureRedirect:'/users/login', failureFlash: 'Invalid username or password'}),
  function(req, res) {
        var previouspath=req.cookies.previouspath;    

        if(req.cookies.checklist==undefined){
           req.flash('success', 'You are now logged in');
             if(req.user.as=='seller'){
                if(previouspath!=undefined){
                if(previouspath.length!=0)
                res.redirect(previouspath);
                else
                res.redirect('/buyer');
                }
                else
                res.redirect('/buyer');            
                }
             else {
                if(previouspath!=undefined){
                      if(previouspath.length!=0)
                      res.redirect(previouspath);
                      else
                      res.redirect('/buyer');
                }
                else
                res.redirect('/buyer');
             }
          }
        else{
         var ids=req.cookies.checklist['data']

                            var checks=[];
                        for(var i=0;i<ids.length;i++){
                            checks.push({user:req.user,data:ids[i]});
                        }
                  checklist.insertMany(checks,function(err, d) {
                     if(err)console.log(err); 

                     res.clearCookie('checklist'); 
               req.flash('success', 'You are now logged in');
             if(req.user.as=='seller'){
                 if(previouspath.length!=0)
                res.redirect(previouspath);
                else
                res.redirect('/seller')

             }
             else {
                if(previouspath.length!=0)
                res.redirect(previouspath);
                else
                res.redirect('/buyer')
             }
         }); 
        } 
});

passport.serializeUser(function(user, done) {
  done(null, user.id);
});

passport.deserializeUser(function(id, done) {
  User.getUserById(id, function(err, user) {
    done(err, user);
  });
});

passport.use(new LocalStrategy(function(username, password, done){
  User.getUserByUsername(username, function(err, user){
    if(err) throw err;
    if(!user){
      return done(null, false, {message: 'Unknown User'});
    }

    User.comparePassword(password, user.password, function(err, isMatch){
      if(err) return done(err);
      if(isMatch){
        return done(null, user);
      } else {
        return done(null, false, {message:'Invalid Password'});
      }
    });
  });
}));

router.post('/register/:type',function(req, res, next) {
  var name = req.body.name;
  var email = req.body.email;
  var username = req.body.username;
  var institution=req.body.institution;
    var education=req.body.education;
    var proffession=req.body.proffession;
  var   country=req.body.country;
  //check if email does not already exists
  //check if username does not already exists

  User.find({ $or: [ { email: { $eq: req.body.email } }, { username: { $eq: req.body.username } } ] },function(err,data){
    if(err)console.log(err);
    if(data.length!=0){

    console.log(data.length);
     req.flash('success','email or username is repeated.');
     res.redirect('/users/register/'+req.params.type);

    }
    else
    {

        var password = req.body.password;
        var password2 = req.body.password2;
        var as      =req.params.type;

        // Form Validator
        req.checkBody('name','Name field is required').notEmpty();
        req.checkBody('email','Email field is required').notEmpty();
        req.checkBody('email','Email is not valid').isEmail();
        req.checkBody('username','Username field is required').notEmpty();
        req.checkBody('password','Password field is required').notEmpty();

        // Check Errors
        var errors = req.validationErrors();

        if(errors){
            res.render('user/register.ejs', {
                errors: errors
            });
        } else{
            var newUser = new User({
            name: name,
            email: email,
            username: username,
            password: password,
            as          :as,
            institution:institution,
             education:education,
             proffession:proffession,
            country:country
          });

          User.createUser(newUser, function(err, user){
            if(err) throw err;
            console.log(user);
          });

          // res.location('/');
      var token=randomstring.generate(7);
      var to=req.body.email;
      var subject='Email Confirmation from dataSeed ';
      var message='<h1>Use this code to register </h1><p>Your verification Code is: <h2>'+token+'</h2></p>';
        var mailOptions=sendmail(to,subject,message);
        transporter.sendMail(mailOptions, function(error, info){
                          if (error) {
                              console.log(error);
                          }
                          else
                          {
                                res.render('user/emailconfirmation.ejs',{username:req.body.username,token:token});

                          }
        });



        }



      }


  });  

  function sendmail(to,subject,message){

    var mailOptions = {
    from: '<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="3155504550425454555d455571565c50585d1f525e5c" rel="noreferrer noopener nofollow">[email protected]</a>',
    to: to,
    subject: subject,
    html: message 

    };
    return mailOptions;

}

  router.post('/emailconfirmation/:token',function(req, res) {
      if(req.params.token==req.body.token){
              req.flash('success', 'You are now registered and can login');
                res.redirect('/');        
        }
        else{
            User.remove({username:req.body.username},function(err,data){
              if(err)console.log(err);
              res.redirect('/');

              });  
        }
  });
});

router.get('/logout', function(req, res){
  req.logout();
  req.flash('success', 'You are now logged out');
  res.redirect('/users/login');
});


//Forgot Password
router.get('/forgot',function(req,res){
  res.render("forgotpassword.ejs");
  });


  router.post('/forgot', function(req, res, next) {
  async.waterfall([
    function(done) {
      crypto.randomBytes(20, function(err, buf) {
        var token = buf.toString('hex');
        done(err, token);
      });
    },
    function(token, done) {
      User.findOne({ email: req.body.email }, function(err, user) {
        if (!user) {
          req.flash('success', 'No account with that email address exists.');
          return res.redirect('/users/forgot');
        }

        user.resetPasswordToken = token;
        user.resetPasswordExpires = Date.now() + 3600000; // 1 hour

        user.save(function(err) {
          done(err, token, user);
        });
      });
    },
    function(token, user, done) {
      var smtpTransport = nodemailer.createTransport({
        service: 'Gmail', 
        auth: {
          user: '<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="c0a4a1b4a1b3a5a5a4acb4a480a7ada1a9aceea3afad" rel="noreferrer noopener nofollow">[email protected]</a>',
          pass: 'mypassword'
        }
      });
      var mailOptions = {
        to: user.email,
        from: '<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="395d584d584a5c5c5d554d5d795e54585055175a5654" rel="noreferrer noopener nofollow">[email protected]</a>',
        subject: 'Node.js Password Reset',
        text: 'You are receiving this because you (or someone else) have requested the reset of the password for your account.\n\n' +
          'Please click on the following link, or paste this into your browser to complete the process:\n\n' +
          'http://' + req.headers.host + '/users/reset/' + token + '\n\n' +
          'If you did not request this, please ignore this email and your password will remain unchanged.\n'
      };
      smtpTransport.sendMail(mailOptions, function(err) {
        console.log('mail sent');
        req.flash('success', 'An e-mail has been sent to ' + user.email + ' with further instructions.');
        done(err, 'done');
      });
    }
  ], function(err) {
    if (err) return next(err);
    res.redirect('/users/forgot');
  });
});

router.get('/reset/:token', function(req, res) {
  User.findOne({ resetPasswordToken: req.params.token, resetPasswordExpires: { $gt: Date.now() } }, function(err, user) {
    if (!user) {
      req.flash('success', 'Password reset token is invalid or has expired.');
      return res.redirect('/users/forgot');
    }
    res.render('reset', {token: req.params.token});
  });
});

router.post('/reset/:token', function(req, res) {
  async.waterfall([
    function(done) {
      User.findOne({ resetPasswordToken: req.params.token, resetPasswordExpires: { $gt: Date.now() } }, function(err, user) {
        if (!user) {
          req.flash('error', 'Password reset token is invalid or has expired.');
          return res.redirect('back');
        }
        if(req.body.password === req.body.confirm) {
          user.setPassword(req.body.password, function(err) {
            user.resetPasswordToken = undefined;
            user.resetPasswordExpires = undefined;

            user.save(function(err) {
              req.logIn(user, function(err) {
                done(err, user);
              });
            });
          })
        } else {
            req.flash("error", "Passwords do not match.");
            return res.redirect('back');
        }
      });
    },
    function(user, done) {
      var smtpTransport = nodemailer.createTransport({
        service: 'Gmail', 
        auth: {
          user: '<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="f99d988d988a9c9c9d958d9db99e94989095d79a9694" rel="noreferrer noopener nofollow">[email protected]</a>',
          pass: 'mypassword'
        }
      });
      var mailOptions = {
        to: user.email,
        from: '<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="8febeefbeefceaeaebe3fbebcfe8e2eee6e3a1ece0e2" rel="noreferrer noopener nofollow">[email protected]</a>',
        subject: 'Your password has been changed',
        text: 'Hello,\n\n' +
          'This is a confirmation that the password for your account ' + user.email + ' has just been changed.\n'
      };
      smtpTransport.sendMail(mailOptions, function(err) {
        req.flash('success', 'Success! Your password has been changed.');
        done(err);
      });
    }
  ], function(err) {
    res.redirect('/login');
  });
});
module.exports = router;

users.js(模型):

var mongoose = require('mongoose');
var bcrypt = require('bcryptjs');
var passportLocalMongoose=require("passport-local-mongoose");
mongoose.connect('mongodb://localhost/dataseed');

var db = mongoose.connection;

// User Schema
var UserSchema = mongoose.Schema({
    username: {
        type: String,
        index: true
    },
    password: {
        type: String
    },
    email: {
        type: String
    },
    name: {
        type: String
    },
    profileimage:{
        type: String
    },
    as:{
        type:String
    },
    institution:{
        type:String
    },
    education:{
        type:String

    },
    proffession:{
        type:String
    },
    country:{
        type:String
    },
    resetPasswordToken: String,
    resetPasswordExpires: Date

});

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

module.exports.getUserById = function(id, callback){
    User.findById(id, callback);
}

module.exports.getUserByUsername = function(username, callback){
    var query = {username: username};
    User.findOne(query, callback);
}

module.exports.comparePassword = function(candidatePassword, hash, callback){
    bcrypt.compare(candidatePassword, hash, function(err, isMatch) {
        callback(null, isMatch);
    });
}

module.exports.createUser = function(newUser, callback){
    bcrypt.genSalt(10, function(err, salt) {
        bcrypt.hash(newUser.password, salt, function(err, hash) {
            newUser.password = hash;
            newUser.save(callback);
        });
    });
}

最佳答案

您似乎没有在用户模型下定义名为 setPassword 的方法。这主要是因为您尚未将 passport-local-mongoose 插入 UserSchema。在从 UserSchema 创建模型之前添加 UserSchema.plugin(passportLocalMongoose);。像这样

    var mongoose = require('mongoose');
    var bcrypt = require('bcryptjs');
    var passportLocalMongoose=require("passport-local-mongoose");
    mongoose.connect('mongodb://localhost/dataseed');

    var db = mongoose.connection;

    // User Schema
    var UserSchema = mongoose.Schema({
        username: {
            type: String,
            index: true
        },
        password: {
            type: String
        },
        email: {
            type: String
        },
        name: {
            type: String
        },
        profileimage:{
            type: String
        },
        as:{
            type:String
        },
        institution:{
            type:String
        },
        education:{
            type:String

        },
        proffession:{
            type:String
        },
        country:{
            type:String
        },
        resetPasswordToken: String,
        resetPasswordExpires: Date

    });

    UserSchema.plugin(passportLocalMongoose);

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

关于express - user.setPassword 不是函数 - Passport 本地 Mongoose ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56204332/

相关文章:

javascript - express.js app.post 中间件未触发

javascript - Mongoose 和 Nodejs 具有存储库模式,无需回调

javascript - Passport.deserializeUser() 不适用于 Firebase

node.js - 基于 sailsjs jwt token 的身份验证示例

javascript - 如何在 Node.js 中使用 php 的 session_id() 之类的东西?

node.js - 快车的路径

javascript - MongoDb:在父级保存中查找插入的子级的生成 ID

node.js - 使用 PassportJS 时将用户序列化/反序列化到 session 中的目的是什么?

node.js - 应用程序为同一用户创建两个 session - Express js

javascript - Mongoose 将两个查询合并为同一集合