Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

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/migrations

Four 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/init

The 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.

Thanks for reading!

Donate to the site — we work hard for you.