From 6d1f934d369c32e66cfbadda5079398dc2710ae6 Mon Sep 17 00:00:00 2001 From: Pinga <121483313+getpinga@users.noreply.github.com> Date: Fri, 5 Jan 2024 14:18:40 +0200 Subject: [PATCH] Added user audit details in panel --- automation/audit.json | 4 ++ cp/app/Auth/Auth.php | 17 +++++ cp/app/Controllers/Auth/AuthController.php | 38 ++++++++++- cp/app/Controllers/ProfileController.php | 25 ++++++- cp/bootstrap/helper.php | 29 +++++++++ cp/resources/views/admin/profile/profile.twig | 65 +++++++++++++++---- database/registry.mariadb.sql | 22 +++++-- database/registry.postgres.sql | 22 +++++-- 8 files changed, 197 insertions(+), 25 deletions(-) diff --git a/automation/audit.json b/automation/audit.json index bd39c78..e44ecaa 100644 --- a/automation/audit.json +++ b/automation/audit.json @@ -204,6 +204,10 @@ "audit": true, "skip": null }, + "users_audit": { + "audit": true, + "skip": null + }, "users_confirmations": { "audit": null, "skip": null diff --git a/cp/app/Auth/Auth.php b/cp/app/Auth/Auth.php index 3017b7a..ae1643d 100644 --- a/cp/app/Auth/Auth.php +++ b/cp/app/Auth/Auth.php @@ -277,6 +277,23 @@ class Auth public static function changeCurrentPassword($oldPassword, $newPassword){ $auth = self::$auth; try { + global $container; + $db = $container->get('db'); + $currentDateTime = new \DateTime(); + $currentDate = $currentDateTime->format('Y-m-d H:i:s.v'); // Current timestamp + $db->insert( + 'users_audit', + [ + 'user_id' => $_SESSION['auth_user_id'], + 'user_event' => 'user.update.password', + 'user_resource' => 'control.panel', + 'user_agent' => $_SERVER['HTTP_USER_AGENT'], + 'user_ip' => get_client_ip(), + 'user_location' => get_client_location(), + 'event_time' => $currentDate, + 'user_data' => null + ] + ); $auth->changePassword($oldPassword, $newPassword); redirect()->route('profile')->with('success','Password has been changed'); } diff --git a/cp/app/Controllers/Auth/AuthController.php b/cp/app/Controllers/Auth/AuthController.php index 916d919..b4e3a2e 100644 --- a/cp/app/Controllers/Auth/AuthController.php +++ b/cp/app/Controllers/Auth/AuthController.php @@ -59,6 +59,8 @@ class AuthController extends Controller * @throws \Pinga\Auth\AuthError */ public function login(Request $request, Response $response){ + global $container; + $data = $request->getParsedBody(); if(isset($data['remember'])){ $remember = $data['remember']; @@ -71,8 +73,25 @@ class AuthController extends Controller $code = null; } $login = Auth::login($data['email'], $data['password'], $remember, $code); - if($login===true) + if($login===true) { + $db = $container->get('db'); + $currentDateTime = new \DateTime(); + $currentDate = $currentDateTime->format('Y-m-d H:i:s.v'); // Current timestamp + $db->insert( + 'users_audit', + [ + 'user_id' => $_SESSION['auth_user_id'], + 'user_event' => 'user.login', + 'user_resource' => 'control.panel', + 'user_agent' => $_SERVER['HTTP_USER_AGENT'], + 'user_ip' => get_client_ip(), + 'user_location' => get_client_location(), + 'event_time' => $currentDate, + 'user_data' => null + ] + ); redirect()->route('home'); + } } /** @@ -80,6 +99,23 @@ class AuthController extends Controller */ public function logout() { + global $container; + $db = $container->get('db'); + $currentDateTime = new \DateTime(); + $currentDate = $currentDateTime->format('Y-m-d H:i:s.v'); // Current timestamp + $db->insert( + 'users_audit', + [ + 'user_id' => $_SESSION['auth_user_id'], + 'user_event' => 'user.logout', + 'user_resource' => 'control.panel', + 'user_agent' => $_SERVER['HTTP_USER_AGENT'], + 'user_ip' => get_client_ip(), + 'user_location' => get_client_location(), + 'event_time' => $currentDate, + 'user_data' => null + ] + ); Auth::logout(); redirect()->route('login'); } diff --git a/cp/app/Controllers/ProfileController.php b/cp/app/Controllers/ProfileController.php index dad0ad8..fd2c1b6 100644 --- a/cp/app/Controllers/ProfileController.php +++ b/cp/app/Controllers/ProfileController.php @@ -73,12 +73,16 @@ class ProfileController extends Controller 'SELECT * FROM users_webauthn WHERE user_id = ?', [$userId] ); + $user_audit = $db->select( + 'SELECT * FROM users_audit WHERE user_id = ? ORDER BY event_time DESC', + [$userId] + ); if ($is_2fa_activated) { - return view($response,'admin/profile/profile.twig',['email' => $email, 'username' => $username, 'status' => $status, 'role' => $role, 'csrf_name' => $csrfName, 'csrf_value' => $csrfValue]); + return view($response,'admin/profile/profile.twig',['email' => $email, 'username' => $username, 'status' => $status, 'role' => $role, 'csrf_name' => $csrfName, 'csrf_value' => $csrfValue, 'userAudit' => $user_audit]); } else if ($is_weba_activated) { - return view($response,'admin/profile/profile.twig',['email' => $email, 'username' => $username, 'status' => $status, 'role' => $role, 'qrcodeDataUri' => $qrcodeDataUri, 'secret' => $secret, 'csrf_name' => $csrfName, 'csrf_value' => $csrfValue, 'weba' => $is_weba_activated]); + return view($response,'admin/profile/profile.twig',['email' => $email, 'username' => $username, 'status' => $status, 'role' => $role, 'qrcodeDataUri' => $qrcodeDataUri, 'secret' => $secret, 'csrf_name' => $csrfName, 'csrf_value' => $csrfValue, 'weba' => $is_weba_activated, 'userAudit' => $user_audit]); } else { - return view($response,'admin/profile/profile.twig',['email' => $email, 'username' => $username, 'status' => $status, 'role' => $role, 'qrcodeDataUri' => $qrcodeDataUri, 'secret' => $secret, 'csrf_name' => $csrfName, 'csrf_value' => $csrfValue]); + return view($response,'admin/profile/profile.twig',['email' => $email, 'username' => $username, 'status' => $status, 'role' => $role, 'qrcodeDataUri' => $qrcodeDataUri, 'secret' => $secret, 'csrf_name' => $csrfName, 'csrf_value' => $csrfValue, 'userAudit' => $user_audit]); } } @@ -114,6 +118,21 @@ class ProfileController extends Controller } try { + $currentDateTime = new \DateTime(); + $currentDate = $currentDateTime->format('Y-m-d H:i:s.v'); // Current timestamp + $db->insert( + 'users_audit', + [ + 'user_id' => $_SESSION['auth_user_id'], + 'user_event' => 'user.enable.2fa', + 'user_resource' => 'control.panel', + 'user_agent' => $_SERVER['HTTP_USER_AGENT'], + 'user_ip' => get_client_ip(), + 'user_location' => get_client_location(), + 'event_time' => $currentDate, + 'user_data' => null + ] + ); $db->update( 'users', [ diff --git a/cp/bootstrap/helper.php b/cp/bootstrap/helper.php index cf4fde0..6078694 100644 --- a/cp/bootstrap/helper.php +++ b/cp/bootstrap/helper.php @@ -396,4 +396,33 @@ function createUuidFromId($id) { // Handle exception return null; } +} + +// Function to get the client IP address +function get_client_ip() { + $ipaddress = ''; + if (getenv('HTTP_CLIENT_IP')) + $ipaddress = getenv('HTTP_CLIENT_IP'); + else if(getenv('HTTP_X_FORWARDED_FOR')) + $ipaddress = getenv('HTTP_X_FORWARDED_FOR'); + else if(getenv('HTTP_X_FORWARDED')) + $ipaddress = getenv('HTTP_X_FORWARDED'); + else if(getenv('HTTP_FORWARDED_FOR')) + $ipaddress = getenv('HTTP_FORWARDED_FOR'); + else if(getenv('HTTP_FORWARDED')) + $ipaddress = getenv('HTTP_FORWARDED'); + else if(getenv('REMOTE_ADDR')) + $ipaddress = getenv('REMOTE_ADDR'); + else + $ipaddress = 'UNKNOWN'; + return $ipaddress; +} + +function get_client_location() { + $PublicIP = get_client_ip(); + $json = file_get_contents("http://ipinfo.io/$PublicIP/geo"); + $json = json_decode($json, true); + $country = $json['country']; + + return $country; } \ No newline at end of file diff --git a/cp/resources/views/admin/profile/profile.twig b/cp/resources/views/admin/profile/profile.twig index f9f336d..bab419d 100644 --- a/cp/resources/views/admin/profile/profile.twig +++ b/cp/resources/views/admin/profile/profile.twig @@ -36,6 +36,9 @@
Track and review all user activities in your account below. Monitor logins, profile changes, and other key actions to ensure security and transparency.
+Event | +User Agent | +IP | +Location | +Timestamp | +
---|---|---|---|---|
{{ user.user_event }} | +{{ user.user_agent }} | +{{ user.user_ip }} | +{{ user.user_location }} | +{{ user.event_time }} | +
No log data for user. | +