From f8206b58408ace61f537415054877aad560ade7d Mon Sep 17 00:00:00 2001 From: Giuseppe Naponiello Date: Wed, 24 Jun 2026 17:02:11 +0200 Subject: [PATCH] =?UTF-8?q?user=20disabled=5Fat=20field=20added=C3=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/Actions/Fortify/AuthenticateUser.php | 32 +++++++++++ backend/app/Models/User.php | 1 + .../app/Providers/FortifyServiceProvider.php | 2 + ..._120000_add_disabled_at_to_users_table.php | 32 +++++++++++ backend/tests/Feature/Auth/LoginTest.php | 53 +++++++++++++++++++ 5 files changed, 120 insertions(+) create mode 100644 backend/app/Actions/Fortify/AuthenticateUser.php create mode 100644 backend/database/migrations/2026_06_24_120000_add_disabled_at_to_users_table.php create mode 100644 backend/tests/Feature/Auth/LoginTest.php diff --git a/backend/app/Actions/Fortify/AuthenticateUser.php b/backend/app/Actions/Fortify/AuthenticateUser.php new file mode 100644 index 0000000..018c6d0 --- /dev/null +++ b/backend/app/Actions/Fortify/AuthenticateUser.php @@ -0,0 +1,32 @@ +input(Fortify::username()))->first(); + + if (! $user || ! Hash::check((string) $request->input('password'), $user->password)) { + return null; + } + + return $user->disabled_at === null ? $user : null; + } +} diff --git a/backend/app/Models/User.php b/backend/app/Models/User.php index da85b91..bf08709 100644 --- a/backend/app/Models/User.php +++ b/backend/app/Models/User.php @@ -73,6 +73,7 @@ class User extends Authenticatable implements Auditable, MustVerifyEmail 'two_factor_confirmed_at' => 'datetime', 'is_system' => 'boolean', 'anonymized_at' => 'datetime', + 'disabled_at' => 'datetime', ]; } diff --git a/backend/app/Providers/FortifyServiceProvider.php b/backend/app/Providers/FortifyServiceProvider.php index e48ab1a..5ffe7df 100644 --- a/backend/app/Providers/FortifyServiceProvider.php +++ b/backend/app/Providers/FortifyServiceProvider.php @@ -2,6 +2,7 @@ namespace App\Providers; +use App\Actions\Fortify\AuthenticateUser; use App\Actions\Fortify\CreateNewUser; use App\Actions\Fortify\ResetUserPassword; use App\Actions\Fortify\UpdateUserPassword; @@ -29,6 +30,7 @@ class FortifyServiceProvider extends ServiceProvider */ public function boot(): void { + Fortify::authenticateUsing(new AuthenticateUser); Fortify::createUsersUsing(CreateNewUser::class); Fortify::updateUserProfileInformationUsing(UpdateUserProfileInformation::class); Fortify::updateUserPasswordsUsing(UpdateUserPassword::class); diff --git a/backend/database/migrations/2026_06_24_120000_add_disabled_at_to_users_table.php b/backend/database/migrations/2026_06_24_120000_add_disabled_at_to_users_table.php new file mode 100644 index 0000000..bce3fbb --- /dev/null +++ b/backend/database/migrations/2026_06_24_120000_add_disabled_at_to_users_table.php @@ -0,0 +1,32 @@ +timestamp('disabled_at')->nullable()->after('anonymized_at'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('users', function (Blueprint $table) { + $table->dropColumn('disabled_at'); + }); + } +}; diff --git a/backend/tests/Feature/Auth/LoginTest.php b/backend/tests/Feature/Auth/LoginTest.php new file mode 100644 index 0000000..05adf11 --- /dev/null +++ b/backend/tests/Feature/Auth/LoginTest.php @@ -0,0 +1,53 @@ +operationalUser(); + + $this->postJson('/api/login', [ + 'email' => $user->email, + 'password' => 'password', + ])->assertOk()->assertJsonPath('two_factor', false); + + $this->assertTrue(Auth::check()); + $this->assertSame($user->id, Auth::id()); + } + + public function test_login_fails_with_wrong_password(): void + { + $user = $this->operationalUser(); + + $this->postJson('/api/login', [ + 'email' => $user->email, + 'password' => 'wrong-password', + ])->assertUnprocessable(); + + $this->assertFalse(Auth::check()); + } + + public function test_login_fails_for_disabled_user(): void + { + $user = $this->operationalUser(['disabled_at' => now()]); + + $this->postJson('/api/login', [ + 'email' => $user->email, + 'password' => 'password', + ])->assertUnprocessable(); + + $this->assertFalse(Auth::check()); + } +}