diff --git a/README.md b/README.md index c101fed..93c023b 100644 --- a/README.md +++ b/README.md @@ -21,9 +21,11 @@ - [Turn ON-OFF](#turn-on-off) - [Views](#visit-monitoring-views) - [Ajax Requests](#ajax-requests) + - [Visit Monitoring Guest Mode](#visit-monitoring-guest-mode) - [Action Monitoring](#action-monitoring) - [Views](#action-monitoring-views) - [Reverse Proxy Config](#action-monitoring-reverse-proxy-config) + - [Action Monitoring Guest Mode](#action-monitoring-guest-mode) - [Authentication Monitoring](#authentication-monitoring) - [Views](#authentication-monitoring-views) - [How to use in big projects](#how-to-use-in-big-projects) @@ -338,6 +340,27 @@ Maybe you may disable record visits for `Ajax` requests, you can use config to d When set to false, Ajax requests will not be recorded. + +### Visit Monitoring Guest Mode + +Determines whether to track and store `visits` for users who are not authenticated (guests). +When set to `true`, the package will also monitor guest user activity. +When set to `false`, only authenticated user visits will be recorded. + +```php +/* + * Configuration settings for visit monitoring. + */ +'visit_monitoring' => [ + ... + + /* + * Determines whether to store `visits` even when the user is not logged in. + */ + 'guest_mode' => true, +], +``` + ## Action Monitoring @@ -385,48 +408,70 @@ If you want to disable some actions like created, you can use the config file: ![Action Monitoring Preview](/art/actions-monitoring/preview.png "Action Monitoring") - -## Authentication Monitoring + +### Action Monitoring Reverse Proxy Config -Have you ever thought about monitoring the entry and exit of users of your application? Now you can :)
-If you want to monitor users when logging in or logout of your application, you need to migrate the migrations to the config file and change true for monitoring authentication. +If you are using Reverse Proxy (Nginx or Cloudflare), you can use config to get real IP from a specific header like `X-Real-IP` or `X-Forwarded-For`: ```php -'authentication_monitoring' => [ +'action_monitoring' => [ ... /* - * Enable or disable monitoring of user login and logout events. - * Set to true to track these actions, or false to disable. + * If your application is behind a reverse proxy (e.g., Nginx or Cloudflare), + * enable this setting to fetch the real client IP from the proxy headers. */ - 'on_login' => true, - 'on_logout' => true, + 'use_reverse_proxy_ip' => false, + + /* + * The header used by reverse proxies to forward the real client IP. + * Common values are 'X-Forwarded-For' or 'X-Real-IP'. + */ + 'real_ip_header' => 'X-Forwarded-For', ], ``` - -### Action Monitoring Reverse Proxy Config + +### Action Monitoring Guest Mode -If you are using Reverse Proxy (Nginx or Cloudflare), you can use config to get real IP from a specific header like `X-Real-IP` or `X-Forwarded-For`: +Determines whether to track and store `actions` for users who are not authenticated (guests). +When set to `true`, the package will also monitor guest user activity. +When set to `false`, only authenticated user visits will be recorded. ```php +/* + * Configuration settings for action monitoring. + */ 'action_monitoring' => [ ... /* - * If your application is behind a reverse proxy (e.g., Nginx or Cloudflare), - * enable this setting to fetch the real client IP from the proxy headers. + * Determines whether to store `actions` even when the user is not logged in. */ - 'use_reverse_proxy_ip' => false, + 'guest_mode' => true, +], +``` + + +## Authentication Monitoring + +Have you ever thought about monitoring the entry and exit of users of your application? Now you can :)
+If you want to monitor users when logging in or logout of your application, you need to migrate the migrations to the config file and change true for monitoring authentication. + +```php +'authentication_monitoring' => [ + ... /* - * The header used by reverse proxies to forward the real client IP. - * Common values are 'X-Forwarded-For' or 'X-Real-IP'. + * Enable or disable monitoring of user login and logout events. + * Set to true to track these actions, or false to disable. */ - 'real_ip_header' => 'X-Forwarded-For', + 'on_login' => true, + 'on_logout' => true, ], ``` + ### Authentication Monitoring Views diff --git a/config/user-monitoring.php b/config/user-monitoring.php index fa1c932..2c9fae4 100644 --- a/config/user-monitoring.php +++ b/config/user-monitoring.php @@ -93,6 +93,11 @@ * https://laravel.com/docs/scheduling */ 'delete_days' => 0, + + /* + * Determines whether to store `visits` even when the user is not logged in. + */ + 'guest_mode' => true, ], /* @@ -126,6 +131,11 @@ * Common values are 'X-Forwarded-For' or 'X-Real-IP'. */ 'real_ip_header' => 'X-Forwarded-For', + + /* + * Determines whether to store `actions` even when the user is not logged in. + */ + 'guest_mode' => true, ], /* diff --git a/src/Middlewares/VisitMonitoringMiddleware.php b/src/Middlewares/VisitMonitoringMiddleware.php index 1c2a34f..c95950a 100644 --- a/src/Middlewares/VisitMonitoringMiddleware.php +++ b/src/Middlewares/VisitMonitoringMiddleware.php @@ -21,6 +21,9 @@ public function handle(Request $request, Closure $next): mixed if (config('user-monitoring.visit_monitoring.ajax_requests', false) === false && $request->ajax()) { return $next($request); } + if (!config('user-monitoring.visit_monitoring.guest_mode', true) && is_null(UserUtils::getUserId())) { + return $next($request); + } $detector = new Detector(); $exceptPages = config('user-monitoring.visit_monitoring.except_pages', []); diff --git a/src/Providers/LaravelUserMonitoringEventServiceProvider.php b/src/Providers/LaravelUserMonitoringEventServiceProvider.php index 50adb36..553fb25 100644 --- a/src/Providers/LaravelUserMonitoringEventServiceProvider.php +++ b/src/Providers/LaravelUserMonitoringEventServiceProvider.php @@ -14,7 +14,7 @@ class LaravelUserMonitoringEventServiceProvider extends EventServiceProvider { public function boot(): void { - $detector = new Detector(); + $detector = new Detector; $table = config('user-monitoring.authentication_monitoring.table'); // Login Event diff --git a/src/Traits/Actionable.php b/src/Traits/Actionable.php index fac1c9a..be0a177 100644 --- a/src/Traits/Actionable.php +++ b/src/Traits/Actionable.php @@ -16,6 +16,10 @@ protected static function boot(): void { parent::boot(); + if (!config('user-monitoring.action_monitoring.guest_mode', true) && is_null(UserUtils::getUserId())) { + return; + } + if (config('user-monitoring.action_monitoring.on_store', false)) { static::created(function (mixed $model) { static::insertActionMonitoring($model, ActionType::ACTION_STORE); @@ -87,7 +91,7 @@ private static function insertActionMonitoring(mixed $model, string $actionType) private static function getRealIP(): string { return config('user-monitoring.use_reverse_proxy_ip') - ? request()->header(config('user-monitoring.real_ip_header')) ?: request()->ip() + ? request()->header(config('user-monitoring.real_ip_header')) : request()->ip(); } } diff --git a/tests/Feature/ActionMonitoringTest.php b/tests/Feature/ActionMonitoringTest.php index 3096c12..d7f9092 100644 --- a/tests/Feature/ActionMonitoringTest.php +++ b/tests/Feature/ActionMonitoringTest.php @@ -6,6 +6,7 @@ use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Support\Facades\DB; use Tests\SetUp\Models\Product; +use Tests\SetUp\Models\ProductSoftDelete; use function Pest\Laravel\{assertDatabaseCount, assertDatabaseHas}; /* @@ -226,7 +227,7 @@ $user = createUser(); auth()->login($user); - $product = \Tests\SetUp\Models\ProductSoftDelete::query()->create([ + $product = ProductSoftDelete::query()->create([ 'title' => 'milwad', 'description' => 'WE ARE HELPING TO OPEN-SOURCE WORLD' ]); @@ -252,7 +253,7 @@ $user = createUser(); auth()->login($user); - $product = \Tests\SetUp\Models\ProductSoftDelete::query()->create([ + $product = ProductSoftDelete::query()->create([ 'title' => 'milwad', 'description' => 'WE ARE HELPING TO OPEN-SOURCE WORLD' ]); @@ -302,3 +303,61 @@ expect($actionMonitoring->getTypeColor())->toBe($colors[$type]); } }); + +test('action not stored when the guest mode is off and user not logged in', function () { + config()->set('user-monitoring.action_monitoring.guest_mode', false); + + $product = Product::query()->create([ + 'title' => 'milwad', + 'description' => 'WE ARE HELPING TO OPEN-SOURCE WORLD' + ]); + $product->delete(); + + // DB Assertions + assertDatabaseCount(config('user-monitoring.action_monitoring.table'), 0); +}); + +test('action stored when the guest mode is on and user not logged in', function () { + config()->set('user-monitoring.action_monitoring.guest_mode', true); + + $product = Product::query()->create([ + 'title' => 'milwad', + 'description' => 'WE ARE HELPING TO OPEN-SOURCE WORLD' + ]); + $product->delete(); + + // DB Assertions + assertDatabaseCount(config('user-monitoring.action_monitoring.table'), 2); +}); + +test('action stored when the guest mode is off and user logged in', function () { + config()->set('user-monitoring.action_monitoring.guest_mode', false); + + $user = createUser(); + auth()->login($user); + + $product = Product::query()->create([ + 'title' => 'milwad', + 'description' => 'WE ARE HELPING TO OPEN-SOURCE WORLD' + ]); + $product->delete(); + + // DB Assertions + assertDatabaseCount(config('user-monitoring.action_monitoring.table'), 2); +}); + +test('action stored when the guest mode is on and user logged in', function () { + config()->set('user-monitoring.action_monitoring.guest_mode', true); + + $user = createUser(); + auth()->login($user); + + $product = Product::query()->create([ + 'title' => 'milwad', + 'description' => 'WE ARE HELPING TO OPEN-SOURCE WORLD' + ]); + $product->delete(); + + // DB Assertions + assertDatabaseCount(config('user-monitoring.action_monitoring.table'), 2); +}); diff --git a/tests/Feature/VisitMonitoringTest.php b/tests/Feature/VisitMonitoringTest.php index 91c4433..5e8f532 100644 --- a/tests/Feature/VisitMonitoringTest.php +++ b/tests/Feature/VisitMonitoringTest.php @@ -62,7 +62,6 @@ // Ajax test('visit monitoring store ajax requests', function () { - \Pest\Laravel\withoutExceptionHandling(); get('/', ['X-Requested-With' => 'XMLHttpRequest']); // DB Assertions @@ -80,12 +79,53 @@ assertDatabaseMissing(config('user-monitoring.visit_monitoring.table'), ['page' => 'http:\/\/localhost']); }); +test('visit monitoring skip store when guest mode is off and user not logged in', function () { + config()->set('user-monitoring.visit_monitoring.guest_mode', false); + + $response = get('/'); + $response->assertContent('milwad'); + + // DB Assertions + assertDatabaseCount(config('user-monitoring.visit_monitoring.table'), 0); + assertDatabaseMissing(config('user-monitoring.visit_monitoring.table'), ['page' => 'http:\/\/localhost']); +}); + +test('visit monitoring store when guest mode is off and user logged in', function () { + config()->set('user-monitoring.visit_monitoring.guest_mode', false); + + $user = createUser(); + $response = actingAs($user)->get('/'); + $response->assertContent('milwad'); + + // DB Assertions + assertDatabaseCount(config('user-monitoring.visit_monitoring.table'), 1); +}); + +test('visit monitoring store when guest mode is on and user logged in', function () { + config()->set('user-monitoring.visit_monitoring.guest_mode', true); + + $user = createUser(); + $response = actingAs($user)->get('/'); + $response->assertContent('milwad'); + + // DB Assertions + assertDatabaseCount(config('user-monitoring.visit_monitoring.table'), 1); +}); + +test('visit monitoring store when guest mode is on and user not logged in', function () { + config()->set('user-monitoring.visit_monitoring.guest_mode', true); + + $response = get('/'); + $response->assertContent('milwad'); + + // DB Assertions + assertDatabaseCount(config('user-monitoring.visit_monitoring.table'), 1); +}); + /** - * Create user. - * - * @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model + * Create user and return it. */ -function createUser() +function createUser(): \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model { return User::query()->create([ 'name' => 'milwad',