mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-06-27 00:59:18 +02:00
feat: prevent duplicate TFE submissions with logging and user feedback
- Add DuplicateThesisException (typed, carries existing thesis metadata) - Add Database::findDuplicateThesis(): matches on year + author + normalised title (exact, prefix, Levenshtein ≤10% of longer string) - ThesisCreateController::submit() runs duplicate check before any DB write and throws DuplicateThesisException on match - AppLogger::logDuplicate() writes status=duplicate entries to the JSON-lines log for audit purposes - App::flash/consumeFlash extended to support 'warning' flash type - admin/actions/formulaire.php: catches DuplicateThesisException, logs it, flashes an HTML warning toast with a clickable link to the existing thesis, and repopulates the form fields - partage/index.php: same catch block; surfaces a plain-text flash-warning banner on the student form with identifier, title, and year of the match; form is repopulated via session - toast.php: renders toast--warning variant - admin.css: .toast--warning + link colour rules - form.css: .flash-warning style for the partage form
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* MediaController
|
||||
*
|
||||
@@ -60,7 +61,7 @@ class MediaController
|
||||
exit;
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
error_log("MediaController visibility check error: " . $e->getMessage());
|
||||
error_log('MediaController visibility check error: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,7 +120,9 @@ class MediaController
|
||||
header('Cache-Control: public, max-age=86400');
|
||||
} elseif (in_array($ext, ['jpg','jpeg','png','gif','webp'], true)) {
|
||||
header('Cache-Control: public, max-age=604800');
|
||||
if (!$forceDownload) header('Content-Disposition: inline');
|
||||
if (!$forceDownload) {
|
||||
header('Content-Disposition: inline');
|
||||
}
|
||||
} elseif ($ext === 'pdf') {
|
||||
header('Cache-Control: public, max-age=86400');
|
||||
header('Content-Disposition: ' . ($forceDownload ? 'attachment' : 'inline'));
|
||||
@@ -163,10 +166,15 @@ class MediaController
|
||||
}
|
||||
[, $range] = explode('=', $range, 2);
|
||||
[$start, $end] = array_pad(explode('-', $range, 2), 2, '');
|
||||
$start = ($start === '') ? 0 : (int)$start;
|
||||
$end = ($end === '') ? $size - 1 : (int)$end;
|
||||
if ($end >= $size) $end = $size - 1;
|
||||
if ($start > $end) { http_response_code(416); exit; }
|
||||
$start = ($start === '') ? 0 : (int)$start;
|
||||
$end = ($end === '') ? $size - 1 : (int)$end;
|
||||
if ($end >= $size) {
|
||||
$end = $size - 1;
|
||||
}
|
||||
if ($start > $end) {
|
||||
http_response_code(416);
|
||||
exit;
|
||||
}
|
||||
|
||||
header('HTTP/1.1 206 Partial Content');
|
||||
header('Content-Range: bytes ' . $start . '-' . $end . '/' . $size);
|
||||
@@ -176,12 +184,17 @@ class MediaController
|
||||
}
|
||||
|
||||
$fp = fopen($path, 'rb');
|
||||
if ($fp === false) { http_response_code(500); exit; }
|
||||
if ($fp === false) {
|
||||
http_response_code(500);
|
||||
exit;
|
||||
}
|
||||
fseek($fp, $start);
|
||||
$remaining = $end - $start + 1;
|
||||
while ($remaining > 0 && !feof($fp)) {
|
||||
$chunk = fread($fp, min(8192, $remaining));
|
||||
if ($chunk === false) break;
|
||||
if ($chunk === false) {
|
||||
break;
|
||||
}
|
||||
echo $chunk;
|
||||
$remaining -= strlen($chunk);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user