2015-11-21 1 views
0

Я хочу проверить, что пользователь имеет роль, которая позволяет ему использовать конечную точку в моем API. Обычно я хотел бы сделать это, взяв userId, отправленный как часть JWT, и сделайте поиск в БД, чтобы увидеть роль пользователя. Это будет происходить внутри вызова API и будет выглядеть примерно так:Как получить доступ к db из промежуточного программного обеспечения node.js

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.

+0

Для того, чтобы это правильно понять, '' функция app.models.User' не определена в функции, вызываемой после 'isUserInRole' или во время? –

+0

i.e является 'app.models.User.findOne' undefined? –

+0

'app.models.User' не определено в момент, когда' isUserInRole' называется промежуточным программным обеспечением, но он доступен в следующей функции.Например, если я использую 'isUserInRole' как промежуточное программное обеспечение и называю его нормальной функцией в анонимной функции, то я вижу, что вызов db выполняется потому, что' app.models.User' не определен. – Ebbs

ответ

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; 

EDIT:

Если вы используете Мангуст, вы также можете сделать что-то более простое, как это:

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

Мое первое предположение было бы b/c, вы на самом деле вызываете функцию, а не просто передаете ее. Кроме того, вы на самом деле не проходите промежуточное программное обеспечение. Функции Middleware выглядеть

function(req,res,next){} 

Кроме того, вы, вероятно, хотите использовать сессии вместо того, чтобы поразить базу данных по каждому запросу

+0

Я не думаю, что использование сеансов - это правильный путь. Я бы предпочел сохранить API без гражданства. Вот почему я решил использовать JWT. Я мог бы добавить роль пользователя в полезную нагрузку JWT, но я чувствую, что это небезопасно, поскольку я не могу доверять тому, что отправляет пользователь, если только я не использую ssl, который я не хочу делать во время разработки. Не доверяя пользователю, почему мне нужно проверить, какие привилегии у него есть, чтобы решить продолжить или нет, а простой вызов db не слишком дорог, не так ли? (Я должен сделать его менее дорогостоящим, указав столбцы для возврата и не возвратить все, как я есть сейчас.) – Ebbs

+0

@MrThursday вы все еще можете использовать сеансы и по-прежнему сохранять свой бэкэнд без гражданства. Вы правы, вы не должны принимать разрешения от клиента, это очень плохо. Тем не менее, вы можете сделать свой вызов db один раз, а затем сохранить свои разрешения в переменной сеанса на стороне сервера, чтобы вам не приходилось ударять db при следующем запросе. Очевидно, вам нужно будет управлять сеансом, включая обработку ситуаций, когда роли пользователя изменяются. Впрочем, это не так, я думаю, что ваша настоящая проблема заключается в том, что вы на самом деле не пишете свой авторизационный вызов в качестве промежуточного программного обеспечения. –