public/index.php line 54

Open in your IDE?
  1. <?php
  2. include_once __DIR__ . '/../vendor/autoload.php'; // Define auto loading for classes
  3. use App\Infrastructure;
  4. use App\Kernel;
  5. use Symfony\Component\ErrorHandler\Debug;
  6. use Symfony\Component\HttpFoundation\Request;
  7. global $kernel, $connection, $twig, $entityManager, $logger, $app;
  8. if ($_SERVER['APP_DEBUG'] ?? false) {
  9.     umask(0000);
  10.     Debug::enable();
  11. }
  12. if ($trustedProxies = $_SERVER['TRUSTED_PROXIES'] ?? false) {
  13.     Request::setTrustedProxies(explode(',', $trustedProxies), Request::HEADER_X_FORWARDED_FOR | Request::HEADER_X_FORWARDED_PORT | Request::HEADER_X_FORWARDED_PROTO);
  14. }
  15. if ($trustedHosts = $_SERVER['TRUSTED_HOSTS'] ?? false) {
  16.     Request::setTrustedHosts([$trustedHosts]);
  17. }
  18. $kernel = new Kernel($_SERVER['APP_ENV'], (bool) ($_SERVER['APP_DEBUG'] ?? false));
  19. $kernel->boot();
  20. $container = $kernel->getContainer();
  21. $session = null;
  22. // If this variable is set to anything, we should not start the session. This
  23. // is really only useful during the docker build process.
  24. if (getenv('DISABLE_SESSIONS') === false) {
  25.     $session = $container->get('session');
  26.     $session->start();
  27. }
  28. $twig = $container->get('twig');
  29. /** @var \Doctrine\DBAL\Connection $connection */
  30. $connection = $container->get('database_connection');
  31. $entityManager = $container->get('doctrine.orm.entity_manager');
  32. $logger = $container->get('logger');
  33. $app = [
  34.     'db' => $connection,
  35.     'twig' => $twig,
  36.     'orm.em' => $entityManager,
  37.     'logger' => $logger,
  38.     'session' => $session,
  39. ];
  40. $request = Request::createFromGlobals();
  41. $response = $kernel->handle($request);
  42. $scriptFile = Infrastructure\LegacyBridge::prepareLegacyScript($request, $response, __DIR__);
  43. if ($scriptFile !== null) {
  44.     // RouterListener (priority 32) throws NotFoundHttpException for legacy routes
  45.     // before PermissionsCheckSubscriber (priority 0) or access_control can run.
  46.     // Both auth and permission checks must happen here, as the sole gateway.
  47.     $legacyPath = trim($request->getPathInfo(), '/');
  48.     $isOpenPath = in_array($legacyPath, ['login', 'logout']);
  49.     // 1. Auth: unauthenticated users go to login.
  50.     if (!$isOpenPath && !($session?->has('user') ?? false)) {
  51.         (new \Symfony\Component\HttpFoundation\RedirectResponse('/login'))->send();
  52.         $kernel->terminate($request, $response);
  53.         exit;
  54.     }
  55.     // 2. Permissions: check sitestructure for authenticated users.
  56.     //    has_permission() is available via composer files autoload (functions.php).
  57.     //    Paths under includes/ are AJAX/utility endpoints that have no sitestructure
  58.     //    row — they rely on their own internal permission checks, so skip them here.
  59.     //    payroll.php and reports.php use query-string-dependent permission rows.
  60.     $isIncludePath = strpos($legacyPath, 'includes') !== false;
  61.     if (!$isOpenPath && !$isIncludePath) {
  62.         $permPath = $legacyPath;
  63.         if (in_array($legacyPath, ['payroll.php', 'reports.php']) && $request->getQueryString()) {
  64.             $permPath .= '?' . $request->getQueryString();
  65.         }
  66.         if (!has_permission($connection, $permPath) && !has_permission($connection, '/' . $permPath)) {
  67.             (new \Symfony\Component\HttpFoundation\RedirectResponse('/login'))->send();
  68.             $kernel->terminate($request, $response);
  69.             exit;
  70.         }
  71.     }
  72.     require $scriptFile;
  73. } else {
  74.     $response->send();
  75. }
  76. $kernel->terminate($request, $response);