I have a use case where I need to assign a user the right to edit highly dynamic items, which can be in the hundreds or thousands. Each user, while belonging to the same type or group, must be assigned to some of these items (and different users may have access to the same Company Items). Furthermore, these items can rapidly grow in number or disappear. These items have no intrinsic relationship with the users, but must be arbitrarily assigned to them.
Lets call these items Company Items.
So, I want to be able to assign Company Items to users, and revoke that access dynamically. These assignments are then used inside controllers to check if some action can go on... Conceptually, the problem is always the same: test if a user has access to a specific item/row in a table, the Company Items' table.
My idea was to use the yii RBAC system, while trying to keep the authorization tree static, thus avoiding creating/deleting roles or tasks every time a Company Item is created or deleted. Instead, I was wondering If I could do this using the $data
parameter in assign($itemName, $userId, $bizRule, $data)
and a tree similar to the following:
- adminUser: role
- companyAdmin: role
- editCompanyItemRole: role with bizrule; bizrule tests access to Company Item by simply checking if
$params['companyItemId']
exists inside$data['companyItemsAllowed']
; at assignment time, should receive a$data
containing an array of Company Items' ids the user should be allowed to edit!- editItem: operation; used to check access in the Controllers, and should be provided with the Company Item id one wishes to check the user against, e.g.,
Yii::app()->user->checkAccess('editItem', array('companyItemId' => 666));
- editItem: operation; used to check access in the Controllers, and should be provided with the Company Item id one wishes to check the user against, e.g.,
- editCompanyItemRole: role with bizrule; bizrule tests access to Company Item by simply checking if
- companyAdmin: role
This way, whenever we need to change the user assignment to Company Items, the only thing we need to do is to alter the $data['companyItemsAllowed']
array inside the original assignment. The role is always the same!
Questions:
- Does this system work, can I use Yii's RBAC system in this fashion ??
- Is this the ideal way to accomplish the requirements, assuming we have thousands of Company Items, and we may have dozens of those assigned to each user ?? Why ??
I wrote a small framework for access control. It is simple, small and light. My motivation was to decouple the access control of my applications from other frameworks, because I think the access control from others frameworks very coupled to framework style.
For instance in Yii where you have to program it in the controller, and I don't like it, because is very boring program new rules when you add a new action(from Yii Wiki):
IMHO, it must be done dynamically. You should be able to program the rule in its administrative system visually and then the developer program an action and a model appropriately and then is ready.
To integrate my library with Yii applications I use import, for example:
And I use
beforeControllerAction()
from module(s) to integrate.When I have time I will write a manual integration for multiple frameworks, first with which I have experience as Yii, Zend and Symfony. And translate the documentation to english. But the code is english now.
I hope that at least give you an idea of how to write your access control.
You can make use of Yii's concept of data owner in its access control implementation.
The first step to implementing this in your own application is to instruct the controller to enable this rule. This is done by overwriting the filters() function.
The 'accessControl' flag specifies that access control is applied for data management. The actual business rules are defined in the accessRules() function, and specifying the access control expression that will be evaluated to provide the desired control. And example of the function implementation is.
The isMyRecord is a method that will be run that returns true or false to indicate if the action should be allowed.
I decided to take the following approach, after deciding that simply maintaining an array of Company Items inside
$data['companyItemsAllowed']
was not the best for these requirements:Users
andCompanyItems
; call itassociation_table
;created the RBAC tree as shown in the question, but where the
bizRule
was something like the following:This allows me to maintain the access control interface, like so:
(recall that we do not need to pass on
userId
on the$params
array!.)Of course, this separates the actual assigning of permissions to Company Items from the RBAC system: I assign
editCompanyItemRole
to some user using the RBAC mechanisms offered by Yii, but each actual item must be assigned individually by inserting a row ontoassociation_table
...So, although first thought about maintaining an array of Company Items inside
$data
would probably work, I think this is best and more flexible. Also, the general idea about thebizRule
seems to work.