Права пользователей в зависимости от сущности.
Права пользователей в зависимости от сущности.
Не могу придумать как правильно использовать RBAC для такой ситуации (и нужно ли его вообще здесь использовать).
Приведу пример работы.
Сервис делится на два условных "Кабинета" - для Покупателей и для Продавцов (Директора и Сотрудников компании).
Имеется база "Компании", с компаниями связаны разнообразные сущности - "Категории", "Товары" и пр.
У каждой компании есть Директор (имеет доступ в интерфейс для Продавцов и может управлять всей компанией - редактировать товары, категории и пр.), Сотрудником ( имеет доступ в интерфейс для Продавцов и может делать только то, что было разрешено Директором). Доступ к данным Компаний могут иметь только Покупатели, которым Директор или Сотрудник дали доступ.
При этом один и тот же пользователь может быть у разных компаний в разных ролях (у одной Директором, у другой Сотрудником, у третьей Покупателем), и даже в одной и той же Компании у пользователя могут быть роли Директора/Сотрудника и Покупателя одновременно.
Получается, что основное решение о том, какие роли имеются у пользователя, принимается на уровне Компании. Пользователь выбирает Компанию из списка тех, к которым у него есть доступ и в зависимости от выбранной компании он получает определенные права.
Все пользователи хранятся в общей таблице users и связываются с компаниями через промежуточную таблицу users2company.
Как лучше организовать права при такой схеме?
Приведу пример работы.
Сервис делится на два условных "Кабинета" - для Покупателей и для Продавцов (Директора и Сотрудников компании).
Имеется база "Компании", с компаниями связаны разнообразные сущности - "Категории", "Товары" и пр.
У каждой компании есть Директор (имеет доступ в интерфейс для Продавцов и может управлять всей компанией - редактировать товары, категории и пр.), Сотрудником ( имеет доступ в интерфейс для Продавцов и может делать только то, что было разрешено Директором). Доступ к данным Компаний могут иметь только Покупатели, которым Директор или Сотрудник дали доступ.
При этом один и тот же пользователь может быть у разных компаний в разных ролях (у одной Директором, у другой Сотрудником, у третьей Покупателем), и даже в одной и той же Компании у пользователя могут быть роли Директора/Сотрудника и Покупателя одновременно.
Получается, что основное решение о том, какие роли имеются у пользователя, принимается на уровне Компании. Пользователь выбирает Компанию из списка тех, к которым у него есть доступ и в зависимости от выбранной компании он получает определенные права.
Все пользователи хранятся в общей таблице users и связываются с компаниями через промежуточную таблицу users2company.
Как лучше организовать права при такой схеме?
Re: Права пользователей в зависимости от сущности.
Спрограммируйте свои Rule со всей этой логикой.
Re: Права пользователей в зависимости от сущности.
Не понимаю, с чего начинать.
Re: Права пользователей в зависимости от сущности.
Ну или я пока понимаю вот такую схему, поправьте, если что не так.
Берем мануал и видим, что мы можем наклепать своих правил правил и рулить ими в зависимости от своих пожеланий. Значит делаем:
Код: Выделить всё
namespace app\rbac;
use yii\rbac\Rule;
class DirectorRule extends Rule
{
public $name = 'isDirector';
/**
* @param string|int $user the user ID.
* @param Item $item the role or permission that this rule is associated width.
* @param array $params parameters passed to ManagerInterface::checkAccess().
* @return bool a value indicating whether the rule permits the role or permission it is associated with.
*/
public function execute($user, $item, $params)
{
return isset($params['company']) ? $params['company']->users2company->user_id == $user : false;
}
}
Код: Выделить всё
namespace app\commands;
use Yii;
use yii\console\Controller;
class RbacController extends Controller
{
public function actionInit()
{
$auth = Yii::$app->authManager;
// add the rule
$rule = new \app\rbac\DirectorRule;
$auth->add($rule);
// добавляем разрешение "updateOwnPost" и привязываем к нему правило.
$updateAllInCompany= $auth->createPermission('updateAllInCompany');
$updateAllInCompany->description = 'Update all data in the Company';
$updateAllInCompany->ruleName = $rule->name;
$auth->add($updateAllInCompany);
// добавляем роль "director" и даём роли разрешение "updateAllInCompany"
$director = $auth->createRole('director');
$auth->add($director );
$auth->addChild($director , $updateAllInCompany);
// Назначение ролей пользователям. 1 и 2 это IDs возвращаемые IdentityInterface::getId()
// обычно реализуемый в модели User.
$auth->assign($director , 2);
}
}
Код: Выделить всё
if (\Yii::$app->user->can('updateAllInCompany', ['company' => $company])) {
// update company
}
Правильно?
Последний раз редактировалось buba 2019.01.05, 18:53, всего редактировалось 1 раз.
Re: Права пользователей в зависимости от сущности.
А ведь получается, что аналогичным образом я могу использовать matchCallback, но тогда будет куча дублирующего кода.
Или подход с matchCallback тут не подходит?
Или подход с matchCallback тут не подходит?
Re: Права пользователей в зависимости от сущности.
Правильно. А matchCallback работает только в AccessControl.
Re: Права пользователей в зависимости от сущности.
А как лучше организовать функционал, чтобы Директор мог Сотрудникам назначать свои права? Забивать все возможные варианты в RBAC или городить свою систему проверки прав?
Re: Права пользователей в зависимости от сущности.
Проще свою систему. И закинуть её внутрь Rule.
Re: Права пользователей в зависимости от сущности.
Т.е. по принципу как выше?
Типа такого?
Код: Выделить всё
namespace app\rbac;
use yii\rbac\Rule;
class SotrudnikRule extends Rule
{
public $name = 'SotrudnikRules';
/**
* @param string|int $user the user ID.
* @param Item $item the role or permission that this rule is associated width.
* @param array $params parameters passed to ManagerInterface::checkAccess().
* @return bool a value indicating whether the rule permits the role or permission it is associated with.
*/
public function execute($user, $item, $params)
{
//здесь адов код по проверке прав у конкретного юзера
}
}
Re: Права пользователей в зависимости от сущности.
Всё вникаю в RBAC и начинает казаться, что описанный, мной выше, подход не очень удобный. Получается, что у меня динамические правила (которые включаются/выключаются в зависимости от статуса пользователя, т.е. фактически роли пользователя), а правильнее было бы динамически назначать роль пользователю. Но что-то не могу найти вариантов решений как динамически назначить роль пользователю.
Re: Права пользователей в зависимости от сущности.
Не зацикливайтесь на ролях фреймворка. Не делайте в RbacController ролей директора и прочих. Сделайте для всех одну статическую фреймворковскую роль user и спрограммируйте всю свою логику в разных Permission к ней.
Код: Выделить всё
class EditOwnCompanyRule extends Rule
{
public fubction execute($user, $item, $params)
{
$company = $params['company'];
return $company->canBeEditedByUser($user->id);
}
}
Код: Выделить всё
if (Yii::$app->user->can('edit-company', $company) ...
Re: Права пользователей в зависимости от сущности.
Но почему, в чём выгода?
Удобней же сделать сразу роли, вроде и "идеологически" правильней всю работу на фреймворк свалить ну и управлять проще - сделал админку и рули права.
Удобней же сделать сразу роли, вроде и "идеологически" правильней всю работу на фреймворк свалить ну и управлять проще - сделал админку и рули права.
Re: Права пользователей в зависимости от сущности.
Не, это статически получается. А мне надо динамически, чтобы если человек хочет получить доступ к данной Компании-1 у него одна роль, а для Компании-2 другая роль.
Вроде нашёл подходящее решение - https://www.yiiframework.com/doc/guide/ ... -umolcaniu , но смущает то, что в методе execute надо, фактически, написать всю иерархию имеющихся ролей
Но зачем мы тогда указываем иерархию при создании этих ролей? У нас и так author идёт потомком от admin, но в методе execute мы это опять перепроверяем, а если у нас 10 ролей, то и 10 проверок.Обратите внимание, так как "author" добавлен как дочерняя роль к "admin", следовательно в реализации метода execute() класса правила вы должны учитывать эту иерархию. Именно поэтому для роли "author" метод execute() вернёт истину, если пользователь принадлежит к группам 1 или 2 (это означает, что пользователь находится в группе администраторов или авторов)
Re: Права пользователей в зависимости от сущности.
Потому, что фреймворк умеет только assign($director, $user) статически, а вам нужно сделать assign($director, $user, $company) динамически.
Re: Права пользователей в зависимости от сущности.
Re: Права пользователей в зависимости от сущности.
В том-то и дело, что в админке это сохраняется пока я (админ) не поменяю. А роли у пользователя должны меняться в зависимости от запрошенного контроллера и/или экшена.
Т.е. на странице
/company/1/index пользователь Директор, а на странице /company/2/index он уже Покупатель.
Re: Права пользователей в зависимости от сущности.
Вы путаете ваши роли, как текущий выбор пользователя, и роли в понятиях RBAC, как то что он в принципе сможет вообще делать.
Он будет Директором на странице /company/1/index если ,например, одна из ролей, которая ему присвоена, владеет разрешением director_access_to_company_id
Re: Права пользователей в зависимости от сущности.
Ну да, только с таким подходом смысла в ролях нет. Всё можно будет разруливать через разрешения. А это, кмк, не очень удобное решение, т.к. придется для каждого "типа" пользователя городить свои конструкции с разрешенными действиями.maleks писал(а): ↑2019.01.07, 15:59Вы путаете ваши роли, как текущий выбор пользователя, и роли в понятиях RBAC, как то что он в принципе сможет вообще делать.Он будет Директором на странице /company/1/index если ,например, одна из ролей, которая ему присвоена, владеет разрешением director_access_to_company_id
Мне кажется, правильнее было бы отталкиваться от стандартного RBAC'а, с его разрешениями и иерархией. Тогда проще добавлять новые роли (если понадобятся) и новые разрешения. И будет всего один чёрный ящик - динамическое назначение роли пользователя.