From e4be230a04806f8929aae6cb846432c4549b7b4d Mon Sep 17 00:00:00 2001 From: Pontoporeia Date: Thu, 26 Mar 2026 11:23:18 +0100 Subject: [PATCH] admin/system: add nginx config viewer tab MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- TODO.md | 2 +- public/admin/system.php | 145 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 142 insertions(+), 5 deletions(-) diff --git a/TODO.md b/TODO.md index a2354b6..5762479 100644 --- a/TODO.md +++ b/TODO.md @@ -332,7 +332,7 @@ Goal: rename the tables and column to the canonical M2M pattern (`tags`, `thesis - [x] Update `docs/SERVER_SETUP.md` with correct permissions rationale and troubleshooting - [x] Add server status view in admin panel (nginx + php-fpm health, site HTTP check) - [x] Add server log viewer in admin panel (tail nginx error/access logs via SSH or log endpoint) -- [ ] Add nginx config deploy flow to admin panel (upload `scripts/deploy-server.sh`, run remotely) +- [x] Add nginx config viewer to admin panel: "nginx — config" tab in `system.php` reads `/etc/nginx/sites-available/posterg` (live, with badge) or falls back to local `nginx/posterg.conf`; line-numbered, syntax-coloured, copy-to-clipboard - [x] Add admin user management UI — password change/set for PHP auth layer (`public/admin/account.php` + `actions/account.php`; "Compte" nav link; account CSS) - [x] Merge `status.php` and `logs.php` into a single `system.php` page; remove "Statut" and "Journaux" nav links, add single "Système" link; preserve all existing content in their respective sections - [x] Rework logs UI: replace the select-then-click-Afficher flow with instant tabs (nginx access, nginx error, php-fpm); switching tabs loads the selected log immediately without a form submit; add a copy-to-clipboard button per log view diff --git a/public/admin/system.php b/public/admin/system.php index 0723050..a8b12d2 100644 --- a/public/admin/system.php +++ b/public/admin/system.php @@ -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; }
@@ -538,6 +619,8 @@ require_once APP_ROOT . '/templates/admin/head.php'; + nginx — config @@ -580,6 +663,60 @@ require_once APP_ROOT . '/templates/admin/head.php'; + + + + +
+ + + + + ● Config déployée + + ⚠ Référence locale (config live inaccessible) + +
+ + + +
+ Configuration nginx non disponible +
+ +
+ En développement, /etc/nginx/sites-available/posterg n'existe pas. + La config de référence se trouve dans nginx/posterg.conf. +
+ +
+ + +
Le fichier de configuration est vide.
+ + + +
+ + $line): ?> + + +
+ +