Rapport-Laravel/app/Services/NeblogisticAuditService.php

242 lines
8.7 KiB
PHP

<?php
namespace App\Services;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
class NeblogisticAuditService
{
/**
* Log an INSERT operation
*/
public static function logInsert($neblogisticId, $newData, Request $request = null)
{
return self::log('INSERT', $neblogisticId, null, $newData, $request);
}
/**
* Log an UPDATE operation
*/
public static function logUpdate($neblogisticId, $oldData, $newData, $changedFields = null, Request $request = null)
{
return self::log('UPDATE', $neblogisticId, $oldData, $newData, $request, $changedFields);
}
/**
* Log a DELETE operation
*/
public static function logDelete($neblogisticId, $oldData, Request $request = null)
{
return self::log('DELETE', $neblogisticId, $oldData, null, $request);
}
/**
* Main logging method
*/
protected static function log($action, $neblogisticId, $oldData = null, $newData = null, Request $request = null, $changedFields = null)
{
try {
$user = Auth::user();
$requestData = self::getRequestData($request);
// Get old record if not provided and it's an update/delete
if (in_array($action, ['UPDATE', 'DELETE']) && !$oldData && $neblogisticId) {
$oldData = DB::table('neblogistic')->where('id', $neblogisticId)->first();
if ($oldData) {
$oldData = json_decode(json_encode($oldData), true);
}
}
// Get new record if it's an insert/update
if (in_array($action, ['INSERT', 'UPDATE']) && !$newData && $neblogisticId) {
$newRecord = DB::table('neblogistic')->where('id', $neblogisticId)->first();
if ($newRecord) {
$newData = json_decode(json_encode($newRecord), true);
}
}
// Calculate changed fields if not provided
if ($action === 'UPDATE' && !$changedFields && $oldData && $newData) {
$changedFields = [];
foreach ($newData as $key => $value) {
$oldValue = $oldData[$key] ?? null;
if ($oldValue !== $value) {
$changedFields[$key] = [
'old' => $oldValue,
'new' => $value
];
}
}
}
// Parse browser details
$browserDetails = self::parseUserAgent($requestData['user_agent'] ?? '');
$auditData = [
'neblogistic_id' => $neblogisticId,
'action' => $action,
'old_data' => $oldData ? json_encode($oldData) : null,
'new_data' => $newData ? json_encode($newData) : null,
'changed_fields' => $changedFields ? json_encode($changedFields) : null,
'user_id' => $user ? $user->id : null,
'user_email' => $user ? ($user->email ?? null) : null,
'user_name' => $user ? ($user->name ?? null) : null,
'ip_address' => $requestData['ip'],
'user_agent' => $requestData['user_agent'],
'browser_details' => json_encode($browserDetails),
'request_url' => $requestData['url'],
'request_method' => $requestData['method'],
'created_at' => now(),
];
DB::table('neblogistic_audit_trail')->insert($auditData);
return true;
} catch (\Exception $e) {
// Log error but don't break the main operation
Log::error('Neblogistic audit trail logging failed: ' . $e->getMessage(), [
'action' => $action,
'neblogistic_id' => $neblogisticId,
'exception' => $e
]);
return false;
}
}
/**
* Get request data safely
*/
protected static function getRequestData($request = null)
{
if (!$request && request()) {
$request = request();
}
if (!$request) {
return [
'ip' => null,
'user_agent' => null,
'url' => null,
'method' => null,
];
}
return [
'ip' => $request->ip() ??
$request->header('X-Forwarded-For') ??
$request->server('REMOTE_ADDR') ??
'unknown',
'user_agent' => $request->header('User-Agent'),
'url' => $request->fullUrl(),
'method' => $request->method(),
];
}
/**
* Parse user agent to extract browser details
*/
protected static function parseUserAgent($userAgent)
{
if (empty($userAgent)) {
return [
'browser' => 'Unknown',
'browser_version' => null,
'platform' => 'Unknown',
'device' => 'Unknown',
];
}
$details = [
'browser' => 'Unknown',
'browser_version' => null,
'platform' => 'Unknown',
'device' => 'Unknown',
];
// Detect browser
if (preg_match('/MSIE|Trident/i', $userAgent)) {
$details['browser'] = 'Internet Explorer';
if (preg_match('/MSIE\s([\d.]+)/', $userAgent, $matches)) {
$details['browser_version'] = $matches[1];
}
} elseif (preg_match('/Edge/i', $userAgent)) {
$details['browser'] = 'Microsoft Edge';
if (preg_match('/Edge\/([\d.]+)/', $userAgent, $matches)) {
$details['browser_version'] = $matches[1];
}
} elseif (preg_match('/Chrome/i', $userAgent) && !preg_match('/Edge/i', $userAgent)) {
$details['browser'] = 'Chrome';
if (preg_match('/Chrome\/([\d.]+)/', $userAgent, $matches)) {
$details['browser_version'] = $matches[1];
}
} elseif (preg_match('/Firefox/i', $userAgent)) {
$details['browser'] = 'Firefox';
if (preg_match('/Firefox\/([\d.]+)/', $userAgent, $matches)) {
$details['browser_version'] = $matches[1];
}
} elseif (preg_match('/Safari/i', $userAgent) && !preg_match('/Chrome/i', $userAgent)) {
$details['browser'] = 'Safari';
if (preg_match('/Version\/([\d.]+)/', $userAgent, $matches)) {
$details['browser_version'] = $matches[1];
}
} elseif (preg_match('/Opera|OPR/i', $userAgent)) {
$details['browser'] = 'Opera';
if (preg_match('/(?:Opera|OPR)\/([\d.]+)/', $userAgent, $matches)) {
$details['browser_version'] = $matches[1];
}
}
// Detect platform
if (preg_match('/Windows/i', $userAgent)) {
$details['platform'] = 'Windows';
} elseif (preg_match('/Macintosh|Mac OS X/i', $userAgent)) {
$details['platform'] = 'macOS';
} elseif (preg_match('/Linux/i', $userAgent)) {
$details['platform'] = 'Linux';
} elseif (preg_match('/Android/i', $userAgent)) {
$details['platform'] = 'Android';
} elseif (preg_match('/iPhone|iPad|iPod/i', $userAgent)) {
$details['platform'] = 'iOS';
}
// Detect device
if (preg_match('/Mobile|Android|iPhone|iPad/i', $userAgent)) {
if (preg_match('/iPad/i', $userAgent)) {
$details['device'] = 'Tablet';
} elseif (preg_match('/iPhone|iPod/i', $userAgent)) {
$details['device'] = 'Mobile';
} elseif (preg_match('/Android/i', $userAgent)) {
$details['device'] = preg_match('/Mobile/i', $userAgent) ? 'Mobile' : 'Tablet';
} else {
$details['device'] = 'Mobile';
}
} else {
$details['device'] = 'Desktop';
}
return $details;
}
/**
* Clean up old audit logs (older than specified months)
*/
public static function cleanupOldLogs($months = 6)
{
try {
$cutoffDate = now()->subMonths($months);
$deleted = DB::table('neblogistic_audit_trail')
->where('created_at', '<', $cutoffDate)
->delete();
Log::info("Cleaned up {$deleted} old neblogistic audit trail records older than {$months} months");
return $deleted;
} catch (\Exception $e) {
Log::error('Failed to cleanup neblogistic audit trail logs: ' . $e->getMessage());
return 0;
}
}
}