An alternative implementation proposal
The approach I propose is very similar to what has been implemented with great success by major frameworks like CakePHP, phpgacl, Spring Framework, Flow 3 and probably hundreds of other projects. I believe that the approach I propose is even cheaper to implement than the currently proposed approach (the way I understand it). And above all: I'm quite sure that it will considerably improve usability of custom role configuration and day-to-day user-to-role assignments.
I propose to establish the following entities to implement authorization:
- access objects (=currently page or component handlers, can be extended to other objects)
- access operations (=currently page or component operations, can be extended to other operations)
- access objects and access operations can be grouped together into access object groups (=in our case this could be workflows like submission, proofreading, etc.)
- access object groups are assigned to roles (=editor role, author role or any "flexible" custom role)
- users are assigned to roles
- The GUI for custom role administration could IMO be greatly simplified:
____________________________________________________ | Drop down: role | | | | Available workflows: Assigned workflows: | | _____________________ _____________________ | | |workflow 1 | |workflow 6 | | | |workflow 2 | |workflow 7 | | | |workflow 3 | -> |workflow 8 | | | |workflow 4 | <- | | | | |workflow 5 | | | | | |... | | | | | --------------------- --------------------- | | | | Button: Create new role | Drop down: based on | |__________________________________________________|
This will replace all six role configuration sections in press setup step 3 (Workflows). The workflows can also be graphically grouped together into subgroups if we have too many of them. (Think of a tree-like arrangement on the left side.) As they are strictly hierarchical, this is not a problem. The many new "roles" that have been created for OMP will be labeled "workflows" (=access object groups) instead.
- The role-to-user assignment would remain exactly as it is (with custom roles appearing as any other role).
- On the database side we need two new tables. One that assigns access object groups to roles and another that assigns low-level access object-operation tuples to access object groups. The existing user to role assignment does not need to be touched. The access objects (handlers) and access operations (handler operations) can be quickly retrieved in a semi-automatic way from the existing index.php pages for page handlers to create the initial database entries in the permission tables.
- Authorization (="user validation") can be removed (with a few exceptions) from the handlers and replaced by a single authorization call in the dispatcher (after the handler operation has been identified but before the handler is actually being called). It comes down to 1 line of code in the dispatcher and a single "AuthorizationManager" class with maybe 50-100 lines of code that does all the work.
- A nice side-effect: Once we have the operation to handler mapping in the database we can also easily get rid of the index.php files altogether and retrieve the contained routing information from the database instead (solves #4876).
Generally I think this kind of design would greatly improve the flexibility of our authorization system while simplifying it at the same time. We'd drastically reduce the amount of authorization code necessary. We'd move from decentralized to centralized authorization and from a blacklist to a whitelist approach which both should reduce the probability of security breaches. And we'd IMO get a much more usable and easy-to-understand user interface for the end user. We'd get fully flexible "custom roles" that can be configured in a more intuitive way (=appealing to concepts already known by the user) than they are now. And "custom roles" would no longer be restricted to mere "synonyms" of hard coded roles.