laravellaravel-authorizationlaravel-5.8laravel-authentication

Laravel: How to make sure a user goes to role-specific home view after registration and after login?


I have created a custom multi-auth system in laravel-5.8 for a college website where every user registers for a specific role: Admin, Faculty, or HOD(Head of Department).

I am making use of the controllers and views which we get after running

php artisan make:auth

Upon registering, all the users are redirecting to default home page, regardless of their roles. The 3 roles are being stored in the Users table as 0, 1, and 2 under column role. I modified the Users table which comes by default.

My login mechanism works well. Users are redirected to the home page of their role. Here is how I do it:

LoginController.php

public function login(Request $request){
if(Auth::attempt(['PID' => $request->PID, 'password' => $request->password])){

    $user = User::where('PID',$request->PID)->first();

    if($user->role == '0'){
        return redirect('home');
    }
    else{
        if($user->role == '1'){
            return redirect('hodhome');
        }
        else{
            return redirect('adminhome');
        }
    }
}
return redirect()->back();
}

This is the route used upon the POST request from login.blade.php

Route::post('/login/custom', 'auth\LoginController@login')->name('login.custom');

But every time I register a new user, it takes users to the faculty home page route, even when they're admins or HODs. Here's the register mechanism:

RegisterController.php (Just showing relevant functions below)

use RegistersUsers;
protected $redirectTo = '/home';
public function __construct()
{
    $this->middleware('guest');
}
//validator function and create function after this line

I have tried to make it work properly by doing this: Changing the variable redirectTo to a function. //an idea: replace "protected $redirectTo = '/home';" by...

protected function redirectTo(array $data){
    if($data['role']=='0'){ return redirect('home'); }
    elseif($data['role']=='1'){ return redirect('hodhome'); }
    else return redirect('adminhome');
}

But it doesn't work, because I seem to be missing something.

Another bummer is the fact that after login, users can access home pages of other roles. the middleware('auth') in my routes helps protect against accessing the URLs when not logged in, but it doesn't stop logged in users from accessing other home pages.

Here are the routes to the home pages:

Auth::routes();

//-------------------MULTI AUTH SYSTEM------------------------------------------

Route::post('/login/custom', 'auth\LoginController@login')->name('login.custom');

Route::get('/home', 'HomeController@index')->name('home');

route::get('/adminhome', function () {
    return view('adminhome');
})->middleware('auth');

route::get('/hodhome', function () {
    return view('hodhome');
})->middleware('auth');
//----------------------------------------------------------------------------

The default welcome.blade.php too redirects logged in users to faculty's home page:

@if (Route::has('login'))
        <div class="top-right links">
            @auth
                <a href="{{ url('/home') }}">Home</a>
            @else
                <a href="{{ route('login') }}">Login</a>

                @if (Route::has('register'))
                    <a href="{{ route('register') }}">Register</a>
                @endif
            @endauth
        </div>
    @endif

  1. How do I make sure users go to the right home pages upon a new registration and when logging in?
  2. How do I make sure home page of one role stays inaccessible to other roles?

EDIT 1:

After incorporating changes suggested by @N69S, This is what's happening:

That solution worked. But when an illegal access to a URL is attempted, an error has to be generated. But instead, user is being sent to the welcome page. This page has only one link in the top right corner, called "HOME". This link does not work when either admin or HOD user is logged in because it routes to '/home' as shown:

//welcome.blade.php
<body>
    <div class="flex-center position-ref full-height">
        @if (Route::has('login'))
            <div class="top-right links">
                @auth
                    <a href="{{ url('/home') }}">Home</a>
                @else
                    <a href="{{ route('login') }}">Login</a>

                    @if (Route::has('register'))
                        <a href="{{ route('register') }}">Register</a>
                    @endif
                @endauth
            </div>
        @endif

        <div class="content">
            <div class="title m-b-md text-center">
                COLLEGE ADMINISTRATION <br> SYSTEM
            </div>
        </div>
    </div>
</body>

How do I change this view file to send logged in user to his role's HOME?


Solution

  • One complete and correct solution would be to separate the entities (HOD, Admin, User) and configure the auth for each one (auth:hod, auth:admin, auth)

    Another solution would be to make 3 separate middleware and group your routes with one of them accordingly.

    btw, redirectTo() method does not take parameters. From Illuminate\Foundation\Auth\RedirectsUsers trait

    /**
     * Get the post register / login redirect path.
     *
     * @return string
     */
    public function redirectPath()
    {
        if (method_exists($this, 'redirectTo')) {
            return $this->redirectTo();
        }
    
        return property_exists($this, 'redirectTo') ? $this->redirectTo : '/home';
    }
    

    ---------------Edit

    For the 3 middleware solution, you can use the command php artisan make:middleware Admin, this will create the Class file app/Http/ Middleware/Admin.php.

    in the handle method, you can do something like

    public function handle($request, Closure $next)
    {
        if(auth()->user() && auth()->user()->role == 2){
            return $next($request);
        }
        return redirect(‘login’)->with(‘error’,’You have not admin access’);
    }
    

    and do the same for the HOD

    To use it like authin the routes, add the middleware in the kernel App\Http\Kernel.php in $routeMiddleware

    protected $routeMiddleware = [
        //....,
        //....,
        'admin' => \App\Http\Middleware\Admin::class,
    ];