mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-02-25 18:45:27 -06:00
Code for #3712
This commit is contained in:
parent
7f48043505
commit
798c73394d
49
app/Events/DetectedNewIPAddress.php
Normal file
49
app/Events/DetectedNewIPAddress.php
Normal file
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
/*
|
||||
* DetectedNewIPAddress.php
|
||||
* Copyright (c) 2020 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\Events;
|
||||
|
||||
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
/**
|
||||
* Class DetectedNewIPAddress
|
||||
*/
|
||||
class DetectedNewIPAddress extends Event
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
public string $ipAddress;
|
||||
public User $user;
|
||||
|
||||
/**
|
||||
* Create a new event instance. This event is triggered when a new user registers.
|
||||
*
|
||||
* @param User $user
|
||||
* @param string $ipAddress
|
||||
*/
|
||||
public function __construct(User $user, string $ipAddress)
|
||||
{
|
||||
$this->ipAddress = $ipAddress;
|
||||
$this->user = $user;
|
||||
}
|
||||
}
|
@ -23,11 +23,14 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Handlers\Events;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Exception;
|
||||
use FireflyIII\Events\DetectedNewIPAddress;
|
||||
use FireflyIII\Events\RegisteredUser;
|
||||
use FireflyIII\Events\RequestedNewPassword;
|
||||
use FireflyIII\Events\UserChangedEmail;
|
||||
use FireflyIII\Mail\ConfirmEmailChangeMail;
|
||||
use FireflyIII\Mail\NewIPAddressWarningMail;
|
||||
use FireflyIII\Mail\RegisteredUser as RegisteredUserMail;
|
||||
use FireflyIII\Mail\RequestedNewPassword as RequestedNewPasswordMail;
|
||||
use FireflyIII\Mail\UndoEmailChangeMail;
|
||||
@ -125,6 +128,78 @@ class UserEventHandler
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Login $event
|
||||
*/
|
||||
public function storeUserIPAddress(Login $event): void
|
||||
{
|
||||
/** @var User $user */
|
||||
$user = $event->user;
|
||||
/** @var array $preference */
|
||||
$preference = app('preferences')->getForUser($user, 'login_ip_history', [])->data;
|
||||
$inArray = false;
|
||||
$ip = request()->ip();
|
||||
Log::debug(sprintf('User logging in from IP address %s', $ip));
|
||||
|
||||
// update array if in array
|
||||
foreach ($preference as $index => $row) {
|
||||
if ($row['ip'] === $ip) {
|
||||
Log::debug('Found IP in array, refresh time.');
|
||||
$preference[$index]['time'] = now(config('app.timezone'))->format('Y-m-d H:i:s');
|
||||
$inArray = true;
|
||||
}
|
||||
// clean up old entries (6 months)
|
||||
$carbon = Carbon::createFromFormat('Y-m-d H:i:s', $preference[$index]['time']);
|
||||
if ($carbon->diffInMonths(today()) > 6) {
|
||||
Log::debug(sprintf('Entry for %s is very old, remove it.', $row['ip']));
|
||||
unset($preference[$index]);
|
||||
}
|
||||
}
|
||||
// add to array if not the case:
|
||||
if (false === $inArray) {
|
||||
$preference[] = [
|
||||
'ip' => $ip,
|
||||
'time' => now(config('app.timezone'))->format('Y-m-d H:i:s'),
|
||||
'notified' => false,
|
||||
];
|
||||
|
||||
|
||||
}
|
||||
$preference = array_values($preference);
|
||||
app('preferences')->setForUser($user, 'login_ip_history', $preference);
|
||||
|
||||
if (false === $inArray) {
|
||||
event(new DetectedNewIPAddress($user, $ip));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DetectedNewIPAddress $event
|
||||
*/
|
||||
public function notifyNewIPAddress(DetectedNewIPAddress $event): void
|
||||
{
|
||||
$user = $event->user;
|
||||
$email = $user->email;
|
||||
$ipAddress = $event->ipAddress;
|
||||
$list = app('preferences')->getForUser($user, 'login_ip_history', [])->data;
|
||||
|
||||
/** @var array $entry */
|
||||
foreach ($list as $index => $entry) {
|
||||
if (false === $entry['notified']) {
|
||||
try {
|
||||
Mail::to($email)->send(new NewIPAddressWarningMail($ipAddress));
|
||||
// @codeCoverageIgnoreStart
|
||||
} catch (Exception $e) {
|
||||
Log::error($e->getMessage());
|
||||
}
|
||||
}
|
||||
$list[$index]['notified'] = true;
|
||||
}
|
||||
|
||||
app('preferences')->setForUser($user, 'login_ip_history', $list);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send email to confirm email change.
|
||||
*
|
||||
@ -167,7 +242,7 @@ class UserEventHandler
|
||||
$ipAddress = $event->ipAddress;
|
||||
$token = app('preferences')->getForUser($user, 'email_change_undo_token', 'invalid');
|
||||
$hashed = hash('sha256', sprintf('%s%s', (string) config('app.key'), $oldEmail));
|
||||
$uri = route('profile.undo-email-change', [$token->data,$hashed]);
|
||||
$uri = route('profile.undo-email-change', [$token->data, $hashed]);
|
||||
try {
|
||||
Mail::to($oldEmail)->send(new UndoEmailChangeMail($newEmail, $oldEmail, $uri, $ipAddress));
|
||||
// @codeCoverageIgnoreStart
|
||||
|
59
app/Mail/NewIPAddressWarningMail.php
Normal file
59
app/Mail/NewIPAddressWarningMail.php
Normal file
@ -0,0 +1,59 @@
|
||||
<?php
|
||||
/*
|
||||
* NewIPAddressWarningMail.php
|
||||
* Copyright (c) 2020 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\Mail;
|
||||
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Laravel\Passport\Client;
|
||||
|
||||
/**
|
||||
* Class NewIPAddressWarningMail
|
||||
*/
|
||||
class NewIPAddressWarningMail extends Mailable
|
||||
{
|
||||
use Queueable, SerializesModels;
|
||||
|
||||
public string $ipAddress;
|
||||
|
||||
/**
|
||||
* OAuthTokenCreatedMail constructor.
|
||||
*
|
||||
* @param string $ipAddress
|
||||
*/
|
||||
public function __construct(string $ipAddress)
|
||||
{
|
||||
$this->ipAddress = $ipAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the message.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function build(): self
|
||||
{
|
||||
return $this->view('emails.new-ip-html')->text('emails.new-ip-text')
|
||||
->subject((string) trans('email.login_from_new_ip'));
|
||||
}
|
||||
}
|
@ -24,6 +24,7 @@ namespace FireflyIII\Providers;
|
||||
|
||||
use Exception;
|
||||
use FireflyIII\Events\AdminRequestedTestMessage;
|
||||
use FireflyIII\Events\DetectedNewIPAddress;
|
||||
use FireflyIII\Events\RegisteredUser;
|
||||
use FireflyIII\Events\RequestedNewPassword;
|
||||
use FireflyIII\Events\RequestedReportOnJournals;
|
||||
@ -67,6 +68,10 @@ class EventServiceProvider extends ServiceProvider
|
||||
Login::class => [
|
||||
'FireflyIII\Handlers\Events\UserEventHandler@checkSingleUserIsAdmin',
|
||||
'FireflyIII\Handlers\Events\UserEventHandler@demoUserBackToEnglish',
|
||||
'FireflyIII\Handlers\Events\UserEventHandler@storeUserIPAddress',
|
||||
],
|
||||
DetectedNewIPAddress::class => [
|
||||
'FireflyIII\Handlers\Events\UserEventHandler@notifyNewIPAddress',
|
||||
],
|
||||
RequestedVersionCheckStatus::class => [
|
||||
'FireflyIII\Handlers\Events\VersionCheckEventHandler@checkForUpdates',
|
||||
|
@ -51,7 +51,6 @@ class RemoteUserGuard implements Guard
|
||||
*/
|
||||
public function __construct(UserProvider $provider, Application $app)
|
||||
{
|
||||
Log::debug('Constructed RemoteUserGuard');
|
||||
$this->application = $app;
|
||||
$this->provider = $provider;
|
||||
$this->user = null;
|
||||
|
@ -33,6 +33,11 @@ return [
|
||||
'admin_test_subject' => 'A test message from your Firefly III installation',
|
||||
'admin_test_body' => 'This is a test message from your Firefly III instance. It was sent to :email.',
|
||||
|
||||
// new IP
|
||||
'login_from_new_ip' => 'You logged in from an unknown IP address.',
|
||||
'new_ip_body' => 'You logged in from a new, unknown IP address:',
|
||||
'new_ip_warning' => 'If you didn\'t login, of if you have no idea what this is about, verify your password security, change it, and log out all other sessions. To do this, go to your profile page. Of course you have 2FA enabled already, right? Stay safe!',
|
||||
|
||||
// access token created
|
||||
'access_token_created_subject' => 'A new access token was created',
|
||||
'access_token_created_body' => 'Somebody (hopefully you) just created a new Firefly III API Access Token for your user account.',
|
||||
|
14
resources/views/v1/emails/new-ip-html.twig
Normal file
14
resources/views/v1/emails/new-ip-html.twig
Normal file
@ -0,0 +1,14 @@
|
||||
{% include 'emails.header-html' %}
|
||||
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
|
||||
{{ trans('email.new_ip_body') }}
|
||||
</p>
|
||||
|
||||
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;font-weight: bold;">
|
||||
{{ ipAddress }}
|
||||
</p>
|
||||
|
||||
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
|
||||
{{ trans('email.new_ip_warning') }}
|
||||
</p>
|
||||
|
||||
{% include 'emails.footer-html' %}
|
8
resources/views/v1/emails/new-ip-text.twig
Normal file
8
resources/views/v1/emails/new-ip-text.twig
Normal file
@ -0,0 +1,8 @@
|
||||
{% include 'emails.header-text' %}
|
||||
{{ trans('email.new_ip_body') }}
|
||||
|
||||
{{ ipAddress }}
|
||||
|
||||
{{ trans('email.new_ip_warning') }}
|
||||
|
||||
{% include 'emails.footer-text' %}
|
Loading…
Reference in New Issue
Block a user