📜 ⬆️ ⬇️

Yii2 RBAC setup

Task


Configure the use of RBAC in Yii2.

Conditions


List of possible roles:


Presetting


app/config/console.php
 'components' => [ // ... 'authManager' => [ 'class' => 'yii\rbac\PhpManager', ], // ... ], 

')
app/config/web.php
 'components' => [ // ... 'authManager' => [ 'class' => 'yii\rbac\PhpManager', 'defaultRoles' => ['admin', 'BRAND', 'TALENT'], //    "guest", ..         UserExt ], // ... ], 


Create the @app/rbac - it will contain permissions and rules.

Creating permissions


In the @app/commands directory create a controller that will generate an array of permissions:
app/commands/RbacController.php
 <?php namespace app\commands; use Yii; use yii\console\Controller; use \app\rbac\UserGroupRule; class RbacController extends Controller { public function actionInit() { $authManager = \Yii::$app->authManager; // Create roles $guest = $authManager->createRole('guest'); $brand = $authManager->createRole('BRAND'); $talent = $authManager->createRole('TALENT'); $admin = $authManager->createRole('admin'); // Create simple, based on action{$NAME} permissions $login = $authManager->createPermission('login'); $logout = $authManager->createPermission('logout'); $error = $authManager->createPermission('error'); $signUp = $authManager->createPermission('sign-up'); $index = $authManager->createPermission('index'); $view = $authManager->createPermission('view'); $update = $authManager->createPermission('update'); $delete = $authManager->createPermission('delete'); // Add permissions in Yii::$app->authManager $authManager->add($login); $authManager->add($logout); $authManager->add($error); $authManager->add($signUp); $authManager->add($index); $authManager->add($view); $authManager->add($update); $authManager->add($delete); // Add rule, based on UserExt->group === $user->group $userGroupRule = new UserGroupRule(); $authManager->add($userGroupRule); // Add rule "UserGroupRule" in roles $guest->ruleName = $userGroupRule->name; $brand->ruleName = $userGroupRule->name; $talent->ruleName = $userGroupRule->name; $admin->ruleName = $userGroupRule->name; // Add roles in Yii::$app->authManager $authManager->add($guest); $authManager->add($brand); $authManager->add($talent); $authManager->add($admin); // Add permission-per-role in Yii::$app->authManager // Guest $authManager->addChild($guest, $login); $authManager->addChild($guest, $logout); $authManager->addChild($guest, $error); $authManager->addChild($guest, $signUp); $authManager->addChild($guest, $index); $authManager->addChild($guest, $view); // BRAND $authManager->addChild($brand, $update); $authManager->addChild($brand, $guest); // TALENT $authManager->addChild($talent, $update); $authManager->addChild($talent, $guest); // Admin $authManager->addChild($admin, $delete); $authManager->addChild($admin, $talent); $authManager->addChild($admin, $brand); } } 


The UserGroupRule class is responsible for checking the equality of the role of the current user, the role specified in the array of permissions. By this we avoid problems with assigning a role to a user by his ID.
app/rbac/UserGroupRule.php
 <?php namespace app\rbac; use Yii; use yii\rbac\Rule; class UserGroupRule extends Rule { public $name = 'userGroup'; public function execute($user, $item, $params) { if (!\Yii::$app->user->isGuest) { $group = \Yii::$app->user->identity->group; if ($item->name === 'admin') { return $group == 'admin'; } elseif ($item->name === 'BRAND') { return $group == 'admin' || $group == 'BRAND'; } elseif ($item->name === 'TALENT') { return $group == 'admin' || $group == 'TALENT'; } } return true; } } 


Now you can remove the access rule in the controller from the behaviors method:
app/controllers/SiteController.php
 public function behaviors() { return [ // ... 'access' => [ 'class' => AccessControl::className(), 'only' => ['logout'], 'rules' => [ [ 'actions' => ['logout'], 'allow' => true, 'roles' => ['@'], ], ], ], // ... ]; } 


Access check


Method 1 - in the controller method:
app/controllers/SiteController.php
 public function actionAbout() { if (!\Yii::$app->user->can('about')) { throw new ForbiddenHttpException('Access denied'); } return $this->render('about'); } 


Method 2 - register beforeAction in order not to write "if !\Yii::$app->user->can" in each method:
app/controllers/SiteController.php
 public function beforeAction($action) { if (parent::beforeAction($action)) { if (!\Yii::$app->user->can($action->id)) { throw new ForbiddenHttpException('Access denied'); } return true; } else { return false; } } 


Generating Permission Files


To generate a file with an array of permissions, run the following command in the project root:
Attention!
Before executing this command, you must delete the @app/rbac/items.php and @app/rbac/rules.php to avoid merge conflicts

 ./yii rbac/init 


Two files should appear in the @app/rbac directory:
app/rbac/items.php
 <?php return [ 'login' => [ 'type' => 2, ], 'logout' => [ 'type' => 2, ], 'error' => [ 'type' => 2, ], 'sign-up' => [ 'type' => 2, ], 'index' => [ 'type' => 2, ], 'view' => [ 'type' => 2, ], 'update' => [ 'type' => 2, ], 'delete' => [ 'type' => 2, ], 'guest' => [ 'type' => 1, 'ruleName' => 'userGroup', 'children' => [ 'login', 'logout', 'error', 'sign-up', 'index', 'view', ], ], 'BRAND' => [ 'type' => 1, 'ruleName' => 'userGroup', 'children' => [ 'update', 'guest', ], ], 'TALENT' => [ 'type' => 1, 'ruleName' => 'userGroup', 'children' => [ 'update', 'guest', ], ], 'admin' => [ 'type' => 1, 'children' => [ 'delete', 'TALENT', 'BRAND', ], ], ]; 


app/rbac/rules.php
 <?php return [ 'userGroup' => 'O:22:"app\\rbac\\UserGroupRule":3:{s:4:"name";s:9:"userGroup";s:9:"createdAt";N;s:9:"updatedAt";N;}', ]; 


Extended Rule for Permissions


For example, it is necessary to prohibit users from editing (updating) not their profile. For this you need an extended rule:
app/rbac/UserProfileOwnerRule.php
 <?php namespace app\rbac; use yii\rbac\Rule; use yii\rbac\Item; class UserProfileOwnerRule extends Rule { public $name = 'isProfileOwner'; /** * @param string|integer $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 boolean a value indicating whether the rule permits the role or permission it is associated with. */ public function execute($user, $item, $params) { if (\Yii::$app->user->identity->group == 'admin') { return true; } return isset($params['profileId']) ? \Yii::$app->user->id == $params['profileId'] : false; } } 


In the file @app/rbac/RbacController.php add:
app/rbac/RbacController.php
 use \app\rbac\UserProfileOwnerRule; // add the rule $userProfileOwnerRule = new UserProfileOwnerRule(); $authManager->add($userProfileOwnerRule); $updateOwnProfile = $authManager->createPermission('updateOwnProfile'); $updateOwnProfile->ruleName = $userProfileOwnerRule->name; $authManager->add($updateOwnProfile); $authManager->addChild($brand, $updateOwnProfile); $authManager->addChild($talent, $updateOwnProfile); 


Test access in the controller method:
app/controllers/UsersController.php
 public function actionUpdate($id) { if (!\Yii::$app->user->can('updateOwnProfile', ['profileId' => \Yii::$app->user->id])) { throw new ForbiddenHttpException('Access denied'); } // ... } 

Source: https://habr.com/ru/post/235485/


All Articles