Review-Batch P0: Sicherheit + Schueler-Ergebnisse + Assessments-Aufblaehung

Sicherheit:
- progress.php: IDOR geschlossen (student_id-Zweig verlangt Lehrer-Login + Klassenbesitz)
- licenses.php: ?admin=1 und generate nur noch fuer echten Admin; Collision-Retry mit Cap
- .htaccess: .env/.sh/.sql/.bak Deny (Defense-in-Depth)

Schueler-Ergebnisse (kritisch):
- sim-metrics.js + .ivm-CSS in schueler.html; renderOwnRunCard-Fallback zeigt jetzt
  Sterne + grafische Kennzahlen fuer die 9 bisher leeren Sims
- sim-metrics.js: klima final_budget als "Mio EUR" statt "EUR" (Faktor 10^6)

Skalierung:
- assessment.php: Zwischen-Pings (phase running/started) nicht mehr persistiert
- heli: 30-s-assessmentPing entfernt (Live-Zustand laeuft ueber Heartbeat)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-08-15 16:21:25 +02:00
parent a3c5753cd7
commit 2984d93e7e
7 changed files with 65 additions and 14 deletions
+8 -7
View File
@@ -15,8 +15,7 @@ if ($method === 'GET') {
if (isset($_GET['admin']) && $_GET['admin'] === '1') {
Session::start();
$adminId = $_SESSION['admin_id'] ?? null;
$teacherId = Session::teacherId();
if (!$adminId && !$teacherId) {
if (!$adminId) {
Response::error('Nicht autorisiert', 401);
}
@@ -169,16 +168,18 @@ if ($method === 'POST') {
Response::ok(['licenseId' => (int)$license['id']]);
}
// Super-Admin: neue Lizenzen generieren
// Super-Admin: neue Lizenzen generieren (NUR echter Admin)
if ($action === 'generate') {
$teacherId = Session::requireTeacher();
Session::start();
if (empty($_SESSION['admin_id'])) Response::error('Nur Admin', 403);
$count = min(1000, max(1, (int)($body['count'] ?? 100)));
$year = (int)($body['year'] ?? date('Y'));
$schoolYear = ($year % 100) . '/' . (($year % 100) + 1);
$chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789';
$generated = 0;
for ($i = 0; $i < $count; $i++) {
$generated = 0; $tries = 0; $maxTries = $count * 10 + 100;
while ($generated < $count && $tries < $maxTries) {
$tries++;
$code = '';
for ($j = 0; $j < 3; $j++) {
if ($j > 0) $code .= '-';
@@ -189,7 +190,7 @@ if ($method === 'POST') {
$db->execute('INSERT INTO licenses (code, school_year) VALUES (?, ?)', [$code, $schoolYear]);
$generated++;
} catch (\Exception $e) {
$i--; // Collision, retry
// Kollision (unwahrscheinlich) → nächster Versuch; $maxTries schützt vor Endlosschleife
}
}
Response::ok(['generated' => $generated]);