[L5] Roles and permissions
Building a CMS for my company in Laravel 5, which makes me so happy.
We are supposed to have different roles, such as "developer", "boss", "sales", "client" etc, and each role should have some set of permissions (to access a certain route).
What would be the best way to accomplish this? I'm talking about both code and database structure.
Great, but which package?
Maybe this? https://github.com/BeatSwitch/lock
Easily build your own with a few tables and methods. Not going to type it all out here but Jeffery has a video about roles and you can easily add permissions to each role and run a few methods to check if a user has permissions.
Basically my suggestion is:
Roles table, role_user pivot to assign a user to a role, Permissions table and a permission_role pivot to assign permissions to a role.
If your developing apps, a role and permissions should be a snap.
https://github.com/caffeinated/shinobi
I'm the developer behind this package and does exactly what you want. It closely follows the same concept that Jeffrey laid out in his Users and Roles video - which I do recommend watching to get an understanding of what's going on.
@ kai_desu
Awesome!!! Looking at it now.
Take a look at Sentry
Sentinel 4 ftw ! :)
I was looking at Vault the other day: https://github.com/rappasoft/vault
I've used this blog post as a basis for putting something simple together for a personal project. You might need to tweak it a little for L5.
Sometimes you don't need the complexity or overhead offered by a prewritten package.
Sentry is written for PHP and not specifically for Laravel. I personally find it messy and most of it you will never use. Just my 1/2 cent.
I initially used Sentry but opted to later switch to just using my own. The way things are laid out it's very easy to create your own. It's a simple as a single middlware and the key to it is is knowing the following:
$route = $request->route();
$action = $route->getAction();
If you dd() $action you'll see it has your route names. So you could just do something like maybe:
if ( ! $request->user()->hasRoute($action['as']))
{
return response('Unauthorized.', 401);
}
return $next($request);
Add the method on the users model. For the database structure it'll depend on how you intend on laying it out. Do you want users to have a single role or multiple roles. This post outlines a decent database structure: https://laracasts.com/discuss/channels/requests/role-based-resources-management . Only thing you might change is the actions table would instead just have:
name
description
route
Thanks guys for all of your help, this will come in handy for lots of people.
Now, what are your advices on building an ACL system in Laravel? Simply put in an example: I have a navigation with three links - link1, link2 and link3. What if you wanted to specify for every user in the system which of those three links the user could see? Ie:
- user1 could see only link 1
- user2 could see link1 and link2
- user3 could see link1, link2 and link3
- user4 could see link1 and link3 etc.
Would you go about it the same way as with the roles system? I very much want to learn how to build this on my own so I'd like to follow best practices as much as possible.
Just wrap the items in the navigation in a permission check:
<nav>
<ul>
@if ( User::acl()->has('permission1') )
<li><a href="#">Link 1</a>
@endif
@if ( User::acl()->has('permission2') )
<li><a href="#">Link 2</a>
@endif
@if ( User::acl()->has('permission3') )
<li><a href="#">Link 3</a>
@endif
</ul>
</nav>
Switch out the permission check for however you've implement that functionality. You might put the menu in a view composer and drop the needed permission in there, then just check using the key on your menu collection.
Edit: Remember, your user is granted permission to access things, they're not assigned things they have access to.
@deringer kudos! That seemed very easy for me too, thought I was wrong and there were other approaches. Many thanks!
@toniperic There's almost always other approaches, it's up to you to determine what works best for you. One day that will change, and then you can refactor!
Don't get caught up in what's better or the "right way", do what works best for you and revise it as your knowledge increases.
I implemented a permission module for Laravel 5: https://github.com/cgrossde/Laraguard (enforcing permissions on controllers/methods) It works great in conjunction with https://github.com/caffeinated/shinobi or https://github.com/romanbican/roles (storing roles and permissions of users)
Adds a permission system to Laravel 5 using the new integrated authentication mechanism. Instead of protecting routes, it protects the controller and its methods. This way you do not expose protected functionality if you forgot to protect a certain route. Controllers are protected with a simple syntax: ControllerName@MethodName. If you have a ClientController.php and want to add a permission called client.edit you would do something like this:
client.edit:
- Client@edit
- Client@update
Laraguard also supports * if you want to allow all methods or all controllers:
client.admin:
- Client@*
site.admin:
- "*@*"
Should be quite easy to use ;) If you use roles or not is entirely up to you.
Have a look at this package - https://github.com/romanbican/roles
Nice package, works great together with Laraguard. I added a link of it to the README ;)
Please or to participate in this conversation.