Ginz77
Ginz77

Reputation: 73

Laravel 8: Middleware Roles

When someone signs up they can register as a profile or business in a drop select. From my code below, how do I create middleware so the profile user can't access the business dashboard and the business user can't access the profile dashboard? How do I protect those pages?

2014_10_12_000000_create_users_table.php

Schema::create('users', function (Blueprint $table) {
    $table->id();
    $table->string('account_type');
    $table->string('first_name');
    $table->string('last_name');
    $table->string('username')->unique();
    $table->string('email')->unique();
    $table->timestamp('email_verified_at')->nullable();
    $table->string('phone');
    $table->string('address', 50);
    $table->string('city', 25);
    $table->char('state', 2);
    $table->char('zip', 10);
    $table->string('password');
    $table->rememberToken();
    $table->timestamps();
});

RegisterController.php

<?php

namespace App\Http\Controllers\Auth;

use App\Models\User;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;

class RegisterController extends Controller
{
    public function index()
    {
        return view('auth.register');
    }

    public function store(Request $request)
    {
        $this->validate($request, [
            'account_type' => 'required|not_in:0',
            'first_name' => 'required|max:255',
            'last_name' => 'required|max:255',
            'username' => 'required|max:15|unique:users',
            'email' => 'required|email|unique:users',
            'phone' => 'required|max:255|digits:10',
            'address' => 'required|max:255',
            'city' => 'required|max:20',
            'state' => 'required|not_in:0',
            'zip' => 'required|regex:/\b\d{5}\b/',
            'password' => 'required|string|confirmed|min:8',
        ]);

        User::create([
            'account_type' => $request->account_type,
            'first_name' => $request->first_name,
            'last_name' => $request->last_name,
            'username' => $request->username,
            'email' => $request->email,
            'phone' => $request->phone,
            'address' => $request->address,
            'city' => $request->city,
            'state' => $request->state,
            'zip' => $request->zip,
            'password' => Hash::make($request->password),
        ]);

        Auth::attempt([
            'email' => $request->email,
            'password' => $request->password,
        ]);

        // Redirect to dashboards based on registers account type
        if(Auth::user()->account_type == 'profile'){
            return redirect()->route('dashboard_profile');
        } else {
            return redirect()->route('dashboard_business');
        }
    }
}

BusinessDashboardController.php

class BusinessDashboardController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth');
    }
    
    public function index()
    {        
        return view('auth.dashboard_business');
    }
}

ProfileDashboardController.php

class ProfileDashboardController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth');
    }

    public function index()
    {
        return view('auth.dashboard_profile');
    }
}

I want to learn to do this without using packages.

Upvotes: 0

Views: 4485

Answers (4)

ShapCyber
ShapCyber

Reputation: 3652

How to create your own middleware for multi User Role in Laravel

Let assumed your roles array could be ["admin","student","staff"];

Create a middleware role checking for the role "admin". Repeat steps 1-4 for each role.

I found this much easier for myself, others may have their own approaches

Step 1 Run artisan command

php artisan make:middleware isAdmin

Step 2

App/Http/Middlewere/isAdmin.php

    namespace App\Http\Middleware;
    
    use Closure;
    use Illuminate\Http\Request;
    use Illuminate\Support\Facades\Auth;
    class isAdmin
    {
         public function handle(Request $request, Closure $next,$is_admin)
        {
            
            $role=Auth::user()->role;
            //Get the role list
            $role_array=explode(",",$role); 
            if (in_array($is_admin, $role_array)) {
            return $next($request);
          }        
           //if not allowed redirect to home page with message
     $message="Unauthorized action.";
//return response($message, 401);//if you have friendly 401 page 


//otherwise I think is a best to return to home page                
                $request->session()->flash('error', $message);
                return redirect()->route('home');
            }
        }

Step 3

App/Http/Kernel.php

protected $routeMiddleware = [
'isAdmin' => \App\Http\Middleware\isAdmin::class,
];

Step 4

Now in your route controller add this line to only allow the user that has an admin role

public function __construct()
    {
         //ONLY ADMIN CAN ACCESS THIS ROUTE
        $this->middleware('isAdmin:admin'); 
        //$this->middleware('isStudent:student');        
        //$this->middleware('isStaff:staff'); 
}

Upvotes: 0

Peter Amo
Peter Amo

Reputation: 201

1- run :

php artisan make:middleware AccountType

2- Add it to the routeMiddleware array in your kernel file by opening app/Http/Kernel.php:

'accType' => \App\Http\Middleware\AccountType::class,

3- Edit AccountType file:

public function handle($request, Closure $next)
{
 // If user account type is profile allow to next or else block the request
     if (Auth::user() &&  Auth::user()->account_type == 'profile') {
            return $next($request);
     }else{
      abort(403, 'Unauthorized action.'); 
     }        
}

4- Apply the middleware to your route:

Route::get('/profile', ['middleware' => 'accType', function () {
    //
}]);

Upvotes: 1

user7747472
user7747472

Reputation: 1952

In addition to the solution given by @nagidi, you can update the middleware handle condition to check either account_type is profile or business.

public function handle($request, Closure $next, $type)
    {

     if (Auth::user() &&  Auth::user()->account_type == $type) {
            return $next($request);
     }
      abort(403, 'Unauthorized action.');
    }
Route::get('/business-profile', ['middleware' => 'accType:business', function () {
    //
}]);
Route::get('/profile', ['middleware' => 'accType:profile', function () {
    //
}]);

Upvotes: 1

behzad m salehi
behzad m salehi

Reputation: 1076

If your want to have a multi authenticate system, whit different logics, its better to implement multiple guard and define them in your desire models :

[...]
'guards' => [
    [...]
    'admin' => [
        'driver' => 'session',
        'provider' => 'admins',
    ],
    'writer' => [
        'driver' => 'session',
        'provider' => 'writers',
    ],
],
[...]

  [...]
'providers' => [
    [...]
    'admins' => [
        'driver' => 'eloquent',
        'model' => App\BusinessDashboard::class,
    ],
    'writers' => [
        'driver' => 'eloquent',
        'model' => App\ProfileDashboard::class,
    ],
],
[...]

you can find a complete guide article in bellow code :
enter link description here

Upvotes: 0

Related Questions