201 lines
6.2 KiB
PHP
201 lines
6.2 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use App\Core\Database;
|
|
use App\Core\Session;
|
|
|
|
class AuditService
|
|
{
|
|
private Database $database;
|
|
private Session $session;
|
|
|
|
public function __construct(Database $database, Session $session)
|
|
{
|
|
$this->database = $database;
|
|
$this->session = $session;
|
|
}
|
|
|
|
public function log(string $action, string $table, int $recordId, array $oldValue = null, array $newValue = null): void
|
|
{
|
|
$userId = $this->session->getUserId();
|
|
|
|
if (!$userId) {
|
|
return; // Skip logging if no user
|
|
}
|
|
|
|
$data = [
|
|
'user_id' => $userId,
|
|
'action' => $action,
|
|
'table_name' => $table,
|
|
'record_id' => $recordId,
|
|
'old_value' => $oldValue ? json_encode($oldValue) : null,
|
|
'new_value' => $newValue ? json_encode($newValue) : null,
|
|
'created_at' => date('Y-m-d H:i:s')
|
|
];
|
|
|
|
try {
|
|
$this->database->insert('audit_log', $data);
|
|
} catch (\Exception $e) {
|
|
error_log('Audit logging failed: ' . $e->getMessage());
|
|
}
|
|
}
|
|
|
|
public function getAuditLog(string $table = null, int $recordId = null, int $limit = 100): array
|
|
{
|
|
$sql = "SELECT al.*, u.name as user_name
|
|
FROM audit_log al
|
|
LEFT JOIN users u ON al.user_id = u.id
|
|
WHERE 1=1";
|
|
$params = [];
|
|
|
|
if ($table) {
|
|
$sql .= " AND al.table_name = :table";
|
|
$params['table'] = $table;
|
|
}
|
|
|
|
if ($recordId) {
|
|
$sql .= " AND al.record_id = :record_id";
|
|
$params['record_id'] = $recordId;
|
|
}
|
|
|
|
$sql .= " ORDER BY al.created_at DESC LIMIT :limit";
|
|
$params['limit'] = $limit;
|
|
|
|
return $this->database->fetchAll($sql, $params);
|
|
}
|
|
|
|
public function getAssetHistory(int $assetId): array
|
|
{
|
|
return $this->getAuditLog('assets', $assetId);
|
|
}
|
|
|
|
public function getUserActivity(int $userId, int $limit = 50): array
|
|
{
|
|
$sql = "SELECT al.*, u.name as user_name
|
|
FROM audit_log al
|
|
LEFT JOIN users u ON al.user_id = u.id
|
|
WHERE al.user_id = :user_id
|
|
ORDER BY al.created_at DESC
|
|
LIMIT :limit";
|
|
|
|
return $this->database->fetchAll($sql, [
|
|
'user_id' => $userId,
|
|
'limit' => $limit
|
|
]);
|
|
}
|
|
|
|
public function getRecentActivity(int $limit = 20): array
|
|
{
|
|
$sql = "SELECT al.*, u.name as user_name
|
|
FROM audit_log al
|
|
LEFT JOIN users u ON al.user_id = u.id
|
|
ORDER BY al.created_at DESC
|
|
LIMIT :limit";
|
|
|
|
return $this->database->fetchAll($sql, ['limit' => $limit]);
|
|
}
|
|
|
|
public function getActivityByDateRange(string $startDate, string $endDate): array
|
|
{
|
|
$sql = "SELECT al.*, u.name as user_name
|
|
FROM audit_log al
|
|
LEFT JOIN users u ON al.user_id = u.id
|
|
WHERE DATE(al.created_at) BETWEEN :start_date AND :end_date
|
|
ORDER BY al.created_at DESC";
|
|
|
|
return $this->database->fetchAll($sql, [
|
|
'start_date' => $startDate,
|
|
'end_date' => $endDate
|
|
]);
|
|
}
|
|
|
|
public function getActivityByAction(string $action, int $limit = 100): array
|
|
{
|
|
$sql = "SELECT al.*, u.name as user_name
|
|
FROM audit_log al
|
|
LEFT JOIN users u ON al.user_id = u.id
|
|
WHERE al.action = :action
|
|
ORDER BY al.created_at DESC
|
|
LIMIT :limit";
|
|
|
|
return $this->database->fetchAll($sql, [
|
|
'action' => $action,
|
|
'limit' => $limit
|
|
]);
|
|
}
|
|
|
|
public function getAssetChanges(int $assetId): array
|
|
{
|
|
$sql = "SELECT al.*, u.name as user_name
|
|
FROM audit_log al
|
|
LEFT JOIN users u ON al.user_id = u.id
|
|
WHERE al.table_name = 'assets'
|
|
AND al.record_id = :asset_id
|
|
AND al.action IN ('update', 'delete')
|
|
ORDER BY al.created_at DESC";
|
|
|
|
return $this->database->fetchAll($sql, ['asset_id' => $assetId]);
|
|
}
|
|
|
|
public function getInventoryActivity(int $inventoryId): array
|
|
{
|
|
$sql = "SELECT al.*, u.name as user_name
|
|
FROM audit_log al
|
|
LEFT JOIN users u ON al.user_id = u.id
|
|
WHERE al.table_name = 'inventories'
|
|
AND al.record_id = :inventory_id
|
|
ORDER BY al.created_at DESC";
|
|
|
|
return $this->database->fetchAll($sql, ['inventory_id' => $inventoryId]);
|
|
}
|
|
|
|
public function cleanupOldLogs(int $daysToKeep = 365): int
|
|
{
|
|
$sql = "DELETE FROM audit_log
|
|
WHERE created_at < DATE_SUB(NOW(), INTERVAL :days DAY)";
|
|
|
|
return $this->database->query($sql, ['days' => $daysToKeep])->rowCount();
|
|
}
|
|
|
|
public function getAuditSummary(): array
|
|
{
|
|
$sql = "SELECT
|
|
COUNT(*) as total_entries,
|
|
COUNT(DISTINCT user_id) as unique_users,
|
|
COUNT(DISTINCT table_name) as tables_affected,
|
|
MIN(created_at) as first_entry,
|
|
MAX(created_at) as last_entry
|
|
FROM audit_log";
|
|
|
|
return $this->database->fetch($sql) ?: [];
|
|
}
|
|
|
|
public function getTopUsers(int $limit = 10): array
|
|
{
|
|
$sql = "SELECT
|
|
u.name as user_name,
|
|
COUNT(*) as activity_count
|
|
FROM audit_log al
|
|
LEFT JOIN users u ON al.user_id = u.id
|
|
GROUP BY al.user_id, u.name
|
|
ORDER BY activity_count DESC
|
|
LIMIT :limit";
|
|
|
|
return $this->database->fetchAll($sql, ['limit' => $limit]);
|
|
}
|
|
|
|
public function getMostActiveTables(int $limit = 10): array
|
|
{
|
|
$sql = "SELECT
|
|
table_name,
|
|
COUNT(*) as activity_count
|
|
FROM audit_log
|
|
GROUP BY table_name
|
|
ORDER BY activity_count DESC
|
|
LIMIT :limit";
|
|
|
|
return $this->database->fetchAll($sql, ['limit' => $limit]);
|
|
}
|
|
}
|