Паруса.JS Policies, есть ли оператор OR, чтобы разрешить действие, если одна из групп политик успешно выполняется?


При настройке политик в sails в config / policies.js такие как:

    ActivityController: {
        create: ['authenticated'],
        update: ['authenticated', 'isActivityOwner'],
        destroy: ['authenticated' ,'isActivityOwner']
    }

Есть ли какая-либо функциональность, которая позволила бы мне предоставить доступ к действию при условии, что одна или несколько групп политик успешно выполнят, возможно, что-то вроде:

    ActivityController: {
        create: ['authenticated'],
        update: ['authenticated', {or:['isActivityOwner', 'isAdmin']}],
        destroy: ['authenticated' ,'isActivityOwner']
    }

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

Если оба эти варианта кажутся плохими решениями, можете ли вы предложить подход, который был бы считаешь, что это лучшая практика?

Простите меня, если это немного очевидно, но я довольно новичок в парусах и узле в целом, и заранее благодарю за любую помощь!
5 13

5 ответов:

Я не нашел никакой официальной поддержки для операторов в политике sails, но вот что я делаю.

ActivityController: {
    update: ['authenticated', 'orActivityOwner', 'orAdmin', orPolicy],
}

И orActivityOwner, и orAdmin возвращают next(), как если бы они действительны. Но они также задают логическое значение переменной сеанса. Помните, что политики выполняются слева направо. Я добавил orPolicy в конец,который затем будет оценивать состояние нашей переменной сеанса.

Проверить паруса-обязательно :

ActivityController: {
    create: 'authenticated',
    update: ['authenticated', must().be.the.owner.or.be.a.member.of('admins')],
    destroy: ['authenticated', must().be.the.owner]
}

Я создал крюк sails, чтобы иметь возможность добавлять параметры в политики:
https://github.com/mastilver/sails-hook-parametized-policies

Я установил пример, в котором я определил политику or:

module.exports = function(firstPolicy, secondPolicy){

    return function(req, res, next){


        var fakeRes = {};

        for(var i in res){
            if(i === 'forbidden'){
                // override the functions you want the `or` factory to handle
                fakeRes[i] = function(){
                    secondPolicy(req, res, next);
                };
            }
            else{
                fakeRes[i] = res[i];
            }
        }


        firstPolicy(req, fakeRes, next);
    }
}

Который вы можете использовать таким образом:

ActivityController: {
        create: ['authenticated'],
        update: ['authenticated', 'or(isActivityOwner, isAdmin)'],
        destroy: ['authenticated' ,'isActivityOwner']
    }

Просто чтобы завершить предыдущий ответ, который работает как заклинание:


Часть информации

Но они также задают логическое значение переменной сеанса

Я сам предпочитаю устанавливать этот булев объект req, что:

  • является более семантическим (доступ предоставлен или не предоставлен ресурсу для запроса , а не для всего сеанса )
  • не требует, чтобы я вручную сбрасывал эту переменную (Я должен добавить, что, если вы Хотите использовать сеанс, как в решении @ Travis, последняя политика orPolicy должна сбросить (даже сбросить) variable, чтобы защитить следующий запрос)

Моя реализация

config/policies.js :

MyController: {
  find: ['orIsTest1', 'orIsTest2', 'protectedResourceGranted']
}

api / policies / orIsTest1.js :

module.exports = function(req, res, next) {
  req.protectedResourceGranted = req.protectedResourceGranted || WHATEVERFIRSTTEST;

  return next();
};

api / policies / orIsTest2.js

module.exports = function(req, res, next) {
  req.protectedResourceGranted = req.protectedResourceGranted || WHATEVERSECONDTEST;

  return next();
};

api / policies / protectedResourceGranted.js

module.exports = function(req, res, next) {
  if(req.protectedResourceGranted) {
    return next();
  }

  return res.forbidden();
};

НБ: просто отвечаю, потому что у меня недостаточно репутации. комментировать.

Другие ответы здесь работают отлично, но вот реализация, которую я нахожу немного чище.

Вместо того, чтобы создавать политики, предназначенные дляили ситуации, которые вызывают next(), даже если они должны потерпеть неудачу, вы можете изменить существующие политики для использования в и/или контекст , при этом практически не меняя своего поведения. Затем создайте составную политику (как предлагал ОП), которая проверяет измененные существующие политика.

config/policies.js с примерами контроллеров и политик:

AdminController: {
  adminDashboard: 'isAuthenticated',
},

ItemController: {
  findOne: 'isPublishedOrIsAuthenticated'
}

api / policies/isAuthenticated.js и api/policies/isPublished.js и любой другой политики, которую вы хотите использовать в качестве части и/или проверить:

Если next было установлено в true логическое значение (в отличие от обратного вызова), просто верните true или false, Прежде чем политика будет нормально возвращаться next(), res.notFound(), и т.д.

module.exports = function(req, res, next) {
  // do some checking
  if(next === true) return true; // or return false
  return next();
};

Обратите внимание, что нам нужно используйте тройной равна распишитесь.

api / policies / isPublishedOrIsAuthenticated.js

module.exports = function(req, res, next) {
  var isPublished = require('./isPublished.js');
  var isAuthenticated = require('./isAuthenticated.js');

  // This reads like what we are trying to achieve!
  // The third argument in each call tells the function to return a boolean
  if(isPublished(req, res, true) || isAuthenticated(req, res, true))
    return next();

  return res.notFound();
};