Problem with Zend_Acl

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Problem with Zend_Acl

Stefan Gehrig
Dear all,

I just started to use Zend_Acl for authorization in one of our projects but
either I do have some real problem understanding the use of assertions or
there is some flaw in the assertion design.
I don't know if some other developers stumbled upon this issue - perhaps
it's just that I don't understand the purpose of assertion correctly.
Let's say, we have the following domain models:

class App_User implements Zend_Acl_Role
{
        //...

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

        public function getRoleId()
        {
                return $this->_group;
        }

        //...
}

class App_GameSheet implements Zend_Acl_Resource
{
        //...

        public function getHomeTeamAdminId()
        {
                return $this->_homeTeamAdminId;
        }

        public function getLeagueAdminId()
        {
                return $this->_leagueAdminId;
        }

        public function getResourceId()
        {
                return __CLASS__;
        }

        //...
}

class App_Acl_GameSheetAssertion 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)
    {
        if (($resource instanceof App_GameSheet) && ($role instanceof
App_User)) {
            $userId = $role->getId();
            $leagueAdmin = $resource->getLeagueAdminId ();
            $homeTeamAdmin = $resource->getHomeTeamAdminId ();
            if (in_array($userId, array($leagueAdmin, $homeTeamAdmin))) {
                return true;
            } else {
                return false;
            }
        }
        return null;
    }
}

I though, I could do the following:

$acl = new Zend_Acl();
$acl->addRole(new Zend_Acl_Role('editor'));
$acl->addRole(new Zend_Acl_Role('admin'), 'editor);
$acl->add(new Zend_Acl_Resource('App_GameSheet');
$acl->allow('admin', null, null, null);
$acl->allow('editor', 'App_GameSheet', null, new
App_Acl_GameSheetAssertion());

$gameSheet = App_GameSheet::load(123);
$user = App_User::load(456);
var_dump($acl->isAllowed($user, $gameSheet, null));

The problem now is that Zend_Acl changes $role and $resource to simple
Zend_Acl_Role and Zend_Acl_Resource objects before passing them into the
assertion.
Am I totally wrong in my understanding of how this should work? I personally
think that the preceding solution would be a very elegant way to cope with
such issues.

Should this be considered a bug or rather an idea for improvement (as this
surely would break BC it would have to wait until ZF 2.0 I assume)?
Is there any other workaround or design that solves this problem using
Zend_Acl? I really thought that I found the philosopher's stone for this
problem ;-)

Thanks to all of you!

Best regards

Stefan



Reply | Threaded
Open this post in threaded view
|

Re: [fw-general] Problem with Zend_Acl

Mon Zafra
That's how I expected assertions to work as well. Transforming the roles and resources into normal Zend_Acl_Role/Resource really limits the usefulness of assertions. This issue is exactly two years old now. There are some workarounds in http://framework.zend.com/issues/browse/ZF-1721 and related issues.

   -- Mon


On Sun, Jun 14, 2009 at 4:55 PM, Stefan Gehrig <[hidden email]> wrote:
Dear all,

I just started to use Zend_Acl for authorization in one of our projects but
either I do have some real problem understanding the use of assertions or
there is some flaw in the assertion design.
I don't know if some other developers stumbled upon this issue - perhaps
it's just that I don't understand the purpose of assertion correctly.
Let's say, we have the following domain models:

class App_User implements Zend_Acl_Role
{
       //...

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

       public function getRoleId()
       {
               return $this->_group;
       }

       //...
}

class App_GameSheet implements Zend_Acl_Resource
{
       //...

       public function getHomeTeamAdminId()
       {
               return $this->_homeTeamAdminId;
       }

       public function getLeagueAdminId()
       {
               return $this->_leagueAdminId;
       }

       public function getResourceId()
       {
               return __CLASS__;
       }

       //...
}

class App_Acl_GameSheetAssertion 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)
   {
       if (($resource instanceof App_GameSheet) && ($role instanceof
App_User)) {
           $userId = $role->getId();
           $leagueAdmin = $resource->getLeagueAdminId ();
           $homeTeamAdmin = $resource->getHomeTeamAdminId ();
           if (in_array($userId, array($leagueAdmin, $homeTeamAdmin))) {
               return true;
           } else {
               return false;
           }
       }
       return null;
   }
}

I though, I could do the following:

$acl = new Zend_Acl();
$acl->addRole(new Zend_Acl_Role('editor'));
$acl->addRole(new Zend_Acl_Role('admin'), 'editor);
$acl->add(new Zend_Acl_Resource('App_GameSheet');
$acl->allow('admin', null, null, null);
$acl->allow('editor', 'App_GameSheet', null, new
App_Acl_GameSheetAssertion());

$gameSheet = App_GameSheet::load(123);
$user = App_User::load(456);
var_dump($acl->isAllowed($user, $gameSheet, null));

The problem now is that Zend_Acl changes $role and $resource to simple
Zend_Acl_Role and Zend_Acl_Resource objects before passing them into the
assertion.
Am I totally wrong in my understanding of how this should work? I personally
think that the preceding solution would be a very elegant way to cope with
such issues.

Should this be considered a bug or rather an idea for improvement (as this
surely would break BC it would have to wait until ZF 2.0 I assume)?
Is there any other workaround or design that solves this problem using
Zend_Acl? I really thought that I found the philosopher's stone for this
problem ;-)

Thanks to all of you!

Best regards

Stefan




Reply | Threaded
Open this post in threaded view
|

Re: [fw-general] Problem with Zend_Acl

Mon Zafra
Ooops, read the date incorrectly. It's actually 23 months old :p

   -- Mon


On Sun, Jun 14, 2009 at 5:52 PM, Mon Zafra <[hidden email]> wrote:
That's how I expected assertions to work as well. Transforming the roles and resources into normal Zend_Acl_Role/Resource really limits the usefulness of assertions. This issue is exactly two years old now. There are some workarounds in http://framework.zend.com/issues/browse/ZF-1721 and related issues.

   -- Mon



On Sun, Jun 14, 2009 at 4:55 PM, Stefan Gehrig <[hidden email]> wrote:
Dear all,

I just started to use Zend_Acl for authorization in one of our projects but
either I do have some real problem understanding the use of assertions or
there is some flaw in the assertion design.
I don't know if some other developers stumbled upon this issue - perhaps
it's just that I don't understand the purpose of assertion correctly.
Let's say, we have the following domain models:

class App_User implements Zend_Acl_Role
{
       //...

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

       public function getRoleId()
       {
               return $this->_group;
       }

       //...
}

class App_GameSheet implements Zend_Acl_Resource
{
       //...

       public function getHomeTeamAdminId()
       {
               return $this->_homeTeamAdminId;
       }

       public function getLeagueAdminId()
       {
               return $this->_leagueAdminId;
       }

       public function getResourceId()
       {
               return __CLASS__;
       }

       //...
}

class App_Acl_GameSheetAssertion 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)
   {
       if (($resource instanceof App_GameSheet) && ($role instanceof
App_User)) {
           $userId = $role->getId();
           $leagueAdmin = $resource->getLeagueAdminId ();
           $homeTeamAdmin = $resource->getHomeTeamAdminId ();
           if (in_array($userId, array($leagueAdmin, $homeTeamAdmin))) {
               return true;
           } else {
               return false;
           }
       }
       return null;
   }
}

I though, I could do the following:

$acl = new Zend_Acl();
$acl->addRole(new Zend_Acl_Role('editor'));
$acl->addRole(new Zend_Acl_Role('admin'), 'editor);
$acl->add(new Zend_Acl_Resource('App_GameSheet');
$acl->allow('admin', null, null, null);
$acl->allow('editor', 'App_GameSheet', null, new
App_Acl_GameSheetAssertion());

$gameSheet = App_GameSheet::load(123);
$user = App_User::load(456);
var_dump($acl->isAllowed($user, $gameSheet, null));

The problem now is that Zend_Acl changes $role and $resource to simple
Zend_Acl_Role and Zend_Acl_Resource objects before passing them into the
assertion.
Am I totally wrong in my understanding of how this should work? I personally
think that the preceding solution would be a very elegant way to cope with
such issues.

Should this be considered a bug or rather an idea for improvement (as this
surely would break BC it would have to wait until ZF 2.0 I assume)?
Is there any other workaround or design that solves this problem using
Zend_Acl? I really thought that I found the philosopher's stone for this
problem ;-)

Thanks to all of you!

Best regards

Stefan





Reply | Threaded
Open this post in threaded view
|

Re: Re: [fw-general] Problem with Zend_Acl

Abraham Block

I wrote a workaround on my blog http://www.aviblock.com/blog/2009/03/19/acl-in-zend-framework/#comments

On Sun, Jun 14, 2009 at 5:54 AM, Mon Zafra <[hidden email]> wrote:
Ooops, read the date incorrectly. It's actually 23 months old :p

   -- Mon



On Sun, Jun 14, 2009 at 5:52 PM, Mon Zafra <[hidden email]> wrote:
That's how I expected assertions to work as well. Transforming the roles and resources into normal Zend_Acl_Role/Resource really limits the usefulness of assertions. This issue is exactly two years old now. There are some workarounds in http://framework.zend.com/issues/browse/ZF-1721 and related issues.

   -- Mon



On Sun, Jun 14, 2009 at 4:55 PM, Stefan Gehrig <[hidden email]> wrote:
Dear all,

I just started to use Zend_Acl for authorization in one of our projects but
either I do have some real problem understanding the use of assertions or
there is some flaw in the assertion design.
I don't know if some other developers stumbled upon this issue - perhaps
it's just that I don't understand the purpose of assertion correctly.
Let's say, we have the following domain models:

class App_User implements Zend_Acl_Role
{
       //...

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

       public function getRoleId()
       {
               return $this->_group;
       }

       //...
}

class App_GameSheet implements Zend_Acl_Resource
{
       //...

       public function getHomeTeamAdminId()
       {
               return $this->_homeTeamAdminId;
       }

       public function getLeagueAdminId()
       {
               return $this->_leagueAdminId;
       }

       public function getResourceId()
       {
               return __CLASS__;
       }

       //...
}

class App_Acl_GameSheetAssertion 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)
   {
       if (($resource instanceof App_GameSheet) && ($role instanceof
App_User)) {
           $userId = $role->getId();
           $leagueAdmin = $resource->getLeagueAdminId ();
           $homeTeamAdmin = $resource->getHomeTeamAdminId ();
           if (in_array($userId, array($leagueAdmin, $homeTeamAdmin))) {
               return true;
           } else {
               return false;
           }
       }
       return null;
   }
}

I though, I could do the following:

$acl = new Zend_Acl();
$acl->addRole(new Zend_Acl_Role('editor'));
$acl->addRole(new Zend_Acl_Role('admin'), 'editor);
$acl->add(new Zend_Acl_Resource('App_GameSheet');
$acl->allow('admin', null, null, null);
$acl->allow('editor', 'App_GameSheet', null, new
App_Acl_GameSheetAssertion());

$gameSheet = App_GameSheet::load(123);
$user = App_User::load(456);
var_dump($acl->isAllowed($user, $gameSheet, null));

The problem now is that Zend_Acl changes $role and $resource to simple
Zend_Acl_Role and Zend_Acl_Resource objects before passing them into the
assertion.
Am I totally wrong in my understanding of how this should work? I personally
think that the preceding solution would be a very elegant way to cope with
such issues.

Should this be considered a bug or rather an idea for improvement (as this
surely would break BC it would have to wait until ZF 2.0 I assume)?
Is there any other workaround or design that solves this problem using
Zend_Acl? I really thought that I found the philosopher's stone for this
problem ;-)

Thanks to all of you!

Best regards

Stefan






Reply | Threaded
Open this post in threaded view
|

Re: Re: [fw-general] Problem with Zend_Acl

Hector Virgen
Try registering your actual App_User and App_GameSheet objects with your ACL instead of generic role/resource objects.

Change this:

$acl->addRole(new Zend_Acl_Role('editor'));
$acl->add(new Zend_Acl_Resource('App_GameSheet');

to this:

$acl->addRole(new App_User());
$acl->add(new App_GameSheet());

Internally, Zend_Acl creates a registry of roles/resources and uses the roleid/resourceid to retrieve the objects from the registry when checking assertions.

The only difficulty in this design is that you have to register each user/resource (unless they can all be grouped into one).

-Hector


On Sun, Jun 14, 2009 at 5:11 AM, Abraham Block <[hidden email]> wrote:

I wrote a workaround on my blog http://www.aviblock.com/blog/2009/03/19/acl-in-zend-framework/#comments


On Sun, Jun 14, 2009 at 5:54 AM, Mon Zafra <[hidden email]> wrote:
Ooops, read the date incorrectly. It's actually 23 months old :p

   -- Mon



On Sun, Jun 14, 2009 at 5:52 PM, Mon Zafra <[hidden email]> wrote:
That's how I expected assertions to work as well. Transforming the roles and resources into normal Zend_Acl_Role/Resource really limits the usefulness of assertions. This issue is exactly two years old now. There are some workarounds in http://framework.zend.com/issues/browse/ZF-1721 and related issues.

   -- Mon



On Sun, Jun 14, 2009 at 4:55 PM, Stefan Gehrig <[hidden email]> wrote:
Dear all,

I just started to use Zend_Acl for authorization in one of our projects but
either I do have some real problem understanding the use of assertions or
there is some flaw in the assertion design.
I don't know if some other developers stumbled upon this issue - perhaps
it's just that I don't understand the purpose of assertion correctly.
Let's say, we have the following domain models:

class App_User implements Zend_Acl_Role
{
       //...

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

       public function getRoleId()
       {
               return $this->_group;
       }

       //...
}

class App_GameSheet implements Zend_Acl_Resource
{
       //...

       public function getHomeTeamAdminId()
       {
               return $this->_homeTeamAdminId;
       }

       public function getLeagueAdminId()
       {
               return $this->_leagueAdminId;
       }

       public function getResourceId()
       {
               return __CLASS__;
       }

       //...
}

class App_Acl_GameSheetAssertion 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)
   {
       if (($resource instanceof App_GameSheet) && ($role instanceof
App_User)) {
           $userId = $role->getId();
           $leagueAdmin = $resource->getLeagueAdminId ();
           $homeTeamAdmin = $resource->getHomeTeamAdminId ();
           if (in_array($userId, array($leagueAdmin, $homeTeamAdmin))) {
               return true;
           } else {
               return false;
           }
       }
       return null;
   }
}

I though, I could do the following:

$acl = new Zend_Acl();
$acl->addRole(new Zend_Acl_Role('editor'));
$acl->addRole(new Zend_Acl_Role('admin'), 'editor);
$acl->add(new Zend_Acl_Resource('App_GameSheet');
$acl->allow('admin', null, null, null);
$acl->allow('editor', 'App_GameSheet', null, new
App_Acl_GameSheetAssertion());

$gameSheet = App_GameSheet::load(123);
$user = App_User::load(456);
var_dump($acl->isAllowed($user, $gameSheet, null));

The problem now is that Zend_Acl changes $role and $resource to simple
Zend_Acl_Role and Zend_Acl_Resource objects before passing them into the
assertion.
Am I totally wrong in my understanding of how this should work? I personally
think that the preceding solution would be a very elegant way to cope with
such issues.

Should this be considered a bug or rather an idea for improvement (as this
surely would break BC it would have to wait until ZF 2.0 I assume)?
Is there any other workaround or design that solves this problem using
Zend_Acl? I really thought that I found the philosopher's stone for this
problem ;-)

Thanks to all of you!

Best regards

Stefan







--
Hector Virgen