Hi,
I need to implement an ACL in my micro app, which is the best way??
Thanks, Stefano
|
Apr '15 |
2 |
1606 |
1 |
Hi Stefano,
Probably too late to help you, but just in case anyone else searches for this (as I did).
Most examples for ACL in Phalcon use controllers and views. In a Micro application there are no controllers or views. Here is a solution for a Micro framework using Collections (which help group handlers into Controllers)
//Create the ACL
$acl = new Phalcon\Acl\Adapter\Memory();
//The default action is DENY access
$acl->setDefaultAction(Phalcon\Acl::DENY);
/*
* ROLES
* Admin - can do anything
* User - can do most things
* Restricted User - read only
* */
$acl->addRole(new Phalcon\Acl\Role('Guest'));
$acl->addRole(new Phalcon\Acl\Role('Restricted User'));
$acl->addRole(new Phalcon\Acl\Role('User'));
$acl->addRole(new Phalcon\Acl\Role('Admin'));
// User can do everything a Restricted User can do
$acl->addInherit('User','Guest');
$acl->addInherit('User','Restricted User');
// Admin can do everything a User and Restricted User can do
$acl->addInherit('Admin','Guest');
$acl->addInherit('Admin','Restricted User');
$acl->addInherit('Admin','User');
/*
* RESOURCES
* for each user, specify the 'controller' and 'method' they have access to (user=>[controller=>[method,method]],...)
* this is created in an array as we later loop over this structure to assign users to resources
* */
$arrResources = [
'guest'=>[
'Users'=>['register','login','resetRequest','resetUpdate'],
],
'restrictedUser'=>[
'Users'=>['readOne'],
],
'user'=>[
'Users'=>['update','delete'],
],
'admin'=>[
'Accounts' => ['upgrade','paymentHistory','invoices']
]
];
foreach($arrResources as $arrResource){
foreach($arrResource as $controller=>$arrMethods){
$acl->addResource(new Phalcon\Acl\Resource($controller),$arrMethods);
}
}
/*
* ACCESS
* */
foreach ($acl->getRoles() as $objRole) {
$roleName = $objRole->getName();
//everyone gets access to global resources
foreach ($arrResources['guest'] as $resource => $method) {
$acl->allow($roleName,$resource,$method);
}
//restricted users
if($roleName == 'Restricted User'){
foreach ($arrResources['restrictedUser'] as $resource => $method) {
$acl->allow($roleName,$resource,$method);
}
}
//users
if($roleName == 'User'){
foreach ($arrResources['user'] as $resource => $method) {
$acl->allow($roleName,$resource,$method);
}
}
//admins
if($roleName == 'Admin'){
foreach ($arrResources['admin'] as $resource => $method) {
$acl->allow($roleName,$resource,$method);
}
}
}
To check if a user has access to a controller/method you can call something like the following in a Middleware event or Application Event:
$app->before(function() use ($app,$acl) {
//get the handler
$arrHandler = $app->getActiveHandler();
//get the controller for this handler (strip off the Controller namespace if required)
$controller = str_replace('Controller\\','',get_class($arrHandler[0]));
//is an Admin user allowed to view the current controller/method?
$allowed = $acl->isAllowed('Admin', $controller, $arrHandler[1]);
return $allowed;
});
Returning false
cancels the route execution.
Hi jkns,
Thank you, I've already implemented it and my solution is like yours :)
Thanks, Stefano
Hi Stefano,
Probably too late to help you, but just in case anyone else searches for this (as I did).
Most examples for ACL in Phalcon use controllers and views. In a Micro application there are no controllers or views. Here is a solution for a Micro framework using Collections (which help group handlers into Controllers)
//Create the ACL $acl = new Phalcon\Acl\Adapter\Memory(); //The default action is DENY access $acl->setDefaultAction(Phalcon\Acl::DENY); /* * ROLES * Admin - can do anything * User - can do most things * Restricted User - read only * */ $acl->addRole(new Phalcon\Acl\Role('Admin')); $acl->addRole(new Phalcon\Acl\Role('User')); $acl->addRole(new Phalcon\Acl\Role('Restricted User')); /* * RESOURCES * for each user, specify the 'controller' and 'method' they have access to (user=>[controller=>[method,method]],...) * this is created in an array as we later loop over this structure to assign users to resources * */ $arrResources = [ 'global'=>[ 'Users'=>['register','readOne','resetRequest','resetUpdate','login'], ], 'user'=>[ 'Users'=>['update','delete'], ], 'admin'=>[ 'Accounts' => ['upgrade','paymentHistory','invoices'] ] ]; foreach($arrResources as $arrResource){ foreach($arrResource as $controller=>$arrMethods){ $acl->addResource(new Phalcon\Acl\Resource($controller),$arrMethods); } } /* * ACCESS * */ foreach ($acl->getRoles() as $objRole) { $roleName = $objRole->getName(); //everyone gets access to global resources foreach ($arrResources['global'] as $resource => $method) { $acl->allow($roleName,$resource,$method); } //admins get access to user resources as well as users if(in_array($roleName, ['Admin','User'])){ foreach ($arrResources['user'] as $resource => $method) { $acl->allow($roleName,$resource,$method); } } //admin only resources if($roleName == 'Admin'){ foreach ($arrResources['admin'] as $resource => $method) { $acl->allow($roleName,$resource,$method); } } }
To check if a user has access to a controller/method you can call something like the following in a Middleware event or Application Event:
$app->before(function() use ($app,$acl) { //get the handler $arrHandler = $app->getActiveHandler(); //get the controller for this handler (strip off the Controller namespace if required) $controller = str_replace('Controller\\','',get_class($arrHandler[0])); //is an Admin user allowed to view the current controller/method? $allowed = $acl->isAllowed('Admin', $controller, $arrHandler[1]); return $allowed; });
Returning
false
cancels the route execution.
No worries. Glad you got it soerted. If we implemented the same thing it must be right!
Jkns
Hi jkns,
Thank you, I've already implemented it and my solution is like yours :)
Thanks, Stefano
Absolutely! It works very well, good job ;)
No worries. Glad you got it soerted. If we implemented the same thing it must be right!
Jkns
Hi jkns,
Thank you, I've already implemented it and my solution is like yours :)
Thanks, Stefano