Bouncer, with Joseph Silber
Matt Stauffer:
Hi, and welcome back to Laravel Podcast, season five, where every single episode is about a particular package this time. So, today we're going to be talking with Joseph Silber, the creator of Bouncer. So, Joseph, can you say hi to the people real quick and tell them a little bit about yourself, before you get into the package conversation?
Joseph Silber:
Yeah. Hi, I'm Joseph Silber and I'm a core contributor to Laravel for many, many years now.
Matt Stauffer:
Mm-hmm (affirmative).
Joseph Silber:
And I also have the Bouncer package, which will be discussing today. I also have a popular, different package called Page Cache, and that's basically my public profile.
Matt Stauffer:
Okay, tell us a little bit about Bouncer. Can you give us the elevator pitch about the package? What's it for? And what is the main job that it's solving for folks?
Joseph Silber:
So, Bouncer is a way to manage permissions and roles for any app that uses Eloquent. Eloquent is Laravel's ORM. Any app that uses Eloquent, if you start using Laravel's built-in gate and the policies eventually, as the app grows, you start having needs for more dynamic stuff, and you want the abilities to live in the database, so that they can be controlled by your users, like an admin can go into a dashboard and control it.
Matt Stauffer:
Mm-hmm (affirmative).
Joseph Silber:
And you also have the need then, for roles to have groups of abilities that are assigned to different users and you can update them together and manage them that way. And that is basically, what Bouncer does.
Matt Stauffer:
Okay. So, before we even talk a little bit more about what it does, can you tell me the history of what inspired you to make it in the first place?
Joseph Silber:
Yeah, so authorization, not to be confused with authentication. I think, we covered that in the previous podcast.
Matt Stauffer:
Yeah.
Joseph Silber:
But, authorization is, every app when it gets to a certain size, usually needs some authorization. And there's always been a lot of PHP packages for authorization. But, back in the day, by now, many years ago, Taylor introduced a gate concept in Laravel, which is Laravel's built-in way to handle authorization. And what I saw then, is that all these existing packages that were off on the side doing their own thing and they weren't integrated fully within Laravel. And I saw an opportunity there, where we can build something that sits on top of what Laravel gives you, so that you can continue using Laravel's authorization checks throughout your app, the same way you're used to using it. And just when you're assigning the abilities, you do that through Bouncer, but the checks all run through the same standard process that all Laravel Apps run through.
Matt Stauffer:
I love that. And if anybody doesn't know, we'll put a link into the show notes to the authentication and authorization episode from last podcast with Joseph. But, effectively, the gate in Laravel basically, allows you to say, "Can this user do this thing, edit this thing, create this thing, or whatever?" So, Joseph is saying, "Let's keep using that same syntax, but allow it to be backed by a more robust system, which is what Bouncer brings to the table." Right?
Joseph Silber:
Yup, perfect.
Matt Stauffer:
Actually, before we talk about how to use it, are there any key dependencies, or steps for setting it up? Or, anything like that? Or, is it really just composer install and run your migrations.
Joseph Silber:
Yeah, Bouncer doesn't have any dependencies. You just install it. Then, you run the migrations. It comes with a set of migrations, because you're going to be storing the stuff in the database. You need several tables that Bouncer sets up for you. And that's basically it. I mean, documentation has a simple walkthrough of how to set it up, no-
Matt Stauffer:
Love it.
Joseph Silber:
Dependencies.
Matt Stauffer:
So, if I were to set it up, if I were to use it, one of my apps today, and I say, "I think I'm going to get a place where maybe my super administrators, right? The people who run the whole app, are going to have to define maybe for each tenant, or something like that. Who's the admin there? Who's the whatever. And maybe, even the admins of the tenant can decide the roles of some of the people beneath them, or whatever. So, all this stuff, the biggest thing with Bouncer, is that this stuff is all happening in the database, which means you can allow users to administer it, versus what you'd have to do traditionally, which is either write it yourself in the database, which means you're having to reinvent the wheel, or the programs are writing that stuff in code, right?" You're defining who has access to what in code, you're defining the roles in codes. So, the cool thing about this, is it's all defined in the database, makes it easy for people to edit it.
Matt Stauffer:
So, if I wanted to set that basic concept up, what's the actual day-to-day experience of working with this application like?
Joseph Silber:
So, it really depends, because you started mentioning they're different tenants and Bouncer does have separate support from multitenancy, which is a whole nother level of complexity on top of standard stuff.
Matt Stauffer:
Oh really?
Joseph Silber:
Yes. We don't have to get into all the detail.
Matt Stauffer:
Yeah, single tenants for now, yeah. For sure.
Joseph Silber:
Yeah. It's in the documentation, but Bouncer has specific support for multitenancy where you can have different roles and different abilities for different tenants of your application.
Matt Stauffer:
Love it.
Joseph Silber:
But, just taking a simple app, that has one set of abilities and one set of roles. Then, probably what you would do is you would set up in a Cedar class, all of the abilities and the roles that you want. You would probably,, start out your roles with the defaults that you think makes sense for which abilities you would hook them up. And then, once you have that, you can build a front-end UI, that's going to let your users toggle that. And then, it's up to you. If you want to let them create new types of roles that you hadn't created, or you only want them to be able to add and remove abilities amongst roles, or assigning users to roles, that's totally up to you. Bouncer gives you all the flexibility there and you decide how you want to build your front-end.
Matt Stauffer:
I love it. So, I have an app, where it has to do with payroll at Titan and there's employees. And then, there's managers, and then there's administrators. And so, I like to be at a place where a manager can add new employees, an employee can't add new employees. So, at some point I would've seeded the three roles, right? There's admin manager, and then there's employee. And then, in a database somewhere, or Nova, or some administrative tool, I basically go to each individual person and say, "What role are they attached to?" And then, am I also attaching roles to abilities? Which are the things that are directly being checked by gate in that same interface? Theoretically, at least?
Joseph Silber:
Yes. Again, theoretically, it's up to you, how you build your user interface. But, Bouncer's interface-
Matt Stauffer:
Right.
Joseph Silber:
If you look at the documentation, Bouncer's interface, everything you do, Bouncer is like a sentence.
Matt Stauffer:
Mm-hmm (affirmative).
Joseph Silber:
So, you could say, "Bouncer, allow user to edit post."
Matt Stauffer:
Right.
Joseph Silber:
Or, you could say, "Bouncer, assign admin to user." So, within Bouncer, you have all this flexibility, and then you decide what you want to expose to your users, how much flexibility you want to give them.
Matt Stauffer:
Right. Love it. So, if somebody finds themself in a place where, for any way, shape, or form, that they decide that they want to have a database managed set of roles and permissions, and who's assigned at each role. Bouncer's basically, a pre-made structure with some really convenient tooling for it. Other than the thing that you just mentioned, you're using this more easy to use syntax for assigning these things. I know that Bouncer doesn't have much of a read syntax, because the reading of this, the configuration is just continue to use Laravel's ACL as it exists, right?
Joseph Silber:
And that's by design.
Matt Stauffer:
Right, that's really cool. Is there any other interface between the programmer and Bouncer, other than the right part when they're setting, who's assigned to a role? Which role has which abilities? Which roles exist? Or, is that really it, you're just configuring those things, and then Bouncer does all the magic from there?
Joseph Silber:
So, this is something that keeps on coming up. In general, you don't have to do that. But, the only thing that people do want to check, is roles, since Laravel's own gate has no built-in concept of roles-
Matt Stauffer:
Concept of roles, right.
Joseph Silber:
People want to ask Bouncer whether a given user has a role-
Matt Stauffer:
Mm-hmm (affirmative).
Joseph Silber:
But, I personally consider that an anti-pattern. And I've written about that in the documentation, because the reason people ask for roles is for example, instead of creating a broad ability that says, access dashboard-
Matt Stauffer:
Right.
Joseph Silber:
And checking that before accessing the dashboard, they hard-coded into their code, is the user A, Admin-
Matt Stauffer:
Admin, or whatever, yeah.
Joseph Silber:
And I don't think that's great, because that locks you into that. The whole idea-
Matt Stauffer:
Yeah.
Joseph Silber:
Here, is that roles are just a shortcut, a way to bundle a bunch-
Matt Stauffer:
A sign.
Joseph Silber:
Of abilities-
Matt Stauffer:
Yes.
Joseph Silber:
And apply them to a user. So, actually I know there are some packages out there that have more syntax sugar around this, for example, Laravel has a built-in blade directive ad cam-
Matt Stauffer:
Mm-hmm (affirmative).
Joseph Silber:
Which, checks whether a user can do something, a given ability. So, Bouncer doesn't actually ship with a, at role, some systems ship with these things. At role, where you check in Blade, whether it's a role, or even a middleware where you could wrap some routes and give it access only based on the user's role. Bouncer doesn't ship with that, because I don't think that's correct way to do it. It might be easy sometimes, to get off the ground, but eventually it comes back to bite you.
Matt Stauffer:
Yeah.
Joseph Silber:
I'd much rather you create a very broad ability and lock it up by that ability, can access dashboard and go assign the access dashboard to the admin role. And then, eventually you can change that up.
Matt Stauffer:
Yeah.
Joseph Silber:
But, people still want to do it. So, Bouncer does give people the ability to ask Bouncer whether a user has a given role, or not. So, they can wire that up themselves, but we don't give it to them, because I don't think that's right.
Matt Stauffer:
Yeah. And I mean, I totally get that. So, in this example of this Payroll App, I originally only had two types. I had users and I had admins. And if I had built it checking on whether you're an admin, and then later wanted to add the manager role, which can do some things, admin can't, but not other. I would've then, had to change all those checks to say, "Is admin, or is manager." But, I originally, built it to say, "Can do this, can do that, can do whatever and assigned those abilities to the admin." So, later when I added managers, I was like, "Oh, add managers also can do these two things. Boom, that's it." Versus, having to suddenly change all my role checks everywhere else. So-
Joseph Silber:
Correct.
Matt Stauffer:
I'm 100% on board with that
Joseph Silber:
Funny thing about that, the method in Bouncer, to check whether a user has a given role is called, "Is a." So, you say, "User is a admin." But, just because I really like things to read like sentences-
Matt Stauffer:
Yeah.
Joseph Silber:
I have an overload, I have two methods. One is, "is a", the other is, "is an" with an N.
Is an admin, or is a subscriber.
Matt Stauffer:
I love that.
Joseph Silber:
What's funny is, I thought, it's very intuitive, but I forgot that some people aren't native English speakers. So, somebody actually opened up an issue on GitHub that they have the name of the role in a variable. And they don't know which of the two to call. Whether it's, "is a", or "is an". So-
Matt Stauffer:
That's awesome.
Joseph Silber:
We have to always remember that. Not everybody speaks English the way we do. And-
Matt Stauffer:
That's cool. But, the funny thing is the answer can be, well, which is appropriate, given the name of your variable.
Joseph Silber:
Correct, that's what I told them, but-
Matt Stauffer:
I love that. That's so good. Okay. So, are there any lesser used features? Or, any cool things that you've seen people do with Bouncer, that are outside of the norm? Or, do most people stick within the main usage of it?
Joseph Silber:
So, I guess, let me just quickly run through the main features, how you interact with Bouncer. So-
Matt Stauffer:
Yeah.
Joseph Silber:
You either say, "Allow...." Roles are simple. You assign a role to a user, or you retract the role from the user.. Abilities, Bouncer has two concepts of abilities, allowing abilities and forbidding abilities. So, you can allow a broad based ability. Let's say, you allow a user to edit any post. Then, you can forbid them from editing a single post.
Matt Stauffer:
Mm-hmm (affirmative).
Joseph Silber:
And that way you can layer these things based on the exact granularity that you need. So, Bouncer has an allow and disallow, allow, adds an ability. Disallow removes the ability.
Matt Stauffer:
Mm-hmm (affirmative).
Joseph Silber:
Forbid doesn't remove the ability, forbid adds a forbidden permission-
Matt Stauffer:
Right.
Joseph Silber:
So, that it locks it down further. So, you can play around with the granularity, whatever you need. And sometimes, the trips are people, because people think, if they say forbid, and then, they say unforbid-
Matt Stauffer:
Mm-hmm (affirmative).
Joseph Silber:
Then, they think it's automatically going to be allowed. And they don't realize that the user actually needs a permission to do that. If you're just removing the forbidden part, it doesn't automatically become allowed.
Matt Stauffer:
Yeah.
Joseph Silber:
So, that's something that's tripped up people, I've tried to improve it in the docs. Maybe, you have an idea for that, but-
Matt Stauffer:
I don't know if I have any better ideas. This makes sense. Because, if remove forbid is very different than allow, right?
Joseph Silber:
Correct, yes.
Matt Stauffer:
So, I think that it's pretty intentional there and it makes sense. So
Joseph Silber:
Yeah. So, what I've seen people do with this, is people use this for banning users. So, if you want ban a user, you don't really want to take away all their abilities, because then once you decide to release the band, you're going to have to somehow figure out and recreate all the abilities you've given them.
Matt Stauffer:
Right.
Joseph Silber:
So, what people do is they create a band role. On the band role, they say, "Forbid everything."
Matt Stauffer:
Okay.
Joseph Silber:
Bouncer has very complex types of abilities. You could do everything you could do per model, individual models, broad based models. You could say, "Allowed to view everything, delete this. It's very flexible."
Matt Stauffer:
Yeah.
Joseph Silber:
So, what people do, they create a band role and that role forbids everything. Now, they want to ban a user, they assign them that role. When they decide to remove the band, they just remove-
Matt Stauffer:
Yeah.
Joseph Silber:
The role and they fall back to all their existing abilities.
Matt Stauffer:
That's great. A forbiddens a forbidden, whatever. When you forbid something, it automatically, overrides any of the allowances that happened before it, right?
Joseph Silber:
Correct.
Matt Stauffer:
Well, any other allowances, it's always an override of the allow.
Joseph Silber:
Correct, yes.
Matt Stauffer:
Okay, that makes sense. Is there any concept of timing? Which layers on top of which, that you have to ever consider? In terms of permissions.
Joseph Silber:
Not really, only with regards to forbidding and allowing that the forbid always takes precedence over whatever was allowed. But, other than that, no.
Matt Stauffer:
They're just stacking up. You can add to allowances. You don't have to worry about which of them came first-
Joseph Silber:
Yeah.
Matt Stauffer:
Because, they're both allowing you to do something.
Joseph Silber:
Yeah, the only difference there, is that in addition to whatever you set up in Bouncer, sometimes you do want to set up some checks within your own code, whether it's by using Gate Define, or within a policy, if it's really complex business logic that doesn't fit within the standard Bouncer stuff. And then, you have to be careful. You have to know which one runs first.
Matt Stauffer:
Got it.
Joseph Silber:
So, actually Bouncer currently... We changed it recently, because people were intuitively thinking about it differently. But, Bouncer currently runs after your policies, after everything you do.
Matt Stauffer:
Okay.
Joseph Silber:
So, if you explicitly allowed something, or you explicitly forbid something and the way that works from the gate is return a bullion.
Matt Stauffer:
Yeah.
Joseph Silber:
There's also other complex types of responses you can reply with, from within a policy that were added later on in Laravel.
Matt Stauffer:
Mm-hmm (affirmative).
Joseph Silber:
But, the main way is you respond with a bullion. And if you return low, then the gate keeps on checking all the checks down the road.
Matt Stauffer:
Oh interesting.
Joseph Silber:
So, the gate itself, also has several levels that are checks. The first checks, there's a global before where-
Matt Stauffer:
Yeah.
Joseph Silber:
You register in the gate before anything starts. So, you could, without Bouncer, you could just say, if the user is an admin let's say, then allow everything. So-
Matt Stauffer:
Yeah.
Joseph Silber:
There's a before and there's the gates and there's the policies and the policies themselves, can also have it before. So, you can have before, just specific to that type of model that the policy addresses.
Matt Stauffer:
Yeah.
Joseph Silber:
And then, there's an after callback, after all of your stuff is done after. So, currently what Bouncer does, is Bouncer registers itself as an after callback on the gate. So, after
all your checks are done, if you did not make a decision, whether to allow, or disallow, then Bouncer runs, if you already made a decision, Bouncer doesn't run at all-
Matt Stauffer:
Got it.
Joseph Silber:
And there's a setting actually, where you could switch it, that's so that Bouncer should run in the before callback. So, it should run before all your code.
Matt Stauffer:
Okay, that's cool.
Joseph Silber:
So, for example, if you were to use the band forbid role that we were talking about before, it wouldn't ban anything that you have explicitly allowed within your code, unless you instruct Bouncer to run before your code.
Matt Stauffer:
That makes a ton of sense. And so, the helpful thing about that is if you have a check and Bouncer by default, is running after you, if you return true, or false, both of them will now forbid, or will basically skip Bouncer entirely, and you got to return dollar void basically, in order to return dollar, or don't return at all in order to allow bouncer to do its thing.
Joseph Silber:
Exactly, yes.
Matt Stauffer:
Okay, that makes a ton of sense. It's very clear that you've worked with a lot of different people using this in a lot of different apps. And that's my favorite type of package, because not only have a lot of nuances and edge cases been considered, but the historic downfall of every major, especially in the jQuery world, I think of this package, is when every single thing that comes along, they just add it and it gets bigger and bigger and bigger and more bloated. And so, I love hearing an opinionated author saying, "I'm still trying to keep this with this original vision I had. I'm trying to make it work for other people, but I'm also always asking like, what's the best next step for the majority of people?" So, seeing how you apply that way of thinking to this package and try to keep it still sensible and still reasonable. You're willing to change from your original defaults. I love how you approach that, man.
Joseph Silber:
Thanks. So, actually another feature that many people have been asking for and which wasn't, again, like you said, in my original vision and people want per model roles. So, people want to, let's say, have an admin role, where obviously, if you apply the admin role to use it, they can do anything within the whole app. They want to apply an admin, let's say for billing, yeah? So, you have invoices. They want to apply a user to be an admin on invoices, which means that they can create the lead update and do anything with invoices.
Matt Stauffer:
Mm-hmm (affirmative).
Joseph Silber:
So, they want to have a role, but apply the role selectively that the user is only that role given on certain-
Matt Stauffer:
Okay.
Joseph Silber:
Either models, or model types.
Matt Stauffer:
Yeah.
Joseph Silber:
And that's an interesting concept. I've tried tackling it many times. And so far, I've failed. And the reason is because, just writing the code itself is not that hard.
Joseph Silber:
What's hard is when it comes to cashing, because Bouncer has several different strategies for cashing. So, you think about you land on a page and that page might be running several auth. checks. You don't want to hit the database for every check.
Matt Stauffer:
Right.
Joseph Silber:
So, by default, what Bouncer does, is it figures out that builds up a huge query behind the scenes,, really complex query. I mean, if you just beautify, that's-
Matt Stauffer:
Yeah.
Joseph Silber:
50 lines, or more.
Matt Stauffer:
Yeah.
Joseph Silber:
And it figures out based on the roles and based on the relationships and everything, and it pulls out all the abilities from the database that the user has. It cashes that for the current request. And then, any further checks that you do, are done against those abilities.
Matt Stauffer:
That's great.
Joseph Silber:
Now, Bouncer also has the option if you want to, where you can cash it across requests.
Matt Stauffer:
Mm-hmm (affirmative).
Joseph Silber:
So, that once it's cashed, follow up and visits are not going to pull it again.
Matt Stauffer:
Yeah.
Joseph Silber:
But, this worked and it worked for me and for my use cases and for the early people that were using this, the Bouncer. But, as people were adding more and more abilities and people were getting really granular and they could have a single user that had literally 100s, if not 1,000s of abilities.
Matt Stauffer:
Wow.
Joseph Silber:
And pulling that many abilities from the database, just wasn't going to cut-
Matt Stauffer:
Too slow, yeah.
Joseph Silber:
So, Bouncer actually has two different strategies that you can configure of how it fetches. Either, it fetches the specific ability that you need for this one, or it cashes it. Now, for the first strategy where we pull out all the abilities, which is what most people usually want, because you don't end up with 1,000s of abilities, unless you're doing something very specific.
Matt Stauffer:
Yeah.
Joseph Silber:
So, if you do that, then you can't really have model-based roles.
Matt Stauffer:
Mm-hmm (affirmative).
Joseph Silber:
Think about it.
Joseph Silber:
The abilities are connected to a specific model, based on the role.
Matt Stauffer:
Yeah.
Joseph Silber:
I don't know how much we can get into the details here and here. Because, it gets really grainy, but it's just-
Matt Stauffer:
Yeah.
Joseph Silber:
Not doable.
Matt Stauffer:
Yeah.
Joseph Silber:
So, there's a lot of decisions that have to be made. I was thinking maybe, of just having to explicitly opt into this feature, so that, you know whether it's going to be a query, or not, but yeah. That's something that the users that ask for it, don't understand the complexity of it and they shouldn't, that's why-
Matt Stauffer:
Yeah.
Joseph Silber:
We get paid the big bucks.
Matt Stauffer:
Right. The bi, open-source bucks, totally.
Joseph Silber:
Exactly.
Matt Stauffer:
But it's funny, because in that app, I told you about the payroll app. I have a role called edits, edit users, or admin users. I have a role called admin billing, and they're different roles that... You can have multiple roles, or abilities. I'm not sure, but basically ended up having to delineate the fact that administering one, versus administering the other is not the same. So, it's not by model, by model. It's like a model-type basis. And it felt a little bit weird to name something, not admin, but admin, whatever. But, in the end, who cares? What I was saying is some people can do this, some people can do that. And each of those is a bundle of abilities, so it's not just a ability. So, I just made those little bundles, and then I signed again... So, I don't know if I had some... I think I may ended up for a manager has multiple roles and a manager has the edit billing, or admin user's role. I don't know, something like that.
Matt Stauffer:
So, in order to do what you're saying, I did end up having to do almost, grandchildren roles, where-
Joseph Silber:
Yeah.
Matt Stauffer:
This role applies these two roles and then this role. So, yeah, I understand that the problem you're running into, because you're talking about basically, bundles that are bundled differently, but you think of them all within the admin scope basically.
Joseph Silber:
Yeah. It's not just admin, for example, you could have a reader, that the role itself basically says, that you can read, you can view everything, but then you want to selectively apply that, "You can view everything, yes. But, I'm only going to apply that to invoices and bills and receipts, let's say."
Matt Stauffer:
Mm-hmm (affirmative).
Joseph Silber:
So again, you could technically just create a reader for invoices role, reader-
Matt Stauffer:
Right.
Joseph Silber:
For this one. But, it gets quite hairy.
Matt Stauffer:
Yeah.
Joseph Silber:
So, maybe one day I'm going to try to tackle that.
Matt Stauffer:
I like, it sounds like a lot, but I like it. So, that's actually a perfect transition. Because, I was about to ask you about the development roadmap. But, actually before we talk about development roadmap, is there any other foundational aspects of work in this package that we haven't talked about?
Joseph Silber:
I guess, ownership. Bouncer has a very powerful concept of ownership. So, in addition to allowing, or disallowing specific abilities directly, you could say that the user can only do that if they own it.
Matt Stauffer:
Mm-hmm (affirmative).
Joseph Silber:
Now, let's think about a post, let's say a post, the editor that wrote it, they own it, it's theirs. Let's say, the post has an underscore user ID. And that user ID is some user. Now, you could say in Bouncer, you could say, "Bouncer, allow user to own posts."
Matt Stauffer:
Okay.
Joseph Silber:
Now, once they can own posts, that means that any post that they're going to try to view, delete, edit, or whatever, it's going to check if the user ID on that post matches the ID of the current user.
Matt Stauffer:
Mm-hmm (affirmative).
Joseph Silber:
And you can configure that, if it should be user ID, or something else and can also say, you only want to allow them to own stuff for certain abilities. They can own it to view it, but not to delete it. So-
Matt Stauffer:
Interesting.
Joseph Silber:
It's really powerful stuff.
Matt Stauffer:
I love that. I mean, that's one of the most common things I do, is you can do this, if you're an admin, or if you're on the post. So-
Joseph Silber:
Correct.
Matt Stauffer:
Totally, makes a ton of sense.
Joseph Silber:
Yeah.
Matt Stauffer:
I love that. Anything else we haven't covered?
Joseph Silber:
Yeah. And then, there's multitenancy-
Matt Stauffer:
Oh, right.
Joseph Silber:
Multitenancy basically, is... The way it works for users is quite simple. It's quite complex behind the scenes, but it's just the middleware that you apply to your routes. And in your middle way, you have to figure out obviously, how you identify the current tenant. Let's say, you have a sub domain, or something. You pull out that sub-domain and Bouncer has a method called Scope two. So, you're saying-
Matt Stauffer:
Okay.
Joseph Silber:
Bouncer, scope two, and you pass it, whatever identifier it is. And now, everything you assign, everything you check at the gate, everything is now going to be scoped to that identifier that you gave it. And people actually use that people you have for multitenancy, but people also use that for regular apps, where they want to have complete separation between the public dashboard and their admin dashboard. So, in a way it's, multitenancy, you have one system where-
Matt Stauffer:
Right, yeah.
Joseph Silber:
You have totally separate roles and abilities for the front end, than you have for your private dashboard.
Matt Stauffer:
Yeah.
Joseph Silber:
So, people do then again, instead of passing a sub-domain, they pass, let's say, public, or private. It's just an identifier.
Matt Stauffer:
It's cool.
Joseph Silber:
Yeah.
Matt Stauffer:
I like that a lot. It makes you think, that anytime you're working with the complicated user experience of ACL, why would you not use this app? Which, is probably the sign of a job, well done. So, that's awesome.
Joseph Silber:
Thanks.
Matt Stauffer:
Okay. So, do you have a development roadmap that you like to share? Is there a next version? Or, did you potentially just push out a next version? Or, anything like that? Where are you?
Joseph Silber:
If you want to talk about versions?
Matt Stauffer:
Yeah, let's talk about it.
Joseph Silber:
I actually have not released 1.0 of Bouncer yet.
Matt Stauffer:
Mm-hmm (affirmative).
Joseph Silber:
And the reason for that, is that to my great detriment, I'm a huge perfectionist. And people think that perfectionist release perfect things and that's not really true. Perfectionist never release-
Matt Stauffer:
Just never release...
Joseph Silber:
Because, they're not perfect. As the saying goes, never let the perfect be the enemy of the good.
Matt Stauffer:
Uh-huh (affirmative).
Joseph Silber:
So, I mean, Bouncer has been downloaded over a million times.
Matt Stauffer:
Yeah.
Joseph Silber:
It has 3000-
Matt Stauffer:
Super stable.
Joseph Silber:
Yeah, super stable. I think, I'm just going to release it right now.
Matt Stauffer:
Love this.
Joseph Silber:
Right now, I'm sitting here with you-
Matt Stauffer:
Yes.
Joseph Silber:
I'm going to release it. Let me just release it. I'm going to release it and that's it-
Matt Stauffer:
Oh my God.
Joseph Silber:
Okay, I'm going to write the release notes afterwards. I'm just going to-
Matt Stauffer:
Okay. This is a special moment.
Joseph Silber:
Published release. That's it, it's published.
Matt Stauffer:
Hey. Come on.
Joseph Silber:
No backtracking of that.
Matt Stauffer:
That's a big deal. I love that. Hold on, I'm trying to see if I... Oh wait, hold on, clapping? Hold on, I'm going live. I've got a sound effects board that I always forget to use. So, I don't know if this is actually going to end up in the editing. So, for if any of the rest of y'all don't hear this. It's going to be just for me and Joseph. Of course. Now this thing is taking forever. It's worth the weight. I swear.
Matt Stauffer:
Oh, come on.
Matt Stauffer:
Okay. I said, "It's worth the weight, I swear." And now, it's just going to spin forever. Oh, well yay.
Joseph Silber:
Okay, great.
Matt Stauffer:
Yeah, there we go. Well, that's awesome.
Joseph Silber:
Oh, there you go.
Matt Stauffer:
There you go. You and I hear it, even if nobody else does. That's awesome.
Joseph Silber:
I actually had a mentor a while back, many years ago. And there was a newsletter that was coming out and he asked me to write something for it. And I told him, I don't have the time.
Matt Stauffer:
Mm-hmm (affirmative).
Joseph Silber:
So, he said, "You have less time than the other people around you? Why don't you have the time?" And I started giving him the talk that I'm a perfectionist and I like everything to be perfect, so it takes me longer. And he told me something then, that was pretty powerful. He said, "The source of perfectionism is usually hubris.
Matt Stauffer:
Ooh.
Joseph Silber:
You're just too proud to release something that is not the best-
Matt Stauffer:
Uh-huh (affirmative).
Joseph Silber:
The most perfect version-
Matt Stauffer:
That's ever been done.
Joseph Silber:
Of what it could be.
Matt Stauffer:
Yeah.
Joseph Silber:
And obviously, that hurt.
Matt Stauffer:
Yeah.
Joseph Silber:
But, I went home and I was thinking about it a couple days. And then, I came back to him. I told him, "I don't think you're right. You know why? Because, everything I do in my private life, that never sees the light of day, that the public never sees. I'm also very, very particular about, and I make sure everything's perfect." So, he says, "Yeah, all perfectionists say that, because you have to be internally consistent."
Matt Stauffer:
You're like, "I thought I got you." And he's like, "Nope, nope, still not."
Joseph Silber:
So, yeah-
Matt Stauffer:
That's funny.
Joseph Silber:
Over the years, I've been thinking about it and I think he's right.
Matt Stauffer:
Mm-hmm (affirmative).
Joseph Silber:
Unfortunately, he is right. So, just got to go for it. Released it-
Matt Stauffer:
I'm glad it's happening. Nice work.
Joseph Silber:
We'll keep going.
Matt Stauffer:
I love it. It's funny, I used to be your perfectionist and then I over-corrected the other direction and I just put everything out no matter what. And then, I ended up with stuff that I wasn't proud of. So, now I'm trying to find a little happy middle space. So, given how high quality I know your work is, I'm pretty sure you're headed towards middle space, not the over-correcting. So, I'm not worried about that one for you. So, now that you have released 1.0, obviously it's going to be maybe up to a month and a half before people actually hear this one. Because, I think it's going to come out in mid April and we're recording on February 22nd. But, if they were interested in taking a look at what your development roadmap is going forward, A, do you have any big plans right now? And B, if you don't, is there any good place for them to look, to see if there's any way they can see where you're headed?
Joseph Silber:
Yeah. So, there's always so much to do. And if you look at the issues, there's a bunch of issues. I try to label them if the feature requests, I'm not really that much on top of it, but I should be-
Matt Stauffer:
It's okay,, it's Open-Source.
Joseph Silber:
Some of the upcoming things I have in my roadmap, is I still do want to figure out how to tackle per model roles-
Matt Stauffer:
Mm-hmm (affirmative).
Joseph Silber:
Where, you can assign roles. Then, there's also something that I also want to tackle, which is built-in constraints to the abilities. This is way more complex, but similar to ownership, but just generically, you should be able to say, "Allow this user to view posts where post priority is one, or whatever." So, you should be able to add arbitrary constraints onto the models, so that the ability only applies based on the models.
Joseph Silber:
That's one of the things I want to do. I also eventually, probably want to break out the documentation from GitHub, because it's growing and growing and growing. And I probably want to create its own website for it, proper. And a really long term goal, is to maybe even create a front-end package with UI. That is-
Matt Stauffer:
Okay.
Joseph Silber:
Something that people can... Similar to what Taylor did with Passport-
Matt Stauffer:
Mm-hmm (affirmative).
Joseph Silber:
Where they have a set of... Yeah, but I know, since they did it, it's become more complex. People use way more-
Matt Stauffer:
More front-end stuff, yeah.
*Joseph Silber:**
People used LiveWire, people use Inertia. They use it with React, with Vue, with Svelte, with-
Matt Stauffer:
Yeah.
Joseph Silber:
So many different. I don't know if that's really doable, but maybe just the plumbing, maybe just the JavaScript part of it, and then let the people do their own UI.
Matt Stauffer:
One thing you could also do is Stripe. And I think the new Cashier does this too. Where when you go to edit this thing, it takes you to almost what feels like a standalone app. So, it's not like it has to be embedded in their existing app. You're just going to tap through to it. And you're like, "Oh, I am now in the thing that has a nice side bar with a logo of my application in it. It's got its own user interface and I'm done with it. I hit save and it just boots me back to my-
Joseph Silber:
Yeah.
Matt Stauffer:
Normal thing. People have become a lot more accepting of that idea, rather than feeling like everything has to be integrated.
Joseph Silber:
Yeah. Stripe does that? Stripe Checkout?
Matt Stauffer:
It's Stripe Checkout, I think. Yeah, I always freaked the name of their individual products and I think the new Cashier does that as well. I remember, talking to Taylor about that. I can't remember exactly where he landed, but I think the new Cashier does something like that as well. So, it's something people are definitely warming up to where it doesn't always have to be perfectly integrated, especially if you're editing something. It's not like the checkout page is an entirely different page all the time. But, I think Stripe Checkout is, but I think, with Cashier at least, I think it's some aspect of when you're editing your own settings, or something like that, I wish I remembered off the top of my head, but yeah.
Joseph Silber:
So, there's actually two parts of the front-end. There's one about the administration, there's also about checks. In addition to being able to check permissions in your backend code. Sometimes, you also want to check permissions in the front end code. If you have an SBA-
Matt Stauffer:
Okay.
Joseph Silber:
Or, anything. You want the front end to be aware of what permissions are allowed and what aren't.
Matt Stauffer:
Mm. Now, that makes sense for sure, as a package.
Joseph Silber:
Yeah. But, that also, just like I said before with caching, that also there's mainly, three different strategies you can take with that. You can either fetch all their abilities up front.
Matt Stauffer:
Mm-hmm (affirmative).
Joseph Silber:
You could have the resources that are returned from the backend include within them, within the response of the resource include what the current user can do with those resources.
Matt Stauffer:
Yup.
Joseph Silber:
And you could also have just an endpoint where you could just send queries to ask whether a user has a certain ability and get a response.
Matt Stauffer:
Mm-hmm (affirmative).
Joseph Silber:
So, these are three different strategies, which is also something that has to be figured out.
Matt Stauffer:
Yeah.
Joseph Silber:
These things are further down on the roadmap, but yeah. Hopefully, one day I'll get there.
Matt Stauffer:
And hopefully, somebody who hears this, gets really excited about the opportunity to help solve the challenge with you and maybe, actually contribute to this to.
Joseph Silber:
Yeah.
Matt Stauffer:
So,, then my next question is literally, would you like to request any helper support? And it sounds like there's plenty of things where if somebody wanted to help out, wanted to be a part of thinking through those things, they can go check out those issues. Do you also have a GitHub sponsor, or Patreon that you want to shout out?
Joseph Silber:
No. No.
Matt Stauffer:
Okay.
Joseph Silber:
I've never done that. Maybe, I should look into it, but I'm good for now.
Matt Stauffer:
Okay. Yeah, it's up to you. So, was there any other way that people could help, or support you, other than chipping into those issues and seeing if they can either help think through it? Or, even think through some of the codes? Is there anything else-
Joseph Silber:
Yeah.
Matt Stauffer:
People could do to support you?
Joseph Silber:
Yeah. Just a second there about the GitHub sponsors, or Patreon or whatever. I do feel like once you turn it into a sponsor, even though it's still open source, it gets closer to a commercial endeavor.
Matt Stauffer:
Yeah.
Joseph Silber:
And you start becoming more responsible for it. Meaning, right now, if I don't want to work on Bouncer-
Matt Stauffer:
You just don't, yeah.
Joseph Silber:
I can't let it go for... I mean, I'd still check on the issues and make sure nothing's broken, but if I don't want to work on it for a couple of months-
Matt Stauffer:
Mm-hmm (affirmative).
Joseph Silber:
If I'm busy, I'm just not going to do it. Once you start accepting sponsors and accepting money from people, I think that moves it up a notch. Even though it's still open source and people are not paying you directly for your work.
Matt Stauffer:
Yeah.
Joseph Silber:
That's what I think. So, I'm not sure-
Matt Stauffer:
Totally understand.
Joseph Silber:
I want to go down that route yet.
Matt Stauffer:
Yeah. And totally fine by you.
Joseph Silber:
Yeah.
Matt Stauffer:
And I would say, that if I were ever to do it in your circumstance, I would try to be very clear, "This means this and it doesn't mean that." But, you're right, even if you spell that ahead of time, people will still develop some entitlement to your time and your energy and that's something you should definitely protect. So, I'm here for it.
Joseph Silber:
Okay, thanks.
Matt Stauffer:
Okay. So, I think we're about wrapped up all the questions I had for you. Before we're done for the day, is there anything else you wanted to talk about with this package?
Joseph Silber:
No, I think, that basically covers it. Yeah-
Matt Stauffer:
Awesome.
Joseph Silber:
Thanks for the opportunity.
Matt Stauffer:
Yeah, thank you for making this package. Thank you for being willing to spend some time on the call today to talk through it and share it with people. I mean, I really appreciate you.
Joseph Silber:
Okay, great. Thank you so much.
Matt Stauffer:
All right, see you all next time.
Joseph Silber:
See you.