Hi Pat,
I've commented inline below:
Patrick Veach wrote:
> To Darby,
>
> Thank you for response. I really would like to have the api I mentioned.
> The current one is perfect for controller::action, but i think there is a
> need
> to be able to allow/deny at the modular level. There is a natural parental
> relationship between module::controller::action. This allows you to specify
> at each level exactly which resources are being allowed/denied.
You can allow/deny on any resource, including a module resource, if you
have defined one in the ACL. As I suggested before, you can structure
your resources such that the module is the parent resource of its child
controller resources. You can take this idea further by considering
actions as resources, and having their controllers be parents of their
action resources. In your case, however, you are treating actions as
Zend_Acl privileges, and this is valid usage as well.
By structuring your resources in a hierarchy, you can take advantage of
Zend_Acl's rule inheritance. That is, if you specify allow() on a module
resource, then this rule applies to all its children resources (i.e.,
controller [and action] resources) except where the inherited rule is
overridden by a rule upon the inheriting resource.
> Here are some things that bother me with the current non-modular ACL.
>
> Modules may have controllers::actions with the same name. The
> indexController comes to
> mind. How do you ban some index::action and allow others?
It does not matter to Zend_Acl whether controller actions have the same
name across modules. Zend_Acl is not tightly coupled to the controller
architecture. It only matters to Zend_Acl that a resource has a unique
identifier. You can create a unique identifier as follows:
$resourceId = "$module.$controller"; // action is a privilege
or
$resourceId = "$module.$controller.$action"; // not using privileges
How to set your allow/deny rules depends on your business rules. But,
I'll continue with the previous example. Again, assume we have:
$acl->add(new Zend_Acl_Resource($module))
->add(new Zend_Acl_Resource("$module.$controller"), $module);
for each $module and $controller in the system.
To deny everyone access to the 'delete' action for all modules and
controllers by default:
$acl->deny(null, null, 'delete');
To allow everyone access to the 'delete' action for all controllers of
the 'spam' module:
$acl->allow(null, 'spam', 'delete');
To deny everyone access to the 'delete' action for the 'index'
controller of the 'spam' module:
$acl->deny(null, 'spam.index', 'delete');
I would highly recommend reading the documentation and tracing the
examples in the documentation to understand rule inheritance and
privileges. The unit tests also have functional tests you can review
that utilize and test rule inheritance and privileges.
> Attempts to solve the above problems (and others) lead to complicated tests
> at the use point.
> i.e. first test the module then test the controller::action. instead of a
> nice clean $acl->allow(...);
No. You need only one call to Zend_Acl::isAllowed() to answer the
authorization query for a given role, resource, and privilege (optional).
To query against a controller action:
$acl->isAllowed($role, "$module.$controller", $action);
Continuing with the example, the following queries whether the current
$role has access to the 'delete' action of the 'index' controller in the
'spam' module:
$acl->isAllowed($role, 'spam.index', 'delete');
> I realize that the current ACL api isn't specific to the controller::action,
> but it does
> map onto the controller::action very nicely. With one more level of
> indirection it should
> map onto the module::controller::action.
Sure, and as I've indicated, this is already possible in userland with
the current API, and after 1.0.0 we may consider adding a plugin that
would provide this highly demanded integration.
I also like Ralf's idea of partitioning the ACL across modules. :)
Best regards,
Darby
>
> cheers,
>
> Pat Veach
>
>
>
>
>
>
>
>
>
>
>> Hi Pat,
>>
>> Though a major use of Zend_Acl is to restrict access to action
>> controllers, Zend_Acl is not limited to this purpose. Thus, its API is
>> not specific to controllers, actions, and modules.
>>
>> Yes, Zend_Acl is extensible, so you should be able to define isAllowed()
>> in an extending class if you want to transform the API as you have
>> indicated.
>>
>> I think that the underlying issue is how you identify and structure your
>> resources. Zend_Acl is flexible on how resources may be identified, so
>> maybe something like the following would work for you:
>>
>> class My_Acl extends Zend_Acl
>> {
>> public function isAllowed($role, $module, $controller, $action)
>> {
>> return parent::isAllowed($role, "$module.$controller", $action);
>> }
>> }
>>
>> The dot separator is arbitrary, and Zend_Acl per se does not care about
>> what role and resource identifiers are used, only that they are unique.
>> So you can come up with your own resource naming schema however
>> appropriate for your needs.
>>
>> Judging from your deny() and allow() usage examples, however, I suspect
>> that you need to organize the resources such that modules are parents of
>> controllers.
>>
>> $acl->add(new Zend_Acl_Resource($module))
>> ->add(new Zend_Acl_Resource("$module.$controller"), $module);
>>
>> Alternatively, you could override these methods in an extending class if
>> you require a specific API (e.g., in your examples below).
>>
>> Hope that helps!
>>
>> Best regards,
>> Darby
>>
>
>