[limb-svn] r6877 - in 3.x/trunk/limb: . acl acl/src acl/tests acl/tests/cases

svn at limb-project.com svn at limb-project.com
Mon Mar 31 17:29:51 MSD 2008


Author: korchasa
Date: 2008-03-31 17:29:51 +0400 (Mon, 31 Mar 2008)
New Revision: 6877
URL: http://fisheye.limb-project.com/changelog/limb/?cs=6877

Added:
   3.x/trunk/limb/acl/
   3.x/trunk/limb/acl/CHANGELOG
   3.x/trunk/limb/acl/DESCRIPTION
   3.x/trunk/limb/acl/MAINTAINERS
   3.x/trunk/limb/acl/SUMMARY
   3.x/trunk/limb/acl/VERSION
   3.x/trunk/limb/acl/common.inc.php
   3.x/trunk/limb/acl/src/
   3.x/trunk/limb/acl/src/lmbAbstractResourceProvider.class.php
   3.x/trunk/limb/acl/src/lmbAbstractRoleProvider.class.php
   3.x/trunk/limb/acl/src/lmbAcl.class.php
   3.x/trunk/limb/acl/src/lmbAclException.class.php
   3.x/trunk/limb/acl/src/lmbAclTools.class.php
   3.x/trunk/limb/acl/src/lmbRolesResolverInterface.interface.php
   3.x/trunk/limb/acl/tests/
   3.x/trunk/limb/acl/tests/cases/
   3.x/trunk/limb/acl/tests/cases/.setup.php
   3.x/trunk/limb/acl/tests/cases/All.php
   3.x/trunk/limb/acl/tests/cases/lmbAclObjectsFeaturesTest.class.php
   3.x/trunk/limb/acl/tests/cases/lmbAclTest.class.php
   3.x/trunk/limb/acl/toolkit.inc.php
Log:
-- initial acl package version

Added: 3.x/trunk/limb/acl/CHANGELOG
===================================================================

Added: 3.x/trunk/limb/acl/DESCRIPTION
===================================================================
--- 3.x/trunk/limb/acl/DESCRIPTION	                        (rev 0)
+++ 3.x/trunk/limb/acl/DESCRIPTION	2008-03-31 13:29:51 UTC (rev 6877)
@@ -0,0 +1 @@
+This package provides tools access controll list features

Added: 3.x/trunk/limb/acl/MAINTAINERS
===================================================================
--- 3.x/trunk/limb/acl/MAINTAINERS	                        (rev 0)
+++ 3.x/trunk/limb/acl/MAINTAINERS	2008-03-31 13:29:51 UTC (rev 6877)
@@ -0,0 +1,5 @@
+
+lead,pachanga,Pavel Shevaev,pacha.shevaev at gmail.com,yes
+lead,syfisher,Sergey Yudin,syfisher at gmail.com,yes
+developer,wiliam,Ilia Moltyaninov,moltyaninov at gmail.com,yes
+developer,tony,Roman Senuta,senutar at gmail.com,yes

Added: 3.x/trunk/limb/acl/SUMMARY
===================================================================
--- 3.x/trunk/limb/acl/SUMMARY	                        (rev 0)
+++ 3.x/trunk/limb/acl/SUMMARY	2008-03-31 13:29:51 UTC (rev 6877)
@@ -0,0 +1 @@
+Access Controll List tools
\ No newline at end of file

Added: 3.x/trunk/limb/acl/VERSION
===================================================================
--- 3.x/trunk/limb/acl/VERSION	                        (rev 0)
+++ 3.x/trunk/limb/acl/VERSION	2008-03-31 13:29:51 UTC (rev 6877)
@@ -0,0 +1 @@
+acl-0.0.1-devel

Added: 3.x/trunk/limb/acl/common.inc.php
===================================================================
--- 3.x/trunk/limb/acl/common.inc.php	                        (rev 0)
+++ 3.x/trunk/limb/acl/common.inc.php	2008-03-31 13:29:51 UTC (rev 6877)
@@ -0,0 +1,18 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+
+/**
+ * @package active_record
+ * @version $Id: common.inc.php 6691 2008-01-15 14:55:59Z serega $
+ */
+require_once('limb/core/common.inc.php');
+//require_once(dirname(__FILE__) . '/toolkit.inc.php');
+//lmb_require('limb/active_record/src/lmbActiveRecord.class.php');
+
+

Added: 3.x/trunk/limb/acl/src/lmbAbstractResourceProvider.class.php
===================================================================
--- 3.x/trunk/limb/acl/src/lmbAbstractResourceProvider.class.php	                        (rev 0)
+++ 3.x/trunk/limb/acl/src/lmbAbstractResourceProvider.class.php	2008-03-31 13:29:51 UTC (rev 6877)
@@ -0,0 +1,19 @@
+<?php
+/*
+* Limb PHP Framework
+*
+* @link http://limb-project.com
+* @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+* @license    LGPL http://www.gnu.org/copyleft/lesser.html
+*/
+abstract class lmbAbstractResourceProvider
+{
+  protected $_resource = null;
+
+  function getResource()
+  {
+    if(is_null($this->_resource))
+      throw new lmbAclException('Resource provider must have filled _resource property');
+    return $this->_resource;
+  }
+}

Added: 3.x/trunk/limb/acl/src/lmbAbstractRoleProvider.class.php
===================================================================
--- 3.x/trunk/limb/acl/src/lmbAbstractRoleProvider.class.php	                        (rev 0)
+++ 3.x/trunk/limb/acl/src/lmbAbstractRoleProvider.class.php	2008-03-31 13:29:51 UTC (rev 6877)
@@ -0,0 +1,20 @@
+<?php
+/*
+* Limb PHP Framework
+*
+* @link http://limb-project.com
+* @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+* @license    LGPL http://www.gnu.org/copyleft/lesser.html
+*/
+
+abstract class lmbAbstractRoleProvider
+{
+  protected $_role = null;
+
+  function getRole()
+  {
+    if(is_null($this->_role))
+      throw new lmbAclException('Role provider must have filled _role property');
+    return $this->_role;
+  }
+}

