Almost every application with multiple user groups requires an Access Control List (ACL) system. There are dozens of ACL implementations. Most of them are buried deep in the applications that use them. Some of them even provide generic capabilities that can be used by extensions (or applications, plug-ins, whatever) to that system.
So one would think that there would be a good generic ACL system out there, or that it would be possible to extract a good general purpose ACL module from another application. Not so. There’s one, phpGACL, that has a lot of capability. But the implementation is monolithic… it looks like another case of sticking a class declaration around a bunch of procedural code and calling it object based. That just won’t do.
There are quite capable applications for implementing ACL. LDAP being one of the best and most popular. But asking the administrator of a relatively simple application to install and configure LDAP on their shared hosting system is a lot to ask. Ideally, the mechanics of the ACL system should be intuitive to the user, if not essentially transparent.
So what else to do but write a new one?
ACL is deceptively simple. At the basic level, you provide a user and an identifier for some resource and you get back an indication of what permission that user has over the resource. That’s easy.
But as soon as you add capabilities that are essential for all but the most basic needs, such as groups, everything gets very complicated. A few years ago I took my first crack at ACL and failed miserably. I stalled on the project’s complexity, left it alone for a while, and when I cam back to it a few months later the code was nearly opaque to me. Not a good sign, so I implemented a simple system targeted for my specific needs at the time and left the general code to gather dust.
A few weeks ago, the need for a more general ACL reared its head again. The Joomla! project, which I’m pretty deeply involved in, also is lacking in terms of fine grained access control. That’s when I looked at, and rejected phpGACL as a possible solution and decided once again to try developing a system from scratch.
Two weeks later and I’ve got most of a decent system up and running, but it hasn’t been easy. This is a case where writing concurrent unit tests has really helped. There’s some extraordinarily difficult logic required to handle conflicts, where two different parts of the ACL tree provide different permission results. The worst part of conflict testing is setting up a data set that contains specific conflicts (I find it extraordinarily hard to build data sets that are both complex and deliberately wrong). Unit tests allow me to build these data sets automatically and verify that a fix to one case doesn’t cause regressions in another. I think that without this testing tool, I would rapidly get bogged down once again and wind up with another pile of incomplete, useless code.