vendor/shopware/platform/src/Storefront/Controller/AuthController.php line 215

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