猫鼬架构实例方法不是函数

时间:2019-06-12 18:20:32

标签: node.js express mongoose passport.js

我以前有过工作的Mongoose实例方法工作版本。我不确定这次有什么不同。这次我所做的唯一不同的事情是,我将server.js文件之外的猫鼬连接功能分离为一个配置文件,该配置文件将被导入并调用connect()函数。

我将主要在带本地策略的通行证中使用此实例方法来登录用户。当我在以前的UserModel.findOne({ email })找到的用户实例上调用实例方法时,verify(password)实例方法不会被调用,并且不会引发任何错误。

出于测试目的,我尝试将UserModel.findOne()硬编码到连接字段中,但确实吸引了用户。然后,我决定立即从返回的名为verify()的用户实例中调用实例方法。

我还试图将方法的名称更改为comparePassword,我尝试使用静态测试来检查它是否被调用(不是),我也试图研究其他方式来导入我的模式和模型,但这似乎行不通。我已经尝试过Async / Await并没有改变输出


文件:mongo.db.js

const connect = () => {
  return new Promise((resolve, reject) => {
    mongoose.connect(
      config.get('DB.STRING'),
      { useCreateIndex: true, useNewUrlParser: true },
      async (err) => {
        if (err) reject(err)
        resolve()
        // TESTING INSTANCE METHODS
        await mongoose.connection
          .collection('users')
          // HARD CODED TEST EMAIL
          .findOne({ email: 'braden_feeney@hotmail.com' }, (err, result) => {
            if (err) reject(err)
            console.log(result)
            console.log(result.verify('test1234'))
          })
      },
    )
  })
}

const close = () => {
  return mongoose.disconnect()
}

export default { connect, close }

文件:passport.config.js

passport.use(
  new LocalStrategy(
    {
      usernameField: 'email',
      passwordField: 'password',
    },
    async (email, password, done) => {
      try {
        // Find the user given the email
        const user = await User.findOne({ email })
        // If not found
        if (!user) return done(null, false)
        // Check if the password is correct
        const isValididated = await user.verify(password)
        // If not matched
        if (!isValididated) return done(null, false)

        // Return the user
        done(null, user)
      } catch (error) {
        done(error, false)
      }
    },
  ),
)

文件:users.model.js

const UserSchema = new Schema(
  // HIDDEN FOR SECURITY
  { ... },
  { versionKey: false, timestamps: true },
)

// HIDDEN FOR SECURITY - PRE SAVE WORKS AS EXPECTED
UserSchema.pre('save', async function(next) { ... })

// THIS IS THE METHOD THAT SHOWS AS 'Not a Function'
UserSchema.methods.verify = function(password) {
  bcrypt.compare(password, this.password, (err, res) => {
    if (err) return new Error(err)
    return res
  })
}

export default model('User', UserSchema)

当我调用user.verify(password)时,我希望看到布尔值要么从函数中返回。

实际结果是抛出错误,指出 TypeError: user.verify is not a function

2 个答案:

答案 0 :(得分:0)

这部分没有意义:

async (email, password, done) => {
    try {
        const user = await User.findOne({ email })
        if (user) // <-- if you have a user record
          return done(null, false) // <-- you return!
        // There was no valid user ... how would there be user.verify?
        const isValididated = await user.verify(password)
        if (!isValididated) return done(null, false)
          done(null, user)
    } catch (error) {
        done(error, false)
    }
}

您似乎返回了有效的用户,但是在没有用户时调用user.verify。因此,看来您的流程有些问题。

答案 1 :(得分:0)

仔细研究过猫鼬如何创建实例方法后,我尝试使用另一种方法使该方法起作用。我不得不将bcrypt.compare()包装在一个Promise中,因为我的代码没有等待响应。

文件:users.model.js

UserSchema.method('verify', function(password) {
  return new Promise((resolve, reject) => {
    bcrypt.compare(password, this.password, (err, res) => {
      if (err) reject(err)
      resolve(res)
    })
  })
})

我仍然更喜欢我的问题中提到的方式,因为我认为它看起来更干净,并且不依赖于字符串作为方法名称。