From 9647e17c468699bb36f9a0893d47526ddd87c763 Mon Sep 17 00:00:00 2001 From: Stephen Jacques Date: Mon, 11 Nov 2024 11:51:38 +0100 Subject: [PATCH 1/6] =?UTF-8?q?feat:=20(LAR-107)=20Modification=20du=20for?= =?UTF-8?q?mulaire=20de=20mot=20de=20passe=20oubli=C3=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pages/auth/forgot-password.blade.php | 41 +++++++++- tests/Feature/Auth/PasswordResetTest.php | 75 +++++++++++++++++++ 2 files changed, 112 insertions(+), 4 deletions(-) create mode 100644 tests/Feature/Auth/PasswordResetTest.php diff --git a/resources/views/livewire/pages/auth/forgot-password.blade.php b/resources/views/livewire/pages/auth/forgot-password.blade.php index 8d4112c6..efdf40c8 100644 --- a/resources/views/livewire/pages/auth/forgot-password.blade.php +++ b/resources/views/livewire/pages/auth/forgot-password.blade.php @@ -1,4 +1,37 @@ - +validate([ + 'email' => ['required', 'string', 'email'], + ]); + + $status = Password::sendResetLink( + $this->only('email') + ); + + if ($status != Password::RESET_LINK_SENT) { + $this->addError('email', __($status)); + + return; + } + + $this->reset('email'); + + session()->flash('status', __($status)); + } +}; ?> + + +
@@ -12,8 +45,7 @@
-
- @csrf +
@@ -24,6 +56,7 @@ type="text" id="email" name="email" + wire:model="email" autocomplete="email" required="true" :value="old('email')" @@ -42,4 +75,4 @@
- +
diff --git a/tests/Feature/Auth/PasswordResetTest.php b/tests/Feature/Auth/PasswordResetTest.php new file mode 100644 index 00000000..ae18ea13 --- /dev/null +++ b/tests/Feature/Auth/PasswordResetTest.php @@ -0,0 +1,75 @@ +get('/forgot-password'); + + $response + ->assertSeeVolt('pages.auth.forgot-password') + ->assertStatus(200); +}); + +test('reset password link can be requested', function (): void { + Notification::fake(); + + $user = User::factory()->create(); + + Volt::test('pages.auth.forgot-password') + ->set('email', $user->email) + ->call('sendPasswordResetLink'); + + Notification::assertSentTo($user, ResetPassword::class); +}); + +test('reset password screen can be rendered', function (): void { + Notification::fake(); + + $user = User::factory()->create(); + + Volt::test('pages.auth.forgot-password') + ->set('email', $user->email) + ->call('sendPasswordResetLink'); + + Notification::assertSentTo($user, ResetPassword::class, function ($notification) { + $response = $this->get('/reset-password/'.$notification->token); + + $response + ->assertSeeVolt('pages.auth.reset-password') + ->assertStatus(200); + + return true; + }); +}); + +test('password can be reset with valid token', function (): void { + Notification::fake(); + + $user = User::factory()->create(); + + Volt::test('pages.auth.forgot-password') + ->set('email', $user->email) + ->call('sendPasswordResetLink'); + + Notification::assertSentTo($user, ResetPassword::class, function ($notification) use ($user) { + $component = Volt::test('pages.auth.reset-password', ['token' => $notification->token]) + ->set('email', $user->email) + ->set('password', 'password') + ->set('password_confirmation', 'password'); + + $component->call('resetPassword'); + + $component + ->assertRedirect('/login') + ->assertHasNoErrors(); + + return true; + }); +}); From cd4c813a337bae5ec851ab06b98f5780f07643e0 Mon Sep 17 00:00:00 2001 From: Stephen Jacques Date: Tue, 12 Nov 2024 09:02:08 +0100 Subject: [PATCH 2/6] fix: (LAR-107) correction des conflits --- .../components/auth-session-status.blade.php | 7 ++ .../pages/auth/forgot-password.blade.php | 4 +- .../views/livewire/pages/auth/login.blade.php | 5 +- .../livewire/pages/auth/register.blade.php | 6 +- .../pages/auth/reset-password.blade.php | 101 +++++++++++++++--- .../pages/auth/verify-email.blade.php | 41 ++++++- tests/Feature/Auth/EmailVerificationTest.php | 46 ++++++++ .../Feature/Auth/PasswordConfirmationTest.php | 46 ++++++++ tests/Feature/Auth/PasswordUpdateTest.php | 41 +++++++ 9 files changed, 276 insertions(+), 21 deletions(-) create mode 100644 resources/views/components/auth-session-status.blade.php create mode 100644 tests/Feature/Auth/EmailVerificationTest.php create mode 100644 tests/Feature/Auth/PasswordConfirmationTest.php create mode 100644 tests/Feature/Auth/PasswordUpdateTest.php diff --git a/resources/views/components/auth-session-status.blade.php b/resources/views/components/auth-session-status.blade.php new file mode 100644 index 00000000..a39bc7d2 --- /dev/null +++ b/resources/views/components/auth-session-status.blade.php @@ -0,0 +1,7 @@ +@props(['status']) + +@if ($status) +
merge(['class' => 'font-medium text-sm text-green-600 dark:text-green-400']) }}> + {{ $status }} +
+@endif diff --git a/resources/views/livewire/pages/auth/forgot-password.blade.php b/resources/views/livewire/pages/auth/forgot-password.blade.php index efdf40c8..6c53ee17 100644 --- a/resources/views/livewire/pages/auth/forgot-password.blade.php +++ b/resources/views/livewire/pages/auth/forgot-password.blade.php @@ -37,6 +37,8 @@ public function sendPasswordResetLink(): void
+ +

