mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-05-06 11:09:18 +02:00
admin/system: add nginx config viewer tab
Add a 'nginx — config' tab to the Système admin page (system.php). - Reads /etc/nginx/sites-available/posterg (live deployed config) first; falls back to nginx/posterg.conf (local reference copy) when the live path is inaccessible (e.g. in dev, or wrong permissions). - Displays a colour-coded badge: green '● Config déployée' for live, amber '⚠ Référence locale' for the fallback. - Renders the full config in the shared .log-output code block with line numbers (data-n gutter via CSS ::before) and lightweight nginx syntax colouring (comments grey, block keywords purple, directives blue). - Reuses the existing copy-to-clipboard button. - Tab routing: activeTab validation extended to accept 'nginx_config'; log pre-loading guards skip when activeTab is 'nginx_config'. - No remote execution: read-only, zero new attack surface.
This commit is contained in:
@@ -190,10 +190,14 @@ const LOG_FILES = [
|
||||
|
||||
const ALLOWED_LINES = [50, 100, 200, 500];
|
||||
|
||||
// Active tab: 'status' or a log key
|
||||
// Nginx config paths (live deployed, then local reference fallback)
|
||||
const NGINX_CONFIG_LIVE = '/etc/nginx/sites-available/posterg';
|
||||
const NGINX_CONFIG_LOCAL = APP_ROOT . '/nginx/posterg.conf';
|
||||
|
||||
// Active tab: 'status', 'nginx_config', or a log key
|
||||
$activeTab = $_GET['tab'] ?? 'nginx_access';
|
||||
if ($activeTab === 'status') {
|
||||
$activeTab = 'status';
|
||||
if ($activeTab === 'status' || $activeTab === 'nginx_config') {
|
||||
// valid as-is
|
||||
} elseif (!array_key_exists($activeTab, LOG_FILES)) {
|
||||
$activeTab = 'nginx_access';
|
||||
}
|
||||
@@ -246,7 +250,7 @@ $logLines = null;
|
||||
$logError = null;
|
||||
$logFileMeta = null;
|
||||
|
||||
if ($activeTab !== 'status') {
|
||||
if ($activeTab !== 'status' && $activeTab !== 'nginx_config') {
|
||||
$logPath = LOG_FILES[$activeTab]['path'];
|
||||
$logLines = readLogTail($logPath, $selectedN, $logError);
|
||||
if (file_exists($logPath)) {
|
||||
@@ -260,6 +264,56 @@ if ($activeTab !== 'status') {
|
||||
}
|
||||
}
|
||||
|
||||
// Pre-load nginx config tab
|
||||
$nginxConfigLines = null;
|
||||
$nginxConfigSource = null;
|
||||
$nginxConfigError = null;
|
||||
$nginxConfigMeta = null;
|
||||
|
||||
if ($activeTab === 'nginx_config') {
|
||||
// Try live deployed config first, fall back to local reference copy
|
||||
$livePath = NGINX_CONFIG_LIVE;
|
||||
$localPath = NGINX_CONFIG_LOCAL;
|
||||
|
||||
if (file_exists($livePath) && is_readable($livePath)) {
|
||||
$raw = file($livePath, FILE_IGNORE_NEW_LINES);
|
||||
if ($raw !== false) {
|
||||
$nginxConfigLines = $raw;
|
||||
$nginxConfigSource = 'live';
|
||||
$sz = filesize($livePath);
|
||||
$nginxConfigMeta = [
|
||||
'path' => $livePath,
|
||||
'size' => $sz > 1048576
|
||||
? number_format($sz / 1048576, 2) . ' MB'
|
||||
: number_format($sz / 1024, 1) . ' KB',
|
||||
'mtime' => date('d/m/Y H:i:s', filemtime($livePath)),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
if ($nginxConfigLines === null && file_exists($localPath) && is_readable($localPath)) {
|
||||
$raw = file($localPath, FILE_IGNORE_NEW_LINES);
|
||||
if ($raw !== false) {
|
||||
$nginxConfigLines = $raw;
|
||||
$nginxConfigSource = 'local';
|
||||
$sz = filesize($localPath);
|
||||
$nginxConfigMeta = [
|
||||
'path' => $localPath,
|
||||
'size' => $sz > 1048576
|
||||
? number_format($sz / 1048576, 2) . ' MB'
|
||||
: number_format($sz / 1024, 1) . ' KB',
|
||||
'mtime' => date('d/m/Y H:i:s', filemtime($localPath)),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
if ($nginxConfigLines === null) {
|
||||
$nginxConfigError = file_exists($livePath)
|
||||
? "Fichier non lisible (permissions insuffisantes) : " . htmlspecialchars($livePath)
|
||||
: "Config live introuvable (" . htmlspecialchars($livePath) . ") et config locale introuvable (" . htmlspecialchars($localPath) . ").";
|
||||
}
|
||||
}
|
||||
|
||||
require_once APP_ROOT . '/templates/admin/head.php';
|
||||
?>
|
||||
|
||||
@@ -518,6 +572,33 @@ require_once APP_ROOT . '/templates/admin/head.php';
|
||||
text-decoration: none;
|
||||
}
|
||||
.sys-refresh-note a:hover { text-decoration: underline; }
|
||||
|
||||
/* ── Nginx config viewer ───────────────────────────────────────────────── */
|
||||
.nginx-source-badge {
|
||||
display: inline-block;
|
||||
font-size: .72rem;
|
||||
font-family: ui-monospace, monospace;
|
||||
padding: .15rem .55rem;
|
||||
border-radius: 3px;
|
||||
margin-left: .6rem;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.nginx-source-badge--live {
|
||||
background: rgba(76,175,80,.15);
|
||||
color: #4caf50;
|
||||
border: 1px solid rgba(76,175,80,.35);
|
||||
}
|
||||
.nginx-source-badge--local {
|
||||
background: rgba(255,193,7,.12);
|
||||
color: #ffc107;
|
||||
border: 1px solid rgba(255,193,7,.35);
|
||||
}
|
||||
/* Nginx syntax highlight layers inside .log-output */
|
||||
.nginx-comment { color: #666; font-style: italic; }
|
||||
.nginx-directive { color: #7eb8f7; }
|
||||
.nginx-block { color: #d4a0ff; font-weight: 600; }
|
||||
.nginx-value { color: #e2c08d; }
|
||||
.nginx-location { color: #79dac8; }
|
||||
</style>
|
||||
|
||||
<main class="admin-main">
|
||||
@@ -538,6 +619,8 @@ require_once APP_ROOT . '/templates/admin/head.php';
|
||||
<?= htmlspecialchars($def['label']) ?>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
<a href="?tab=nginx_config"
|
||||
class="sys-tab <?= $activeTab === 'nginx_config' ? 'active' : '' ?>">nginx — config</a>
|
||||
</nav>
|
||||
|
||||
<?php if ($activeTab === 'status'): ?>
|
||||
@@ -580,6 +663,60 @@ require_once APP_ROOT . '/templates/admin/head.php';
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php elseif ($activeTab === 'nginx_config'): ?>
|
||||
<!-- ════════════════════════════════════════════════════════════════════
|
||||
NGINX CONFIG PANEL
|
||||
════════════════════════════════════════════════════════════════════ -->
|
||||
|
||||
<?php if ($nginxConfigMeta): ?>
|
||||
<div class="log-meta">
|
||||
<span data-label="Fichier"><?= htmlspecialchars($nginxConfigMeta['path']) ?></span>
|
||||
<span data-label="Taille"><?= $nginxConfigMeta['size'] ?></span>
|
||||
<span data-label="Modifié"><?= $nginxConfigMeta['mtime'] ?></span>
|
||||
<?php if ($nginxConfigSource === 'live'): ?>
|
||||
<span class="nginx-source-badge nginx-source-badge--live">● Config déployée</span>
|
||||
<?php else: ?>
|
||||
<span class="nginx-source-badge nginx-source-badge--local">⚠ Référence locale (config live inaccessible)</span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($nginxConfigError !== null): ?>
|
||||
<div class="log-unavailable">
|
||||
<strong>Configuration nginx non disponible</strong>
|
||||
<div class="log-unavail-path"><?= htmlspecialchars($nginxConfigError) ?></div>
|
||||
<?php if (php_sapi_name() === 'cli-server'): ?>
|
||||
<div class="log-unavail-dev">
|
||||
En développement, <code>/etc/nginx/sites-available/posterg</code> n'existe pas.
|
||||
La config de référence se trouve dans <code>nginx/posterg.conf</code>.
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<?php elseif (empty($nginxConfigLines)): ?>
|
||||
<div class="log-empty">Le fichier de configuration est vide.</div>
|
||||
|
||||
<?php else: ?>
|
||||
<?php
|
||||
// Minimal nginx syntax coloring — applied per line
|
||||
function nginxLineClass(string $line): string {
|
||||
$trimmed = ltrim($line);
|
||||
if ($trimmed === '' || str_starts_with($trimmed, '#')) return 'nginx-comment';
|
||||
if (preg_match('/^\s*(location|server|upstream|events|http|geo|map|types)\b/', $line)) return 'nginx-block';
|
||||
return 'nginx-directive';
|
||||
}
|
||||
?>
|
||||
<div class="log-output" id="log-output" role="region" aria-label="Configuration nginx">
|
||||
<button class="log-copy-btn" id="log-copy-btn" type="button" title="Copier la configuration">
|
||||
Copier
|
||||
</button>
|
||||
<?php foreach ($nginxConfigLines as $i => $line): ?>
|
||||
<span class="log-line <?= nginxLineClass($line) ?>"
|
||||
data-n="<?= $i + 1 ?>"><?= htmlspecialchars($line, ENT_QUOTES | ENT_SUBSTITUTE) ?></span>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php else: ?>
|
||||
<!-- ════════════════════════════════════════════════════════════════════
|
||||
LOG PANEL
|
||||
|
||||
Reference in New Issue
Block a user