Bouncer: a Laravel Package for Role and Ability Authorization
Published on by Paul Redmond
Bouncer is an authorization package by Joseph Silber which allows role and ability checks at Laravel’s authorization gate. The package is described as follows:
Bouncer provides a mechanism to handle roles and abilities in Laravel’s ACL. With an expressive and fluent syntax, it stays out of your way as much as possible: use it when you want, ignore it when you don’t.
Bouncer makes it trivial to quickly create roles and abilities with a fluent API that creates them automatically.
Bouncer::allow('admin')->to('ban-users');
You can optionally add the HasRolesAndAbilities
trait to the User
model. This trait allows you to assign roles and abilities, and check them with in the model.
use Silber\Bouncer\Database\HasRolesAndAbilities; class User extends Authenticatable{ use Notifiable, HasRolesAndAbilities;}
When you assign a role that hasn’t been created yet, Bouncer will do it automatically.
$user->assign('admin');
As a quick example, imagine a database seeder that creates a few roles with Bouncer and assigns users to a role using the HasRolesAndAbilities
trait.
public function run(){ \Bouncer::allow('admin')->toManage(Post::class); \Bouncer::allow('editor')->to('update', \App\Post::class); $admin = factory(App\User::class)->create([ 'email' => 'admin@example.com' ]); $admin->assign('admin'); $editor = factory(App\User::class)->create([ 'email' => 'editor@example.com' ]); $editor->assign('editor'); factory(App\User::class)->create([ 'email' => 'user@example.com' ]);}
The database seeder conveniently creates two roles: admin and editor. The admin will have permission to all post abilities on the App\Post
model. The editor role only has the update
ability.
With the above roles, abilities, and users, we can define a route and protect updating a Post
using Laravel’s Authorize
middleware.
Route::get('/posts/{post}', 'PostsController@show') ->name('post.update') ->middleware('can:update,post');
Both authenticated administrators and editors will be able to see a post, guests will be redirected to login, and authenticated users lacking the update
ability will get a 403 Forbidden
response.
In the view, you can use Laravel’s @can
directive to check for abilities and Bouncer will intercept the check and authorize it if an ability has been granted to the user.
@can ('update', $post) <a href="{{ route('post.update', $post) }}">Edit Post</a>@endcan
Not only can you grant user abilities through roles, but you can also assign an ability directly to a user.
$post = \App\Post::first();$normalUser = \App\User::find('email', 'user@example.com')->first(); // Only update a specific post, perhaps one this user submitted.$normalUser->allow('update', $post) // Ability to update all posts directly on a user$normalUser->allow('update', \App\Post::class);
Bouncer provides methods for checking user roles, but the Bouncer documentation warns against role checking directly:
Generally speaking, you should not have a need to check roles directly. It is better to allow a role certain abilities, then check for those abilities instead. If what you need is very general, you can create very broad abilities. For example, an
access-dashboard
ability is always better than checking foradmin
oreditor
roles directly.
Last, if you want to get a user’s abilities, call $user->getAbilities()
, which returns a database collection:
Check out the package’s readme to learn how to install and use Bouncer. The cheat sheet is handy for a quick overview of the package’s API and capabilities.