phalcon

Working with ACL

Syntax#

  • You can use ’*’ as second and third parameter in Phalcon\Acl::allow and Phalcon\Acl::deny methods. This will mean any resource and action respectively.
  • Second argument in Phalcon\Acl::addRole tells from which role inheritance access.

Remarks#

  • You should serialize your ACL to some file or cache backend instead of creating it on each request.
  • Also it’s good idea to keep acl in seperated file.
  • Phalcon\Acl is able to send events to event manager, there are two events - beforeCheckAccess and afterCheckAccess.
  • You can use Phalcon\Acl\AdapterInterface to implement your own acl adapter.
  • You can protect your routes using acl with combination of proper listener in dispatcher

Creating an ACL

You can create ACL by using Phalcon\Acl\Adapter\Memory class:

$acl = new Phalcon\Acl\Adapter\Memory();

By default phalcon allows action to resource which has not been defined, to change this you can use:

$acl->setDefaultAction(Phalcon\Acl::DENY);

Roles can be added in two ways - using Phalcon\Acl\Role or just plain string:

$roleAdministrator = new Phalcon\Acl\Role('Administrator');
$acl->addRole($roleAdministrator);
$acl->addRole('Customer');

Resources can be added in two ways too, you can add actions as single action or as array:

$resourceCategories = new Phalcon\Acl\Resource('categories');
$acl->addResource($resourceCategories, 'create');
$acl->addResource('products', ['create', 'update']);

Defining Access Control and querying an ACL

You can allow role to access some action on resource by:

$acl->allow('Administrator', 'products', 'create');

You can deny role to access some action on resource by:

$acl->deny('Customer', 'categories', 'create');

You can check if role is allowed to some action on resource by using:

$acl->isAllowed('Administrator', 'products', 'create');

Additional condition in ACL

You can add also add some more logic which has to be checked to your ACL using anonymous functions. They will be executed when using Phalcon\Acl\Adapter\Memory::allow() or Phalcon\Acl\Adapter\Memory::deny(), if they will return true, they role will be allowed to access certain action on resource.

$acl->allow('Customer', 'products', 'create', function($parameter) {
    return $parameter % 2 == 0;
});
$acl->isAllowed('Customer', 'products', 'create', ['parameter' => 1]); // this will return false
$acl->isAllowed('Customer', 'products', 'create', ['parameter' => 2]); // this will return true

Notice how parameters are passed to function. Your key in array needs to have the same name as in function. Also default parameters parameters can be passed, as well as objects.

Objects as roles and resources

By implementing Phalcon\Acl\RoleAware or Phalcon\Acl\ResourceAware you can use them as objects in Phalcon\Acl\Adapter\Memory::isAllowed().

// Create our class which will be used as roleName
class UserRole implements Phalcon\Acl\RoleAware
{
    protected $id;
    protected $roleName;

    public function __construct($id, $roleName)
    {
        $this->id = $id;
        $this->roleName = $roleName;
    }

    public function getId()
    {
        return $this->id;
    }

    // Implemented function from RoleAware Interface
    public function getRoleName()
    {
        return $this->roleName;
    }
}
// Create our class which will be used as resourceName
class ModelResource implements Phalcon\Acl\ResourceAware
{
    protected $id;
    protected $resourceName;
    protected $userId;

    public function __construct($id, $resourceName, $userId)
    {
        $this->id = $id;
        $this->resourceName = $resourceName;
        $this->userId = $userId;
    }

    public function getId()
    {
        return $this->id;
    }

    public function getUserId()
    {
        return $this->userId;
    }

    // Implemented function from ResourceAware Interface
    public function getResourceName()
    {
        return $this->resourceName;
    }
}
$customer = new ModelResource(1, "products", 2);
$administrator = new UserRole(1, "Administrator");
$acl->isAllowed($administrator, $customer, 'create');

Also ability to use objects can be combined with additional condition in acl:

$acl->allow('Administrator', 'products', 'update', function(UserRole $user, ModelResource $model) {
    return $user->getId == $model->getUserId();
});
$product = new ModelResource(1, 'products', 2);
$administrator = new UserRole(1, 'Administrator');
$anotherAdministrator = new UserRole(2, 'Administrator');
$acl->isAllowed($administrator, $product, 'update'); // this will return false
$acl->isAllowed($anotherAdministrator, $product, 'update'); // this will return true

Notice that with additional condition and using objects in isAllowed method you don’t need to pass those objects as arguments. They are passed automatically only if there are correct types before arguments in function. This gives you huge ability to control if certain users can edit for example certain models in your application and when they can do it.


This modified text is an extract of the original Stack Overflow Documentation created by the contributors and released under CC BY-SA 3.0 This website is not affiliated with Stack Overflow