GeoNetAgent, LDAPWeb, server-audit, server-connection
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

<?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) : '—';
}
}