CoderFunda
  • Home
  • About us
    • Contact Us
    • Disclaimer
    • Privacy Policy
    • About us
  • Home
  • Php
  • HTML
  • CSS
  • JavaScript
    • JavaScript
    • Jquery
    • JqueryUI
    • Stock
  • SQL
  • Vue.Js
  • Python
  • Wordpress
  • C++
    • C++
    • C
  • Laravel
    • Laravel
      • Overview
      • Namespaces
      • Middleware
      • Routing
      • Configuration
      • Application Structure
      • Installation
    • Overview
  • DBMS
    • DBMS
      • PL/SQL
      • SQLite
      • MongoDB
      • Cassandra
      • MySQL
      • Oracle
      • CouchDB
      • Neo4j
      • DB2
      • Quiz
    • Overview
  • Entertainment
    • TV Series Update
    • Movie Review
    • Movie Review
  • More
    • Vue. Js
    • Php Question
    • Php Interview Question
    • Laravel Interview Question
    • SQL Interview Question
    • IAS Interview Question
    • PCS Interview Question
    • Technology
    • Other

23 May, 2022

Releasing Bouncer: Roles and Permissions for Laravel apps

 Programing Coderfunda     May 23, 2022     Laravel, Packages     No comments   

 After many years in development, 56 releases, 1.3 million downloads, and over 2,800 unsolicited stars, Bouncer has finally reached version 1.0. It has been extremely reliable and stable for quite a while now, and is being used in production by countless apps worldwide.

This is a personal update, with some musings about my journey through the years - from inception to final release. For technical information on how to use Bouncer day to day, check out the extensive documentation or listen to me discuss it with Matt Stauffer on The Laravel Podcast.


What is Bouncer?

Before diving into my personal journey, here's a quick overview of what Bouncer is, and how it fits into the greater Laravel ecosystem.

Bouncer is an open source package for dynamically managing roles and permissions in the database, fully integrated with Laravel's Gate.

Without getting into detail, here's a short list of some of its key features:

  • Simple abilities:

    1Bouncer::allow($user)->to('access-dashboard');
  • Model abilities:

    1Bouncer::allow($user)->to('view', Invoice::class);
    2Bouncer::allow($user)->to('delete', $invoice);
  • Flexible roles:

    1Bouncer::allow('admin')->everything();
    2Bouncer::assign('admin')->to($user);
  • Forbidding abilities:

    1Bouncer::allow($user)->to('view', Invoice::class);
    2Bouncer::forbid($user)->to('view', $confidentialInvoice);
  • Powerful ownership:

    1Bouncer::allow($user)->toOwn(Post::class);
  • Straighforward multi-tenancy:

    1Bouncer::scope()->to($tenantId);
  • Built-in caching

    1Bouncer::cache();

...and much more. For details, check out the full documentation, or just glance over the cheat sheet.

The original idea for Bouncer

Back in August of 2015, Taylor added a new Authorization system in Laravel 5.2, called the Gate. This provided a nice API for defining permission checks in your app for various actions, through simple define callbacks and full on policies, as well as hooks throughout the system for checking permissions against what you've defined.

As soon as I started playing with this, I knew it will be the future of ACL for all Laravel apps. It's just so good. Taylor has this amazing sense for clear and intuitive APIs, and the Gate abstraction really brought that to light.

However, one thing was missing from the built-in authorization system: dynamic permissions, stored in the database. The way the gate is built, all checks are performed by hard-coded functions defined in your app, so there's no way to allow your admins to control any of it at runtime via some dashboard UI. As Taylor's original commit clearly states:

[The built-in gate] gives a structure to organizing logic that authorizes actions on entities. It does not make any determination on how "user roles" are
stored

At the time, there were many other popular ACL systems which did support tweaking permissions at runtime, but they had one major drawback: they were all built prior to Laravel's Gate. They were completely separate systems; if you decided to use them, you would forgo all of the niceties and beautiful integrations that Laravel's gate offered.

So I decided to build an open source package that would get you the best of both worlds: dynamic DB-driven permissions, fully integrated with Laravel's gate. We made some improvements to the gate checks in Laravel 5.3, making it more streamlined and predictable, thus easier to store those abilities in the DB.

The Bouncer name and logo

The name Bouncer came to me pretty early on. A bouncer's duty is to provide security at the gate and to check people's permissions. So this was a very natural paring to the Gate in Laravel.

Interestingly, the logo designer I was working with at the time (who is not a native English speaker) did not get the reference. Here are some original logos he designed:

Bouncer early logo drafts

The two to the right are clearly inspired by a bouncing motion. Oof! Hopefully native speakers do get it right away.

After quickly clarifying the meaning of the word bouncer, we started iterating on actual bouncers. We tried friendly bouncers, threatening bouncers, bearded bouncers, square-jawed bouncers, and a ton of different variations. Here are just a few:

Bouncer early logo drafts

I'm quite fond of what we ultimately ended up with:

Bouncer

It exudes a strong sense of security, but the roundness makes it feel friendlier and less threatening.

Technical underpinnings

Bouncer's raison d'etre is to seamlessly integrate with Laravel's gate. To achieve that, I set out with a single goal in mind: you should only have to interact with Bouncer when assigning roles and abilities to users. For the actual authorization checks, Laravel's own hooks throughout the system should work automatically, without any special Bouncer syntax.

The way Bouncer hooks into Laravel's gate checks is pretty simple. The Gate lets you define a global before callback, which gets called before any other checks you've defined: if your before callback allows or disallows an action, no further checks will run.

While the before callback was originally intended for stuff like "allow everything for admins", I immediately realized that this would be the perfect place to hook up dynamic checks, allowing me to query the database for any permissions. This is how it originally worked (we later switched it to using the after callback - you can read more about that in this thread).

Documentation

From the get-go, documentation has been extremely important to me. Open source projects live or die by their documentation, so I wanted Bouncer's docs to be the best it possibly can. And especially in the Laravel ecosystem, Taylor has set an extremely high bar for meticulous documentation.

In a way, clear docs are sometimes even more important than the code itself. Without telling your users how to use your tool, very few of them will source dive to figure it out. They'll just move on to the next thing.

I attribute a lot of Bouncer's success to the clear documentation, but there's still a lot more to do on that front. Being the creator and having a clear picture of the whole puzzle, it's easy to forget what people new to the tool struggle with.

For example: as stated earlier, Bouncer is only meant to be used for assigning roles and permissions to users. The actual authorization checks are to be handled like you would in any standard Laravel app. So I figured I don't have to repeat all that, since it's clearly outlined in the Laravel docs. Nevertheless, I still see people struggle with that a lot. They set up their their roles and permissions, then don't know where to go from their. That's an area I still want to flesh out in the docs.

Working up to the release

Let me just state this right now: postponing the 1.0 release till now has done my users a disservice. Bouncer has been stable for years, and actively used in production the world over. And yet, I was always hesitant to release it, since I knew there's so much more I want to add to it. I discussed this at length with Matt on the podcast: I fell down the trap of wanting to make it perfect before releasing it, which is obviously impossible. As Voltaire has warned: "Perfect is the enemy of good".

So as I'm releasing version 1.0 of Bouncer, there are still 2 outstanding features that I really wanted to have included in the initial release, but didn't make the cut:

  1. Per-model roles. For the longest time, people have been clamoring to have a way of assigning roles to users only for a given model (or model class). Here's what that code would look like:

    1// Note: this is not implemented yet
    2Bouncer::allow('editor')->to(['view', 'edit'])->everything();
    3Bouncer::assign('editor')->to($user)->for(Invoice:class);

    With that, the user would be able to do see and edit all invoices, but nothing else. This can of course now be done directly without a role, but doing it through a role would provide another level of flexibility.

    I've tried tackling this many times, but it turns out to be quite tricky, because caching becomes a real nightmare. I still hope to tackle it one day. We'll see.

  2. Ability constraints. Allowing arbitrary constraints on a given ability would add even more granular control:

    1// Note: this is not implemented yet
    2Bouncer::allow($user)
    3 ->to('view', Post::class)
    4 ->where('is_confidential', false);

    If you go source diving in Bouncer, you'll find some code and tests where I started implementing this. It's far from done, but stay tuned.

Overall, Bouncer is in a really great place. Every good product has a long roadmap, and thinking I can get to the end of that road before releasing a 1.0 was both foolish and unrealistic.

So there, live on air during the podcast, I released Bouncer. It felt great!

  • Share This:  
  •  Facebook
  •  Twitter
  •  Google+
  •  Stumble
  •  Digg
Email ThisBlogThis!Share to XShare to Facebook

Related Posts:

  • Laravel Relationship Events Laravel Relationship Events is a package by Viacheslav Ostrovskiy that adds extra model relationship events. This package comes with the follo… Read More
  • Laravel Tenancy – Multi-Tenant Package for Laravel   Laravel Tenancy is a package by Daniël Klabbers, Paulo Trajano, and Bertrand Kintanar, for making your Laravel application multi-tenant: The … Read More
  • Eventy: WordPress-like Actions and Filters for Laravel Eventy is a Laravel package by Tor Morten Jensen that brings WordPress-style actions and filters to your Laravel app. This package has a lightwe… Read More
  • Laravel Self-Diagnosis Package Laravel Self-Diagnosis is a package by Marcel Pociot that performs self-diagnostics tests on your application. The checks include standard thi… Read More
  • Automatically Open Files on Artisan “Make” Commands  “Open on Make” is a neat little package by Andrew Huggins that makes it easy to have newly created files open in your editor of choice. When yo… Read More
Newer Post Older Post Home

0 comments:

Post a Comment

Thanks

Meta

Popular Posts

  • Vue3 :style backgroundImage not working with require
    I'm trying to migrate a Vue 2 project to Vue 3. In Vue 2 I used v-bind style as follow: In Vue 3 this doesn't work... I tried a...
  • SQL ORDER BY Keyword
      The SQL ORDER BY Keyword The ORDER BY keyword is used to sort the result-set in ascending or descending order. The ORDER BY keyword sorts ...
  • Enabling authentication in swagger
    I created a asp.net core empty project running on .net6. I am coming across an issue when I am trying to enable authentication in swagger. S...
  • failed to load storage framework cache laravel excel
       User the export file and controller function  ..         libxml_use_internal_errors ( true ); ..Good To Go   public function view () : ...
  • Laravel auth login with phone or email
          <?php     Laravel auth login with phone or email     <? php     namespace App \ Http \ Controllers \ Auth ;         use ...

Categories

  • Ajax (26)
  • Bootstrap (30)
  • DBMS (42)
  • HTML (12)
  • HTML5 (45)
  • JavaScript (10)
  • Jquery (34)
  • Jquery UI (2)
  • JqueryUI (32)
  • Laravel (1017)
  • Laravel Tutorials (23)
  • Laravel-Question (6)
  • Magento (9)
  • Magento 2 (95)
  • MariaDB (1)
  • MySql Tutorial (2)
  • PHP-Interview-Questions (3)
  • Php Question (13)
  • Python (36)
  • RDBMS (13)
  • SQL Tutorial (79)
  • Vue.js Tutorial (68)
  • Wordpress (150)
  • Wordpress Theme (3)
  • codeigniter (108)
  • oops (4)
  • php (853)

Social Media Links

  • Follow on Twitter
  • Like on Facebook
  • Subscribe on Youtube
  • Follow on Instagram

Pages

  • Home
  • Contact Us
  • Privacy Policy
  • About us

Blog Archive

  • September (100)
  • August (50)
  • July (56)
  • June (46)
  • May (59)
  • April (50)
  • March (60)
  • February (42)
  • January (53)
  • December (58)
  • November (61)
  • October (39)
  • September (36)
  • August (36)
  • July (34)
  • June (34)
  • May (36)
  • April (29)
  • March (82)
  • February (1)
  • January (8)
  • December (14)
  • November (41)
  • October (13)
  • September (5)
  • August (48)
  • July (9)
  • June (6)
  • May (119)
  • April (259)
  • March (122)
  • February (368)
  • January (33)
  • October (2)
  • July (11)
  • June (29)
  • May (25)
  • April (168)
  • March (93)
  • February (60)
  • January (28)
  • December (195)
  • November (24)
  • October (40)
  • September (55)
  • August (6)
  • July (48)
  • May (2)
  • January (2)
  • July (6)
  • June (6)
  • February (17)
  • January (69)
  • December (122)
  • November (56)
  • October (92)
  • September (76)
  • August (6)

  • Failed to install 'cordova-plugin-firebase': CordovaError: Uh oh - 9/21/2024
  • pyspark XPath Query Returns Lists Omitting Missing Values Instead of Including None - 9/20/2024
  • SQL REPL from within Python/Sqlalchemy/Psychopg2 - 9/20/2024
  • MySql Explain with Tobias Petry - 9/20/2024
  • How to combine information from different devices into one common abstract virtual disk? [closed] - 9/20/2024

Laravel News

  • ElasticLens: Eloquent-Powered Elasticsearch for Laravel - 5/29/2025
  • Compare Collection Keys with Laravel's diffKeys Method - 5/25/2025
  • "In Array Keys" Validation Rule Added in Laravel 12.16 - 5/28/2025
  • Validate URLs Effectively with Laravel's Str::isUrl Method - 5/25/2025
  • Setup Social Auth Redirects with Laravel Herd - 5/27/2025

Copyright © 2025 CoderFunda | Powered by Blogger
Design by Coderfunda | Blogger Theme by Coderfunda | Distributed By Coderfunda