Added: 3.x/trunk/limb/acl/src/lmbAcl.class.php
===================================================================
--- 3.x/trunk/limb/acl/src/lmbAcl.class.php	                        (rev 0)
+++ 3.x/trunk/limb/acl/src/lmbAcl.class.php	2008-03-31 13:29:51 UTC (rev 6877)
@@ -0,0 +1,268 @@
+<?php
+/*
+* Limb PHP Framework
+*
+* @link http://limb-project.com
+* @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+* @license    LGPL http://www.gnu.org/copyleft/lesser.html
+*/
+
+lmb_require('limb/acl/src/lmbRoleProviderInterface.interface.php');
+lmb_require('limb/acl/src/lmbResourceProviderInterface.interface.php');
+lmb_require('limb/acl/src/lmbRolesResolverInterface.interface.php');
+lmb_require('limb/acl/src/lmbAclException.class.php');
+
+class lmbAcl
+{
+  protected $_roles = array();
+  protected $_resources = array();
+  public $_roles_rules = array();
+  public $_resources_rules = array();
+  public $_privileges_rules = array();
+
+  function __construct() {}
+
+  function addRole($role, $parents = array())
+  {
+    if(!is_array($parents))
+      $parents = array($parents);
+
+    foreach($parents as $parent)
+    {
+      if(!$this->isRoleExist($parent))
+      throw new lmbAclException('Parent role not exist', array(
+        'role' => $role,
+        'parent' => $parent,
+      ));
+    }
+
+    $this->_roles[$role] = $parents;
+
+    return $this;
+  }
+
+  function getRoles()
+  {
+    return array_keys($this->_roles);
+  }
+
+  function isRoleExist($role)
+  {
+    return array_key_exists($role, $this->_roles);
+  }
+
+  function getRoleInherits($role)
+  {
+    $inherits = $this->_roles[$role];
+
+    if(!count($inherits))
+      return array();
+
+    foreach($inherits as $inherit)
+      $inherits  = array_merge($inherits, $this->getRoleInherits($inherit));
+
+    return $inherits;
+  }
+
+  function addResource($resource, $parents = array())
+  {
+    if(!is_array($parents))
+      $parents = array($parents);
+
+    foreach($parents as $parent)
+    {
+      if(!$this->isResourceExist($parent))
+      throw new lmbAclException('Parent role not exist', array(
+        'role' => $resource,
+        'parent' => $parent,
+      ));
+    }
+
+    $this->_resources[$resource] = $parents;
+
+    return true;
+  }
+
+  function getResources()
+  {
+    return array_keys($this->_resources);
+  }
+
+  function isResourceExist($resource)
+  {
+    return array_key_exists($resource, $this->_resources);
+  }
+
+  function getResourceInherits($resource)
+  {
+    $inherits = $this->_resources[$resource];
+
+    if(!count($inherits))
+      return array();
+
+    foreach($inherits as $inherit)
+      $inherits  = array_merge($inherits, $this->getResourceInherits($inherit));
+
+    return $inherits;
+  }
+
+  protected function _isExistRoleRule($role, $privilege)
+  {
+    if(!array_key_exists($role, $this->_roles_rules))
+      return false;
+    if(is_array($this->_roles_rules[$role]))
+      return in_array($privilege, $this->_roles_rules[$role]);
+    return true;
+  }
+
+  protected function _applyRoleRule($role, $rule, $privileges)
+  {
+    $this->_removeResourceRule($role);
+    if(0 === count($privileges))
+      $this->_roles_rules[$role] = $rule;
+    else
+      foreach($privileges as $privilege)
+          $this->_roles_rules[$role][$privilege] = $rule;
+  }
+
+  protected function _getRoleRule($role, $privelege)
+  {
+    if(!is_array($this->_roles_rules[$role]))
+      return $this->_roles_rules[$role];
+    else
+    {
+      if(!array_key_exists($privelege, $this->_roles_rules[$role]))
+        return false;
+      return $this->_roles_rules[$role][$privelege];
+    }
+  }
+
+  protected function _removeResourceRule($role)
+  {
+    unset($this->_resources_rules[$role]);
+  }
+
+  protected function _isExistResourceRule($role, $resource)
+  {
+    if(!array_key_exists($role, $this->_resources_rules))
+      return false;
+    return array_key_exists($resource, $this->_resources_rules[$role]);
+  }
+
+  protected function _applyResourceRule($role, $resource, $rule)
+  {
+    if(!array_key_exists($role, $this->_resources_rules))
+      $this->_resources_rules[$role] = array();
+
+    $this->_removePrivilegesRule($role, $resource);
+
+    $this->_resources_rules[$role][$resource] = $rule;
+  }
+
+  protected function _getResourceRule($role, $resource)
+  {
+    return $this->_resources_rules[$role][$resource];
+  }
+
+  protected function _isExistPrivilegeRule($role, $resource, $privilege)
+  {
+    if(!array_key_exists($role, $this->_privileges_rules))
+      return false;
+    if(!array_key_exists($resource, $this->_privileges_rules[$role]))
+      return false;
+    return array_key_exists($privilege, $this->_privileges_rules[$role][$resource]);
+  }
+
+  protected function _applyPrivilegesRule($role, $resource, $privileges, $rule)
+  {
+    if(!array_key_exists($role, $this->_privileges_rules))
+      $this->_privileges_rules[$role] = array();
+
+    if(!array_key_exists($resource, $this->_privileges_rules[$role]))
+      $this->_privileges_rules[$role][$resource] = array();
+
+    foreach($privileges as $privilege)
+      $this->_privileges_rules[$role][$resource] = array_merge($this->_privileges_rules[$role][$resource], array($privilege => $rule));
+  }
+
+  protected function _removePrivilegesRule($role, $resource)
+  {
+    unset($this->_privileges_rules[$role][$resource]);
+  }
+
+  protected function _getPrivilegeRule($role, $resource, $privilege)
+  {
+    return $this->_privileges_rules[$role][$resource][$privilege];
+  }
+
+  protected function _checkResource($resource)
+  {
+    if(!is_null($resource) && !$this->isResourceExist($resource))
+      throw new lmbAclException('Resource not exist', array('resource' => $resource));
+  }
+
+  function isAllowed($role, $resource = null, $privilege = null)
+  {
+    if($resource instanceof lmbRolesResolverInterface)
+      if($resolved_role = $resource->getRoleFor($role))
+        $role = $resolved_role;
+
+    if($resource instanceof lmbAbstractResourceProvider)
+      $resource = $resource->getResource();
+
+    $this->_checkResource($resource);
+
+    if($role instanceof lmbAbstractRoleProvider)
+      $role = $role->getRole();
+
+    if(!$this->isRoleExist($role))
+      throw new lmbAclException('Role not exist', array('role' => $role));
+
+    foreach($this->getRoleInherits($role) as $inherit)
+      if($this->isAllowed($inherit, $resource, $privilege))
+        return true;
+
+    if($this->_isExistPrivilegeRule($role, $resource, $privilege))
+      return $this->_getPrivilegeRule($role, $resource, $privilege);
+
+    if($this->_isExistResourceRule($role, $resource))
+      return $this->_getResourceRule($role, $resource);
+
+    if($this->_isExistRoleRule($role, $privilege))
+      return $this->_getRoleRule($role, $privilege);
+
+    return false;
+  }
+
+  function setRule($role, $resource = null, $privileges = array(), $rule)
+  {
+    if(!is_array($privileges))
+      $privileges = array($privileges);
+
+    if(!$this->isRoleExist($role))
+      throw new lmbAclException('Role not exist', array('role' => $role));
+
+    if(is_null($resource))
+      return $this->_applyRoleRule($role, $rule, $privileges);
+    else
+    {
+      $this->_checkResource($resource);
+
+      if(0 === count($privileges))
+        $this->_applyResourceRule($role, $resource, $rule);
+      else
+        $this->_applyPrivilegesRule($role, $resource, $privileges, $rule);
+    }
+  }
+
+  function allow($role, $resource = null, $privileges = array())
+  {
+    $this->setRule($role, $resource, $privileges, true);
+  }
+
+  function deny($role, $resource = null, $privileges = array())
+  {
+    $this->setRule($role, $resource, $privileges, false);
+  }
+
+}

