1

I need a solution where authenticated users are allowed access to certain Controllers/Actions based not on their user type :ie. admin or normal user (although I may add this using standard ACL later) but according to the current status of their user.

For example :

Have they been a member of the site for more than 1 week?

Have they filled in their profile fully?

Actually, now that I think about it, kind of like they have on this site with their priviledges and badges.

dimbo
  • 817
  • 1
  • 11
  • 25

1 Answers1

1

For dynamic condition-based tests like you are describing, you can use dynamic assertions in your Zend_Acl rules.

For example:

class My_Acl_IsProfileComplete implements Zend_Acl_Assert_Interface
{
    protected $user;

    public function __construct($user)
    {
        $this->user = $user;
    }

   public function assert(Zend_Acl $acl, 
                           Zend_Acl_Role_Interface $role = null,
                           Zend_Acl_Resource_Interface $resource = null,
                           $privilege = null)
    {
        // check the user's profile
        if (null === $this->user){
            return false;
        }
        return $this->user->isProfileComplete();  // for example
    }
}

Then when defining your Acl object:

$user = Zend_Auth::getInstance()->getIdentity();
$assertion = new My_Acl_Assertion_IsProfileComplete($user);
$acl->allow($role, $resource, $privilege, $assertion);

Of course, some of the details depend upon the specifics of what you need to check and what you can use in your depend upon what you store in your Zend_Auth::setIdentity() call - only a user Id, a full user object, etc. And the roles, resources, and privileges are completely app-specific. But hopefully this gives the idea.

Also, since the assertion object requires a user object at instantiation, this dynamic rule cannot be added at Bootstrap. But, you can create the core Acl instance with static rules during bootstrap and then register a front controller plugin (to run at preDispatch(), say) that adds the dynamic assertion. This way, the Acl is fully populated by the time you get to your controllers where presumably you would be checking them.

Just thinking out loud.

David Weinraub
  • 14,144
  • 4
  • 42
  • 64
  • Hi - just wondering if you've ever seen/used dynamic assertions generated from role-specific conditions? For example, in the OP's question `"a member of the site for more than 1 week"` could be `a member of the site for more than $n week(s)"` where `$n` is different for each role, so the admin would have access at `$n >= 0` weeks, a moderator might be `$n >= 1` and the actual member might be `$n >= 4`... – boatingcow Jan 13 '12 at 13:03
  • I've never seen it;an interesting question. But it seems that rules like that could be codified as an array keyed on rolenames with the number of weeks required in order to be considered "long enough". This array could be aded into the dynamic assertion, perhaps as an optional constructor argument (with sane defaults). Then when the `assert()` method of dynamic assertion is eventually invoked, it has the role-based rules (from instantiation) and the role in question (as part of the `assert()` signature), which should be enough. – David Weinraub Jan 13 '12 at 13:54
  • That's kind of what I was thinking. I asked a question a while back http://stackoverflow.com/questions/7526855/how-to-codify-and-store-dynamic-permission-constraints but didn't really get much further. Would be good to find some more resources on this type of thing! – boatingcow Jan 13 '12 at 14:03
  • _This_ SO question is probably not the place for a detailed discussion of _that_ SO question, but just 1 comment: Seems like the system you describe in that question has another level of abstraction on top of the above. That is, the role-based rules are not static, but need to be read from some a data store managed by the HR team. But it seems like you could codify each rule of those rules as a validator (fed from the datastore), wrap all the validators into a kind-of validator chain, and then pass that validator chain to the constructor of the dynamic assertion described above. – David Weinraub Jan 13 '12 at 15:12
  • Yes, will try not to hijack the original question! I think a mashup of the answer to @dimbo's original question and the _dynamic_ (i.e. not static) `dynamic assertions` I'm proposing would be a Good Thing. – boatingcow Jan 13 '12 at 16:24