Skip to content

Instantly share code, notes, and snippets.

@amochohan
Last active November 8, 2023 21:03
Star You must be signed in to star a gist
Save amochohan/8cb599ee5dc0af5f4246 to your computer and use it in GitHub Desktop.
Laravel 5 Simple ACL - Protect routes by an account / role type

#Laravel 5 Simple ACL manager

Protect your routes with user roles. Simply add a 'role_id' to the User model, install the roles table and seed if you need some example roles to get going.

If the user has a 'Root' role, then they can perform any actions.

Installation

Simply copy the files across into the appropriate directories, and register the middleware in App\Http\Kernel.php

Then specify a 'roles' middleware on the route you'd like to protect, and specify the individual roles as an array:

Route::get('user/{user}', [
     'middleware' => ['auth', 'roles'],
     'uses' => 'UserController@index',
     'roles' => ['administrator', 'manager']
]);

If you found this ACL manager helpful please give this repo a star, and give me a follow. Any questions, please leave a comment.

<?php namespace App\Http\Middleware;
// First copy this file into your middleware directoy
use Closure;
class CheckRole{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
// Get the required roles from the route
$roles = $this->getRequiredRoleForRoute($request->route());
// Check if a role is required for the route, and
// if so, ensure that the user has that role.
if($request->user()->hasRole($roles) || !$roles)
{
return $next($request);
}
return response([
'error' => [
'code' => 'INSUFFICIENT_ROLE',
'description' => 'You are not authorized to access this resource.'
]
], 401);
}
private function getRequiredRoleForRoute($route)
{
$actions = $route->getAction();
return isset($actions['roles']) ? $actions['roles'] : null;
}
}
<?php
// Register the new route middleware
protected $routeMiddleware = [
'auth' => 'App\Http\Middleware\Authenticate',
'auth.basic' => 'Illuminate\Auth\Middleware\AuthenticateWithBasicAuth',
'guest' => 'App\Http\Middleware\RedirectIfAuthenticated',
'roles' => 'App\Http\Middleware\CheckRole',
];
<?php namespace App;
use Illuminate\Database\Eloquent\Model;
class Role extends Model {
protected $table = 'roles';
public function users()
{
return $this->hasMany('App\User', 'role_id', 'id');
}
}
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateRolesTable extends Migration {
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('role', function($table) {
$table->increments('id');
$table->string('name', 40);
$table->string('description', 255);
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('role');
}
}
<?php
use Illuminate\Database\Seeder;
use Illuminate\Database\Eloquent\Model;
use App\Role;
class RoleTableSeeder extends Seeder{
public function run()
{
if (App::environment() === 'production') {
exit('I just stopped you getting fired. Love, Amo.');
}
DB::table('role')->truncate();
Role::create([
'id' => 1,
'name' => 'Root',
'description' => 'Use this account with extreme caution. When using this account it is possible to cause irreversible damage to the system.'
]);
Role::create([
'id' => 2,
'name' => 'Administrator',
'description' => 'Full access to create, edit, and update companies, and orders.'
]);
Role::create([
'id' => 3,
'name' => 'Manager',
'description' => 'Ability to create new companies and orders, or edit and update any existing ones.'
]);
Role::create([
'id' => 4,
'name' => 'Company Manager',
'description' => 'Able to manage the company that the user belongs to, including adding sites, creating new users and assigning licences.'
]);
Role::create([
'id' => 5,
'name' => 'User',
'description' => 'A standard user that can have a licence assigned to them. No administrative features.'
]);
}
}
<?php
Route::get('user/{user}', [
'middleware' => ['auth', 'roles'], // A 'roles' middleware must be specified
'uses' => 'UserController@index',
'roles' => ['administrator', 'manager'] // Only an administrator, or a manager can access this route
]);
<?php
// The User model
public function role()
{
return $this->hasOne('App\Role', 'id', 'role_id');
}
public function hasRole($roles)
{
$this->have_role = $this->getUserRole();
// Check if the user is a root account
if($this->have_role->name == 'Root') {
return true;
}
if(is_array($roles)){
foreach($roles as $need_role){
if($this->checkIfUserHasRole($need_role)) {
return true;
}
}
} else{
return $this->checkIfUserHasRole($roles);
}
return false;
}
private function getUserRole()
{
return $this->role()->getResults();
}
private function checkIfUserHasRole($need_role)
{
return (strtolower($need_role)==strtolower($this->have_role->name)) ? true : false;
}
@AngeloMerlo
Copy link

I'm using 5.3 laravel and I have a problem I do not know how to solve. Could anyone help me, please?

Route: Route::get('/', function () { return view('welcome'); });
error: FatalThrowableError in CheckRole.php line 20: Call to a member function hasRole() on null

@greatsami
Copy link

greatsami commented Oct 13, 2016

Update:
I solved my issue. by adding this codes in app\Exceptions\Handler.php @ unauthenticated function:

$route = Route::getCurrentRoute()->getPath();
switch($route) {
     case 'admin':
             $login = '/admin/login';
             break;
     default:
             $login = '/login';
             break;
}

return redirect()->guest($login);

Now its working :)