{{ __('pages/auth.forgot.page_title') }}

@@ -44,7 +46,7 @@ public function sendPasswordResetLink(): void {{ __('pages/auth.forgot.description') }}
- +
diff --git a/resources/views/livewire/pages/auth/login.blade.php b/resources/views/livewire/pages/auth/login.blade.php index 75a3ce10..9c09977e 100644 --- a/resources/views/livewire/pages/auth/login.blade.php +++ b/resources/views/livewire/pages/auth/login.blade.php @@ -27,12 +27,15 @@ public function login(): void
- + + +

{{ __('pages/auth.login.title') }}

+
diff --git a/resources/views/livewire/pages/auth/register.blade.php b/resources/views/livewire/pages/auth/register.blade.php index 4495bb08..1a4d331a 100644 --- a/resources/views/livewire/pages/auth/register.blade.php +++ b/resources/views/livewire/pages/auth/register.blade.php @@ -25,9 +25,11 @@ public function register(): void ->mixedCase()], ]); - $validated['password'] = Hash::make($validated['password']); + $user = User::create($validated); - event(new Registered(User::create($validated))); + $user->assignRole('user'); + + event(new Registered($user)); session()->flash('status', __('pages/auth.register.email_verification_status')); } diff --git a/resources/views/livewire/pages/auth/reset-password.blade.php b/resources/views/livewire/pages/auth/reset-password.blade.php index 433d15d4..c47ad7e3 100644 --- a/resources/views/livewire/pages/auth/reset-password.blade.php +++ b/resources/views/livewire/pages/auth/reset-password.blade.php @@ -1,54 +1,125 @@ - +token = $token; + + $this->email = request()->string('email'); + } + + /** + * Reset the password for the given user. + */ + public function resetPassword(): void + { + $this->validate([ + 'token' => ['required'], + 'email' => ['required', 'string', 'email'], + 'password' => ['required', 'string', 'confirmed', PasswordRules::min(8) + ->uncompromised() + ->numbers() + ->mixedCase()], + ]); + + $status = Password::reset( + $this->only('email', 'password', 'password_confirmation', 'token'), + function ($user) { + $user->forceFill([ + 'password' => Hash::make($this->password), + 'remember_token' => Str::random(60), + ])->save(); + + event(new PasswordReset($user)); + } + ); + + if ($status != Password::PASSWORD_RESET) { + $this->addError('email', __($status)); + + return; + } + + Session::flash('status', __($status)); + + $this->redirectRoute('login', navigate: true); + } +}; ?> + +
+ + + + +

