Problem: Frontend JS bundle used credentials:'same-origin' which dropped cookies on cross-domain requests. Login worked (200) but the subsequent /auth/me check returned 401, leaving the user stuck on the login screen. Fix: - AuthController now sets a dtp_jwt HttpOnly cookie on login/refresh - Cookie uses Domain=.fahrschultermin.de (shared between frontend and api subdomain), Secure, SameSite=Lax, Max-Age=8h - JwtMiddleware reads JWT from Authorization header OR cookie - Added AuthController::me() endpoint (was missing, caused 500) - Logout endpoint clears the cookie - Frontend index.php patches fetch() to use credentials:'include' for all /api/v1/* calls
57 lines
2.2 KiB
PHP
Executable File
57 lines
2.2 KiB
PHP
Executable File
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Services;
|
|
|
|
use App\Repositories\AppointmentRepository;
|
|
use App\Repositories\StudentRepository;
|
|
use App\Support\Database;
|
|
|
|
final class RequirementService
|
|
{
|
|
public function progressForStudent(int $studentId): array
|
|
{
|
|
$db = Database::connection();
|
|
$snapshots = (new StudentRepository())->requirements($studentId);
|
|
|
|
$statement = $db->prepare(
|
|
'SELECT au.requirement_key,
|
|
SUM(CASE WHEN a.status = "planned" THEN au.units_counted ELSE 0 END) AS planned_units,
|
|
SUM(CASE WHEN a.status = "completed" THEN au.units_counted ELSE 0 END) AS completed_units
|
|
FROM appointment_units au
|
|
JOIN appointments a ON a.id = au.appointment_id
|
|
WHERE a.student_id = :student_id
|
|
GROUP BY au.requirement_key'
|
|
);
|
|
$statement->execute(['student_id' => $studentId]);
|
|
$totals = [];
|
|
foreach ($statement->fetchAll() as $row) {
|
|
$totals[$row['requirement_key']] = [
|
|
'planned' => (int) $row['planned_units'],
|
|
'completed' => (int) $row['completed_units'],
|
|
];
|
|
}
|
|
|
|
return array_map(static function (array $snapshot) use ($totals): array {
|
|
$row = $totals[$snapshot['requirement_key']] ?? ['planned' => 0, 'completed' => 0];
|
|
$priorCompleted = (int) ($snapshot['prior_completed_units'] ?? 0);
|
|
$appointmentCompleted = (int) $row['completed'];
|
|
$completed = $priorCompleted + $appointmentCompleted;
|
|
$open = (int) $snapshot['required_units'] - $row['planned'] - $completed;
|
|
|
|
return [
|
|
'requirement_key' => $snapshot['requirement_key'],
|
|
'phase_label' => $snapshot['phase_label'] ?? '',
|
|
'label' => $snapshot['label'],
|
|
'required_units' => (int) $snapshot['required_units'],
|
|
'planned_units' => $row['planned'],
|
|
'completed_units' => $completed,
|
|
'prior_completed_units' => $priorCompleted,
|
|
'appointment_completed_units' => $appointmentCompleted,
|
|
'open_units' => $open,
|
|
];
|
|
}, $snapshots);
|
|
}
|
|
}
|