vendor/shopware/core/Checkout/Customer/Subscriber/CustomerTokenSubscriber.php line 48

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Shopware\Core\Checkout\Customer\Subscriber;
  3. use Shopware\Core\Checkout\Customer\CustomerEvents;
  4. use Shopware\Core\Framework\DataAbstractionLayer\EntityWriteResult;
  5. use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityDeletedEvent;
  6. use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityWrittenEvent;
  7. use Shopware\Core\Framework\Log\Package;
  8. use Shopware\Core\PlatformRequest;
  9. use Shopware\Core\System\SalesChannel\Context\SalesChannelContextPersister;
  10. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  11. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  12. use Symfony\Component\HttpFoundation\RequestStack;
  13. /**
  14. * @deprecated tag:v6.5.0 - reason:becomes-internal - EventSubscribers will become internal in v6.5.0
  15. */
  16. #[Package('customer-order')]
  17. class CustomerTokenSubscriber implements EventSubscriberInterface
  18. {
  19. private SalesChannelContextPersister $contextPersister;
  20. private RequestStack $requestStack;
  21. /**
  22. * @internal
  23. */
  24. public function __construct(
  25. SalesChannelContextPersister $contextPersister,
  26. RequestStack $requestStack
  27. ) {
  28. $this->contextPersister = $contextPersister;
  29. $this->requestStack = $requestStack;
  30. }
  31. /**
  32. * @return array<string, string|array{0: string, 1: int}|list<array{0: string, 1?: int}>>
  33. */
  34. public static function getSubscribedEvents()
  35. {
  36. return [
  37. CustomerEvents::CUSTOMER_WRITTEN_EVENT => 'onCustomerWritten',
  38. CustomerEvents::CUSTOMER_DELETED_EVENT => 'onCustomerDeleted',
  39. ];
  40. }
  41. public function onCustomerWritten(EntityWrittenEvent $event): void
  42. {
  43. foreach ($event->getWriteResults() as $writeResult) {
  44. if ($writeResult->getOperation() !== EntityWriteResult::OPERATION_UPDATE) {
  45. continue;
  46. }
  47. $payload = $writeResult->getPayload();
  48. if (!$this->customerCredentialsChanged($payload)) {
  49. continue;
  50. }
  51. $customerId = $payload['id'];
  52. $newToken = $this->invalidateUsingSession($customerId);
  53. if ($newToken) {
  54. $this->contextPersister->revokeAllCustomerTokens($customerId, $newToken);
  55. } else {
  56. $this->contextPersister->revokeAllCustomerTokens($customerId);
  57. }
  58. }
  59. }
  60. public function onCustomerDeleted(EntityDeletedEvent $event): void
  61. {
  62. foreach ($event->getIds() as $customerId) {
  63. $this->contextPersister->revokeAllCustomerTokens($customerId);
  64. }
  65. }
  66. /**
  67. * @param array<string, mixed> $payload
  68. */
  69. private function customerCredentialsChanged(array $payload): bool
  70. {
  71. return isset($payload['password']);
  72. }
  73. private function invalidateUsingSession(string $customerId): ?string
  74. {
  75. $master = $this->requestStack->getMainRequest();
  76. if (!$master) {
  77. return null;
  78. }
  79. // Is not a storefront request
  80. if (!$master->attributes->has(PlatformRequest::ATTRIBUTE_SALES_CHANNEL_CONTEXT_OBJECT)) {
  81. return null;
  82. }
  83. /** @var SalesChannelContext $context */
  84. $context = $master->attributes->get(PlatformRequest::ATTRIBUTE_SALES_CHANNEL_CONTEXT_OBJECT);
  85. // Not loggedin skip
  86. if ($context->getCustomer() === null) {
  87. return null;
  88. }
  89. // The written customer is not the same as logged-in. We don't modify the user session
  90. if ($context->getCustomer()->getId() !== $customerId) {
  91. return null;
  92. }
  93. $token = $context->getToken();
  94. $newToken = $this->contextPersister->replace($token, $context);
  95. $context->assign([
  96. 'token' => $newToken,
  97. ]);
  98. if (!$master->hasSession()) {
  99. return null;
  100. }
  101. $session = $master->getSession();
  102. $session->migrate();
  103. $session->set('sessionId', $session->getId());
  104. $session->set(PlatformRequest::HEADER_CONTEXT_TOKEN, $newToken);
  105. $master->headers->set(PlatformRequest::HEADER_CONTEXT_TOKEN, $newToken);
  106. return $newToken;
  107. }
  108. }