diff --git a/app/Events/Security/MFABackupFewLeft.php b/app/Events/Security/User/UserHasFewMFABackupCodesLeft.php similarity index 73% rename from app/Events/Security/MFABackupFewLeft.php rename to app/Events/Security/User/UserHasFewMFABackupCodesLeft.php index f31e325b18..39a67b6acd 100644 --- a/app/Events/Security/MFABackupFewLeft.php +++ b/app/Events/Security/User/UserHasFewMFABackupCodesLeft.php @@ -1,8 +1,7 @@ . */ -declare(strict_types=1); - -namespace FireflyIII\Events\Security; +namespace FireflyIII\Events\Security\User; use FireflyIII\Events\Event; use FireflyIII\User; use Illuminate\Contracts\Auth\Authenticatable; use Illuminate\Queue\SerializesModels; +use InvalidArgumentException; -class MFABackupFewLeft extends Event +class UserHasFewMFABackupCodesLeft extends Event { use SerializesModels; @@ -39,6 +37,8 @@ class MFABackupFewLeft extends Event { if ($user instanceof User) { $this->user = $user; + return; } + throw new InvalidArgumentException('User must be an instance of User.'); } } diff --git a/app/Events/Security/MFABackupNoLeft.php b/app/Events/Security/User/UserHasNoMFABackupCodesLeft.php similarity index 73% rename from app/Events/Security/MFABackupNoLeft.php rename to app/Events/Security/User/UserHasNoMFABackupCodesLeft.php index a56b8ce097..23ac6fbb89 100644 --- a/app/Events/Security/MFABackupNoLeft.php +++ b/app/Events/Security/User/UserHasNoMFABackupCodesLeft.php @@ -1,8 +1,7 @@ . */ -declare(strict_types=1); - -namespace FireflyIII\Events\Security; +namespace FireflyIII\Events\Security\User; use FireflyIII\Events\Event; use FireflyIII\User; use Illuminate\Contracts\Auth\Authenticatable; use Illuminate\Queue\SerializesModels; +use InvalidArgumentException; -class MFABackupNoLeft extends Event +class UserHasNoMFABackupCodesLeft extends Event { use SerializesModels; @@ -39,6 +37,8 @@ class MFABackupNoLeft extends Event { if ($user instanceof User) { $this->user = $user; + return; } + throw new InvalidArgumentException('User must be an instance of User.'); } } diff --git a/app/Handlers/Events/Security/MFAHandler.php b/app/Handlers/Events/Security/MFAHandler.php index 972af1223a..60659098d6 100644 --- a/app/Handlers/Events/Security/MFAHandler.php +++ b/app/Handlers/Events/Security/MFAHandler.php @@ -25,13 +25,9 @@ declare(strict_types=1); namespace FireflyIII\Handlers\Events\Security; use Exception; -use FireflyIII\Events\Security\MFABackupFewLeft; -use FireflyIII\Events\Security\MFABackupNoLeft; use FireflyIII\Events\Security\MFAManyFailedAttempts; use FireflyIII\Events\Security\MFANewBackupCodes; use FireflyIII\Events\Security\MFAUsedBackupCode; -use FireflyIII\Notifications\Security\MFABackupFewLeftNotification; -use FireflyIII\Notifications\Security\MFABackupNoLeftNotification; use FireflyIII\Notifications\Security\MFAManyFailedAttemptsNotification; use FireflyIII\Notifications\Security\MFAUsedBackupCodeNotification; use FireflyIII\Notifications\Security\NewBackupCodesNotification; @@ -40,57 +36,6 @@ use Illuminate\Support\Facades\Notification; class MFAHandler { - public function sendBackupFewLeftMail(MFABackupFewLeft $event): void - { - Log::debug(sprintf('Now in %s', __METHOD__)); - - $user = $event->user; - $count = $event->count; - - try { - Notification::send($user, new MFABackupFewLeftNotification($user, $count)); - } catch (Exception $e) { - $message = $e->getMessage(); - if (str_contains($message, 'Bcc')) { - Log::warning('[Bcc] Could not send notification. Please validate your email settings, use the .env.example file as a guide.'); - - return; - } - if (str_contains($message, 'RFC 2822')) { - Log::warning('[RFC] Could not send notification. Please validate your email settings, use the .env.example file as a guide.'); - - return; - } - Log::error($e->getMessage()); - Log::error($e->getTraceAsString()); - } - } - - public function sendBackupNoLeftMail(MFABackupNoLeft $event): void - { - Log::debug(sprintf('Now in %s', __METHOD__)); - - $user = $event->user; - - try { - Notification::send($user, new MFABackupNoLeftNotification($user)); - } catch (Exception $e) { - $message = $e->getMessage(); - if (str_contains($message, 'Bcc')) { - Log::warning('[Bcc] Could not send notification. Please validate your email settings, use the .env.example file as a guide.'); - - return; - } - if (str_contains($message, 'RFC 2822')) { - Log::warning('[RFC] Could not send notification. Please validate your email settings, use the .env.example file as a guide.'); - - return; - } - Log::error($e->getMessage()); - Log::error($e->getTraceAsString()); - } - } - public function sendMFAFailedAttemptsMail(MFAManyFailedAttempts $event): void { Log::debug(sprintf('Now in %s', __METHOD__)); diff --git a/app/Http/Controllers/Auth/TwoFactorController.php b/app/Http/Controllers/Auth/TwoFactorController.php index 983f0f8b26..6c39a4e6d2 100644 --- a/app/Http/Controllers/Auth/TwoFactorController.php +++ b/app/Http/Controllers/Auth/TwoFactorController.php @@ -23,13 +23,13 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Auth; -use FireflyIII\Support\Facades\Preferences; use Carbon\Carbon; -use FireflyIII\Events\Security\MFABackupFewLeft; -use FireflyIII\Events\Security\MFABackupNoLeft; use FireflyIII\Events\Security\MFAManyFailedAttempts; use FireflyIII\Events\Security\MFAUsedBackupCode; +use FireflyIII\Events\Security\User\UserHasFewMFABackupCodesLeft; +use FireflyIII\Events\Security\User\UserHasNoMFABackupCodesLeft; use FireflyIII\Http\Controllers\Controller; +use FireflyIII\Support\Facades\Preferences; use FireflyIII\User; use Illuminate\Contracts\View\Factory; use Illuminate\Contracts\View\View; @@ -49,12 +49,12 @@ class TwoFactorController extends Controller /** * What to do if 2FA lost? */ - public function lostTwoFactor(): Factory|View + public function lostTwoFactor(): Factory | View { /** @var User $user */ $user = auth()->user(); $siteOwner = config('firefly.site_owner'); - $title = (string) trans('firefly.two_factor_forgot_title'); + $title = (string)trans('firefly.two_factor_forgot_title'); return view('auth.lost-two-factor', ['user' => $user, 'siteOwner' => $siteOwner, 'title' => $title]); } @@ -63,11 +63,11 @@ class TwoFactorController extends Controller * @throws ContainerExceptionInterface * @throws NotFoundExceptionInterface */ - public function submitMFA(Request $request): Redirector|RedirectResponse + public function submitMFA(Request $request): Redirector | RedirectResponse { /** @var array $mfaHistory */ - $mfaHistory = Preferences::get('mfa_history', [])->data; - $mfaCode = (string) $request->get('one_time_password'); + $mfaHistory = Preferences::get('mfa_history', [])->data; + $mfaCode = (string)$request->get('one_time_password'); // is in history? then refuse to use it. if ($this->inMFAHistory($mfaCode, $mfaHistory)) { @@ -82,7 +82,7 @@ class TwoFactorController extends Controller // if not OK, save error. if (!$authenticator->isAuthenticated()) { - $user = auth()->user(); + $user = auth()->user(); $this->addToMFAFailureCounter(); $counter = $this->getMFAFailureCounter(); if (3 === $counter || 10 === $counter) { @@ -168,7 +168,7 @@ class TwoFactorController extends Controller private function addToMFAFailureCounter(): void { - $preference = (int) Preferences::get('mfa_failure_count', 0)->data; + $preference = (int)Preferences::get('mfa_failure_count', 0)->data; ++$preference; Log::channel('audit')->info(sprintf('MFA failure count is set to %d.', $preference)); Preferences::set('mfa_failure_count', $preference); @@ -176,7 +176,7 @@ class TwoFactorController extends Controller private function getMFAFailureCounter(): int { - $value = (int) Preferences::get('mfa_failure_count', 0)->data; + $value = (int)Preferences::get('mfa_failure_count', 0)->data; Log::channel('audit')->info(sprintf('MFA failure count is %d.', $value)); return $value; @@ -220,7 +220,7 @@ class TwoFactorController extends Controller */ private function removeFromBackupCodes(string $mfaCode): void { - $list = Preferences::get('mfa_recovery', [])->data; + $list = Preferences::get('mfa_recovery', [])->data; if (!is_array($list)) { $list = []; } @@ -230,13 +230,13 @@ class TwoFactorController extends Controller if (count($newList) <= 3 && count($newList) > 0) { $user = auth()->user(); Log::channel('audit')->info(sprintf('User "%s" has used a backup code. They have %d backup codes left.', $user->email, count($newList))); - event(new MFABackupFewLeft($user, count($newList))); + event(new UserHasFewMFABackupCodesLeft($user, count($newList))); } // if the list is empty, send notification if (0 === count($newList)) { $user = auth()->user(); Log::channel('audit')->info(sprintf('User "%s" has used their last backup code.', $user->email)); - event(new MFABackupNoLeft($user)); + event(new UserHasNoMFABackupCodesLeft($user)); } Preferences::set('mfa_recovery', $newList); diff --git a/app/Listeners/Security/User/NotifiesUserAboutFewCodesLeft.php b/app/Listeners/Security/User/NotifiesUserAboutFewCodesLeft.php new file mode 100644 index 0000000000..b3f4d989b1 --- /dev/null +++ b/app/Listeners/Security/User/NotifiesUserAboutFewCodesLeft.php @@ -0,0 +1,58 @@ +. + */ + +namespace FireflyIII\Listeners\Security\User; + +use Exception; +use FireflyIII\Events\Security\User\UserHasFewMFABackupCodesLeft; +use FireflyIII\Notifications\Security\MFABackupFewLeftNotification; +use Illuminate\Support\Facades\Log; +use Illuminate\Support\Facades\Notification; + +class NotifiesUserAboutFewCodesLeft +{ + + public function handle(UserHasFewMFABackupCodesLeft $event): void { + Log::debug(sprintf('Now in %s', __METHOD__)); + + $user = $event->user; + $count = $event->count; + + try { + Notification::send($user, new MFABackupFewLeftNotification($user, $count)); + } catch (Exception $e) { + $message = $e->getMessage(); + if (str_contains($message, 'Bcc')) { + Log::warning('[Bcc] Could not send notification. Please validate your email settings, use the .env.example file as a guide.'); + + return; + } + if (str_contains($message, 'RFC 2822')) { + Log::warning('[RFC] Could not send notification. Please validate your email settings, use the .env.example file as a guide.'); + + return; + } + Log::error($e->getMessage()); + Log::error($e->getTraceAsString()); + } + } + +} diff --git a/app/Listeners/Security/User/NotifiesUserAboutNoCodesLeft.php b/app/Listeners/Security/User/NotifiesUserAboutNoCodesLeft.php new file mode 100644 index 0000000000..3cef29559d --- /dev/null +++ b/app/Listeners/Security/User/NotifiesUserAboutNoCodesLeft.php @@ -0,0 +1,56 @@ +. + */ + +namespace FireflyIII\Listeners\Security\User; + +use Exception; +use FireflyIII\Events\Security\User\UserHasNoMFABackupCodesLeft; +use FireflyIII\Notifications\Security\MFABackupNoLeftNotification; +use Illuminate\Support\Facades\Log; +use Illuminate\Support\Facades\Notification; + +class NotifiesUserAboutNoCodesLeft +{ + public function handle(UserHasNoMFABackupCodesLeft $event): void { + Log::debug(sprintf('Now in %s', __METHOD__)); + + $user = $event->user; + + try { + Notification::send($user, new MFABackupNoLeftNotification($user)); + } catch (Exception $e) { + $message = $e->getMessage(); + if (str_contains($message, 'Bcc')) { + Log::warning('[Bcc] Could not send notification. Please validate your email settings, use the .env.example file as a guide.'); + + return; + } + if (str_contains($message, 'RFC 2822')) { + Log::warning('[RFC] Could not send notification. Please validate your email settings, use the .env.example file as a guide.'); + + return; + } + Log::error($e->getMessage()); + Log::error($e->getTraceAsString()); + } + } + +} diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index f6f880bd5a..2ac881c1e7 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -35,8 +35,6 @@ use FireflyIII\Events\RequestedNewPassword; use FireflyIII\Events\RequestedReportOnJournals; use FireflyIII\Events\RequestedSendWebhookMessages; use FireflyIII\Events\RequestedVersionCheckStatus; -use FireflyIII\Events\Security\MFABackupFewLeft; -use FireflyIII\Events\Security\MFABackupNoLeft; use FireflyIII\Events\Security\MFAManyFailedAttempts; use FireflyIII\Events\Security\MFANewBackupCodes; use FireflyIII\Events\Security\MFAUsedBackupCode; @@ -193,12 +191,12 @@ class EventServiceProvider extends ServiceProvider MFAUsedBackupCode::class => [ 'FireflyIII\Handlers\Events\Security\MFAHandler@sendUsedBackupCodeMail', ], - MFABackupFewLeft::class => [ - 'FireflyIII\Handlers\Events\Security\MFAHandler@sendBackupFewLeftMail', - ], - MFABackupNoLeft::class => [ - 'FireflyIII\Handlers\Events\Security\MFAHandler@sendBackupNoLeftMail', - ], + // MFABackupFewLeft::class => [ + // 'FireflyIII\Handlers\Events\Security\MFAHandler@sendBackupFewLeftMail', + // ], + // MFABackupNoLeft::class => [ + // 'FireflyIII\Handlers\Events\Security\MFAHandler@sendBackupNoLeftMail', + // ], MFAManyFailedAttempts::class => [ 'FireflyIII\Handlers\Events\Security\MFAHandler@sendMFAFailedAttemptsMail', ],