Reputation: 25691
I want my users validate their email address before the can access to website.
I think there is no a prebuilt system, so I added an enabled
boolean field, default false
, to my users table.
How can I handle this?
I'm looking at source code here: https://github.com/laravel/framework/blob/5.5/src/Illuminate/Foundation/Auth/AuthenticatesUsers.php#L74-L79
/**
* Attempt to log the user into the application.
*
* @param \Illuminate\Http\Request $request
* @return bool
*/
protected function attemptLogin(Request $request)
{
return $this->guard()->attempt(
$this->credentials($request), $request->filled('remember')
);
}
/**
* Get the needed authorization credentials from the request.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
protected function credentials(Request $request)
{
return $request->only($this->username(), 'password');
}
I'd like to override the 'attempt' method of guard ... but I've not idea of what is a 'guard' (I'll for for documentation, I promise) and where / how to override or extend or implement to check the enabled field
EDIT
I found this documentation: https://laravel.com/docs/5.5/authentication#authenticating-users
I REALLY cannot understand where the call to this method come from... and how to populate the $email
and $password
vars...... Anyway I tried this, but I obtained NOTHING. No error, but user logged even if it has enabled set to false. Note that my 'username' field is litterally 'username'. I'm not using email field.
public function authenticate()
{
if (Auth::attempt(['username' => $username, 'password' => $password, 'enabled' => true]))
{
// Authentication passed...
return redirect($this->redirectTo());
}
}
public function username()
{
return 'username';
}
Upvotes: 0
Views: 2387
Reputation: 25691
I found a well- working solution
In my LoginController.php
I override two function from the trait AuthenticatesUsers;
.
Note that the 2nd override is just to override the message to the user.
/**
* Attempt to log the user into the application.
* NOTE: this override DO NOT uses at all the trait version
* See: https://laravel.com/docs/5.5/authentication#authenticating-users
*
* @param \Illuminate\Http\Request $request
* @return bool
*/
protected function attemptLogin(Request $request)
{
return Auth::attempt(
$this->credentials($request) + ["enabled" => true],
$request->filled('remember')
);
}
/**
* Get the failed login response instance.
* NOTE: this override DO NOT uses at all the trait version
*
* @param \Illuminate\Http\Request $request
* @return \Symfony\Component\HttpFoundation\Response
*
* @throws ValidationException
*/
protected function sendFailedLoginResponse(Request $request)
{
throw ValidationException::withMessages([
$this->username() => [trans('auth.failed_or_account_not_activated')],
]);
}
I add some explanations.
attemptLogin
Default implementation of the framework is
return $this->guard()->attempt(
$this->credentials($request), $request->filled('remember')
);
attempt
accepts an array as first argument to be used for credentials, and a boolean as second argument, with the meaning of "remember user login'
The credentials
function is implemented as
protected function credentials(Request $request)
{
return $request->only($this->username(), 'password');
}
In my implementation, instead of passing username and password I pass
$this->credentials($request) + ["enabled" => true],
so I am passing 3 fields instead of only one; I pass
array [ 'username', 'password', 'enabled' ]
Internally the framework will do a lookup into db for a user with given username, password and enabled field values.
sendFailedLoginResponse
This override is only for showing a more precise error message to the user. Because user in this case can have right username and password, but he/she could be not enabled.
So I don't want a probably misleading error like "wrong user credentials', but a more contextualized "wrong user credentials or account not activated".
Default sendFailedLoginResponse
implementation is
throw ValidationException::withMessages([
$this->username() => [trans('auth.failed')],
]);
I simply asked Laravel to send a different string
throw ValidationException::withMessages([
$this->username() => [trans('auth.failed_or_account_not_activated')],
]);
The strings to be translated must blaced into resources/lang/<lang_code>/auth.php
I added a string translation near the default
'failed' => 'Le credenziali inserite non corrispondono a nessun utente',
I added
'failed_or_account_not_activated' => "Le credenziali inserite non corrispondono a nessun utente oppure l'account non è stato ancora attivato",
Upvotes: 4
Reputation: 1848
I want my users validate their email address before the can access to website.
Auth::attempt()
of laravel to login the user using the email
. For more information, visit this link.Note: If you also want to pass other field, you can do it like so:
Auth::attempt(['email' => $request->input('email'), 'enabled' => 1]);
Upvotes: 1