src/EventListener/RequestListener.php line 164

Open in your IDE?
  1. <?php
  2. namespace App\EventListener;
  3. use App\Controller\AccessDeniedController;
  4. use App\Entity\User;
  5. use App\Entity\WebService;
  6. use App\Entity\WebServiceLog;
  7. use App\Repository\DomainRepository;
  8. use App\Repository\UserRepository;
  9. use App\Service\Misc;
  10. use App\Service\OrganisationService;
  11. use Doctrine\ORM\EntityManagerInterface;
  12. use Doctrine\ORM\NonUniqueResultException;
  13. use GraphQL\Utils\AST;
  14. use Overblog\GraphQLBundle\Request\Parser;
  15. use Symfony\Component\DependencyInjection\ContainerInterface;
  16. use Symfony\Component\HttpFoundation\RedirectResponse;
  17. use Symfony\Component\HttpFoundation\Request;
  18. use Symfony\Component\HttpFoundation\RequestStack;
  19. use Symfony\Component\HttpFoundation\Response;
  20. use Symfony\Component\HttpKernel\Event\ControllerEvent;
  21. use Symfony\Component\HttpKernel\Event\ResponseEvent;
  22. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  23. use Symfony\Component\Security\Core\Security;
  24. readonly class RequestListener
  25. {
  26.     public function __construct(
  27.         private Security               $security,
  28.         private UrlGeneratorInterface  $router,
  29.         private Misc                   $misc,
  30.         private RequestStack           $requestStack,
  31.         private UserRepository         $userRepository,
  32.         private DomainRepository       $domainRepository,
  33.         private EntityManagerInterface $entityManager,
  34.         private ContainerInterface     $container,
  35.         private OrganisationService    $organisationService
  36.     )
  37.     {
  38.     }
  39.     /**
  40.      * @throws NonUniqueResultException
  41.      */
  42.     public function onKernelController(ControllerEvent $event): void
  43.     {
  44.         /**
  45.          * @var User $user
  46.          */
  47.         $user $this->security->getUser();
  48.         if ($user && $event->isMainRequest() && $user->isCustomer()) {
  49.             $controller $event->getController();
  50.             if (in_array($controller[1], ['chooseOrganisation''choose'])) {
  51.                 return;
  52.             }
  53.             $session $this->requestStack->getSession();
  54.             // Verifier si l'utilisateur a plusieurs organisation
  55.             if (
  56.                 $this->userRepository->getCountOrga($user) > &&
  57.                 $session->get('organisation'null) === null &&
  58.                 !in_array($controller[1], ['chooseOrganisation''choose''endpointAction'])
  59.             ) {
  60.                 $event->stopPropagation();
  61.                 $router $this->router;
  62.                 $event->setController(static function () use ($router) {
  63.                     return new RedirectResponse($router->generate('choose_organisation'));
  64.                 });
  65.             }
  66.             if ($controller[1] === 'endpointAction') {
  67.                 $domainId $this->requestStack->getCurrentRequest()?->get('id'0);
  68.                 $routeName $this->requestStack->getCurrentRequest()?->attributes->get('name');
  69.                 if (
  70.                     $domainId === &&
  71.                     !$this->isAllowedCall()
  72.                 ) {
  73.                     $event->stopPropagation();
  74.                     $event->setController(static function () {
  75.                         return new Response(
  76.                             'Domain ID is required.',
  77.                             Response::HTTP_FORBIDDEN
  78.                         );
  79.                     });
  80.                     return;
  81.                 }
  82.                 $domain $this->domainRepository->getDomainByUserAndId(
  83.                     $user->getId(),
  84.                     $domainId
  85.                 );
  86.                 $organisation $domain?->getOrganisation();
  87.                 $sub $this->misc->getActifSubsription($organisation);
  88.                 if (
  89.                     ($organisation === null || !$organisation->getIsAdded()) &&
  90.                     !$this->isAllowedCall()
  91.                 ) {
  92.                     $event->stopPropagation();
  93.                     $event->setController(static function () {
  94.                         return new Response(
  95.                             'Requested resources didn\'t exist.',
  96.                             Response::HTTP_UNAUTHORIZED
  97.                         );
  98.                     });
  99.                 }else if (
  100.                     ($sub === null) &&
  101.                     !$this->isAllowedCall()
  102.                 ) {
  103.                     $event->stopPropagation();
  104.                     $event->setController(static function () {
  105.                         return new Response(
  106.                             'Your subscription has expired.',
  107.                             Response::HTTP_FORBIDDEN
  108.                         );
  109.                     });
  110.                 }
  111.                 if ($organisation && $routeName === 'publicEndpoint') {
  112.                     $this->organisationService->setupConsumedQuota($organisation);
  113.                     if ($organisation->getQuota() <= $organisation->getConsumedQuota()) {
  114.                         $event->stopPropagation();
  115.                         $event->setController(static function () {
  116.                             return new Response(
  117.                                 'you have exceeded your quota.',
  118.                                 Response::HTTP_TOO_MANY_REQUESTS
  119.                             );
  120.                         });
  121.                     }
  122.                 }
  123.             } else {
  124.                 $organisation $this->misc->getUserOrganisation($user);
  125.                 $sub $this->misc->getActifSubsription($organisation);
  126.                 if (
  127.                     !($controller[0] instanceof AccessDeniedController) &&
  128.                     ($organisation === null || $sub === null || !$organisation->getIsAdded())
  129.                 ) {
  130.                     $event->stopPropagation();
  131.                     // Set your custom controller that produces a 403 response
  132.                     $router $this->router;
  133.                     $event->setController(static function () use ($router) {
  134.                         return new RedirectResponse($router->generate('access_denied'));
  135.                     });
  136.                 } elseif (
  137.                     $controller[0] instanceof AccessDeniedController &&
  138.                     $sub &&
  139.                     $organisation->getIsAdded() &&
  140.                     !in_array($controller[1], ['chooseOrganisation''choose'])
  141.                 ) {
  142.                     $router $this->router;
  143.                     $event->setController(static function () use ($router) {
  144.                         return new RedirectResponse($router->generate('home'));
  145.                     });
  146.                 }
  147.             }
  148.         }
  149.     }
  150.     public function onKernelResponse(ResponseEvent $event): void
  151.     {
  152.         try {
  153.             $response $event->getResponse()->getContent();
  154.             $decodedResponse json_decode($responsetrue512JSON_THROW_ON_ERROR);
  155.             $routeName $this->requestStack->getCurrentRequest()?->attributes->get('name');
  156.             if ($routeName === 'publicEndpoint') {
  157.                 if (
  158.                     !isset($decodedResponse['errors']) &&
  159.                     $event->getResponse()->isSuccessful()
  160.                 ) {
  161.                     $this->manageWebServiceStats();
  162.                 }
  163.             }
  164.         } catch (\Exception $e) {
  165.         }
  166.     }
  167.     /**
  168.      * @return bool
  169.      */
  170.     private function isAllowedCall(): bool
  171.     {
  172.         $functionNames $this->getGraphQLFunctionName($this->requestStack->getCurrentRequest());
  173.         return count(
  174.                 array_intersect(
  175.                     [
  176.                         'updateProfile''getProfile''enable2fAuth''getDomain''__schema',
  177.                         'recoverPassword''forgotPassword''upsertOrganisation''getIndustry'
  178.                     ],
  179.                     $functionNames
  180.                 )
  181.             ) > 0;
  182.     }
  183.     /**
  184.      * @param Request $request
  185.      * @return array|string[]
  186.      */
  187.     private function getGraphQLFunctionName(Request $request): array
  188.     {
  189.         try {
  190.             $requestParser = new Parser();
  191.             $parse $requestParser->parse($request);
  192.             $parse2 \GraphQL\Language\Parser::parse($parse['query']);
  193.             $array AST::toArray($parse2);
  194.             $functions = [];
  195.             foreach ($array['definitions'] as $definition) {
  196.                 foreach ($definition['selectionSet']['selections'] as $selection) {
  197.                     if (!in_array($selection['name']['value'], $functionstrue)) {
  198.                         $functions[] = $selection['name']['value'];
  199.                     }
  200.                 }
  201.             }
  202.             return $functions;
  203.         } catch (\Exception $e) {
  204.             return ['Invalid request'];
  205.         }
  206.     }
  207.     /**
  208.      * @return void
  209.      */
  210.     private function manageWebServiceStats(): void
  211.     {
  212.         $user $this->security->getUser();
  213.         $functionNames $this->getGraphQLFunctionName($this->requestStack->getCurrentRequest());
  214.         foreach ($functionNames as $functionName) {
  215.             if (!in_array($functionName$this->getResolverAndMutation(), true)) {
  216.                 continue;
  217.             }
  218.             $ws $this->entityManager->getRepository(WebService::class)->findOneBy(['name' => $functionName]);
  219.             if (!$ws) {
  220.                 $ws = new WebService();
  221.                 $ws->setName($functionName);
  222.                 $this->entityManager->persist($ws);
  223.             }
  224.             $ws->addWebServiceLog(
  225.                 (new WebServiceLog())
  226.                     ->setCalledBy($user)
  227.             );
  228.         }
  229.         $this->entityManager->flush();
  230.     }
  231.     /**
  232.      * @return array
  233.      */
  234.     private function getResolverAndMutation(): array
  235.     {
  236.         $services = ['overblog_graphql.query_resolver''overblog_graphql.mutation_resolver'];
  237.         $resolversAndMutations = [];
  238.         foreach ($services as $serviceId) {
  239.             $service $this->container->get($serviceId);
  240.             array_push(
  241.                 $resolversAndMutations,
  242.                 ...array_keys($service->getAliases())
  243.             );
  244.         }
  245.         return $resolversAndMutations;
  246.     }
  247. }