Merge branch 'develop' into dependabot/npm_and_yarn/develop/jquery-4.0.0

This commit is contained in:
mergify[bot]
2026-01-19 18:50:15 +00:00
committed by GitHub
7 changed files with 150 additions and 93 deletions
@@ -1,8 +1,7 @@
<?php
/*
* EnabledMFA.php
* Copyright (c) 2024 james@firefly-iii.org.
* UserHasFewMFABackupCodesLeft.php
* Copyright (c) 2026 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
@@ -17,19 +16,18 @@
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
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.');
}
}
@@ -1,8 +1,7 @@
<?php
/*
* EnabledMFA.php
* Copyright (c) 2024 james@firefly-iii.org.
* UserHasNoMFABackupCodesLeft.php
* Copyright (c) 2026 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
@@ -17,19 +16,18 @@
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
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.');
}
}
@@ -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__));
@@ -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);
@@ -0,0 +1,58 @@
<?php
/*
* NotifiesUserAboutFewCodesLeft.php
* Copyright (c) 2026 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
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());
}
}
}
@@ -0,0 +1,56 @@
<?php
/*
* NotifiesUserAboutNoCodesLeft.php
* Copyright (c) 2026 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
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());
}
}
}
+6 -8
View File
@@ -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',
],