Entrust
Role-based Permissions for Laravel 5
Install / Use
/learn @Zizaco/EntrustREADME
ENTRUST (Laravel 9|10 Package)
Forked from zizaco/entrust
Entrust is a succinct and flexible way to add Role-based Permissions to Laravel 9|10.
If you are using an older version of laravel, use version ~3.0
Contents
Installation
- In order to install Laravel 5 Entrust, just add the following to your composer.json. Then run
composer update:
"zizaco/entrust": "5.2.x-dev"
- Open your
config/app.phpand add the following to theprovidersarray:
Zizaco\Entrust\EntrustServiceProvider::class,
- In the same
config/app.phpand add the following to thealiasesarray:
'Entrust' => Zizaco\Entrust\EntrustFacade::class,
- Run the command below to publish the package config file
config/entrust.php:
php artisan vendor:publish
- Open your
config/auth.phpand add the following to it:
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => Namespace\Of\Your\User\Model\User::class,
'table' => 'users',
],
],
- If you want to use Middleware (requires Laravel 5.1 or later) you also need to add the following:
'role' => \Zizaco\Entrust\Middleware\EntrustRole::class,
'permission' => \Zizaco\Entrust\Middleware\EntrustPermission::class,
'ability' => \Zizaco\Entrust\Middleware\EntrustAbility::class,
to routeMiddleware array in app/Http/Kernel.php.
Configuration
Set the property values in the config/auth.php.
These values will be used by entrust to refer to the correct user table and model.
To further customize table names and model namespaces, edit the config/entrust.php.
User relation to roles
Now generate the Entrust migration:
php artisan entrust:migration
It will generate the <timestamp>_entrust_setup_tables.php migration.
You may now run it with the artisan migrate command:
php artisan migrate
After the migration, four new tables will be present:
roles— stores role recordspermissions— stores permission recordsrole_user— stores many-to-many relations between roles and userspermission_role— stores many-to-many relations between roles and permissions
Models
Role
Create a Role model inside app/models/Role.php using the following example:
<?php namespace App;
use Zizaco\Entrust\EntrustRole;
class Role extends EntrustRole
{
}
The Role model has three main attributes:
name— Unique name for the Role, used for looking up role information in the application layer. For example: "admin", "owner", "employee".display_name— Human readable name for the Role. Not necessarily unique and optional. For example: "User Administrator", "Project Owner", "Widget Co. Employee".description— A more detailed explanation of what the Role does. Also optional.
Both display_name and description are optional; their fields are nullable in the database.
Permission
Create a Permission model inside app/models/Permission.php using the following example:
<?php namespace App;
use Zizaco\Entrust\EntrustPermission;
class Permission extends EntrustPermission
{
}
The Permission model has the same three attributes as the Role:
name— Unique name for the permission, used for looking up permission information in the application layer. For example: "create-post", "edit-user", "post-payment", "mailing-list-subscribe".display_name— Human readable name for the permission. Not necessarily unique and optional. For example "Create Posts", "Edit Users", "Post Payments", "Subscribe to mailing list".description— A more detailed explanation of the Permission.
In general, it may be helpful to think of the last two attributes in the form of a sentence: "The permission display_name allows a user to description."
User
Next, use the EntrustUserTrait trait in your existing User model. For example:
<?php
use Zizaco\Entrust\Traits\EntrustUserTrait;
class User extends Eloquent
{
use EntrustUserTrait; // add this trait to your user model
...
}
This will enable the relation with Role and add the following methods roles(), hasRole($name), withRole($name), can($permission), and ability($roles, $permissions, $options) within your User model.
Don't forget to dump composer autoload
composer dump-autoload
And you are ready to go.
Soft Deleting
The default migration takes advantage of onDelete('cascade') clauses within the pivot tables to remove relations when a parent record is deleted. If for some reason you cannot use cascading deletes in your database, the EntrustRole and EntrustPermission classes, and the HasRole trait include event listeners to manually delete records in relevant pivot tables. In the interest of not accidentally deleting data, the event listeners will not delete pivot data if the model uses soft deleting. However, due to limitations in Laravel's event listeners, there is no way to distinguish between a call to delete() versus a call to forceDelete(). For this reason, before you force delete a model, you must manually delete any of the relationship data (unless your pivot tables uses cascading deletes). For example:
$role = Role::findOrFail(1); // Pull back a given role
// Regular Delete
$role->delete(); // This will work no matter what
// Force Delete
$role->users()->sync([]); // Delete relationship data
$role->perms()->sync([]); // Delete relationship data
$role->forceDelete(); // Now force delete will work regardless of whether the pivot table has cascading delete
Usage
Concepts
Let's start by creating the following Roles and Permissions:
$owner = new Role();
$owner->name = 'owner';
$owner->display_name = 'Project Owner'; // optional
$owner->description = 'User is the owner of a given project'; // optional
$owner->save();
$admin = new Role();
$admin->name = 'admin';
$admin->display_name = 'User Administrator'; // optional
$admin->description = 'User is allowed to manage and edit other users'; // optional
$admin->save();
Next, with both roles created let's assign them to the users.
Thanks to the HasRole trait this is as easy as:
$user = User::where('username', '=', 'michele')->first();
// role attach alias
$user->attachRole($admin); // parameter can be an Role object, array, or id
// or eloquent's original technique
$user->roles()->attach($admin->id); // id only
Now we just need to add permissions to those Roles:
$createPost = new Permission();
$createPost->name = 'create-post';
$createPost->display_name = 'Create Posts'; // optional
// Allow a user to...
$createPost->description = 'create new blog posts'; // optional
$createPost->save();
$editUser = new Permission();
$editUser->name = 'edit-user';
$editUser->display_name = 'Edit Users'; // optional
// Allow a user to...
$editUser->description = 'edit existing users'; // optional
$editUser->save();
$admin->attachPermission($createPost);
// equivalent to $admin->perms()->sync(array($createPost->id));
$owner->attachPermissions(array($createPost, $editUser));
// equivalent to $owner->perms()->sync(array($createPost->id, $editUser->id));
Checking for Roles & Permissions
Now we can check for roles and permissions simply by doing:
$user->hasRole('owner'); // false
$user->hasRole('admin'); // true
$user->can('edit-user'); // false
$user->can('create-post'); // true
Both hasRole() and can() can receive an array of roles & permissions to check:
$user->hasRole(['owner', 'admin']); // true
$user->can(['edit-user', 'create-post']); // true
By default, if any of the roles or permissions are present for a user then the method will return true.
Passing true as a second parameter instructs the method to require all of the items:
$user->hasRole(['owner', 'admin']); // true
$user->hasRole(['owner', 'admin'], true); // false, user does not have admin role
$user->can(['edit-user', 'create-post']); // true
$user->can(['edit-user', 'create-post'], true); // false, user does not have edit-user permission
You can have as many Roles as you want for each User and vice versa.
The Entrust class has shortcuts to both can() and hasRole() for the currently logged in user:
Entrust::hasRole('role-name');
Entrust::can('permission-name');
// is identical to
Auth::user()->hasRole('role-name');
Auth::user()->can('permission-name');
You can also use placeholders (wildcards) to check any matching permission by doing:
// match any admin permission
$user->can("admin.*"); // true
// match any permission about users
$user->can("*_users"); // true
To filter users according a specific role, you may use withRole() scope, for example to retrieve all admins:
$admins = User::withRole('admin')->g
