wip - UA table

This commit is contained in:
Dr Masroor Ehsan 2025-01-21 14:21:40 +06:00
parent c9e87ef1bb
commit 8b99410b45
6 changed files with 91 additions and 20 deletions

View File

@ -3,6 +3,7 @@
namespace App\Services\AuditTrail; namespace App\Services\AuditTrail;
use App\Models\Study; use App\Models\Study;
use App\Services\BrowserService;
use Illuminate\Contracts\Auth\Authenticatable; use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
@ -12,15 +13,15 @@ class ActivityLogger
private ?int $userId = null; private ?int $userId = null;
private int $activity; private Activity $activity;
private int $category; private Category $category;
private ?string $url = null; private ?string $url = null;
private ?string $notes = null; private ?string $notes = null;
private ?string $userAgent = null; private ?int $userAgentId = null;
private ?string $ipAddr = null; private ?string $ipAddr = null;
@ -59,14 +60,14 @@ public function by(Authenticatable|int|null $user = null): static
return $this; return $this;
} }
public function did(int $activity): static public function did(Activity $activity): static
{ {
$this->activity = $activity; $this->activity = $activity;
return $this; return $this;
} }
public function category(int $category): static public function category(Category $category): static
{ {
$this->category = $category; $this->category = $category;
@ -96,7 +97,7 @@ public function notes(string $notes): static
public function ua(?string $agent = null): static public function ua(?string $agent = null): static
{ {
$this->userAgent = $agent ?? request()->userAgent(); $this->userAgentId = BrowserService::upsertBrowser($agent);
return $this; return $this;
} }
@ -131,11 +132,11 @@ public function log(bool $initDefaults = true): bool
->insert([ ->insert([
'study_id' => $this->studyId, 'study_id' => $this->studyId,
'user_id' => $this->userId, 'user_id' => $this->userId,
'category' => $this->category, 'category' => $this->category->value,
'activity' => $this->activity, 'activity' => $this->activity->value,
'orthanc_uuid' => $this->orthancId, 'orthanc_uuid' => $this->orthancId,
'ip_addr' => $this->ipAddr, 'ip_addr' => $this->ipAddr,
'user_agent' => $this->userAgent, 'user_agent_id' => $this->userAgentId,
'url' => $this->url, 'url' => $this->url,
'notes' => $this->notes, 'notes' => $this->notes,
'created_at' => now(), 'created_at' => now(),

View File

@ -0,0 +1,49 @@
<?php
namespace App\Services;
use Illuminate\Support\Facades\DB;
final class BrowserService
{
public static function userAgent()
{
return app('browser-detect')->userAgent();
}
public static function findUA(?string $ua = null): ?int
{
$ua ??= app('browser-detect')->userAgent();
$row = DB::table('user_agents')->where('user_agent', $ua)->first(['id']);
if ($row) {
return $row->id;
}
return null;
}
public static function upsertBrowser(?string $ua = null): int
{
$browser = blank($ua)
? app('browser-detect')->detect()
: app('browser-detect')->parse($ua);
$id = self::findUA($browser->userAgent());
if ($id) {
return $id;
}
$params = [
'user_agent' => $browser->userAgent(),
'device_type' => $browser->deviceType(),
'device_family' => $browser->deviceFamily(),
'device_model' => $browser->deviceModel(),
'browser_name' => $browser->browserName(),
'browser_version' => $browser->browserVersion(),
'platform' => $browser->platformFamily(),
'platform_version' => $browser->platformVersion(),
];
DB::table('user_agents')->insert($params);
return self::findUA($browser->userAgent());
}
}

View File

@ -13,6 +13,7 @@
"culturegr/presenter": "^1.4", "culturegr/presenter": "^1.4",
"filament/filament": "^3.2", "filament/filament": "^3.2",
"hashids/hashids": "^5.0", "hashids/hashids": "^5.0",
"hisorange/browser-detect": "^5.0",
"laravel/framework": "^11.31", "laravel/framework": "^11.31",
"laravel/jetstream": "^5.3", "laravel/jetstream": "^5.3",
"laravel/sanctum": "^4.0", "laravel/sanctum": "^4.0",

21
config/browser-detect.php Normal file
View File

@ -0,0 +1,21 @@
<?php
return [
'cache' => [
/**
* Interval in seconds, as how long a result should be cached.
*/
'interval' => 10080,
/**
* Cache prefix, the user agent string will be hashed and appended at the end.
*/
'prefix' => 'bd4_',
],
'security' => [
/**
* Byte length where the header is cut off, if some attacker sends a long header
* then the library will make a cut this byte point.
*/
'max-header-length' => 2048,
],
];

View File

@ -11,17 +11,16 @@
*/ */
public function up(): void public function up(): void
{ {
Schema::create('user_agents', function (Blueprint $table) { Schema::create('user_agents', static function (Blueprint $table) {
$table->id(); $table->id();
$table->string('user_agent'); $table->string('user_agent')->unique();
$table->string('browser'); $table->string('device_type')->nullable();
$table->string('browser_version'); $table->string('device_family')->nullable();
$table->string('os'); $table->string('device_model')->nullable();
$table->string('os_version'); $table->string('browser_name')->nullable();
$table->string('device'); $table->string('browser_version')->nullable();
$table->string('device_type'); $table->string('platform')->nullable();
$table->string('device_brand'); $table->string('platform_version')->nullable();
$table->string('device_model');
$table->timestamps(); $table->timestamps();
}); });
} }

View File

@ -15,7 +15,7 @@ public function up(): void
$table->unsignedTinyInteger('category'); $table->unsignedTinyInteger('category');
$table->unsignedSmallInteger('activity'); $table->unsignedSmallInteger('activity');
$table->ipAddress('ip_addr')->nullable(); $table->ipAddress('ip_addr')->nullable();
$table->string('user_agent')->nullable(); $table->unsignedBigInteger('user_agent_id')->nullable();
$table->string('orthanc_uuid')->nullable(); $table->string('orthanc_uuid')->nullable();
$table->text('url')->nullable(); $table->text('url')->nullable();
$table->text('notes')->nullable(); $table->text('notes')->nullable();