back2lobby / access-control
Roles and Permissions manager for laravel
Requires
- php: ^8.1
- illuminate/auth: ^9.0|^10.0
- illuminate/cache: ^9.0|^10.0
- illuminate/collections: ^9.0|^10.0
- illuminate/container: ^9.0|^10.0
- illuminate/contracts: ^9.0|^10.0
- illuminate/database: ^9.0|^10.0
- illuminate/support: ^9.0|^10.0
- illuminate/validation: ^9.0|^10.0
Requires (Dev)
- laravel/pint: ^1.8
- orchestra/testbench: ^8.0
This package is auto-updated.
Last update: 2025-01-03 15:34:00 UTC
README
AccessControl is a Laravel package for easy role & permission management with model-based role assignment and role-based permissions.
Table of Contents
Introduction
AccessControl simplifies role & permission management by enabling the assignment of roles based on models and defining role-based permissions for fine-grained control over user access.
Once installed, you can simply tell the access-control what you want to allow at the gate:
// Give a role some permission AccessControl::allow("manager")->to('edit-company'); // Assign role to any user AccessControl::assign('manager')->to($user); // You can also assign role for a specific roleable model AccessControl::assign('manager',$company)->to($user); // Checking the permission on user for a roleable model AccessControl::canUser($user)->do("edit-company",$company); // Checking if the user has a role for that model AccessControl::is($user)->a("manager",$company);
Installation
Note: AccessControl requires PHP 8.1+ and Laravel 9.0+
-
Install AccessControl with composer:
composer require back2lobby/access-control
-
Use the
HasRoles
in the User Model:use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Foundation\Auth\User as Authenticatable; use Back2Lobby\AccessControl\Traits\HasRoles; class User extends Authenticatable { use HasFactory, HasRoles // code here }
If you want to use custom user model instead of
App\Models\User
, head over to Custom User Model section. -
If you have a roleable model, then add AccessControl's trait to your roleable model:
use Back2Lobby\AccessControl\Traits\Roleable; class Post extends Model { use Roleable; }
-
Now, to run AccessControl's migrations. First publish the migrations into your app's
migrations
directory, by running the following command:php artisan vendor:publish --tag="access-control.migrations"
-
Finally, run the migrations:
php artisan migrate
Once it's installed, you can use a seeder to create base roles and permissions for your Laravel application. For example:
use Illuminate\Database\Seeder; use Back2Lobby\AccessControl\Facades\AccessControlFacade as AccessControl; class AccessControlSeeder extends Seeder { public function run() { // Create all roles AccessControl::createManyRoles([ [ 'name' => 'admin', 'title' => 'Administrator', ], [ 'name' => 'editor', 'title' => 'Editor', ] ]); // Create all permissions AccessControl::createManyPermissions([ [ 'name' => 'create-post', 'title' => 'Create Post', 'description' => 'Allows user to create a new post', ], [ 'name' => 'edit-post', 'title' => 'Edit Post', 'description' => 'Allows user to edit an existing post', ], ]); } }
Facade
Whenever you use the AccessControl
facade in your code, remember to add this line to your namespace imports at the top of the file:
use AccessControl;
If your IDE is facing any issues with this facade, please use barryvdh/laravel-ide-helper
Terminologies
Role:
A set of permissions that can be assigned to a user.
Permission:
A right to perform a specific action or access a specific resource.
Direct permission:
A permission that is allowed or forbidden directly to a role.
Indirect permission:
A permission that a user has because of a super permission it has, rather than being directly allowed or forbidden.
Super permission:
A permission that is used to grant all permissions, except for those that are forbidden directly.
Direct Role
A role is a direct role for a permission if it is allowed for the permission directly.
Indirect Role
A role is an indirect role for a permission, if it is not allowed for the permission directly rather the role have that permission because it has super permission.
Usage
Role
Creating Role
Role can be created using createRole
method. Example:
$superAdmin = AccessControl::createRole([ 'name' => 'super-admin', 'title' => 'Super Admin' ]);
You can specify roleables also, which will restrict the role to be assigned for the given roleable. Example:
AccessControl::createRole([ 'name' => 'manager', 'title' => 'Manager', 'roleables' => [Company::class] ]); // ✓ assigning role with allowed roleable will work fine $user->assign('manager',$company); // ✗ assigning role with roleable that's not allowed will throw error $user->assign('manager',$post);
Multiple roles can be created at once like this:
AccessControl::createManyRole([ ['name','company-manager','tittle'=>'Company Manager'], ['name','company-user','title' => 'Company User'] ]);
Updating Role
Role can be updated using updateRole
method.
Example:
// using role name AccessControl::updateRole('author',[ 'name' => 'post-author', 'title' => 'Post Author' ]);
Deleting Role
Role can be deleted using deleteRole
method.
Example:
AccessControl::deleteRole('author');
Getting Role
To retrieve a role, you can use the method getRole
. Example:
AccessControl::getRole('admin');
To retrieve all the roles available we can do something like to get a Collection of available roles.
AccessControl::getAllRoles();
Allowing Permissions
To allow a role for a specific permission, you can use the method allow
and then chain it with method to
. Example:
AccessControl::allow('author')->to('edit'); // with permission name AccessControl::allow('author')->to($permission); // with permission object AccessControl::allow('author')->to(3); // with permission id
Alternatively, we can use allow
method from Role Model itself like:
$role->allow('create-post');
To allow all the permissions available indirectly (except forbidden specifically), use method superPermission
like this:
AccessControl::allow('super-admin')->superPermission();
The method superPermission
needs the permission named *
. It will create it in case it's not available.
Disallowing Permissions
Take back a permission from a user with method disallow
and chain it with method to
. Example:
AccessControl::disallow('admin')->to('create admin');
Alternatively, we can use disallow
from Role Model itself like:
$role->disallow('create-post');
To take back the super permission given to the role, use method superPermission()
like this:
AccessControl::disallow('manager')->superPermission();
Forbidding Permissions
Forbid a permission for the role using method forbid
and chain it with method to
. Example:
AccessControl::forbid('manager')->to('delete company');
Alternatively, we can use forbid
from Role Model itself like:
$role->forbid('create-post');
You can forbid the role from all the permissions indirectly (except allowed specifically) using the method superPermission()
like this:
AccessControl::forbid('manager')->superPermission();
Getting Permissions For Role
To get all the permissions a role have including allowed and forbidden, we can use method getAllPermissionsOf
like:
$permissions = AccessControl::getAllPermissionsOf('manager');
To get only specific type of permissions for the role, we can use methods getAllowedPermissionsOf
, getDirectlyAllowedPermissionsOf
, getIndirectlyAllowedPermissionsOf
, getForbiddenPermissionsOf
, getDirectlyForbiddenPermissionsOf
, getIndirectlyForbiddenPermissionsOf
. Examples:
// getting allowed permissions $allowedPermissions = AccessControl::getAllowedPermissionsOf('manager'); $directlyAllowedPermissions = AccessControl::getDirectlyAllowedPermissionsOf('manager'); $indirectlyAllowedPermissions = AccessControl::getIndirectlyAllowedPermissionsOf('manager'); // getting forbidden permissions $forbiddenPermissions = AccessControl::getForbiddenPermissionsOf('manager'); $directlyForbiddenPermissions = AccessControl::getDirectlyForbiddenPermissionsOf('manager'); $indirectlyForbiddenPermissions = AccessControl::getIndirectlyForbiddenPermissionsOf('manager');
Read Terminologies if you don't know about direct/indirect permissions.
Assigning Role
Role can be assigned to any user using method assign
and chain it with to
method. Alternatively, you can use the assign
method that's available method on the User model itself. Example:
AccessControl::assign('admin')->to($user); // using facade $user->assign('editor'); // using user model
You can also specify the roleable if the role requires specific roleables like this. For example, you want a user to be manager for a specific project only. It can be achieved like this:
AccessControl::assign('manager',$project)->to($user); // using facade $user->assign('manager',$project); // using user model
Retracting Role
Assigned role can be retracted from any user using method retract
and chain it with from
method. Example:
AccessControl::retract('admin')->from($user);
You can also specify the roleable to retract role only for the specific roleable. For example, if a user is the manager of multiple companies, the manager role for only given company will be retracted from the user:
AccessControl::retract('manager',$company)->from($user);
Checking Role
To check if a user have a specific role use method is
and chain it with a
or an
methods. Example:
AccessControl::is($user)->a('manager',$company); AccessControl::is($user)->an('admin');
To check if a user have a specific role chain it with notA
or notAn
methods. Example:
AccessControl::is($user)->notA('manager',$company); AccessControl::is($user)->notAn('admin');
To check if user have all the given roles, we can do something like:
AccessControl::is($user)->all([ 'admin', 'manager' ]);
It doesn't check for any roleables even if the role is restricted to some roleables. For Example, It will return true if the user have manager role for any roleable:
AccessControl::is($user)->all([ 'manager' ]);
To check if user have any of the given roles, we can do something like:
AccessControl::is($user)->any([ 'admin', 'manager' ]);
Resetting Role
To remove all the permissions from a role, we can reset it using the method resetRole
method. Example:
AccessControl::resetRole('admin');
Permission
Creating Permission
Permission can be created using the method createPermission
method. Example:
AccessControl::createPermission([ 'name' => 'edit-post', 'title' => 'Edit Post' ]);
Multiple permissions can be created at once using the method createManyPermissions
like this:
AccessControl::createManyPermissions([ ['name' => 'create-post','title' => 'Create Post'], ['name' => 'edit-post','title' => 'Edit Post'], ['name' => 'delete-post','title' => 'Delete Post'] ]);
Updating Permission
Permission can be updated using the method updatePermission
. For example, to change a permission's name from remove-post to delete-post we can do something like:
AccessControl::updatePermission('remove-post',[ 'name' => 'delete-post', 'title' => 'Delete Post' ]);
Deleting Permission
To delete a permission we can use the method deletePermission
like:
AccessControl::deletePermission('edit-post');
Getting Permission
To retrieve a permission we can use the method getPermission
like:
AccessControl::getPermission('delete-company');
To retrieve all the permissions available, use the method getPermissions
. Example:
AccessControl::getPermissions();
Getting Roles Having Permission
To get all the roles that have a permission, we can use method getAllRolesOf
like:
$rolesWhoCanEdit = AccessControl::getAllRolesOf('edit-post');
To get only specific type of roles for the permission, we can use methods getAllowedRolesOf
, getDirectlyAllowedRolesOf
, getIndirectlyAllowedRolesOf
, getForbiddenRolesOf
, getDirectlyForbiddenRolesOf
, getIndirectlyForbiddenRolesOf
. Examples:
// getting allowed roles $allowedRoles = AccessControl::getAllowedRolesOf('edit-post'); $directlyAllowedRoles = AccessControl::getDirectlyAllowedRolesOf('edit-post'); $indirectlyAllowedRoles = AccessControl::getIndirectlyAllowedRolesOf('edit-post'); // getting forbidden roles $forbiddenRoles = AccessControl::getForbiddenRolesOf('edit-post'); $directlyForbiddenRoles = AccessControl::getDirectlyForbiddenRolesOf('edit-post'); $indirectlyForbiddenRoles = AccessControl::getIndirectlyForbiddenRolesOf('edit-post');
Read Terminologies if you don't know about direct/indirect roles.
User
Getting User Roles
To get all the roles assigned to a user, we can use the method roles
provided by Back2Lobby\AccessControl\Models\User
. Example:
$roles = $user->roles()->get();
Getting User Permissions
To get all the permissions allowed for user through various roles, we can use the method permissions
provided by Back2Lobby\AccessControl\Models\User
. Example:
$roles = $user->permissions();
Getting Users With Specific Role
To get all the users that have a specific role, we can use the static method whereIs
provided by Back2Lobby\AccessControl\Models\User
. Example:
$admins = User::whereIs('admin')->get();
If the target role is restricted to some roleables, we can do something like:
$players = User::whereIs('player',$team)->get();
You can also reverse the logic by using users
method from the role model instead:
$admins = $adminRole->users()->get();
Getting Users With Specific Permission
To get all the users that have a specific permission, we can use the static method whereHas
provided by Back2Lobby\AccessControl\Models\User
. Example:
$users = User::whereHas('edit-post',$post)->get();
Checking User Permission
To check if a user have specific permission from any role, we can use the method canUser
and chain it with method do
like this:
$canCreatePost = AccessControl::canUser($user)->do('create-post');
You can also specify roleables like this:
$canEditPost = AccessControl::canUser($user)->do('edit-post',$post);
Resetting User
To remove all the roles from a user, we can use the method resetUser
. Example:
AccessControl::resetUser($user);
Features
Cache
All roles and permissions are cached and refreshed automatically every 24 hours. This optimization improves performance and reduces unnecessary database queries. Note that user data is not cached as it can frequently change.
You can manually sync all the roles and permissions with database with sync
method. For example:
AccessControl::sync();
To clear the cache you can use the method clearCache
like:
AccessControl::clearCache();
Even after clearing cache the local store will still have the roles and permissions, you can remove them also using the method reset
: Example:
AccessControl::reset();
Manually caching the store can be achieved using cache
like:
AccessControl::cache();
Note: By default,
file
is used as the cache driver, but it can be changed inaccess.php
config file.
Authorization
To check roles and permissions in blade files, we can use Laravel built in can
method on the user model. For Example:
if($user->can('view-dashboard')){ // your code here }
If you want to check permission for a specific model, then we can do something like:
$user->can('edit-company',$company);
Blade Directive
Similarly, to check roles and permissions in blade files, we can use Laravel built in @can
directive to check. For Example:
@can('ban-users') <button class="btn btn-danger">Ban User</button> @endcan @can('edit-post',$post) <a href="{{ route('post.edit') }}">Edit Post</a> @endcan
Config File
Access Control provides a configuration file that can be used to configure the behaviour of the package including specifying cache driver and custom user model.
You can publish the config file access.php
using the command:
php artisan vendor:publish --tag="access-control.config"
Middleware
Similarly, built in can
middleware from Laravel as:
Route::get('/dashboard', function () { return view('dashboard'); })->middleware('can:access-dashboard');
This will check if the authenticated user has the access-dashboard permission before processing the request.
You can also use the can
middleware to check permissions for a specific model instance. For example, the route below will only be processed for users who have the edit-post
permission on the Post model instance that is passed to route model binding in /posts/{post}/edit
.
Route::get('/posts/{post}/edit', function () { return view('dashboard'); })->middleware('can:edit-post,' . Post::class);
In this case, Post::class
is passed to specify the model class for which the permission check should be performed. Note that this will only work if the route has route model binding for the Post model.
Custom User Model
By default, App\Models\User
model is used for authorization and authentication for this package. To use custom model instead, following steps are needed:
- Specify the model in
access.php
. For Example,
'auth_user_model' => CustomUserModel::class
- Make sure your custom user model extends
Illuminate\Foundation\Auth\User
. - Migrate the database tables related to the package or just use this command to get a fresh database.
php artisan migrate:fresh
- Note: Make sure you have specified the new auth model for the guard in
auth.php
config file. For Example,
'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'customUsers', ], ], 'providers' => [ 'customUsers' => [ 'driver' => 'eloquent', 'model' => App\Models\CustomUserModel::class, ], ],