Downloads
Stars
Version
This is a package that provide Access Control List for Laravel 6.0|7.0|8.0|9.0.
For Laravel 6.0|7.0|8.0 use v1.
For Laravel 9.0|10.0 use v2.
This package can be installed through Composer:
composer require rohsyl/laravel-acl
After installation you must perform these steps:
config/app.php
file:'providers' => [
// ...
rohsyl\LaravelAcl\ServiceProvider::class,
];
This step will copy config files in the config folder of your Laravel App.
config/acl.php
congig/acl/users.php
php artisan vendor:publish --provider="rohsyl\LaravelAcl\ServiceProvider"
When it is published you can manage the configuration of larvel-acl through the file in config/acl.php
, it contains:
<?php
return [
/*
* Defaults for laravel-acl
*/
'defaults' => [
/**
* The acls consists in a set of permissions for a given entity.
* Here you can set the default acls (acls defined in the models section of this config file) used by laravel-acl
*/
'acls' => 'users',
],
/**
* Here you map models to acls.
*
* You can add new row by adding :
* [Model] => [acls_name]
*
* After adding a new line here, you will need to add a new configuration files under config/acl/[acls_name].php
*/
'models' => [
App\Models\User::class => 'users',
],
/**
* Cache configuration
*/
'cache' => [
'enable' => true,
'key' => 'laravel-acl_',
'store' => '',
'expiration_time' => 432000
],
];
laravel-acl
provide acls and permissions not only to one model (default App\Models\User
) but you can configure many. By default, the acls users
that is using the model App\Models\User
is used.
But you can add more acls if needed.
'defaults' => [
'acls' => 'users',
],
'models' => [
App\Models\User::class => 'users',
],
Exemple :
'defaults' => [
'acls' => 'users',
],
'models' => [
App\Models\User::class => 'users',
App\Models\Member::class => 'members',
],
Each acls have a config file associated. users
has config/acl/users.php
and contains the following :
<?php
return [
/**
* Register every permissions here
* key is the name of the permission
* value is the id of the permission
* Every permissions can have a different access level
* 0 = ACL_NONE -> no permission
* 1 = ACL_READ -> read permission
* 2 = ACL_CREATE -> create permission
* 3 = ACL_UPDATE -> update permission
* 4 = ACL_DELETE -> delete permission
* Access level are incrmental. If user has a permission with an access level of ACL_CREATE
* it means that the user can ACL_READ and ACL_CREATE
*/
'permissions' => [
'superadmin' => 0,
'user' => 1,
'group' => 2,
'page' => 3,
],
/**
*
*/
'roles' => [
'admins' => "1",
'user' => "0",
],
'model' => [
// direct acl on user
'user' => [
/**
* Enable acl for user
*/
'enableAcl' => true,
/**
* The attribute where the acl is stored in the User model.
* It's basically the name of the column in the database
*/
'attributeName' => 'acl',
],
// acl via groups of user
// n-n relation between user and group
'group' => [
/**
* Enable acl for group
*/
'enableAcl' => false,
/**
* The name of the relationship from the User model to the "group" model
*/
'relationship' => 'groups',
/**
* The attribute where the acl is stored in the "group" model.
* It's basically the name of the column in the database
*/
'attributeName' => 'acl',
]
],
'cache' => [
'key' => 'laravel-acl_',
'store' => '',
'expiration_time' => 432000
]
];
Optionally, you can enable direct acl on User
To enable this feature, you have to edit model.user.enableAcl
it in the config/acl/users.php
file and do the following instructions.
If you don't want direct acl on user, you can jump to the next chapter.
User
modelAdd the UserAcl
trait in your User
model.
namespace App;
...
use rohsyl\LaravelAcl\Traits\UserAcl;
class User extends Model {
use UserAcl;
...
}
users
tableCreate a new migration file to update the users
table
php artisan make:migration add_acl_in_users_table --table=users
And add the new column
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddAclInUsersTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->text('acl')->nullable();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('acl');
});
}
}
By default the name of this column is
acl
, but you can change it by updatingmodel.user.attributeName
in theconfig/acl/users.php
file and in this migration file.
Optionnaly you can enable group acl.
To enable this feature, you have to edit model.user.enableAcl
it in the config/acl/users.php
file and do the following instructions.
If you don't want direct acl on user, you can jump to the next chapter.
To enable the acl for groups, you have to create some more tables or to update your existing tables.
You need a groups
table and the pivot table group_user
to create the ManyToMany relation.
(it's okay if you have different naming)
If you need to create these tables please follow the chapter 4.1.1 else follow the 4.1.2
Do not create these tables if you already have similar grouping table with a ManyToMany relation to
User
.
Create a new migration file to create the groups
table
php artisan make:migration create_groups_table
with the following content :
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateGroupsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('groups', function (Blueprint $table) {
$table->bigIncrements('id');
$this->string('name');
$this->text('acl')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('groups');
}
}
The name of the
acl
column can be changed by updatingmodel.group.attributeName
in theconfig/acl/users.php
file and in this migration file.
Add a new migration file to create the pivot table named group_user
php artisan make:migration create_group_user_table
with the following content :
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateGroupUserTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('group_user', function (Blueprint $table) {
$table->unsignedBigInteger('user_id');
$table->unsignedBigInteger('group_id');
$table->foreign('user_id')
->references('id')->on('users');
$table->foreign('group_id')
->references('id')->on('groups');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('group_user');
}
}
That's all for database table creation.
Add the acl column in your grouping table.
Create a new migration file to update your grouping table.
Be sure to have the right name for the table.
php artisan make:migration add_acl_in_groups_table --table=groups
And add the new column
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddAclInUsersTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('groups', function (Blueprint $table) {
$table->text('acl')->nullable();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('groups', function (Blueprint $table) {
$table->dropColumn('acl');
});
}
}
By default the name of this column is
acl
, but you can change it by updatingmodel.group.attributeName
in theconfig/acl/users.php
file and in this migration file.
That's all for database table update.
Add the GroupAcl
trait in your Group model. You also need to add the relationship to the User
model
namespace App\Models;
...
use rohsyl\LaravelAcl\Traits\GroupAcl;
class Group extends Model
{
use GroupAcl;
...
public function users() {
return $this->belongsToMany('App\User');
}
}
User
modelAdd the relation into the User
model.
If your group table has a different name, it's not a problem. You just have to update model.group.relationship
and set this name on the relation function
in the the config/acl/users.php
file
namespace App;
class User extends Model {
...
public function groups() {
return $this->belongsToMany('App\Group');
}
}
Everthing is ready, now jump to the documentation section to learn more about laravel-acl.
This chapter explain how laravel-acl works and describe the available tools (helpers, middleware, ...).
Permission and roles are managed in a hard coded way in the config/acl/users.php
file. This choice was made to simplify the use
and to avoid database query as much as possible.
You can easly add permissions by adding a new entry in the permissions
array in the config/acl/users.php
file.
The key is the name of the permission and the value is the identifier
It's mandatory to have the superadmin
permission with the identifier set as 0
.
You can manage every other permissions the way you want.
'permissions' => [
'superadmin' => 0,
'user' => 1,
'group' => 2,
'page' => 3,
'run_page_import' => 9,
],
A role is a preset of permissions. You can manage roles with the roles
array in the config/acl/users.php
file.
The key is the name of the role and the value is the ACL.
'roles' => [
'admins' => "1",
'user' => "4110",
],
What is the ACL ?
It's a string value that define the permissions of a user or a group.
This value is stored by default in the acl
column in the users
table and in the group table.
Let's take the following ACL as a exemple.
"1000003410"
If we have defined the following permissions.
'permissions' => [
'superadmin' => 0,
'user' => 1,
'group' => 2,
'page' => 3,
'run_page_export' => 8,
'run_page_import' => 9,
],
ACL are red from the right to the left.
What does each digit means ?
"0"
of the ACL "1000003410"
represent the permission with the 0
identifier. In our case it's the superadmin
permissions."1"
represent the permission with the 1
identifier. (it's the user
permission)."3"
represent the page
permission."0"
represent the run_page_export
permission."1"
represent the run_page_import
permission.But, what are those values "0"
, "1"
, "2"
, "3"
, "4"
on each digit ?
These values define the access level for the given permission
Value | CONSTANT | Description |
---|---|---|
"0" |
ACL_NONE or ACL_DENY |
no access |
"1" |
ACL_READ or ACL_ALLOW |
the user (or group) has a read permission to something or is allowed to perform an action |
"2" |
ACL_CREATE |
the user (or group) has the creation permission |
"3" |
ACL_UPDATE |
the user (or group) has the update permission |
"4" |
ACL_DELETE |
the user (or group) has the deletion permission |
So, to describe the ACL "1000003410"
, the user has the following permissions/restrictions :
superadmin
;user
permission;group
permission;page
permission;run_page_export
;run_page_import
.You know everything about the permissions, roles and ACL. Jump to the next chapter to learn how to grant and revoke permissions
How to give the superadmin permission to a user :
$user->grantPermission('superadmin', ACL_ALLOW);
$user->save();
If you don't save, the permission will not persist in the database.
How to give the read access to the group
permission to a user :
$user->grantPermission('group', ACL_READ);
$user->save();
How to give the delete access to the page
permission to a user :
$user->grantPermission('page', ACL_DELETE);
$user->save();
How to grant many permissions at once :
$user->grantPermissions([
'page' => ACL_READ,
'user' => ACL_UPDATE
]);
$user->save();
How to revoke a permission :
$user->revokePermission('user');
$user->save();
or you can also grant the ACL_NONE
or ACL_DENY
level.
$user->grantPermission('user', ACL_DENY);
$user->save();
How to revoke many permissions:
$user->revokePermissions(['user', 'group']);
$user->save();
How to revoke all permissions:
$user->revokePermissions();
$user->save();
It works the same way as with the user.
$group->grantPermission('user', ACL_READ);
$group->save();
$group->grantPermissions([
'user' => ACL_READ,
'page' => ACL_UPDATE,
'run_page_export' => ACL_ALLOW
]);
$group->save();
$group->revokePermission('user');
$group->save();
$group->revokePermissions(['user', 'run_page_export']);
$group->save();
Now that you know how to grant and revoke permissions to a user or a group, you need to learn how to check permissions for a user.
This chapter describe every way to check if a user has the permissions to acces pages or perform actions.
You can use Gate facade provided by laravel.
Gate::allows('user', [ACL_CREATE]);
You can use the Laravel can
method of the User
to check a permission.
Check if the user can read page :
$hasPermission = auth()->user()->can('page', [ACL_READ]);
It will return true if the user is able to read pages else it return false.
Check if the user can edit user in the context of the given group :
$group = Group::find(1);
$hasPermission = auth()->user()->can('page', [ACL_READ, $group]);
It will return true only if the user has the acces granted by the given group else it return false.
It's usefull to manage access to entity that are in relation with a specific group.
Check if the user can update the page in the context of many groups :
$group1 = Group::find(1);
$group2 = Group::find(12);
$hasPermission = auth()->user()->can('page', [ACL_READ, collect([$group1, $group2])]);
The 2nd parameter (groups)" must be a collection
Illuminate\Support\Collection
.
You can use the acl
middleware provided by laravel-acl to protect routes or a whole resource directly in the route files (routes/web.php
).
Restrict the access to user with a given permission and level
Route::get('users/index', 'UserController@index')->name('users.index')->middleware('acl:user:1');
This route will allow the acces only to user who have the
user
permission with theACL_READ
level.
Restrict the access to user with any of the given permission and level
Route::get('users/index', 'UserController@index')->name('users.index')->middleware('acl:user:1|group:1');
This route will allow the acces only to user who have the
user
permission with theACL_READ
level or thegroup
permission with theACL_READ
level.
It's usefull to be able to hide some buttons in your blade view. To achieve this, you can use some directive provided by Laravel.
@can
blade directive@can('user', [ACL_READ])
allow
@else
denied
@endcan
It's the same as writing
@if(auth()->user()->can('user', [ACL_READ]))
allow
@else
denied
@endif
@cannot
blade directive@cannot('user', [ACL_READ])
denied
@else
allow
@endcannot
@canany
blade directive@canany(['user', 'page'], [ACL_READ])
The user has page or user permisson with a read level
@elsecanany(['group'], ACL_READ)
Or the user has the group permission with a read level
@else
denied
@endcannot
Checking if the user can read page
acl_has_permission($user, 'page', ACL_READ)
You can retrieve all permissions with the helper method :
$permissions = acl_permissions()
Get permissions for another acls, just pass the acls name in parameter
acl_permissions('members')
You can retrieve all roles with the helper method :
$roles = acl_roles()
Get roles for another acls, just pass the acls name in parameter
acl_permissions('members')
strict
optionSometimes, you will probably want to check if the user have strictly a permission.
What does this mean ?
Exemple:
$user1
have the superadmin
permission$user2
have the is_manager
permissionSo when you check if the $user1
have the is_manager
permission :
$user1->can('is_manager');
this will return
true
even if he don't have theis_manager
permission because he issuperadmin
.
It's possible to check permissions with the strict parameter.
$user1->can('is_manager', ACL_STRCT);
this will return
false
even if the user issuperadmin
.
$user2->can('is_manager', ACL_STRCT);
this will return
true
because$user2
have theis_manager
permission.