Skip to content

Commit

Permalink
Merge pull request #20 from rappasoft/develop
Browse files Browse the repository at this point in the history
v1.2
  • Loading branch information
rappasoft authored Nov 22, 2021
2 parents 14aed2d + 1cf3f97 commit 945f0f1
Show file tree
Hide file tree
Showing 15 changed files with 159 additions and 15 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
fail-fast: true
matrix:
os: [ubuntu-latest, windows-latest]
php: [8.0]
php: [8.0, 7.4]
laravel: [8.*]
stability: [prefer-lowest, prefer-stable]
include:
Expand Down
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@

All notable changes to `Laravel Authentication Log` will be documented in this file.

### 1.2.0 - 2021-11-21

### Added

- Fire a successful login after a failed login on an unknown (new) device. - https://github.com/rappasoft/laravel-authentication-log/pull/15
- Make the events the package is listening for configurable in the config file
- Added French translation and missing location translations - https://github.com/rappasoft/laravel-authentication-log/pull/18
- PHP 7.4 Support

### 1.1.1 - 2021-10-20

### Changed
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
}
],
"require": {
"php": "^8.0",
"php": "^7.4|^8.0",
"illuminate/contracts": "^8.37",
"spatie/laravel-package-tools": "^1.4.3"
},
Expand Down
8 changes: 8 additions & 0 deletions config/authentication-log.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@
// The database connection where the authentication_log table resides. Leave empty to use the default
'db_connection' => null,

// The events the package listens for to log
'events' => [
'login' => \Illuminate\Auth\Events\Login::class,
'failed' => \Illuminate\Auth\Events\Failed::class,
'logout' => \Illuminate\Auth\Events\Logout::class,
'logout-other-devices' => \Illuminate\Auth\Events\OtherDeviceLogout::class,
],

