Add user password reset

This commit is contained in:
Bruno
2024-07-15 14:41:46 +01:00
parent 9199f7cad8
commit 18a589c2fd
7 changed files with 270 additions and 0 deletions

View File

@@ -0,0 +1,21 @@
<?php
namespace App\Livewire\Auth;
use Livewire\Component;
use App\Livewire\Forms\ForgotPasswordForm;
class ForgotPassword extends Component
{
public ForgotPasswordForm $form;
public function send()
{
$this->form->sendPasswordResetLink();
}
public function render()
{
return view('livewire.auth.forgot-password');
}
}

View File

@@ -0,0 +1,35 @@
<?php
namespace App\Livewire\Auth;
use Livewire\Component;
use App\Livewire\Forms\ResetPasswordForm;
class ResetPassword extends Component
{
public ResetPasswordForm $form;
/**
* Mount the component.
*/
public function mount(string $token): void
{
$this->form->setToken($token);
$this->form->setEmail(request()->string('email'));
}
public function send(): void
{
if (!$this->form->resetPassword()) {
return;
}
$this->redirect(route('login', absolute: false), navigate: true);
}
public function render()
{
return view('livewire.auth.reset-password');
}
}

View File

@@ -0,0 +1,47 @@
<?php
namespace App\Livewire\Forms;
use Livewire\Form;
use App\Models\User;
use Illuminate\Support\Str;
use Illuminate\Validation\Rules;
use Livewire\Attributes\Validate;
use Illuminate\Auth\Events\Lockout;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Auth\Events\Registered;
use Illuminate\Support\Facades\Password;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Validation\ValidationException;
class ForgotPasswordForm extends Form
{
#[Validate('required|string|email')]
public string $email = '';
/**
* Send a password reset link to the provided email address.
*/
public function sendPasswordResetLink(): void
{
$this->validate();
// We will send the password reset link to this user. Once we have attempted
// to send the link, we will examine the response then see the message we
// need to show to the user. Finally, we'll send out a proper response.
$status = Password::sendResetLink(
$this->only('email')
);
if ($status != Password::RESET_LINK_SENT) {
$this->addError('email', __($status));
return;
}
$this->reset('email');
session()->flash('status', __($status));
}
}

View File

@@ -0,0 +1,77 @@
<?php
namespace App\Livewire\Forms;
use Livewire\Form;
use Illuminate\Support\Str;
use Livewire\Attributes\Locked;
use Illuminate\Validation\Rules;
use Livewire\Attributes\Validate;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\Password;
use Illuminate\Auth\Events\PasswordReset;
class ResetPasswordForm extends Form
{
#[Locked]
public string $token = '';
public string $email = '';
public string $password = '';
public string $password_confirmation = '';
public function rules()
{
return [
'token' => ['required'],
'email' => ['required', 'string', 'email'],
'password' => ['required', 'string', 'confirmed', Rules\Password::defaults()],
];
}
public function setToken(string $token): void
{
$this->token = $token;
}
public function setEmail(string $email): void
{
$this->email = $email;
}
/**
* Reset the password for the given user.
*/
public function resetPassword(): bool
{
$this->validate();
// Here we will attempt to reset the user's password. If it is successful we
// will update the password on an actual user model and persist it to the
// database. Otherwise we will parse the error and return the response.
$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 the password was successfully reset, we will redirect the user back to
// the application's home authenticated view. If there is an error we can
// redirect them back to where they came from with their error message.
if ($status != Password::PASSWORD_RESET) {
$this->addError('email', __($status));
return false;
}
Session::flash('status', __($status));
return true;
}
}

View File

@@ -0,0 +1,41 @@
<div class="flex flex-grow">
<main class="flex flex-col gap-10 flex-grow place-content-center bg-[#F6F7F8] dark:bg-[#181C20]">
<div class="mx-auto">
<h1 class="text-3xl font-semibold">Many Notes</h1>
</div>
<div class="md:container md:mx-auto">
<div class="flex flex-col gap-6 sm:mx-auto sm:w-full sm:max-w-sm p-6 sm:p-9 bg-[#FCFFFC] dark:bg-[#14171B] rounded-lg">
<div class="text-center">
<x-form.session-status :status="session('status')" />
</div>
<div class="text-center">
<x-form.text>
{{ __('Can\'t sign in? Enter your email and we\'ll send you a link to reset your password.') }}
</x-form.text>
</div>
<x-form wire:submit="send" class="flex flex-col gap-6">
<x-form.input
name="form.email"
label="{{ __('Email') }}"
type="email"
required
autofocus
/>
<x-form.submit label="{{ __('Send') }}" target="send" />
</x-form>
<div class="text-center">
<x-form.text>
<x-form.link wire:navigate href="{{ route('login') }}">
{{ __('Back to Sign in') }}
</x-form.link>
</x-form.text>
</div>
</div>
</div>
</main>
</div>

View File

@@ -0,0 +1,45 @@
<div class="flex flex-grow">
<main class="flex flex-col gap-10 flex-grow place-content-center bg-[#F6F7F8] dark:bg-[#181C20]">
<div class="mx-auto">
<h1 class="text-3xl font-semibold">Many Notes</h1>
</div>
<div class="md:container md:mx-auto">
<div class="flex flex-col gap-6 sm:mx-auto sm:w-full sm:max-w-sm p-6 sm:p-9 bg-[#FCFFFC] dark:bg-[#14171B] rounded-lg">
<x-form wire:submit="send" class="flex flex-col gap-6">
<x-form.input
name="form.email"
label="{{ __('Email') }}"
type="email"
required
/>
<x-form.input
name="form.password"
label="{{ __('New password') }}"
type="password"
required
autofocus
/>
<x-form.input
name="form.password_confirmation"
label="{{ __('Confirm password') }}"
type="password"
required
/>
<x-form.submit label="{{ __('Reset Password') }}" target="send" />
</x-form>
<div class="text-center">
<x-form.text>
<x-form.link wire:navigate href="{{ route('login') }}">
{{ __('Back to Sign in') }}
</x-form.link>
</x-form.text>
</div>
</div>
</div>
</main>
</div>

View File

@@ -2,9 +2,13 @@
use App\Livewire\Auth\Login;
use App\Livewire\Auth\Register;
use App\Livewire\Auth\ResetPassword;
use App\Livewire\Auth\ForgotPassword;
use Illuminate\Support\Facades\Route;
Route::middleware('guest')->group(function () {
Route::get('register', Register::class)->name('register');
Route::get('login', Login::class)->name('login');
Route::get('forgot-password', ForgotPassword::class)->name('forgot.password');
Route::get('reset-password/{token}', ResetPassword::class)->name('password.reset');
});