vendor/shopware/storefront/Controller/AuthController.php line 217

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Shopware\Storefront\Controller;
  3. use Shopware\Core\Checkout\Cart\SalesChannel\CartService;
  4. use Shopware\Core\Checkout\Customer\Exception\BadCredentialsException;
  5. use Shopware\Core\Checkout\Customer\Exception\CustomerAuthThrottledException;
  6. use Shopware\Core\Checkout\Customer\Exception\CustomerNotFoundByHashException;
  7. use Shopware\Core\Checkout\Customer\Exception\CustomerNotFoundException;
  8. use Shopware\Core\Checkout\Customer\Exception\CustomerRecoveryHashExpiredException;
  9. use Shopware\Core\Checkout\Customer\Exception\InactiveCustomerException;
  10. use Shopware\Core\Checkout\Customer\SalesChannel\AbstractLoginRoute;
  11. use Shopware\Core\Checkout\Customer\SalesChannel\AbstractLogoutRoute;
  12. use Shopware\Core\Checkout\Customer\SalesChannel\AbstractResetPasswordRoute;
  13. use Shopware\Core\Checkout\Customer\SalesChannel\AbstractSendPasswordRecoveryMailRoute;
  14. use Shopware\Core\Framework\Context;
  15. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
  16. use Shopware\Core\Framework\DataAbstractionLayer\Exception\InconsistentCriteriaIdsException;
  17. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  18. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  19. use Shopware\Core\Framework\RateLimiter\Exception\RateLimitExceededException;
  20. use Shopware\Core\Framework\Routing\Annotation\RouteScope;
  21. use Shopware\Core\Framework\Routing\Annotation\Since;
  22. use Shopware\Core\Framework\Validation\DataBag\RequestDataBag;
  23. use Shopware\Core\Framework\Validation\Exception\ConstraintViolationException;
  24. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  25. use Shopware\Storefront\Framework\Routing\Annotation\NoStore;
  26. use Shopware\Storefront\Framework\Routing\RequestTransformer;
  27. use Shopware\Storefront\Page\Account\Login\AccountGuestLoginPageLoadedHook;
  28. use Shopware\Storefront\Page\Account\Login\AccountLoginPageLoadedHook;
  29. use Shopware\Storefront\Page\Account\Login\AccountLoginPageLoader;
  30. use Symfony\Component\HttpFoundation\Request;
  31. use Symfony\Component\HttpFoundation\Response;
  32. use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
  33. use Symfony\Component\Routing\Annotation\Route;
  34. /**
  35.  * @Route(defaults={"_routeScope"={"storefront"}})
  36.  *
  37.  * @deprecated tag:v6.5.0 - reason:becomes-internal - Will be internal
  38.  */
  39. class AuthController extends StorefrontController
  40. {
  41.     private AccountLoginPageLoader $loginPageLoader;
  42.     private EntityRepositoryInterface $customerRecoveryRepository;
  43.     private AbstractSendPasswordRecoveryMailRoute $sendPasswordRecoveryMailRoute;
  44.     private AbstractResetPasswordRoute $resetPasswordRoute;
  45.     private AbstractLoginRoute $loginRoute;
  46.     private AbstractLogoutRoute $logoutRoute;
  47.     private CartService $cartService;
  48.     /**
  49.      * @internal
  50.      */
  51.     public function __construct(
  52.         AccountLoginPageLoader $loginPageLoader,
  53.         EntityRepositoryInterface $customerRecoveryRepository,
  54.         AbstractSendPasswordRecoveryMailRoute $sendPasswordRecoveryMailRoute,
  55.         AbstractResetPasswordRoute $resetPasswordRoute,
  56.         AbstractLoginRoute $loginRoute,
  57.         AbstractLogoutRoute $logoutRoute,
  58.         CartService $cartService
  59.     ) {
  60.         $this->loginPageLoader $loginPageLoader;
  61.         $this->customerRecoveryRepository $customerRecoveryRepository;
  62.         $this->sendPasswordRecoveryMailRoute $sendPasswordRecoveryMailRoute;
  63.         $this->resetPasswordRoute $resetPasswordRoute;
  64.         $this->loginRoute $loginRoute;
  65.         $this->logoutRoute $logoutRoute;
  66.         $this->cartService $cartService;
  67.     }
  68.     /**
  69.      * @Since("6.0.0.0")
  70.      * @Route("/account/login", name="frontend.account.login.page", methods={"GET"})
  71.      * @NoStore
  72.      */
  73.     public function loginPage(Request $requestRequestDataBag $dataSalesChannelContext $context): Response
  74.     {
  75.         /** @var string $redirect */
  76.         $redirect $request->get('redirectTo''frontend.account.home.page');
  77.         $customer $context->getCustomer();
  78.         if ($customer !== null && $customer->getGuest() === false) {
  79.             $request->request->set('redirectTo'$redirect);
  80.             return $this->createActionResponse($request);
  81.         }
  82.         $page $this->loginPageLoader->load($request$context);
  83.         $this->hook(new AccountLoginPageLoadedHook($page$context));
  84.         return $this->renderStorefront('@Storefront/storefront/page/account/register/index.html.twig', [
  85.             'redirectTo' => $redirect,
  86.             'redirectParameters' => $request->get('redirectParameters'json_encode([])),
  87.             'page' => $page,
  88.             'loginError' => (bool) $request->get('loginError'),
  89.             'waitTime' => $request->get('waitTime'),
  90.             'errorSnippet' => $request->get('errorSnippet'),
  91.             'data' => $data,
  92.         ]);
  93.     }
  94.     /**
  95.      * @Since("6.3.4.1")
  96.      * @Route("/account/guest/login", name="frontend.account.guest.login.page", methods={"GET"})
  97.      * @NoStore
  98.      */
  99.     public function guestLoginPage(Request $requestSalesChannelContext $context): Response
  100.     {
  101.         /** @var string $redirect */
  102.         $redirect $request->get('redirectTo''frontend.account.home.page');
  103.         $customer $context->getCustomer();
  104.         if ($customer !== null) {
  105.             $request->request->set('redirectTo'$redirect);
  106.             return $this->createActionResponse($request);
  107.         }
  108.         $waitTime = (int) $request->get('waitTime');
  109.         if ($waitTime) {
  110.             $this->addFlash(self::INFO$this->trans('account.loginThrottled', ['%seconds%' => $waitTime]));
  111.         }
  112.         if ((bool) $request->get('loginError')) {
  113.             $this->addFlash(self::DANGER$this->trans('account.orderGuestLoginWrongCredentials'));
  114.         }
  115.         $page $this->loginPageLoader->load($request$context);
  116.         $this->hook(new AccountGuestLoginPageLoadedHook($page$context));
  117.         return $this->renderStorefront('@Storefront/storefront/page/account/guest-auth.html.twig', [
  118.             'redirectTo' => $redirect,
  119.             'redirectParameters' => $request->get('redirectParameters'json_encode([])),
  120.             'page' => $page,
  121.         ]);
  122.     }
  123.     /**
  124.      * @Since("6.0.0.0")
  125.      * @Route("/account/logout", name="frontend.account.logout.page", methods={"GET"})
  126.      */
  127.     public function logout(Request $requestSalesChannelContext $contextRequestDataBag $dataBag): Response
  128.     {
  129.         if ($context->getCustomer() === null) {
  130.             return $this->redirectToRoute('frontend.account.login.page');
  131.         }
  132.         try {
  133.             $this->logoutRoute->logout($context$dataBag);
  134.             $this->addFlash(self::SUCCESS$this->trans('account.logoutSucceeded'));
  135.             $parameters = [];
  136.         } catch (ConstraintViolationException $formViolations) {
  137.             $parameters = ['formViolations' => $formViolations];
  138.         }
  139.         return $this->redirectToRoute('frontend.account.login.page'$parameters);
  140.     }
  141.     /**
  142.      * @Since("6.0.0.0")
  143.      * @Route("/account/login", name="frontend.account.login", methods={"POST"}, defaults={"XmlHttpRequest"=true})
  144.      */
  145.     public function login(Request $requestRequestDataBag $dataSalesChannelContext $context): Response
  146.     {
  147.         $customer $context->getCustomer();
  148.         if ($customer !== null && $customer->getGuest() === false) {
  149.             return $this->createActionResponse($request);
  150.         }
  151.         try {
  152.             $token $this->loginRoute->login($data$context)->getToken();
  153.             if (!empty($token)) {
  154.                 $this->addCartErrors($this->cartService->getCart($token$context));
  155.                 return $this->createActionResponse($request);
  156.             }
  157.         } catch (BadCredentialsException UnauthorizedHttpException InactiveCustomerException CustomerAuthThrottledException $e) {
  158.             if ($e instanceof InactiveCustomerException) {
  159.                 $errorSnippet $e->getSnippetKey();
  160.             }
  161.             if ($e instanceof CustomerAuthThrottledException) {
  162.                 $waitTime $e->getWaitTime();
  163.             }
  164.         }
  165.         $data->set('password'null);
  166.         return $this->forwardToRoute(
  167.             'frontend.account.login.page',
  168.             [
  169.                 'loginError' => true,
  170.                 'errorSnippet' => $errorSnippet ?? null,
  171.                 'waitTime' => $waitTime ?? null,
  172.             ]
  173.         );
  174.     }
  175.     /**
  176.      * @Since("6.1.0.0")
  177.      * @Route("/account/recover", name="frontend.account.recover.page", methods={"GET"})
  178.      */
  179.     public function recoverAccountForm(Request $requestSalesChannelContext $context): Response
  180.     {
  181.         $page $this->loginPageLoader->load($request$context);
  182.         return $this->renderStorefront('@Storefront/storefront/page/account/profile/recover-password.html.twig', [
  183.             'page' => $page,
  184.         ]);
  185.     }
  186.     /**
  187.      * @Since("6.1.0.0")
  188.      * @Route("/account/recover", name="frontend.account.recover.request", methods={"POST"})
  189.      */
  190.     public function generateAccountRecovery(Request $requestRequestDataBag $dataSalesChannelContext $context): Response
  191.     {
  192.         try {
  193.             $data->get('email')
  194.                 ->set('storefrontUrl'$request->attributes->get(RequestTransformer::STOREFRONT_URL));
  195.             $this->sendPasswordRecoveryMailRoute->sendRecoveryMail(
  196.                 $data->get('email')->toRequestDataBag(),
  197.                 $context,
  198.                 false
  199.             );
  200.             $this->addFlash(self::SUCCESS$this->trans('account.recoveryMailSend'));
  201.         } catch (CustomerNotFoundException $e) {
  202.             $this->addFlash(self::SUCCESS$this->trans('account.recoveryMailSend'));
  203.         } catch (InconsistentCriteriaIdsException $e) {
  204.             $this->addFlash(self::DANGER$this->trans('error.message-default'));
  205.         } catch (RateLimitExceededException $e) {
  206.             $this->addFlash(self::INFO$this->trans('error.rateLimitExceeded', ['%seconds%' => $e->getWaitTime()]));
  207.         }
  208.         return $this->redirectToRoute('frontend.account.recover.page');
  209.     }
  210.     /**
  211.      * @Since("6.1.0.0")
  212.      * @Route("/account/recover/password", name="frontend.account.recover.password.page", methods={"GET"})
  213.      */
  214.     public function resetPasswordForm(Request $requestSalesChannelContext $context): Response
  215.     {
  216.         $page $this->loginPageLoader->load($request$context);
  217.         $hash $request->get('hash');
  218.         if (!$hash) {
  219.             $this->addFlash(self::DANGER$this->trans('account.passwordHashNotFound'));
  220.             return $this->redirectToRoute('frontend.account.recover.request');
  221.         }
  222.         $customerHashCriteria = new Criteria();
  223.         $customerHashCriteria->addFilter(new EqualsFilter('hash'$hash));
  224.         $customerRecovery $this->customerRecoveryRepository
  225.             ->search($customerHashCriteria$context->getContext())
  226.             ->first();
  227.         if ($customerRecovery === null) {
  228.             $this->addFlash(self::DANGER$this->trans('account.passwordHashNotFound'));
  229.             return $this->redirectToRoute('frontend.account.recover.request');
  230.         }
  231.         if (!$this->checkHash($hash$context->getContext())) {
  232.             $this->addFlash(self::DANGER$this->trans('account.passwordHashExpired'));
  233.             return $this->redirectToRoute('frontend.account.recover.request');
  234.         }
  235.         return $this->renderStorefront('@Storefront/storefront/page/account/profile/reset-password.html.twig', [
  236.             'page' => $page,
  237.             'hash' => $hash,
  238.             'formViolations' => $request->get('formViolations'),
  239.         ]);
  240.     }
  241.     /**
  242.      * @Since("6.1.0.0")
  243.      * @Route("/account/recover/password", name="frontend.account.recover.password.reset", methods={"POST"})
  244.      */
  245.     public function resetPassword(RequestDataBag $dataSalesChannelContext $context): Response
  246.     {
  247.         $hash $data->get('password')->get('hash');
  248.         try {
  249.             $pw $data->get('password');
  250.             $this->resetPasswordRoute->resetPassword($pw->toRequestDataBag(), $context);
  251.             $this->addFlash(self::SUCCESS$this->trans('account.passwordChangeSuccess'));
  252.         } catch (ConstraintViolationException $formViolations) {
  253.             $this->addFlash(self::DANGER$this->trans('account.passwordChangeNoSuccess'));
  254.             return $this->forwardToRoute(
  255.                 'frontend.account.recover.password.page',
  256.                 ['hash' => $hash'formViolations' => $formViolations'passwordFormViolation' => true]
  257.             );
  258.         } catch (CustomerNotFoundByHashException $e) {
  259.             $this->addFlash(self::DANGER$this->trans('account.passwordChangeNoSuccess'));
  260.             return $this->forwardToRoute('frontend.account.recover.request');
  261.         } catch (CustomerRecoveryHashExpiredException $e) {
  262.             $this->addFlash(self::DANGER$this->trans('account.passwordHashExpired'));
  263.             return $this->forwardToRoute('frontend.account.recover.request');
  264.         }
  265.         return $this->redirectToRoute('frontend.account.profile.page');
  266.     }
  267.     private function checkHash(string $hashContext $context): bool
  268.     {
  269.         $criteria = new Criteria();
  270.         $criteria->addFilter(new EqualsFilter('hash'$hash));
  271.         $recovery $this->customerRecoveryRepository->search($criteria$context)->first();
  272.         $validDateTime = (new \DateTime())->sub(new \DateInterval('PT2H'));
  273.         return $recovery && $validDateTime $recovery->getCreatedAt();
  274.     }
  275. }