Issues

ZF-1722: Zend_Acl assertions broken when inheritance is required (ie DepthFirstSearch)

Issue Type: Bug Created: 2007-07-14T21:45:52.000+0000 Last Updated: 2009-09-29T07:22:54.000+0000 Status: Resolved Fix version(s): - 1.9.1 (11/Aug/09)

Reporter: Ralph Schindler (ralph) Assignee: Ralph Schindler (ralph) Tags: - Zend_Acl

Related issues: - ZF-5425

Attachments:

Description

Reproduction code

<pre class="highlight">
webdeveloper@webdevelopment ~/testing $ cat test_aclwhoswho.php 
<?php

require_once 'Zend/Acl.php';
require_once 'Zend/Acl/Role.php';
require_once 'Zend/Acl/Resource.php';

class HasIQFor implements Zend_Acl_Assert_Interface
{
    public function assert(Zend_Acl $acl, Zend_Acl_Role_Interface $role = null,
                           Zend_Acl_Resource_Interface $resource = null, $privilege = null)
    {
        echo "digging deeper";
        echo var_dump($role);
    }
}

class Acl_Child implements Zend_Acl_Role_Interface { public function getRoleId() { return 'Child'; } }
class Acl_Parent implements Zend_Acl_Role_Interface { public function getRoleId() { return 'Parent'; } }

$acl = new Zend_Acl();
$acl->addRole(new Zend_Acl_Role('Child'))
    ->addRole(new Zend_Acl_Role('Parent'), 'Child')
    ->add(new Zend_Acl_Resource('Toy'))
    ->add(new Zend_Acl_Resource('PokerGame'))
    ->allow('Child', 'Toy', 'Play', new HasIQFor())
    ->allow('Parent', 'PokerGame', 'Play', new HasIQFor());

$child = new Acl_Child();
$mommy = new Acl_Parent();

echo "Children and toys?\n"; echo $acl->isAllowed($child, 'Toy', 'Play');
echo "\n\nChildren and poker?\n"; echo $acl->isAllowed($child, 'PokerGame', 'Play');
echo "\n\nParents and toys?\n"; echo $acl->isAllowed($mommy, 'Toy', 'Play');
echo "\n\nParents and poker?\n"; echo $acl->isAllowed($mommy, 'PokerGame', 'Play');

webdeveloper@webdevelopment ~/testing $ php test_aclwhoswho.php 
Children and toys?
digging deeperobject(Zend_Acl_Role)#2 (1) {
  ["_roleId:protected"]=>
  string(5) "Child"
}


Children and poker?


Parents and toys?
digging deeperobject(Zend_Acl_Role)#2 (1) {
  ["_roleId:protected"]=>
  string(5) "Child"
}


Parents and poker?
digging deeperobject(Zend_Acl_Role)#4 (1) {
  ["_roleId:protected"]=>
  string(6) "Parent"
}

you can notice the problem in the 3rd case where when trying to determine if the parent has the IQ to play with the toy, the parent object is not passed to the assertion.

Comments

Posted by Darby Felton (darby) on 2007-07-26T11:55:20.000+0000

Postponing to after 1.0.1.

Posted by Darby Felton (darby) on 2007-08-01T15:02:36.000+0000

We should resolve this for 1.1.0.

Posted by Simon Mundy (peptolab) on 2007-09-27T17:44:42.000+0000

But why is this a problem? The rule is satisfied by the Child role and since there is no ACL specifically for Parents on the Toy then Zend_Acl returns true.

Wouldn't performance suffer if Zend_Acl iterates through the whole inheritance only to come to the same conclusion that it did in the first place? Or do you see a use case where a custom Assertion will need to query this hierarchy to supply a more qualitative answer?

Posted by Ralph Schindler (ralph) on 2007-09-28T11:49:12.000+0000

Hey Simon, The problem i specifically notice (from above) is in test case number 3. If I am writing custom assertions, then my assertion (if applied) should always get the exact object that i proposed when i asked if it "isAllowed".

<pre class="highlight">
// IF I DO:
$acl->isAllowed($mommy, 'Toy', 'Play'); // where mommy is of type (class Acl_Parent)

I should expect any assertions that were triggered as a result of that exact query should indeed get teh exact object i passed into the query. The reason for that expectation is in case I want to call some Acl_Parent specific methods in order to assert that what is queried should be allowed or not.

I see no direct performance impact, its simply a matter of whats being passed to the assertion.

as far as this statement: > Or do you see a use case where a custom Assertion will need to query this hierarchy to supply a more qualitative answer?

Assertions don't query the inheritance chain, its actually the other way around, currently the inheritance chain is iterated in order to trigger the appropriate assertion.

make sense?

Posted by Martin Pärtel (lagitus) on 2008-07-01T10:14:48.000+0000

This is still not fixed in 1.5.2, and is still quite irritating when trying to write any non-trivial assertions.

One workaround: Inherit Zend_Acl, override isAllowed(), store the parameters in a private member and make them available through a new method, say, "getLastRequest()". Then, in an assertion, get them using something like: list($role, $resource, $privilege) = $acl->getLastRequest();

(It's a good idea to make sure getLastRequest() always returns objects, even if a string was passed to isAllowed().)

Posted by Ralph Schindler (ralph) on 2009-07-30T18:41:14.000+0000

Fix in trunk as of r17317, please test.

Have you found an issue?

See the Overview section for more details.

Copyright

© 2006-2016 by Zend, a Rogue Wave Company. Made with by awesome contributors.

This website is built using zend-expressive and it runs on PHP 7.

Contacts