Added: 3.x/trunk/limb/acl/src/lmbAclException.class.php
===================================================================
--- 3.x/trunk/limb/acl/src/lmbAclException.class.php	                        (rev 0)
+++ 3.x/trunk/limb/acl/src/lmbAclException.class.php	2008-03-31 13:29:51 UTC (rev 6877)
@@ -0,0 +1,10 @@
+<?php
+/*
+* Limb PHP Framework
+*
+* @link http://limb-project.com
+* @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+* @license    LGPL http://www.gnu.org/copyleft/lesser.html
+*/
+
+class lmbAclException extends lmbException {}

Added: 3.x/trunk/limb/acl/src/lmbAclTools.class.php
===================================================================
--- 3.x/trunk/limb/acl/src/lmbAclTools.class.php	                        (rev 0)
+++ 3.x/trunk/limb/acl/src/lmbAclTools.class.php	2008-03-31 13:29:51 UTC (rev 6877)
@@ -0,0 +1,34 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+lmb_require('limb/toolkit/src/lmbAbstractTools.class.php');
+lmb_require('limb/acl/src/lmbAcl.class.php');
+
+/**
+ * class lmbFsTools.
+ *
+ * @package fs
+ * @version $Id$
+ */
+class lmbAclTools extends lmbAbstractTools
+{
+  protected $acl = null;
+
+  function getAcl()
+  {
+    if(is_null($this->acl))
+      $this->acl = new lmbAcl();
+
+    return $this->acl;
+  }
+
+  function setAcl($acl)
+  {
+    $this->acl = $acl;
+  }
+}

Added: 3.x/trunk/limb/acl/src/lmbRolesResolverInterface.interface.php
===================================================================
--- 3.x/trunk/limb/acl/src/lmbRolesResolverInterface.interface.php	                        (rev 0)
+++ 3.x/trunk/limb/acl/src/lmbRolesResolverInterface.interface.php	2008-03-31 13:29:51 UTC (rev 6877)
@@ -0,0 +1,13 @@
+<?php
+/*
+* Limb PHP Framework
+*
+* @link http://limb-project.com
+* @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+* @license    LGPL http://www.gnu.org/copyleft/lesser.html
+*/
+
+interface lmbRolesResolverInterface
+{
+  function getRoleFor($object);
+}

Added: 3.x/trunk/limb/acl/tests/cases/.setup.php
===================================================================
--- 3.x/trunk/limb/acl/tests/cases/.setup.php	                        (rev 0)
+++ 3.x/trunk/limb/acl/tests/cases/.setup.php	2008-03-31 13:29:51 UTC (rev 6877)
@@ -0,0 +1,2 @@
+<?php
+require_once(dirname(__FILE__) . '/../../common.inc.php');

