Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Yii Framework 2.0 Role Based Access Control RBAC

Learning Yii Framework 2.0 I have tried to use Role Bases Access Control from the documentation of Yii 2.0. But the guide documentation is too short to me that I cannot complete this learning. I have added the following code to my config file.

'components' => [
    'authManager' => [
        'class' => 'yii\rbac\DbManager',
    ],
],

I have create the database tables with the following sql script.

drop table [auth_assignment];
drop table [auth_item_child];
drop table [auth_item];
drop table [auth_rule];

create table [auth_rule]
(
    [name]  varchar(64) not null,
    [data]  text,
    [created_at]           integer,
    [updated_at]           integer,
    primary key ([name])
);

create table [auth_item]
(
   [name]                 varchar(64) not null,
   [type]                 integer not null,
   [description]          text,
   [rule_name]            varchar(64),
   [data]                 text,
   [created_at]           integer,
   [updated_at]           integer,
   primary key ([name]),
   foreign key ([rule_name]) references [auth_rule] ([name]) on delete set null on update    cascade
);

create index [idx-auth_item-type] on [auth_item] ([type]);

create table [auth_item_child]
(
   [parent]               varchar(64) not null,
   [child]                varchar(64) not null,
   primary key ([parent],[child]),
   foreign key ([parent]) references [auth_item] ([name]) on delete cascade on update cascade,
   foreign key ([child]) references [auth_item] ([name]) on delete cascade on update cascade
);

create table [auth_assignment]
(
   [item_name]            varchar(64) not null,
   [user_id]              varchar(64) not null,
   [created_at]           integer,
   primary key ([item_name], [user_id]),
   foreign key ([item_name]) references [auth_item] ([name]) on delete cascade on update cascade
);

I have built the authentication data with the following.

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

        // add "createPost" permission
        $createPost = $auth->createPermission('createPost');
        $createPost->description = 'Create a post';
        $auth->add($createPost);

        // add "updatePost" permission
        $updatePost = $auth->createPermission('updatePost');
        $updatePost->description = 'Update post';
        $auth->add($updatePost);

        // add "author" role and give this role the "createPost" permission
        $author = $auth->createRole('author');
        $auth->add($author);
        $auth->addChild($author, $createPost);

        // add "admin" role and give this role the "updatePost" permission
        // as well as the permissions of the "author" role
        $admin = $auth->createRole('admin');
        $auth->add($admin);
        $auth->addChild($admin, $updatePost);
        $auth->addChild($admin, $author);

        // Assign roles to users. 1 and 2 are IDs returned by IdentityInterface::getId()
        // usually implemented in your User model.
        $auth->assign($author, 2);
        $auth->assign($admin, 1);
    }
}

When access to this actionInit() method via this controller, the above database tables have been filled with the data based on the above code. Furthermore, in my user's table I have two users, admin user has the id number 1 and author user has the id number 2. I use the following code to create a user.

public function create()
{
    if ($this->validate()) {
        $user = new User();
        $user->username = $this->username;
        $user->email = $this->email;
        $user->setPassword($this->password);
        $user->generateAuthKey();
        $user->save(false);

        // the following three lines were added:
        $auth = Yii::$app->authManager;
        $authorRole = $auth->getRole('author');
        $auth->assign($authorRole, $user->getId());

        return $user;
    }

    return null;
}

With the above code all new inserted users will be author. With the if-statements below I can grant or deny access.

if (\Yii::$app->user->can('createPost')) {
    // create post
}

if (\Yii::$app->user->can('updatePost')) {
    // update post
}

So far so good. Everything works fine. The scenario of the above code is that normal author can create post, but cannot update post. Admin can update post and can do everything author can do. Now I want normal author to be able to update his/her own post. I don't know how to go further from here. I have followed the Yii Guide Documentation/Secury/Authorization paragraph Role based access control (RBAC). I have never used Yii 1. That's why I could not figure out with such short explanation of Yii 2.0 documentation RBAC.

like image 386
O Connor Avatar asked Oct 30 '14 11:10

O Connor


People also ask

What is RBAC in YII framework?

This package provides RBAC (Role-Based Access Control) library. It is used in Yii Framework but is usable separately as well. Flexible RBAC hierarchy with roles, permissions and rules. Role inheritance. Data could be passed to rules when checking access. Multiple storage adapters.

How to check if a user has a role in Yii?

The call Yii::app ()->user->checkAccess ('staff') will return true if the user has the role "staff" or "admin". In your controller, you can filter with accessRules () using the "roles" attribute of the rule.

How to access the authmanager application component in Yii?

We can then access the authManager application component using Yii::app ()->authManager. 8. Defining Authorization Hierarchy Defining authorization hierarchy involves three steps: defining authorization items, establishing relationships between authorization items, and assigning roles to application users.

How to create a role based access control model?

If you need simple Role based access control without the long RBAC process then this article is just for you. Lets jump to the point. On your user table make a column named 'roles'. Create the model accordingly. It will be named "User" here. When you add users you can assign them a role among 'admin', 'user', 'staff' etc etc.


1 Answers

You need access rule and the docs are clear so create it like

namespace app\rbac;

use yii\rbac\Rule;

/**
 * Checks if authorID matches user passed via params
 */
class AuthorRule extends Rule
{
    public $name = 'isAuthor';

    /**
     * @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)
    {
        return isset($params['post']) ? $params['post']->createdBy == $user : false;
    }
}

then, add it in your RBAC role

$auth = Yii::$app->authManager;

// add the rule
$rule = new \app\rbac\AuthorRule;
$auth->add($rule);

// add the "updateOwnPost" permission and associate the rule with it.
$updateOwnPost = $auth->createPermission('updateOwnPost');
$updateOwnPost->description = 'Update own post';
$updateOwnPost->ruleName = $rule->name;
$auth->add($updateOwnPost);

// "updateOwnPost" will be used from "updatePost"
$auth->addChild($updateOwnPost, $updatePost);

// allow "author" to update their own posts
$auth->addChild($author, $updateOwnPost);

Finally asign role to user in signup

$auth = Yii::$app->authManager;
$authorRole = $auth->getRole('author');
$auth->assign($authorRole, $userid_here);

to check if user have ability to edit use code below where $post is Model for posts

if (\Yii::$app->user->can('updatePost', ['post' => $post])) {
    // update post
}

All these are taken from guide. Let me know if you have any problem

like image 189
Stefano Mtangoo Avatar answered Oct 26 '22 17:10

Stefano Mtangoo