diff --git a/app/Actions/Fortify/CreateNewUser.php b/app/Actions/Fortify/CreateNewUser.php deleted file mode 100644 index dc91af02..00000000 --- a/app/Actions/Fortify/CreateNewUser.php +++ /dev/null @@ -1,53 +0,0 @@ - ['required', 'string', 'max:255'], - 'email' => [ - 'required', - 'string', - 'email', - 'max:255', - Rule::unique(User::class), - ], - 'username' => [ - 'required', - 'string', - 'min:6', - 'max:20', - 'alpha_dash', - Rule::unique(User::class, 'username'), - ], - 'password' => $this->passwordRules(), - ])->validate(); - - /** @var User $user */ - $user = User::create([ - 'name' => $input['name'], - 'email' => $input['email'], - 'username' => Str::lower($input['username']), - 'password' => Hash::make($input['password']), - 'opt_in' => isset($input['opt_in']), - ]); - - $user->assignRole('user'); - - return $user; - } -} diff --git a/app/Actions/Fortify/PasswordValidationRules.php b/app/Actions/Fortify/PasswordValidationRules.php deleted file mode 100644 index 50f9221a..00000000 --- a/app/Actions/Fortify/PasswordValidationRules.php +++ /dev/null @@ -1,26 +0,0 @@ - - */ - protected function passwordRules(): array - { - return [ - 'required', - 'string', - ! app()->environment('production') ? - Rules\Password::min(6) : - Rules\Password::min(6)->uncompromised(), - ]; - } -} diff --git a/app/Actions/Fortify/ResetUserPassword.php b/app/Actions/Fortify/ResetUserPassword.php deleted file mode 100644 index 45d145ae..00000000 --- a/app/Actions/Fortify/ResetUserPassword.php +++ /dev/null @@ -1,26 +0,0 @@ - $this->passwordRules(), - ])->validate(); - - $user->forceFill([ - 'password' => Hash::make($input['password']), - ])->save(); - } -} diff --git a/app/Actions/Fortify/UpdateUserPassword.php b/app/Actions/Fortify/UpdateUserPassword.php deleted file mode 100644 index f615e631..00000000 --- a/app/Actions/Fortify/UpdateUserPassword.php +++ /dev/null @@ -1,31 +0,0 @@ - ['required', 'string'], - 'password' => $this->passwordRules(), - ])->after(function ($validator) use ($user, $input): void { - if (! isset($input['current_password']) || ! Hash::check($input['current_password'], $user->password)) { - $validator->errors()->add('current_password', __('Le mot de passe fourni ne correspond pas à votre mot de passe actuel.')); - } - })->validateWithBag('updatePassword'); - - $user->forceFill([ - 'password' => Hash::make($input['password']), - ])->save(); - } -} diff --git a/app/Actions/Fortify/UpdateUserProfileInformation.php b/app/Actions/Fortify/UpdateUserProfileInformation.php deleted file mode 100644 index bb88729c..00000000 --- a/app/Actions/Fortify/UpdateUserProfileInformation.php +++ /dev/null @@ -1,48 +0,0 @@ - ['required', 'string', 'max:255'], - - 'email' => [ - 'required', - 'string', - 'email', - 'max:255', - Rule::unique('users')->ignore($user->id), - ], - ])->validateWithBag('updateProfileInformation'); - - if ($input['email'] !== $user->email) { - $this->updateVerifiedUser($user, $input); - } else { - $user->forceFill([ - 'name' => $input['name'], - 'email' => $input['email'], - ])->save(); - } - } - - private function updateVerifiedUser(User $user, array $input): void - { - $user->forceFill([ - 'name' => $input['name'], - 'email' => $input['email'], - 'email_verified_at' => null, - ])->save(); - - $user->sendEmailVerificationNotification(); - } -} diff --git a/app/Http/Controllers/Auth/VerifyEmailController.php b/app/Http/Controllers/Auth/VerifyEmailController.php new file mode 100644 index 00000000..b273f1c9 --- /dev/null +++ b/app/Http/Controllers/Auth/VerifyEmailController.php @@ -0,0 +1,35 @@ +user(); + + if ($user === null) { + return redirect()->route('login'); + } + + if ($user->hasVerifiedEmail()) { + return redirect()->intended(route('dashboard', absolute: false).'?verified=1'); + } + + if ($user->markEmailAsVerified()) { + event(new Verified($user)); + } + + return redirect()->intended(route('dashboard', absolute: false).'?verified=1'); + } +} diff --git a/app/Livewire/Forms/LoginForm.php b/app/Livewire/Forms/LoginForm.php new file mode 100644 index 00000000..352d41e0 --- /dev/null +++ b/app/Livewire/Forms/LoginForm.php @@ -0,0 +1,74 @@ +ensureIsNotRateLimited(); + + if (! Auth::attempt($this->only(['email', 'password']), $this->remember)) { + RateLimiter::hit($this->throttleKey()); + + throw ValidationException::withMessages([ + 'form.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([ + 'form.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()); + } +} diff --git a/app/Providers/FortifyServiceProvider.php b/app/Providers/FortifyServiceProvider.php deleted file mode 100644 index af8a3d28..00000000 --- a/app/Providers/FortifyServiceProvider.php +++ /dev/null @@ -1,47 +0,0 @@ - view('auth.login')); - Fortify::registerView(fn () => view('auth.register')); - Fortify::requestPasswordResetLinkView(fn () => view('auth.forgot-password')); - Fortify::resetPasswordView(fn (Request $request) => view('auth.reset-password', ['request' => $request])); - Fortify::verifyEmailView(fn () => view('auth.verify-email')); - - Fortify::createUsersUsing(CreateNewUser::class); - Fortify::updateUserProfileInformationUsing(UpdateUserProfileInformation::class); - Fortify::updateUserPasswordsUsing(UpdateUserPassword::class); - Fortify::resetUserPasswordsUsing(ResetUserPassword::class); - - RateLimiter::for( - 'login', - fn (Request $request) => Limit::perMinute(5) - ->by($request->email.$request->ip()) - ); - - RateLimiter::for( - 'two-factor', - fn (Request $request) => Limit::perMinute(5) - ->by($request->session()->get('login.id')) - ); - } -} diff --git a/app/Providers/VoltServiceProvider.php b/app/Providers/VoltServiceProvider.php new file mode 100644 index 00000000..eed72748 --- /dev/null +++ b/app/Providers/VoltServiceProvider.php @@ -0,0 +1,21 @@ +=7.1 <9.0" - }, - "require-dev": { - "phpunit/phpunit": "^7 || ^8 || ^9 || ^10 || ^11", - "squizlabs/php_codesniffer": "*" - }, - "type": "library", - "autoload": { - "psr-4": { - "DASPRiD\\Enum\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-2-Clause" - ], - "authors": [ - { - "name": "Ben Scholzen 'DASPRiD'", - "email": "mail@dasprids.de", - "homepage": "https://dasprids.de/", - "role": "Developer" - } - ], - "description": "PHP 7.1 enum implementation", - "keywords": [ - "enum", - "map" - ], - "support": { - "issues": "https://github.com/DASPRiD/Enum/issues", - "source": "https://github.com/DASPRiD/Enum/tree/1.0.6" - }, - "time": "2024-08-09T14:30:48+00:00" - }, { "name": "daverandom/libdns", "version": "v2.1.0", @@ -2592,16 +2488,16 @@ }, { "name": "filament/actions", - "version": "v3.2.122", + "version": "v3.2.123", "source": { "type": "git", "url": "https://github.com/filamentphp/actions.git", - "reference": "3badf1a1589bf70fdc625130f6dfc1ca2146a32f" + "reference": "de0a2c9d453ceb6546b1a804a8240d0b8367b1ce" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/actions/zipball/3badf1a1589bf70fdc625130f6dfc1ca2146a32f", - "reference": "3badf1a1589bf70fdc625130f6dfc1ca2146a32f", + "url": "https://api.github.com/repos/filamentphp/actions/zipball/de0a2c9d453ceb6546b1a804a8240d0b8367b1ce", + "reference": "de0a2c9d453ceb6546b1a804a8240d0b8367b1ce", "shasum": "" }, "require": { @@ -2641,20 +2537,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2024-10-31T13:38:12+00:00" + "time": "2024-11-06T08:50:46+00:00" }, { "name": "filament/filament", - "version": "v3.2.122", + "version": "v3.2.123", "source": { "type": "git", "url": "https://github.com/filamentphp/panels.git", - "reference": "076f5367a3dfe5f6864d117f6826ca7821586931" + "reference": "5c4bf4225106e5d2a1348de4e717a1ef8432b332" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/panels/zipball/076f5367a3dfe5f6864d117f6826ca7821586931", - "reference": "076f5367a3dfe5f6864d117f6826ca7821586931", + "url": "https://api.github.com/repos/filamentphp/panels/zipball/5c4bf4225106e5d2a1348de4e717a1ef8432b332", + "reference": "5c4bf4225106e5d2a1348de4e717a1ef8432b332", "shasum": "" }, "require": { @@ -2706,20 +2602,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2024-10-31T13:38:14+00:00" + "time": "2024-11-06T08:50:55+00:00" }, { "name": "filament/forms", - "version": "v3.2.122", + "version": "v3.2.123", "source": { "type": "git", "url": "https://github.com/filamentphp/forms.git", - "reference": "c863b5765b871485a2c624c43a0eb6e957a04b54" + "reference": "f75386dc6f3c41fd3178265a71806f1ed4be0478" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/forms/zipball/c863b5765b871485a2c624c43a0eb6e957a04b54", - "reference": "c863b5765b871485a2c624c43a0eb6e957a04b54", + "url": "https://api.github.com/repos/filamentphp/forms/zipball/f75386dc6f3c41fd3178265a71806f1ed4be0478", + "reference": "f75386dc6f3c41fd3178265a71806f1ed4be0478", "shasum": "" }, "require": { @@ -2762,11 +2658,11 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2024-10-31T13:38:16+00:00" + "time": "2024-11-06T08:50:57+00:00" }, { "name": "filament/infolists", - "version": "v3.2.122", + "version": "v3.2.123", "source": { "type": "git", "url": "https://github.com/filamentphp/infolists.git", @@ -2817,7 +2713,7 @@ }, { "name": "filament/notifications", - "version": "v3.2.122", + "version": "v3.2.123", "source": { "type": "git", "url": "https://github.com/filamentphp/notifications.git", @@ -2869,7 +2765,7 @@ }, { "name": "filament/support", - "version": "v3.2.122", + "version": "v3.2.123", "source": { "type": "git", "url": "https://github.com/filamentphp/support.git", @@ -2928,16 +2824,16 @@ }, { "name": "filament/tables", - "version": "v3.2.122", + "version": "v3.2.123", "source": { "type": "git", "url": "https://github.com/filamentphp/tables.git", - "reference": "56a852f7992a01ad8d7b85034cdbb2ae8a21086a" + "reference": "d066eed11528f1928a76cbe9075c54ddfe26fd1e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/tables/zipball/56a852f7992a01ad8d7b85034cdbb2ae8a21086a", - "reference": "56a852f7992a01ad8d7b85034cdbb2ae8a21086a", + "url": "https://api.github.com/repos/filamentphp/tables/zipball/d066eed11528f1928a76cbe9075c54ddfe26fd1e", + "reference": "d066eed11528f1928a76cbe9075c54ddfe26fd1e", "shasum": "" }, "require": { @@ -2976,11 +2872,11 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2024-10-31T13:38:27+00:00" + "time": "2024-11-06T08:51:06+00:00" }, { "name": "filament/widgets", - "version": "v3.2.122", + "version": "v3.2.123", "source": { "type": "git", "url": "https://github.com/filamentphp/widgets.git", @@ -4136,16 +4032,16 @@ }, { "name": "jaybizzle/crawler-detect", - "version": "v1.2.120", + "version": "v1.2.121", "source": { "type": "git", "url": "https://github.com/JayBizzle/Crawler-Detect.git", - "reference": "2b325bdce46bbb8a2e96dc740ad37c743c9d8617" + "reference": "40ecda6322d4163fe2c6e1dd47c574f580b8487f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/JayBizzle/Crawler-Detect/zipball/2b325bdce46bbb8a2e96dc740ad37c743c9d8617", - "reference": "2b325bdce46bbb8a2e96dc740ad37c743c9d8617", + "url": "https://api.github.com/repos/JayBizzle/Crawler-Detect/zipball/40ecda6322d4163fe2c6e1dd47c574f580b8487f", + "reference": "40ecda6322d4163fe2c6e1dd47c574f580b8487f", "shasum": "" }, "require": { @@ -4182,9 +4078,9 @@ ], "support": { "issues": "https://github.com/JayBizzle/Crawler-Detect/issues", - "source": "https://github.com/JayBizzle/Crawler-Detect/tree/v1.2.120" + "source": "https://github.com/JayBizzle/Crawler-Detect/tree/v1.2.121" }, - "time": "2024-09-15T14:31:21+00:00" + "time": "2024-10-20T21:42:39+00:00" }, { "name": "jean85/pretty-package-versions", @@ -4623,71 +4519,6 @@ }, "time": "2024-10-02T18:06:08+00:00" }, - { - "name": "laravel/fortify", - "version": "v1.24.4", - "source": { - "type": "git", - "url": "https://github.com/laravel/fortify.git", - "reference": "5bd3bdd535acf4054865c64eec6d8bb8c60cc127" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laravel/fortify/zipball/5bd3bdd535acf4054865c64eec6d8bb8c60cc127", - "reference": "5bd3bdd535acf4054865c64eec6d8bb8c60cc127", - "shasum": "" - }, - "require": { - "bacon/bacon-qr-code": "^3.0", - "ext-json": "*", - "illuminate/support": "^10.0|^11.0", - "php": "^8.1", - "pragmarx/google2fa": "^8.0", - "symfony/console": "^6.0|^7.0" - }, - "require-dev": { - "mockery/mockery": "^1.0", - "orchestra/testbench": "^8.16|^9.0", - "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^10.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - }, - "laravel": { - "providers": [ - "Laravel\\Fortify\\FortifyServiceProvider" - ] - } - }, - "autoload": { - "psr-4": { - "Laravel\\Fortify\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Taylor Otwell", - "email": "taylor@laravel.com" - } - ], - "description": "Backend controllers and scaffolding for Laravel authentication.", - "keywords": [ - "auth", - "laravel" - ], - "support": { - "issues": "https://github.com/laravel/fortify/issues", - "source": "https://github.com/laravel/fortify" - }, - "time": "2024-10-29T13:59:23+00:00" - }, { "name": "laravel/framework", "version": "v10.48.22", @@ -6278,6 +6109,78 @@ ], "time": "2024-10-15T19:35:06+00:00" }, + { + "name": "livewire/volt", + "version": "v1.6.5", + "source": { + "type": "git", + "url": "https://github.com/livewire/volt.git", + "reference": "d09fdb4cb52c6ce821d255683195bb6d446fe141" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/livewire/volt/zipball/d09fdb4cb52c6ce821d255683195bb6d446fe141", + "reference": "d09fdb4cb52c6ce821d255683195bb6d446fe141", + "shasum": "" + }, + "require": { + "laravel/framework": "^10.38.2|^11.0", + "livewire/livewire": "^3.0", + "php": "^8.1" + }, + "require-dev": { + "laravel/folio": "^1.1", + "mockery/mockery": "^1.6", + "orchestra/testbench": "^8.15.0|^9.0", + "pestphp/pest": "^2.9.5", + "phpstan/phpstan": "^1.10" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + }, + "laravel": { + "providers": [ + "Livewire\\Volt\\VoltServiceProvider" + ] + } + }, + "autoload": { + "files": [ + "functions.php" + ], + "psr-4": { + "Livewire\\Volt\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + }, + { + "name": "Nuno Maduro", + "email": "nuno@laravel.com" + } + ], + "description": "An elegantly crafted functional API for Laravel Livewire.", + "homepage": "https://github.com/livewire/volt", + "keywords": [ + "laravel", + "livewire", + "volt" + ], + "support": { + "issues": "https://github.com/livewire/volt/issues", + "source": "https://github.com/livewire/volt" + }, + "time": "2024-05-31T19:07:20+00:00" + }, { "name": "maennchen/zipstream-php", "version": "3.1.1", @@ -8076,16 +7979,16 @@ }, { "name": "phpdocumentor/reflection-docblock", - "version": "5.4.1", + "version": "5.5.1", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "9d07b3f7fdcf5efec5d1609cba3c19c5ea2bdc9c" + "reference": "0c70d2c566e899666f367ab7b80986beb3581e6f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/9d07b3f7fdcf5efec5d1609cba3c19c5ea2bdc9c", - "reference": "9d07b3f7fdcf5efec5d1609cba3c19c5ea2bdc9c", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/0c70d2c566e899666f367ab7b80986beb3581e6f", + "reference": "0c70d2c566e899666f367ab7b80986beb3581e6f", "shasum": "" }, "require": { @@ -8098,13 +8001,13 @@ "webmozart/assert": "^1.9.1" }, "require-dev": { - "mockery/mockery": "~1.3.5", + "mockery/mockery": "~1.3.5 || ~1.6.0", "phpstan/extension-installer": "^1.1", "phpstan/phpstan": "^1.8", "phpstan/phpstan-mockery": "^1.1", "phpstan/phpstan-webmozart-assert": "^1.2", "phpunit/phpunit": "^9.5", - "vimeo/psalm": "^5.13" + "psalm/phar": "^5.26" }, "type": "library", "extra": { @@ -8134,9 +8037,9 @@ "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", "support": { "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", - "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.4.1" + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.5.1" }, - "time": "2024-05-21T05:55:05+00:00" + "time": "2024-11-06T11:58:54+00:00" }, { "name": "phpdocumentor/type-resolver", @@ -8428,58 +8331,6 @@ }, "time": "2024-10-13T11:25:22+00:00" }, - { - "name": "pragmarx/google2fa", - "version": "v8.0.3", - "source": { - "type": "git", - "url": "https://github.com/antonioribeiro/google2fa.git", - "reference": "6f8d87ebd5afbf7790bde1ffc7579c7c705e0fad" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/antonioribeiro/google2fa/zipball/6f8d87ebd5afbf7790bde1ffc7579c7c705e0fad", - "reference": "6f8d87ebd5afbf7790bde1ffc7579c7c705e0fad", - "shasum": "" - }, - "require": { - "paragonie/constant_time_encoding": "^1.0|^2.0|^3.0", - "php": "^7.1|^8.0" - }, - "require-dev": { - "phpstan/phpstan": "^1.9", - "phpunit/phpunit": "^7.5.15|^8.5|^9.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "PragmaRX\\Google2FA\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Antonio Carlos Ribeiro", - "email": "acr@antoniocarlosribeiro.com", - "role": "Creator & Designer" - } - ], - "description": "A One Time Password Authentication package, compatible with Google Authenticator.", - "keywords": [ - "2fa", - "Authentication", - "Two Factor Authentication", - "google2fa" - ], - "support": { - "issues": "https://github.com/antonioribeiro/google2fa/issues", - "source": "https://github.com/antonioribeiro/google2fa/tree/v8.0.3" - }, - "time": "2024-09-05T11:56:40+00:00" - }, { "name": "psr/cache", "version": "3.0.0", @@ -10174,16 +10025,16 @@ }, { "name": "spatie/image-optimizer", - "version": "1.7.5", + "version": "1.8.0", "source": { "type": "git", "url": "https://github.com/spatie/image-optimizer.git", - "reference": "43aff6725cd87bb78ccd8532633cfa8bdc962505" + "reference": "4fd22035e81d98fffced65a8c20d9ec4daa9671c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/image-optimizer/zipball/43aff6725cd87bb78ccd8532633cfa8bdc962505", - "reference": "43aff6725cd87bb78ccd8532633cfa8bdc962505", + "url": "https://api.github.com/repos/spatie/image-optimizer/zipball/4fd22035e81d98fffced65a8c20d9ec4daa9671c", + "reference": "4fd22035e81d98fffced65a8c20d9ec4daa9671c", "shasum": "" }, "require": { @@ -10223,9 +10074,9 @@ ], "support": { "issues": "https://github.com/spatie/image-optimizer/issues", - "source": "https://github.com/spatie/image-optimizer/tree/1.7.5" + "source": "https://github.com/spatie/image-optimizer/tree/1.8.0" }, - "time": "2024-05-16T08:48:33+00:00" + "time": "2024-11-04T08:24:54+00:00" }, { "name": "spatie/invade", @@ -11280,16 +11131,16 @@ }, { "name": "symfony/console", - "version": "v6.4.13", + "version": "v6.4.14", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "f793dd5a7d9ae9923e35d0503d08ba734cec1d79" + "reference": "897c2441ed4eec8a8a2c37b943427d24dba3f26b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/f793dd5a7d9ae9923e35d0503d08ba734cec1d79", - "reference": "f793dd5a7d9ae9923e35d0503d08ba734cec1d79", + "url": "https://api.github.com/repos/symfony/console/zipball/897c2441ed4eec8a8a2c37b943427d24dba3f26b", + "reference": "897c2441ed4eec8a8a2c37b943427d24dba3f26b", "shasum": "" }, "require": { @@ -11354,7 +11205,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.4.13" + "source": "https://github.com/symfony/console/tree/v6.4.14" }, "funding": [ { @@ -11370,7 +11221,7 @@ "type": "tidelift" } ], - "time": "2024-10-09T08:40:40+00:00" + "time": "2024-11-05T15:34:40+00:00" }, { "name": "symfony/css-selector", @@ -11573,16 +11424,16 @@ }, { "name": "symfony/error-handler", - "version": "v6.4.13", + "version": "v6.4.14", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "e3c78742f86a5b65fe2ac4c4b6b776d92fd7ca0c" + "reference": "9e024324511eeb00983ee76b9aedc3e6ecd993d9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/e3c78742f86a5b65fe2ac4c4b6b776d92fd7ca0c", - "reference": "e3c78742f86a5b65fe2ac4c4b6b776d92fd7ca0c", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/9e024324511eeb00983ee76b9aedc3e6ecd993d9", + "reference": "9e024324511eeb00983ee76b9aedc3e6ecd993d9", "shasum": "" }, "require": { @@ -11628,7 +11479,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v6.4.13" + "source": "https://github.com/symfony/error-handler/tree/v6.4.14" }, "funding": [ { @@ -11644,7 +11495,7 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:18:03+00:00" + "time": "2024-11-05T15:34:40+00:00" }, { "name": "symfony/event-dispatcher", @@ -11937,16 +11788,16 @@ }, { "name": "symfony/http-client", - "version": "v6.4.13", + "version": "v6.4.14", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "509d0e8a798bf5e41e0b6317e9bce1140af47376" + "reference": "05d88cbd816ad6e0202edd9a9963cb9d615b8826" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/509d0e8a798bf5e41e0b6317e9bce1140af47376", - "reference": "509d0e8a798bf5e41e0b6317e9bce1140af47376", + "url": "https://api.github.com/repos/symfony/http-client/zipball/05d88cbd816ad6e0202edd9a9963cb9d615b8826", + "reference": "05d88cbd816ad6e0202edd9a9963cb9d615b8826", "shasum": "" }, "require": { @@ -12010,7 +11861,7 @@ "http" ], "support": { - "source": "https://github.com/symfony/http-client/tree/v6.4.13" + "source": "https://github.com/symfony/http-client/tree/v6.4.14" }, "funding": [ { @@ -12026,7 +11877,7 @@ "type": "tidelift" } ], - "time": "2024-10-14T18:15:01+00:00" + "time": "2024-11-05T16:39:55+00:00" }, { "name": "symfony/http-client-contracts", @@ -12108,16 +11959,16 @@ }, { "name": "symfony/http-foundation", - "version": "v6.4.13", + "version": "v6.4.14", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "4c0341b3e0a7291e752c69d2a1ed9a84b68d604c" + "reference": "ba020a321a95519303a3f09ec2824d34d601c388" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/4c0341b3e0a7291e752c69d2a1ed9a84b68d604c", - "reference": "4c0341b3e0a7291e752c69d2a1ed9a84b68d604c", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/ba020a321a95519303a3f09ec2824d34d601c388", + "reference": "ba020a321a95519303a3f09ec2824d34d601c388", "shasum": "" }, "require": { @@ -12165,7 +12016,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v6.4.13" + "source": "https://github.com/symfony/http-foundation/tree/v6.4.14" }, "funding": [ { @@ -12181,20 +12032,20 @@ "type": "tidelift" } ], - "time": "2024-10-11T19:20:58+00:00" + "time": "2024-11-05T16:39:55+00:00" }, { "name": "symfony/http-kernel", - "version": "v6.4.13", + "version": "v6.4.14", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "4474015c363ec0cd3bf47d55657e68630dbae66e" + "reference": "8278a947d0369754a47b758a9e17b72cab970951" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/4474015c363ec0cd3bf47d55657e68630dbae66e", - "reference": "4474015c363ec0cd3bf47d55657e68630dbae66e", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/8278a947d0369754a47b758a9e17b72cab970951", + "reference": "8278a947d0369754a47b758a9e17b72cab970951", "shasum": "" }, "require": { @@ -12279,7 +12130,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v6.4.13" + "source": "https://github.com/symfony/http-kernel/tree/v6.4.14" }, "funding": [ { @@ -12295,7 +12146,7 @@ "type": "tidelift" } ], - "time": "2024-10-27T13:00:29+00:00" + "time": "2024-11-06T09:45:21+00:00" }, { "name": "symfony/mailer", @@ -13236,16 +13087,16 @@ }, { "name": "symfony/process", - "version": "v6.4.13", + "version": "v6.4.14", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "1f9f59b46880201629df3bd950fc5ae8c55b960f" + "reference": "25214adbb0996d18112548de20c281be9f27279f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/1f9f59b46880201629df3bd950fc5ae8c55b960f", - "reference": "1f9f59b46880201629df3bd950fc5ae8c55b960f", + "url": "https://api.github.com/repos/symfony/process/zipball/25214adbb0996d18112548de20c281be9f27279f", + "reference": "25214adbb0996d18112548de20c281be9f27279f", "shasum": "" }, "require": { @@ -13277,7 +13128,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v6.4.13" + "source": "https://github.com/symfony/process/tree/v6.4.14" }, "funding": [ { @@ -13293,7 +13144,7 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:18:03+00:00" + "time": "2024-11-06T09:25:01+00:00" }, { "name": "symfony/psr-http-message-bridge", @@ -13886,16 +13737,16 @@ }, { "name": "symfony/var-dumper", - "version": "v6.4.13", + "version": "v6.4.14", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "2acb151474ed8cb43624e3f41a0bf7c4c8ce4f41" + "reference": "93c09246038178717a9c14b809ea8151ffcf7091" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/2acb151474ed8cb43624e3f41a0bf7c4c8ce4f41", - "reference": "2acb151474ed8cb43624e3f41a0bf7c4c8ce4f41", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/93c09246038178717a9c14b809ea8151ffcf7091", + "reference": "93c09246038178717a9c14b809ea8151ffcf7091", "shasum": "" }, "require": { @@ -13951,7 +13802,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v6.4.13" + "source": "https://github.com/symfony/var-dumper/tree/v6.4.14" }, "funding": [ { @@ -13967,7 +13818,7 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:18:03+00:00" + "time": "2024-11-05T15:34:40+00:00" }, { "name": "tijsverkoyen/css-to-inline-styles", @@ -14993,6 +14844,68 @@ ], "time": "2024-10-19T23:04:40+00:00" }, + { + "name": "laravel/breeze", + "version": "v1.29.1", + "source": { + "type": "git", + "url": "https://github.com/laravel/breeze.git", + "reference": "22c53b84b7fff91b01a318d71a10dfc251e92849" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/breeze/zipball/22c53b84b7fff91b01a318d71a10dfc251e92849", + "reference": "22c53b84b7fff91b01a318d71a10dfc251e92849", + "shasum": "" + }, + "require": { + "illuminate/console": "^10.17", + "illuminate/filesystem": "^10.17", + "illuminate/support": "^10.17", + "illuminate/validation": "^10.17", + "php": "^8.1.0" + }, + "require-dev": { + "orchestra/testbench": "^8.0", + "phpstan/phpstan": "^1.10" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + }, + "laravel": { + "providers": [ + "Laravel\\Breeze\\BreezeServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Laravel\\Breeze\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Minimal Laravel authentication scaffolding with Blade and Tailwind.", + "keywords": [ + "auth", + "laravel" + ], + "support": { + "issues": "https://github.com/laravel/breeze/issues", + "source": "https://github.com/laravel/breeze" + }, + "time": "2024-03-04T14:35:21+00:00" + }, { "name": "laravel/pint", "version": "v1.18.1", @@ -15958,16 +15871,16 @@ }, { "name": "phpstan/phpstan", - "version": "1.12.7", + "version": "1.12.8", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "dc2b9976bd8b0f84ec9b0e50cc35378551de7af0" + "reference": "f6a60a4d66142b8156c9da923f1972657bc4748c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/dc2b9976bd8b0f84ec9b0e50cc35378551de7af0", - "reference": "dc2b9976bd8b0f84ec9b0e50cc35378551de7af0", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/f6a60a4d66142b8156c9da923f1972657bc4748c", + "reference": "f6a60a4d66142b8156c9da923f1972657bc4748c", "shasum": "" }, "require": { @@ -16012,7 +15925,7 @@ "type": "github" } ], - "time": "2024-10-18T11:12:07+00:00" + "time": "2024-11-06T19:06:49+00:00" }, { "name": "phpunit/php-code-coverage", diff --git a/config/app.php b/config/app.php index af1a0c9e..3945225d 100644 --- a/config/app.php +++ b/config/app.php @@ -167,7 +167,6 @@ /* * Package Service Providers... */ - App\Providers\FortifyServiceProvider::class, App\Providers\Filament\AdminPanelProvider::class, LaravelFeature\Provider\FeatureServiceProvider::class, diff --git a/config/fortify.php b/config/fortify.php deleted file mode 100644 index 866d2aaa..00000000 --- a/config/fortify.php +++ /dev/null @@ -1,147 +0,0 @@ - 'web', - - /* - |-------------------------------------------------------------------------- - | Fortify Password Broker - |-------------------------------------------------------------------------- - | - | Here you may specify which password broker Fortify can use when a user - | is resetting their password. This configured value should match one - | of your password brokers setup in your "auth" configuration file. - | - */ - - 'passwords' => 'users', - - /* - |-------------------------------------------------------------------------- - | Username / Email - |-------------------------------------------------------------------------- - | - | This value defines which model attribute should be considered as your - | application's "username" field. Typically, this might be the email - | address of the users but you are free to change this value here. - | - | Out of the box, Fortify expects forgot password and reset password - | requests to have a field named 'email'. If the application uses - | another name for the field you may define it below as needed. - | - */ - - 'username' => 'email', - - 'email' => 'email', - - /* - |-------------------------------------------------------------------------- - | Home Path - |-------------------------------------------------------------------------- - | - | Here you may configure the path where users will get redirected during - | authentication or password reset when the operations are successful - | and the user is authenticated. You are free to change this value. - | - */ - - 'home' => RouteServiceProvider::HOME, - - /* - |-------------------------------------------------------------------------- - | Fortify Routes Prefix / Subdomain - |-------------------------------------------------------------------------- - | - | Here you may specify which prefix Fortify will assign to all the routes - | that it registers with the application. If necessary, you may change - | subdomain under which all of the Fortify routes will be available. - | - */ - - 'prefix' => '', - - 'domain' => null, - - /* - |-------------------------------------------------------------------------- - | Fortify Routes Middleware - |-------------------------------------------------------------------------- - | - | Here you may specify which middleware Fortify will assign to the routes - | that it registers with the application. If necessary, you may change - | these middleware but typically this provided default is preferred. - | - */ - - 'middleware' => ['web'], - - /* - |-------------------------------------------------------------------------- - | Rate Limiting - |-------------------------------------------------------------------------- - | - | By default, Fortify will throttle logins to five requests per minute for - | every email and IP address combination. However, if you would like to - | specify a custom rate limiter to call then you may specify it here. - | - */ - - 'limiters' => [ - 'login' => 'login', - 'two-factor' => 'two-factor', - ], - - /* - |-------------------------------------------------------------------------- - | Register View Routes - |-------------------------------------------------------------------------- - | - | Here you may specify if the routes returning views should be disabled as - | you may not need them when building your own application. This may be - | especially true if you're writing a custom single-page application. - | - */ - - 'views' => true, - - /* - |-------------------------------------------------------------------------- - | Features - |-------------------------------------------------------------------------- - | - | Some of the Fortify features are optional. You may disable the features - | by removing them from this array. You're free to only remove some of - | these features or you can even remove all of these if you need to. - | - */ - - 'features' => [ - Features::registration(), - Features::resetPasswords(), - Features::emailVerification(), - Features::updateProfileInformation(), - Features::updatePasswords(), - Features::twoFactorAuthentication([ - 'confirmPassword' => true, - ]), - ], - -]; diff --git a/resources/views/auth/forgot-password.blade.php b/resources/views/livewire/pages/auth/forgot-password.blade.php similarity index 100% rename from resources/views/auth/forgot-password.blade.php rename to resources/views/livewire/pages/auth/forgot-password.blade.php diff --git a/resources/views/auth/login.blade.php b/resources/views/livewire/pages/auth/login.blade.php similarity index 81% rename from resources/views/auth/login.blade.php rename to resources/views/livewire/pages/auth/login.blade.php index 5f3d7079..da144ea3 100644 --- a/resources/views/auth/login.blade.php +++ b/resources/views/livewire/pages/auth/login.blade.php @@ -1,12 +1,39 @@ - +validate(); + + $this->form->authenticate(); + + Session::regenerate(); + + $this->redirectIntended(default: route('dashboard', absolute: false), navigate: true); + } +}; ?> + +
+ +

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

