I want to verify that a user has a role which allows him/her to use an endpoint in my API. Usually I would go about doing so by taking the userId sent as part of a JWT and do a lookup on the DB to see what the user's role is. It would happen inside an API call and would look something like this:
var userId = getUserIdFromJwt();
app.models.User.findOne({_id: userId}, function (err, user) {
...check if user is in role...
});
Now I want to try and move that code to a piece of middleware, which would look like this:
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"});
}
}
});
};
The middleware would be implemented like this:
const allowableRoles = ['admin', 'implementor'];
app.get('/getStuff/', isUserInRole(app, allowableRoles), function (req, res) {
... do stuff if user is in role ...
});
At this point I am running into a problem where the app.models.User
value is always undefined
.
I do not understand why app.models.User
is undefined at this point as I can access it within the anonymous function inside the get call.
How would I go about about access the DB from within my middleware if I cannot send it app.models.User
?
For reference, I am using Mongoose and exposing it to my app in the server.js from which I access the a MongoDB db.
I think you're problem is that you are trying to get models before they are actually initialized, as you are binding the app to the parameters on initialization of the app.
So in your main app file, I would do module.exports = app;
and then in your middleware file, simply include the app by doing var app = require('./path/to/app');
. Then remove the app
from the middleware. You might end up with something like this:
var app = require('./path/to/app');
exports.isUserInRole = function(allowableRoles) {};
And in your route change it to this:
const allowableRoles = ['admin', 'implementor'];
app.get('/getStuff/', isUserInRole(allowableRoles), function (req, res) {}
And lastly in your app file, add the app to the exports:
module.exports = app;
EDIT:
If you're using Mongoose, you can also do something more simple like this:
var mongoose = require('mongoose');
var User = mongoose.model('User');