235 lines
11 KiB
PHP
235 lines
11 KiB
PHP
<?php
|
|
require_once '../includes/db.php';
|
|
require_once '../includes/functions.php';
|
|
requireRole('admin');
|
|
|
|
// --- Handle Actions ---
|
|
$successMsg = '';
|
|
$errorMsg = '';
|
|
|
|
// Delete Backup
|
|
if (isset($_POST['delete_backup'])) {
|
|
$fileToDelete = basename($_POST['file_name']);
|
|
$filePath = "backups/" . $fileToDelete;
|
|
if (file_exists($filePath)) {
|
|
unlink($filePath);
|
|
logActivity($_SESSION['admin_id'], 'BACKUP_DELETE', "Deleted backup: $fileToDelete");
|
|
$successMsg = "Backup deleted successfully.";
|
|
}
|
|
}
|
|
|
|
// --- Resource Monitoring Calculations ---
|
|
$totalSpace = disk_total_space("/");
|
|
$freeSpace = disk_free_space("/");
|
|
$usedSpace = $totalSpace - $freeSpace;
|
|
$usedPercent = round(($usedSpace / $totalSpace) * 100, 1);
|
|
|
|
function getDirSize($dir) {
|
|
$size = 0;
|
|
if (is_dir($dir)) {
|
|
foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir)) as $file) {
|
|
$size += $file->getSize();
|
|
}
|
|
}
|
|
return $size;
|
|
}
|
|
$audioSize = getDirSize("../assets/uploads/audio");
|
|
$imageSize = getDirSize("../assets/uploads/images");
|
|
$podcastPercent = round(($audioSize / $totalSpace) * 100, 2);
|
|
|
|
$load = sys_getloadavg();
|
|
$cpuLoad = $load[0] * 100 / 4;
|
|
|
|
// --- Backup List ---
|
|
$backupDir = "backups";
|
|
if (!is_dir($backupDir)) mkdir($backupDir, 0755, true);
|
|
$backups = array_filter(glob($backupDir . "/*.tar.gz"), 'is_file');
|
|
|
|
// Sort by date (mtime) descending
|
|
usort($backups, function($a, $b) {
|
|
return filemtime($b) - filemtime($a);
|
|
});
|
|
|
|
// --- Activity Logs ---
|
|
$stmt = $pdo->query("SELECT * FROM activity_log ORDER BY timestamp DESC LIMIT 100");
|
|
$logs = $stmt->fetchAll();
|
|
|
|
function formatBytes($bytes, $precision = 2) {
|
|
$units = array('B', 'KB', 'MB', 'GB', 'TB');
|
|
$bytes = max($bytes, 0);
|
|
$pow = floor(($bytes ? log($bytes) : 0) / log(1024));
|
|
$pow = min($pow, count($units) - 1);
|
|
$bytes /= pow(1024, $pow);
|
|
return round($bytes, $precision) . ' ' . $units[$pow];
|
|
}
|
|
?>
|
|
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>System Management - <?php echo getSetting($pdo, 'site_title'); ?></title>
|
|
<link rel="stylesheet" href="../assets/css/style.css">
|
|
<style>
|
|
.system-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 2rem; margin-top: 2rem; }
|
|
.gauge-container { text-align: center; margin-top: 1rem; }
|
|
.gauge-bar { background: rgba(255,255,255,0.05); height: 12px; border-radius: 6px; overflow: hidden; margin-top: 10px; }
|
|
.gauge-fill { height: 100%; transition: width 1s ease-out; }
|
|
.backup-list { width: 100%; border-collapse: collapse; margin-top: 1.5rem; }
|
|
.backup-list th, .backup-list td { padding: 1rem; text-align: left; border-bottom: 1px solid var(--glass-border); }
|
|
.status-badge { padding: 0.25rem 0.75rem; border-radius: 20px; font-size: 0.75rem; font-weight: 600; }
|
|
.log-window {
|
|
background: rgba(15, 23, 42, 0.8);
|
|
border: 1px solid var(--glass-border);
|
|
border-radius: 12px;
|
|
height: 300px;
|
|
overflow-y: scroll;
|
|
padding: 1rem;
|
|
font-family: 'Courier New', Courier, monospace;
|
|
font-size: 0.85rem;
|
|
color: #10b981;
|
|
}
|
|
.log-entry { margin-bottom: 0.5rem; padding-bottom: 0.5rem; border-bottom: 1px solid rgba(255,255,255,0.05); }
|
|
.log-time { color: var(--text-muted); margin-right: 1rem; }
|
|
.log-action { font-weight: 600; text-transform: uppercase; margin-right: 1rem; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<nav>
|
|
<a href="<?php echo PROJECT_ROOT_URL; ?>/" class="logo">Admin Dashboard</a>
|
|
<div class="nav-links">
|
|
<a href="dashboard.php">Episodes</a>
|
|
<a href="upload.php">Upload New</a>
|
|
<a href="settings.php">Site Settings</a>
|
|
<a href="users.php">Manage Users</a>
|
|
<a href="system.php" style="color: var(--primary-color);">System</a>
|
|
<a href="logout.php">Logout</a>
|
|
</div>
|
|
</nav>
|
|
|
|
<div class="container" style="margin-top: 3rem;">
|
|
<?php if ($successMsg): ?>
|
|
<p style="color: #10b981; margin-bottom: 2rem;"><?php echo $successMsg; ?></p>
|
|
<?php endif; ?>
|
|
|
|
<h2>System Resource Overview</h2>
|
|
|
|
<div class="system-grid">
|
|
<div class="episode-card" style="margin-bottom: 0;">
|
|
<h3>Disk Storage</h3>
|
|
<div class="gauge-container">
|
|
<div style="display: flex; justify-content: space-between; font-size: 0.9rem;">
|
|
<span>Used: <?php echo formatBytes($usedSpace); ?></span>
|
|
<span>Total: <?php echo formatBytes($totalSpace); ?></span>
|
|
</div>
|
|
<div class="gauge-bar"><div class="gauge-fill" style="width: <?php echo $usedPercent; ?>%; background: var(--primary-color);"></div></div>
|
|
<p style="margin-top: 1rem; font-size: 0.8rem; color: var(--text-muted);">Podcast Files: <?php echo formatBytes($audioSize); ?> (<?php echo $podcastPercent; ?>% of total)</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="episode-card" style="margin-bottom: 0;">
|
|
<h3>Server Load</h3>
|
|
<div class="gauge-container">
|
|
<div style="display: flex; justify-content: space-between; font-size: 0.9rem;">
|
|
<span>CPU Load</span>
|
|
<span><?php echo round($cpuLoad, 1); ?>%</span>
|
|
</div>
|
|
<div class="gauge-bar"><div class="gauge-fill" style="width: <?php echo min(100, $cpuLoad); ?>%; background: <?php echo $cpuLoad > 80 ? '#ef4444' : '#10b981'; ?>;"></div></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div style="display: flex; justify-content: space-between; align-items: center; margin-top: 4rem;">
|
|
<h2>System Backups</h2>
|
|
<form action="backup_handler.php" method="POST">
|
|
<button type="submit" name="generate_backup" class="btn btn-primary">🚀 Generate Full Backup</button>
|
|
</form>
|
|
</div>
|
|
|
|
<div class="episode-card" style="margin-top: 2rem;">
|
|
<?php if (empty($backups)): ?>
|
|
<p style="text-align: center; color: var(--text-muted); padding: 2rem;">No backups found.</p>
|
|
<?php else: ?>
|
|
<table class="backup-list">
|
|
<thead>
|
|
<tr>
|
|
<th>Backup Name</th>
|
|
<th>Date Created</th>
|
|
<th>Size</th>
|
|
<th>Type</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($backups as $file):
|
|
$name = basename($file);
|
|
$date = date("F j, Y, g:i a", filemtime($file));
|
|
$size = formatBytes(filesize($file));
|
|
$type = strpos($name, 'db') !== false ? 'Database' : (strpos($name, 'audio') !== false ? 'Audio' : 'Site');
|
|
?>
|
|
<tr>
|
|
<td style="font-family: monospace; font-size: 0.85rem;"><?php echo $name; ?></td>
|
|
<td><?php echo $date; ?></td>
|
|
<td><?php echo $size; ?></td>
|
|
<td><span class="status-badge" style="background: rgba(99,102,241,0.1); color: var(--primary-color);"><?php echo $type; ?></span></td>
|
|
<td style="display: flex; gap: 1rem;">
|
|
<a href="<?php echo $file; ?>" download style="color: var(--primary-color); text-decoration: none; font-weight: 600;">Download</a>
|
|
<form method="POST" onsubmit="return confirm('Delete this backup file?')">
|
|
<input type="hidden" name="file_name" value="<?php echo $name; ?>">
|
|
<button type="submit" name="delete_backup" style="background: none; border: none; color: #ef4444; cursor: pointer; font-weight: 600; padding: 0;">Delete</button>
|
|
</form>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
<div style="margin-top: 4rem;">
|
|
<h2>System Activity Log</h2>
|
|
<div class="log-window">
|
|
<?php foreach ($logs as $log):
|
|
$color = (strpos($log['action'], 'FAILED') !== false || strpos($log['action'], 'UNAUTHORIZED') !== false) ? '#ef4444' : '#10b981';
|
|
?>
|
|
<div class="log-entry">
|
|
<span class="log-time">[<?php echo $log['timestamp']; ?>]</span>
|
|
<span class="log-action" style="color: <?php echo $color; ?>;"><?php echo $log['action']; ?></span>
|
|
<span class="log-user">User: <?php echo htmlspecialchars($log['username']); ?></span>
|
|
<div style="margin-left: 2rem; color: #94a3b8; margin-top: 0.25rem;">
|
|
Details: <?php echo htmlspecialchars($log['details']); ?>
|
|
<span style="font-size: 0.75rem; opacity: 0.5;">(IP: <?php echo $log['ip_address']; ?>)</span>
|
|
</div>
|
|
</div>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
</div>
|
|
|
|
<div style="margin-top: 4rem; padding: 3rem; background: rgba(239, 68, 68, 0.05); border: 1px solid rgba(239, 68, 68, 0.2); border-radius: 24px;">
|
|
<h2 style="color: #ef4444;">System Restoration</h2>
|
|
<p style="color: var(--text-muted); margin-top: 1rem;">Upload your backup .tar.gz files to restore the system.</p>
|
|
|
|
<form action="restore_handler.php" method="POST" enctype="multipart/form-data" style="margin-top: 2rem; display: grid; gap: 1.5rem;" onsubmit="return confirm('DANGER: This will overwrite your entire site and database. Are you absolutely sure?')">
|
|
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 1rem;">
|
|
<div class="form-group">
|
|
<label>Audio Backup (.tar.gz)</label>
|
|
<input type="file" name="backup_audio" accept=".tar.gz,.gz" required>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Database Backup (.tar.gz)</label>
|
|
<input type="file" name="backup_db" accept=".tar.gz,.gz" required>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Site Files Backup (.tar.gz)</label>
|
|
<input type="file" name="backup_site" accept=".tar.gz,.gz" required>
|
|
</div>
|
|
</div>
|
|
<button type="submit" class="btn" style="background: #ef4444; color: white;">Start System Restoration</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<?php include '../includes/footer.php'; ?>
|
|
</body>
|
|
</html>
|