ServerManager project files
This commit is contained in:
195
src/Services/AuditService.php
Executable file
195
src/Services/AuditService.php
Executable file
@@ -0,0 +1,195 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ServerManager\Services;
|
||||
|
||||
use ServerManager\Core\Database;
|
||||
use ServerManager\Core\Session;
|
||||
use ServerManager\Core\Logger;
|
||||
|
||||
class AuditService
|
||||
{
|
||||
private Database $db;
|
||||
private Logger $logger;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->db = Database::getInstance();
|
||||
$this->logger = Logger::getInstance();
|
||||
}
|
||||
|
||||
public function log(
|
||||
string $action,
|
||||
string $entityType,
|
||||
?int $entityId,
|
||||
?array $details = null,
|
||||
?array $metadata = null
|
||||
): void {
|
||||
$userId = Session::get('user_id');
|
||||
$username = Session::get('username');
|
||||
$ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown';
|
||||
$userAgent = $_SERVER['HTTP_USER_AGENT'] ?? 'unknown';
|
||||
$now = date('Y-m-d H:i:s');
|
||||
|
||||
$this->db->insert('audit_logs', [
|
||||
'user_id' => $userId,
|
||||
'username' => $username ?? 'system',
|
||||
'action' => $action,
|
||||
'entity_type' => $entityType,
|
||||
'entity_id' => $entityId,
|
||||
'details' => $details ? json_encode($details, JSON_UNESCAPED_SLASHES) : null,
|
||||
'ip_address' => $ip,
|
||||
'user_agent' => $userAgent,
|
||||
'created_at' => $now,
|
||||
]);
|
||||
|
||||
$logMessage = sprintf(
|
||||
'[AUDIT] %s | %s | %s:%s | User: %s (%d)',
|
||||
$action,
|
||||
$entityType,
|
||||
$entityId ?? 'N/A',
|
||||
$ip,
|
||||
$username ?? 'system',
|
||||
$userId ?? 0
|
||||
);
|
||||
|
||||
$this->logger->info($logMessage);
|
||||
|
||||
if (in_array($action, ['credential_access', 'credential_decrypt', 'credential_use'])) {
|
||||
$this->logger->warning("[CREDENTIAL_ACCESS] {$logMessage}");
|
||||
}
|
||||
}
|
||||
|
||||
public function logCredentialAccess(int $serverId, string $reason): void
|
||||
{
|
||||
$server = $this->db->fetch('SELECT name, ip_address FROM servers WHERE id = ?', [$serverId]);
|
||||
$serverName = $server['name'] ?? 'Unknown';
|
||||
|
||||
$this->log(
|
||||
'credential_access',
|
||||
'server_credentials',
|
||||
$serverId,
|
||||
[
|
||||
'server_name' => $serverName,
|
||||
'ip_address' => $server['ip_address'] ?? 'unknown',
|
||||
'reason' => $reason,
|
||||
'timestamp' => date('c'),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function logLogin(string $username, bool $success, ?string $reason = null): void
|
||||
{
|
||||
$this->log(
|
||||
$success ? 'login_success' : 'login_failed',
|
||||
'user',
|
||||
null,
|
||||
[
|
||||
'username' => $username,
|
||||
'success' => $success,
|
||||
'reason' => $reason,
|
||||
]
|
||||
);
|
||||
|
||||
if (!$success) {
|
||||
$this->logger->warning("[SECURITY] Failed login attempt for username: {$username}", [
|
||||
'ip' => $_SERVER['REMOTE_ADDR'] ?? 'unknown',
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
public function logServerAction(int $serverId, string $action, string $command): void
|
||||
{
|
||||
$this->log(
|
||||
'server_action',
|
||||
'server',
|
||||
$serverId,
|
||||
[
|
||||
'action' => $action,
|
||||
'command' => $command,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function logUserManagement(int $userId, string $action): void
|
||||
{
|
||||
$this->log(
|
||||
$action,
|
||||
'user',
|
||||
$userId,
|
||||
[
|
||||
'performed_by' => Session::get('username'),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function getRecentActivity(int $limit = 20): array
|
||||
{
|
||||
return $this->db->fetchAll(
|
||||
'SELECT al.*, u.username as actor_name
|
||||
FROM audit_logs al
|
||||
LEFT JOIN users u ON al.user_id = u.id
|
||||
ORDER BY al.created_at DESC
|
||||
LIMIT ?',
|
||||
[$limit]
|
||||
);
|
||||
}
|
||||
|
||||
public function getAuditLogs(int $page = 1, int $perPage = 50, array $filters = []): array
|
||||
{
|
||||
$where = [];
|
||||
$params = [];
|
||||
|
||||
if (!empty($filters['action'])) {
|
||||
$where[] = 'al.action = ?';
|
||||
$params[] = $filters['action'];
|
||||
}
|
||||
|
||||
if (!empty($filters['user_id'])) {
|
||||
$where[] = 'al.user_id = ?';
|
||||
$params[] = $filters['user_id'];
|
||||
}
|
||||
|
||||
if (!empty($filters['entity_type'])) {
|
||||
$where[] = 'al.entity_type = ?';
|
||||
$params[] = $filters['entity_type'];
|
||||
}
|
||||
|
||||
if (!empty($filters['date_from'])) {
|
||||
$where[] = 'al.created_at >= ?';
|
||||
$params[] = $filters['date_from'];
|
||||
}
|
||||
|
||||
if (!empty($filters['date_to'])) {
|
||||
$where[] = 'al.created_at <= ?';
|
||||
$params[] = $filters['date_to'];
|
||||
}
|
||||
|
||||
$whereClause = !empty($where) ? 'WHERE ' . implode(' AND ', $where) : '';
|
||||
$offset = ($page - 1) * $perPage;
|
||||
|
||||
$total = $this->db->fetch(
|
||||
"SELECT COUNT(*) as total FROM audit_logs al {$whereClause}",
|
||||
$params
|
||||
);
|
||||
|
||||
$logs = $this->db->fetchAll(
|
||||
"SELECT al.*, u.username as actor_name
|
||||
FROM audit_logs al
|
||||
LEFT JOIN users u ON al.user_id = u.id
|
||||
{$whereClause}
|
||||
ORDER BY al.created_at DESC
|
||||
LIMIT ? OFFSET ?",
|
||||
array_merge($params, [$perPage, $offset])
|
||||
);
|
||||
|
||||
return [
|
||||
'data' => $logs,
|
||||
'total' => (int) ($total['total'] ?? 0),
|
||||
'page' => $page,
|
||||
'per_page' => $perPage,
|
||||
'total_pages' => ceil((int) ($total['total'] ?? 0) / $perPage),
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user