Download the PHP package uwla/lacl without Composer
On this page you can find all versions of the php package uwla/lacl. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Package lacl
Short Description Laravel Access Control List
License MIT
Homepage https://github.com/uwla/lacl
Informations about the package lacl
LACL - Laravel Access Control List
Implementation of Access Control List System in Laravel.
The system handles authorizations of certain actions based on roles and permissions. Permissions are assigned to roles, and roles are assigned to users. If a user's role has the matching permission, then the user is authorized to perform the given action; else the user is forbidden. The permissions can be arbitrarily defined by the application developers.
The system can handle resource-based permissions, that is: a permission is associated with a resource/model/entity in the database. Thus, it is possible to, for example, define authorization for a user to edit all articles or just the articles he has created by creating permissions for those articles in particular. This is better than adding a 'user_id' column to the articles table.
Features
- Role-based access control list
- Per-role permission: assign permission to a role
- Per-user permission: assign permission to a user
- Per-model permission: associate a unique model in DB with a permission
- Automated Laravel Policies for controllers using per-model permissions
- Clean interface with permission-name guessing
- Arbitrary permissions
- Arbitrary roles
Demo
A demo app is available on github at uwla/lacl-demo to illustrate usage.
FAQ
Why should I use this package instead of popular ones, such as spatie permissions?
This package provides some functionality that spatie's and other permission-management packages do not provide, such as per-model permission and Resource Policy automation. At the same time, their packages provide functionality that this package does not provide, such as searching permissions based on wildcards or support for team permissions. Please, read the full README to understand better what this package does and what it does not. If you should use this package or not will depend on the specific needs for your application; it is up to you as developer to figure it out.
Why this package?
I had specific needs that led me to develop this package and I was not aware of another package that would fit my needs at the time I started developing this package.
Installation
Install using composer:
Publish the ACL table migrations:
Run the migrations:
Usage
Convention used here:
User
refers toApp\Models\User
Role
refers toUwla\Lacl\Models\Role
Permission
refers toUwla\Lacl\Models\Permission
Collection
refers toIlluminate\Database\Eloquent\Collection
HasRole
Add Traits to the application's user class:
Add role or multiple roles to user (the roles must already exist):
Role the role or multiple roles to user (revoking previous ones):
Get the roles of the user (returns Collection<Role>
or array<string>
):
Delete role (returns void
):
Has role (returns bool
):
Count how many roles the user has (returns int
):
Get multiple users along with their roles:
Get multiple users along with the names of their roles:
HasPermission
Here, we will assign permissions to a role, but they can also be assigned directly to a user or any model by using the traits and contracts as follow:
Add a permission or multiple permissions to a role (the permissions must already exist):
Set the permission or multiple permissions to role (revoking previous ones):
Get the permissions of the role (return a Collection
of Permission
or string
):
Delete permission (returns void
):
Has permission (returns bool
):
Count how many permissions the role has (returns int
):
Get multiple roles along with their permissions:
Get multiple roles along with the name of their permissions:
Permissions
Create an arbitrary permission:
Create a permission for a given model:
Get a permission by name:
Get all roles associated with a permission:
Get all model instances for the given model class which have the specific permission:
It is worth noting that you can perform any operations on Permission
that are
supported by Eloquent models, such as deleting, updating, fetching, etc.
Per-model permission
The Trait Permissionable
provides an interface for managing CRUD permissions
associated with a given model. In the following examples, we will use the
Article
model to illustrate how would we manage per-article permissions.
First, make sure the class do use the trait.
OBS: If your model needs to use both Permissionable
and HasRole
traits,
then you will be better off using the PermissionableHasRole
trait, which is
basically a mix of the both that solves conflict declarations between them. That
could be the case for the User
class, which could have roles and, at the same
time, be a permissionable model.
Here is a summary of the auxiliary methods provided by Permissionable
:
Name | Description |
---|---|
createViewPermission |
Create permission for viewing the model. |
createUpdatePermission |
Create permission for updating the model. |
createDeletePermission |
Create permission for deleting the model. |
createCrudPermissions |
Create permissions above. |
getViewPermission |
Get the permission for viewing the model. |
getUpdatePermission |
Get the permission for updating the model. |
getDeletePermission |
Get the permission for deleting the model. |
getCrudPermissions |
Get the permissions above. |
deleteViewPermission |
Delete the permission for viewing the model. |
deleteUpdatePermission |
Delete the permission for updating the model. |
deleteDeletePermission |
Delete the permission for deleting the model. |
deleteCrudPermissions |
Delete the permissions above. |
grantViewPermission |
Grant the permission for viewing the model to the given user/role. |
grantUpdatePermission |
Grant the permission for updating the model to the given user/role. |
grantDeletePermission |
Grant the permission for deleting the model to the given user/role. |
grantCrudPermissions |
Grant the permissions above to the given user/role. |
revokeViewPermission |
Revoke the permission for viewing the model from the given user/role. |
revokeUpdatePermission |
Revoke the permission for updating the model from the given user/role. |
revokeDeletePermission |
Revoke the permission for deleting the model from the given user/role. |
revokeCrudPermissions |
Revoke the permissions above from the given user/role. |
As you can see, the per-model permissions are 'view', 'update', and 'delete'. This is because the most generic actions a user can perform on a single model is to view it, update it, or delete it. It also facilitates automation and integration with Laravel Policies.
The create-permission helpers will either fetch from or insert into the database the associated permission, depending on whether it already exists or not. The get-permissions helpers assume the permission exists in DB, and then try to fetch. The delete-permission helpers will try to delete the permissions in DB, but does not assume they already exist. The grant permission helpers will assign the permissions to the user or to the given user/role, which assumes the permissions already exist (if they don't exist, an Error will be thrown). The revoke-permission helpers try to revoke the permission from the user/role; it assumes the permissions exist but it does not assume the user/role has access to those permissions.
Create crud permission (or fetch them, if already exist) for the article:
Get the permissions, assuming they were already created before:
Delete the permissions (they may exist or not).
Grant the permissions to the user:
Revoking permissions is done in the same way:
For now, to check if the user has a permission to view/update/delete the model, you could do the following:
Also, it is important to remember that the user permissions are all permissions assigned specifically to him plus the permissions assigned to any role he has. Therefore, if the user does not have a direct permission to view the article, but one of his roles has the permission, then the user will also have that permission.
Per-model permission deletion
To delete all per-model permissions associated with a model, you can use the
deleteThisModelPermissions
method that comes with the Permissionable
trait.
If you want that behavior to be triggered automatically before deleting an
Eloquent model, you can add that to the boot
method of your model:
Just keep in mind that mass deletions do not trigger the static:deleted
because when you use Eloquent Models for mass deletion it will not fetch the
models first and later deleted them one by one. It will, instead, send a
deletion query to the database, so it does instantiate any model.
Per-model permission dynamically
There is a shorter, cleaner way (aka, syntax sugar) to deal with permissions:
Whenever you call a method that it is undefined, it will trigger PHP's language
construct __call
method, which allows us programmers to define custom
behavior to handle undefined methods. In this case, the HasPermission
trait
handles custom behavior in the following way:
- If the method name does not start with
hasPermissionTo
,addPermissionTo
, ordelPermissionTo
, then it will call theparent::__call
to handle it. - The remaining of the method name (in this case, it is
SendEmails
) is passed to a method calledguessPermissionName
, which you are encouraged to overwrite to fit your needs. - By default,
guessPermissionName
will just lower case the first letter of the remaining method name. - It will then call one of the following
hasPermission
,addPermission
,delPermission
, depending on the method name. - If an argument is passed, it is assumed to be a class that uses the
Permissionable
trait, provided by this package. The permission to be create/checked/delete will be a model-based permission
The default convention is that the permission name is prefixed with the
<model>.
, where <model>
is the lowercase name of the model's class. This is
the current convention, but it will be customizable in the near future.
Here is an example with models:
Notice that before adding a permission, the permission should already exist. If the permission does not exist, you should create it.
Per-model permission model fetching
Here is how to fetch the models of a specific type that the user or a role has access to:
This will fetch all Article
models such that there is a per-model permission
associated with them and the user or role has access to at least one of such
per-model permissions.
You can specify the name of the permission too:
That way, you have granular control to fetch the models each user or role has permission to access, filtering by a particular action (aka, permission name).
Generic model permissions
Generic model permissions are permissions to access all instances of a model. This is different from per-model permission, which handles access to a particular instance of a model.
Those generic model permissions are create
, viewAny
, updateAny
, and
deleteAny
. They are designed to follow the standards of Laravel Policies. Of
course, you can redefine those and use the custom names you want, but it is more
convenient to stick to those conventions because we can automate tasks instead
of manually defining custom names.
The interface for generic model permissions are the same as for the per-model permission, the only difference is that the methods are static.
In the second example above, the user would be able to delete all articles
since he was granted permission to deleteAny
any article model.
Everything that was explained about per-model permissions applies to generic model permissions: creation, fetching, deletion, granting, revoking, dynamic names, etc. There are only three differences:
- The permissions must be created, fetched, and deleted using static methods.
- The permissions grant access to all models, not just one.
- The permission names end with the
Any
, such asupdateAny
, except for thecreate
permission.
Actually, there is also more two exceptions. First, to delete all generic model permissions:
Delete all model permissions, both generic model permissions and per-model permissions (be careful with this one, since it will delete all of them):
Resource Policy
This package provides the ResourcePolicy
trait to automate Laravel Policies
using a standard convention for creating permissions.
The convention is:
- To create a model, the user must have the
{model}.create
permission. - To view all models, the user must have the
{model}.viewAny
permission. - To view a specific model, the user must have either the
{model}.viewAny
permission or the{model}.view
per-model permission for the specific model. - To update a specific model, the user must have either the
{model}.updateAny
permission or the{model}.update
per-model permission for the specific model. - To delete a specific model, the user must have either the
{model}.deleteAny
permission or the{model}.delete
per-model permission for the specific model. - To force-delete a specific model, the user must have either the
{model}.forceDeleteAny
permission or the{model}.forceDelete
per-model permission for the specific model. - To restore a specific model, the user must have either the
{model}.restoreAny
permission or the{model}.restore
per-model permission for the specific model.
Where {model}
is the lowercase name of the model's class name. For example, if
it is the App\Models\User
, it would be user
; if it is App\Models\Product
,
it would be product
.
Here is how you would use it for a ArticlePolicy
:
Then, in the ArticleController
:
The Laravel Policies are triggered before the request is handled to the
controller. Since we are using the ResourcePolicy
, before the request is sent
to the ArticleController
, our application will check if the user has the
permission to perform the action associated with the method. The goal here is
to have an automated process of Access Control, freeing the developer from
having to manually check if the user has the permission to perform the common
CRUD operations.
Overriding Permissions and Role models
It is possible to override the models which are used by the traits HasRole
,
HasPermission
, Permissionable
, PermissionableHasRole
.
To do so, just override the protected static methods Permission
and Role
:
CONTRIBUTIONS
Contributions are welcome. Fork the repository, make your changes, then make a pull request. Check development for all development-related instructions.
HELP
If you any need help, feel free to open an issue on this package's github repo.
LICENSE
MIT.