diff --git a/app/Http/Controllers/Api/SettingsController.php b/app/Http/Controllers/Api/SettingsController.php index 2a4b757674..3d2723f8d8 100644 --- a/app/Http/Controllers/Api/SettingsController.php +++ b/app/Http/Controllers/Api/SettingsController.php @@ -11,6 +11,8 @@ use Mail; use App\Notifications\SlackTest; use Notification; use App\Notifications\MailTest; +use App\Http\Transformers\LoginAttemptsTransformer; +use DB; class SettingsController extends Controller { @@ -143,6 +145,30 @@ class SettingsController extends Controller } + /** + * Get a list of login attempts + * + * @author [A. Gianotto] [] + * @since [v5.0.0] + * @param \Illuminate\Http\Request $request + * @return array + */ + public function showLoginAttempts(Request $request) + { + $allowed_columns = ['id', 'username', 'remote_ip', 'user_agent','successful','created_at']; + + $login_attempts = DB::table('login_attempts'); + $order = $request->input('order') === 'asc' ? 'asc' : 'desc'; + $sort = in_array($request->get('sort'), $allowed_columns) ? $request->get('sort') : 'created_at'; + + $total = $login_attempts->count(); + $login_attempts->orderBy($sort, $order); + $login_attempt_results = $login_attempts->skip(request('offset', 0))->take(request('limit', 20))->get(); + + return (new LoginAttemptsTransformer)->transformLoginAttempts($login_attempt_results, $total); + + } + } diff --git a/app/Http/Controllers/SettingsController.php b/app/Http/Controllers/SettingsController.php index 73f9720948..80ec5a4c64 100755 --- a/app/Http/Controllers/SettingsController.php +++ b/app/Http/Controllers/SettingsController.php @@ -1103,4 +1103,8 @@ class SettingsController extends Controller } } + + public function getLoginAttempts() { + return view('settings.logins'); + } } diff --git a/app/Http/Transformers/LoginAttemptsTransformer.php b/app/Http/Transformers/LoginAttemptsTransformer.php new file mode 100644 index 0000000000..ca6d7ffbe0 --- /dev/null +++ b/app/Http/Transformers/LoginAttemptsTransformer.php @@ -0,0 +1,42 @@ +transformDatatables($array, $total); + } + + public function transformLoginAttempt($login_attempt) + { + + if ($login_attempt) { + $array = [ + 'id' => (int) $login_attempt->id, + 'username' => e($login_attempt->username), + 'user_agent' => e($login_attempt->user_agent), + 'remote_ip' => (!config('app.lock_passwords')) ? e($login_attempt->remote_ip) : '--', + 'successful' => e($login_attempt->successful), + 'created_at' => Helper::getFormattedDateObject($login_attempt->created_at, 'datetime'), + ]; + return $array; + } + + + } + + + +} diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 1df4cf892e..336d5b1d9e 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -2,6 +2,11 @@ "requires": true, "lockfileVersion": 1, "dependencies": { + "@fortawesome/fontawesome-free": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-5.2.0.tgz", + "integrity": "sha512-4pgStJx9UmydKc7wwF6Xjw4dFqzUnQejeuP2aUNHWazayWbmMbrx5rieN9+oob4bUwkf1thS3am0Ko+uhFHpNA==" + }, "@sindresorhus/is": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz", @@ -462,7 +467,7 @@ "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "requires": { "ms": "2.0.0" @@ -2242,7 +2247,7 @@ "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "requires": { "ms": "2.0.0" @@ -5645,7 +5650,7 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", "dev": true }, "uglify-js": { @@ -9116,7 +9121,7 @@ "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "integrity": "sha1-QfuyAkPlCxK+DwS43tvwdSDOhB0=", "dev": true, "requires": { "color-convert": "1.9.1" @@ -9136,7 +9141,7 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", "dev": true }, "supports-color": { @@ -9479,7 +9484,7 @@ "postcss": { "version": "5.2.18", "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "integrity": "sha1-ut+hSX1GJE9jkPWLMZgw2RB4U8U=", "dev": true, "requires": { "chalk": "1.1.3", @@ -9558,7 +9563,7 @@ "schema-utils": { "version": "0.4.5", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.5.tgz", - "integrity": "sha512-yYrjb9TX2k/J1Y5UNy3KYdZq10xhYcF8nMpAW6o3hy6Q8WSIEf9lJHG/ePnOBfziPM3fvQwfOwa13U/Fh8qTfA==", + "integrity": "sha1-IYNvBgiqwXt4+ePiTa/xSlyhOj4=", "dev": true, "requires": { "ajv": "6.4.0", @@ -12449,13 +12454,13 @@ "commander": { "version": "2.13.0", "resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz", - "integrity": "sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==", + "integrity": "sha1-aWS8pnaF33wfFDDFhPB9dZeIW5w=", "dev": true }, "schema-utils": { "version": "0.4.5", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.5.tgz", - "integrity": "sha512-yYrjb9TX2k/J1Y5UNy3KYdZq10xhYcF8nMpAW6o3hy6Q8WSIEf9lJHG/ePnOBfziPM3fvQwfOwa13U/Fh8qTfA==", + "integrity": "sha1-IYNvBgiqwXt4+ePiTa/xSlyhOj4=", "dev": true, "requires": { "ajv": "6.4.0", @@ -12465,13 +12470,13 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", "dev": true }, "uglify-es": { "version": "3.3.9", "resolved": "https://registry.npmjs.org/uglify-es/-/uglify-es-3.3.9.tgz", - "integrity": "sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ==", + "integrity": "sha1-DBxPBwC+2NvBJM2zBNJZLKID5nc=", "dev": true, "requires": { "commander": "2.13.0", @@ -12945,7 +12950,7 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", "dev": true } } diff --git a/package.json b/package.json index 27a862d458..0f6c1019d8 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "vue-template-compiler": "2.4.4" }, "dependencies": { + "@fortawesome/fontawesome-free": "^5.2.0", "blueimp-file-upload": "^9.18.0", "bootstrap": "^3.3.7", "bootstrap-colorpicker": "^2.5.1", diff --git a/resources/views/settings/index.blade.php b/resources/views/settings/index.blade.php index c17f4013b9..9007abd3c8 100755 --- a/resources/views/settings/index.blade.php +++ b/resources/views/settings/index.blade.php @@ -151,6 +151,17 @@ +
+
+
+ +
+ Login Attempts +

List of logins

+
+
+
+
diff --git a/resources/views/settings/logins.blade.php b/resources/views/settings/logins.blade.php new file mode 100644 index 0000000000..0812340d4a --- /dev/null +++ b/resources/views/settings/logins.blade.php @@ -0,0 +1,54 @@ +@extends('layouts/default') + +{{-- Page title --}} +@section('title') + Attempted Logins + @parent +@stop + +{{-- Page content --}} +@section('content') + +
+
+
+
+ + + + + + + + + + + + +
UsernameLogin AttemptUser AgentIPSuccess
+
+
+
+
+@stop + + +@section('moar_scripts') + @include ('partials.bootstrap-table') +@stop diff --git a/resources/views/vendor/mail/html/themes/default.css b/resources/views/vendor/mail/html/themes/default.css index 7411166383..1949363b08 100644 --- a/resources/views/vendor/mail/html/themes/default.css +++ b/resources/views/vendor/mail/html/themes/default.css @@ -186,8 +186,8 @@ img { .table td { color: #74787E; font-size: 15px; - line-height: 18px; - padding: 10px 0; + line-height: 15px; + padding: 8px 0; } .content-cell { diff --git a/routes/api.php b/routes/api.php index c66c388820..d23adb046c 100644 --- a/routes/api.php +++ b/routes/api.php @@ -555,6 +555,13 @@ Route::group(['prefix' => 'v1','namespace' => 'Api'], function () { 'uses' => 'SettingsController@ldaptest' ]); + Route::get('settings/login-attempts', [ + 'middleware' => ['auth', 'authorize:superuser'], + 'as' => 'api.settings.login_attempts', + 'uses' => 'SettingsController@showLoginAttempts' + ]); + + Route::post('settings/ldaptestlogin', [ 'as' => 'api.settings.ldaptestlogin', 'uses' => 'SettingsController@ldaptestlogin' diff --git a/routes/web.php b/routes/web.php index 7ee5f6f3d0..20974f5f80 100644 --- a/routes/web.php +++ b/routes/web.php @@ -166,6 +166,8 @@ Route::group([ 'prefix' => 'admin','middleware' => ['auth', 'authorize:superuser Route::get('purge', ['as' => 'settings.purge.index', 'uses' => 'SettingsController@getPurge']); Route::post('purge', ['as' => 'settings.purge.save', 'uses' => 'SettingsController@postPurge']); + Route::get('login-attempts', ['as' => 'settings.logins.index','uses' => 'SettingsController@getLoginAttempts' ]); + # Backups Route::group([ 'prefix' => 'backups', 'middleware' => 'auth' ], function () {