Issues

ZF-2257: Zend_Acl - access control list processing error

Description

Bug example follows:


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

$acl = new Zend_Acl();

$acl->addRole(new Zend_Acl_Role('foo'));
$acl->add(new Zend_Acl_Resource('bar'));

$acl->allow('foo','bar');
$acl->deny('foo');

echo 'access to bar by foo is '.($acl->isAllowed('foo','bar') ? 'allowed' : 'denied');

I've encountered an error during processing simple ACL. First, we allow acces to resource 'bar' by 'foo' role, and then we deny access to all resources by this role. Expecting result is 'denied', but unfortunately 'allowed' appears on screen...

ACL works as expected when we explictly pass a resource to deny method, - try change last acl line to:


$acl->deny('foo','bar');

Comments

This is not a bug, it works as intended. $acl->deny('foo') means deny 'foo' access to all resources where other rules have not been defined. It basically sets a default.

Please evaluate and categorize as necessary.

I still think that it's a bug.

If $acl->allow('foo') gives access to ALL resources to foo role, then why $acl->deny('foo') doesn't do opposite ? If, as you say, $acl->deny('foo') means deny 'foo' access to all resources where other rules have not been defined then why $acl->deny('foo', 'bar') doesn't mean the same (deny 'foo' access to 'bar' WHERE OTHER RULES HAVE NOT BEEN DEFINED) ???

Besides, I'd understand your explanation if it really should be used to set a default values, BUT it is the way acl works by default WITHOUT explictly calling $acl->deny(). So what is a deny() method() possible NULL values for? If it shouldn't be called with NULL values then why are they declared as default in following php implementation?

public function deny($roles = null, $resources = null, $privileges = null, Zend_Acl_Assert_Interface $assert = null)

You should throw an exception in such a situation and not declare it as default.

After I review ZF ACL php code It looks for me like that it is a consequence of chosen implementation and it's not easily fixable.

I agree with you, Bogdan, that it is very confusing. The documentation should make clear, that a "null" value doesn´t actually mean "all" roles/resources but "all, if not defined otherwise".

But I think a change to this issue would have some performance impact as in your example, the whole rule tree would have to be traversed to deny every single rule that was allowed for the various resources (child resources of what you want to deny). The other way around "$acl->allow('admin');" would have to set "allow" for every previously set rule.

So I would suggest a convention, that either, you don´t use resources at all ($resource = null) or always define resources, but never mixing those two approaches. When using both, "null" should only be used as a fallback setting.

Perhaps this issue would be more completely resolved with additions and/or modifications to the documentation. Indeed, the behavior described is the behavior intended - that the use of {{null}} implies a fallback or default rule in the case where a more specific rule does not apply. In general, Zend_Acl obeys a given rule if and only if a more specific rule does not apply.

Shall we reopen the issue until documentation is updated thusly?

In general, Zend_Acl obeys a given rule if and only if a more specific rule does not apply.

And that's a sentence missing in documentation! It explains every "problem" mentioned in this issue. I think issue should be reopened until documentation is updated.

Reopening pending addition to documentation.

Resolved with SVN r9112.

Updating for the 1.6.0 release.