Files
xamxam/public/admin/thanks.php
Théophile Gervreau-Mercier 8613f71112 security: add PHP session auth guard for admin panel (item #2, CRITICAL)
- 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)
2026-02-08 14:22:45 +01:00

202 lines
7.4 KiB
PHP

<?php
// Bootstrap application
require_once __DIR__ . "/../../config/bootstrap.php";
require_once __DIR__ . '/../../lib/AdminAuth.php';
// PHP-level auth guard (defence-in-depth behind nginx Basic Auth)
AdminAuth::requireLogin();
// Configure error reporting
ini_set('display_errors', 0);
ini_set('log_errors', 1);
ini_set('error_log', 'error.log');
require __DIR__ . '/../../lib/Database.php';
// Security: Validate thesis ID parameter
$thesisId = null;
$thesis = null;
$files = [];
$error = null;
if (isset($_GET['id'])) {
$thesisId = filter_var($_GET['id'], FILTER_VALIDATE_INT);
if ($thesisId !== false && $thesisId > 0) {
try {
$db = new Database();
$pdo = $db->getPDO();
// Get thesis data
$thesis = $db->getThesis($thesisId);
if (!$thesis) {
$error = "TFE non trouvé.";
} else {
// Get associated files
$stmt = $pdo->prepare("
SELECT file_type, file_name, file_size, mime_type, uploaded_at
FROM thesis_files
WHERE thesis_id = ?
ORDER BY file_type, uploaded_at
");
$stmt->execute([$thesisId]);
$files = $stmt->fetchAll();
}
} catch (Exception $e) {
error_log("Error loading thesis: " . $e->getMessage());
$error = "Erreur lors de la lecture des données.";
}
} else {
error_log("Invalid thesis ID: " . $_GET['id']);
$error = "Identifiant invalide.";
}
} else {
$error = "Aucun identifiant spécifié.";
}
// Helper function to format file size
function formatFileSize($bytes) {
if ($bytes >= 1073741824) {
return number_format($bytes / 1073741824, 2) . ' GB';
} elseif ($bytes >= 1048576) {
return number_format($bytes / 1048576, 2) . ' MB';
} elseif ($bytes >= 1024) {
return number_format($bytes / 1024, 2) . ' KB';
} else {
return $bytes . ' bytes';
}
}
// Set page title for header
$pageTitle = "Merci";
?>
<?php require_once __DIR__ . '/inc/head.php'; ?>
<main>
<?php if ($error): ?>
<div class="error">
<p>⚠️ <?php echo htmlspecialchars($error); ?></p>
<p><a href="/admin/add.php">Retour au formulaire</a></p>
</div>
<?php elseif ($thesis): ?>
<p>d'avoir soumis votre TFE. Les informations ont été enregistrées et sont en attente de traitement.</p>
<div class="thesis-info">
<h2>Récapitulatif de votre soumission</h2>
<h3>Informations de base</h3>
<dl>
<dt>Identifiant:</dt>
<dd><strong><?php echo htmlspecialchars($thesis['identifier']); ?></strong></dd>
<dt>Titre:</dt>
<dd><?php echo htmlspecialchars($thesis['title']); ?></dd>
<?php if ($thesis['subtitle']): ?>
<dt>Sous-titre:</dt>
<dd><?php echo htmlspecialchars($thesis['subtitle']); ?></dd>
<?php endif; ?>
<dt>Auteur·ice(s):</dt>
<dd><?php echo htmlspecialchars($thesis['authors']); ?></dd>
<dt>Année:</dt>
<dd><?php echo htmlspecialchars($thesis['year']); ?></dd>
</dl>
<h3>Détails académiques</h3>
<dl>
<dt>Orientation:</dt>
<dd><?php echo htmlspecialchars($thesis['orientation'] ?? 'Non spécifié'); ?></dd>
<dt>Atelier Pratique:</dt>
<dd><?php echo htmlspecialchars($thesis['ap_program'] ?? 'Non spécifié'); ?></dd>
<dt>Finalité:</dt>
<dd><?php echo htmlspecialchars($thesis['finality_type'] ?? 'Non spécifié'); ?></dd>
<?php if ($thesis['supervisors']): ?>
<dt>Promoteur·ice(s):</dt>
<dd><?php echo htmlspecialchars($thesis['supervisors']); ?></dd>
<?php endif; ?>
</dl>
<h3>Contenu</h3>
<dl>
<?php if ($thesis['synopsis']): ?>
<dt>Synopsis:</dt>
<dd><?php echo nl2br(htmlspecialchars($thesis['synopsis'])); ?></dd>
<?php endif; ?>
<?php if ($thesis['languages']): ?>
<dt>Langue(s):</dt>
<dd><?php echo htmlspecialchars($thesis['languages']); ?></dd>
<?php endif; ?>
<?php if ($thesis['formats']): ?>
<dt>Format(s):</dt>
<dd><?php echo htmlspecialchars($thesis['formats']); ?></dd>
<?php endif; ?>
<?php if ($thesis['keywords']): ?>
<dt>Mots-clés:</dt>
<dd><?php echo htmlspecialchars($thesis['keywords']); ?></dd>
<?php endif; ?>
<?php if ($thesis['file_size_info']): ?>
<dt>Durée/Taille:</dt>
<dd><?php echo htmlspecialchars($thesis['file_size_info']); ?></dd>
<?php endif; ?>
<?php if ($thesis['baiu_link']): ?>
<dt>Lien:</dt>
<dd><a href="<?php echo htmlspecialchars($thesis['baiu_link']); ?>" target="_blank" rel="noopener noreferrer">
<?php echo htmlspecialchars($thesis['baiu_link']); ?>
</a></dd>
<?php endif; ?>
</dl>
<?php if (!empty($files)): ?>
<h3>Fichiers téléversés</h3>
<table>
<thead>
<tr>
<th>Type</th>
<th>Nom du fichier</th>
<th>Taille</th>
<th>Date</th>
</tr>
</thead>
<tbody>
<?php foreach ($files as $file): ?>
<tr>
<td><?php echo htmlspecialchars($file['file_type']); ?></td>
<td><?php echo htmlspecialchars($file['file_name']); ?></td>
<td><?php echo formatFileSize($file['file_size']); ?></td>
<td><?php echo date('d/m/Y H:i', strtotime($file['uploaded_at'])); ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php endif; ?>
<h3>Statut de publication</h3>
<p><strong>⏳ En attente</strong> - Votre TFE ne sera publié qu'après la soutenance et l'ajout éventuel d'une note contextuelle par le jury.</p>
<p class="submitted-date">
Soumis le <?php echo date('d/m/Y à H:i', strtotime($thesis['submitted_at'])); ?>
</p>
</div>
<p><a href="/admin/add.php">Soumettre un autre TFE</a></p>
<?php else: ?>
<p>Aucune donnée à afficher.</p>
<p><a href="/admin/add.php">Retour au formulaire</a></p>
<?php endif; ?>
</main>
<?php require_once __DIR__ . '/inc/footer.php'; ?>