SOLVED: AuthManager Question

I created a few roles; essentially own is a business owner who can only modify his own business, the other is an admin who can control everything.

My question is do I have to check access to both (‘updateOwnBusiness’ or ‘updateBusiness’), or should I only have to check for one (‘updateOwnBusiness’). I was under the impression that if you have the permission to updateBusiness, then checks for ‘updateOwnBusiness’ should pass…




    $auth->createOperation('createBusiness', 'create a business');

    $auth->createOperation('readBusiness', 'read a business');

    $auth->createOperation('updateBusiness', 'update a business');

    $auth->createOperation('deleteBusiness', 'delete a business');

    

    $bizRule='return Yii::app()->user->id==$params["business"]->owner->email;';

    $task=$auth->createTask('updateOwnBusiness', 'update a business by owner himself', $bizRule);

    $task->addChild('updateBusiness');






if (Yii::app()->user->checkAccess('updateOwnBusiness', array('business'=>$model)) || Yii::app()->user->checkAccess('updateBusiness'))

{

  // update

}



You have your logic backwards. If you have permission to ‘updateOwnBusiness’, then checks to ‘updateBusiness’ will pass if you satisfy the bizRule of ‘updateOwnBusiness’.

As long as you have your permission assignments done correctly.

Here is how I think you would need to do your permissions assignments, with your current permissions structure, to do what you are trying to do.

Normal users: Each normal user must have ‘updateOwnBusiness’ task assigned to them.

Admin users: Each admin user has ‘updateBusiness’ operation assigned to them.

Then you will only have to do one check with your current permissions structure




if (Yii::app()->user->checkAccess('updateBusiness', array('business' => $model))

{

  // update

}



This is why:

Each user must be assigned the ‘updateOwnBusiness’ because the authManager will only find items that are assigned to a given user. Even if that item is a Task, it will only be checked if it assigned to the current user.

Because the ‘updateBusiness’ operation is a child of the ‘updateOwnBusiness’ task, anyone who is assigned ‘updateOwnBusiness’ and can pass the bizRule will also have ‘updateBusiness’ permissions.

By doing this check for ‘updateBusiness’, it means that the user must either have direct access to ‘updateBusiness’ (an admin, etc), or pass the bizRule for ‘updateOwnBusiness’.

Does that make sense?

thanks killermonk, yes it does! i see how the relationships work now.

@killermonk:

This is a really good explanation, thanks. A lot of users have problems understanding RBAC hierarchies. Do you think you could mash up a cookbook article with maybe some simple examples? I feel like you’re the right guy for this … ;)

I guess my next question would be if admin role also inherits the owner role, should I have to specify each role in the action? Currently that is what is required.


      array('allow', // allow authenticated user to perform 'update' actions

        'actions'=>array('update'),

        'users'=>array('@'),

        'roles'=>array('owner', 'admin'),


    // owner role

    $bizRule='return (!Yii::app()->user->isGuest && Yii::app()->user->isOwner);';

    $role=$auth->createRole('owner', 'business owner', $bizRule);

    $role->addChild('user');

    $role->addChild('createBusiness');

    $role->addChild('updateOwnBusiness');




    // admin role

    $role=$auth->createRole('admin');

    $role->addChild('owner');

    $role->addChild('deleteBusiness');

    $role->addChild('updateBusiness');

    $auth->assign('admin','admin');

With your permissions structure, you would still need to do a check for both.

You need to do the check for both because of the bizRule associated with the ‘owner’ role. Even if someone has admin permissions they will not be able to pass the bizRule and therefore will not validate for that permission.

In this instance, making the ‘owner’ role and child of the ‘admin’ role does not add any benefit because of the bizRule.

What I do in situations like this is actually make the operations children of the ‘admin’ role, rather than making the ‘owner’ role a child of the ‘admin’ role.

So something like this:




    // owner role

    $bizRule='return (!Yii::app()->user->isGuest && Yii::app()->user->isOwner);';

    $role=$auth->createRole('owner', 'business owner', $bizRule);

    $role->addChild('user');

    $role->addChild('createBusiness');

    $role->addChild('updateOwnBusiness');




    // admin role

    $role=$auth->createRole('admin');

    $role->addChild('createBusiness');

    $role->addChild('updateOwnBusiness');

    $role->addChild('deleteBusiness');

    $role->addChild('updateBusiness');

    $auth->assign('admin','admin');



In this way, admin still will validate for those operations but does not have to satisfy the bizRule associated with the ‘owner’ role.

Then, on your controller, you could simply check for the specific operation you wanted (such as ‘updateBusiness’) and it will validate for both admins and owners.

One thing you should note, though, is that to do the cascading of permissions required multiple database queries using the RBAC. It can be, depending on your permission structure, fairly heavy to check for individual operations rather than just roles. Because of this, you should try to keep your permissions structure fairly flat. This will decrease the load associated with checking for permissions.

Yes, that makes sense; the business rule will evaluate to false for admin. Good point on calling RBAC for specific permissions.

Thanks again.