'notifications' => [
'new-device' => [
// Send the NewDevice notification
Expand Down
5 changes: 3 additions & 2 deletions docs/known-issues.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ title: Known Issues
weight: 2
---

Curable:
Fixed:

- [This cache store is not supported. - torann/geoip](https://github.com/Torann/laravel-geoip/issues/147#issuecomment-528414630)
- When the session renews Laravel fires the Login event which results in a new login row [1](https://github.com/rappasoft/laravel-authentication-log/issues/13) [2](https://rappasoft.com/docs/laravel-authentication-log/v1/start/configuration#user-content-example-event-override)

Unsolved:

- [When the session renews Laravel fires the Login event which results in a new login row](https://github.com/rappasoft/laravel-authentication-log/issues/13)
- None
93 changes: 93 additions & 0 deletions docs/start/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,14 @@ return [

// The database connection where the authentication_log table resides. Leave empty to use the default
'db_connection' => null,

// The events the package listens for to log (as of v1.3)
'events' => [
'login' => \Illuminate\Auth\Events\Login::class,
'failed' => \Illuminate\Auth\Events\Failed::class,
'logout' => \Illuminate\Auth\Events\Logout::class,
'logout-other-devices' => \Illuminate\Auth\Events\OtherDeviceLogout::class,
],

'notifications' => [
'new-device' => [
Expand Down Expand Up @@ -84,3 +92,88 @@ class User extends Authenticatable
```

The package will listen for Laravel's Login, Logout, Failed, and OtherDeviceLogout events.

## Overriding default Laravel events

If you would like to listen to your own events you may override them in the package config (as of v1.3).

### Example event override

You may notice that Laravel [fires a Login event when the session renews](https://github.com/laravel/framework/blob/master/src/Illuminate/Auth/SessionGuard.php#L149) if the user clicked 'remember me' when logging in. This will produce empty login rows each time which is not what we want. The way around this is to fire your own `Login` event instead of listening for Laravels.

You can create a Login event that takes the user:

```php
<?php

namespace App\Domains\Auth\Events;

use Illuminate\Queue\SerializesModels;

class Login
{
use SerializesModels;

public $user;

public function __construct($user)
{
$this->user = $user;
}
}
```

Then override it in the package config:

```php
// The events the package listens for to log
'events' => [
'login' => \App\Domains\Auth\Events\Login::class,
...
],
```

Then call it where you login your user:

```php
event(new Login($user));
```

Now the package will only register actual login events, and not session re-authentications.

### Overriding in Fortify

If you are working with Fortify and would like to register your own Login event, you can append a class to the authentication stack:

In FortifyServiceProvider:

```php
Fortify::authenticateThrough(function () {
return array_filter([
...
FireLoginEvent::class,
]);
});
```

`FireLoginEvent` is just a class that fires the event:

```php
<?php

namespace App\Domains\Auth\Actions;

use App\Domains\Auth\Events\Login;

class FireLoginEvent
{
public function handle($request, $next)
{
if ($request->user()) {
event(new Login($request->user()));
}

return $next($request);
}
}
```
2 changes: 2 additions & 0 deletions resources/lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,7 @@
"Regards": "Regards",
"There has been a failed login attempt to your :app account.": "There has been a failed login attempt to your :app account.",
"Time": "Time",
"Unknown City": "Unknown City",
"Unknown State": "Unknown State",
"Your :app account logged in from a new device.": "Your :app account logged in from a new device."
}
15 changes: 15 additions & 0 deletions resources/lang/fr.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"A failed login to your account": "Échec de la connexion à votre compte",
"Account": "Compte",
"Browser": "Navigateur",
"Hello": "Bonjour",
"If this was you, you can ignore this alert. If you suspect any suspicious activity on your account, please change your password.": "Si c’était vous, vous pouvez ignorer cette alerte. Si vous soupçonnez une activité suspecte sur votre compte, veuillez modifier votre mot de passe.",
"IP Address": "Adresse IP",
"Location": "Emplacement",
"Regards": "Cordialement",
"There has been a failed login attempt to your :app account.": "Une tentative de connexion à votre compte sur :app a échoué.",
"Time": "Heure",
"Unknown City": "Ville inconnue",
"Unknown State": "État inconnu",
"Your :app account logged in from a new device.": "Connexion à votre compte sur :app depuis un nouvel appareil."
}
2 changes: 1 addition & 1 deletion resources/views/emails/failed.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
> **@lang('IP Address'):** {{ $ipAddress }}<br/>
> **@lang('Browser'):** {{ $browser }}<br/>
@if ($location && $location['default'] === false)
> **@lang('Location'):** {{ $location['city'] ?? 'Unknown City' }}, {{ $location['state'], 'Unknown State' }}
> **@lang('Location'):** {{ $location['city'] ?? __('Unknown City') }}, {{ $location['state'], __('Unknown State') }}
@endif

@lang('If this was you, you can ignore this alert. If you suspect any suspicious activity on your account, please change your password.')
Expand Down
2 changes: 1 addition & 1 deletion resources/views/emails/new.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
> **@lang('IP Address'):** {{ $ipAddress }}<br/>
> **@lang('Browser'):** {{ $browser }}<br/>
@if ($location && $location['default'] === false)
> **@lang('Location'):** {{ $location['city'] ?? 'Unknown City' }}, {{ $location['state'], 'Unknown State' }}
> **@lang('Location'):** {{ $location['city'] ?? __('Unknown City') }}, {{ $location['state'], __('Unknown State') }}
@endif

@lang('If this was you, you can ignore this alert. If you suspect any suspicious activity on your account, please change your password.')
Expand Down
8 changes: 4 additions & 4 deletions src/LaravelAuthenticationLogServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ public function configurePackage(Package $package): void
->hasCommand(PurgeAuthenticationLogCommand::class);

$events = $this->app->make(Dispatcher::class);
$events->listen(Login::class, LoginListener::class);
$events->listen(Failed::class, FailedLoginListener::class);
$events->listen(Logout::class, LogoutListener::class);
$events->listen(OtherDeviceLogout::class, OtherDeviceLogoutListener::class);
$events->listen(config('authentication-log.events.login') ?? Login::class, LoginListener::class);
$events->listen(config('authentication-log.events.failed') ?? Failed::class, FailedLoginListener::class);
$events->listen(config('authentication-log.events.logout') ?? Logout::class, LogoutListener::class);
$events->listen(config('authentication-log.events.other-device-logout') ?? OtherDeviceLogout::class, OtherDeviceLogoutListener::class);
}
}
6 changes: 5 additions & 1 deletion src/Listeners/FailedLoginListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,12 @@ public function __construct(Request $request)
$this->request = $request;
}

public function handle(Failed $event): void
public function handle($event): void
{
if (! $event instanceof (config('authentication-log.events.failed') ?? Failed::class)) {
return;
}

if ($event->user) {
$log = $event->user->authentications()->create([
'ip_address' => $ip = $this->request->ip(),
Expand Down
8 changes: 6 additions & 2 deletions src/Listeners/LoginListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,17 @@ public function __construct(Request $request)
$this->request = $request;
}

public function handle(Login $event): void
public function handle($event): void
{
if (! $event instanceof (config('authentication-log.events.login') ?? Login::class)) {
return;
}

if ($event->user) {
$user = $event->user;
$ip = $this->request->ip();
$userAgent = $this->request->userAgent();
$known = $user->authentications()->whereIpAddress($ip)->whereUserAgent($userAgent)->first();
$known = $user->authentications()->whereIpAddress($ip)->whereUserAgent($userAgent)->whereLoginSuccessful(true)->first();
$newUser = Carbon::parse($user->{$user->getCreatedAtColumn()})->diffInMinutes(Carbon::now()) < 1;

$log = $user->authentications()->create([
Expand Down
6 changes: 5 additions & 1 deletion src/Listeners/LogoutListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,12 @@ public function __construct(Request $request)
$this->request = $request;
}

public function handle(Logout $event): void
public function handle($event): void
{
if (! $event instanceof (config('authentication-log.events.logout') ?? Logout::class)) {
return;
}

if ($event->user) {
$user = $event->user;
$ip = $this->request->ip();
Expand Down
6 changes: 5 additions & 1 deletion src/Listeners/OtherDeviceLogoutListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,12 @@ public function __construct(Request $request)
$this->request = $request;
}

public function handle(OtherDeviceLogout $event): void
public function handle($event): void
{
if (! $event instanceof (config('authentication-log.events.other-device-logout') ?? OtherDeviceLogout::class)) {
return;
}

if ($event->user) {
$user = $event->user;
$ip = $this->request->ip();
Expand Down

0 comments on commit 945f0f1

Please sign in to comment.