false, 'error' => 'Authentication required']); exit; } // CSRF protection for write requests if (in_array($_SERVER['REQUEST_METHOD'], ['POST', 'PUT', 'DELETE'])) { require_once dirname(__DIR__) . '/middleware/CsrfMiddleware.php'; $csrfToken = $_SERVER['HTTP_X_CSRF_TOKEN'] ?? ''; if (!CsrfMiddleware::validateToken($csrfToken)) { http_response_code(403); header('Content-Type: application/json'); echo json_encode(['success' => false, 'error' => 'Invalid CSRF token']); exit; } // Rotate token after successful validation; endpoints include it in their JSON response $GLOBALS['_new_csrf_token'] = CsrfMiddleware::rotateToken(); } header('Content-Type: application/json'); // Common variables $currentUser = $_SESSION['user']; $userId = $currentUser['user_id']; $isAdmin = $currentUser['is_admin'] ?? false; $conn = Database::getConnection(); /** * Output a JSON response, appending the rotated CSRF token so the * client-side lt.api interceptor can update window.CSRF_TOKEN. */ function apiRespond(array $data): void { if (!empty($GLOBALS['_new_csrf_token'])) { $data['csrf_token'] = $GLOBALS['_new_csrf_token']; } echo json_encode($data); exit; }