-
+ @csrf
@@ -16,6 +43,7 @@ name="email" autocomplete="email" required="true" + wire:model="form.email" aria-label="{{ __('validation.attributes.email') }}" :placeholder="__('validation.attributes.email')" /> @@ -26,6 +54,7 @@ id="password" name="password" required="true" + wire:model="form.password" aria-label="{{ __('validation.attributes.password') }}" :placeholder="__('validation.attributes.password')" /> @@ -65,4 +94,4 @@ class="font-medium text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hov - +
diff --git a/resources/views/auth/register.blade.php b/resources/views/livewire/pages/auth/register.blade.php similarity index 99% rename from resources/views/auth/register.blade.php rename to resources/views/livewire/pages/auth/register.blade.php index 37412f20..2f4ffbfd 100644 --- a/resources/views/auth/register.blade.php +++ b/resources/views/livewire/pages/auth/register.blade.php @@ -135,4 +135,4 @@ - + \ No newline at end of file diff --git a/resources/views/auth/reset-password.blade.php b/resources/views/livewire/pages/auth/reset-password.blade.php similarity index 100% rename from resources/views/auth/reset-password.blade.php rename to resources/views/livewire/pages/auth/reset-password.blade.php diff --git a/resources/views/auth/verify-email.blade.php b/resources/views/livewire/pages/auth/verify-email.blade.php similarity index 100% rename from resources/views/auth/verify-email.blade.php rename to resources/views/livewire/pages/auth/verify-email.blade.php diff --git a/routes/auth.php b/routes/auth.php new file mode 100644 index 00000000..4fbfb939 --- /dev/null +++ b/routes/auth.php @@ -0,0 +1,33 @@ +group(function (): void { + Volt::route('register', 'pages.auth.register') + ->name('register'); + + Volt::route('login', 'pages.auth.login') + ->name('login'); + + Volt::route('forgot-password', 'pages.auth.forgot-password') + ->name('password.request'); + + Volt::route('reset-password/{token}', 'pages.auth.reset-password') + ->name('password.reset'); +}); + +Route::middleware('auth')->group(function (): void { + Volt::route('verify-email', 'pages.auth.verify-email') + ->name('verification.notice'); + + Route::get('verify-email/{id}/{hash}', VerifyEmailController::class) + ->middleware(['signed', 'throttle:6,1']) + ->name('verification.verify'); + + Volt::route('confirm-password', 'pages.auth.confirm-password') + ->name('password.confirm'); +}); diff --git a/routes/web.php b/routes/web.php index d4a537cb..1a7edfcc 100644 --- a/routes/web.php +++ b/routes/web.php @@ -62,3 +62,5 @@ Route::get('callback-payment', NotchPayCallBackController::class)->name('notchpay-callback'); require __DIR__.'/features/account.php'; + +require __DIR__.'/auth.php'; diff --git a/tests/Feature/Auth/AuthenticationTest.php b/tests/Feature/Auth/AuthenticationTest.php new file mode 100644 index 00000000..580ca08b --- /dev/null +++ b/tests/Feature/Auth/AuthenticationTest.php @@ -0,0 +1,62 @@ +get('/login'); + + $response + ->assertOk() + ->assertSeeVolt('pages.auth.login'); +}); + +test('users can authenticate using the login screen', function (): void { + $user = User::factory()->create(); + + $component = Volt::test('pages.auth.login') + ->set('form.email', $user->email) + ->set('form.password', 'password'); + + $component->call('login'); + + $component + ->assertHasNoErrors() + ->assertRedirect(route('dashboard', absolute: false)); + + $this->assertAuthenticated(); +}); + +test('users can not authenticate with invalid password', function (): void { + $user = User::factory()->create(); + + $component = Volt::test('pages.auth.login') + ->set('form.email', $user->email) + ->set('form.password', 'wrong-password'); + + $component->call('login'); + + $component + ->assertHasErrors() + ->assertNoRedirect(); + + $this->assertGuest(); +}); + +test('users can logout', function (): void { + $user = User::factory()->create(); + + $this->actingAs($user); + + $component = Volt::test('layout.navigation'); + + $component->call('logout'); + + $component + ->assertHasNoErrors() + ->assertRedirect('/'); + + $this->assertGuest(); +}); diff --git a/tests/Feature/Auth/LoginTest.php b/tests/Feature/Auth/LoginTest.php deleted file mode 100644 index 174d7fd7..00000000 --- a/tests/Feature/Auth/LoginTest.php +++ /dev/null @@ -1,3 +0,0 @@ -