FabrizioCaldarelli
8/29/2019 - 8:54 PM

Yii2 RBAC

<?php
namespace console\controllers;

use Yii;
use yii\console\Controller;

class RbacController extends Controller
{
    private $auth;

    private function createPermission($name, $roles, $rule = null)
    {
        $p = $this->auth->createPermission($name);
        $p->description = $name;
        if($rule != null) $p->ruleName = $rule->name;
        $this->auth->add($p);
        foreach($roles as $role) $this->auth->addChild($role, $p);
        return $p;
    }

    private function createRule($ruleClass)
    {
        $rule = new $ruleClass;
        $this->auth->add($rule);
        return $rule;
    }

    public function actionInit()
    {
        $auth = Yii::$app->authManager;

        $this->auth = $auth;

        $auth->removeAll();

        // RUOLO superadmin
        $roleSuperadmin = $auth->createRole('superadmin');
        $auth->add($roleSuperadmin);

        // RUOLO company_admin
        $roleCompanyAdmin = $auth->createRole('company_admin');
        $auth->add($roleCompanyAdmin);

        // Rule
        $roomsRule = $this->createRule(\backend\models\rule\RoomsRule::className());

        // -----------
        // BACKEND - ROOMS
        // -----------
        $this->createPermission('backend.rooms.create', [$roleCompanyAdmin], $roomsRule);
        $this->createPermission('backend.rooms.view',   [$roleCompanyAdmin], $roomsRule);
        $this->createPermission('backend.rooms.update', [$roleCompanyAdmin], $roomsRule);
        $this->createPermission('backend.rooms.delete', [$roleCompanyAdmin], $roomsRule);
        $this->createPermission('backend.rooms.index',  [$roleCompanyAdmin], $roomsRule);

        // Imposta tutti gli utenti
		foreach(\common\models\User::find()->all() as $u)
		{
			$u->configureRbac();
		}


		$auth->addChild($roleSuperadmin, $roleCompanyAdmin);

    }
}
?>
<?php
class User extends ActiveRecord implements IdentityInterface
{
    // Access
    const ACCESS_SUPERADMIN = 'superadmin';
    const ACCESS_COMPANY_ADMIN = 'company_admin';

    public function configureRbac()
    {
        $auth = \Yii::$app->authManager;

        // Remove all roles
        $auth->revokeAll($this->id);

        if($this->access!=null)
        {
            $auth->assign($auth->getRole($this->access), $this->id);
        }
    }
<?php
class RoomsController extends BaseController
{
    /**
     * @inheritdoc
     */
    public function behaviors()
    {
        return \yii\helpers\ArrayHelper::merge(parent::behaviors(), [
            'access' => new \yii\helpers\ReplaceArrayValue([
                'class' => \yii\filters\AccessControl::className(),
                'rules' => [

                    [ 'allow' => true, 'actions' => ['create'], 'roles' => ['backend.rooms.create'], ],
                    [ 'allow' => true, 'actions' => ['delete'], 'roles' => ['backend.rooms.delete'], 'roleParams' => ['id' => Yii::$app->request->get('id')] ],
                    [ 'allow' => true, 'actions' => ['index'],  'roles' => ['backend.rooms.index'], ],
                    [ 'allow' => true, 'actions' => ['update'], 'roles' => ['backend.rooms.update'], 'roleParams' => ['id' => Yii::$app->request->get('id')] ],
                    [ 'allow' => true, 'actions' => ['view'],   'roles' => ['backend.rooms.view'], 'roleParams' => ['id' => Yii::$app->request->get('id')] ],

                    [ 'allow' => true, 'actions' => ['qrcode'] ],

                ],
            ]),
        ]);
    }
<?php
namespace backend\models\rule;

use yii\rbac\Rule;
use common\models\User;

/**
 * RoomsRule
 */
class RoomsRule extends Rule
{
    public $name = 'backend.rooms';

    /**
     * @param string|int $user the user ID.
     * @param Item $item the role or permission that this rule is associated with
     * @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)
     {
         $retVal = false;

         $userModel = User::findOne($user);

         if($item->name == $this->name.'.index')
         {
             $retVal = true;
         }
         else if($item->name == $this->name.'.check-in-out')
         {
             $retVal = true;
         }
         else if($item->name == $this->name.'.create')
         {
            $retVal = true;
         }
         else
         {
            if(isset($params['id']))
            {
                if($userModel->access == \common\models\User::ACCESS_HOTEL)
                {
                    $room = \common\models\Room::findOne($params['id']);
                    $retVal = ($userModel->hotel_id == $room->hotel_id);
                }
                else
                {
                    $retVal = true;
                }
            }
        }

         return $retVal;
     }
}