I want to save the datetime of last interaction of a user with the application inside the user table.
I'm using Laravel 8.
I added a column in users table (last_interaction):
Schema::create('users', function(Blueprint $table)
{
$table->engine = 'InnoDB';
$table->integer('id', true);
$table->string('firstname');
$table->string('lastname');
$table->string('username', 192);
$table->string('email', 192);
$table->string('password');
$table->string('avatar')->nullable();
$table->string('phone', 192);
$table->integer('role_id');
$table->boolean('statut')->default(1);
$table->datetime('last_interaction'); //The column where to save the datetime of last interaction
$table->timestamps(6);
$table->softDeletes();
});
Is it possible to update the users table with each request done! or should i do it on login only (for Optimisations) ?
You can make new middleware with this command php artisan make:middleware LastInteraction
App\Http\Middleware\LastInteraction.php:
public function handle(Request $request, Closure $next)
{
if (Auth::check()) {
$user = Auth::user();
$user->last_interacted = Carbon::now();
$user->save();
}
return $next($request);
}
This will set a field of last_interacted to the current time given this field exists in your migration. If it doesn't exist create one.
App\Http\Kernel.php
protected $middleware = [
(...)
\App\Http\Middleware\LastInteraction::class,
];
This will register the middleware to be applied globally to each route.
I am beginner in Laravel and php.
I use in my project Laravel 6.
I have this migrations:
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->char('enable', 1)->default(0);
$table->rememberToken();
$table->timestamps();
});
How to change Laravel's default login so that it allows the login of a user who has enable = 1 (enable = 0 - we do not allow, similar to those with an incorrect password)
According to Laravel document on Manually Authenticating Users, you can use this code to authenticate users with enabled field set to true only.
$email = $request->input('email');
$password = $request->input('password');
if (Auth::attempt(['email' => $email, 'password' => $password, 'enabled' => 1])) {
// The user is active, not suspended, and exists.
}
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:
I would like to be able to log in only if the user has enable = 1
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?
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.
For that you have to make custom login controller and handle this situation.
I am mentioning this in detail check me below given steps.
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');
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');
}
}
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.
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.
I have a table like this:
Schema::create('partners', function (Blueprint $table) {
$table->increments('id');
$table->binary('image');
$table->string('name');
$table->string('link');
$table->timestamps();
});
Then, after validation, I need to add data from forms, defined as this:
{{Form::file('image')}} I tried this way:
public function newPartner(Request $request) {
$validator = Validator::make($request->all(), [
'name' => 'required',
'link' => 'required'
]);
if ($validator->fails()) {
return redirect('partners/create')->withErrors($validator);
}
Partner::create($request->all());
return redirect('/');
}
But it doesn't fill the binary field with the uploaded image.
How can I achieve this?
Thank you for helping me.
I'm making my first big project using Laravel 5.1 and I'd like to add an extra check during user login to see if the user has activated their account.
This is the schema of the users table
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('username');
$table->string('email')->unique();
$table->string('password', 60);
$table->rememberToken();
$table->boolean('is_admin')->default(true);
$table->boolean('is_active')->default(true);
$table->timestamps();
});
I've tried adding a $credentials['is_active'] = true; after $credentials = $this->getCredentials($request); in AutheticatesUser#postLogin and it works but I want to have a custom error if the user's account isn't active because the default one(These credentials do not match our records.) is not that intuitive for the user.
Any suggestions in achieving that?
Thank you!
You can override the postLogin method in your AuthController and check whether the user is active or not like this.
class AuthController extends Controller
{
public function postLogin(Request $request){
$this->validate($request, [
'email' => 'required|email', 'password' => 'required',
]);
$credentials = $this->getCredentials($request);
// This section is the only change
if (Auth::validate($credentials)) {
$user = Auth::getLastAttempted();
if ($user->is_active) {
Auth::login($user, $request->has('remember'));
return redirect()->intended($this->redirectPath());
} else {
return redirect($this->loginPath()) // Change this to redirect elsewhee
->withInput($request->only('email', 'remember'))
->withErrors([
'active' => 'Please active your account'
]);
}
}
return redirect($this->loginPath())
->withInput($request->only('email', 'remember'))
->withErrors([
'email' => $this->getFailedLoginMessage(),
]);
}
}
You can check following way
if(Auth::attempt(['email'=>$email,'password'=>$password,'is_admin'=>1]))
{
return redirect()->intended('admin/dashboard');
}