Request RBAC enhancements

I’m developing an rbac module and I’ve run into some Yii features I’d like to see changed or added in a future Yii version:

  1. I’d like CController to have a method “public function operations()”.

  2. I’d like the default CController method beforeAction to throw an event (like onBeforeAction) instead of overriding it in descendent classes.

Explanations:

  1. controller method ‘public function operations()’

This function returns an array with operations supported by this particular controller. The array could consist of elements like the following:




'op_editownprofile' => array(        // the internal name of the operation

    'type' => 'action',              // values for type: 'action' for a controller action

                                     //                  'command' for a controller command

                                     //                  <custom developer value> to be used inside bussiness

                                     //                        rules, inside views, etc.

    'name' => 'edit',                // the name of the action, command, ...; here it represents actionEdit

    'params' => array(

        'id' => Yii::app()->user->id,  // any attributes passed with the requested url.

    ),

    'label' => 'Edit own profile',   // the human readable name for this operation

),



The above code defines the operation ‘op_editownprofile’ which is the actionEdit method of this controller. It passes access control only if the passed attribute ‘id’ matches the current user’s id.

  1. onBeforeAction event

This would enable us to add routines that check if a user has access. This way it is possible to develop rbac for third party controllers without having to change the third party software.

Pros for this approach:

  • By being able to add an event, one can add rbac processing on a controller, even if the controller is developed by a third party.

  • The third party can develop its controller without knowledge of the rbac software used.

  • The third party may have defined a list of operations applicable for that controller, to be used by the rbac system (mine, srbac’s, Yii’s, …).

  • Even if the third party couldn’t care less about rbac and defining operations for his controller, using a behavior we can then add our own operations and rbac for that controller.

  • The rbac software can get a list of all operations used throughout the whole system and do something with it (rbac management).

  • If the operations() method or the onBeforeAction event is developed as a behavior, it can probably be added to a controller (or the controller’s module) in the configuration file (i.e. protected/config/main.php).

  • Currently one can develop rbac on a controller, but all controllers wanting to use it must extend from the new rbac controller. Therefore third party controllers cannot take advantage of this rbac software unless the third party controller is changed to extend from the rbac controller.

Cons for this approach:

I haven’t thought of any (yet?).

Sample code of how things could work:

Yii framework:




class CActionEvent extends CEvent

{

    // @var CAction is set when the event is triggered by CController::beforeAction().

    public $action;

}


class CController extends Cxxx

{

    public function beforeAction($action)

    {

        $event = new CActionEvent;

        $event->action = $action;

        // launch onBeforeAction($event) event

    }

}



Third party software:




class ThirdPartyController extends CController

{

  public function actionApplaud() {...};

}



My rbac extension for the third party controller:




class ThirdPartyControllerRbacBehavior extends CBehavior

{

    public function init(...)

    { // add event $this->beforeActionEvent to $this->owner };


    public function beforeActionEvent($event)

    {

        $operations = $this->owner->operations();

        $user = Yii::app()->user;

        $action = $event->action;

        // check if user is allowed access to the action

    }


    public function operations()

    {

        return array(

            'op_applaudyii' => array(

                'type' => 'action',

                'name' => 'applaud',

                'params' => array(

                  'who' => 'Yii',

                ),

                'label' => 'Applaud for Yii',

            ),

            'op_applaud' => array(

                'type' => 'action',

                'name' => 'applaud',

                'label' => 'Applaud for everyone',

            ),

        );

    }

}



Looking forward to any comments on my rbac wishes.

The example given in (1) basically deals with a role that’s dependent on target object, in this case the ‘profile’. It also moves some of the what the db should hold back into the code. Instead I suggest a method




public function getOpRoles($action)

{

    // return an array of roles based on current user and the target object of the given action.

    // For example, roles could be 'Owner', 'Manager', 'Supervisor', 'Section Editor', 'Author'

    // depending on the needs of the application.

}



Item (2) is definitely a good idea. In my module, http://www.yiiframework.com/extension/hierarchical-rbac/ , I chose to subclass the CWebApplication to get over this limitation.