Hi

I used your tutorial and every thing is OK.
i built admin layouts as separate theme, when I write in url: (http://multiauth.dev/admin) (and not logged) it redirect me to original login.
I need to redirect me to (http://multiauth.dev/admin/login).

i have a note if logged to admin i can see (http://multiauth.dev/admin/login) page.

How i can do it?
note: I'm newbie with laravel

@JoseCage
Copy link

Thank you o much for this snnipet..

Works for me.. 👍 📦 💯

@Shkeeny
Copy link

Shkeeny commented Nov 24, 2016

Hello, I'm new to Laravel, how do I add a restriction to this route: Route::resource('users', 'UserController'); ? Thanks in advance!

@amochohan
Copy link
Author

@Shkeeny this code won't work with route resources out of the box.

@k9uma
Copy link

k9uma commented Dec 7, 2016

Hai, I used this method a couple months ago L5.0, just tried it with 5.3 and i keep getting the same error about not finding the CheckRole class, something like this "ReflectionException in Container.php line 749:
Class App\Http\Middleware\CheckRole does not exist"
Any ideas??

@yourzed
Copy link

yourzed commented Dec 7, 2016

Hi @drawmyattention,
your code works great with my project. The thing is that it only works for two roles, when I do a thirth, it passes the autenthication, but the view shows a 500 error with no more info. My routes are like this:

Route::group(['middleware' => ['auth','roles'], 'roles' => ['Administrator']], function() {
Route::controller('/system/dashboard', 'AdminController');
.... THIS WORKS
});

Route::group(['middleware' => ['auth','roles'], 'roles' => ['Role1']], function() {
Route::controller('/system/dashboard', 'AdminController');
.... THIS WORKS
});

Route::group(['middleware' => ['auth','roles'], 'roles' => ['Role2']], function() {
Route::controller('/system/dashboard', 'AdminController');
.... IT Goes to the controller, but when showing the view: error 500...
});

Any idea of why? Of course I have all the roles on the database. And If I delete the last route group and try to login with that customer, it shows the Insuficient role, you are not allowed, correctly.
Thanks in advance

@amochohan
Copy link
Author

@yourzed if it gets to the controller, the middleware has allowed the request. If you're getting a 500 error from the view, I don't see how that'd related. You may be referring to a value that doesn't exist, which causes blade to thrown an exception.

@yourzed
Copy link

yourzed commented Dec 9, 2016

Many thanks @drawmyattention, finally I managed to work it ! I had to made some changes on the app.php and that was all. Thanks, it works like charm on laravel 5.1 ;)

@daino92
Copy link

daino92 commented Dec 13, 2016

@drawmyattention Hello mate! So I get this error:

BadMethodCallException in Builder.php line 2405:
Call to undefined method Illuminate\Database\Query\Builder::role()

This is my sample route:

Route::get('/admin/products', [
'uses' => 'AdminController@adminProducts',
'as' => 'admin.products',
'middleware' => ['auth', 'roles'],
'roles' => ['admin'],
]);

Can you tell me what's going on? Also I have added the roles() relationship function on the User model.

@rutvij2292
Copy link

rutvij2292 commented Jan 17, 2017

@drawmyattention Thanks for the simple solution for ACL. I would like to add few lines in controller to work with Route::group.

Here's my suggestion.

`
Route::group(['middleware' => ['auth', 'roles'], 'roles' => ['admin']], function() {
Route::get('admin/{user_id}/edit/{course_id}/reasons/{reason_id}', [
'uses' => 'AdminController@reasonsShowAndEdit'
]);

    Route::get('admin/{user_id}/edit/{course_id}', [
        'uses' => 'AdminController@journalsShow',
    ]);

    Route::get('admin/home', [
        'uses' => 'AdminController@index',
    ]);
});

`

This works like a charm. Thanks once again.

@rexdarel
Copy link

Hi, im using the make:auth and I'm new to laravel. I have added a column "type" in the users table to determine if the user is an admin or super admin or just a user. I was able to protect the components of my view files (like buttons, tables) using the "type" column but the problem is the routes of the super admin can still access by the admin... My question is, how can I use your solution on my current situation? Or do you have any idea how to protect the routes base on the column "type"?

@candrasetiadi
Copy link

Hello...
Everyhting was work for me.
But How i make the roles specified on controller? you make it on route file like this 'roles' => ['admin', 'superadmin']
because i have dynamic roles on my roles table.

please help me. thanks

@gitongacollin
Copy link

gitongacollin commented Oct 10, 2018

Hi, I'm new to Laravel
Every time I try to check if the roles are working I'm getting this error
Call to a member function hasRole() on null
I create a route to try check
Kindly help

Here is the snippet of my route
`Route::group(['middleware'=>['authen','roles'],'roles'=>['Root']],function(){
//for Root

Route::get('/createUser',function(){
	echo "This is for Root test";
});`

@miladjamali
Copy link

nice this helped me much thank you

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment