- <?php declare(strict_types=1);
- namespace Shopware\Storefront\Controller;
- use Shopware\Core\Checkout\Cart\SalesChannel\CartService;
- use Shopware\Core\Checkout\Customer\Exception\BadCredentialsException;
- use Shopware\Core\Checkout\Customer\Exception\CustomerAuthThrottledException;
- use Shopware\Core\Checkout\Customer\Exception\CustomerNotFoundByHashException;
- use Shopware\Core\Checkout\Customer\Exception\CustomerNotFoundException;
- use Shopware\Core\Checkout\Customer\Exception\CustomerRecoveryHashExpiredException;
- use Shopware\Core\Checkout\Customer\Exception\InactiveCustomerException;
- use Shopware\Core\Checkout\Customer\SalesChannel\AbstractLoginRoute;
- use Shopware\Core\Checkout\Customer\SalesChannel\AbstractLogoutRoute;
- use Shopware\Core\Checkout\Customer\SalesChannel\AbstractResetPasswordRoute;
- use Shopware\Core\Checkout\Customer\SalesChannel\AbstractSendPasswordRecoveryMailRoute;
- use Shopware\Core\Framework\Context;
- use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
- use Shopware\Core\Framework\DataAbstractionLayer\Exception\InconsistentCriteriaIdsException;
- use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
- use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
- use Shopware\Core\Framework\RateLimiter\Exception\RateLimitExceededException;
- use Shopware\Core\Framework\Routing\Annotation\RouteScope;
- use Shopware\Core\Framework\Routing\Annotation\Since;
- use Shopware\Core\Framework\Validation\DataBag\RequestDataBag;
- use Shopware\Core\Framework\Validation\Exception\ConstraintViolationException;
- use Shopware\Core\System\SalesChannel\SalesChannelContext;
- use Shopware\Storefront\Framework\Routing\Annotation\NoStore;
- use Shopware\Storefront\Framework\Routing\RequestTransformer;
- use Shopware\Storefront\Page\Account\Login\AccountGuestLoginPageLoadedHook;
- use Shopware\Storefront\Page\Account\Login\AccountLoginPageLoadedHook;
- use Shopware\Storefront\Page\Account\Login\AccountLoginPageLoader;
- use Symfony\Component\HttpFoundation\Request;
- use Symfony\Component\HttpFoundation\Response;
- use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
- use Symfony\Component\Routing\Annotation\Route;
- /**
-  * @Route(defaults={"_routeScope"={"storefront"}})
-  */
- class AuthController extends StorefrontController
- {
-     private AccountLoginPageLoader $loginPageLoader;
-     private EntityRepositoryInterface $customerRecoveryRepository;
-     private AbstractSendPasswordRecoveryMailRoute $sendPasswordRecoveryMailRoute;
-     private AbstractResetPasswordRoute $resetPasswordRoute;
-     private AbstractLoginRoute $loginRoute;
-     private AbstractLogoutRoute $logoutRoute;
-     private CartService $cartService;
-     public function __construct(
-         AccountLoginPageLoader $loginPageLoader,
-         EntityRepositoryInterface $customerRecoveryRepository,
-         AbstractSendPasswordRecoveryMailRoute $sendPasswordRecoveryMailRoute,
-         AbstractResetPasswordRoute $resetPasswordRoute,
-         AbstractLoginRoute $loginRoute,
-         AbstractLogoutRoute $logoutRoute,
-         CartService $cartService
-     ) {
-         $this->loginPageLoader = $loginPageLoader;
-         $this->customerRecoveryRepository = $customerRecoveryRepository;
-         $this->sendPasswordRecoveryMailRoute = $sendPasswordRecoveryMailRoute;
-         $this->resetPasswordRoute = $resetPasswordRoute;
-         $this->loginRoute = $loginRoute;
-         $this->logoutRoute = $logoutRoute;
-         $this->cartService = $cartService;
-     }
-     /**
-      * @Since("6.0.0.0")
-      * @Route("/account/login", name="frontend.account.login.page", methods={"GET"})
-      * @NoStore
-      */
-     public function loginPage(Request $request, RequestDataBag $data, SalesChannelContext $context): Response
-     {
-         /** @var string $redirect */
-         $redirect = $request->get('redirectTo', 'frontend.account.home.page');
-         $customer = $context->getCustomer();
-         if ($customer !== null && $customer->getGuest() === false) {
-             $request->request->set('redirectTo', $redirect);
-             return $this->createActionResponse($request);
-         }
-         $page = $this->loginPageLoader->load($request, $context);
-         $this->hook(new AccountLoginPageLoadedHook($page, $context));
-         return $this->renderStorefront('@Storefront/storefront/page/account/register/index.html.twig', [
-             'redirectTo' => $redirect,
-             'redirectParameters' => $request->get('redirectParameters', json_encode([])),
-             'page' => $page,
-             'loginError' => (bool) $request->get('loginError'),
-             'waitTime' => $request->get('waitTime'),
-             'errorSnippet' => $request->get('errorSnippet'),
-             'data' => $data,
-         ]);
-     }
-     /**
-      * @Since("6.3.4.1")
-      * @Route("/account/guest/login", name="frontend.account.guest.login.page", methods={"GET"})
-      * @NoStore
-      */
-     public function guestLoginPage(Request $request, SalesChannelContext $context): Response
-     {
-         /** @var string $redirect */
-         $redirect = $request->get('redirectTo', 'frontend.account.home.page');
-         $customer = $context->getCustomer();
-         if ($customer !== null) {
-             $request->request->set('redirectTo', $redirect);
-             return $this->createActionResponse($request);
-         }
-         $waitTime = (int) $request->get('waitTime');
-         if ($waitTime) {
-             $this->addFlash(self::INFO, $this->trans('account.loginThrottled', ['%seconds%' => $waitTime]));
-         }
-         if ((bool) $request->get('loginError')) {
-             $this->addFlash(self::DANGER, $this->trans('account.orderGuestLoginWrongCredentials'));
-         }
-         $page = $this->loginPageLoader->load($request, $context);
-         $this->hook(new AccountGuestLoginPageLoadedHook($page, $context));
-         return $this->renderStorefront('@Storefront/storefront/page/account/guest-auth.html.twig', [
-             'redirectTo' => $redirect,
-             'redirectParameters' => $request->get('redirectParameters', json_encode([])),
-             'page' => $page,
-         ]);
-     }
-     /**
-      * @Since("6.0.0.0")
-      * @Route("/account/logout", name="frontend.account.logout.page", methods={"GET"})
-      */
-     public function logout(Request $request, SalesChannelContext $context, RequestDataBag $dataBag): Response
-     {
-         if ($context->getCustomer() === null) {
-             return $this->redirectToRoute('frontend.account.login.page');
-         }
-         try {
-             $this->logoutRoute->logout($context, $dataBag);
-             $this->addFlash(self::SUCCESS, $this->trans('account.logoutSucceeded'));
-             $parameters = [];
-         } catch (ConstraintViolationException $formViolations) {
-             $parameters = ['formViolations' => $formViolations];
-         }
-         return $this->redirectToRoute('frontend.account.login.page', $parameters);
-     }
-     /**
-      * @Since("6.0.0.0")
-      * @Route("/account/login", name="frontend.account.login", methods={"POST"}, defaults={"XmlHttpRequest"=true})
-      */
-     public function login(Request $request, RequestDataBag $data, SalesChannelContext $context): Response
-     {
-         $customer = $context->getCustomer();
-         if ($customer !== null && $customer->getGuest() === false) {
-             return $this->createActionResponse($request);
-         }
-         try {
-             $token = $this->loginRoute->login($data, $context)->getToken();
-             if (!empty($token)) {
-                 $this->addCartErrors($this->cartService->getCart($token, $context));
-                 return $this->createActionResponse($request);
-             }
-         } catch (BadCredentialsException | UnauthorizedHttpException | InactiveCustomerException | CustomerAuthThrottledException $e) {
-             if ($e instanceof InactiveCustomerException) {
-                 $errorSnippet = $e->getSnippetKey();
-             }
-             if ($e instanceof CustomerAuthThrottledException) {
-                 $waitTime = $e->getWaitTime();
-             }
-         }
-         $data->set('password', null);
-         return $this->forwardToRoute(
-             'frontend.account.login.page',
-             [
-                 'loginError' => true,
-                 'errorSnippet' => $errorSnippet ?? null,
-                 'waitTime' => $waitTime ?? null,
-             ]
-         );
-     }
-     /**
-      * @Since("6.1.0.0")
-      * @Route("/account/recover", name="frontend.account.recover.page", methods={"GET"})
-      */
-     public function recoverAccountForm(Request $request, SalesChannelContext $context): Response
-     {
-         $page = $this->loginPageLoader->load($request, $context);
-         return $this->renderStorefront('@Storefront/storefront/page/account/profile/recover-password.html.twig', [
-             'page' => $page,
-         ]);
-     }
-     /**
-      * @Since("6.1.0.0")
-      * @Route("/account/recover", name="frontend.account.recover.request", methods={"POST"})
-      */
-     public function generateAccountRecovery(Request $request, RequestDataBag $data, SalesChannelContext $context): Response
-     {
-         try {
-             $data->get('email')
-                 ->set('storefrontUrl', $request->attributes->get(RequestTransformer::STOREFRONT_URL));
-             $this->sendPasswordRecoveryMailRoute->sendRecoveryMail(
-                 $data->get('email')->toRequestDataBag(),
-                 $context,
-                 false
-             );
-             $this->addFlash(self::SUCCESS, $this->trans('account.recoveryMailSend'));
-         } catch (CustomerNotFoundException $e) {
-             $this->addFlash(self::SUCCESS, $this->trans('account.recoveryMailSend'));
-         } catch (InconsistentCriteriaIdsException $e) {
-             $this->addFlash(self::DANGER, $this->trans('error.message-default'));
-         } catch (RateLimitExceededException $e) {
-             $this->addFlash(self::INFO, $this->trans('error.rateLimitExceeded', ['%seconds%' => $e->getWaitTime()]));
-         }
-         return $this->redirectToRoute('frontend.account.recover.page');
-     }
-     /**
-      * @Since("6.1.0.0")
-      * @Route("/account/recover/password", name="frontend.account.recover.password.page", methods={"GET"})
-      */
-     public function resetPasswordForm(Request $request, SalesChannelContext $context): Response
-     {
-         $page = $this->loginPageLoader->load($request, $context);
-         $hash = $request->get('hash');
-         if (!$hash) {
-             $this->addFlash(self::DANGER, $this->trans('account.passwordHashNotFound'));
-             return $this->redirectToRoute('frontend.account.recover.request');
-         }
-         $customerHashCriteria = new Criteria();
-         $customerHashCriteria->addFilter(new EqualsFilter('hash', $hash));
-         $customerRecovery = $this->customerRecoveryRepository
-             ->search($customerHashCriteria, $context->getContext())
-             ->first();
-         if ($customerRecovery === null) {
-             $this->addFlash(self::DANGER, $this->trans('account.passwordHashNotFound'));
-             return $this->redirectToRoute('frontend.account.recover.request');
-         }
-         if (!$this->checkHash($hash, $context->getContext())) {
-             $this->addFlash(self::DANGER, $this->trans('account.passwordHashExpired'));
-             return $this->redirectToRoute('frontend.account.recover.request');
-         }
-         return $this->renderStorefront('@Storefront/storefront/page/account/profile/reset-password.html.twig', [
-             'page' => $page,
-             'hash' => $hash,
-             'formViolations' => $request->get('formViolations'),
-         ]);
-     }
-     /**
-      * @Since("6.1.0.0")
-      * @Route("/account/recover/password", name="frontend.account.recover.password.reset", methods={"POST"})
-      */
-     public function resetPassword(RequestDataBag $data, SalesChannelContext $context): Response
-     {
-         $hash = $data->get('password')->get('hash');
-         try {
-             $pw = $data->get('password');
-             $this->resetPasswordRoute->resetPassword($pw->toRequestDataBag(), $context);
-             $this->addFlash(self::SUCCESS, $this->trans('account.passwordChangeSuccess'));
-         } catch (ConstraintViolationException $formViolations) {
-             $this->addFlash(self::DANGER, $this->trans('account.passwordChangeNoSuccess'));
-             return $this->forwardToRoute(
-                 'frontend.account.recover.password.page',
-                 ['hash' => $hash, 'formViolations' => $formViolations, 'passwordFormViolation' => true]
-             );
-         } catch (CustomerNotFoundByHashException $e) {
-             $this->addFlash(self::DANGER, $this->trans('account.passwordChangeNoSuccess'));
-             return $this->forwardToRoute('frontend.account.recover.request');
-         } catch (CustomerRecoveryHashExpiredException $e) {
-             $this->addFlash(self::DANGER, $this->trans('account.passwordHashExpired'));
-             return $this->forwardToRoute('frontend.account.recover.request');
-         }
-         return $this->redirectToRoute('frontend.account.profile.page');
-     }
-     private function checkHash(string $hash, Context $context): bool
-     {
-         $criteria = new Criteria();
-         $criteria->addFilter(new EqualsFilter('hash', $hash));
-         $recovery = $this->customerRecoveryRepository->search($criteria, $context)->first();
-         $validDateTime = (new \DateTime())->sub(new \DateInterval('PT2H'));
-         return $recovery && $validDateTime < $recovery->getCreatedAt();
-     }
- }
-