如何从node.js中间件访问数据库

时间:2015-11-21 19:06:31

标签: node.js mongodb express mongoose middleware

我想验证用户是否具有允许他/她在我的API中使用端点的角色。通常我会通过将userId作为JWT的一部分发送来执行此操作,并在DB上查找以查看用户的角色。它会发生在API调用中,看起来像这样:

var userId = getUserIdFromJwt();

app.models.User.findOne({_id: userId}, function (err, user) {
    ...check if user is in role...
});

现在我想尝试将代码移动到一个中间件,看起来像这样:

exports.isUserInRole = function(app, allowableRoles) {
    var userId = getUserIdFromJwt();

    app.models.User.findOne({_id: userId}, function (error, user) {
        if (error) {
            return res.status(500).json(error);
        }

        return function (req, res, next) {
            if(_.includes(allowableRoles, user.Role)) {
                next();
            } else {
                return res.status(401).json({"error": "User not in role"});
            }
        }
    });
};

中间件将实现如下:

const allowableRoles = ['admin', 'implementor'];
app.get('/getStuff/', isUserInRole(app, allowableRoles), function (req, res) {
   ... do stuff if user is in role ...
});

此时我遇到app.models.User值始终为undefined的问题。

我不明白为什么此时app.models.User未定义,因为我可以在get调用中的匿名函数中访问它。

如果我无法发送app.models.User,我将如何从中间件访问数据库?

作为参考,我使用Mongoose并将其公开给我在server.js中的应用程序,我从中访问MongoDB数据库。

2 个答案:

答案 0 :(得分:0)

我的第一个猜测是b / c你实际上是在调用函数而不是仅仅传入函数。另外,你实际上并没有传递中间件。中间件功能看起来像

function(req,res,next){}

此外,您可能希望利用会话而不是在每个请求上访问数据库

答案 1 :(得分:0)

我认为你的问题是你在实际初始化模型之前尝试获取模型,因为你将应用程序绑定到应用程序初始化时的参数。

因此,在您的主应用文件中,我会module.exports = app;,然后在您的中间件文件中,只需通过执行var app = require('./path/to/app');来包含该应用。然后从中间件中删除app。你最终会得到这样的东西:

var app = require('./path/to/app');

exports.isUserInRole = function(allowableRoles) {};

在您的路线中将其更改为:

const allowableRoles = ['admin', 'implementor'];
app.get('/getStuff/', isUserInRole(allowableRoles), function (req, res) {}

最后在您的应用文件中,将应用添加到导出中:

module.exports = app;

编辑:

如果你使用的是Mongoose,你也可以做一些更简单的事情:

var mongoose = require('mongoose');
var User = mongoose.model('User');