Ugly CakePHP ACL hack
(I appreciate if someone correct my engrish mistakes)
I found difficult to understand CakePHP DB-ACL model, I think the INI-ACL is the simplest and it is enoght for my needs, also I don't have shell access to the server where I'm deploying a simple application, so I can't bake (I guess it is possible to do that without baking too).
The syntax for the INI-ACL is very simple, it is the syntax of a old-school -windows days- ini file. And is something like this, you define users, groups, and objects. you can give or deny access to an object to a entire group or to a user.
You can combine ACL component with the CakePHP Auth component making it, very easy -and powerful- way to administer a website.
Here is a example.
[bofh] groups = admin, user allow = wipe_computer [luser] ;this guy is a bofh enemy groups = user deny = play [admin] allow = adminstuff [user] allow = work, play
The bad thing about INI-ACL is that is not so good integrated to the CakePHP framework like the DB-ACL component. So I decide to workaround a solution.
Look at this lines in my app_controller.php file.
class AppController extends Controller
{
...
function getACO()
{
return(strtolower(implode("/", array($this->name, $this->action))));
}
function canAccess()
{
return (bool) $this->Acl->check($this->Auth->user('username'), $this->getACO());
}
...
}I do not import the ACL nor Auth components into the AppController. They are only imported in the Controllers who need it.
I only need to use the function canAccess in the controller where I want ACL. Like this.
class UsersController extends AppController
{
...
function beforeFilter()
{
parent::beforeFilter();
$this->Auth->authorize = 'controller';
$this->Auth->loginError = __('wrongPassword', true);
$this->Auth->authError = __('notAuthorized', true);
$this->Auth->allow('register');
}
function isAuthorized()
{
return $this->canAccess();
}
...
}But this does not work without the following modification to the file: CAKE/libs/controller/components/acl.php (I know is ugly, it break the framework -but hey it works for me-)
class IniAcl extends AclBase {
...
function check($aro, $aco, $aco_action = null) {
if ($this->config == null) {
$this->config = $this->readConfigFile(CONFIGS . 'acl.ini.php');
}
$aclConfig = $this->config;
//this is my mod!
if (!isset($aclConfig[$aro])) {
$aro = "*";
}
//end of my mod!
if (isset($aclConfig[$aro]['deny'])) {
...
}This allows the following configuration of my APP/config/acl.ini.php
;Users [admin1] groups = admin, user, visitor [user1] groups = admin, user allow = admin/x [*] groups = user, visitor [] groups = visitor ;Groups [admin] allow = pages/admin_edit, pages/admin_index, pages/admin_add, users/admin_index, users/admin_edit, users/admin_add [user] allow = users/index, users/logout [visitor] allow = users/register, pages/display
As you can see this simple modification allows the use of '*' to reffer to any authenticated (thanks to the Auth component) user, and '´´' to anyone who is not authenticated. Very handy (I insist, for me)
