Creating a expressjs middleware that accepts parameters

node.jsExpress

node.js Problem Overview


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();
}

node.js Solutions


Solution 1 - node.js

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();
  })
}

Solution 2 - node.js

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();
};

Solution 3 - node.js

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) {

})

Solution 4 - node.js

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

Solution 5 - node.js

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();
  }
}

Solution 6 - node.js

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 ));

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionVartan ArabyanView Question on Stackoverflow
Solution 1 - node.jsJonathan OngView Answer on Stackoverflow
Solution 2 - node.jschovyView Answer on Stackoverflow
Solution 3 - node.jszeveroView Answer on Stackoverflow
Solution 4 - node.jsjarragaView Answer on Stackoverflow
Solution 5 - node.jsasdfView Answer on Stackoverflow
Solution 6 - node.jsRicardo AlvesView Answer on Stackoverflow