Download the PHP package rotexsoft/versatile-acl without Composer
On this page you can find all versions of the php package rotexsoft/versatile-acl. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download rotexsoft/versatile-acl
More information about rotexsoft/versatile-acl
Files in rotexsoft/versatile-acl
Package versatile-acl
Short Description A simple light-weight and highly customizable package that can be used for implementing access control in any php application.
License BSD-3-Clause
Homepage https://github.com/rotexsoft/versatile-acl
Informations about the package versatile-acl
Versatile Acl
A simple, highly flexible and customizable access control package for PHP applications.
Installation
Via composer: (Requires PHP 7.4+ or PHP 8.0+).
composer require rotexsoft/versatile-acl
Branching
These are the branches in this repository:
- master: contains code for the latest major version of this package.
- 4.x: contains code for the 4.x version of this package. No new features, only bug fixes.
- 1.X: contains code for the 1.X version of this package. Abandoned.
Introduction
A PHP application can use this package to define Permissionable Entities (e.g. application users or groups that users can belong to).
- Each entity is an instance of \VersatileAcl\Interfaces\PermissionableEntityInterface which is implemented by \VersatileAcl\GenericPermissionableEntity in this package.
- Each entity can be associated to another entity as a parent Entity.
- Each entity can have one or more permissions defined. These are direct permissions
- A permission in this package is an object that represents whether or not an action (represented by a case-insensitive string) can be performed by an entity on a resource (represented by a case-insensitive string).
- A permission is an instance of \VersatileAcl\Interfaces\PermissionInterface which is implemented by \VersatileAcl\GenericPermission in this package.
- Each entity also inherits permissions from its parent entities.
- The package allows you to give direct permissions a higher priority than inherited permissions (the default behavior) and also allows you to do the reverse, if you so desire.
Below is an overview of the classes in this package:
Click here to see the full Class Diagram for this package.
In your applications, you will be mostly be working with instances of VersatileAcl\VersatileAcl; this class exposes most of the functionality of the underlying classes in this package listed below:
-
\VersatileAcl\GenericPermissionableEntity : Represents an entity in your application
-
\VersatileAcl\GenericPermissionableEntitiesCollection : A collection class for storing one or more entities in your application
-
\VersatileAcl\GenericPermission : Represents a permission to be assigned to an entity in your application
- \VersatileAcl\GenericPermissionsCollection : A collection class for storing one or more permissions belonging to a particular entity in your application. It is possible to assign the same instance of this class to more than one entity, but it is recommended that you maintain separate instances of this class for each entity in your application.
Example Real-world Usage
We will be using a blog application that has a users table containing information about registered blog users (the users in this table are also authors of blog posts and commentators on blog posts in the application), a posts table and a comments table. Below is the schema for the sample application:
Below are the relationship rules for the blog application
- A user can author many posts
- A user can make one or more comments on each post
- A post can have one or more comments associated with it
Below are some access control group definitions that are relevant to this sample blog application:
Group Name | Resource | Action | Allowed |
---|---|---|---|
admin | all | all | yes |
comments-moderators | comment | approve | yes |
comments-moderators | comment | delete | yes |
comments-owners | comment | all | yes |
posts-moderators | post | approve | yes |
posts-moderators | post | delete | yes |
posts-owners | post | all | yes |
NOTE: the permissions associated with the comments-owners and posts-owners will require an assertion callback that further checks that members of the group can only perform actions on the comments or posts they own (not comments and posts owned by other users).
Let's model these groups and permissions using VersatileAcl\VersatileAcl.
NOTE: \VersatileAcl\GenericPermission::getAllActionsIdentifier() is a special string that represents all actions any entity can perform on each resource in your application.
NOTE: \VersatileAcl\GenericPermission::getAllResourcesIdentifier() is a special string that represents all available resources in your application.
Now that we have created entity objects for each group and added the necessary permissions to the appropriate entity objects, we are ready to go ahead with defining the entity objects that will represent the users below in the blog application.
Below is a list of userids of users in the application
- frankwhite
- ginawhite
- johndoe
- janedoe
- jackbauer
- jillbauer
Let's create and register entity objects for each user in our VersatileAcl object:
Below are the group membership definitions:
Group | User |
---|---|
admin | frankwhite |
comments-moderators | ginawhite |
comments-moderators | johndoe |
posts-moderators | janedoe |
comments-owners | all |
posts-owners | all |
Let's model these relationships by adding the appropriate entity objects representing the groups as parent entities to the respective user entity objects:
Now that we have set up our groups, users and permissions, let's see how to check if a user is allowed to perform an action on a resource in our application.
Let's start with the user 'frankwhite' that belongs to the 'admin' group. This user should be able to perform any action on any resource in the application:
Now let's continue with the user 'ginawhite' that belongs to the 'comments-moderators' group. This user should be able to only approve and delete comments in the application (the user should also be able to approve and delete posts they have created):
Now let's continue with the user 'johndoe' that belongs to the 'comments-moderators' group. This user should be able to only approve and delete comments in the application (the user should also be able to approve and delete posts they have created):
Now let's continue with the user 'janedoe' that belongs to the 'posts-moderators' group. This user should be able to only approve and delete posts in the application (the user should also be able to approve and delete comments they have created):
Now let's continue with the user 'jackbauer' that only belongs to the 'owners' group. This user should be able to ONLY approve and delete comments and posts they have created in the application:
Finally, let's test the user 'jillbauer' that also only belongs to the 'owners' group. This user should be able to ONLY approve and delete comments and posts they have created in the application:
NOTE: You can override the $additionalAssertions callable supplied to VersatileAcl::addPermission(...) by passing another callback as the fourth argument to VersatileAcl::isAllowed(...). In all the examples above, we passed null as the fourth argument to VersatileAcl::isAllowed(...), meaning that we want the $additionalAssertions callable supplied to VersatileAcl::addPermission(...) to be used instead (if present).
This is just an example of how this package can be used to enforce access control in an application. You can obviously come up with other more creative ways to adapt this package to your specific use case.
Study the class diagram for this package to get a better understanding of how the various classes interact.
Debugging
You can also get information about what's going under the hood of any instance of VersatileAcl\VersatileAcl and finally echo the contents of the string returned by VersatileAcl::getAuditTrail().
You can increase or decrease the amount of information returned by VersatileAcl::getAuditTrail() by calling VersatileAcl::enableVerboseAudit(bool $performVerboseAudit=true) with a value of true or false.
Finally, you can clear / empty / reset the string returned by VersatileAcl::getAuditTrail() by calling VersatileAcl::clearAuditTrail()
Here's an example below:
Produces the output below:
Public Methods of VersatileAcl\VersatileAcl
Method | Description |
---|---|
__construct( string $permissionableEntityInterfaceClassName = GenericPermissionableEntity::class, string $permissionInterfaceClassName = GenericPermission::class, string $permissionableEntitiesCollectionInterfaceClassName = GenericPermissionableEntitiesCollection::class, string $permissionsCollectionInterfaceClassName = GenericPermissionsCollection::class ) |
The constructor through which you can specify alternate fully qualified class names of classes that implement PermissionsCollectionInterface . |
addEntity(string $entityId): self | Adds an entity to an instance of this class if it doesn't already exist. Entity IDs are treated in a case-insensitive manner, meaning that 'ALice' and 'alicE' both refer to the same entity |
addParentEntity(string $entityId, string $parentEntityId): self | Add an entity with an ID value of $parentEntityId as a parent entity to another entity with an ID value of $entityId in an instance of this class. If an entity with an ID value of $entityId does not exist in the instance of this class upon which this method is called, the entity will be created and added first before the parent entity is added to it. Both IDs are treated in a case-insensitive manner, meaning that if $entityId has a value of 'ALice' or 'alicE' both will refer to the same entity or if $parentEntityId has a value of 'ALice' or 'alicE' both will refer to the same parent entity. You can use this method as a shortcut to creating both an entity and its associated parent entities, eliminating the need for calling addEntity first before calling this method. |
addPermission( string $entityId, string $action, string $resource, bool $allowActionOnResource = true, callable $additionalAssertions = null, ...$argsForCallback ): self |
Used for adding a permission to an entity with the specified ID. If the entity does not exist, it will be created and the permission will be added to it. See __construct in PermissionInterface for more information about all the parameters to this method (except the first). You should provide default values for each parameter to your $additionalAssertions callback function. |
clearAuditTrail(): self | Empties the contents of the Audit Trail containing the trace of all logged internal activities. |
createEntity(string $entityId): PermissionableEntityInterface | A helper method for creating entity objects which you would be responsible for managing outside of this class. You would not normally need to use this method except if you want to more control over how the entities and permissions in your application are managed. |
createEntityCollection(): PermissionableEntitiesCollectionInterface | A helper method for creating collection objects used to store entity objects which you would be responsible for managing outside of this class. You would not normally need to use this method except if you want to more control over how the entities and permissions in your application are managed. |
createPermission( string $action, string $resource, bool $allowActionOnResource = true, callable $additionalAssertions = null, ...$argsForCallback ): PermissionInterface |
A helper method for creating permission objects which you would be responsible for managing outside of this class. You would not normally need to use this method except if you want to more control over how the entities and permissions in your application are managed. See __construct in PermissionInterface for more information about the parameters to this method. |
createPermissionCollection(): PermissionsCollectionInterface | A helper method for creating collection objects used to store permission objects which you would be responsible for managing outside of this class. You would not normally need to use this method except if you want to more control over how the entities and permissions in your application are managed. |
enableAuditTrail(bool $canAudit=true): self | Enables or disables the logging of internal activities performed in some of the important public methods of this class. |
enableVerboseAudit(bool $performVerboseAudit=true): self | Enables or disables verbose logging of internal activities performed in some of the important public methods of this class. This method only increases or decreases the level of detail of the internal activities that are logged. It does not not disable logging. |
getAllEntities() : ?PermissionableEntitiesCollectionInterface | Returns a collection of all entities added to an instance of this class or null if the collection has not yet been initialized. |
getAuditTrail(): string | Returns a string containing a trace of all logged internal activities performed in some of the important public methods of this class. |
getEntity(string $entityId): ?PermissionableEntityInterface | Gets and returns an entity with specified Id from an instance of this class or returns NULL if an entity with specified Id doesn't already exist. |
isAllowed( string $entityId, string $action, string $resource, callable $additionalAssertions = null, ...$argsForCallback ): bool |
Check if the specified action in $action can be performed on the specified resource in $resource based on the existing permissions associated with either the specified entity with an ID value in $entityId or all entities associated with the instance of this class this method is being invoked on if $entityId === ''. See PermissionInterface::isAllowed($action, $resource, $additionalAssertions, ...$argsForCallback) for definitions of all but the first parameter. |
removeEntity(string $entityId): ?PermissionableEntityInterface | Removes an entity from an instance of this class if it exists and returns the removed entity or NULL if the entity does not exist. |
removeParentEntity( string $entityId, string $parentEntityId ): ?PermissionableEntityInterface |
Remove and return an entity with an ID value in $parentEntityId that is a parent entity to another entity with an ID value in $entityId, if the instance of this class upon which this method is being called contains an entity with the ID value in $entityId, else NULL is returned. |
removePermission( string $entityId, string $action, string $resource, bool $allowActionOnResource = true, callable $additionalAssertions = null, ...$argsForCallback ): ?PermissionInterface |
Remove a permission from the entity with an ID value specified in $entityId and return the removed permission or return null if either the entity and / or permission do not exist. |