Skip to content

Commit

Permalink
Beautify Livewire Stack (#326)
Browse files Browse the repository at this point in the history
* refactoring initial

* fix missing variable

* refactor

* extract login form

* extract logout

* fix errors

* refactor functional stack

* spacing

* import function

* update pest tests
  • Loading branch information
taylorotwell authored Oct 29, 2023
1 parent 72541b1 commit c348b02
Show file tree
Hide file tree
Showing 25 changed files with 241 additions and 172 deletions.
8 changes: 8 additions & 0 deletions src/Console/InstallsLivewireStack.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,14 @@ protected function installLivewireStack($functional = false)
(new Filesystem)->ensureDirectoryExists(app_path('View/Components'));
(new Filesystem)->copyDirectory(__DIR__.'/../../stubs/default/app/View/Components', app_path('View/Components'));

// Actions...
(new Filesystem)->ensureDirectoryExists(app_path('Livewire/Actions'));
(new Filesystem)->copyDirectory(__DIR__.'/../../stubs/livewire-common/app/Livewire/Actions', app_path('Livewire/Actions'));

// Forms...
(new Filesystem)->ensureDirectoryExists(app_path('Livewire/Forms'));
(new Filesystem)->copyDirectory(__DIR__.'/../../stubs/livewire-common/app/Livewire/Forms', app_path('Livewire/Forms'));

// Dark mode...
if (! $this->option('dark')) {
$this->removeDarkClasses((new Finder)
Expand Down
20 changes: 20 additions & 0 deletions stubs/livewire-common/app/Livewire/Actions/Logout.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace App\Livewire\Actions;

use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Session;

class Logout
{
/**
* Log the current user out of the application.
*/
public function __invoke(): void
{
Auth::guard('web')->logout();

Session::invalidate();
Session::regenerateToken();
}
}
72 changes: 72 additions & 0 deletions stubs/livewire-common/app/Livewire/Forms/LoginForm.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?php

namespace App\Livewire\Forms;

use Illuminate\Auth\Events\Lockout;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Str;
use Illuminate\Validation\ValidationException;
use Livewire\Attributes\Rule;
use Livewire\Form;

class LoginForm extends Form
{
#[Rule('required|string|email')]
public string $email = '';

#[Rule('required|string')]
public string $password = '';

#[Rule('boolean')]
public bool $remember = false;

/**
* Attempt to authenticate the request's credentials.
*
* @throws \Illuminate\Validation\ValidationException
*/
public function authenticate(): void
{
$this->ensureIsNotRateLimited();

if (! Auth::attempt($this->only(['email', 'password']), $this->remember)) {
RateLimiter::hit($this->throttleKey());

throw ValidationException::withMessages([
'email' => trans('auth.failed'),
]);
}

RateLimiter::clear($this->throttleKey());
}

/**
* Ensure the authentication request is not rate limited.
*/
protected function ensureIsNotRateLimited(): void
{
if (! RateLimiter::tooManyAttempts($this->throttleKey(), 5)) {
return;
}

event(new Lockout(request()));

$seconds = RateLimiter::availableIn($this->throttleKey());

throw ValidationException::withMessages([
'email' => trans('auth.throttle', [
'seconds' => $seconds,
'minutes' => ceil($seconds / 60),
]),
]);
}

/**
* Get the authentication rate limiting throttle key.
*/
protected function throttleKey(): string
{
return Str::transliterate(Str::lower($this->email).'|'.request()->ip());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
$user = User::factory()->create();

$component = Volt::test('pages.auth.login')
->set('email', $user->email)
->set('password', 'password');
->set('form.email', $user->email)
->set('form.password', 'password');

$component->call('login');

Expand All @@ -32,8 +32,8 @@
$user = User::factory()->create();

$component = Volt::test('pages.auth.login')
->set('email', $user->email)
->set('password', 'wrong-password');
->set('form.email', $user->email)
->set('form.password', 'wrong-password');

$component->call('login');

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ public function test_users_can_authenticate_using_the_login_screen(): void
$user = User::factory()->create();

$component = Volt::test('pages.auth.login')
->set('email', $user->email)
->set('password', 'password');
->set('form.email', $user->email)
->set('form.password', 'password');

$component->call('login');

Expand All @@ -43,8 +43,8 @@ public function test_users_can_not_authenticate_with_invalid_password(): void
$user = User::factory()->create();

$component = Volt::test('pages.auth.login')
->set('email', $user->email)
->set('password', 'wrong-password');
->set('form.email', $user->email)
->set('form.password', 'wrong-password');

$component->call('login');

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
<?php
$logout = function () {
auth()->guard('web')->logout();
use App\Livewire\Actions\Logout;
session()->invalidate();
session()->regenerateToken();
$logout = function (Logout $logout) {
$logout();
$this->redirect('/', navigate: true);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php
use App\Providers\RouteServiceProvider;
use Illuminate\Support\Facades\Auth;
use Illuminate\Validation\ValidationException;
use function Livewire\Volt\layout;
Expand All @@ -16,8 +17,8 @@
$confirmPassword = function () {
$this->validate();
if (! auth()->guard('web')->validate([
'email' => auth()->user()->email,
if (! Auth::guard('web')->validate([
'email' => Auth::user()->email,
'password' => $this->password,
])) {
throw ValidationException::withMessages([
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php
use Illuminate\Support\Facades\Password;
use Illuminate\Support\Facades\Session;
use function Livewire\Volt\layout;
use function Livewire\Volt\rules;
Expand Down Expand Up @@ -30,7 +31,7 @@
$this->reset('email');
session()->flash('status', __($status));
Session::flash('status', __($status));
};
?>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,54 +1,22 @@
<?php
use App\Livewire\Forms\LoginForm;
use App\Providers\RouteServiceProvider;
use Illuminate\Auth\Events\Lockout;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Str;
use Illuminate\Validation\ValidationException;
use Illuminate\Support\Facades\Session;
use function Livewire\Volt\form;
use function Livewire\Volt\layout;
use function Livewire\Volt\rules;
use function Livewire\Volt\state;
layout('layouts.guest');
state(['email' => '', 'password' => '', 'remember' => false]);
rules([
'email' => ['required', 'string', 'email'],
'password' => ['required', 'string'],
'remember' => ['boolean'],
]);
form(LoginForm::class);
$login = function () {
$this->validate();
$throttleKey = Str::transliterate(Str::lower($this->email).'|'.request()->ip());
if (RateLimiter::tooManyAttempts($throttleKey, 5)) {
event(new Lockout(request()));
$seconds = RateLimiter::availableIn($throttleKey);
throw ValidationException::withMessages([
'email' => trans('auth.throttle', [
'seconds' => $seconds,
'minutes' => ceil($seconds / 60),
]),
]);
}
if (! auth()->attempt($this->only(['email', 'password']), $this->remember)) {
RateLimiter::hit($throttleKey);
throw ValidationException::withMessages([
'email' => trans('auth.failed'),
]);
}
RateLimiter::clear($throttleKey);
$this->form->authenticate();
session()->regenerate();
Session::regenerate();
$this->redirect(
session('url.intended', RouteServiceProvider::HOME),
Expand All @@ -66,15 +34,15 @@
<!-- Email Address -->
<div>
<x-input-label for="email" :value="__('Email')" />
<x-text-input wire:model="email" id="email" class="block mt-1 w-full" type="email" name="email" required autofocus autocomplete="username" />
<x-text-input wire:model="form.email" id="email" class="block mt-1 w-full" type="email" name="email" required autofocus autocomplete="username" />
<x-input-error :messages="$errors->get('email')" class="mt-2" />
</div>

<!-- Password -->
<div class="mt-4">
<x-input-label for="password" :value="__('Password')" />

<x-text-input wire:model="password" id="password" class="block mt-1 w-full"
<x-text-input wire:model="form.password" id="password" class="block mt-1 w-full"
type="password"
name="password"
required autocomplete="current-password" />
Expand All @@ -85,7 +53,7 @@
<!-- Remember Me -->
<div class="block mt-4">
<label for="remember" class="inline-flex items-center">
<input wire:model="remember" id="remember" type="checkbox" class="rounded dark:bg-gray-900 border-gray-300 dark:border-gray-700 text-indigo-600 shadow-sm focus:ring-indigo-500 dark:focus:ring-indigo-600 dark:focus:ring-offset-gray-800" name="remember">
<input wire:model="form.remember" id="remember" type="checkbox" class="rounded dark:bg-gray-900 border-gray-300 dark:border-gray-700 text-indigo-600 shadow-sm focus:ring-indigo-500 dark:focus:ring-indigo-600 dark:focus:ring-offset-gray-800" name="remember">
<span class="ml-2 text-sm text-gray-600 dark:text-gray-400">{{ __('Remember me') }}</span>
</label>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
use App\Models\User;
use App\Providers\RouteServiceProvider;
use Illuminate\Auth\Events\Registered;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\Rules;
use function Livewire\Volt\layout;
use function Livewire\Volt\rules;
use function Livewire\Volt\state;
Expand All @@ -31,7 +33,7 @@
event(new Registered($user = User::create($validated)));
auth()->login($user);
Auth::login($user);
$this->redirect(RouteServiceProvider::HOME, navigate: true);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use Illuminate\Auth\Events\PasswordReset;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Password;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Str;
use Illuminate\Validation\Rules;
Expand Down Expand Up @@ -53,7 +54,7 @@ function ($user) {
return;
}
session()->flash('status', __($status));
Session::flash('status', __($status));
$this->redirectRoute('login', navigate: true);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
<?php
use App\Livewire\Actions\Logout;
use App\Providers\RouteServiceProvider;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Session;
use function Livewire\Volt\layout;
layout('layouts.guest');
$sendVerification = function () {
if (auth()->user()->hasVerifiedEmail()) {
if (Auth::user()->hasVerifiedEmail()) {
$this->redirect(
session('url.intended', RouteServiceProvider::HOME),
navigate: true
Expand All @@ -16,16 +19,13 @@
return;
}
auth()->user()->sendEmailVerificationNotification();
Auth::user()->sendEmailVerificationNotification();
session()->flash('status', 'verification-link-sent');
Session::flash('status', 'verification-link-sent');
};
$logout = function () {
auth()->guard('web')->logout();
session()->invalidate();
session()->regenerateToken();
$logout = function (Logout $logout) {
$logout();
$this->redirect('/', navigate: true);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
<?php
use App\Livewire\Actions\Logout;
use Illuminate\Support\Facades\Auth;
use function Livewire\Volt\rules;
use function Livewire\Volt\state;
state(['password' => '']);
rules(['password' => ['required', 'string', 'current_password']]);
$deleteUser = function () {
$deleteUser = function (Logout $logout) {
$this->validate();
tap(auth()->user(), fn () => auth()->logout())->delete();
session()->invalidate();
session()->regenerateToken();
tap(Auth::user(), $logout(...))->delete();
$this->redirect('/', navigate: true);
};
Expand Down
Loading

0 comments on commit c348b02

Please sign in to comment.