Методы экземпляра схемы Mongoose не являются функцией - PullRequest
0 голосов
/ 12 июня 2019

У меня была рабочая версия методов экземпляра mongoose, которые работали раньше. Я не уверен, что в этот раз отличается от этого. Единственное, что я сделал по-другому, на этот раз - это то, что я разделил функцию подключения 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 голосов
/ 17 июня 2019

Поработав над тем, как mongoose создает методы экземпляра, я попытался использовать другой способ заставить метод работать. Мне пришлось обернуть bcrypt.compare() в обещание, потому что мой код не ждал ответа.

Файл: 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)
    })
  })
})

Я все еще предпочитаю способ, упомянутый в моем вопросе, потому что я считаю, что он выглядит чище и не полагается на строку в качестве имени метода.

0 голосов
/ 12 июня 2019

Этот раздел не имеет смысла:

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, когда у вас нет пользователя. Так что, кажется, ваш поток несколько проблематичен.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...