These are chat archives for PHPixie/Hotline

11th
Nov 2015
Kostya
@KokaUA
Nov 11 2015 04:40

Практически закончил обдумывать acl, времени правда мало было свободно, вот и затянулось.
Вот встал весьма интересный вопрос, думаю как лучше поступить. Собственно вопрос, какой из вариантов выбрать.
1) Указывать в роутах в атрибутах превилегию, которая нужна для конкретного экшина.

  • Проверка доступа на уровне httpprocessor, как результат если нету доступа, мы даже не строем нужный процессор.
  • Можно указывать дефолтную превилегию для рядо роутов, например для всего бандла указать что требуется авторизация.
  • Для подобного рода роутов не самый удобный способ.
          'default' => [
              'type'     => 'pattern',
              'path'     => '(<processor>(/<action>))',
              'defaults' => [
                  'processor' => 'home',
                  'action'    => 'index',
                  'Permissions' => 'registrationRequired'
              ]
          ]
    Нужно будит часто явно указывать path для роутов что-бы указывать более конкретные превилегии.
    2) В каждом процессоре создавать метод rules() в котором указывать для какого экшина какая привилегия требуется.
  • Не нужно править роуты вроде '(<processor>(/<action>))' каждый раз при изменение превилегии к конкретному экшину.
  • Открыв процессор сразу видно какие превилегии в нем требуются для конкретного экшина.
  • Проще задавать несколько превилегий для одного экшина.
  • Проверка на уровне процессора, как результат его в любом случае строить понадобится.

Вот и встал вопрос, какой вариант лучше выбрать? Как вы щитаете?

Vadim Meling
@Linfuby
Nov 11 2015 05:26
Доброе утро. На мой взгляд правильнее было бы указывать в самом процессоре (вариант 2), так как многие процессоры могут строится от дефолтного роута, но с разными привилегиями, и в варианте 1, нужно будет прописывать каждый роут, что не очень хорошо, если процессоров будет хотя бы 30.
При этом нужно учитывать, что для каждого экшкна могут понадобиться свои привелегии
Например:
Процессор требует привелегии минимум менеджера
Экшн: editAction() требует права на редактирование
Экшн: deleteAction() требует права на удаление
При условии, что удалять имеют права только администраторы, а менеджеры имеют права редактировать.
Конечно при простом исполнении ACL ($role=='manager') такое не реализуется (Нужно создавать роли manager_edit, manager_delete и т.д.)
Тут интересная статья есть по поводу контроля доступа
http://habrahabr.ru/company/custis/blog/248649/
Kostya
@KokaUA
Nov 11 2015 05:59
@Linfuby Читал уже раньше, но спасибо.
Kostya
@KokaUA
Nov 11 2015 09:23

Интересный зверь получается в планах.
1) В базе хранится роли пользователей. one to many.
2) В базе хранятся имена привилегий, которые привязываются к ролям. many to many.
3) В приложении для каждой привилегии есть свой файл, который хранит набор правил, правила просто классы с простой логикой.

В процессе проверки доступа, мы сначала проверяем есть ли у нашего юзера конкретная привилегия, и если она есть то создаем её и проверяем выполненные ли все правила.
Таким образом мы можем составлять гибкие привилегии с условиями.
Например есть экшин удаления поста. Указываем привилегию DeletePost.
А уже в файле привилегии задаем ряд правил для конкретной привилегии.
Например

class DeletePost
{
    protected function rules()
    {
        $this->rule('AuthorPost')
        ->or()
        ->rule('roleAdmin');
    }
}

Таким образом мы проверяем если мы автор поста или у нас роль админ, то нам можно это делать.
Ну по сути в rule можно писать любую логику, для проверки доступа.
Кажется подобная реализация имеет право на жизнь

Kostya
@KokaUA
Nov 11 2015 09:34
Кстати как это чудо если что обозвать, rbac или acl
Roman Tsiupa
@dracony
Nov 11 2015 09:54
как то не оригинально)
cerberus =)
вот тебе кстати еще и 3й вариант подумать:
отдельный конфиг файл в котором задается отношение между набором аттрибутов запроса
и ролью
например
return array(
    array(
        'attributes' => array(
             'processor' => 'bla',
            'action' => 'foo'  
         ),
        'roles' => array('admin')
    )
);
на самом деле это получаеться даже не acl
а фаервол
потому что фильтрация идет на уровне пустить запрос/не пустить
acl это больше по части ограничения доступу к конкретным записям в базе
типа вот ту можно редактировать этому пользователю
а вот ту нет
Roman Tsiupa
@dracony
Nov 11 2015 10:01
кстати может сделать это не бандлом со своим HTTPProcessor, так как тогда оно будет работать только в своем бандле
можно сделать на глобальном уровне
подсунув его в HTTP
Kostya
@KokaUA
Nov 11 2015 10:03
Ну сама логика будит в отдельной либе. Ну а связка в пикси будит, или наследовать от protectedAction ну или в HTTPProcessor переопределять.
На щет конфига все равно, с динамическими роутами будут проблемы.
Roman Tsiupa
@dracony
Nov 11 2015 10:04
не будут если конфиг отдельный)
тогда можно в зависимости от аттрибута 'action' роль выбирать тоже_
    protected function dispatchProcessor()
    {
        $this->components()->yourAuth()->awesomeProcessor(parent::dispatchProcessor());
    }
Kostya
@KokaUA
Nov 11 2015 10:06
В смысле сделать конфиг типа фаервол, и в нем указывать процессор экшин и превилегию. А уже в httpprocessors читать конфиг и проверять?
yourAuth() не понадобится, авторизация то пикси будет.
Roman Tsiupa
@dracony
Nov 11 2015 10:07
protected $nextProcessor;
public function __construct($nextProcessor) {
    $this->nextProcessor = $nextProcessor;
}

public function process($request)
{
     if(//tvoja proverka) {
          return $this->nextProcessor->process($request);
     }

     return $http->responses->response("Frobidden", array(), 403);
}
yourAuth() - тот компонент фаервола в котором лежыт тот процессор что я ниже написал
тогда в конфиге фаервола можно даже бандл указывать
Kostya
@KokaUA
Nov 11 2015 10:10
Интересная мысля кстати, получается сделать проверку через субпроцессор
Roman Tsiupa
@dracony
Nov 11 2015 10:12
угу
вот с эти методом dispatchProcessor можо все что хочешь делать
на самом деле еще лучше так
Kostya
@KokaUA
Nov 11 2015 10:13
Он возвращает текущий процессор получается или следующий??
Кстати ты не заболел? Русскими буквами писать стал))
Roman Tsiupa
@dracony
Nov 11 2015 10:14
ти подменяешь dispatchProcessor на свой, но передаешь ему реальный dispatchProcessor как параметр
а уже он сам решает вызывать трушный процессор или возвратить ошыбку
ну сорри))) щас переключусь
))
кстати еще лучше сделать вот так:
public function dispatchProcessor()
{
                return $yourAuth->checkIsAllowedProcessor(
                    parent::dispatchProcessor(),
                    $this->forbiddenProcessor()
                );
}

public function forbiddenProcessor()
{
  ...
}
class CheckIsAllowedProcessor implements \PHPixie\Processors\Processor
{
    protected $allowedProcessor;
    protected $forbiddenProcessor;

     public function __construct($allowedProcessor, $forbiddenProcessor)
    {
        $this->....
     }

     public function process($request) {
          if(.....) {
                return $this->allowedProcessor->process($request);
           }
           return $this->forbiddenProcessor->process($request);
     }
}
то есто твой процессор просто делает развилку
Roman Tsiupa
@dracony
Nov 11 2015 10:19
в зависимости от того подходит пользователь или нет
тогда пользователь сможет сам переопределить forbiddenProcessor как он пожелает
(показать 403, сделать редирект на форму логина, итд)
Kostya
@KokaUA
Nov 11 2015 10:22
Окей, я только не совсем понял на щет dispatchProcessor() он вызывается перед вызомов process, а возвращает экземпляр процессора или request где имя и экшин заданы в атрибутах?
щас
        return $processors->catchException(
            $processors->chain(array(
                $this->requestProcessor(),
                $this->contextProcessor(),
                $processors->checkIsProcessable(
                    $this->builder->configuration()->httpProcessor(),
                    $this->dispatchProcessor(),
                    $this->notFoundProcessor()
                )
            )),
            $this->exceptionProcessor()
        );
это путь запроса
$this->requestProcessor() - в нем создаеться сам запрос
$this->contextProcessor() - он создает контексты
$processors->checkIsProcessable - проверяет существует ли нужный процессор (то есть есть ли что вызывать)
$this->builder->configuration()->httpProcessor() - собственно где проверять
$this->dispatchProcessor() - этот вызыветься когда процессор существует (то есть роут валиден)
$this->notFoundProcessor() - этот когда невалиден
то есть checkIsProcessable делает развилку
и все это обертываеться в $processors->catchException который ловит ошыбкы и рендерит с помощью процессора $this->exceptionProcessor()
по дефолту dispatchProcessor делает вот что:
        return $processors->chain(array(
            $this->builder->configuration()->httpProcessor(),
            $frameworkProcessors->httpNormalizeResponse(),
        ));
$this->builder->configuration()->httpProcessor() - вот это вызов цепочки процессоров которая уже ведет к бандлам и тд
$frameworkProcessors->httpNormalizeResponse() - превращает результат предыдущего в хттп респонс
Roman Tsiupa
@dracony
Nov 11 2015 10:28
то есть все манипуляции с запросом лучше всего как раз делать перед в dispatchProcessor
так как там уже все готово (контекст и тд)
фактически все что делает dispatchProcessor это вызов бандла
то есть но не "dispatchProcessor() он вызывается перед вызомов process"
а он сам и вызывает process
Kostya
@KokaUA
Nov 11 2015 10:32
Получается в httpprocessor мы делаем.
// Переопределяем вызов процессора
public function dispatchProcessor()
{
               // Возвращаем свой суб процессор
                return $yourAuth->checkIsAllowedProcessor(
                    parent::dispatchProcessor(),
                    $this->forbiddenProcessor()
                );
}
class CheckIsAllowedProcessor implements \PHPixie\Processors\Processor
{
    protected $allowedProcessor;
    protected $forbiddenProcessor;

     public function __construct($allowedProcessor, $forbiddenProcessor)
    {
        $this->....
     }
// переопределяем процесс,и если все ок то возвращаем process() с оригинального процессора, если нет то свой с для обработки ошибки
     public function process($request) {
          if(.....) {
                return $this->allowedProcessor->process($request);
           }
           return $this->forbiddenProcessor->process($request);
     }
}
Roman Tsiupa
@dracony
Nov 11 2015 10:33
это не в httpprocessor
в фреймворке
Kostya
@KokaUA
Nov 11 2015 10:35
Получается нам нужно будит переопределять Framework/src/PHPixie/Framework/HTTP.php и в билдере его создание?
Roman Tsiupa
@dracony
Nov 11 2015 10:36
угу
на то оно "глобально"
я думаю включить в проект пустой переопределенный HTTP
Kostya
@KokaUA
Nov 11 2015 10:37
А смысл пустой включать?
Roman Tsiupa
@dracony
Nov 11 2015 10:37
тогда надо будет только туда копипастнуть
=)
Kostya
@KokaUA
Nov 11 2015 10:37
А так сложно файл создать?
Roman Tsiupa
@dracony
Nov 11 2015 10:37
да нет))
но тогда он уже сразу будет и вбилдере прописан)
чтоб пользователем легче было =)
ну хз) может действительно лишнее))
Kostya
@KokaUA
Nov 11 2015 10:40
Ну вроди понял, но в общем dispatchProcessor() возвращает процессор в котором вызывается process? p.s.Покурю 4м.
:point_up: 11 ноября 2015 г., 11:23 что на это щет думаешь, кажется не плохо.
Kostya
@KokaUA
Nov 11 2015 10:47
Кстати сюда еще
public function __construct($allowedProcessor, $forbiddenProcessor)
{
$this->....
}
передавать билдер по идее нужно, что-бы получить доступ к компонентам
Roman Tsiupa
@dracony
Nov 11 2015 10:48
ну да, там зависимости какие тебе надо
но компоненты у тебе будет получать билдер твоего компонента
а не сам процессор
class DeletePost
{
    protected function rules()
    {
        $this->rule('AuthorPost')
        ->or()
        ->rule('roleAdmin');
    }
}
тут я чуть не понял зачем
ведь у нас DeletePost уже связан с этими ролями в базе
Kostya
@KokaUA
Nov 11 2015 10:50
rule не роль, а условие.
К примеру ->rule('EditSelfPost15MinAfterCreated')
Roman Tsiupa
@dracony
Nov 11 2015 10:51
а понял
ну хз я бы вот эти 15 минут проверял уже при валидации
если человек сабмитит форму слишком позно
тебе ж надо ему правильный месседж показать
а не 403
и не "у вас нет прав"
надо предусмотреть еще вариант где реально 3 роли на все приложение)
Kostya
@KokaUA
Nov 11 2015 10:53
Ну я к тому что сделать правила простыми условиями, что-бы их можно было применять в разных экшинах а не привязывать к валидации конкретного.
Roman Tsiupa
@dracony
Nov 11 2015 10:53
а то это наверное более часто встречаеться
Kostya
@KokaUA
Nov 11 2015 10:54
Если 3 роли то там и самому простую acl написать быстро можно без условий
Roman Tsiupa
@dracony
Nov 11 2015 10:54
надо еще примеров придумать чтобы лучше рассмотреть
Kostya
@KokaUA
Nov 11 2015 10:55
Ну примеры будут в процессе написания придумыватся, за одно и рефакторинг)
Ну вообще мне кажется на основе правил проверять привилегии, весьма неплохая затея.
Тогда не нужно будит куча привилегий, типа author|moderator|admin
Roman Tsiupa
@dracony
Nov 11 2015 10:56
угу)
можно еще у @Linfuby спросить
он там магазин строит) ему наверное точно надо
лан) я за работу)
чуть потмо буду)
Kostya
@KokaUA
Nov 11 2015 10:58
@dracony Ну с тем что-бы задавать в процессорах привилегии посоветовал, посмотрим что он про отдельный конфиг скажет.
Roman Tsiupa
@dracony
Nov 11 2015 10:58
еще можно сюда помотреть
это платный компонент к ларавелке для всего этого
даже есть sentinel-expired-permissions для вот таких 15 минут
но там ваервола как я понял нет
Kostya
@KokaUA
Nov 11 2015 11:02
Ну как делать вроде определился. Там в процессе уже если что буду уточнять.
Кстати как думаешь выкладывать простенький бандл авторизации или нет? По сути простой бандлы где только свои шаблоны страниц при желании указывать.
Roman Tsiupa
@dracony
Nov 11 2015 11:07
ну можно включить пару шаблонов в бутстрап 3 бандл)
или даже с авторизацией туда
а может и отдельно =) кому-то точно пригодится =)
Kostya
@KokaUA
Nov 11 2015 11:09
Ладно будит свободное время, напишу readme к этому делу.
p.s.Весело но мне сложнее написать инструкцию чем сам код)))
Roman Tsiupa
@dracony
Nov 11 2015 11:10
=))
мне тоже))
поэтому доков мало)
Kostya
@KokaUA
Nov 11 2015 11:10
Кстати чем ты md файлы редачишь?
Roman Tsiupa
@dracony
Nov 11 2015 11:10
ничем
ну типа тем же редактором что код
я там особо хитрое ничего не использую
Kostya
@KokaUA
Nov 11 2015 11:11
хз мне в редакторе не удобно, обычно в https://stackedit.io/ стараюсь.
Roman Tsiupa
@dracony
Nov 11 2015 11:11
прикольно =)
ну правда
я когда азпускаю сайт на локалке
то при обновлении страницы он автоматически парсит
и я сразу вижу что написал
Kostya
@KokaUA
Nov 11 2015 11:12
Как я помню злился когда после получаса редактирования, у меня браузер завис и все пропало
Кстати нужно наверно будит поискать добровольца что-бы перевел мои описания на английский, ибо я бред напишу)).
@dracony Кстати если не сложно посмотри https://github.com/KokaUA/flash-messages/tree/master/src кажется все весьма не плохо переписал.
Roman Tsiupa
@dracony
Nov 11 2015 11:17
посмотрю вечером)
надо еще что-то на работе сделать до обеда)))