4

This is pretty standard login function and validation that works nicely. But I also want to check that the user is active. I have set up a column in my users table with 'active' set to either 0 or 1.

public function post_login() 
{
    $input = Input::all();

    $rules = array(
        'email' => 'required|email',
        'password' => 'required',
    );  

    $validation = Validator::make($input, $rules);

    if ($validation->fails())
    {
        return Redirect::to_route('login_user')
            ->with_errors($validation->errors)->with_input();
    }

    $credentials = array(
        'username' => $input['email'],
        'password' => $input['password'],
    );

    if (Auth::attempt($credentials)) 
    {
        // Set remember me cookie if the user checks the box
        $remember = Input::get('remember');
        if ( !empty($remember) )
        {
            Auth::login(Auth::user()->id, true);
        }

        return Redirect::home();

    } else {
        return Redirect::to_route('login_user')
            ->with('login_errors', true);
    }
}

I've tried something like this already:

$is_active = Auth::user()->active;

if (!$is_active == 1)
{
    echo "Account not activated";
}

But this can only be used within the 'auth attempt' if statement and at that point the users credentials(email and pass) are already validated. So even if the users account if not active at this point they are already logged in.

I need a way to return validation to let them know they still need to activate their account and check if their account is set at the same time their email and pass are being checked.

Stephan-v
  • 19,255
  • 31
  • 115
  • 201

5 Answers5

8

Filters are the way to go. It's easy and clean to solve this problem, see my example below.

Route::filter('auth', function()
{
    if (Auth::guest())
{
    if (Request::ajax())
    {
        return Response::make('Unauthorized', 401);
    }
    else
    {
        return Redirect::guest('login');
    }
}
else
{
    // If the user is not active any more, immidiately log out.
    if(Auth::check() && !Auth::user()->active)
    {
        Auth::logout();

        return Redirect::to('/');
    }
}
});
blinkiebill
  • 81
  • 1
  • 1
4

Can't you use something like this:

if (Auth::once($credentials))
{
    if(!Auth::user()->active) {
        Auth::logout();

        echo "Account not activated";
    }
}
Antonio Carlos Ribeiro
  • 86,191
  • 22
  • 213
  • 204
3

Just make the active field one of the confirmations. You can do this:

$credentials = array(
        'username' => $input['email'],
        'password' => $input['password'],
        'active' => 1
    );

    if (Auth::attempt($credentials)) 
    {
        // User is active and password was correct
    }

If you want to specifically tell the user they are not active - you can follow it up with this:

    if (Auth::validate(['username' => $input['email'], 'password' => $input['password'], 'active' => 0]))
    {
        return echo ('you are not active');
    }
Laurence
  • 58,936
  • 21
  • 171
  • 212
2

A better solution might be to create an Auth driver that extends the Eloquent Auth driver already in use and then override the attempt method.

Then change your auth config to use your driver.

Something like:

<?php

class Myauth extends Laravel\Auth\Drivers\Eloquent {

    /**
     * Attempt to log a user into the application.
     *
     * @param  array $arguments
     * @return void
     */
    public function attempt($arguments = array())
    {
        $user = $this->model()->where(function($query) use($arguments)
        {
            $username = Config::get('auth.username');

            $query->where($username, '=', $arguments['username']);

            foreach(array_except($arguments, array('username', 'password', 'remember')) as $column => $val)
            {
                $query->where($column, '=', $val);
            }
        })->first();

        // If the credentials match what is in the database we will just
        // log the user into the application and remember them if asked.
        $password = $arguments['password'];

        $password_field = Config::get('auth.password', 'password');

        if ( ! is_null($user) and Hash::check($password, $user->{$password_field}))
        {
            if ($user->active){
                return $this->login($user->get_key(), array_get($arguments, 'remember'));
            } else {
                Session::flash('authentication', array('message' => 'You must activate your account before you can log in'));
            }
        }

        return false;
    }
}
?>

In your login screen, check for Session::get('authentication') and handle accordingly.

Alternatively, allow them to log in but don't let them access any pages other than one that offers a link to resend the activation email.

PottyBert
  • 1,902
  • 1
  • 13
  • 14
0

This is what I do:

if (\Auth::attempt(['EmailWork' => $credentials['EmailWork'], 'password' => $credentials['Password']], $request->has('remember'))) {
    if (\Auth::once(['EmailWork' => $credentials['EmailWork'], 'password' => $credentials['Password']])) {
        if (!\Auth::user()->FlagActive == 'Active') {
            \Auth::logout();
            return redirect($this->loginPath())
                ->withInput($request->only('EmailWork', 'RememberToken'))
                ->withErrors([
                    'Active' => 'You are not activated!',
                ]);
        }
    }

    return redirect('/');
}

return redirect($this->loginPath())
    ->withInput($request->only('EmailWork', 'RememberToken'))
    ->withErrors([
        'EmailWork' => $this->getFailedLoginMessage(),
    ]);
Nisal Gunawardana
  • 1,345
  • 16
  • 20