View Source

<ac:macro ac:name="unmigrated-inline-wiki-markup"><ac:plain-text-body><![CDATA[{zone-template-instance:ZFPROP:Proposal Zone Template}

{note}This component will be ZF >=2.0 only and will not be shipped with a (tentative) ZF1.11{note}




0.5 - 17 December 1909: Initial Draft.

Zend_RBAC is a component used to determine if a user (subject), member of one or more roles, has access to a resource.

* [1 RBAC Specification|]
* [2 Wikipedia|]

* A _user_ CAN be member of one or more _roles_
* A _role_ CAN be the parent of one or more other _roles_
* An _object_ CAN be assigned to one or more _roles_
* If a _user_ is member of a _role_ (or any of the _role's_ childs) to which the
requested _object_ was assigned, the _user_ MUST be allowed access. Otherwise, MUST NOT.

* Zend_Exception

* Zend_Db

Zend_Rbac is a component that can be used to determine whether a subject (user) that has one or more roles, has access to one or more resources, after you have defined the available resources, roles and users. One does only _allow_ (not disallow) roles access to resources, assign users to roles, and determine if any roles inherit from other roles.

Following example based on [1]:


Object 1 ------\ /-------User 1
\ /
= H E A L E R == ---------User 2
/ | \
Object 2 ------/ ^ \-------User 3
Object 3 ------\ ^ /-------User 4
\ | /
== I N T E R N == ---------User 5
/ | \
Object 4 ------/ ^ \-------User 6
Object 5 ------\ ^ /--------User 7
\ | /
== D O C T O R == ---------User 8
/ \
Object 6 ------/ \--------User 9
Interns can do everything a healer can do
Doctors can do everything an intern can

Healers have access to object 1 & 2 only
Interns have access to object 1, 2, 3 & 4 only
Doctors have access to object 1, 2, 3, 4, 5 & 6 only

This component is different than Zend_Acl because:
* Zend_Rbac does not feature the disallowing of access, only allowing access, meaning that there's no problems by design (as is with Zend_Acl: ZF-5369)
* It makes a distinction between roles and users (subjects) whereas Zend_Acl only has resources and roles
* It's faster and uses less lines of code (that's what I'm aiming at)
* It's adapter based by default
* It does not use privileges *

\* If you want to replicate this behavior, you're advised to use several resources to achieve this. Meaning that where with zend_acl you have one resource named 'resource' with the privileges 'add', 'edit' and 'delete', you're expected to add the resources 'resource_add', 'resource_edit', and 'resource_delete'.

Some users (on IRC) have suggested to replace this component with Zend_Acl in ZF2.0 because it essentially does the same: determine if a certain user/role has access to a certain resource (but then done better :D). If there's a majority in the community that wishes to replace this component with Zend_Acl, it should definitely be considered.{zone-data}

* Milestone 1: \[DONE\] Design notes will be published here
* Milestone 2: \[DONE\] Write unittests
* Milestone 3: \[DONE\] Write working (basic) prototype, commit in [userbranch|]
* Milestone 4: \[DONE\] Write Resource Plugin, assertions, adapters & FC-lugin => [userbranch|]
* Milestone 5: Drop class interface here (or emphasize link to userbranch, hey, developers are lazy by definition)
* Milestone 6: Get proposal reviewed, updated, accepted
* Milestone 7: Write documentation (or find s/o to do so, volunteers? :D)
* Milestone 8: Get code reviewed by Matthew/liaison and move to trunk
* Milestone 9: Release immediately, and don't forget to promote Zym meanwhile

* Zend_Rbac
* Zend_Rbac_Exception
* Zend_Rbac_Object
* Zend_Rbac_ObjectInterface
* Zend_Rbac_Resource (interface)
* Zend_Rbac_Role (interface)
* Zend_Rbac_Subject (interface)

* Zend_Rbac_Object_Resource
* Zend_Rbac_Object_Role
* Zend_Rbac_Object_Subject

Todo (read: not in userbranch):
* Zend_Rbac_Adapter_DbTable
* Zend_Rbac_Adapter_Abstract
* Zend_Rbac_Assert_?
* Zend_App_Resource_Rbac
* Zend_Controller_Front_Plugin_Rbac
* More_To_Come?


The following code implements the given scenario under 'operation'

$rbac = new Zend_Rbac();

$internRole = new Zend_Rbac_Role('intern');
$user5 = new Zend_Rbac_Subject('user5');

$rbac->assign($internRole, 'user4');
$rbac->assign('intern', $user5);
$rbac->assign('intern', 'user6');

$rbac->assign('doctor', array('user7','user8','user9');

$rbac->setChild('intern', 'healer'); // <parent>, <child>
$rbac->setChild('doctor', 'intern');

$rbac->subscribe('healer', array('object1', 'object2');
$rbac->subscribe('intern', array('object3', 'object4');
$rbac->subscribe('doctor', array('object5', 'object6');

$rbac->isAllowed('user1', 'object1'); // True
$rbac->isAllowed('user1', 'object3'); // False
$rbac->isAllowed('user4', 'object1'); // True
$rbac->isAllowed('user4', 'object3'); // True
$rbac->isAllowed('user4', 'object5'); // False
$rbac->isAllowed('user9', 'object1'); // True
$rbac->isAllowed('user9', 'object3'); // True
$rbac->isAllowed('user9', 'object5'); // True

Alternatively you can use your models, by having them implement the correct interface, and adding a __toString() method that returns a unique identifier.
Model_User implements Zend_Rbac_Subject {

protected $_userId = 'userName';

public function __toString() {
return $this->_userId;

$rbac = new Zend_Rbac();
$rbac->addSubject(new Model_User());

class Zend_Rbac_Exception extends Zend_Exception {}

For the rest of the code, please see [GitHub|]