Files
server-manager/views/admin/audit.php
Agent 88f3c1f964 refactor: extract inline CSS/JS from views into separate asset files (20+ files)
Phase A — HTML removed from PHP files:
- RateLimitMiddleware.php: heredoc moved to views/errors/429.php
- public/index.php: inline HTML replaced with View::error()
- AuthMiddleware.php: <script> redirect replaced with <meta refresh>

Phase B — Inline CSS/JS extracted from views:
- CSS: landing.css (459 lines), legal.css (shared by terms+privacy)
- JS: 17 new files extracted from ~20 view files
  - main.js (layout sidebar + notifications)
  - dashboard-chart.js, server-show.js, server-services.js
  - nginx-manager.js, database-manager.js
  - terminal.js, team-show.js, team-index.js
  - server-list.js, server-permissions.js (shared by edit+create)
  - server-ssl.js, server-processes.js, system-users.js
  - admin-users.js, audit-log.js, admin-notifications.js, admin-security.js
  - notifications.js

Total: -3264 lines from views, +288 lines in new assets
2026-06-14 08:04:01 -04:00

191 lines
10 KiB
PHP
Executable File

<?php
$logs = $logs ?? [];
$action = $action ?? '';
$username = $username ?? '';
$ipAddress = $ipAddress ?? '';
$entityType = $entityType ?? '';
$details = $details ?? '';
$dateFrom = $dateFrom ?? '';
$dateTo = $dateTo ?? '';
function selected(string $value, string $compare): string {
return $value === $compare ? 'selected' : '';
}
?>
<div class="page-header">
<div class="page-header-left">
<h1 class="page-title">Audit Logs</h1>
<p class="page-subtitle">Comprehensive activity tracking and security monitoring</p>
</div>
<div class="page-header-right">
<button class="btn btn-sm" onclick="clearFilters()"><i class="fas fa-times"></i> Clear Filters</button>
</div>
</div>
<div class="card">
<div class="card-body">
<div class="table-responsive">
<table class="table">
<thead>
<tr>
<th>Time</th>
<th>User</th>
<th>Action</th>
<th>Entity</th>
<th>Details</th>
<th>IP Address</th>
</tr>
<tr class="filter-row">
<th>
<div class="filter-date-group">
<input type="date" id="f_date_from" class="form-input" placeholder="From" value="<?= htmlspecialchars($dateFrom) ?>">
<span class="filter-date-sep">—</span>
<input type="date" id="f_date_to" class="form-input" placeholder="To" value="<?= htmlspecialchars($dateTo) ?>">
</div>
</th>
<th>
<div class="filter-input-wrap">
<input type="text" id="f_username" class="form-input filter-input" placeholder="User..." value="<?= htmlspecialchars($username) ?>">
<?php if ($username !== ''): ?>
<button class="filter-clear" onclick="clearField('f_username')" title="Clear">&times;</button>
<?php endif; ?>
</div>
</th>
<th>
<select id="f_action" class="form-select">
<option value="">All Actions</option>
<option value="login_success" <?= selected($action, 'login_success') ?>>Login Success</option>
<option value="login_failed" <?= selected($action, 'login_failed') ?>>Login Failed</option>
<option value="server_created" <?= selected($action, 'server_created') ?>>Server Created</option>
<option value="server_deleted" <?= selected($action, 'server_deleted') ?>>Server Deleted</option>
<option value="credential_access" <?= selected($action, 'credential_access') ?>>Credential Access</option>
<option value="command_executed" <?= selected($action, 'command_executed') ?>>Command Executed</option>
<option value="user_created" <?= selected($action, 'user_created') ?>>User Created</option>
<option value="user_deleted" <?= selected($action, 'user_deleted') ?>>User Deleted</option>
<option value="logout" <?= selected($action, 'logout') ?>>Logout</option>
<option value="user_registered" <?= selected($action, 'user_registered') ?>>User Registered</option>
<option value="profile_updated" <?= selected($action, 'profile_updated') ?>>Profile Updated</option>
<option value="server_action" <?= selected($action, 'server_action') ?>>Server Action</option>
<option value="user_updated" <?= selected($action, 'user_updated') ?>>User Updated</option>
</select>
</th>
<th>
<select id="f_entity_type" class="form-select">
<option value="">All Entities</option>
<option value="user" <?= selected($entityType, 'user') ?>>User</option>
<option value="server" <?= selected($entityType, 'server') ?>>Server</option>
<option value="server_credentials" <?= selected($entityType, 'server_credentials') ?>>Credentials</option>
</select>
</th>
<th>
<div class="filter-input-wrap">
<input type="text" id="f_details" class="form-input filter-input" placeholder="Details..." value="<?= htmlspecialchars($details) ?>">
<?php if ($details !== ''): ?>
<button class="filter-clear" onclick="clearField('f_details')" title="Clear">&times;</button>
<?php endif; ?>
</div>
</th>
<th>
<div class="filter-input-wrap">
<input type="text" id="f_ip_address" class="form-input filter-input" placeholder="IP..." value="<?= htmlspecialchars($ipAddress) ?>">
<?php if ($ipAddress !== ''): ?>
<button class="filter-clear" onclick="clearField('f_ip_address')" title="Clear">&times;</button>
<?php endif; ?>
</div>
</th>
</tr>
</thead>
<tbody>
<?php foreach ($logs['data'] as $log): ?>
<tr class="audit-row <?= str_contains($log['action'] ?? '', 'failed') ? 'audit-row-danger' : '' ?>">
<td><?= htmlspecialchars($log['created_at'] ?? '') ?></td>
<td><?= htmlspecialchars($log['actor_name'] ?? $log['username'] ?? 'System') ?></td>
<td>
<span class="badge badge-<?= match(true) {
str_contains($log['action'] ?? '', 'failed') => 'danger',
str_contains($log['action'] ?? '', 'success') => 'success',
str_contains($log['action'] ?? '', 'deleted') => 'danger',
str_contains($log['action'] ?? '', 'created') => 'success',
default => 'info',
} ?>">
<?= htmlspecialchars(str_replace('_', ' ', $log['action'] ?? '')) ?>
</span>
</td>
<td><?= htmlspecialchars(($log['entity_type'] ?? '') . ' #' . ($log['entity_id'] ?? '')) ?></td>
<td>
<?php if ($log['details'] ?? false): ?>
<pre class="audit-details"><?= htmlspecialchars($log['details']) ?></pre>
<?php else: ?>
-
<?php endif; ?>
</td>
<td><code><?= htmlspecialchars($log['ip_address'] ?? '') ?></code></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php
$totalPages = $logs['total_pages'] ?? 0;
$currentPage = $logs['page'] ?? 1;
if ($totalPages > 1):
$window = 3;
$qs = function (int $p) use ($action, $username, $ipAddress, $entityType, $details, $dateFrom, $dateTo) {
return '?page=' . $p
. ($action !== '' ? '&amp;action=' . urlencode($action) : '')
. ($username !== '' ? '&amp;username=' . urlencode($username) : '')
. ($ipAddress !== '' ? '&amp;ip_address=' . urlencode($ipAddress) : '')
. ($entityType !== '' ? '&amp;entity_type=' . urlencode($entityType) : '')
. ($details !== '' ? '&amp;details=' . urlencode($details) : '')
. ($dateFrom !== '' ? '&amp;date_from=' . urlencode($dateFrom) : '')
. ($dateTo !== '' ? '&amp;date_to=' . urlencode($dateTo) : '');
};
?>
<div class="pagination">
<?php if ($currentPage > 1): ?>
<a href="<?= $qs($currentPage - 1) ?>" class="page-link">&laquo; Previous</a>
<?php endif; ?>
<?php
$showPages = [];
$showPages[] = 1;
if ($currentPage > $window + 2) {
$showPages[] = '...';
}
$start = max(2, $currentPage - $window);
$end = min($totalPages - 1, $currentPage + $window);
for ($i = $start; $i <= $end; $i++) {
$showPages[] = $i;
}
if ($currentPage < $totalPages - $window - 1) {
$showPages[] = '...';
}
if ($totalPages > 1) {
$showPages[] = $totalPages;
}
foreach ($showPages as $p):
?>
<?php if ($p === '...'): ?>
<span class="page-link page-ellipsis">…</span>
<?php else: ?>
<a href="<?= $qs($p) ?>" class="page-link <?= $p === $currentPage ? 'active' : '' ?>"><?= $p ?></a>
<?php endif; ?>
<?php endforeach; ?>
<?php if ($currentPage < $totalPages): ?>
<a href="<?= $qs($currentPage + 1) ?>" class="page-link">Next &raquo;</a>
<?php endif; ?>
</div>
<?php endif; ?>
</div>
</div>
<script src="/assets/js/audit-log.js"></script>