Подтвердить что ты не робот

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

При настройке политик в парусах в config/policy.js, например:

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

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

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

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

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

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

4b9b3361

Ответ 1

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

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

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

Ответ 2

проверьте sails-must:

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

Ответ 3

Я создал паруса для добавления параметров в правила:
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']
    }

Ответ 4

Чтобы завершить предыдущий ответ, это работает как шарм:


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

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

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

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

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

config/policy.js:

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

api/policy/orIsTest1.js:

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

  return next();
};

апи/политика/orIsTest2.js

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

  return next();
};

API/политика/protectedResourceGranted.js

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

  return res.forbidden();
};

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

Ответ 5

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

Вместо создания политик, предназначенных для ситуации ИЛИ, вызывающих next(), даже если они должны завершиться неудачей, вы можете изменить существующие политики для использования в контексте AND/OR, не изменяя их поведения, Затем создайте составную политику (например, предлагаемую OP), которая проверяет измененные существующие политики.

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

AdminController: {
  adminDashboard: 'isAuthenticated',
},

ItemController: {
  findOne: 'isPublishedOrIsAuthenticated'
}

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

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

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

Обратите внимание, что нам нужно использовать знак triple-equals.

апи/политика/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();
};