diff --git a/app/Filament/Pages/Auth/RequestPasswordReset.php b/app/Filament/Pages/Auth/RequestPasswordReset.php new file mode 100644 index 0000000..f8d7ede --- /dev/null +++ b/app/Filament/Pages/Auth/RequestPasswordReset.php @@ -0,0 +1,66 @@ +rateLimit(2); + } catch (TooManyRequestsException $exception) { + Notification::make() + ->title(__('filament-panels::pages/auth/password-reset/request-password-reset.notifications.throttled.title', [ + 'seconds' => $exception->secondsUntilAvailable, + 'minutes' => ceil($exception->secondsUntilAvailable / 60), + ])) + ->body(array_key_exists('body', __('filament-panels::pages/auth/password-reset/request-password-reset.notifications.throttled') ?: []) ? __('filament-panels::pages/auth/password-reset/request-password-reset.notifications.throttled.body', [ + 'seconds' => $exception->secondsUntilAvailable, + 'minutes' => ceil($exception->secondsUntilAvailable / 60), + ]) : null) + ->danger() + ->send(); + + return; + } + + $data = $this->form->getState(); + $status = Password::broker(Filament::getAuthPasswordBroker())->sendResetLink( + $data, + function (CanResetPassword $user, string $token): void { + if (! method_exists($user, 'notify')) { + $userClass = $user::class; + throw new Exception("Model [{$userClass}] does not have a [notify()] method."); + } + + $notification = new ResetPasswordNotification($token); + $user->notify($notification); + }, + ); + + if ($status !== Password::RESET_LINK_SENT) { + Notification::make() + ->title(__($status)) + ->danger() + ->send(); + + return; + } + + Notification::make() + ->title(__($status)) + ->success() + ->send(); + + $this->form->fill(); + } +} diff --git a/app/Notifications/ResetPasswordNotification.php b/app/Notifications/ResetPasswordNotification.php new file mode 100644 index 0000000..5beb130 --- /dev/null +++ b/app/Notifications/ResetPasswordNotification.php @@ -0,0 +1,56 @@ + + */ + public function via(object $notifiable): array + { + return ['mail']; + } + + /** + * Get the mail representation of the notification. + */ + public function toMail(object $notifiable): MailMessage + { + return (new MailMessage) + ->subject(Lang::get('Benachrichtigung zum Zurücksetzen des Passworts')) + ->greeting(Lang::get('Hallo')." {$notifiable->name},") + ->line(Lang::get('Sie erhalten diese E-Mail, weil wir eine Anfrage zum Zurücksetzen des Passworts für Ihr Konto erhalten haben.')) + ->action(Lang::get('Passwort Zurücksetzen'), $this->resetUrl($notifiable)) + ->line(Lang::get('Dieser Link zum Zurücksetzen des Passworts läuft in :count Minuten ab.', ['count' => config('auth.passwords.'.config('auth.defaults.passwords').'.expire')])) + ->line(Lang::get('Wenn Sie keine Passwortzurücksetzung beantragt haben, sind keine weiteren Maßnahmen erforderlich.')); + } + + /** + * Get the array representation of the notification. + * + * @return array + */ + public function toArray(object $notifiable): array + { + return [ + // + ]; + } +} diff --git a/app/Notifications/VerifyEmail.php b/app/Notifications/VerifyEmail.php new file mode 100644 index 0000000..7c4efc3 --- /dev/null +++ b/app/Notifications/VerifyEmail.php @@ -0,0 +1,114 @@ +verificationUrl($notifiable); + + if (static::$toMailCallback) { + return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl); + } + + return $this->buildMailMessage($verificationUrl); + } + + /** + * Get the verify email notification mail message for the given URL. + * + * @param string $url + * @return \Illuminate\Notifications\Messages\MailMessage + */ + protected function buildMailMessage($url) + { + return (new MailMessage) + ->subject(Lang::get('Verify Email Address')) + ->line(Lang::get('Please click the button below to verify your email address.')) + ->action(Lang::get('Verify Email Address'), $url) + ->line(Lang::get('If you did not create an account, no further action is required.')); + } + + /** + * Get the verification URL for the given notifiable. + * + * @param mixed $notifiable + * @return string + */ + protected function verificationUrl($notifiable) + { + if (static::$createUrlCallback) { + return call_user_func(static::$createUrlCallback, $notifiable); + } + + return URL::temporarySignedRoute( + 'verification.verify', + Carbon::now()->addMinutes(Config::get('auth.verification.expire', 60)), + [ + 'id' => $notifiable->getKey(), + 'hash' => sha1($notifiable->getEmailForVerification()), + ] + ); + } + + /** + * Set a callback that should be used when creating the email verification URL. + * + * @param \Closure $callback + * @return void + */ + public static function createUrlUsing($callback) + { + static::$createUrlCallback = $callback; + } + + /** + * Set a callback that should be used when building the notification mail message. + * + * @param \Closure(mixed, string): (\Illuminate\Notifications\Messages\MailMessage|\Illuminate\Contracts\Mail\Mailable) $callback + * @return void + */ + public static function toMailUsing($callback) + { + static::$toMailCallback = $callback; + } +} diff --git a/app/Providers/Filament/AdminPanelProvider.php b/app/Providers/Filament/AdminPanelProvider.php index 3aedc94..bd4ffa7 100644 --- a/app/Providers/Filament/AdminPanelProvider.php +++ b/app/Providers/Filament/AdminPanelProvider.php @@ -4,6 +4,7 @@ namespace App\Providers\Filament; use Agencetwogether\HooksHelper\HooksHelperPlugin; use App\Filament\Pages\Auth\Register; +use App\Filament\Pages\Auth\RequestPasswordReset; use App\Http\Middleware\AppUserAGBMiddleware; use Awcodes\LightSwitch\Enums\Alignment; use Awcodes\LightSwitch\LightSwitchPlugin; @@ -39,7 +40,7 @@ class AdminPanelProvider extends PanelProvider ->id('admin') ->path('app') ->login() - ->passwordReset() + ->passwordReset(RequestPasswordReset::class) ->emailVerification() ->emailChangeVerification() ->databaseNotifications() diff --git a/resources/views/filament/pages/auth/request-password-reset.blade.php b/resources/views/filament/pages/auth/request-password-reset.blade.php new file mode 100644 index 0000000..bb8ed15 --- /dev/null +++ b/resources/views/filament/pages/auth/request-password-reset.blade.php @@ -0,0 +1,3 @@ + + {{-- Page content --}} +