Reputation: 3073
I am trying to create a middleware that can accept parameters. How can this be done?
example
app.get('/hasToBeAdmin', HasRole('Admin'), function(req,res){
})
HasRole = function(role, req, res, next){
if (role != user.role) {
res.redirect('/NotInRole');
}
next();
}
Upvotes: 153
Views: 68363
Reputation: 21
Here is my simple solution for this. Basically we cannot pass arguments to middleware but using wrapper function we can achieve this.
const restrictTo = (...roles) => {
return (req, res, next) => {
// roles are : ['admin', 'user'], role : req.user.role
if (!roles.includes(req.user.role)) // I am taking role from req.user you can get it from model
{
return new Error('You dont have permission to delete the tour', 404)
}
next();
}
};
Call it like ...
router.delete(restrictTo('admin', 'user'), handler);
Upvotes: 2
Reputation: 2578
After following documentation from here, I was able to solve this issue, I made this middleware and passed the array of role_ids that were allowed to access the route
exports.authorize = function (roles) {
return function (req, res, next) {
console.log(roles)
if (roles?.includes(req.user.role_id)) {
return next()
} else {
return res.status(403).send({
error: "Not Authorized to access this route"
})
}
}
}
and called it in routes file like this
myRouter.get("/", authorize([USER_ROLES.OPERATOR]), getSomething);
if you are wondoring what user role is its just like an enum
const USER_ROLES = Object.freeze({
ADMIN: 1,
HOST: 2,
OPERATOR: 3,
LOCKER_ADMIN: 4,
MERCHANT: 5,
CUSTOMER: 6,
COURIER: 7,
ECOMMERCE: 8
});
Upvotes: 2
Reputation: 561
Since we are in 2021 why not using an ES6 syntax?... Using NodeJS v14.16.1 the example below works like a charm :-)
With express routers
const someFunc = ({ option1, option2 }) =>
router.get("/", (req, res, next) => {
// code
next();
});
module.exports = someFunc;
or
const someFunc = ({ option1, option2 }) =>
(req, res, next) => {
// code
next();
};
module.exports = someFunc;
... Then call it like:
const someFunc = require('./middlewares/someFunc.js');
app.use(someFunc({option1: 'test', option2: false ));
Upvotes: 2
Reputation: 437
I use this solution. I recieve a jwt token in body req, and get role information from there
//roleMiddleware.js
const checkRole = role => {
return (req, res, next) => {
if (req.role == role) {
console.log(`${role} role granted`)
next()
} else {
res.status(401).send({ result: 'error', message: `No ${role} permission granted` })
}
}
}
module.exports = { checkRole }
So first I use auth middleware to know if is a valid user, and then the role middleware to know if user have access to the api route
// router.js
router.post('/v1/something-protected', requireAuth, checkRole('commercial'), (req, res) => {
// do what you want...
})
I hope to be useful
Upvotes: 12
Reputation: 2412
Alternatively if you do not have too many cases or if role is NOT a string:
function HasRole(role) {
return function (req, res, next) {
if (role !== req.user.role) res.redirect(/* ... */);
else next();
}
}
var middlware_hasRoleAdmin = HasRole('admin'); // define router only once
app.get('/hasToBeAdmin', middlware_hasRoleAdmin, function (req, res) {
})
Upvotes: 8
Reputation: 75814
app.get('/hasToBeAdmin', (req, res, next) => {
hasRole(req, res, next, 'admin');
}, (req,res) => {
// regular route
});
const hasRole = (req, res, next, role) => {
if(role != user.role){
res.redirect('/NotInRole');
}
next();
};
Upvotes: 27
Reputation: 1032
If you have various permissions levels you could structure them like this:
const LEVELS = Object.freeze({
basic: 1,
pro: 2,
admin: 3
});
/**
* Check if user has the required permission level
*/
module.exports = (role) => {
return (req, res, next) => {
if (LEVELS[req.user.role] < LEVELS[role]) return res.status(401).end();
return next();
}
}
Upvotes: 3
Reputation: 20345
function HasRole(role) {
return function(req, res, next) {
if (role !== req.user.role) res.redirect(...);
else next();
}
}
I also want to make sure that I don't make multiple copies of the same function:
function HasRole(role) {
return HasRole[role] || (HasRole[role] = function(req, res, next) {
if (role !== req.user.role) res.redirect(...);
else next();
})
}
Upvotes: 212