ZF-10879: Acl stoped working in 1.11.1

Description

After upgrading from 1.11.0 to 1.11.1 Acl just does not work anymore in my code. I use a model based Acl system. If I use the Acl.php file from 1.11.0 in zf 1.11.1 then it works. I can't see what's wrong looking at the difference bewteen the two files. But what ever was changed in zf 1.11.1 Acl.php broke my code.

This is a critical element for me. If you need examples of my code it can be seen here: http://bazaar.launchpad.net/~shaun-shaunfreeman/…

Comments

Saying "it just does not work anymore" is not helpful. We cannot review your entire codebase to review how you are using the Acl component.

Please provide, at minimum, exactly what error message or unexpected behavior you are experiencing as well as a simple code sample (think: a dozen or two lines of code at most) to reproduce the problem.

There are no error messages. The expected behaviour is that Acl should only allow users with the right roles to access their allow areas.

A Guest can access the login and register actions but not admin and logout.

Also the menu should show links according to access rights.

Now when a guest views the site he can see all menu links and access the admin area. When trying to view the login area nothing appears when before he could see the login form. It seems all access is denied and/or not implemented.

When I set it so anyone can view login and tying loging in then the session is cleared when Zend_Auth should be set in it.

If I now use the Acl.php from zf 1.11.0 in zf 1.11.1 then everything works as it should.

The problem seems that Acl doesn't get set any more in the setRule method of Acl.php but I don't know why.

I am using a database to store the roles of the user which is queried when logging in and the the respective role is set.

I am still leaning this framework so I will try to reproduce the error in a dozen or two lines.

But as my code is in two or three classes I am finding it difficult to condense for the error to occur.

Acl is new to me and I am finding it difficult to understand so please be patience with me. All I now at the moment is it was working in zf 1.11.0 and now it is not in zf 1.11.1 and the problem lies somewhere in Acl.php or the changes that where made means I have to reimplement Acl differently.

I have worked out why it's not working.

In the zf 1.11.1 Acl.php in the setRule method all my resources get set into the $allResources array, but nothing is done with it! So all my resources do not get any any rules set to them.

This update has changed the way Acl works and breaks backward compatibility with zf 1.11.0, which in my opion shouldn't happen on a bug fix release.

Now there is a comment on line 652 which says {quote} $allResources = array(); // this might be used later if resource iteration is required {quote}

now if I add this code at line 656:


$resources = (count($allResources) > 0) ? $allResources : null;

it works again!

my acl model looks like this:


class Uthando_Model_Acl_Uthando extends Zend_Acl
{
    public function __construct()
    {
        $this->addRole(new Uthando_Model_Acl_Role_Guest)
             ->addRole(new Uthando_Model_Acl_Role_Registered)
             ->addRole(new Uthando_Model_Acl_Role_Manager, 'Registered')
             ->addRole(new Uthando_Model_Acl_Role_Administrator, 'Manager')
             ->addRole(new Uthando_Model_Acl_Role_SuperAdministrator, 'Administrator');

        $this->deny();

        $this->add(new Uthando_Model_Acl_Resource_Guest)
             ->allow('Guest')
             ->deny(array(
                 'Registered',
                 'Manager',
                 'Administrator',
                 'SuperAdministrator'
                 ));
        $this->add(new Uthando_Model_Acl_Resource_User)->allow('Registered');
        $this->add(new Uthando_Model_Acl_Resource_Admin)->allow('Manager');
    }
}

I hope this is helpful If you need more please let me know.

Shaun,

Could you take a look at the attached patch for Zend_Acl_AclTest and let me know if i've accurately reproduced the ACL usage you outlined in your last post?

I added your suggested modification to Zend_Acl:


Index: library/Zend/Acl.php
===================================================================
--- library/Zend/Acl.php (revision 23890)
+++ library/Zend/Acl.php (working copy)
@@ -654,6 +654,7 @@
                 $allResources[] = $rTarget['instance'];
             }
             unset($rTarget);
+            $resources = (count($allResources) > 0) ? $allResources : null;
         }

         // normalize privileges to array

and ran the test suite again with the attached test added, and the test still failed.

I think I may have spotted the problem....let me know if i'm on the right track here: When you run this code:


$this->add(new Uthando_Model_Acl_Resource_Guest)
     ->allow('Guest')
     ->deny(array(
         'Registered',
         'Manager',
         'Administrator',
         'SuperAdministrator'
     ));

It creates the resource Guest and, because add() returns an instance of Zend_Acl and you don't specify a resource on the chained allow() and deny() call, it globally allows Guest and denies everyone else. As Guest is the only resource available, that's fine. However, the next line:


$this->add(new Uthando_Model_Acl_Resource_User)->allow('Registered');

Creates a new resource User and allows Registered access, which applies to both User and Guest resources because add() returns Zend_Acl and your chained allow() call doesn't specify a resource. So, the allow('Registered') call affects both resources.

Does that seem like an accurate synopsis of what's happening?

If it does, you can fix it by adding the resource name each allow()/deny() call should apply to as the second argument to the allow()/deny() call