1

I have this migrations:

Schema::create('users', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->bigInteger('company_id')->unsigned();
            $table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
            $table->boolean('enable')->default(0);
            $table->string('name', 120)->nullable();
            $table->string('surname', 120)->nullable();
            $table->string('email', 120)->unique();
            $table->timestamp('email_verified_at')->nullable();
            $table->string('password');
            $table->bigInteger('counter')->default(0);
            $table->string('url_address', 160);
            $table->string('ip', 25)->nullable();
            $table->boolean('isCompany')->default(0);
            $table->boolean('isMailing')->default(0);
            $table->text('content')->nullable();
            $table->string('nip1', 12)->nullable();
            $table->string('business1', 120)->nullable();
            $table->string('phone1', 60)->nullable();
            $table->string('street1', 150)->nullable();
            $table->string('number1', 8)->nullable();
            $table->string('postal_code1', 12)->nullable();
            $table->string('city1', 100)->nullable();
            $table->bigInteger('country_id1')->default(0);
            $table->bigInteger('provincial_id1')->default(0);
            $table->string('nip2', 12)->nullable();
            $table->string('business2', 120)->nullable();
            $table->string('phone2', 60)->nullable();
            $table->string('street2', 150)->nullable();
            $table->string('number2', 8)->nullable();
            $table->string('postal_code2', 12)->nullable();
            $table->string('city2', 100)->nullable();
            $table->bigInteger('country_id2')->default(0);
            $table->bigInteger('provincial_id2')->default(0);
            $table->string('nip3', 12)->nullable();
            $table->string('business3', 120)->nullable();
            $table->string('phone3', 60)->nullable();
            $table->string('street3', 150)->nullable();
            $table->string('number3', 8)->nullable();
            $table->string('postal_code3', 12)->nullable();
            $table->string('city3', 100)->nullable();
            $table->bigInteger('country_id3')->default(0);
            $table->bigInteger('provincial_id3')->default(0);
            $table->decimal('cash', 9, 2)->default(0);
            $table->decimal('lng', 10, 8)->default(0);
            $table->decimal('lat', 10, 8)->default(0);
            $table->boolean('enable_map')->default(0);
            $table->rememberToken();
            $table->timestamps();
            $table->engine = "InnoDB";
        });

I have 2 questions in connection with logging in to Laravel:

  1. I would like to be able to log in only if the user has enable = 1

  2. The parameter enable is the default value of 0. After clicking the activation link in the mail I would like to change enable = 0 on enable = 1

How can I do this?

3
  • Are you using custom authentication or built in? Commented May 15, 2019 at 18:46
  • yes, I use original Laravel auth (build in) Commented May 15, 2019 at 19:03
  • I have posted answer check that Commented May 16, 2019 at 4:56

3 Answers 3

3

When calling the attempt() method you can pass an array of credentials that can be used.

You can do as mentioned previously and create your own controllers, but if you're using the auth scaffolding that comes with laravel (This includes auth:make and the classes in app/Http/Controllers/Auth) you can simply edit the file:

app/Http/Controllers/Auth/LoginController.php

In here you want to override the credentials method by adding the following:

protected function credentials(Request $request)
{
    return array_merge($request->only($this->username(), 'password'), ['active' => 1]);
}

This means that when the rest of the code kicks in automatically, it'll make the credentails array look something like:

array(
    'username' => 'theusername',
    'password' => 'thepassword',
    'active'   => 1
)

It was mentioned previously that you should cast your attribute to a boolean, but this is not true. Laravel migrations create a tiny int column instead of a boolean, and the casting only works when dealing with models. Since this array is used to generate where conditions on the DB query, casting won't work as the value in the DB will be 1 not true.

Sign up to request clarification or add additional context in comments.

7 Comments

IMO this is the more standard way of doing what was asked in OP. One query though, what if I want to show a custom error message for in-active users?
I don't use the scaffolding myself because I often do things like you're suggesting, which isn't easily achiavable. Instead, I use the validate method to validate creditals, then get the user object myself, and perform a few checks. Active and validated for example. I then return a custom error or login passing the object.
I was also performing the extra check after fetching the user object from db, but that was a extra query fired to db and that's why I liked your method more because it omit that extra query. But turns out we can't send custom messages then :(
You can login by passing the user object, that won't generate an extra query. You'd just be replacing the prebuilt query with your own.
Yes I can, but again that will come with some extra work like set user session manually.
|
-1

For that you have to make custom login controller and handle this situation. I am mentioning this in detail check me below given steps.

  1. Update your routes/web.php

    Route::get('/', function () {
       return redirect(route('login'));
    });
    Route::get('/home', 'HomeController@index')->name('home');
    
    Route::post('/authenticate', 'LoginController@authenticate')->name('authenticate');
    Route::get('/logout', '\App\Http\Controllers\Auth\LoginController@logout');
    
    1. Create app/Http/Controllers/LoginController.php

and add this method into this controller

 /**
     * Handle an authentication attempt.
     *
     * @param  \Illuminate\Http\Request $request
     *
     * @return Response
     */
    public function authenticate(Request $request)
    {
        //ADD VALIDATION CODE HERE

        $credentials = $request->only('email', 'password');

        if (Auth::attempt($credentials)) {
            // Authentication passed...
            return redirect()->intended('dashboard');
        }
    }
  1. So I have mentioned in above method "//ADD VALIDATION CODE HERE " at that place you have to validate request and make query to check that user is enabled or not.

I hope this will work for you.

1 Comment

This is not the way to go at all. This is a lot of code and extra effort to do something that you can do be default. Don't overcomplicate things by overriding classes and recreating the functionality when you can simply update an array.
-1

You will have to override the default controllers and routes.

First remove the auth routes as you are going to create them yourself.

Then define your controllers.

For the login part you can create your own Login Controller and in there make your own login attempt which is what Laravel uses. There you can add your desired attribute validations like this.

public function login(Request $request)
{
    //Validate your form data here
    $request->validate([
        'email' => ['required', 'string'],
        'password' => ['required', 'string'],
    ]);

    //Create your own login attempt here
    $login_atempt = Auth::attempt([
        'email' => $request->email,
        'password' => $request->password,
        'enabled' => true //or 1 , I recommend you to cast your attribute to boolean in your model
    ], $request->filled('remember'));

    if ($login_atempt) {
        $request->session()->regenerate();

        return redirect()->route('home'); //Your home screen route after successful login
    }

    //using custom validation message as Laravel does
    throw ValidationException::withMessages([
        'email' => [trans('auth.failed')],
    ]);
}

also add a simple method to call the login form.

public function showLoginForm()
{
    return view('auth.login');
}

Then your routes (I named my controller, UserLoginController)

Route::group(['middleware' => 'guest'], function () {
    Route::get('/login', 'UserLoginController@showLoginForm')->name('login.index');
    Route::post('/login', 'UserLoginController@login')->name('login');
});

For the second question Laravel documentation states

After an email address is verified, the user will automatically be redirected to /home. You can customize the post verification redirect location by defining a redirectTo method or property on the VerificationController:

protected $redirectTo = '/dashboard';

So you can make your own controller that handles that enable attribute change and redirection.

To finish, make sure you manually add the auth routes you need.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.