验证 Hapi.js 和 Bookshelf.js 问题

Validation with Hapi.js and Bookshelf.js issues

我正在按照他们在 bookshelf.js (http://bookshelfjs.org/#Model) 网站上提供的 login 示例进行操作,但出于某种原因,无论我是否提交密码是否错误

这是我的路线:

    {
        method: 'POST',
        path: '/auth/login',
        config: {
            auth: false,
            payload: { allow: 'application/json' },
            handler: function(request, reply) {
                var email = request.payload.email;
                var pwd = request.payload.password;

                User.login(email, pwd).then(function(user) {
                    reply(user.pick('api_token'));
                }).catch(User.NotFoundError, function() {
                    reply({error: email + ' not found'}).code(400)
                }).catch(function(err) {
                    console.error(err);
                });
            },
            validate: {
                payload: Joi.object().keys({
                    email: Joi.string().email().required(),
                    password: Joi.string().required()
                })
            }
        }
    }

这是我的模型:

'use strict';

var Bluebird = require('bluebird');
var bcrypt = Bluebird.promisifyAll(require('bcrypt'));


module.exports = function(bookshelf) {
    var User = bookshelf.Model.extend({
        tableName: 'user',
    }, {
        login: Bluebird.method(function(email, password) {
            return new this({email: email.toLowerCase().trim()})
                .fetch({require: true})
                .tap(function(user) {
                    return bcrypt.compareAsync(password, user.get('encrypted_password'));
                });
        })
    });

    return User;
};

我不确定发生了什么。我 console.log 通过比较一个好的请求和一个坏的请求的密码得到了响应,那段代码正在运行,但就像我说的,即使我提交了一个错误的密码,用户也会被返回

是的,这里的文档是错误的。

您没有对 compareAsync 的结果执行任何操作。它 returns 一个解析为布尔值的承诺(文档 here)。

所以你可能想做这样的事情:

在某处创建错误class。我正在使用 Bookshelf 使用的 'create-error' 模块。

InvalidPasswordError = require('create-error')('InvalidPasswordError');

现在当密码不匹配时触发此错误。

login: Bluebird.method(function(email, password) {
  return new this({email: email.toLowerCase().trim()})
    .fetch({require: true})
    .tap(function(user) {
      return bcrypt.compareAsync(password, user.get('encrypted_password'))
        .then(function (matches) {
          if (!matches) throw new InvalidPasswordError();
        }
    });
})

现在按类型捕获该错误并以适当的错误响应。

handler: function(request, reply) {
  var email = request.payload.email;
  var pwd = request.payload.password;

  User.login(email, pwd).then(function(user) {
    reply(user.pick('api_token'));
  }).catch(User.NotFoundError, function() {
    reply({error: email + ' not found'}).code(400);
  }).catch(InvalidPasswordError, function() {
    reply({error: 'invalid password'}).code(400);
  }).catch(function(err) {
    console.error(err);
  });
},

我认为 Rhys van der Waerden 提供了一个很好的解决方案。但是,要弄清楚您的代码有什么问题,请考虑以下内容(来自 bluebird 规范):

getUser().tap(function(user) {
    //Like in finally, if you return a promise from the handler
    //the promise is awaited for before passing the original value through
    return recordStatsAsync();
}).then(function(user) {
    //user is the user from getUser(), not recordStatsAsync()
});

如您所见,.then案例得到了完整的结果,.tap的异步部分没有提供.then的数据。

长话短说:从 .tap 更改为 .then,你应该会很好。但是,您将获得的结果将是 truefalse 而不是用户数据。