custom/plugins/MoorlSignIn/src/Core/Subscriber/KernelEventSubscriber.php line 98

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Moorl\SignIn\Core\Subscriber;
  3. use League\OAuth2\Client\Provider\Exception\IdentityProviderException;
  4. use Moorl\SignIn\Core\Service\SignInService;
  5. use Moorl\SignIn\MoorlSignIn;
  6. use Shopware\Core\Checkout\Customer\Event\CustomerLoginEvent;
  7. use Shopware\Core\Checkout\Customer\Event\CustomerLogoutEvent;
  8. use Shopware\Core\Framework\Adapter\Cache\CacheStateSubscriber;
  9. use Shopware\Core\Framework\Context;
  10. use Shopware\Core\Framework\Log\LoggerFactory;
  11. use Shopware\Core\Framework\Uuid\Uuid;
  12. use Shopware\Core\SalesChannelRequest;
  13. use Shopware\Core\System\SystemConfig\SystemConfigService;
  14. use Shopware\Storefront\Framework\Cache\CacheResponseSubscriber;
  15. use Shopware\Storefront\Framework\Cache\Event\HttpCacheGenerateKeyEvent;
  16. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  17. use Symfony\Component\HttpFoundation\RedirectResponse;
  18. use Symfony\Component\HttpFoundation\RequestStack;
  19. use Symfony\Component\HttpKernel\Event\ExceptionEvent;
  20. use Symfony\Component\HttpKernel\Event\RequestEvent;
  21. use Symfony\Component\HttpKernel\KernelEvents;
  22. use Symfony\Component\Routing\RouterInterface;
  23. use Psr\Log\LoggerInterface;
  24. use Monolog\Logger;
  25. class KernelEventSubscriber implements EventSubscriberInterface
  26. {
  27.     private SystemConfigService $systemConfigService;
  28.     private RequestStack $requestStack;
  29.     private RouterInterface $router;
  30.     private SignInService $signInService;
  31.     private LoggerInterface $logger;
  32.     public function __construct(
  33.         RequestStack $requestStack,
  34.         RouterInterface $router,
  35.         SystemConfigService $systemConfigService,
  36.         SignInService $signInService,
  37.         LoggerFactory $loggerFactory
  38.     ) {
  39.         $this->requestStack $requestStack;
  40.         $this->router $router;
  41.         $this->systemConfigService $systemConfigService;
  42.         $this->signInService $signInService;
  43.         $this->logger $loggerFactory->createRotating(
  44.             'moorl_sign_in',
  45.             7,
  46.             (int) $systemConfigService->get('MoorlSignIn.config.logLevel') ?: Logger::DEBUG
  47.         );
  48.     }
  49.     public static function getSubscribedEvents(): array
  50.     {
  51.         return [
  52.             KernelEvents::REQUEST => 'checkToken',
  53.             KernelEvents::EXCEPTION => 'tokenNotSetHandler',
  54.             HttpCacheGenerateKeyEvent::class => 'onHttpCacheGenerateKeyEvent',
  55.             CustomerLoginEvent::class => 'onCustomerLogin',
  56.             CustomerLogoutEvent::class => 'onCustomerLogout'
  57.         ];
  58.     }
  59.     public function onHttpCacheGenerateKeyEvent(HttpCacheGenerateKeyEvent $event): void
  60.     {
  61.         $request $event->getRequest();
  62.         $systemState $request->cookies->get(CacheResponseSubscriber::SYSTEM_STATE_COOKIE);
  63.         if (!$systemState) {
  64.             return;
  65.         }
  66.         $isLoggedIn mb_strpos($systemStateCacheStateSubscriber::STATE_LOGGED_IN) !== false;
  67.         if (!$isLoggedIn) {
  68.             return;
  69.         }
  70.         $hash $event->getHash();
  71.         $hash hash('sha256'$hash '-' serialize(CacheStateSubscriber::STATE_LOGGED_IN));
  72.         $event->setHash($hash);
  73.     }
  74.     public function onCustomerLogin(CustomerLoginEvent $event): void
  75.     {
  76.         $master $this->requestStack->getMasterRequest();
  77.         $session $master->getSession();
  78.         $session->set(MoorlSignIn::SKIP_CHECK_TOKENtrue);
  79.     }
  80.     public function onCustomerLogout(CustomerLogoutEvent $event): void
  81.     {
  82.         $master $this->requestStack->getMasterRequest();
  83.         $session $master->getSession();
  84.         $session->remove(MoorlSignIn::SKIP_CHECK_TOKEN);
  85.     }
  86.     public function tokenNotSetHandler(ExceptionEvent $event): void
  87.     {
  88.         if (!$event->getThrowable() instanceof IdentityProviderException) {
  89.             return;
  90.         }
  91.         $redirectUrl $this->systemConfigService->get('MoorlSignIn.config.redirectUrl');
  92.         if (!$redirectUrl) {
  93.             return;
  94.         }
  95.         $redirectResponse = new RedirectResponse($redirectUrl);
  96.         $event->setResponse($redirectResponse);
  97.     }
  98.     public function checkToken(RequestEvent $event): void
  99.     {
  100.         // Is is not sales channel request then do nothing
  101.         if (!$event->getRequest()->attributes->has(SalesChannelRequest::ATTRIBUTE_IS_SALES_CHANNEL_REQUEST)) {
  102.             return;
  103.         }
  104.         $salesChannelId $event->getRequest()->attributes->get('sw-sales-channel-id');
  105.         if (!$salesChannelId) {
  106.             return;
  107.         }
  108.         $master $this->requestStack->getMasterRequest();
  109.         $routeBlacklist $this->systemConfigService->get('MoorlSignIn.config.routeBlacklist'$salesChannelId);
  110.         if ($routeBlacklist) {
  111.             if (!in_array($master->attributes->get('_route'), $routeBlacklist)) {
  112.                 return;
  113.             }
  114.         }
  115.         // If no redirect set, do nothing
  116.         $redirectTo $this->systemConfigService->get('MoorlSignIn.config.redirectTo'$salesChannelId);
  117.         if (!$redirectTo) {
  118.             return;
  119.         }
  120.         if ($redirectTo === 'redirectUrl') {
  121.             // Fixed redirect
  122.             $redirectResponse = new RedirectResponse(
  123.                 $this->systemConfigService->get('MoorlSignIn.config.redirectUrl'$salesChannelId)
  124.             );
  125.         } else {
  126.             // Router redirect
  127.             $redirectResponse = new RedirectResponse(
  128.                 $this->router->generate($redirectTo$master->query->all())
  129.             );
  130.         }
  131.         $redirectActive $this->systemConfigService->get('MoorlSignIn.config.redirectActive'$salesChannelId);
  132.         // No Session set, Redirect is Active
  133.         if ((!$master || !$master->hasSession()) && $redirectActive) {
  134.             $this->logger->info('No Session set, Redirect is Active');
  135.             $event->setResponse($redirectResponse);
  136.             return;
  137.         }
  138.         $session $master->getSession();
  139.         $lastPage $master->server->get('REQUEST_SCHEME') .  '://' $master->server->get('HTTP_HOST') . $master->server->get('REDIRECT_URL');
  140.         // Fetch query data
  141.         $queryData $master->query->all();
  142.         // Get name of query param for the token
  143.         $queryParam $this->systemConfigService->get('MoorlSignIn.config.tokenQueryParam'$salesChannelId);
  144.         // Token is not set by default
  145.         $token null;
  146.         if ($queryParam) {
  147.             $token $master->query->get($queryParam);
  148.             // Remove token query param and rebuild other query data
  149.             unset($queryData[$queryParam]);
  150.         }
  151.         if ($queryData) {
  152.             // Last page with GET params but no token
  153.             $lastPageAll $lastPage '?' http_build_query($queryData);
  154.         } else {
  155.             // Last page
  156.             $lastPageAll $lastPage;
  157.         }
  158.         // Remember last page
  159.         $session->set(MoorlSignIn::LAST_KNOWN_PAGE$lastPageAll);
  160.         $isLoggedIn $session->get(MoorlSignIn::SKIP_CHECK_TOKEN);
  161.         // User not Logged In, No Token Set, Redirect is Active
  162.         if (!$isLoggedIn && !$token && $redirectActive) {
  163.             $this->logger->info('User not Logged In, No Token Set, Redirect is Active');
  164.             $event->setResponse($redirectResponse);
  165.             return;
  166.         }
  167.         // Token Set
  168.         if ($token) {
  169.             $this->logger->info('Token Set'$master->query->all());
  170.             if ($master->query->get('PayerID') || $master->query->get('_sw_payment_token')) {
  171.                 $this->logger->info('Payment token detected');
  172.                 return; // Skip PayPal token
  173.             }
  174.             $state Uuid::randomHex();
  175.             $providerName $this->systemConfigService->get('MoorlSignIn.config.tokenProvider'$salesChannelId);
  176.             $data = [
  177.                 'provider' => $providerName,
  178.                 'lastPage' => $lastPage,
  179.                 'lastPageAll' => $lastPageAll,
  180.                 'token' => $token,
  181.                 'state' => $state
  182.             ];
  183.             $this->logger->info('Create new login session'$data);
  184.             $this->signInService->createSession($dataContext::createDefaultContext());
  185.             $redirectResponse = new RedirectResponse($this->router->generate('moorl.oauth2.login', ['state' => $state]));
  186.             $event->setResponse($redirectResponse);
  187.             sleep(1);
  188.             return;
  189.         }
  190.         $this->logger->info('No Token Set'$master->query->all());
  191.         // User not Logged In, Redirect is Active
  192.         if (!$isLoggedIn && $redirectActive) {
  193.             $this->logger->info('User not Logged In, Redirect is Active');
  194.             $event->setResponse($redirectResponse);
  195.         }
  196.     }
  197. }