hostadmin
@hostadmin

Как разрулить через RBAC установку прав в зависимости от выбранной «сущности»?

Не могу придумать как правильно использовать RBAC для такой ситуации (и нужно ли его вообще здесь использовать).

Приведу пример работы.
Сервис делится на два условных "Кабинета" - для Покупателей и для Продавцов (Директора и Сотрудников компании).

Имеется база "Компании", с компаниями связаны разнообразные сущности - "Категории", "Товары" и пр.

У каждой компании есть Директор (имеет доступ в интерфейс для Продавцов и может управлять всей компанией - редактировать товары, категории и пр.), Сотрудником ( имеет доступ в интерфейс для Продавцов и может делать только то, что было разрешено Директором). Доступ к данным Компаний могут иметь только Покупатели, которым Директор или Сотрудник дали доступ.
При этом один и тот же пользователь может быть у разных компаний в разных ролях (у одной Директором, у другой Сотрудником, у третьей Покупателем), и даже в одной и той же Компании у пользователя могут быть роли Директора/Сотрудника и Покупателя одновременно.

5c2fbde52dba9620059699.png

Получается, что основное решение о том, какие роли имеются у пользователя, принимается на уровне Компании. Пользователь выбирает Компанию из списка тех, к которым у него есть доступ и в зависимости от выбранной компании он получает определенные права.

Все пользователи хранятся в общей таблице users и связываются с компаниями через промежуточную таблицу users2company.

Как лучше организовать права при такой схеме?

ПС. Система построена на Yii2, но, думаю, что принцип RBAC'а у Yii2 и Laravel довольно спохожий.
  • Вопрос задан
  • 110 просмотров
Пригласить эксперта
Ответы на вопрос 2
inoise
@inoise
Solution Architect, AWS Certified, Serverless
это называется bizRule) то есть кастомный обработчик, привязанный к Permission
Ответ написан
@jazzus
Не знаю насколько поможет мой опыт т.к. я сам только учусь) но я сделал так:

3 таблицы

Roles
role_perms
perms

Связываем роли и пермы через manytomany.

В AuthServiceProvider прописываем правила. Типа

Gate::define('CREATE_PRODUCT', function($user){
          return $user->canDo(3);
        });

На каждый пермишен или автоматизировать.

В модели User делаем проверку

public function canDo($perm_id) {
      foreach ($this->roles as $role) {
        foreach ($role->perms as $perm) {
          if ($perm_id==$perm->id) {
            return true; }}}}

Теперь подключив Gate к контроллеру можно делать перед выполнением метода.

if (Gate::denies('CREATE_PRODUCT ')) {
               abort(404);
             }

И в шаблоне

@can ('CREATE_PRODUCT’)
Код создания продукта
@endcan

Все. Можно ограничить еще в роутах (через мидделварь, эт о просто). Что там еще? Назначать роли в контроллерах просто. Типа

If($user->isDirector() and $company->type(‘it’))
{
$user->roles()->attach($id);
}

Attach делает запись в промежуточной таблице
Type – метод у компаний, который ищет по массиву типов
isDirector - метод у юзера типа

public function isDirector()
{
if роль == director return true;
return false;
}

Или получать роль через имя

public function getRole($name)
    {
        return $this->roles()->where('name', $name);
    }

Но лучше (для меня) создать дату с ролями в модели User (типа констант) и искать по id, а не по name(я так сделал)

Что касается разных ролей для каждой компании. Можно связать компании роли и юзеры и получать права записью типа
$user->company($id)->roles();
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы