2009年5月24日星期日

Re: [fw-auth] Zend_Acl: allow members to view all product and guests to view latest only

Actually, it does work as long as you register your acl rules using real objects and not their string ids. If you pass in strings, the ACL automatically creates generic resource/role objects and passes those to the assertions. But if you use real objects, then those same objects are stored in the ACL role/resource registries.

Here is some sample code that shows custom role/resource objects being passed to the assertion:

<?php

class MyResource implements Zend_Acl_Resource_Interface
{
    public function getResourceId()
    {
        return 'myresource:1';
    }
}

class MyRole implements Zend_Acl_Role_Interface
{
    public function getRoleId()
    {
        return 'myrole:2';
    }
}

class MyAssertion 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 get_class($role); // prints "MyRole"
        echo get_class($resource); // prints "MyResource"
        return ($role instanceof MyRole AND $resource instanceof MyResource);
    }
}

$acl = new Zend_Acl();

$myRole = new MyRole();
$myResource = new MyResource();
$myAssertion = new MyAssertion();

$acl->add($myResource);
$acl->addRole($myRole);

$acl->allow($myRole, $myResource, null, $myAssertion);
$acl->isAllowed($myRole, $myResource); // returns true

In order for it to work in a real-world application is to provide unique resource IDs for each resource, and the same with roles. Basically, you can't create a generic resource "product" that represents all of the products in the system, unless you want a rule that applies to all of them.

In a real product class, the getResourceId() method should return a unique resource Id for that product -- like "product:123".

If your products inherit from a base "product" resource, and no matching rule exists for the specific resource "product:123", that's when the generic resource kicks in (which is what you saw in your assertion).

-Hector


On Sun, May 24, 2009 at 10:43 AM, Abraham Block <atblock@gmail.com> wrote:
Hector,
Last time I tried something like this I ran into this bug (http://zendframework.com/issues/browse/ZF-1721) which is still not fixed as far as I know! Because of this bug, your resource being injected into the assertion is not your object but a string. I wrote a blog post on how I got around this (http://www.aviblock.com/blog/2009/03/19/acl-in-zend-framework/)

Was this working for you, or are you just conjecturing? 


On Sun, May 24, 2009 at 12:23 PM, Hector Virgen <djvirgen@gmail.com> wrote:
I've been working with the ACL lately and here's what I've come up with. Hopefully it will help.

First, update your Product class so it implements Zend_Acl_Resource_Interface. This will allow you to pass your product object in as a parameter in $acl->isAllowed().

class Product implements Zend_Acl_Resource_Interface
{
    /* ... */
    public function getResourceId()
    {
        return "product:{$this->_id}";
    }
    /* ... */
}

Then create a new Acl Assertion class for guests that will return true if the date is within the allowed range:

class ProductWithinDateAssertion 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)
    {
        // return null if resource is not a product.
        if (!$resource instanceof Product) return null;

        // return true if product is within date range
        $minDate = time() - (60 * 60 * 24 * 30); // 30 days
        return ($product->getDate() > $minDate);
    }
}

You'll need to update your ACL before querying it, like this:

$product = new Product(123);
$acl->add($product);
$acl->allow('guest', $product, 'view', new ProductWithinDateAssertion());

$acl->isAllowed('guest', $product, 'view'); // returns true or false based on the date of the product.

You might want to look at these pages for more details on how this works:



-Hector


On Sat, May 23, 2009 at 9:08 AM, iceangel89 <comet2005@gmail.com> wrote:

how can i make my acl such that members can view all products and guests view
latest/most popular only, as a trial?
--
View this message in context: http://www.nabble.com/Zend_Acl%3A-allow-members-to-view-all-product-and-guests-to-view-latest-only-tp23685837p23685837.html
Sent from the Zend Auth mailing list archive at Nabble.com.




没有评论: