简体   繁体   中英

Processing all middleware in an express route

I'm building an API with express and I'm using multiple middleware in my routes. Below is one of my endpoints

Router.route('/:id/documents')
  .get([isAuthenticated, isAdmin || isUserOwn], Users.getUserDocuments);

Below are my middleware:

export const isAdmin = (req, res, next) => {
  if (req.decoded.role === 1) {
    next();
  } else {
    res.status(401).send({
      status: 'error',
      message: 'Only admins are authorized to access this resource',
    });
  }
};

export const isUserOwn = (req, res, next) => {
  if (req.decoded.userId === parseInt(req.params.id, 10)) {
    next();
  } else {
    res.status(401).send({
      status: 'error',
      message: 'Only the owner can access this resource',
    });
  }
};

I only want the owner of the document and an admin to have access to the document. The problem I'm having now is if the user is not an admin, it sends the isAdmin response without even getting to the isUserOwn middleware. I've actually thought about converting both into one middleware but I'm also using them individually on other routes. How do I get it to run both?

function isAdminOrisUserOwn(req,res,next){
  if(req.decoded.userId === parseInt(req.params.id, 10) || req.decoded.role === 1){
   next();
  }else{
   //error
  }
}

Functions are generally truthy, so

func1 || func2

Is equal to

func1

The solution might be an extra function like above, or a really complicated approach:

app.use(function(req,res,next){
 isAdmin(req,{ 
  status(code){
    isUserOwn(req,res,next);
    return this;
   },
   send(){}
  },next);

Maybe the most elegant approach would be some wrapper functions eg:

function every(...funcs){
 return function(req,res,next){
   var every=false;
   funcs.reduce(function(func,middle){
     return function(){
       middle(req,res,func);
     }
   },_=>every=true);
  if(every) next() else res.error(404);
 };
}

function some(...funcs){
 return function(req,res,next){
   var some=false;
   if(funcs.some(function(middle){
          middle(req,res,_=>some=true);
          return some;
     }
   })) next() else res.error(404);
 };
}

So you can do:

app.use(some(isAdmin,isUserOwn),...);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM