Как стать автором
Обновить

Комментарии 26

Почему решили делать свой класс Authorization, а не встроиться в механизм политик?

Честно говоря, не помню. Модуль был написан довольно давно, но кажется что-то в этих политиках мне не понравилось…
Я попробую вспомнить и напишу вам.

Я поразмыслил немного, да и некоторые комментарии навели меня на определенные мысли.
Во-первых у меня было мало времени, т.к. нужно было срочно сделать вменяемую систему авторизации. \Gate:before() в этом контексте было приемлемым и очень элегантным решением — не нужно менять никаких предков, просто поставил и сразу все работает как нужно.
В связи с Policies сразу встал вопрос: как организовать иерархию операций? Тогда мне некогда было об этом думать серьезно.
Сегодня я поразмышлял на эту тему основательно и, в принципе, придумал способ встраивания. Но выглядит это как некоторое притягивание за уши… по крайней мере в нынешнем виденьи.
Конечно использование Policies несколько структурирует пермишины, но с другой стороны и усложняет восприятие целостной картины, а роли еще сильней усложнят ее. Вот и возникает вопрос: а нужно ли это усложнение для не слишком больших проектов? На мой взгляд — нет.

В свое время, когда понадобилось сделать rbac с ограничениями просмотра по ролям, гоняясь за универсальностью, отказался от понятия permissions и оставил только roles. В результате в мидлвале роута пишу что-то подобное `rbac:admin|manager&own`, что означает, что админ может видеть (и редактировать в случае update) все, а менеджер только принадлежащие ему сущности. Завел небольшую конвенцию, что в урле id будет называться с префиксом сущности, например `users/user_id` и в мидлваре проверяю, если встречается `own`, то есть ли у пользователя этот id в связи ->users(), если не нашлось, то в ->user(), иначе доступ запрещен. Здесь, конечно, предполагается преобразование этого самого user_id в users() и/или user() (что не всегда выглядит красиво в случае составных названий) и регулярный поход в базу и не сказать, что способ удобный, но избавляет от тонны permissions. :)
Как разрешить пользователю редактировать только свои статьи?

Roles, Bouncer — могут такое
Ожидал этого комментария :)
Да, свои могут. А, например, только статьи опубликованные за последний месяц?
Ну то есть, вы же понимаете, что там просто задействованы отношения, а здесь можно воротить что угодно.
Bouncer — может такое :)

Я очень внимательно изучил документацию и даже исходники (но не очень внимательно). И единственное, что я заметил


// You can also grant an ability only to a specific model
Bouncer::allow($user)->to('edit', $post);

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



но если вы покажете мне, что где-то при проверке вызывается замыкание или еще что-то в этом роде, то буду вам премного благодарен. А пока я все-таки продолжу настаивать, что Bouncer не может разрешить редактировать только статьи, опубликованные за последний месяц.

Извиняюсь, по первому взгляду на https://github.com/JosephSilber/bouncer/blob/master/src/Clipboard.php#L26 думал, что все позитивные проверки будут дальше проваливаться в polices или abilities.
Если бы автор там возвращал null, то всё так и работало бы.
Извиняюсь ещё раз за невнимательность)
Есть еще такая библиотека, которая легче и удобнее, чем эти монстры и умеет во вложенность /middleware с помощью встроенной механиики guard
То что в middleware можно перехватить request увидел. Но как в контроллере вызвать проверку permission и передать в проверку аргумент не понял.
Да, библиотеки, разработанные в компании Spatie, не один раз ускорили процесс разработки тех или иных модулей десятки тысяч разработчиков. И laravel-permission не исключение. Я лично применяю ее в своих проектах.

Но все же, у этой библиотеки не все так гладко получается, особенно когда в проекте больше одного guard-а.
Не всё гладко, но отдать дань spatie их решения очень сильно сопутствую вектору развития самого Laravel и садятся как влитые в проекты. Чего не скажешь о конкурентных решениях
Хм… а никаких встроенных механизмов для этого нет! И это очень странно, т.к. в большинстве систем пользователи генерируют какой-то контент (например статьи) и должны иметь возможность его редактировать, при этом не имея доступа к редактированию чужого.

Серьёзно? Прям таки нет

В том месте, откуда взята эта цитата, речь шла о больших, серьезных модулях и что в них нет такого простого и нужного механизма (передача параметра в функцию-проверку).
В Laravel такой механизм есть и именно благодаря его наличию существует опираясь на эту инфраструктуру данный модуль.
Но в Laravel нет ролей и это обесценивает Policies на 90%. Фактически они превращаются в фильтры — если я сделаю как написано в примере:


class PostPolicy {
    public function update(User $user, Post $post) {
        return $user->id === $post->user_id;
    }
}

то начну фильтровать всех пользователей. Как же мне тогда "менеджеру" разрешить редактировать все? Писать if? Куда? В код? Спасибо, не надо!
Или в метод update что-то вроде if($user->role=='manager')-elseif-elseif-else? Тоже увольте.
Вот и получается, что Policies есть, а применить их в реальном проекте затруднительно.

Спасибо. Хотелось бы увидеть такую-же статью о ABAC.

Да, но она никак не связана с Laravel.

Я думал вас интересует ABAC как концепция.

А что с ним? Он есть в списке.
Метод интересный. Но я сделал еще проще, гораздо. В провайдере Auth подключил полисы, в которых проверяю принадлежит ли пользователю контент. А в методе регистрации создаю роли типа такого:

// All privileges without limitation (for admin and manager).
        Gate::define('administer-users', function ($user) {
            return $user->role == 'manager' || $user->role == 'admin';
        });


Будет время, напишу об этом у себя в блоге: https://cleverman.org

Не вполне вас понял.


  1. Как вы реализуете последовательность проверок в полисях? (update-post → update-post-in-category → update-own-post)


  2. В примере вы определяете пермишин в котором на самом деле проверяете роли… это очень странно, т.е. фактически это эквивалент проверки ролей в коде. В любой статье по RBAC (и в этой тоже) написано, что проверять роли в коде это идеологически неверно. В коде нужно проверять разрешения (операции).
    Если в вашем примере administer-users больше не должны видеть какое-то меню, то нужно лезть в код и убирать can('administer-users') бог знает в скольких местах и в каком-нибудь обязательно забыть… В случае вышеописанного модуля необходимо просто в настройках изъять операцию из роли администратора.
Вы знаете, я много лет проработал с Друпал 7. Писал свои модули, свой функционал и т.д. Так вот, если бы увидели, как система ролей и прав сделана там, то у вас был бы нервный срыв и не проходящий ужас, еще очень долго. Поэтому, для мелких и чуть больше проектов, нет смысла вообще городить огород с разветвленными правами.

В полисах я сделал так:
 public function destroyPost(User $user, Post $post)
    {
        return $user->id == $post->user_id || Gate::check('administer-users');
    }

    public function editPost(User $user, Post $post)
    {
        return $user->id == $post->user_id || Gate::check('administer-users');
    }


Опять же таки, я решил пойти путем «с хвоста». Право 'administer-users' всегда дает доступ ко всему, у кого есть роль админ или менеджер. Есть еще право 'user-content' с ролью user (или любой другой, какую вы назначите). Вот именно оно всегда и везде проверяется. Если мне нужно всем владельцам закрыть возможность в редактировании своих постов, то не трогая контроллеры, можно просто вернуть false в полисе.

Если мне нужно вообще все запретить для авторизованных пользователей, то я верну false в проверке для права 'user-content'.

Плюс не стоит забывать еще тот момент, что мы работаем с фреймворком, и все бремя ответственности по разработке архитектуры ложится на программиста. Поэтому, было бы очень здорово продумать еще на начальной стадии разработки, что это за проект, каковы его цели, кому нужен доступ, а кому нет, что вообще должны делать пользователи, а что им нельзя. И исходя из этого уже создавать систему прав. А то, очень часто, вначале пилится проект, а потом уже думается, а что делать с ролями и правами. И начинается забег с костылями. Это сугубо мое личное мнение. Никому его не навязываю.
У меня есть один проект на Drupal 7, Best-House.org, так там в настройках прав есть 300!!! полей с доступом к тому или другому функционалу. Это все можно нащелкать мышкой (просмотр, редактирование, удаление, доступ к настройкам и т.д.) и это к каждому полю. После этого трэша, я сказал себе хватит. И упростил все до состоянии неотесанной доски.
Оставлю это здесь
Bouncer::allow($user)->to('edit', $post);
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории