Rbac Permission relationship between parent and child

Dear,

I’m learning about Role based access control and I get a stuck at the relationship between parent and child of permission. I can see that in guide, we have:




// 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);



And in resource




/**

 * Adds an item as a child of another item.

 * @param Item $parent

 * @param Item $child

 * @throws \yii\base\Exception if the parent-child relationship already exists or if a loop has been detected.

 */

 public function addChild($parent, $child);



Both of them mean ‘updateOwnPost’ is a parent of ‘updatePost’. But it makes no sense, because the user having permission ‘updateOwnPost’ is also have power of ‘updatePost’. So why could a parent inherit from a child? I don’t understand the logic at here. Could you please explain more about it?

The example is distinguishing two actions: ‘updatePost’ and ‘updateOwnPost’ :

http://www.yiiframework.com/doc-2.0/guide-security-authorization.html#generating-rbac-data

With ‘updatePost’ you give the user the capability to update any posts.

With ‘updateOwnPost’ you give the user the capability to update own posts;

Since ‘admin’ role has ‘updatePost’ permission, users that are in this role will be checked against this condition




if (\Yii::$app->user->can('updatePost')) {

    // create post

}

will be true;



Since ‘author’ role has not ‘updatePost’ permission, but it exists a rule from ‘updatePost’ named ‘updateOwnPost’, when a check ‘updatePost’ will be required, it will checked ‘updateOwnPost’, that descends from it




if (\Yii::$app->user->can('updatePost')) {

    // create post

}

will be true only if execute() method of the rule will return true;



If you don’t assign ‘updatePost’ permission to ‘author’ role, you avoid that ‘author’ role could be update any posts (right!).

But you want that ‘author’ could update his own post. So you create a new permission ‘updateOwnPost’ that descends from ‘updatePost’ and assign it to a rule assigned to ‘author’ role.

So you can always call the same check




if (\Yii::$app->user->can('updatePost')) {

    // create post

}



for every users. Otherwise you could make differences in check




if (\Yii::$app->user->can('updatePost')) {

    // create post

}


or


if (\Yii::$app->user->can('updateOwnPost')) {

    // create post

}



but this is longer and less clear.

The words "parent" and "child" may be a little confusing. They are not the synonyms of "general, whole" and "specific, part".

Please take a look at the figure in the guide.

Access Check

The key concept in the rbac hierarchy is arrows and their directions.

An arrow relates 2 items. An item on the starting point is called "child" and one on the ending point is called "parent". And all the items and the arrows in the hierarchy must construct an one-way network.

On one end of the network are located permissions that permit the controller actions, and on the other end are individual users.

Checking access right is performed by trying to find a route from the action to the user following the arrows.

  1. Can John "updatePost"?

"updatePost" has 2 parents: "admin" and "updateOwnPost". But the route via "admin" is not possible for John, because John is not a parent of "admin". So we have to take another route, i.e., "updatePost" => "updateOwnPost" => "author" => "John".

There’s a rule called “AuthorRule” attached to “updateOwnPost”. It checks whether the user is the creator of the post. If he/she is, then he/she can proceed to the next item and finally get the right to update the post.

  1. Can Jane "updatePost"?

Yes, always, because there’s a route from “updatePost” to “Jane” via “admin”. The other route via “updateOwnPost” may or may not be available for her, depending on whether she is the creator of the post or not. It’s just the same as John. But she can update any post of any author because she has a route via “admin”.

  1. How do we call "can" method?

We use this:




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

    // update post

}



We start from "updatePost", not from "updateOwnPost". Otherwise we could not provide a route via "admin" for Jane.

And we pass the additional parameter that will be used by "AuthorRule". It is not used in "updatePost", but must be there from the beginning for the sake of "updateOwnPost".

By this way we could simplify the code for access checking.

  1. What if "updateOwnPost" and "updatePost" have no parent-child relation?

Since we have no route between "updatePost" and "updateOwnPost", we have to check 2 of them independently:




if (\Yii::$app->user->can('updatePost') ||

       \Yii::$app->user->can('updateOwnPost', ['post' => $post])) {

    // update post

}



This will work as expected, but is not as effective as 3).

  1. What if "updateOwnPost" is a child of "updatePost"?

Now the arrow between "updatePost" and "updateOwnPost" has the opposite direction.




if (\Yii::$app->user->can('updateOwnPost', ['post' => $post])) {

    // update post

}



But the code above works only for John. It won’t give Jane an admin right to update any post.

Be aware that you have to pass "AuthorRule" in order to proceed from "updateOwnPost" to "updatePost". It means that only the authors can proceed to "updatePost".

So in this case you’ll end up writing the same code as 4).

Now, I hope you’ll agree that “updateOwnPost” must be a parent of “updatePost”. :)

Hi Fabrizio Caldarelli,

Thank you, I understand what you mean that present how a permission and role works. Thing makes me not sense is the inheritance. As you said: “But you want that ‘author’ could update his own post. So you create a new permission ‘updateOwnPost’ that descends from ‘updatePost’ and assign it to a rule assigned to ‘author’ role.”, it means ‘updateOwnPost’ will inherit the power of ‘updatePost’ and have one ‘AuthorRule’ to be different.

However, at the method $auth->addChild($updateOwnPost, $updatePost). You can see that ‘updateOwnPost’ is a parent, and it inherit from a child. So i think it makes no sense. I think a child should inherit from a parent because it makes more logical.

@softark: Thank you very much for deeply explaining. It is very clearly about the hierarchy of arrows and directions. You help me more clear about the relationship by reviewing how the ‘updatePost’ is used. In additions, Just more 3 questions please, why do they call the item on the starting point the “child” and the ending point the “parent”? Why not the reverse? Does it have any rule or meaning or just they like that ?

I also don’t know the reason for the naming. Probably it’s because the hierarchy has a parent-child structure as a whole.

And I also had difficulties comprehending the relation between "updatePost" and "updateOwnPost" at first. It was very confusing to me.

What I learned is that the reason for adding "updateOwnPost" as a parent of "updatePost" might be just practical rather than logical. The seemingly tricky relation simplifies the code for access checking. But as you see in 4) in my previous post, we could do it without the direct relation between the 2 permissions. Or we may think of "updateOwnPost" not as a parent but a cousin of "updatePost" who could provide a narrow alternative route when the main route is closed.

Yes, thank you very much for your kindly support! :D

If you want detail understanding please check table auth_item_child

there you will get detail about the parent and child updateOwnPost is parent and child will be update route

and updateOwnpost is child when author is parent

table look like this

Parent child

updateOwnPost companies/update

author updateOwnPost