es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Symfony 5 + Doctrine – Agregar un Filtro a cada solicitud, basado en el usuario actual.

Estoy tratando de establecer dinámicamente un filtro “tenant_id” en algunas acciones de mis controladores.

He creado una clase que extiende SQLFilter y he colocado dentro de addFilterConstraint la lógica para hacer eso.

El problema es el parámetro dinámico “tenant”:

Si coloco este fragmento de código dentro de cada una de las acciones de mis controladores, funciona:

$em->getFilters()->getFilter('tenant')->setParameter('tenant_id', $security->getUser()->getTenant()->getId());

Por supuesto, esto no es mantenible, así que estoy tratando de mover esta lógica a otro lugar para que sea más limpio y más fácil de mantener.

Estoy pensando en algo como un Evento, pero tendría que despachar un Evento en cada Request, cuando el Security ya haya hecho su trabajo y luego tendría que modificar el EntityManager.

¿Alguna idea?

Gracias.

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Una solución podría ser usar un event listener de kernel de Symfony. Puedes crear un listener para el evento kernel.controller, que se disparará antes de que se llame a cualquier acción del controlador. En este listener, puedes recuperar el EntityManager y establecer el parámetro tenant_id en el filtro tenant.

    Aquí tienes un ejemplo:

    1. Crea un nuevo servicio en tu archivo services.yaml:
      services:
         app.listener.tenant_filter_listener:
             class: App\EventListener\TenantFilterListener
             tags:
                 - { name: kernel.event_listener, event: kernel.controller }
      

      Esto registrará un nuevo listener para el evento kernel.controller.

    2. Crea una nueva clase TenantFilterListener:

      <?php
      
      namespace App\EventListener;
      
      use Doctrine\ORM\EntityManagerInterface;
      use Symfony\Component\HttpKernel\Event\ControllerEvent;
      
      class TenantFilterListener
      {
         private $entityManager;
      
         public function __construct(EntityManagerInterface $entityManager)
         {
             $this->entityManager = $entityManager;
         }
      
         public function onKernelController(ControllerEvent $event)
         {
             // Recupera el objeto Tenant del contexto de seguridad
             $tenantId = $event->getRequest()->getUser()->getTenant()->getId();
      
             // Establece el parámetro tenant_id en el filtro "tenant"
             $this->entityManager
                 ->getFilters()
                 ->getFilter("tenant")
                 ->setParameter("tenant_id", $tenantId);
         }
      }
      

      Este listener recupera el EntityManager, obtiene el filtro tenant y establece el parámetro tenant_id con el ID del tenant actual del contexto de seguridad.

    3. Asegúrate de tener el filtro tenant registrado en tu configuración de Doctrine:

      doctrine:
         dbal:
             # ...
         orm:
             auto_generate_proxy_classes: true
             filters:
                 tenant:
                     class: App\Doctrine\TenantFilter
                     enabled: true
      

    4. ¡Eso es todo! Ahora cada vez que se llame a una acción del controlador, el filtro tenant se aplicará automáticamente con el ID de tenant correcto.

    Ten en cuenta que necesitarás tener configurada la configuración de seguridad correcta para recuperar el usuario actual y el ID del tenant. Este es solo un ejemplo para darte una idea de cómo usar un event listener para establecer dinámicamente un parámetro de filtro.

Comments are closed.