Added: 3.x/trunk/limb/acl/tests/cases/All.php
===================================================================
--- 3.x/trunk/limb/acl/tests/cases/All.php	                        (rev 0)
+++ 3.x/trunk/limb/acl/tests/cases/All.php	2008-03-31 13:29:51 UTC (rev 6877)
@@ -0,0 +1,295 @@
+<?php
+class Zend_AclTest extends PHPUnit_Framework_TestCase
+{
+    /**
+     * Ensures that basic removal of a single Role works
+     *
+     * @return void
+     */
+    public function testRoleRegistryRemoveOne()
+    {
+        $roleGuest = new Zend_Acl_Role('guest');
+        $this->_acl->addRole($roleGuest)
+                   ->removeRole($roleGuest);
+        $this->assertFalse($this->_acl->hasRole($roleGuest));
+    }
+
+    /**
+     * Ensures that an exception is thrown when a non-existent Role is specified for removal
+     *
+     * @return void
+     */
+    public function testRoleRegistryRemoveOneNonExistent()
+    {
+        try {
+            $this->_acl->removeRole('nonexistent');
+            $this->fail('Expected Zend_Acl_Role_Registry_Exception not thrown upon removing a non-existent Role');
+        } catch (Zend_Acl_Role_Registry_Exception $e) {
+            $this->assertContains('not found', $e->getMessage());
+        }
+    }
+
+    /**
+     * Ensures that removal of all Roles works
+     *
+     * @return void
+     */
+    public function testRoleRegistryRemoveAll()
+    {
+        $roleGuest = new Zend_Acl_Role('guest');
+        $this->_acl->addRole($roleGuest)
+                   ->removeRoleAll();
+        $this->assertFalse($this->_acl->hasRole($roleGuest));
+    }
+
+    /**
+     * Ensures that basic removal of a single Resource works
+     *
+     * @return void
+     */
+    public function testResourceRemoveOne()
+    {
+        $resourceArea = new Zend_Acl_Resource('area');
+        $this->_acl->add($resourceArea)
+                   ->remove($resourceArea);
+        $this->assertFalse($this->_acl->has($resourceArea));
+    }
+
+    /**
+     * Ensures that an exception is thrown when a non-existent Resource is specified for removal
+     *
+     * @return void
+     */
+    public function testResourceRemoveOneNonExistent()
+    {
+        try {
+            $this->_acl->remove('nonexistent');
+            $this->fail('Expected Zend_Acl_Exception not thrown upon removing a non-existent Resource');
+        } catch (Zend_Acl_Exception $e) {
+            $this->assertContains('not found', $e->getMessage());
+        }
+    }
+
+    /**
+     * Ensures that removal of all Resources works
+     *
+     * @return void
+     */
+    public function testResourceRemoveAll()
+    {
+        $resourceArea = new Zend_Acl_Resource('area');
+        $this->_acl->add($resourceArea)
+                   ->removeAll();
+        $this->assertFalse($this->_acl->has($resourceArea));
+    }
+
+    public function testRolePrivilegeAssert()
+    {
+        $roleGuest = new Zend_Acl_Role('guest');
+        $this->_acl->addRole($roleGuest)
+                   ->allow($roleGuest, null, 'somePrivilege', new Zend_AclTest_AssertTrue());
+        $this->assertTrue($this->_acl->isAllowed($roleGuest, null, 'somePrivilege'));
+        $this->_acl->allow($roleGuest, null, 'somePrivilege', new Zend_AclTest_AssertFalse());
+        $this->assertFalse($this->_acl->isAllowed($roleGuest, null, 'somePrivilege'));
+    }
+
+    /**
+     * Ensures that removing the default deny rule results in default deny rule
+     *
+     * @return void
+     */
+    public function testRemoveDefaultDeny()
+    {
+        $this->assertFalse($this->_acl->isAllowed());
+        $this->_acl->removeDeny();
+        $this->assertFalse($this->_acl->isAllowed());
+    }
+
+    /**
+     * Ensures that removing the default deny rule results in assertion method being removed
+     *
+     * @return void
+     */
+    public function testRemoveDefaultDenyAssert()
+    {
+        $this->_acl->deny(null, null, null, new Zend_AclTest_AssertFalse());
+        $this->assertTrue($this->_acl->isAllowed());
+        $this->_acl->removeDeny();
+        $this->assertFalse($this->_acl->isAllowed());
+    }
+
+    /**
+     * Ensures that removing the default allow rule results in default deny rule being assigned
+     *
+     * @return void
+     */
+    public function testRemoveDefaultAllow()
+    {
+        $this->_acl->allow();
+        $this->assertTrue($this->_acl->isAllowed());
+        $this->_acl->removeAllow();
+        $this->assertFalse($this->_acl->isAllowed());
+    }
+
+    /**
+     * Ensures that removing non-existent default allow rule does nothing
+     *
+     * @return void
+     */
+    public function testRemoveDefaultAllowNonExistent()
+    {
+        $this->_acl->removeAllow();
+        $this->assertFalse($this->_acl->isAllowed());
+    }
+
+    /**
+     * Ensures that removing non-existent default deny rule does nothing
+     *
+     * @return void
+     */
+    public function testRemoveDefaultDenyNonExistent()
+    {
+        $this->_acl->allow()
+                   ->removeDeny();
+        $this->assertTrue($this->_acl->isAllowed());
+    }
+
+    /**
+     * Ensures that for a particular Role, a deny rule on a specific Resource is honored before an allow rule
+     * on the entire ACL
+     *
+     * @return void
+     */
+    public function testRoleDefaultAllowRuleWithResourceDenyRule()
+    {
+        $this->_acl->addRole(new Zend_Acl_Role('guest'))
+                   ->addRole(new Zend_Acl_Role('staff'), 'guest')
+                   ->add(new Zend_Acl_Resource('area1'))
+                   ->add(new Zend_Acl_Resource('area2'))
+                   ->deny()
+                   ->allow('staff')
+                   ->deny('staff', array('area1', 'area2'));
+        $this->assertFalse($this->_acl->isAllowed('staff', 'area1'));
+    }
+
+    /**
+     * Ensures that for a particular Role, a deny rule on a specific privilege is honored before an allow
+     * rule on the entire ACL
+     *
+     * @return void
+     */
+    /**
+     * Ensure that basic rule removal works
+     *
+     * @return void
+     */
+    public function testRulesRemove()
+    {
+        $this->_acl->allow(null, null, array('privilege1', 'privilege2'));
+        $this->assertFalse($this->_acl->isAllowed());
+        $this->assertTrue($this->_acl->isAllowed(null, null, 'privilege1'));
+        $this->assertTrue($this->_acl->isAllowed(null, null, 'privilege2'));
+        $this->_acl->removeAllow(null, null, 'privilege1');
+        $this->assertFalse($this->_acl->isAllowed(null, null, 'privilege1'));
+        $this->assertTrue($this->_acl->isAllowed(null, null, 'privilege2'));
+    }
+
+    /**
+     * Ensures that removal of a Role results in its rules being removed
+     *
+     * @return void
+     */
+    public function testRuleRoleRemove()
+    {
+        $this->_acl->addRole(new Zend_Acl_Role('guest'))
+                   ->allow('guest');
+        $this->assertTrue($this->_acl->isAllowed('guest'));
+        $this->_acl->removeRole('guest');
+        try {
+            $this->_acl->isAllowed('guest');
+            $this->fail('Expected Zend_Acl_Role_Registry_Exception not thrown upon isAllowed() on non-existent Role');
+        } catch (Zend_Acl_Role_Registry_Exception $e) {
+            $this->assertContains('not found', $e->getMessage());
+        }
+        $this->_acl->addRole(new Zend_Acl_Role('guest'));
+        $this->assertFalse($this->_acl->isAllowed('guest'));
+    }
+
+    /**
+     * Ensures that removal of all Roles results in Role-specific rules being removed
+     *
+     * @return void
+     */
+    public function testRuleRoleRemoveAll()
+    {
+        $this->_acl->addRole(new Zend_Acl_Role('guest'))
+                   ->allow('guest');
+        $this->assertTrue($this->_acl->isAllowed('guest'));
+        $this->_acl->removeRoleAll();
+        try {
+            $this->_acl->isAllowed('guest');
+            $this->fail('Expected Zend_Acl_Role_Registry_Exception not thrown upon isAllowed() on non-existent Role');
+        } catch (Zend_Acl_Role_Registry_Exception $e) {
+            $this->assertContains('not found', $e->getMessage());
+        }
+        $this->_acl->addRole(new Zend_Acl_Role('guest'));
+        $this->assertFalse($this->_acl->isAllowed('guest'));
+    }
+
+    /**
+     * Ensures that removal of a Resource results in its rules being removed
+     *
+     * @return void
+     */
+    public function testRulesResourceRemove()
+    {
+        $this->_acl->add(new Zend_Acl_Resource('area'))
+                   ->allow(null, 'area');
+        $this->assertTrue($this->_acl->isAllowed(null, 'area'));
+        $this->_acl->remove('area');
+        try {
+            $this->_acl->isAllowed(null, 'area');
+            $this->fail('Expected Zend_Acl_Exception not thrown upon isAllowed() on non-existent Resource');
+        } catch (Zend_Acl_Exception $e) {
+            $this->assertContains('not found', $e->getMessage());
+        }
+        $this->_acl->add(new Zend_Acl_Resource('area'));
+        $this->assertFalse($this->_acl->isAllowed(null, 'area'));
+    }
+
+    /**
+     * Ensures that removal of all Resources results in Resource-specific rules being removed
+     *
+     * @return void
+     */
+    public function testRulesResourceRemoveAll()
+    {
+        $this->_acl->add(new Zend_Acl_Resource('area'))
+                   ->allow(null, 'area');
+        $this->assertTrue($this->_acl->isAllowed(null, 'area'));
+        $this->_acl->removeAll();
+        try {
+            $this->_acl->isAllowed(null, 'area');
+            $this->fail('Expected Zend_Acl_Exception not thrown upon isAllowed() on non-existent Resource');
+        } catch (Zend_Acl_Exception $e) {
+            $this->assertContains('not found', $e->getMessage());
+        }
+        $this->_acl->add(new Zend_Acl_Resource('area'));
+        $this->assertFalse($this->_acl->isAllowed(null, 'area'));
+    }
+
+    /**
+     * Ensures that the $onlyParents argument to inheritsRole() works
+     *
+     * @return void
+     * @see    http://framework.zend.com/issues/browse/ZF-2502
+     */
+    public function testRoleInheritanceSupportsCheckingOnlyParents()
+    {
+        $this->_acl->addRole(new Zend_Acl_Role('grandparent'))
+                   ->addRole(new Zend_Acl_Role('parent'), 'grandparent')
+                   ->addRole(new Zend_Acl_Role('child'), 'parent');
+        $this->assertFalse($this->_acl->inheritsRole('child', 'grandparent', true));
+    }
+
+}

