<?php
declare(strict_types=1);
namespace Bodymed\Webshop\StoreFront\Controller;
use Bodymed\Webshop\BodymedID\DataProvider as BodymedIdDataProvider;
use Bodymed\Webshop\Core\Checkout\Customer\SalesChannel\LoginRoute;
use Bodymed\Webshop\StoreFront\Security\OAuth\BodymedIDResourceOwner;
use KnpU\OAuth2ClientBundle\Client\OAuth2Client;
use League\OAuth2\Client\Provider\Exception\IdentityProviderException;
use League\OAuth2\Client\Token\AccessToken;
use Psr\Log\LoggerInterface;
use Shopware\Core\Checkout\Cart\SalesChannel\CartService;
use Shopware\Core\Checkout\Customer\Exception\BadCredentialsException;
use Shopware\Core\Checkout\Customer\SalesChannel\AbstractLoginRoute;
use Shopware\Core\Framework\Routing\Annotation\RouteScope;
use Shopware\Core\Framework\Validation\DataBag\RequestDataBag;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Shopware\Storefront\Controller\StorefrontController;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Routing\RouterInterface;
/**
* @RouteScope(scopes={"storefront"})
*/
class BodymedIDController extends StorefrontController
{
public const REDIRECT_SESSION_KEY = 'redirectTo';
public const REDIRECT_SESSION_Parameter = 'redirectParameters';
public const REDIRECT_DEFAULT_ROUTE = 'frontend.account.home.page';
private OAuth2Client $oauthClient;
private AbstractLoginRoute $loginRoute;
private CartService $cartService;
private BodymedIdDataProvider $bodymedIdDataProvider;
private RouterInterface $router;
private SessionInterface $session;
private LoggerInterface $logger;
public function __construct(
OAuth2Client $bodymedID_OAuthClient,
AbstractLoginRoute $loginRoute,
CartService $cartService,
BodymedIdDataProvider $bodymedIdDataProvider,
RouterInterface $router,
SessionInterface $session,
LoggerInterface $logger
) {
$this->oauthClient = $bodymedID_OAuthClient;
$this->loginRoute = $loginRoute;
$this->cartService = $cartService;
$this->bodymedIdDataProvider = $bodymedIdDataProvider;
$this->router = $router;
$this->session = $session;
$this->logger = $logger;
}
/**
* @Route("/bodymed-id/connect", name="frontend.bodymed_id.connect", options={"seo"="false"}, methods={"GET"})
*/
public function connect(Request $request, RequestDataBag $data, SalesChannelContext $context): RedirectResponse
{
if ($context->getCustomer()) {
return $this->redirectToRoute('frontend.account.home.page');
}
$redirectTo = $request->get('redirectTo', 'frontend.account.home.page');
$redirectParameters = '';
if ($request->get('redirectParameters')) {
$redirectParameters = $this->decodeParam($request, 'redirectParameters');
}
$this->session->set(self::REDIRECT_SESSION_KEY, $redirectTo);
$this->session->set(self::REDIRECT_SESSION_Parameter, $redirectParameters);
return $this->oauthClient->redirect([
'email profile roles',
]);
}
/**
* @Route("/bodymed-id/connect-check", name="frontend.bodymed_id.connect_check", options={"seo"="false"}, methods={"GET"})
*/
public function connectCheck(Request $request, RequestDataBag $data, SalesChannelContext $context): ?Response
{
try {
/* @var $accessToken AccessToken */
$accessToken = $this->oauthClient->getAccessToken();
/* @var $user BodymedIDResourceOwner */
$user = $this->oauthClient->fetchUserFromToken($accessToken);
if (false === $user->hasRole($this->bodymedIdDataProvider->getRequiredRole())) {
throw new BadCredentialsException();
}
$data->set('email', $user->getEmail());
$data->set(LoginRoute::FROM_BODYMED_ID_DATA_BAG_KEY, true);
$token = $this->loginRoute->login($data, $context)->getToken();
if (!empty($token)) {
/*if (Feature::isActive('FEATURE_NEXT_10058')) {
$this->addCartErrors($this->cartService->getCart($token, $context));
}*/
$redirectRoute = $this->session->get(self::REDIRECT_SESSION_KEY) ?? self::REDIRECT_DEFAULT_ROUTE;
$this->session->remove(self::REDIRECT_SESSION_KEY);
if ('frontend.detail.page' == $redirectRoute || 'frontend.navigation.page' === $redirectRoute) {
$redirectParams = $this->session->get(self::REDIRECT_SESSION_Parameter) ?? '';
if (\is_string($redirectParams)) {
$redirectParams = \json_decode($redirectParams, true);
}
if (\is_array($redirectParams)) {
if (isset($redirectParams['productId'])) {
return $this->redirectToRoute($redirectRoute, [
'productId' => $redirectParams['productId'],
't' => \microtime(true),
]);
}
if (isset($redirectParams['navigationId'])) {
return $this->redirectToRoute($redirectRoute, [
'navigationId' => $redirectParams['navigationId'],
't' => \microtime(true),
]);
}
}
/* Fallback to Account-Home */
return $this->redirectToRoute('frontend.account.home.page');
} else {
try {
$route = $this->router->generate($redirectRoute);
return $this->redirect($route);
} catch (\Exception $e) {
$this->logger->error($e->getMessage(), [
'exception' => $e,
'user.email' => $user->getEmail(),
]);
return $this->redirectToRoute(self::REDIRECT_DEFAULT_ROUTE);
}
}
}
} catch (IdentityProviderException $e) {
#$this->addFlash('danger', 'Es ist etwas schief gelaufen. Bitte versuchen Sie es noch einmal');
$this->logger->error($e->getMessage(), [
'exception' => $e,
'request_data' => $data->all(),
]);
$redirectRoute = $this->session->get(self::REDIRECT_SESSION_KEY) ?? 'frontend.account.home.page';
return $this->redirectToRoute($redirectRoute);
}
}
/**
* @Route("/bodymed-id/logout", name="frontend.bodymed_id.logout", options={"seo"="false"}, methods={"GET"})
*/
public function logout(Request $request): RedirectResponse
{
$accountUrl = $this->router->generate(
'frontend.account.logout.page',
[],
UrlGeneratorInterface::ABSOLUTE_URL
);
$redirectUri = $this->bodymedIdDataProvider->getLogoutUrl($accountUrl);
return new RedirectResponse($redirectUri->__toString());
}
private function isValidRedirectUrl(?string $redirectUrl): bool
{
return false !== \filter_var($redirectUrl, FILTER_VALIDATE_URL);
}
}