src/EventSubscriber/SessionModulesSubscriber.php line 52

Open in your IDE?
  1. <?php
  2. namespace App\EventSubscriber;
  3. use App\Security\ModulesResolver;
  4. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  5. use Symfony\Component\HttpKernel\Event\RequestEvent;
  6. use Symfony\Component\HttpKernel\KernelEvents;
  7. use Symfony\Component\Security\Core\Security;
  8. use Symfony\Contracts\Cache\CacheInterface;
  9. use Symfony\Contracts\Cache\ItemInterface;
  10. class SessionModulesSubscriber implements EventSubscriberInterface
  11. {
  12.     private ModulesResolver $modulesResolver;
  13.     private CacheInterface $cache;
  14.     private Security $security;
  15.     public function __construct(ModulesResolver $modulesResolverCacheInterface $cacheSecurity $security)
  16.     {
  17.         $this->modulesResolver $modulesResolver;
  18.         $this->cache $cache;
  19.         $this->security $security;
  20.     }
  21.     public static function getSubscribedEvents(): array
  22.     {
  23.         return [
  24.             // Escuchamos el request. Prioridad 0 se ejecuta DESPUÉS del SessionListener y del Firewall 
  25.             // asegurando que el Token de seguridad esté cargado si el usuario está logueado.
  26.             KernelEvents::REQUEST => 'onKernelRequest',
  27.         ];
  28.     }
  29.     public function onKernelRequest(RequestEvent $event): void
  30.     {
  31.         // Solo nos interesa la petición principal (evitar sub-requests en twig)
  32.         if (!$event->isMainRequest()) {
  33.             return;
  34.         }
  35.         $request $event->getRequest();
  36.         
  37.         // Si no hay sesión, no hay nada que comprobar
  38.         if (!$request->hasSession()) {
  39.             return;
  40.         }
  41.         $session $request->getSession();
  42.         // Solo actuamos si el usuario ya está logueado y tiene módulos inicializados en esta sesión
  43.         if (!$session->has('_modules')) {
  44.             return;
  45.         }
  46.         // Obtener la versión global de los módulos desde la caché.
  47.         // Si no existe (ej. recién borrada por el ConfigurationController), se genera con el timestamp actual.
  48.         // Nota: cache.app suele venir configurada por defecto en Symfony.
  49.         $globalVersion $this->cache->get('global_modules_version', function (ItemInterface $item) {
  50.             $item->expiresAfter(31536000); // 1 Año de tiempo de vida
  51.             return time();
  52.         });
  53.         // Obtener la versión que tiene almacenada la sesión actual del usuario (por defecto 0 si acaba de loguearse)
  54.         $sessionVersion $session->get('session_modules_version'0);
  55.         // Si la versión de la sesión es anterior a la global, significa que la configuración global ha cambiado
  56.         if ($sessionVersion $globalVersion) {
  57.             $user $this->security->getUser();
  58.             
  59.             if ($user !== null) {
  60.                 // Recalculamos los permisos del usuario (que hace una llamada a la BD y verifica global y rol)
  61.                 $mods $this->modulesResolver->resolveForUser($user);
  62.                 
  63.                 // Actualizamos la sesión en caliente
  64.                 $session->set('_modules', (object) $mods);
  65.                 $session->set('_config'$this->modulesResolver->getGlobalConfiguration());
  66.             }
  67.             
  68.             // Actualizamos la versión de la sesión para que la comprobación if ($sessionVersion < $globalVersion) 
  69.             // devuelva false la próxima vez, ahorrando llamadas a base de datos.
  70.             $session->set('session_modules_version'$globalVersion);
  71.         }
  72.     }
  73. }