From 8b99410b45d2a09288fbd2ddd9e77b924db68ea7 Mon Sep 17 00:00:00 2001 From: Dr Masroor Ehsan Date: Tue, 21 Jan 2025 14:21:40 +0600 Subject: [PATCH] wip - UA table --- app/Services/AuditTrail/ActivityLogger.php | 19 +++---- app/Services/BrowserService.php | 49 +++++++++++++++++++ composer.json | 1 + config/browser-detect.php | 21 ++++++++ ..._11_21_821544_create_user_agents_table.php | 19 ++++--- ...4_12_30_152300_create_audit_logs_table.php | 2 +- 6 files changed, 91 insertions(+), 20 deletions(-) create mode 100644 app/Services/BrowserService.php create mode 100644 config/browser-detect.php diff --git a/app/Services/AuditTrail/ActivityLogger.php b/app/Services/AuditTrail/ActivityLogger.php index 7ef210a..3a926d8 100644 --- a/app/Services/AuditTrail/ActivityLogger.php +++ b/app/Services/AuditTrail/ActivityLogger.php @@ -3,6 +3,7 @@ namespace App\Services\AuditTrail; use App\Models\Study; +use App\Services\BrowserService; use Illuminate\Contracts\Auth\Authenticatable; use Illuminate\Support\Facades\DB; @@ -12,15 +13,15 @@ class ActivityLogger private ?int $userId = null; - private int $activity; + private Activity $activity; - private int $category; + private Category $category; private ?string $url = null; private ?string $notes = null; - private ?string $userAgent = null; + private ?int $userAgentId = null; private ?string $ipAddr = null; @@ -59,14 +60,14 @@ public function by(Authenticatable|int|null $user = null): static return $this; } - public function did(int $activity): static + public function did(Activity $activity): static { $this->activity = $activity; return $this; } - public function category(int $category): static + public function category(Category $category): static { $this->category = $category; @@ -96,7 +97,7 @@ public function notes(string $notes): static public function ua(?string $agent = null): static { - $this->userAgent = $agent ?? request()->userAgent(); + $this->userAgentId = BrowserService::upsertBrowser($agent); return $this; } @@ -131,11 +132,11 @@ public function log(bool $initDefaults = true): bool ->insert([ 'study_id' => $this->studyId, 'user_id' => $this->userId, - 'category' => $this->category, - 'activity' => $this->activity, + 'category' => $this->category->value, + 'activity' => $this->activity->value, 'orthanc_uuid' => $this->orthancId, 'ip_addr' => $this->ipAddr, - 'user_agent' => $this->userAgent, + 'user_agent_id' => $this->userAgentId, 'url' => $this->url, 'notes' => $this->notes, 'created_at' => now(), diff --git a/app/Services/BrowserService.php b/app/Services/BrowserService.php new file mode 100644 index 0000000..e178751 --- /dev/null +++ b/app/Services/BrowserService.php @@ -0,0 +1,49 @@ +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()); + } +} diff --git a/composer.json b/composer.json index 3dcb359..81c142a 100644 --- a/composer.json +++ b/composer.json @@ -13,6 +13,7 @@ "culturegr/presenter": "^1.4", "filament/filament": "^3.2", "hashids/hashids": "^5.0", + "hisorange/browser-detect": "^5.0", "laravel/framework": "^11.31", "laravel/jetstream": "^5.3", "laravel/sanctum": "^4.0", diff --git a/config/browser-detect.php b/config/browser-detect.php new file mode 100644 index 0000000..1c85b19 --- /dev/null +++ b/config/browser-detect.php @@ -0,0 +1,21 @@ + [ + /** + * 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, + ], +]; diff --git a/database/migrations/2024_11_21_821544_create_user_agents_table.php b/database/migrations/2024_11_21_821544_create_user_agents_table.php index 0db547b..9b99443 100644 --- a/database/migrations/2024_11_21_821544_create_user_agents_table.php +++ b/database/migrations/2024_11_21_821544_create_user_agents_table.php @@ -11,17 +11,16 @@ */ public function up(): void { - Schema::create('user_agents', function (Blueprint $table) { + Schema::create('user_agents', static function (Blueprint $table) { $table->id(); - $table->string('user_agent'); - $table->string('browser'); - $table->string('browser_version'); - $table->string('os'); - $table->string('os_version'); - $table->string('device'); - $table->string('device_type'); - $table->string('device_brand'); - $table->string('device_model'); + $table->string('user_agent')->unique(); + $table->string('device_type')->nullable(); + $table->string('device_family')->nullable(); + $table->string('device_model')->nullable(); + $table->string('browser_name')->nullable(); + $table->string('browser_version')->nullable(); + $table->string('platform')->nullable(); + $table->string('platform_version')->nullable(); $table->timestamps(); }); } diff --git a/database/migrations/2024_12_30_152300_create_audit_logs_table.php b/database/migrations/2024_12_30_152300_create_audit_logs_table.php index 895eb83..3ad245b 100644 --- a/database/migrations/2024_12_30_152300_create_audit_logs_table.php +++ b/database/migrations/2024_12_30_152300_create_audit_logs_table.php @@ -15,7 +15,7 @@ public function up(): void $table->unsignedTinyInteger('category'); $table->unsignedSmallInteger('activity'); $table->ipAddress('ip_addr')->nullable(); - $table->string('user_agent')->nullable(); + $table->unsignedBigInteger('user_agent_id')->nullable(); $table->string('orthanc_uuid')->nullable(); $table->text('url')->nullable(); $table->text('notes')->nullable();