Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
d23d7d5
add `guest_mode` to config
milwad-dev Mar 16, 2025
9b61490
Merge branch '1.x' of https://github.com/binafy/laravel-user-monitori…
milwad-dev Jun 24, 2025
b04db83
add condition in visit middleware for guest mode
milwad-dev Jun 24, 2025
17770bd
add `visit monitoring skip store when guest mode is off and user not …
milwad-dev Jun 24, 2025
f55422f
add `visit monitoring store when guest mode is off and user logged in…
milwad-dev Jun 24, 2025
f833be6
add `visit monitoring store when guest mode is on and user logged in`…
milwad-dev Jun 24, 2025
76f41fa
add `visit monitoring store when guest mode is on and user not logged…
milwad-dev Jun 24, 2025
e43a6be
Update VisitMonitoringTest.php
milwad-dev Jun 24, 2025
504ac7f
Update Actionable.php
milwad-dev Jun 25, 2025
db8d3ba
add `action not stored when the guest mode is off and user not logged…
milwad-dev Jun 25, 2025
ca547d2
add `action stored when the guest mode is on and user not logged in` …
milwad-dev Jun 25, 2025
3bc2c0d
add `action stored when the guest mode is off and user logged in` test
milwad-dev Jun 25, 2025
a6f564f
add `action stored when the guest mode is on and user logged in` test
milwad-dev Jun 25, 2025
a1d6bff
Update Actionable.php
milwad-dev Jun 25, 2025
a42ffa5
Update LaravelUserMonitoringEventServiceProvider.php
milwad-dev Jun 25, 2025
8bfa031
Update user-monitoring.php
milwad-dev Jun 25, 2025
630c594
Update README.md
milwad-dev Jun 25, 2025
b046619
Update README.md
milwad-dev Jun 25, 2025
6aac745
Update README.md
milwad-dev Jun 25, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 63 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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.

<a name="visit-monitoring-guest-mode"></a>
### 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,
],
```

<a name="action-monitoring"></a>
## Action Monitoring

Expand Down Expand Up @@ -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")

<a name="authentication-monitoring"></a>
## Authentication Monitoring
<a name="action-monitoring-reverse-proxy-config"></a>
### Action Monitoring Reverse Proxy Config

Have you ever thought about monitoring the entry and exit of users of your application? Now you can :) <br>
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',
],
```

<a name="action-monitoring-reverse-proxy-config"></a>
### Action Monitoring Reverse Proxy Config
<a name="action-monitoring-guest-mode"></a>
### 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,
],
```

<a name="authentication-monitoring"></a>
## Authentication Monitoring

Have you ever thought about monitoring the entry and exit of users of your application? Now you can :) <br>
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,
],
```


<a name="authentication-monitoring-views"></a>
### Authentication Monitoring Views

Expand Down
10 changes: 10 additions & 0 deletions config/user-monitoring.php
Original file line number Diff line number Diff line change
Expand Up @@ -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,
],

/*
Expand Down Expand Up @@ -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,
],

/*
Expand Down
3 changes: 3 additions & 0 deletions src/Middlewares/VisitMonitoringMiddleware.php
Original file line number Diff line number Diff line change
Expand Up @@ -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', []);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 5 additions & 1 deletion src/Traits/Actionable.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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();
}
}
63 changes: 61 additions & 2 deletions tests/Feature/ActionMonitoringTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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};

/*
Expand Down Expand Up @@ -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'
]);
Expand All @@ -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'
]);
Expand Down Expand Up @@ -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);
});
50 changes: 45 additions & 5 deletions tests/Feature/VisitMonitoringTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@
// Ajax

test('visit monitoring store ajax requests', function () {
\Pest\Laravel\withoutExceptionHandling();
get('/', ['X-Requested-With' => 'XMLHttpRequest']);

// DB Assertions
Expand All @@ -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',
Expand Down