views:

362

answers:

2

Hi All. Using PHP and Zend_ACL, I want to create an extremely flexible permissions system. I want to be able to assign permissions to all objects of a certain type, as well as to instances of those objects. If a specific instance of an object is queried and it doesn't exist in the resource tree then the permission set for the 'generic' object can be used. My problem is that this needs to nest and I can't figure out a way to do it without multiple inheritance, which Zend_ACL doesn't support.

An example would be this. An online learning site with faculties, courses, and events. Each event belongs to a course, and each course to a faculty. I would like to be able to permit each faculty role to access all the courses (and events by inheritance), but a particular faculty wants their material private. So I make the structure of my resource tree have a resource node for each faculty and have each course belonging to that faculty branch from the faculty node instead of branching from the generic course node which gives each course it's default permissions. With the new structure how can I apply my generic course permissions? The same goes for events below courses, if I want each event to only be readable if the parent course is readable, but I also want to apply a default set of permissions to each event, how can I organize the tree such that each event inherits from its parent and it's generic node without multiple inheritance?

Any questions or comments or suggestions for a different system are very welcome.

A: 

Zend ACL is extremely flexible. Permissions from the child overwrite the inherited permissions from the parent resources. Even if I don't completely get your example, I think the Zend ACL model support your design. You can access to specific resources for specific roles, without any problem.

Nevertheless, maybe you can read also about assertions, which give you an extra degree of freedom.

Elzo Valugi
I can't see a way to fit my requirements in to the current system. I want to be able to define a default set of rules for each type of object, but also give specific rules to instances of those objects while preserving inheritance among the types and instances. This means that event ID #4 inherits from its parent course instance, as well as the default event type.
In Zend_ACL faculties, courses and events they are all resources, and they inherit from each other.And let's say we have 2 roles: insider and outsider.When you construct your ACL tree you will allow by default acccess to all to the insider and close all access to the outsider for the same resources.This will be your default behaviour.Now if you want some special behaviour for a role/resource given an extra condition of your naming, you just atach an assertion to the rule. If the assertion is executed you have your exeception from general rule, otherwise the regular rule is executed.
Elzo Valugi
I've been playing around with assertions, and I think that they will work however designing and interface to allow application of them will be very hard. Also, http://zendframework.com/issues/browse/ZF-1721 prevents me from doing what I want with assertions (non-trivial stuff). Do you think I can deploy a patched Zend Framework?
I wouldn't recommend unless is for a simple project. On long term things will go messier and complicated. I've already tried this path with other bugs. If extending the current ACL class is not an option for you maybe you should build your own ACL system.
Elzo Valugi
+2  A: 

Your multiple inheritance problem is all in your head - unless of course can be in multiple faculties - etc. Build an additional "parent Resource" that can change ACL from the base "course".

You don't want the course to inherit the faculty permissions directly; you'll probably want someone to be able to edit the courses for that faculty (a TA or something) - but not the faculty itself right?

faculties, courses, and events. Each event belongs to a course, and each course to a faculty

Parent -> middleman -> child
Courses -> Courses:Faculty2 -> Courses:Faculty2:Course1 
Events -> Events:Course1 -> Events:Course1:Event3

etc

This will give you groups of Courses by faculty, but still inherit default course permissions. As you add each resource - just make it parent to its group resource, which parents to the overall resource.

If you want all events for a particular course to be hidden - you just set a permission on Event:Course#

If you want to be able to set a permission on all events of a faculty, you can just add another "middleman" parent above Event:Course1 that groups Events by Faculty as well: Events:Faculty2:Course1:Event3

I've found for a permissions system 9 times out of 10 you don't need (or want the confusion) of multiple inheritance. If your access control is more complicated than a simple tree, you should re-evaluate your access control.

gnarf