Search code examples
phplaravellaravel-5laravel-5.3

Laravel Three State Login Attempt


As default Laravel Login attempt method returns bool but I want to modify it and getting another result if user exists but user's status is passive. I do not want to change any code in laravel vendor directory. I can write my own login method in LoginController like AuthenticatesUsers::login() easily but the problem is SessionGuard::attempt() has own lifecycle, it is not a trait that LoginController uses it.

Following is original version of SessionGuard::attempt() method.

public function attempt(array $credentials = [], $remember = false, $login = false)
{
    $this->fireAttemptEvent($credentials, $remember, $login);

    $this->lastAttempted = $user = $this->provider->retrieveByCredentials($credentials);

    // If an implementation of UserInterface was returned, we'll ask the provider
    // to validate the user against the given credentials, and if they are in
    // fact valid we'll log the users into the application and return true.
    if ($this->hasValidCredentials($user, $credentials)) {

        if ($login) {
            $this->login($user, $remember);
        }

        return true;
    }

    // If the authentication attempt fails we will fire an event so that the user
    // may be notified of any suspicious attempts to access their account from
    // an unrecognized user. A developer may listen to this event as needed.
    if ($login) {
        $this->fireFailedEvent($user, $credentials);
    }

    return false;
}

Note:

$credentials = [
            'email' => $request->input('email'),
            'password' => $request->input('password'),
            'status_id' => 1
           ];

But I want to remove status_id field and I want to show message to users if user's status_id is not 1.

Basically I just want to override SessionGuard::attempt() method, something like this.

public function attempt(array $credentials = [], $remember = false, $login = false)
{
    $this->fireAttemptEvent($credentials, $remember, $login);

    $this->lastAttempted = $user = $this->provider->retrieveByCredentials($credentials);

    // If an implementation of UserInterface was returned, we'll ask the provider
    // to validate the user against the given credentials, and if they are in
    // fact valid we'll log the users into the application and return true.
    if ($this->hasValidCredentials($user, $credentials)) {
        //User exists but user's status_id is not 1
        if($user->status_id != 1)
            return 2; // 2 for passive accounts
        if ($login) {
            $this->login($user, $remember);
        }

        return 1; //for active accounts
    }

    // If the authentication attempt fails we will fire an event so that the user
    // may be notified of any suspicious attempts to access their account from
    // an unrecognized user. A developer may listen to this event as needed.
    if ($login) {
        $this->fireFailedEvent($user, $credentials);
    }

    return 0; // for non exists acounts
}

How can I achive this?


Solution

  • You can do it inside your login function of your controller (normally the LoginController)

    You first get the user with a unique email. Then you check if the account has the variable. If yes you can try to login the user, if not you can throw an error.

    class LoginController extends Controller
    {
    
        use AuthenticatesUsers;
    
            public function login(Request $request) {
            $this->validateLogin($request);
    
            // If the class is using the ThrottlesLogins trait, we can automatically throttle
            // the login attempts for this application. We'll key this by the username and
            // the IP address of the client making these requests into this application.
            if ($this->hasTooManyLoginAttempts($request)) {
                $this->fireLockoutEvent($request);
    
                return $this->sendLockoutResponse($request);
            }
            $user = App\User::where('email', $request->get('email'))->first();
    
            if ($user && $user->status_id == 1 && $this->attemptLogin($request)) {
                return $this->sendLoginResponse($request);
            }
    
            // If the login attempt was unsuccessful we will increment the number of attempts
            // to login and redirect the user back to the login form. Of course, when this
            // user surpasses their maximum number of attempts they will get locked out.
            $this->incrementLoginAttempts($request);
    
            return $this->sendFailedLoginResponse($request);
        }
    }