Added: 3.x/trunk/limb/acl/tests/cases/lmbAclObjectsFeaturesTest.class.php
===================================================================
--- 3.x/trunk/limb/acl/tests/cases/lmbAclObjectsFeaturesTest.class.php	                        (rev 0)
+++ 3.x/trunk/limb/acl/tests/cases/lmbAclObjectsFeaturesTest.class.php	2008-03-31 13:29:51 UTC (rev 6877)
@@ -0,0 +1,123 @@
+<?php
+/*
+* Limb PHP Framework
+*
+* @link http://limb-project.com
+* @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+* @license    LGPL http://www.gnu.org/copyleft/lesser.html
+*/
+lmb_require('limb/acl/src/lmbAcl.class.php');
+lmb_require('limb/acl/src/lmbAbstractRoleProvider.class.php');
+lmb_require('limb/acl/src/lmbAbstractResourceProvider.class.php');
+lmb_require('limb/acl/src/lmbRolesResolverInterface.interface.php');
+
+class Acl_Tests_Admin extends lmbAbstractRoleProvider
+{
+  public $_role = 'admin';
+}
+
+class Acl_Tests_User extends lmbAbstractRoleProvider
+{
+  protected $is_logged_in;
+  public $name;
+
+  function __construct($is_logged_in = false)
+  {
+    $this->is_logged_in = $is_logged_in;
+  }
+
+  function getRole()
+  {
+    if($this->is_logged_in)
+      return 'member';
+    else
+      return 'guest';
+  }
+}
+
+class Acl_Tests_Member extends lmbAbstractRoleProvider
+{
+  public $name;
+  protected $_role = 'member';
+
+  function __construct($name)
+  {
+    $this->name = $name;
+  }
+
+}
+
+class Acl_Tests_Article extends lmbAbstractResourceProvider implements lmbRolesResolverInterface
+{
+  protected $_resource = 'article';
+
+  function getRoleFor($object)
+  {
+    if('Bob' === $object->name)
+      return 'owner';
+    if('Valtazar' === $object->name)
+      return 'approver';
+  }
+}
+
+class lmbAclObjectsFeatureTest extends UnitTestCase
+{
+  protected $acl;
+
+  function setUp()
+  {
+    $this->acl = new lmbAcl();
+  }
+
+  function testGetRoleDefinedByProperty()
+  {
+    $admin = new Acl_Tests_Admin();
+    $this->assertEqual('admin', $admin->getRole());
+  }
+
+  function testGetRoleFromOverridedMethod()
+  {
+    $user = new Acl_Tests_User($is_logged_in = false);
+    $this->assertEqual('guest', $user->getRole());
+
+    $user = new Acl_Tests_User($is_logged_in = true);
+    $this->assertEqual('member', $user->getRole());
+  }
+
+  function testGetRoleFromResolver()
+  {
+    $article = new Acl_Tests_Article();
+
+    $user = new Acl_Tests_Member('Bob');
+    $this->assertEqual('owner', $article->getRoleFor($user));
+
+    $user = new Acl_Tests_Member('Valtazar');
+    $this->assertEqual('approver', $article->getRoleFor($user));
+  }
+
+  function testAclDynamicResolving()
+  {
+    $article = new Acl_Tests_Article();
+    $member = new Acl_Tests_Member('Vasya');
+    $owner = new Acl_Tests_Member('Bob');
+    $approver = new Acl_Tests_Member('Valtazar');
+
+    $this->acl->addRole('member');
+    $this->acl->addRole('owner', 'member');
+    $this->acl->addRole('approver', 'owner');
+    $this->acl->addResource('article');
+
+    $this->acl->allow('owner', 'article', 'edit');
+    $this->acl->allow('approver', 'article', 'disapprove');
+
+    $this->assertFalse($this->acl->isAllowed($member, $article, 'edit'));
+    $this->assertFalse($this->acl->isAllowed($member, $article, 'disapprove'));
+
+    $this->assertTrue($this->acl->isAllowed($owner, $article, 'edit'));
+    $this->assertFalse($this->acl->isAllowed($owner, $article, 'disapprove'));
+
+    $this->assertTrue($this->acl->isAllowed($approver, $article, 'edit'));
+    $this->assertTrue($this->acl->isAllowed($approver, $article, 'disapprove'));
+  }
+
+}

Added: 3.x/trunk/limb/acl/tests/cases/lmbAclTest.class.php
===================================================================
--- 3.x/trunk/limb/acl/tests/cases/lmbAclTest.class.php	                        (rev 0)
+++ 3.x/trunk/limb/acl/tests/cases/lmbAclTest.class.php	2008-03-31 13:29:51 UTC (rev 6877)
@@ -0,0 +1,373 @@
+<?php
+/*
+* Limb PHP Framework
+*
+* @link http://limb-project.com
+* @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+* @license    LGPL http://www.gnu.org/copyleft/lesser.html
+*/
+lmb_require('limb/acl/src/lmbAcl.class.php');
+
+class lmbAclTest extends UnitTestCase
+{
+  /**
+   * @var lmbAcl
+   */
+  public $acl;
+
+  function setUp()
+  {
+    $this->acl = new lmbAcl();
+  }
+
+  function testAddAndGetRoles()
+  {
+    $this->assertIdentical(count($this->acl->getRoles()), 0);
+    $this->assertFalse($this->acl->isRoleExist('guest'));
+    $this->acl->addRole('guest');
+    $this->assertIdentical(count($this->acl->getRoles()), 1);
+    $this->assertTrue($this->acl->isRoleExist('guest'));
+  }
+
+  function testRoleInherits()
+  {
+    $acl = $this->acl;
+
+    $acl->addRole('guest');
+    $this->assertIdentical($acl->getRoleInherits('guest'), array());
+
+    $acl->addRole('member', 'guest');
+    $this->assertIdentical($acl->getRoleInherits('member'), array('guest'));
+
+    $acl->addRole('admin', 'member');
+    $inherits = $acl->getRoleInherits('admin');
+    $this->assertTrue(in_array('member', $inherits));
+    $this->assertTrue(in_array('guest', $inherits));
+  }
+
+  function testRoleInheritsOnNotExistedRole()
+  {
+    try {
+      $this->acl->addRole('guest','tiabaltu');
+      $this->fail();
+    } catch(lmbAclException $e) {
+      $this->pass();
+    }
+  }
+
+  function testRoleInheritsMultiple()
+  {
+    $acl = $this->acl;
+
+    $acl->addRole('guest');
+    $acl->addRole('member');
+    $acl->addRole('admin', array('guest', 'member'));
+
+    $inherits = $acl->getRoleInherits('admin');
+    $this->assertTrue(in_array('member', $inherits));
+    $this->assertTrue(in_array('guest', $inherits));
+  }
+
+  function testAddAndGetResources()
+  {
+    $this->assertIdentical(count($this->acl->getResources()), 0);
+    $this->assertFalse($this->acl->isResourceExist('content'));
+    $this->acl->addResource('content');
+    $this->assertIdentical(count($this->acl->getResources()), 1);
+    $this->assertTrue($this->acl->isResourceExist('content'));
+  }
+
+  function testResourceInherits()
+  {
+    $acl = $this->acl;
+
+    $acl->addResource('content');
+    $this->assertIdentical($acl->getResourceInherits('content'), array());
+
+    $acl->addResource('articles', 'content');
+    $this->assertIdentical($acl->getResourceInherits('articles'), array('content'));
+
+    $acl->addResource('news', 'articles');
+    $inherits = $acl->getResourceInherits('news');
+    $this->assertTrue(in_array('articles', $inherits));
+    $this->assertTrue(in_array('content', $inherits));
+  }
+
+  function testResourceInheritsOnNotExistedResource()
+  {
+    try {
+      $this->acl->addResource('content','tiabaltu');
+      $this->fail();
+    } catch(lmbAclException $e) {
+      $this->pass();
+    }
+  }
+
+  function testResourceInheritsMultiple()
+  {
+    $acl = $this->acl;
+
+    $acl->addResource('content');
+    $acl->addResource('articles');
+    $acl->addResource('news', array('content', 'articles'));
+
+    $inherits = $acl->getResourceInherits('news');
+    $this->assertTrue(in_array('articles', $inherits));
+    $this->assertTrue(in_array('content', $inherits));
+  }
+
+  function testIsAllowedNonExistent()
+  {
+    $this->acl->addRole('guest');
+    $this->acl->addResource('news');
+
+    try {
+      $this->acl->isAllowed('guest', 'not exist', 'view');
+      $this->fail();
+    } catch (lmbAclException $e) {
+      $this->pass();
+    }
+
+    try {
+      $this->acl->isAllowed('not exist', 'news', 'view');
+      $this->fail();
+    } catch (lmbAclException $e) {
+      $this->pass();
+    }
+
+    try {
+      $this->acl->isAllowed('guest', 'news', 'view');
+      $this->pass();
+    } catch (lmbAclException $e) {
+      $this->fail();
+    }
+  }
+
+  function testDefaultDeny()
+  {
+    $this->acl->addRole('guest');
+    $this->acl->addResource('news');
+    $this->assertFalse($this->acl->isAllowed('guest', 'news', 'view'));
+  }
+
+  function testAllowAndDenyOnPrivelege()
+  {
+    $this->acl->addRole('guest');
+    $this->acl->addResource('news');
+    $this->acl->allow('guest', 'news', 'view');
+    $this->assertTrue($this->acl->isAllowed('guest', 'news', 'view'));
+    $this->acl->deny('guest', 'news', 'view');
+    $this->assertFalse($this->acl->isAllowed('guest', 'news', 'view'));
+  }
+
+  function testAllowAndDenyOnResource()
+  {
+    $this->acl->addRole('guest');
+    $this->acl->addResource('news');
+    $this->acl->allow('guest', 'news');
+    $this->assertTrue($this->acl->isAllowed('guest', 'news'));
+    $this->acl->deny('guest', 'news');
+    $this->assertFalse($this->acl->isAllowed('guest', 'news'));
+  }
+
+  function testAllowAndDenyOnRole()
+  {
+    $this->acl->addRole('admin');
+    $this->acl->allow('admin');
+    $this->assertTrue($this->acl->isAllowed('admin'));
+    $this->acl->deny('admin');
+    $this->assertFalse($this->acl->isAllowed('admin'));
+  }
+
+  function testAllowAndDenyOnRoleForAllResource()
+  {
+    $this->acl->addRole('guest');
+    $this->acl->addResource('news');
+    $this->acl->allow('guest', null, 'view');
+    $this->assertTrue($this->acl->isAllowed('guest', 'news', 'view'));
+    $this->assertFalse($this->acl->isAllowed('guest', 'news', 'add'));
+    $this->acl->deny('guest', null, 'view');
+    $this->assertFalse($this->acl->isAllowed('guest', 'news', 'view'));
+  }
+
+  function testAllowAndDenyLevelsCombinations()
+  {
+    $this->acl->addRole('guest');
+    $this->acl->addResource('news');
+    $this->acl->addResource('articles');
+
+    $this->acl->allow('guest');
+    $this->assertTrue($this->acl->isAllowed('guest', 'news', 'view'));
+    $this->assertTrue($this->acl->isAllowed('guest', 'news', 'add'));
+
+    $this->acl->deny('guest', 'news');
+    $this->assertFalse($this->acl->isAllowed('guest', 'news', 'view'));
+    $this->assertFalse($this->acl->isAllowed('guest', 'news', 'add'));
+
+    $this->acl->allow('guest', 'news', 'view');
+    $this->assertTrue($this->acl->isAllowed('guest', 'news', 'view'));
+    $this->assertFalse($this->acl->isAllowed('guest', 'news', 'add'));
+
+    $this->acl->deny('guest', 'news');
+    $this->assertFalse($this->acl->isAllowed('guest', 'news', 'view'));
+    $this->assertFalse($this->acl->isAllowed('guest', 'news', 'add'));
+
+    $this->acl->allow('guest');
+    $this->assertTrue($this->acl->isAllowed('guest', 'news', 'view'));
+    $this->assertTrue($this->acl->isAllowed('guest', 'news', 'add'));
+
+  }
+
+  function testAllowAndDenyWithInherits()
+  {
+    $this->acl->addRole('guest');
+    $this->acl->addRole('member', 'guest');
+
+    $this->acl->addResource('news');
+
+    $this->acl->allow('guest', 'news', 'view');
+    $this->acl->allow('member', 'news', 'vote');
+
+    $this->assertTrue($this->acl->isAllowed('guest', 'news', 'view'));
+    $this->assertFalse($this->acl->isAllowed('guest', 'news', 'vote'));
+
+    $this->assertTrue($this->acl->isAllowed('member', 'news', 'view'));
+    $this->assertTrue($this->acl->isAllowed('member', 'news', 'vote'));
+  }
+
+  function testBlackBoxTest()
+  {
+    $acl = $this->acl;
+
+    $acl->addResource('content');
+
+    $acl->addRole('guest');
+    $acl->addRole('staff', 'guest');
+    $acl->addRole('editor', 'staff');
+    $acl->addRole('administrator');
+
+    // Guest may only view content
+    $acl->allow('guest', null, 'view');
+
+    // Staff inherits view privilege from guest, but also needs additional privileges
+    $acl->allow('staff', null, array('edit', 'submit', 'revise'));
+
+    // Editor inherits view, edit, submit, and revise privileges, but also needs additional privileges
+    $acl->allow('editor', null, array('publish', 'archive', 'delete'));
+
+    // Administrator inherits nothing but is allowed all privileges
+    $acl->allow('administrator');
+
+    // Access control checks based on above permission sets
+
+    $this->assertTrue($acl->isAllowed('guest', 'content', 'view'));
+    $this->assertFalse($acl->isAllowed('guest', 'content', 'edit'));
+    $this->assertFalse($acl->isAllowed('guest', 'content', 'submit'));
+    $this->assertFalse($acl->isAllowed('guest', 'content', 'revise'));
+    $this->assertFalse($acl->isAllowed('guest', 'content', 'publish'));
+    $this->assertFalse($acl->isAllowed('guest', 'content', 'archive'));
+    $this->assertFalse($acl->isAllowed('guest', 'content', 'delete'));
+    $this->assertFalse($acl->isAllowed('guest', 'content', 'unknown'));
+    $this->assertFalse($acl->isAllowed('guest'));
+
+    $this->assertTrue($acl->isAllowed('staff', 'content', 'view'));
+    $this->assertTrue($acl->isAllowed('staff', 'content', 'edit'));
+    $this->assertTrue($acl->isAllowed('staff', 'content', 'submit'));
+    $this->assertTrue($acl->isAllowed('staff', 'content', 'revise'));
+    $this->assertFalse($acl->isAllowed('staff', 'content', 'publish'));
+    $this->assertFalse($acl->isAllowed('staff', 'content', 'archive'));
+    $this->assertFalse($acl->isAllowed('staff', 'content', 'delete'));
+    $this->assertFalse($acl->isAllowed('staff', 'content', 'unknown'));
+    $this->assertFalse($acl->isAllowed('staff'));
+
+    $this->assertTrue($acl->isAllowed('editor', 'content', 'view'));
+    $this->assertTrue($acl->isAllowed('editor', 'content', 'edit'));
+    $this->assertTrue($acl->isAllowed('editor', 'content', 'submit'));
+    $this->assertTrue($acl->isAllowed('editor', 'content', 'revise'));
+    $this->assertTrue($acl->isAllowed('editor', 'content', 'publish'));
+    $this->assertTrue($acl->isAllowed('editor', 'content', 'archive'));
+    $this->assertTrue($acl->isAllowed('editor', 'content', 'delete'));
+    $this->assertFalse($acl->isAllowed('editor', 'content', 'unknown'));
+    $this->assertFalse($acl->isAllowed('editor'));
+
+    $this->assertTrue($acl->isAllowed('administrator', 'content', 'view'));
+    $this->assertTrue($acl->isAllowed('administrator', 'content', 'edit'));
+    $this->assertTrue($acl->isAllowed('administrator', 'content', 'submit'));
+    $this->assertTrue($acl->isAllowed('administrator', 'content', 'revise'));
+    $this->assertTrue($acl->isAllowed('administrator', 'content', 'publish'));
+    $this->assertTrue($acl->isAllowed('administrator', 'content', 'archive'));
+    $this->assertTrue($acl->isAllowed('administrator', 'content', 'delete'));
+    $this->assertTrue($acl->isAllowed('administrator', 'content', 'unknown'));
+    $this->assertTrue($acl->isAllowed('administrator'));
+
+    // Some checks on specific areas, which inherit access controls from the root ACL node
+    $acl->addResource('newsletter');
+    $acl->addResource('pending', 'newsletter');
+    $acl->addResource('gallery');
+    $acl->addResource('profiles', 'gallery');
+    $acl->addResource('config');
+    $acl->addResource('hosts', 'config');
+
+    $this->assertTrue($acl->isAllowed('guest', 'pending', 'view'));
+    $this->assertTrue($acl->isAllowed('staff', 'profiles', 'revise'));
+    $this->assertTrue($acl->isAllowed('staff', 'pending', 'view'));
+    $this->assertTrue($acl->isAllowed('staff', 'pending', 'edit'));
+    $this->assertFalse($acl->isAllowed('staff', 'pending', 'publish'));
+    $this->assertFalse($acl->isAllowed('staff', 'pending'));
+    $this->assertFalse($acl->isAllowed('editor', 'hosts', 'unknown'));
+    $this->assertTrue($acl->isAllowed('administrator', 'pending'));
+
+    // Add a new group, marketing, which bases its permissions on staff
+    $acl->addRole('marketing', 'staff');
+
+    // Refine the privilege sets for more specific needs
+
+    // Allow marketing to publish and archive newsletters
+    $acl->allow('marketing', 'newsletter', array('publish', 'archive'));
+
+    // Allow marketing to publish and archive latest news
+    $acl->addResource('news');
+    $acl->addResource('latest', 'news');
+    $acl->allow('marketing', 'latest', array('publish', 'archive'));
+
+    // Deny staff (and marketing, by inheritance) rights to revise latest news
+    $acl->deny('staff', 'latest', 'revise');
+
+    $acl->addResource('announcement', 'news');
+
+    $this->assertTrue($acl->isAllowed('marketing', 'content', 'view'));
+    $this->assertTrue($acl->isAllowed('marketing', 'content', 'edit'));
+    $this->assertTrue($acl->isAllowed('marketing', 'content', 'submit'));
+    $this->assertTrue($acl->isAllowed('marketing', 'content', 'revise'));
+    $this->assertFalse($acl->isAllowed('marketing', 'content', 'publish'));
+    $this->assertFalse($acl->isAllowed('marketing', 'content', 'archive'));
+    $this->assertFalse($acl->isAllowed('marketing', 'content', 'delete'));
+    $this->assertFalse($acl->isAllowed('marketing', 'content', 'unknown'));
+    $this->assertFalse($acl->isAllowed('marketing'));
+
+    $this->assertTrue($acl->isAllowed('marketing', 'newsletter', 'publish'));
+    $this->assertFalse($acl->isAllowed('staff', 'pending', 'publish'));
+    $this->assertTrue($acl->isAllowed('marketing', 'newsletter', 'archive'));
+    $this->assertFalse($acl->isAllowed('marketing', 'newsletter', 'delete'));
+    $this->assertFalse($acl->isAllowed('marketing', 'newsletter'));
+
+    $this->assertTrue($acl->isAllowed('marketing', 'latest', 'publish'));
+    $this->assertTrue($acl->isAllowed('marketing', 'latest', 'archive'));
+    $this->assertFalse($acl->isAllowed('marketing', 'latest', 'delete'));
+    $this->assertFalse($acl->isAllowed('marketing', 'latest', 'revise'));
+    $this->assertFalse($acl->isAllowed('marketing', 'latest'));
+
+    $this->assertFalse($acl->isAllowed('marketing', 'announcement', 'archive'));
+    $this->assertFalse($acl->isAllowed('staff', 'announcement', 'archive'));
+
+    $this->assertFalse($acl->isAllowed('staff', 'latest', 'publish'));
+
+    $acl->allow('marketing', 'latest');
+
+    $this->assertTrue($acl->isAllowed('marketing', 'latest', 'archive'));
+    $this->assertTrue($acl->isAllowed('marketing', 'latest', 'publish'));
+    $this->assertTrue($acl->isAllowed('marketing', 'latest', 'edit'));
+    $this->assertTrue($acl->isAllowed('marketing', 'latest'));
+  }
+
+}

Added: 3.x/trunk/limb/acl/toolkit.inc.php
===================================================================
--- 3.x/trunk/limb/acl/toolkit.inc.php	                        (rev 0)
+++ 3.x/trunk/limb/acl/toolkit.inc.php	2008-03-31 13:29:51 UTC (rev 6877)
@@ -0,0 +1,18 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+
+/**
+ * @package fs
+ * @version $Id$
+ */
+lmb_require('limb/toolkit/src/lmbToolkit.class.php');
+lmb_require('limb/fs/src/lmbAclTools.class.php');
+lmbToolkit :: merge(new lmbAclTools());
+
+



More information about the limb-svn mailing list