You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
133 lines
4.8 KiB
133 lines
4.8 KiB
<?php |
|
|
|
namespace App\Services; |
|
|
|
use Illuminate\Http\Request; |
|
|
|
class ClientContextService |
|
{ |
|
public function normalizeFromRequest(Request $request): array |
|
{ |
|
$data = $request->validate([ |
|
'browser' => ['nullable', 'string', 'max:64'], |
|
'browser_version' => ['nullable', 'string', 'max:32'], |
|
'os' => ['nullable', 'string', 'max:64'], |
|
'os_version' => ['nullable', 'string', 'max:32'], |
|
'screen' => ['nullable', 'string', 'max:32'], |
|
'cpu_cores' => ['nullable', 'integer', 'min:1', 'max:256'], |
|
'device_memory_gb' => ['nullable', 'numeric', 'min:0', 'max:1024'], |
|
'gpu' => ['nullable', 'string', 'max:255'], |
|
'language' => ['nullable', 'string', 'max:32'], |
|
'timezone' => ['nullable', 'string', 'max:64'], |
|
'webrtc_ip' => ['nullable', 'string', 'max:45'], |
|
]); |
|
|
|
$ua = $request->userAgent() ?? ''; |
|
$parsed = $this->parseUserAgent($ua); |
|
|
|
return array_filter([ |
|
'browser' => $data['browser'] ?? $parsed['browser'], |
|
'browser_version' => $data['browser_version'] ?? $parsed['browser_version'], |
|
'os' => $data['os'] ?? $parsed['os'], |
|
'os_version' => $data['os_version'] ?? $parsed['os_version'], |
|
'screen' => $data['screen'] ?? null, |
|
'cpu_cores' => isset($data['cpu_cores']) ? (int) $data['cpu_cores'] : null, |
|
'device_memory_gb' => isset($data['device_memory_gb']) ? (float) $data['device_memory_gb'] : null, |
|
'gpu' => $data['gpu'] ?? null, |
|
'language' => $data['language'] ?? null, |
|
'timezone' => $data['timezone'] ?? null, |
|
'webrtc_ip' => $data['webrtc_ip'] ?? null, |
|
'user_agent' => mb_substr($ua, 0, 500), |
|
], fn ($value) => $value !== null && $value !== ''); |
|
} |
|
|
|
public function storeInSession(Request $request, array $context): void |
|
{ |
|
$request->session()->put('audit_client_context', $context); |
|
} |
|
|
|
public function fromSession(Request $request): array |
|
{ |
|
$context = $request->session()->get('audit_client_context'); |
|
|
|
return is_array($context) ? $context : []; |
|
} |
|
|
|
/** |
|
* @return array{browser: ?string, browser_version: ?string, os: ?string, os_version: ?string} |
|
*/ |
|
public function parseUserAgent(string $ua): array |
|
{ |
|
$browser = null; |
|
$browserVersion = null; |
|
$os = null; |
|
$osVersion = null; |
|
|
|
if (preg_match('/Edg\/([\d.]+)/', $ua, $m)) { |
|
$browser = 'Edge'; |
|
$browserVersion = $m[1]; |
|
} elseif (preg_match('/OPR\/([\d.]+)/', $ua, $m) || preg_match('/Opera\/([\d.]+)/', $ua, $m)) { |
|
$browser = 'Opera'; |
|
$browserVersion = $m[1]; |
|
} elseif (preg_match('/Chrome\/([\d.]+)/', $ua, $m) && ! str_contains($ua, 'Edg/')) { |
|
$browser = 'Chrome'; |
|
$browserVersion = $m[1]; |
|
} elseif (preg_match('/Firefox\/([\d.]+)/', $ua, $m)) { |
|
$browser = 'Firefox'; |
|
$browserVersion = $m[1]; |
|
} elseif (preg_match('/Version\/([\d.]+).*Safari/', $ua, $m)) { |
|
$browser = 'Safari'; |
|
$browserVersion = $m[1]; |
|
} |
|
|
|
if (preg_match('/Windows NT ([\d.]+)/', $ua, $m)) { |
|
$os = 'Windows'; |
|
$osVersion = match ($m[1]) { |
|
'10.0' => '10/11', |
|
'6.3' => '8.1', |
|
'6.2' => '8', |
|
'6.1' => '7', |
|
default => $m[1], |
|
}; |
|
} elseif (preg_match('/Android ([\d.]+)/', $ua, $m)) { |
|
$os = 'Android'; |
|
$osVersion = $m[1]; |
|
} elseif (preg_match('/iPhone OS ([\d_]+)/', $ua, $m) || preg_match('/iPad.*OS ([\d_]+)/', $ua, $m)) { |
|
$os = 'iOS'; |
|
$osVersion = str_replace('_', '.', $m[1]); |
|
} elseif (str_contains($ua, 'Mac OS X')) { |
|
$os = 'macOS'; |
|
if (preg_match('/Mac OS X ([\d_]+)/', $ua, $m)) { |
|
$osVersion = str_replace('_', '.', $m[1]); |
|
} |
|
} elseif (str_contains($ua, 'Linux')) { |
|
$os = 'Linux'; |
|
} |
|
|
|
return [ |
|
'browser' => $browser, |
|
'browser_version' => $browserVersion, |
|
'os' => $os, |
|
'os_version' => $osVersion, |
|
]; |
|
} |
|
|
|
public function summary(array $context): string |
|
{ |
|
$parts = []; |
|
|
|
if (! empty($context['browser'])) { |
|
$parts[] = $context['browser'].(! empty($context['browser_version']) ? ' '.$context['browser_version'] : ''); |
|
} |
|
|
|
if (! empty($context['os'])) { |
|
$parts[] = $context['os'].(! empty($context['os_version']) ? ' '.$context['os_version'] : ''); |
|
} |
|
|
|
if (! empty($context['screen'])) { |
|
$parts[] = $context['screen']; |
|
} |
|
|
|
return $parts !== [] ? implode(' · ', $parts) : '—'; |
|
} |
|
}
|
|
|