Roles and permissions (RBAC)
When there are several kinds of users with different rights (an author, an editor, an administrator), isGuest checks are no longer enough. RBAC (role-based access control) describes rights with two notions: a permission is a single action such as "update a post", and a role is a set of permissions assigned to a user.
Setup
The authManager component is responsible for RBAC. Add it to config/web.php and to config/console.php:
// config/web.php and config/console.php
'components' => [
'authManager' => [
'class' => 'yii\rbac\DbManager',
],
],DbManager stores roles in the database. Its tables are created by a ready-made migration:
php yii migrate --migrationPath=@yii/rbac/migrationsFour tables with names starting with auth_ appear in the database.
Creating roles and permissions
Roles are created once, with a console command. Create the file commands/RbacController.php:
// commands/RbacController.php
namespace app\commands;
use Yii;
use yii\console\Controller;
class RbacController extends Controller
{
public function actionInit(): void
{
$auth = Yii::$app->authManager;
$auth->removeAll();
$createPost = $auth->createPermission('createPost');
$auth->add($createPost);
$deletePost = $auth->createPermission('deletePost');
$auth->add($deletePost);
$author = $auth->createRole('author');
$auth->add($author);
$auth->addChild($author, $createPost);
$admin = $auth->createRole('admin');
$auth->add($admin);
$auth->addChild($admin, $author);
$auth->addChild($admin, $deletePost);
}
}php yii rbac/initThe command writes two permissions and two roles to the database. addChild() nests one into another: an author may create posts, and an administrator gets everything an author can do plus deleting.
Assigning a role to a user
$auth = Yii::$app->authManager;
$auth->assign($auth->getRole('author'), $user->id);The call links a role to a user number. It is convenient to do this right after registration. A role is taken away with $auth->revoke($role, $user->id).
Checking in code
public function actionDelete(int $id)
{
if (!Yii::$app->user->can('deletePost')) {
throw new ForbiddenHttpException('Only an administrator may delete posts.');
}
// deleting
}The can() method returns true if the current user has the permission, directly or through a role. An author gets a 403 error, an administrator deletes the post. Check permissions, not roles: then the content of roles can change without touching the code.
Checking in a filter
AccessControl understands role and permission names in the roles key:
'rules' => [
[
'allow' => true,
'actions' => ['create'],
'roles' => ['createPost'],
],
[
'allow' => true,
'actions' => ['delete'],
'roles' => ['deletePost'],
],
],The filter calls can() itself, so the check in the action need not be repeated.
Checking in a view
<?php
// views/post/view.php
use yii\helpers\Html;
?>
<?php if (Yii::$app->user->can('deletePost')): ?>
<?= Html::a('Delete', ['post/delete', 'id' => $post->id], ['data-method' => 'post']) ?>
<?php endif; ?>Only an administrator sees the delete button.
Common mistake
If the authManager component is not described in the settings, can() does not raise an error but simply returns false, and access is closed to everyone, including the administrator. Check that the component is added to both configuration files and that the role is really assigned to the user.