{{ __('pages/auth.reset.page_title') }}

- - @csrf - +
- - {{ __('validation.attributes.email') }} -
- - {{ __('validation.attributes.password') }} -
- - {{ __('validation.attributes.password_confirmation') }} -
@@ -63,4 +134,4 @@
- +
diff --git a/resources/views/livewire/pages/auth/verify-email.blade.php b/resources/views/livewire/pages/auth/verify-email.blade.php index 2ab84225..76d45e57 100644 --- a/resources/views/livewire/pages/auth/verify-email.blade.php +++ b/resources/views/livewire/pages/auth/verify-email.blade.php @@ -1,4 +1,41 @@ - +hasVerifiedEmail()) { + $this->redirectIntended(default: route('dashboard', absolute: false), navigate: true); + + return; + } + + Auth::user()->sendEmailVerificationNotification(); + + Session::flash('status', 'verification-link-sent'); + } + + /** + * Log the current user out of the application. + */ + public function logout(Logout $logout): void + { + $logout(); + + $this->redirect('/', navigate: true); + } +}; ?> + +

@@ -44,4 +81,4 @@ class="text-sm text-gray-500 dark:text-gray-400 underline hover:text-gray-900 fo

- +
diff --git a/tests/Feature/Auth/EmailVerificationTest.php b/tests/Feature/Auth/EmailVerificationTest.php new file mode 100644 index 00000000..f282dff0 --- /dev/null +++ b/tests/Feature/Auth/EmailVerificationTest.php @@ -0,0 +1,46 @@ +unverified()->create(); + + $response = $this->actingAs($user)->get('/verify-email'); + + $response->assertStatus(200); +}); + +test('email can be verified', function () { + $user = User::factory()->unverified()->create(); + + Event::fake(); + + $verificationUrl = URL::temporarySignedRoute( + 'verification.verify', + now()->addMinutes(60), + ['id' => $user->id, 'hash' => sha1($user->email)] + ); + + $response = $this->actingAs($user)->get($verificationUrl); + + Event::assertDispatched(Verified::class); + expect($user->fresh()->hasVerifiedEmail())->toBeTrue(); + $response->assertRedirect(route('dashboard', absolute: false).'?verified=1'); +}); + +test('email is not verified with invalid hash', function () { + $user = User::factory()->unverified()->create(); + + $verificationUrl = URL::temporarySignedRoute( + 'verification.verify', + now()->addMinutes(60), + ['id' => $user->id, 'hash' => sha1('wrong-email')] + ); + + $this->actingAs($user)->get($verificationUrl); + + expect($user->fresh()->hasVerifiedEmail())->toBeFalse(); +}); diff --git a/tests/Feature/Auth/PasswordConfirmationTest.php b/tests/Feature/Auth/PasswordConfirmationTest.php new file mode 100644 index 00000000..21c28c39 --- /dev/null +++ b/tests/Feature/Auth/PasswordConfirmationTest.php @@ -0,0 +1,46 @@ +create(); + + $response = $this->actingAs($user)->get('/confirm-password'); + + $response + ->assertSeeVolt('pages.auth.confirm-password') + ->assertStatus(200); +}); + +test('password can be confirmed', function () { + $user = User::factory()->create(); + + $this->actingAs($user); + + $component = Volt::test('pages.auth.confirm-password') + ->set('password', 'password'); + + $component->call('confirmPassword'); + + $component + ->assertRedirect('/dashboard') + ->assertHasNoErrors(); +}); + +test('password is not confirmed with invalid password', function () { + $user = User::factory()->create(); + + $this->actingAs($user); + + $component = Volt::test('pages.auth.confirm-password') + ->set('password', 'wrong-password'); + + $component->call('confirmPassword'); + + $component + ->assertNoRedirect() + ->assertHasErrors('password'); +}); diff --git a/tests/Feature/Auth/PasswordUpdateTest.php b/tests/Feature/Auth/PasswordUpdateTest.php new file mode 100644 index 00000000..33b1d4b5 --- /dev/null +++ b/tests/Feature/Auth/PasswordUpdateTest.php @@ -0,0 +1,41 @@ +create(); + + $this->actingAs($user); + + $component = Volt::test('profile.update-password-form') + ->set('current_password', 'password') + ->set('password', 'new-password') + ->set('password_confirmation', 'new-password') + ->call('updatePassword'); + + $component + ->assertHasNoErrors() + ->assertNoRedirect(); + + $this->assertTrue(Hash::check('new-password', $user->refresh()->password)); +}); + +test('correct password must be provided to update password', function () { + $user = User::factory()->create(); + + $this->actingAs($user); + + $component = Volt::test('profile.update-password-form') + ->set('current_password', 'wrong-password') + ->set('password', 'new-password') + ->set('password_confirmation', 'new-password') + ->call('updatePassword'); + + $component + ->assertHasErrors(['current_password']) + ->assertNoRedirect(); +}); From e3dfba42f901f41a55b9e680fb08c76849cbc93a Mon Sep 17 00:00:00 2001 From: Stephen Jacques Date: Mon, 11 Nov 2024 14:54:35 +0100 Subject: [PATCH 3/6] feat: (LAR-107) Mise a jour --- resources/views/livewire/pages/auth/register.blade.php | 2 +- tests/Feature/Auth/EmailVerificationTest.php | 8 +++++--- tests/Feature/Auth/PasswordConfirmationTest.php | 8 +++++--- tests/Feature/Auth/PasswordUpdateTest.php | 6 ++++-- 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/resources/views/livewire/pages/auth/register.blade.php b/resources/views/livewire/pages/auth/register.blade.php index 1a4d331a..959ed81a 100644 --- a/resources/views/livewire/pages/auth/register.blade.php +++ b/resources/views/livewire/pages/auth/register.blade.php @@ -177,4 +177,4 @@ public function register(): void -
\ No newline at end of file +
diff --git a/tests/Feature/Auth/EmailVerificationTest.php b/tests/Feature/Auth/EmailVerificationTest.php index f282dff0..ededd4dd 100644 --- a/tests/Feature/Auth/EmailVerificationTest.php +++ b/tests/Feature/Auth/EmailVerificationTest.php @@ -1,11 +1,13 @@ unverified()->create(); $response = $this->actingAs($user)->get('/verify-email'); @@ -13,7 +15,7 @@ $response->assertStatus(200); }); -test('email can be verified', function () { +test('email can be verified', function (): void { $user = User::factory()->unverified()->create(); Event::fake(); @@ -31,7 +33,7 @@ $response->assertRedirect(route('dashboard', absolute: false).'?verified=1'); }); -test('email is not verified with invalid hash', function () { +test('email is not verified with invalid hash', function (): void { $user = User::factory()->unverified()->create(); $verificationUrl = URL::temporarySignedRoute( diff --git a/tests/Feature/Auth/PasswordConfirmationTest.php b/tests/Feature/Auth/PasswordConfirmationTest.php index 21c28c39..2ca9ce48 100644 --- a/tests/Feature/Auth/PasswordConfirmationTest.php +++ b/tests/Feature/Auth/PasswordConfirmationTest.php @@ -1,11 +1,13 @@ create(); $response = $this->actingAs($user)->get('/confirm-password'); @@ -15,7 +17,7 @@ ->assertStatus(200); }); -test('password can be confirmed', function () { +test('password can be confirmed', function (): void { $user = User::factory()->create(); $this->actingAs($user); @@ -30,7 +32,7 @@ ->assertHasNoErrors(); }); -test('password is not confirmed with invalid password', function () { +test('password is not confirmed with invalid password', function (): void { $user = User::factory()->create(); $this->actingAs($user); diff --git a/tests/Feature/Auth/PasswordUpdateTest.php b/tests/Feature/Auth/PasswordUpdateTest.php index 33b1d4b5..3a0ff291 100644 --- a/tests/Feature/Auth/PasswordUpdateTest.php +++ b/tests/Feature/Auth/PasswordUpdateTest.php @@ -1,12 +1,14 @@ create(); $this->actingAs($user); @@ -24,7 +26,7 @@ $this->assertTrue(Hash::check('new-password', $user->refresh()->password)); }); -test('correct password must be provided to update password', function () { +test('correct password must be provided to update password', function (): void { $user = User::factory()->create(); $this->actingAs($user); From 583a633c717cab28cd89c28c226ae7dc5057ea92 Mon Sep 17 00:00:00 2001 From: Stephen Jacques Date: Mon, 11 Nov 2024 14:55:54 +0100 Subject: [PATCH 4/6] feat: (LAR-107) Suppression des commentaire --- resources/views/livewire/pages/auth/verify-email.blade.php | 6 ------ 1 file changed, 6 deletions(-) diff --git a/resources/views/livewire/pages/auth/verify-email.blade.php b/resources/views/livewire/pages/auth/verify-email.blade.php index 76d45e57..876e7b55 100644 --- a/resources/views/livewire/pages/auth/verify-email.blade.php +++ b/resources/views/livewire/pages/auth/verify-email.blade.php @@ -8,9 +8,6 @@ new class extends Component { - /** - * Send an email verification notification to the user. - */ public function sendVerification(): void { if (Auth::user()->hasVerifiedEmail()) { @@ -24,9 +21,6 @@ public function sendVerification(): void Session::flash('status', 'verification-link-sent'); } - /** - * Log the current user out of the application. - */ public function logout(Logout $logout): void { $logout(); From 23882cf0985671ae558dbc241ff10c0e30b786f1 Mon Sep 17 00:00:00 2001 From: Stephen Jacques Date: Mon, 11 Nov 2024 17:51:24 +0100 Subject: [PATCH 5/6] fix: (LAR-107) suppresion du fichier auth-session --- resources/views/components/auth-session-status.blade.php | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 resources/views/components/auth-session-status.blade.php diff --git a/resources/views/components/auth-session-status.blade.php b/resources/views/components/auth-session-status.blade.php deleted file mode 100644 index a39bc7d2..00000000 --- a/resources/views/components/auth-session-status.blade.php +++ /dev/null @@ -1,7 +0,0 @@ -@props(['status']) - -@if ($status) -
merge(['class' => 'font-medium text-sm text-green-600 dark:text-green-400']) }}> - {{ $status }} -
-@endif From a8cd3094b81ff54a3cca86c2a1f033e2aea5e36a Mon Sep 17 00:00:00 2001 From: Stephen Jacques Date: Tue, 12 Nov 2024 08:29:35 +0100 Subject: [PATCH 6/6] fix: (LAR-107) correction des espaces --- .../views/livewire/pages/auth/forgot-password.blade.php | 8 +++----- resources/views/livewire/pages/auth/login.blade.php | 6 +++--- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/resources/views/livewire/pages/auth/forgot-password.blade.php b/resources/views/livewire/pages/auth/forgot-password.blade.php index 6c53ee17..03962031 100644 --- a/resources/views/livewire/pages/auth/forgot-password.blade.php +++ b/resources/views/livewire/pages/auth/forgot-password.blade.php @@ -30,14 +30,13 @@ public function sendPasswordResetLink(): void } }; ?> -
-
- +
+ - +

{{ __('pages/auth.forgot.page_title') }} @@ -48,7 +47,6 @@ public function sendPasswordResetLink(): void

-
{{ __('validation.attributes.email') }} diff --git a/resources/views/livewire/pages/auth/login.blade.php b/resources/views/livewire/pages/auth/login.blade.php index 9c09977e..cffecd5b 100644 --- a/resources/views/livewire/pages/auth/login.blade.php +++ b/resources/views/livewire/pages/auth/login.blade.php @@ -26,10 +26,10 @@ public function login(): void
-
- +
+ - +

{{ __('pages/auth.login.title') }}