diff --git a/app/Http/Controllers/ManageController.php b/app/Http/Controllers/ManageController.php index 0125923..3a31f02 100644 --- a/app/Http/Controllers/ManageController.php +++ b/app/Http/Controllers/ManageController.php @@ -10,7 +10,9 @@ use App\Http\Requests\StoreSettingsRequest; use App\Services\Import; use App\Services\Shaarli\Shaarli; use App\Tag; +use App\User; use Illuminate\Http\Request; +use Lab404\AuthChecker\Models\Login; use Maatwebsite\Excel\Facades\Excel; class ManageController extends Controller @@ -124,4 +126,16 @@ class ManageController extends Controller $this->flash(__('Settings updated!'), 'success'); return redirect()->back(); } + + public function logins(Request $request) + { + /** @var User $user */ + $user = $request->user(); + $logins = Login::where('user_id', $user->id)->latest()->paginate(25); + + return view('manage.logins')->with([ + 'logins' => $logins, + 'page_title' => __('Logins'), + ]); + } } diff --git a/app/Http/Middleware/RedirectIfAuthenticated.php b/app/Http/Middleware/RedirectIfAuthenticated.php index e4cec9c..e27860e 100644 --- a/app/Http/Middleware/RedirectIfAuthenticated.php +++ b/app/Http/Middleware/RedirectIfAuthenticated.php @@ -18,7 +18,7 @@ class RedirectIfAuthenticated public function handle($request, Closure $next, $guard = null) { if (Auth::guard($guard)->check()) { - return redirect('/home'); + return redirect('/'); } return $next($request); diff --git a/app/User.php b/app/User.php index 698b942..dc2ee9e 100644 --- a/app/User.php +++ b/app/User.php @@ -5,10 +5,13 @@ namespace App; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; use Illuminate\Support\Str; +use Lab404\AuthChecker\Interfaces\HasLoginsAndDevicesInterface; +use Lab404\AuthChecker\Models\HasLoginsAndDevices; -class User extends Authenticatable +class User extends Authenticatable implements HasLoginsAndDevicesInterface { - use Notifiable; + use Notifiable, + HasLoginsAndDevices; protected $fillable = [ 'name', diff --git a/changelog.md b/changelog.md index da28014..0eea1a0 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,14 @@ +# 1.2.3 + +## Added + +- Log all logins and associated devices with new section in settings + +## Fixed + +- Typo in secure login page title +- Redirection when already logged + # 1.2.2 ## Added diff --git a/composer.json b/composer.json index 37290ea..4c1f201 100644 --- a/composer.json +++ b/composer.json @@ -12,16 +12,17 @@ "php": "^7.2", "doctrine/dbal": "^2.9", "fideloper/proxy": "^4.0", + "hashids/hashids": "^2.0.4|~3.0", + "lab404/laravel-auth-checker": "^1.4", "laravel/framework": "^6.0", "laravel/scout": "^7.1", "laravel/tinker": "^1.0", "maatwebsite/excel": "^3.1", + "marceauka/laravel-scout-tntsearch-driver": "^7.2", "nesk/puphpeteer": "^1.6", "norkunas/youtube-dl-php": "^1.3", "predis/predis": "^1.1", - "spatie/valuestore": "^1.2", - "hashids/hashids": "^2.0.4|~3.0", - "marceauka/laravel-scout-tntsearch-driver": "^7.2" + "spatie/valuestore": "^1.2" }, "require-dev": { "facade/ignition": "^1.4", diff --git a/composer.lock b/composer.lock index bf362ee..cf5ce49 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "d5160bf7c9afca7b33c069cd8edec517", + "content-hash": "fedbba17b0cc9c7ab416eaa9f1821a73", "packages": [ { "name": "clue/socket-raw", @@ -820,6 +820,186 @@ "description": "Highlight PHP code in terminal", "time": "2018-09-29T18:48:56+00:00" }, + { + "name": "jaybizzle/crawler-detect", + "version": "v1.2.84", + "source": { + "type": "git", + "url": "https://github.com/JayBizzle/Crawler-Detect.git", + "reference": "b7f35477a56609dd0d753c07ada912b66af3df01" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/JayBizzle/Crawler-Detect/zipball/b7f35477a56609dd0d753c07ada912b66af3df01", + "reference": "b7f35477a56609dd0d753c07ada912b66af3df01", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8|^5.5|^6.5", + "satooshi/php-coveralls": "1.*" + }, + "type": "library", + "autoload": { + "psr-4": { + "Jaybizzle\\CrawlerDetect\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mark Beech", + "email": "m@rkbee.ch", + "role": "Developer" + } + ], + "description": "CrawlerDetect is a PHP class for detecting bots/crawlers/spiders via the user agent", + "homepage": "https://github.com/JayBizzle/Crawler-Detect/", + "keywords": [ + "crawler", + "crawler detect", + "crawler detector", + "crawlerdetect", + "php crawler detect" + ], + "time": "2019-06-14T21:10:21+00:00" + }, + { + "name": "jenssegers/agent", + "version": "v2.6.3", + "source": { + "type": "git", + "url": "https://github.com/jenssegers/agent.git", + "reference": "bcb895395e460478e101f41cdab139c48dc721ce" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/jenssegers/agent/zipball/bcb895395e460478e101f41cdab139c48dc721ce", + "reference": "bcb895395e460478e101f41cdab139c48dc721ce", + "shasum": "" + }, + "require": { + "jaybizzle/crawler-detect": "^1.2", + "mobiledetect/mobiledetectlib": "^2.7.6", + "php": ">=5.6" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^5.0|^6.0|^7.0" + }, + "suggest": { + "illuminate/support": "^4.0|^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + }, + "laravel": { + "providers": [ + "Jenssegers\\Agent\\AgentServiceProvider" + ], + "aliases": { + "Agent": "Jenssegers\\Agent\\Facades\\Agent" + } + } + }, + "autoload": { + "psr-4": { + "Jenssegers\\Agent\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jens Segers", + "homepage": "https://jenssegers.com" + } + ], + "description": "Desktop/mobile user agent parser with support for Laravel, based on Mobiledetect", + "homepage": "https://github.com/jenssegers/agent", + "keywords": [ + "Agent", + "browser", + "desktop", + "laravel", + "mobile", + "platform", + "user agent", + "useragent" + ], + "time": "2019-01-19T21:32:55+00:00" + }, + { + "name": "lab404/laravel-auth-checker", + "version": "1.4.2", + "source": { + "type": "git", + "url": "https://github.com/404labfr/laravel-auth-checker.git", + "reference": "2f3cb283fb4fd6cf50234a56c689a6a8fdf483b1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/404labfr/laravel-auth-checker/zipball/2f3cb283fb4fd6cf50234a56c689a6a8fdf483b1", + "reference": "2f3cb283fb4fd6cf50234a56c689a6a8fdf483b1", + "shasum": "" + }, + "require": { + "jenssegers/agent": "^2.6", + "laravel/framework": "^6.0", + "php": "^7.2" + }, + "require-dev": { + "orchestra/database": "^4.0", + "orchestra/testbench": "^4.0", + "phpunit/phpunit": "^8.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Lab404\\AuthChecker\\AuthCheckerServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Lab404\\AuthChecker\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "404lab", + "email": "web@404lab.fr" + } + ], + "description": "Laravel Auth Checker allows you to log users authentication, devices authenticated from and lock intrusions.", + "keywords": [ + "Authentication", + "IP", + "check", + "device", + "laravel", + "laravel-package", + "laravel-plugin", + "package", + "plugin", + "user" + ], + "time": "2019-09-26T13:29:34+00:00" + }, { "name": "laravel/framework", "version": "v6.0.4", @@ -1477,6 +1657,58 @@ ], "time": "2018-11-04T22:12:12+00:00" }, + { + "name": "mobiledetect/mobiledetectlib", + "version": "2.8.34", + "source": { + "type": "git", + "url": "https://github.com/serbanghita/Mobile-Detect.git", + "reference": "6f8113f57a508494ca36acbcfa2dc2d923c7ed5b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/serbanghita/Mobile-Detect/zipball/6f8113f57a508494ca36acbcfa2dc2d923c7ed5b", + "reference": "6f8113f57a508494ca36acbcfa2dc2d923c7ed5b", + "shasum": "" + }, + "require": { + "php": ">=5.0.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.8.35||~5.7" + }, + "type": "library", + "autoload": { + "classmap": [ + "Mobile_Detect.php" + ], + "psr-0": { + "Detection": "namespaced/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Serban Ghita", + "email": "serbanghita@gmail.com", + "homepage": "http://mobiledetect.net", + "role": "Developer" + } + ], + "description": "Mobile_Detect is a lightweight PHP class for detecting mobile devices. It uses the User-Agent string combined with specific HTTP headers to detect the mobile environment.", + "homepage": "https://github.com/serbanghita/Mobile-Detect", + "keywords": [ + "detect mobile devices", + "mobile", + "mobile detect", + "mobile detector", + "php mobile detect" + ], + "time": "2019-09-18T18:44:20+00:00" + }, { "name": "monolog/monolog", "version": "2.0.0", diff --git a/config/auth-checker.php b/config/auth-checker.php new file mode 100644 index 0000000..a18ab7f --- /dev/null +++ b/config/auth-checker.php @@ -0,0 +1,66 @@ + env('AUTH_CHECKER_THROTTLE', 0), + + /* + |-------------------------------------------------------------------------- + | Device matching attributes + |-------------------------------------------------------------------------- + | + | Declare fields that are used to define if a device is new or not for an + | user. For example, specifying 'platform', 'platform_version' and + | 'browser' will not create a new device if the user already has + | a device registered for these attributes. + | + */ + 'device_matching_attributes' => [ + # Ex: OS X, Windows, ... + 'platform', + # Ex: 10_12_2, 8, ... + 'platform_version', + # Ex: Chrome, Firefox, ... + 'browser', + # Ex: 42.0.2311.135, 37.0, ... + //'browser_version', + ], + + /* + |-------------------------------------------------------------------------- + | User login column + |-------------------------------------------------------------------------- + | + | Declare the name of the column used to authenticate an user. + | By default, it's 'email' but you can change it to your needs. + | + */ + 'login_column' => 'email', + + /* + |-------------------------------------------------------------------------- + | Models + |-------------------------------------------------------------------------- + | + | Customize models used by the package. + | Custom models must extends defaults ones. + | + */ + 'models' => [ + # Ex: App\Models\Device (default: Lab404\AuthChecker\Models\Device) + 'device' => null, + # Ex: App\Models\Login (default: Lab404\AuthChecker\Models\Login) + 'login' => null, + ] + +]; diff --git a/database/migrations/2019_09_26_153342_create_devices_table.php b/database/migrations/2019_09_26_153342_create_devices_table.php new file mode 100644 index 0000000..2aa6d80 --- /dev/null +++ b/database/migrations/2019_09_26_153342_create_devices_table.php @@ -0,0 +1,33 @@ +bigIncrements('id'); + $table->bigInteger('user_id')->unsigned()->index(); + $table->string('platform')->nullable(); + $table->string('platform_version')->nullable(); + $table->string('browser')->nullable(); + $table->string('browser_version')->nullable(); + $table->boolean('is_desktop')->default(0); + $table->boolean('is_mobile')->default(0); + $table->string('language')->nullable(); + $table->boolean('is_trusted')->default(0)->index(); + $table->boolean('is_untrusted')->default(0)->index(); + $table->timestamps(); + + // $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); + }); + } + + public function down() + { + Schema::dropIfExists('devices'); + } +} diff --git a/database/migrations/2019_09_26_153342_create_logins_table.php b/database/migrations/2019_09_26_153342_create_logins_table.php new file mode 100644 index 0000000..73a7c96 --- /dev/null +++ b/database/migrations/2019_09_26_153342_create_logins_table.php @@ -0,0 +1,27 @@ +bigIncrements('id'); + $table->ipAddress('ip_address'); + $table->string('type')->default(\Lab404\AuthChecker\Models\Login::TYPE_LOGIN)->index(); + $table->bigInteger('user_id')->unsigned()->index(); + $table->bigInteger('device_id')->unsigned()->index()->nullable(); + $table->timestamps(); + + // $table->foreign('device_id')->references('id')->on('devices')->onDelete('cascade'); + }); + } + + public function down() + { + Schema::dropIfExists('logins'); + } +} diff --git a/resources/lang/fr.json b/resources/lang/fr.json index 4b95a4b..e1031fb 100644 --- a/resources/lang/fr.json +++ b/resources/lang/fr.json @@ -61,6 +61,7 @@ "Contents": "Contenus", "Session": "Session", "Account": "Compte", + "Logins": "Connexions", "Import": "Importer", "Export": "Exporter", "More": "Plus", @@ -150,6 +151,15 @@ "Youtube-dl binary": "Éxécutable Youtube-dl", "Settings updated!": "Paramètres mis à jour !", + "No logins": "Aucune connexion", + "IP address": "Adresse IP", + "System": "Système", + "Date": "Date", + "Status": "Statut", + "Succeeded": "Réussie", + "Locked": "Bloquée", + "Failed": "Échouée", + "Update account": "Modifier le compte", "Your account has been updated!": "Votre compte a été mis à jour !", "Update password": "Modifier le mot de passe", diff --git a/resources/views/layouts/manage.blade.php b/resources/views/layouts/manage.blade.php index 0d7ab34..c42beb4 100644 --- a/resources/views/layouts/manage.blade.php +++ b/resources/views/layouts/manage.blade.php @@ -17,6 +17,9 @@ {{ __('Tags') }} + {{ __('Logins') }} {{ __('Export') }} diff --git a/resources/views/login-secure.blade.php b/resources/views/login-secure.blade.php index 58afa24..cfdeba0 100644 --- a/resources/views/login-secure.blade.php +++ b/resources/views/login-secure.blade.php @@ -5,7 +5,7 @@
-
{{ __('Secure Login') }}
+
{{ __('Secure login') }}
diff --git a/resources/views/manage/logins.blade.php b/resources/views/manage/logins.blade.php new file mode 100644 index 0000000..329f985 --- /dev/null +++ b/resources/views/manage/logins.blade.php @@ -0,0 +1,64 @@ +@extends('layouts.manage') + +@section('content') +
+
+
+
{{ __('Logins') }}
+ +
+ @if($logins->isEmpty()) +
{{ __('No logins') }}
+ @else +
+ + + + + + + + + + + @foreach($logins as $login) + + + + + + + @endforeach + +
{{ __('IP address') }}{{ __('System') }}{{ __('Date') }}{{ __('Status') }}
+ + {{ $login->ip_address }} + + +
+
+ {{ $login->device->is_mobile ? '📱' : '🖥' }} +
+
+
{{ $login->device->platform }} {{ $login->device->platform_version }}
+
{{ $login->device->browser }} {{ $login->device->browser_version }}
+
+
+
{{ $login->created_at->diffForHumans() }} + @if($login->type === \Lab404\AuthChecker\Models\Login::TYPE_LOGIN) + {{ __('Succeeded') }} + @elseif($login->type === \Lab404\AuthChecker\Models\Login::TYPE_LOCKOUT) + {{ __('Locked') }} + @else + {{ __('Failed') }} + @endif +
+
+ + {{ $logins->links() }} + @endif +
+
+
+
+@endsection diff --git a/resources/views/vendor/pagination/bootstrap-4.blade.php b/resources/views/vendor/pagination/bootstrap-4.blade.php index 28e0e63..3a03574 100644 --- a/resources/views/vendor/pagination/bootstrap-4.blade.php +++ b/resources/views/vendor/pagination/bootstrap-4.blade.php @@ -2,12 +2,12 @@