From 8881ca55665e1993b485314a21c37c2d6a8f1942 Mon Sep 17 00:00:00 2001 From: Milwad <98118400+milwad-dev@users.noreply.github.com> Date: Fri, 5 Sep 2025 12:38:42 +0330 Subject: [PATCH 01/13] Update VisitMonitoringMiddleware.php --- src/Middlewares/VisitMonitoringMiddleware.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Middlewares/VisitMonitoringMiddleware.php b/src/Middlewares/VisitMonitoringMiddleware.php index c95950a..003794e 100644 --- a/src/Middlewares/VisitMonitoringMiddleware.php +++ b/src/Middlewares/VisitMonitoringMiddleware.php @@ -25,7 +25,7 @@ public function handle(Request $request, Closure $next): mixed return $next($request); } - $detector = new Detector(); + $detector = new Detector; $exceptPages = config('user-monitoring.visit_monitoring.except_pages', []); if (empty($exceptPages) || !$this->checkIsExceptPages($request->path(), $exceptPages)) { From b8dd238cbf363c399470b4040a0696eb797bbd37 Mon Sep 17 00:00:00 2001 From: Milwad <98118400+milwad-dev@users.noreply.github.com> Date: Fri, 5 Sep 2025 12:41:43 +0330 Subject: [PATCH 02/13] Create MonitoringCondition.php --- src/Contracts/MonitoringCondition.php | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 src/Contracts/MonitoringCondition.php diff --git a/src/Contracts/MonitoringCondition.php b/src/Contracts/MonitoringCondition.php new file mode 100644 index 0000000..a516925 --- /dev/null +++ b/src/Contracts/MonitoringCondition.php @@ -0,0 +1,10 @@ + Date: Fri, 5 Sep 2025 12:46:26 +0330 Subject: [PATCH 03/13] Update user-monitoring.php --- config/user-monitoring.php | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/config/user-monitoring.php b/config/user-monitoring.php index 2c9fae4..011845b 100644 --- a/config/user-monitoring.php +++ b/config/user-monitoring.php @@ -98,6 +98,26 @@ * Determines whether to store `visits` even when the user is not logged in. */ 'guest_mode' => true, + + /* + | Here you can define one or more conditions that determine whether a visit + | should be logged. Each condition must return a boolean (true = log visit, + | false = skip logging). + | + | All conditions are evaluated before monitoring. If any condition returns + | false, the visit will NOT be recorded. + | + | Supported formats: + | + | 1. Class name (must implement MonitoringCondition interface): + | \App\Monitoring\YourCustomCondition::class + | + | 2. Closure / callback (receives the current Request and authenticated user): + | function (Request $request, $user) { + | return $user && $user->isAdmin(); + | } + */ + 'conditions' => [], ], /* From 892ed8d2139884c633cfd854e466b2ada54e5c77 Mon Sep 17 00:00:00 2001 From: Milwad <98118400+milwad-dev@users.noreply.github.com> Date: Fri, 5 Sep 2025 12:47:56 +0330 Subject: [PATCH 04/13] Update VisitMonitoringMiddleware.php --- src/Middlewares/VisitMonitoringMiddleware.php | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/Middlewares/VisitMonitoringMiddleware.php b/src/Middlewares/VisitMonitoringMiddleware.php index 003794e..65b8e35 100644 --- a/src/Middlewares/VisitMonitoringMiddleware.php +++ b/src/Middlewares/VisitMonitoringMiddleware.php @@ -2,6 +2,7 @@ namespace Binafy\LaravelUserMonitoring\Middlewares; +use Binafy\LaravelUserMonitoring\Contracts\MonitoringCondition; use Binafy\LaravelUserMonitoring\Utills\Detector; use Binafy\LaravelUserMonitoring\Utills\UserUtils; use Closure; @@ -25,6 +26,11 @@ public function handle(Request $request, Closure $next): mixed return $next($request); } + // Custom conditions from config + if (! $this->shouldMonitor($request)) { + return $next($request); + } + $detector = new Detector; $exceptPages = config('user-monitoring.visit_monitoring.except_pages', []); @@ -53,4 +59,30 @@ protected function checkIsExceptPages(string $page, array $exceptPages): bool { return collect($exceptPages)->contains($page); } + + /** + * Determine if monitoring should be performed for the given request and user. + */ + protected function shouldMonitor(Request $request): bool + { + $config = config('user-monitoring.visit_monitoring.conditions', []); + + foreach ($config as $condition) { + if (is_callable($condition)) { + if (! $condition($request)) { + return false; + } + } elseif (is_string($condition)) { + $instance = new $condition; + if (! $instance instanceof MonitoringCondition) { + continue; + } + if (! $instance->shouldMonitor($request)) { + return false; + } + } + } + + return true; + } } From 482c905cb5a562d3a2694aeeaa37e1b5735aee6d Mon Sep 17 00:00:00 2001 From: Milwad <98118400+milwad-dev@users.noreply.github.com> Date: Fri, 5 Sep 2025 12:48:23 +0330 Subject: [PATCH 05/13] Update user-monitoring.php --- config/user-monitoring.php | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/config/user-monitoring.php b/config/user-monitoring.php index 011845b..ca28e76 100644 --- a/config/user-monitoring.php +++ b/config/user-monitoring.php @@ -106,16 +106,6 @@ | | All conditions are evaluated before monitoring. If any condition returns | false, the visit will NOT be recorded. - | - | Supported formats: - | - | 1. Class name (must implement MonitoringCondition interface): - | \App\Monitoring\YourCustomCondition::class - | - | 2. Closure / callback (receives the current Request and authenticated user): - | function (Request $request, $user) { - | return $user && $user->isAdmin(); - | } */ 'conditions' => [], ], From c86ff71f57eb8f6ed92fcf5acaa1039797f33d36 Mon Sep 17 00:00:00 2001 From: Milwad <98118400+milwad-dev@users.noreply.github.com> Date: Fri, 5 Sep 2025 12:49:06 +0330 Subject: [PATCH 06/13] Update user-monitoring.php --- config/user-monitoring.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/config/user-monitoring.php b/config/user-monitoring.php index ca28e76..158cfc3 100644 --- a/config/user-monitoring.php +++ b/config/user-monitoring.php @@ -146,6 +146,13 @@ * Determines whether to store `actions` even when the user is not logged in. */ 'guest_mode' => true, + + /* + * Here you can define one or more conditions that determine whether an action + * should be logged. Each condition must return a boolean (true = log action, + * false = skip logging). + */ + 'conditions' => [], ], /* From 671533dd87430d57544a22367cf10a77007241ca Mon Sep 17 00:00:00 2001 From: Milwad <98118400+milwad-dev@users.noreply.github.com> Date: Fri, 5 Sep 2025 12:50:45 +0330 Subject: [PATCH 07/13] Update Actionable.php --- src/Traits/Actionable.php | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/Traits/Actionable.php b/src/Traits/Actionable.php index be0a177..8a5f7dc 100644 --- a/src/Traits/Actionable.php +++ b/src/Traits/Actionable.php @@ -2,9 +2,11 @@ namespace Binafy\LaravelUserMonitoring\Traits; +use Binafy\LaravelUserMonitoring\Contracts\MonitoringCondition; use Binafy\LaravelUserMonitoring\Utills\ActionType; use Binafy\LaravelUserMonitoring\Utills\Detector; use Binafy\LaravelUserMonitoring\Utills\UserUtils; +use Illuminate\Http\Request; use Illuminate\Support\Facades\DB; trait Actionable @@ -20,6 +22,11 @@ protected static function boot(): void return; } + // Custom conditions from config + if (! static::shouldMonitor(request())) { + return; + } + if (config('user-monitoring.action_monitoring.on_store', false)) { static::created(function (mixed $model) { static::insertActionMonitoring($model, ActionType::ACTION_STORE); @@ -94,4 +101,30 @@ private static function getRealIP(): string ? request()->header(config('user-monitoring.real_ip_header')) : request()->ip(); } + + /** + * Determine if monitoring should be performed for the given request and user. + */ + protected static function shouldMonitor(Request $request): bool + { + $config = config('user-monitoring.action_monitoring.conditions', []); + + foreach ($config as $condition) { + if (is_callable($condition)) { + if (! $condition($request)) { + return false; + } + } elseif (is_string($condition)) { + $instance = new $condition; + if (! $instance instanceof MonitoringCondition) { + continue; + } + if (! $instance->shouldMonitor($request)) { + return false; + } + } + } + + return true; + } } From 2b5c9f8906189a2a33f02abfb32df3aba1a4d3f8 Mon Sep 17 00:00:00 2001 From: Milwad <98118400+milwad-dev@users.noreply.github.com> Date: Fri, 5 Sep 2025 12:56:19 +0330 Subject: [PATCH 08/13] add `action is stored when config conditions are true` test --- tests/Feature/ActionMonitoringTest.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/Feature/ActionMonitoringTest.php b/tests/Feature/ActionMonitoringTest.php index d7f9092..72089ee 100644 --- a/tests/Feature/ActionMonitoringTest.php +++ b/tests/Feature/ActionMonitoringTest.php @@ -4,6 +4,7 @@ use Binafy\LaravelUserMonitoring\Utills\ActionType; use Binafy\LaravelUserMonitoring\Utills\UserUtils; use Illuminate\Foundation\Testing\RefreshDatabase; +use Illuminate\Http\Request; use Illuminate\Support\Facades\DB; use Tests\SetUp\Models\Product; use Tests\SetUp\Models\ProductSoftDelete; @@ -361,3 +362,19 @@ // DB Assertions assertDatabaseCount(config('user-monitoring.action_monitoring.table'), 2); }); + +test('action is stored when config conditions are true', function () { + config()->set('user-monitoring.action_monitoring.conditions', [ + function (Request $request) { + return true; + }, + ]); + + Product::query()->create([ + 'title' => 'milwad', + 'description' => 'WE ARE HELPING TO OPEN-SOURCE WORLD' + ]); + + // DB Assertions + assertDatabaseCount(config('user-monitoring.action_monitoring.table'), 1); +}); From 02d0a80a3262cf20361362c428b47d7b06eef5a7 Mon Sep 17 00:00:00 2001 From: Milwad <98118400+milwad-dev@users.noreply.github.com> Date: Fri, 5 Sep 2025 12:56:41 +0330 Subject: [PATCH 09/13] add `action is not stored when config conditions are false` test --- tests/Feature/ActionMonitoringTest.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/Feature/ActionMonitoringTest.php b/tests/Feature/ActionMonitoringTest.php index 72089ee..ada2dac 100644 --- a/tests/Feature/ActionMonitoringTest.php +++ b/tests/Feature/ActionMonitoringTest.php @@ -378,3 +378,19 @@ function (Request $request) { // DB Assertions assertDatabaseCount(config('user-monitoring.action_monitoring.table'), 1); }); + +test('action is not stored when config conditions are false', function () { + config()->set('user-monitoring.action_monitoring.conditions', [ + function (Request $request) { + return false; + }, + ]); + + Product::query()->create([ + 'title' => 'milwad', + 'description' => 'WE ARE HELPING TO OPEN-SOURCE WORLD' + ]); + + // DB Assertions + assertDatabaseCount(config('user-monitoring.action_monitoring.table'), 0); +}); From e62adbf120be694de4a4f592ee68e3e57b7753fa Mon Sep 17 00:00:00 2001 From: Milwad <98118400+milwad-dev@users.noreply.github.com> Date: Fri, 5 Sep 2025 12:57:38 +0330 Subject: [PATCH 10/13] add `visit monitoring store when config conditions are true` test --- tests/Feature/VisitMonitoringTest.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/Feature/VisitMonitoringTest.php b/tests/Feature/VisitMonitoringTest.php index 5e8f532..b6bcb29 100644 --- a/tests/Feature/VisitMonitoringTest.php +++ b/tests/Feature/VisitMonitoringTest.php @@ -2,6 +2,7 @@ use Binafy\LaravelUserMonitoring\Models\VisitMonitoring; use Illuminate\Foundation\Testing\RefreshDatabase; +use Illuminate\Http\Request; use Tests\SetUp\Models\User; use function Pest\Laravel\{actingAs, get}; use function Pest\Laravel\{assertDatabaseCount, assertDatabaseHas, assertDatabaseMissing}; @@ -122,6 +123,20 @@ assertDatabaseCount(config('user-monitoring.visit_monitoring.table'), 1); }); +test('visit monitoring store when config conditions are true', function () { + config()->set('user-monitoring.visit_monitoring.conditions', [ + function (Request $request) { + return true; + }, + ]); + + $response = get('/'); + $response->assertContent('milwad'); + + // DB Assertions + assertDatabaseCount(config('user-monitoring.visit_monitoring.table'), 1); +}); + /** * Create user and return it. */ From 47317bbdd12396d00ba6a9b3160a14197971cbf2 Mon Sep 17 00:00:00 2001 From: Milwad <98118400+milwad-dev@users.noreply.github.com> Date: Fri, 5 Sep 2025 12:58:08 +0330 Subject: [PATCH 11/13] add `visit monitoring is not store when config conditions are false` test --- tests/Feature/VisitMonitoringTest.php | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/tests/Feature/VisitMonitoringTest.php b/tests/Feature/VisitMonitoringTest.php index b6bcb29..35018ea 100644 --- a/tests/Feature/VisitMonitoringTest.php +++ b/tests/Feature/VisitMonitoringTest.php @@ -123,7 +123,7 @@ assertDatabaseCount(config('user-monitoring.visit_monitoring.table'), 1); }); -test('visit monitoring store when config conditions are true', function () { +test('visit monitoring is store when config conditions are true', function () { config()->set('user-monitoring.visit_monitoring.conditions', [ function (Request $request) { return true; @@ -137,6 +137,20 @@ function (Request $request) { assertDatabaseCount(config('user-monitoring.visit_monitoring.table'), 1); }); +test('visit monitoring is not store when config conditions are false', function () { + config()->set('user-monitoring.visit_monitoring.conditions', [ + function (Request $request) { + return false; + }, + ]); + + $response = get('/'); + $response->assertContent('milwad'); + + // DB Assertions + assertDatabaseCount(config('user-monitoring.visit_monitoring.table'), 0); +}); + /** * Create user and return it. */ From 974037ef92233a45776c0b87d927f855e1eb1dfb Mon Sep 17 00:00:00 2001 From: Milwad <98118400+milwad-dev@users.noreply.github.com> Date: Fri, 5 Sep 2025 13:02:44 +0330 Subject: [PATCH 12/13] add `Visit Monitoring Custom Conditions` to readme --- README.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/README.md b/README.md index 9a26ad1..7c56760 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ - [Views](#visit-monitoring-views) - [Ajax Requests](#ajax-requests) - [Visit Monitoring Guest Mode](#visit-monitoring-guest-mode) + - [Visit Monitoring Custom Conditions](#visit-monitoring-custom-conditions) - [Action Monitoring](#action-monitoring) - [Views](#action-monitoring-views) - [Reverse Proxy Config](#action-monitoring-reverse-proxy-config) @@ -366,6 +367,34 @@ When set to `false`, only authenticated user visits will be recorded. ], ``` + +### Visit Monitoring Custom Conditions + +The `Laravel User Monitoring` package allows you to define custom conditions for visit monitoring. +Conditions give you full control over when a visit should be logged. + +#### 🔧 How It Works + +- Conditions are checked before a visit is stored. +- If any condition returns false, the visit will be skipped. +- You can define conditions as closures or as class-based rules. + +```php +'visit_monitoring' => [ + 'conditions' => [ + // Class-based condition (must implement MonitoringCondition interface) + \App\Monitoring\YourCustomCondition::class, + + // Closure-based condition (receives the Request and authenticated User) + function (Illuminate\Http\Request $request) { + $user = $request->user(); + + return $user && $user->isAdmin(); + }, + ], +], +``` + ## Action Monitoring From 32fde43a4b7b89f9876fd2d7b8339f91b1426929 Mon Sep 17 00:00:00 2001 From: Milwad <98118400+milwad-dev@users.noreply.github.com> Date: Fri, 5 Sep 2025 13:04:36 +0330 Subject: [PATCH 13/13] add `Action Monitoring Custom Conditions` to readme --- README.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/README.md b/README.md index 7c56760..d45312d 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,7 @@ - [Views](#action-monitoring-views) - [Reverse Proxy Config](#action-monitoring-reverse-proxy-config) - [Action Monitoring Guest Mode](#action-monitoring-guest-mode) + - [Action Monitoring Custom Conditions](#action-monitoring-custom-conditions) - [Authentication Monitoring](#authentication-monitoring) - [Views](#authentication-monitoring-views) - [How to use in big projects](#how-to-use-in-big-projects) @@ -486,6 +487,34 @@ When set to `false`, only authenticated user visits will be recorded. ], ``` + +### Action Monitoring Custom Conditions + +The `Laravel User Monitoring` package lets you define custom conditions for action monitoring (create, update, delete events on models). +Conditions give you control over when model actions should be logged. + +#### 🔧 How It Works + +- Conditions are checked before an action is stored. +- If any condition returns false, the action will be skipped. +- You can define conditions as closures or class-based rules. + +```php +'action_monitoring' => [ + 'conditions' => [ + // Class-based condition (must implement MonitoringCondition interface) + \App\Monitoring\YourCustomCondition::class, + + // Closure-based condition (receives the Request and authenticated User) + function (Illuminate\Http\Request $request) { + $user = $request->user(); + + return $user && $user->isAdmin(); + }, + ], +], +``` + ## Authentication Monitoring