The admin has ViewAnyPerson as child, so he can view all persons without further checks.
Another role has ViewRelatedPerson as a child, so he must pass the rule in order to view the person.
And it all worked great.
Until i had to add another alternative rule to access a person. So i created another permission with its rule called ViewSameRegionPerson. And i gived this permission to another role.
I expected Yii to execute ViewRelatedPerson for the role that has ViewRelatedPerson as child, and the other rule for the other role.
But i noticed both rules get executed.
So i tried removing ViewRelatedPerson from the first rolechildren.
Both rules get executed as well.
So, after the long premise, my question is:
How can i make a rule just for a role?
As far as I understand, when “ViewAnyPerson” has both “ViewRelatedPerson” and “ViewSameRegionPerson” as its parents, you can’t stop Yii RBAC from checking both of them, because the access checking starts from an action and goes up the RBAC tree from child to parent until it successfully reaches the user or fails to reach the user.
So, how can i achieve the following?
The user group “NormalPerson” must check ViewRelatedPerson only.
The user group “RegionManager” must check ViewSameRegionPerson only.
If he/she passes the rule, he/she may have the ViewAnyPerson permission
When you do the access checking, something like the following will occur:
There’s a restricted action to view a person’s profile … actionViewPerson for example.
You can check the permission by Yii::$app->user->can('ViewAnyPerson', ['targetPerson' => $targetPerson]) in actionViewPerson method.
If the user has ‘admin’ role, then the result of access checking is positive, because ‘admin’ role has ViewAnyPerson permission as a child.
If the user doesn’t have ‘admin’ role, then RBAC will check the parents of ViewAnyPerson permission, i.e., ViewRelatedPerson and ViewSameRegionPerson permissions.
If ViewRelatedPerson get passed, then RBAC will check if the user has some role (‘relative’ for example) that has ViewRelatedPerson as a child.
If ViewSameRegionPerson get passed, then RBAC will check if the user has some role (‘region’ for example) that has ViewSameRegionPerson as a child.
All that you have to do in the controller code is #2. Others will be automatically taken care of by RBAC system. RBAC will start from the action, going up the RBAC hierarchy, and try to reach the current user.