Skip to content

Commit 987dca0

Browse files
committed
feat:(LAR-89) add tracking for user
1 parent 82fcb62 commit 987dca0

File tree

5 files changed

+66
-0
lines changed

5 files changed

+66
-0
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Http\Middleware;
6+
7+
use Carbon\Carbon;
8+
use Closure;
9+
use Illuminate\Http\Request;
10+
use Symfony\Component\HttpFoundation\Response;
11+
12+
final class TrackLastActivity
13+
{
14+
public function handle(Request $request, Closure $next): Response
15+
{
16+
if ($user = $request->user()) {
17+
$lastActive = $user->last_active_at;
18+
19+
if (! $lastActive || $lastActive->diffInMinutes(Carbon::now()) >= 3) {
20+
$user->update([
21+
'last_active_at' => now(),
22+
]);
23+
}
24+
}
25+
26+
return $next($request);
27+
}
28+
}

app/Models/User.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
* @property Carbon | null $banned_at
5555
* @property Carbon $created_at
5656
* @property Carbon $updated_at
57+
* @property Carbon | null $last_active_at
5758
* @property Collection | Activity[] $activities
5859
* @property Collection | Article[] $articles
5960
* @property Collection | Thread[] $threads
@@ -96,13 +97,15 @@ final class User extends Authenticatable implements FilamentUser, HasAvatar, Has
9697
'banned_at',
9798
'banned_reason',
9899
'opt_in',
100+
'last_active_at',
99101
];
100102

101103
protected $hidden = [
102104
'password',
103105
'remember_token',
104106
'two_factor_recovery_codes',
105107
'two_factor_secret',
108+
'last_active_at',
106109
];
107110

108111
protected $casts = [

bootstrap/app.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
]);
2121
$middleware->web(append: [
2222
LocaleMiddleware::class,
23+
\App\Http\Middleware\TrackLastActivity::class,
2324
]);
2425
})
2526
->withExceptions(function (Exceptions $exceptions): void {
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use Illuminate\Database\Migrations\Migration;
6+
use Illuminate\Database\Schema\Blueprint;
7+
use Illuminate\Support\Facades\Schema;
8+
9+
return new class extends Migration
10+
{
11+
public function up(): void
12+
{
13+
Schema::table('users', static function (Blueprint $table): void {
14+
$table->timestamp('last_active_at')->nullable();
15+
});
16+
}
17+
18+
public function down(): void
19+
{
20+
Schema::table('users', function (Blueprint $table): void {
21+
$table->dropColumn('last_active_at');
22+
});
23+
}
24+
};

tests/Feature/UserActivitiesTest.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use App\Models\Activity;
66
use App\Models\Article;
77
use Carbon\Carbon;
8+
use Illuminate\Support\Facades\Route;
89

910
it('records activity when an article is created', function (): void {
1011
$user = $this->login();
@@ -39,3 +40,12 @@
3940
Carbon::now()->subWeek()->format('Y-m-d')
4041
));
4142
});
43+
44+
it('does not update the last activity for unauthenticated users', function (): void {
45+
Route::middleware(\App\Http\Middleware\TrackLastActivity::class)
46+
->get('/activity-user', fn () => 'ok');
47+
48+
$this->get('/activity-user')->assertOk();
49+
50+
$this->assertDatabaseMissing('users', ['last_active_at' => now()]);
51+
});

0 commit comments

Comments
 (0)