Как организовать RBAC в Yii2 для контроля помимо доступов еще и доступ по языку к контенту?
В таком варианте очень неудобно использовать permission для разграничения прав, так как permission можно привязать только к группе пользователя, но не к самому пользователю.
Странно, у меня все получалось:$authManager = Yii::$app->authManager;
$userID = 1;
$permission = $authManager->getPermission('language_ru');
$authManager->assign($permission, $userID);
Таким образом пользователю можно сколь угодно прав выдать.
Да, это так, но есть одно "но", пытаюсь автоматизировать проверку правил, из замечательного проекта https://github.com/trntv/yii2-starter-kit взят GlobalAccessBehavior, который задает глобально права доступы на экшины.
Вот как это выглядит
Есть консольная команда, которая пробегается по всем модулям админки, собирает контроллеры и все экшины, так же пробегается по контроллерам внутри админки и делает то же самое.
правила составляются следующим образом
backend___
Далее это все привязывается к роли.
Все работает отлично, но когда возникает ситуация, когда конкретному пользователю (а их может быть и десяток) нужно отключить определенный контроллер или даже экшн, то в случае с использованием permission, его не понимает AccessControl, так как доступ задать можно для роли.
В случае использования permission, подобную проверку проводить нужно в методе контроллера beforeAction public function beforeAction() {
        $permission = 'backend_' . Yii::$app->controller->module->id . '_' . Yii::$app->controller->id . '_' . Yii::$app->controller->action->id;

        if (!Yii::$app->user->can($permission)) {
            throw new yii\web\ForbiddenHttpException;
        }
    }
В таком случае, это необходимо реализовывать в базовом контроллере.
Еще есть вариант все же заставить понимать AccessRule permission а не только роли, немного его переопределив<?php

namespace common\behaviors;
use yii\base\Action;
use yii\filters\AccessRule;
use yii\helpers\Inflector;


/**
 * @class   AccessRuleCustom
 *
 * @package common\behaviors
 * @author  Sergey Doniy <doniysa@gmail.com>
 */
class AccessRuleCustom extends AccessRule
{
    public $checkPermissions = true;
    public $prefix = 'backend_';

    public function allows($action, $user, $request)
    {
        return parent::allows($action, $user, $request) || $this->hasPermission($action);
    }

    protected function hasPermission(Action $action) {
        if (!$this->checkPermissions)
            return false;

        $permission = $this->prefix . $action->controller->module->id . '_' . $action->controller->id . '_' . Inflector::id2camel($action->id);

        return \Yii::$app->user->can($permission);

    }

}
Во втором варианте все работает, во всяком случае permission проходят, и все ок. Остановился в конечном счете на этом варианте - у пользователя всего одна роль, к которой привязываются дефолтные пермишины, а отдельные привязываются непосредственно к пользователю.
Для того, чтобы не хардкодить с языками и ролями по ним, отдельно создал две таблицы
auth_assignment_language_item
которая хранит перечень языков - т.е. по сути permission для языка
и таблицу
auth_assignment_language
Которая в свою очередь хранит привязку отдельного пользователя к языку
и таблицу auth_assignment_language_child
Для привязки роли к языку
Расширен функционал RBAC для управления еще и языками (так как rbac храню в БД, то расширен DbManager)
В отдельные таблицы вынес для того, чтобы логика данных была прозрачна, что позволило достаточно быстро накидать gui-интерфейс для управления правами на конкретный язык.
Это я описал свою реализацию поднятой темы.
Но все равно не уверен, что нет более лучших подходов для реализации.
Интересно будет почитать, кто как решал подобные задачи и какими методами - сразу уточню - система пишется не под один проект, это внутренняя CMS компании и hot-фиксы и пинание системы под конкретный случай усложнит разработку следующих проектов, поэтому приходится по максимуму (насколько позволяет время) делать ее гибкой и расширяемой для большинства задач, которые перед разработчиками ставятся.