4

I'm using entrust for managing role based permissions in Laravel 5.3, and naturally using manual/custom logins for different user types. Is it possible for Auth::attempt() to handle foreign table relationships? Basically, I want to do something like this:

if(Auth::attempt(['email' => $request->email, 'password' => $request->password, hasRole('teacher') => true])) {
        return redirect()->intended('teacher/dashboard');
}

But I keep getting the error that hasRole() is an undefined function. I have included use Zizaco\Entrust\Traits\EntrustUserTrait; and use EntrustUserTrait;, which I thought would provide me with access to the function, but apparently not.

I appreciate the fact that hasRole() is a method for user objects, and at the time of checking I don't have a user object but I can't do a role check after attempt has succeeded because then the user has already been logged in, and if the role was wrong I would need to log them out as their credentials are correct, but not for the role; which seems slow and not pragmatic.

How should I go about handling this? Is there an alternative to Auth::attempt that I can use that will not log in the user, but check the user exists with specified input, and then run the role check, and then use another function to start an authenticated session?

If useful my LoginController is here:

<?php

namespace App\Http\Controllers\Teacher;

use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use Illuminate\Http\Request;
use Validator;
use Zizaco\Entrust\Traits\EntrustUserTrait;

class LoginController extends Controller {
    use EntrustUserTrait;

    public function showLoginForm() {
        return view('teacher/login');
    }

    public function authenticate(Request $request) {
        Validator::make($request->all(), [
            'email' => 'required|email',
            'password' => 'required',
        ])->validate();

        if(Auth::attempt(['email' => $request->email, 'password' => $request->password, hasRole('teacher') => true])) {
            return redirect()->intended('teacher/dashboard');
        }

        return redirect('admin/login')->with('invalid', 'Invalid username or password');
    }
}

Any help or direction would be much appreciated. Thanks.

A. Appleby
  • 469
  • 1
  • 10
  • 23

3 Answers3

1

what you can do is:

 if(Auth::attempt(['email' => $request->email, 'password' => $request->password)) {
     if($user = Auth::user()->hasRole('teacher')) {
         return redirect()->intended('teacher/dashboard');
     } else {
         return redirect()->intended('teacher/dashboard');
     }
 }
Purvesh
  • 628
  • 7
  • 12
  • 2
    This will log someone in who isn't necessarily a teacher, but can be authenticated at a different login portal – A. Appleby Nov 06 '16 at 11:49
1

so this is what I did on login check role

$user = User::whereEmail($request->email)->first();

// I added this is because the customer 
// are not suppose to login from here
if(!$user || $user->hasRole(['customer'])){
    return $this->sendFailedLoginResponse($request);
}

if ($this->guard()->attempt($credentials, $request->has('remember'))) {
    return $this->sendLoginResponse($request);
}

then if you wanna to change the route base on user role you can try to replace the redirectPath method by simply

public function redirectPath()
{
    $user = Auth::user();
    if($user->hasRole(['admin', 'system_admin']))
        return '/backend';
    elseif($user->hasRole(['teacher']))
        return '/teacher';
}
Jason Seah
  • 1,514
  • 3
  • 13
  • 19
  • This is a good solution, particularly if I end up unifying the login controller. However, for simplicity and keeping inline with provided functions to maintain the context of the question I have created another solution and marked as answer. – A. Appleby Nov 06 '16 at 11:53
1

I ended up manually doing the authentication check and using Auth::login($user) to create the authenticated session. This way the user was only logged in provided they met the role requirements for the specific login portal and controller.

public function authenticate(Request $request) {
    Validator::make($request->all(), [
        'email' => 'required|email',
        'password' => 'required',
    ])->validate();

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

    if($user) {
        if(Hash::check($request->password, $user->password) && $user->hasRole('teacher')) {
            Auth::login($user);
            return redirect()->intended('teacher/dashboard');
        }
    }

    return redirect('teacher/login')->with('invalid', 'Invalid username or password');
}
A. Appleby
  • 469
  • 1
  • 10
  • 23