Laravel and User Roles 04.02.2018

Bootstrapping a Laravel app with different dashboards for different user roles.

For a laravel based project that I was working on recently I needed to build a system that allowed for two types of users with a unique dashboard for each. Admin users would have access to user management, content management, etc while normal users can update profile data and create personal posts.

This was the first time I'd built this type of system in Laravel, so thought it would be a good thing to document in case I need to use it again. For the sake of completeness I'm starting this from the point of actually creating the laravel project, but with the assumption that the database has already been created.


First create the new laravel project.

composer create-project --prefer-dist laravel/laravel mysite

cd into new project directory and run the routine to create the laravel authentication framework.


cd mysite
php artisan make:auth

Next update the user table migration. I'll need to add a new column for 'role'. In this case I'm using a type string with 'user' being the default value. 

// database/migrations/some_date_create_users_table.php
// inside Schema::create
$table->string('role')->default('user');

Create a new seeder for the Users table.

php artisan make:seeder UsersTableSeeder

// update the run() method in database/seeds/UsersTableSeeder.php
DB::table('users')->insert([
    'name' => 'User Name',
    'email' => 'mail@mail.com',
    'password' => bcrypt('mypass123'),
    'role' => 'admin'
]);

// update the run() method in database/seeds/DatabaseSeeder.php
$this->call(UsersTableSeeder::class);

Next update the .env file with the database connection params. (DB_DATABASE, DB_USERNAME, and DB_PASSWORD)

Now we're ready to run our migrations and seed the database...


php artisan migrate
php artisan db:seed

...and create new middleware for Admin and User Roles


php artisan make:middleware AdminMiddleware
php artisan make:middleware UserMiddleware

In each of these middlewares I need to pull in Auth

use Illuminate\Support\Facades\Auth;

after the namespace declaration.

For the handle() function in each middleware I'm checking Auth::user()->role. If the role matches what we're checking for we continue, otherwise we're redirecting to a 'permission denied' page.


// app\Http\Middleware\AdminMiddleware.php
public function handle($request, Closure $next) 
{
    if(Auth() && Auth::user()->role == 'admin') {
        return $next($request);
    }
    return redirect('/denied'); 
}

// app\Http\Middleware\UserMiddleware.php
public function handle($request, Closure $next) 
{
    if(Auth() && Auth::user()->role == 'user') {
        return $next($request);
    }
    return redirect('/denied'); 
}

Register the new Middlewares so they can be used in route groups: 


// app/Http/Kernel.php
protected $routeMiddleware = [
    // existing middlewares listed here
    'admin' => \App\Http\Middleware\AdminMiddleware::class,
    'user' => \App\Http\Middleware\UserMiddleware::class,
];

Add new routes: 


// routes/web.php
// admin only routes
Route::group(['middleware' => ['auth', 'admin']], function() {
	Route::get('/dashboard', 'DashController@admin'); 
});

// normal user only routes
Route::group(['middleware' => ['auth', 'user']], function() {
	Route::get('/member_dashboard', 'DashController@user'); 
});

// any logged in user
Route::group(['middleware' => ['auth']], function() {

	// main dashboard route that will route to correct admin area
	// based on role
	Route::get('/dash', 'DashController@index');

	// no permission for request
	Route::get('/denied', function() {
		return 'denied'; // route to a view
	});
});

Create the new controller and add methods for the new routes: 

php artisan make:controller DashController

// app/Http/Controllers/DashController.php
// after namespace declaration
use Illuminate\Support\Facades\Auth;

// inside the class
public function index() {
    if(Auth::user()->role == 'admin') {
        return redirect('/dashboard');
    }
    return redirect('/member_dashboard'); 
}

public function admin() {
    return 'logged in as admin';
}

public function user() {
    return 'logged in as normal user';
}

Lastly set the redirect path in LoginController.php, RegisterController.php and ResetPasswordController.php:

protected $redirectTo = '/dash';