mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-05-06 19:19:19 +02:00
- lib/AdminAuth.php: new class with requireLogin(), login(), logout(), isAuthenticated(); starts session with hardened cookie params (HttpOnly, SameSite=Strict, Secure, Path=/admin) — also resolves item #8 (session cookie hardening) - requireLogin() auto-authenticates from nginx Basic Auth credentials ($_SERVER['PHP_AUTH_PW']) so the user only sees one browser prompt; falls back to /admin/login.php if the proxy is absent/misconfigured - config/admin_credentials.php: gitignored credential store; define ADMIN_PASSWORD_HASH with a bcrypt hash to enable PHP auth - config/admin_credentials.example.php: template for the above - config/bootstrap.php: auto-loads admin_credentials.php if present - .gitignore: exclude config/admin_credentials.php - public/admin/login.php: fallback login form (shown only when nginx Basic Auth is bypassed / proxy absent) - public/admin/logout.php: session destruction + redirect to login - All 7 admin PHP files: replace session_start() with AdminAuth::requireLogin() (defence-in-depth behind nginx Basic Auth) - public/admin/inc/head.php: Déconnexion button when ADMIN_PASSWORD_HASH is defined - nginx/PHP_AUTH_LAYER.md: documents dual-auth architecture, UX flow, and setup instructions - docs/TODO.SECURITY.md: items #2 and #8 moved to Resolved; priority order updated (all CRITICAL done)
69 lines
2.8 KiB
PHP
69 lines
2.8 KiB
PHP
<!DOCTYPE html>
|
||
<html lang="fr">
|
||
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title><?php echo htmlspecialchars($pageTitle ?? 'Admin'); ?> - Post-ERG</title>
|
||
<link rel="stylesheet" href="/assets/modern-normalize.min.css">
|
||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/water.css@2/out/water.css">
|
||
<link rel="stylesheet" href="/assets/admin.css">
|
||
<link rel="shortcut icon" href="/assets/admin_favicon.svg" type="image/svg+xml">
|
||
<?php if (php_sapi_name() === 'cli-server'): ?>
|
||
<!-- Live reload for development -->
|
||
<script>
|
||
(function poll() {
|
||
fetch('/live-reload.php')
|
||
.then(r => r.json())
|
||
.then(d => { if (d.changed) location.reload(); else setTimeout(poll, 1000); })
|
||
.catch(() => setTimeout(poll, 2000));
|
||
})();
|
||
</script>
|
||
<?php endif; ?>
|
||
</head>
|
||
|
||
<body>
|
||
<header>
|
||
<h1><?php echo htmlspecialchars($pageTitle ?? 'Admin'); ?></h1>
|
||
<nav>
|
||
<?php
|
||
// Detect current page
|
||
$currentPage = basename($_SERVER['PHP_SELF']);
|
||
$thesisId = $_GET['id'] ?? null;
|
||
|
||
// Build navigation based on context
|
||
$navLinks = [];
|
||
|
||
// Always show list
|
||
if ($currentPage !== 'index.php') {
|
||
$navLinks[] = '<a href="/admin/"><button>📋 Liste des TFE</button></a>';
|
||
}
|
||
|
||
// Show add thesis if not on add page
|
||
if ($currentPage !== 'add.php') {
|
||
$navLinks[] = '<a href="/admin/add.php"><button>➕ Ajouter un TFE</button></a>';
|
||
}
|
||
|
||
// Show import if not on import page
|
||
if ($currentPage !== 'import.php') {
|
||
$navLinks[] = '<a href="/admin/import.php"><button>📥 Importer CSV</button></a>';
|
||
}
|
||
|
||
// If on edit or thanks page with thesis ID, show edit and view links
|
||
if ($thesisId && in_array($currentPage, ['edit.php', 'thanks.php'])) {
|
||
if ($currentPage !== 'edit.php') {
|
||
$navLinks[] = '<a href="/admin/edit.php?id=' . intval($thesisId) . '"><button>✏️ Modifier</button></a>';
|
||
}
|
||
if ($currentPage !== 'thanks.php') {
|
||
$navLinks[] = '<a href="/admin/thanks.php?id=' . intval($thesisId) . '"><button>👁️ Voir</button></a>';
|
||
}
|
||
}
|
||
|
||
echo implode(' ', $navLinks);
|
||
?>
|
||
<?php if (defined('ADMIN_PASSWORD_HASH')): ?>
|
||
<a href="/admin/logout.php"><button>🔐 Déconnexion</button></a>
|
||
<?php endif; ?>
|
||
</nav>
|
||
</header>
|