first commit
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\UserOauthBundle\Admin\Tabs;
|
||||
|
||||
use KupShop\AdminBundle\Admin\WindowTab;
|
||||
|
||||
class LanguagesSettingsOauthTab extends WindowTab
|
||||
{
|
||||
protected $title = 'settingsOauth';
|
||||
|
||||
protected $template = 'languagesSettingsOauth.tpl';
|
||||
|
||||
public static function getTypes()
|
||||
{
|
||||
return [
|
||||
'languagesSettings' => 1,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
$txt_str['languagesSettingsOauthTab'] = [
|
||||
'settingsOauth' => 'Přihlašování',
|
||||
];
|
||||
@@ -0,0 +1,191 @@
|
||||
<div id="settingsOauth" class="tab-pane fade in boxFlex">
|
||||
<h1 class="h4 main-panel-title">Facebook</h1>
|
||||
<div class="form-group">
|
||||
<div class="col-md-2 control-label">Client ID</div>
|
||||
<div class="col-md-7">
|
||||
<div class="input-group" data-input-overwrite>
|
||||
{$isEmpty = array_key_exists('client_id', $body.data.oauth.facebook) && is_null($body.data.oauth.facebook.client_id)}
|
||||
<input type="text" class="form-control input-sm" name="data[oauth][facebook][client_id]"
|
||||
placeholder="{$dbcfg.oauth.facebook.client_id}"
|
||||
value="{if $isEmpty} {else}{$body.data.oauth.facebook.client_id}{/if}">
|
||||
{input_overwrite value_path=['oauth', 'facebook', 'client_id'] isEmpty=$isEmpty}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-md-2 control-label">Client secret</div>
|
||||
<div class="col-md-7">
|
||||
<div class="input-group" data-input-overwrite>
|
||||
{$isEmpty = array_key_exists('client_secret', $body.data.oauth.facebook) && is_null($body.data.oauth.facebook.client_secret)}
|
||||
<input type="text" class="form-control input-sm" name="data[oauth][facebook][client_secret]"
|
||||
placeholder="{$dbcfg.oauth.facebook.client_secret}"
|
||||
value="{if $isEmpty} {else}{$body.data.oauth.facebook.client_secret}{/if}">
|
||||
{input_overwrite value_path=['oauth', 'facebook', 'client_secret'] isEmpty=$isEmpty}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-md-2 control-label">Return URL</div>
|
||||
<div class="col-md-7">
|
||||
<span class="form-control input-sm disabled" disabled>{$cfg.Addr.full}login/check-facebook</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h1 class="h4 main-panel-title">Google</h1>
|
||||
<div class="form-group">
|
||||
<div class="col-md-2 control-label">Client ID</div>
|
||||
<div class="col-md-7">
|
||||
<div class="input-group" data-input-overwrite>
|
||||
{$isEmpty = array_key_exists('client_id', $body.data.oauth.google) && is_null($body.data.oauth.google.client_id)}
|
||||
<input type="text" class="form-control input-sm" name="data[oauth][google][client_id]"
|
||||
placeholder="{$dbcfg.oauth.google.client_id}"
|
||||
value="{if $isEmpty} {else}{$body.data.oauth.google.client_id}{/if}">
|
||||
{input_overwrite value_path=['oauth', 'google', 'client_id'] isEmpty=$isEmpty}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-md-2 control-label">Client secret</div>
|
||||
<div class="col-md-7">
|
||||
<div class="input-group" data-input-overwrite>
|
||||
{$isEmpty = array_key_exists('client_secret', $body.data.oauth.google) && is_null($body.data.oauth.google.client_secret)}
|
||||
<input type="text" class="form-control input-sm" name="data[oauth][google][client_secret]"
|
||||
placeholder="{$dbcfg.oauth.google.client_secret}"
|
||||
value="{if $isEmpty} {else}{$body.data.oauth.google.client_secret}{/if}">
|
||||
{input_overwrite value_path=['oauth', 'google', 'client_secret'] isEmpty=$isEmpty}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-md-2 control-label">Return URL</div>
|
||||
<div class="col-md-7">
|
||||
<span class="form-control input-sm disabled" disabled>{$cfg.Addr.full}login/check-google</span>
|
||||
</div>
|
||||
</div>
|
||||
{ifmodule USER_OAUTH__SEZNAM_LOGIN}
|
||||
<h1 class="h4 main-panel-title">Seznam</h1>
|
||||
<div class="form-group">
|
||||
<div class="col-md-2 control-label">Client ID</div>
|
||||
<div class="col-md-7">
|
||||
<div class="input-group" data-input-overwrite>
|
||||
{$isEmpty = array_key_exists('client_id', $body.data.oauth.seznam) && is_null($body.data.oauth.seznam.client_id)}
|
||||
<input type="text" class="form-control input-sm" name="data[oauth][seznam][client_id]"
|
||||
placeholder="{$dbcfg.oauth.seznam.client_id}"
|
||||
value="{if $isEmpty} {else}{$body.data.oauth.seznam.client_id}{/if}">
|
||||
{input_overwrite value_path=['oauth', 'seznam', 'client_id'] isEmpty=$isEmpty}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-md-2 control-label">Client secret</div>
|
||||
<div class="col-md-7">
|
||||
<div class="input-group" data-input-overwrite>
|
||||
{$isEmpty = array_key_exists('client_secret', $body.data.oauth.seznam) && is_null($body.data.oauth.seznam.client_secret)}
|
||||
<input type="text" class="form-control input-sm" name="data[oauth][seznam][client_secret]"
|
||||
placeholder="{$dbcfg.oauth.seznam.client_secret}"
|
||||
value="{if $isEmpty} {else}{$body.data.oauth.seznam.client_secret}{/if}">
|
||||
{input_overwrite value_path=['oauth', 'seznam', 'client_secret'] isEmpty=$isEmpty}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-md-2 control-label">Return URL</div>
|
||||
<div class="col-md-7">
|
||||
<span class="form-control input-sm disabled" disabled>{$cfg.Addr.full}login/check-seznam</span>
|
||||
</div>
|
||||
</div>
|
||||
{/ifmodule}
|
||||
{ifmodule USER_OAUTH__AMAZON_LOGIN}
|
||||
<h1 class="h4 main-panel-title">Amazon</h1>
|
||||
<div class="form-group">
|
||||
<div class="col-md-2 control-label">Client ID</div>
|
||||
<div class="col-md-7">
|
||||
<div class="input-group" data-input-overwrite>
|
||||
{$isEmpty = array_key_exists('client_id', $body.data.oauth.amazon) && is_null($body.data.oauth.amazon.client_id)}
|
||||
<input type="text" class="form-control input-sm" name="data[oauth][amazon][client_id]"
|
||||
placeholder="{$dbcfg.oauth.amazon.client_id}"
|
||||
value="{if $isEmpty} {else}{$body.data.oauth.amazon.client_id}{/if}">
|
||||
{input_overwrite value_path=['oauth', 'amazon', 'client_id'] isEmpty=$isEmpty}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-md-2 control-label">Client secret</div>
|
||||
<div class="col-md-7">
|
||||
<div class="input-group" data-input-overwrite>
|
||||
{$isEmpty = array_key_exists('client_secret', $body.data.oauth.amazon) && is_null($body.data.oauth.amazon.client_secret)}
|
||||
<input type="text" class="form-control input-sm" name="data[oauth][amazon][client_secret]"
|
||||
placeholder="{$dbcfg.oauth.amazon.client_secret}"
|
||||
value="{if $isEmpty} {else}{$body.data.oauth.amazon.client_secret}{/if}">
|
||||
{input_overwrite value_path=['oauth', 'amazon', 'client_secret'] isEmpty=$isEmpty}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-md-2 control-label">Return URL</div>
|
||||
<div class="col-md-7">
|
||||
<span class="form-control input-sm disabled" disabled>{$cfg.Addr.full}login/check-amazon</span>
|
||||
</div>
|
||||
</div>
|
||||
{/ifmodule}
|
||||
{ifmodule USER_OAUTH__APPLE_LOGIN}
|
||||
<h1 class="h4 main-panel-title">Apple</h1>
|
||||
<div class="form-group">
|
||||
<div class="col-md-2 control-label">Client ID</div>
|
||||
<div class="col-md-7">
|
||||
<div class="input-group" data-input-overwrite>
|
||||
{$isEmpty = array_key_exists('client_id', $body.data.oauth.apple) && is_null($body.data.oauth.apple.client_id)}
|
||||
<input type="text" class="form-control input-sm" name="data[oauth][apple][client_id]"
|
||||
placeholder="{$dbcfg.oauth.apple.client_id}"
|
||||
value="{if $isEmpty} {else}{$body.data.oauth.apple.client_id}{/if}">
|
||||
{input_overwrite value_path=['oauth', 'apple', 'client_id'] isEmpty=$isEmpty}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-md-2 control-label">Team ID</div>
|
||||
<div class="col-md-7">
|
||||
<div class="input-group" data-input-overwrite>
|
||||
{$isEmpty = array_key_exists('team_id', $body.data.oauth.apple) && is_null($body.data.oauth.apple.team_id)}
|
||||
<input type="text" class="form-control input-sm" name="data[oauth][apple][team_id]"
|
||||
placeholder="{$dbcfg.oauth.apple.team_id}"
|
||||
value="{if $isEmpty} {else}{$body.data.oauth.apple.team_id}{/if}">
|
||||
{input_overwrite value_path=['oauth', 'apple', 'team_id'] isEmpty=$isEmpty}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-md-2 control-label">Key ID</div>
|
||||
<div class="col-md-7">
|
||||
<div class="input-group" data-input-overwrite>
|
||||
{$isEmpty = array_key_exists('key_id', $body.data.oauth.apple) && is_null($body.data.oauth.apple.key_id)}
|
||||
<input type="text" class="form-control input-sm" name="data[oauth][apple][key_id]"
|
||||
placeholder="{$dbcfg.oauth.apple.key_id}"
|
||||
value="{if $isEmpty} {else}{$body.data.oauth.apple.key_id}{/if}">
|
||||
{input_overwrite value_path=['oauth', 'apple', 'key_id'] isEmpty=$isEmpty}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-md-2 control-label">Auth key</div>
|
||||
<div class="col-md-7">
|
||||
<div class="input-group" data-input-overwrite>
|
||||
{$isEmpty = array_key_exists('auth_key', $body.data.oauth.apple) && is_null($body.data.oauth.apple.auth_key)}
|
||||
<input type="text" class="form-control input-sm" name="data[oauth][apple][auth_key]"
|
||||
placeholder="{$dbcfg.oauth.apple.auth_key}"
|
||||
value="{if $isEmpty} {else}{$body.data.oauth.apple.auth_key}{/if}">
|
||||
<div class="input-group-btn">
|
||||
{insert_file_browse link="auth_key"}
|
||||
</div>
|
||||
{input_overwrite value_path=['oauth', 'apple', 'auth_key'] isEmpty=$isEmpty}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-md-2 control-label">Return URL</div>
|
||||
<div class="col-md-7">
|
||||
<span class="form-control input-sm disabled" disabled>{$cfg.Addr.full}login/check-apple</span>
|
||||
</div>
|
||||
</div>
|
||||
{/ifmodule}
|
||||
</div>
|
||||
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\UserOauthBundle\Controller;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
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\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
|
||||
class BindExternalAccountController extends AbstractController
|
||||
{
|
||||
use \DatabaseCommunication;
|
||||
|
||||
/** @var SessionInterface */
|
||||
private $session;
|
||||
|
||||
/** @var TokenStorageInterface */
|
||||
private $tokenStorage;
|
||||
|
||||
public function __construct(SessionInterface $session, TokenStorageInterface $tokenStorage)
|
||||
{
|
||||
$this->session = $session;
|
||||
$this->tokenStorage = $tokenStorage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/login-bind/{provider}/")
|
||||
*/
|
||||
public function bindAction(Request $request)
|
||||
{
|
||||
$provider = $request->get('provider');
|
||||
$this->session->set('bind_external_account', $provider);
|
||||
$next = $request->query->get('next');
|
||||
if (empty($next)) {
|
||||
$next = $request->headers->get('referer');
|
||||
}
|
||||
if (!empty($next)) {
|
||||
if (parse_url($next, PHP_URL_QUERY)) {
|
||||
$next .= '&wpj_utm=auth';
|
||||
} else {
|
||||
$next .= '?wpj_utm=auth';
|
||||
}
|
||||
} else {
|
||||
$next = path('account', ['wpj_utm' => 'auth']);
|
||||
}
|
||||
|
||||
return new RedirectResponse(path('hwi_oauth_service_redirect', [
|
||||
'service' => $provider,
|
||||
'next' => $next,
|
||||
]));
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/login-unbind/{id}/")
|
||||
*/
|
||||
public function unbindAction(Request $request)
|
||||
{
|
||||
$token = $this->tokenStorage->getToken();
|
||||
if ($user = $token?->getUser()) {
|
||||
if (method_exists($user, 'getID')) {
|
||||
$userProvider = $this->selectSQL('users_provider_ids', [
|
||||
'id' => $request->get('id'),
|
||||
'id_user' => $user->getID(),
|
||||
])->fetch();
|
||||
$result = $this->deleteSQL('users_provider_ids', [
|
||||
'id' => $request->get('id'),
|
||||
'id_user' => $user->getID(),
|
||||
]);
|
||||
if ($result == 1) {
|
||||
if ($request->isXmlHttpRequest()) {
|
||||
return new Response();
|
||||
} else {
|
||||
addUserMessage(
|
||||
sprintf(
|
||||
translate('oauth', 'login')['binding_removed'],
|
||||
ucfirst($userProvider['provider']),
|
||||
$userProvider['email']
|
||||
),
|
||||
'success'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($request->isXmlHttpRequest()) {
|
||||
return new Response('', 500);
|
||||
} else {
|
||||
return new RedirectResponse(path('settings'));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\UserOauthBundle\Controller;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Session\SessionInterface;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
class CartRegisterController extends AbstractController
|
||||
{
|
||||
/** @var SessionInterface */
|
||||
private $session;
|
||||
|
||||
public function __construct(SessionInterface $session)
|
||||
{
|
||||
$this->session = $session;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/login-cart/{provider}/")
|
||||
*/
|
||||
public function loginCartAction(Request $request)
|
||||
{
|
||||
$provider = $request->get('provider');
|
||||
$previous = $request->server->get('HTTP_REFERER');
|
||||
if ($previous) {
|
||||
$this->session->set('oauth_register_redirect', $previous);
|
||||
}
|
||||
|
||||
return new RedirectResponse("/connect/{$provider}");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace KupShop\UserOauthBundle\DependencyInjection\Compiler;
|
||||
|
||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
|
||||
class ResourceOwnerPass implements CompilerPassInterface
|
||||
{
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
foreach ($container->getDefinitions() as $key => $definition) {
|
||||
if (str_starts_with($key, 'hwi_oauth.resource_owner.')) {
|
||||
$definition->setAutowired(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace KupShop\UserOauthBundle\EventSubscriber;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\Security\Http\Event\LogoutEvent;
|
||||
|
||||
class LogoutSubscriber implements EventSubscriberInterface
|
||||
{
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
LogoutEvent::class => [
|
||||
['onLogout', 200],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function onLogout(LogoutEvent $event): void
|
||||
{
|
||||
// set `logout: true` session to notify js-shop
|
||||
$event->getRequest()->getSession()
|
||||
->set('logout', true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace KupShop\UserOauthBundle\ResourceOwner;
|
||||
|
||||
use HWI\Bundle\OAuthBundle\OAuth\RequestDataStorageInterface;
|
||||
use HWI\Bundle\OAuthBundle\OAuth\ResourceOwner\GenericOAuth2ResourceOwner;
|
||||
use HWI\Bundle\OAuthBundle\OAuth\Response\UserResponseInterface;
|
||||
use HWI\Bundle\OAuthBundle\Security\Helper\NonceGenerator;
|
||||
use KupShop\AgeVerifyBundle\Utils\AgeVerifyUtil;
|
||||
use KupShop\KupShopBundle\Config;
|
||||
use KupShop\KupShopBundle\Context\DomainContext;
|
||||
use KupShop\KupShopBundle\Util\Contexts;
|
||||
use Query\Operator;
|
||||
use Symfony\Component\Security\Http\HttpUtils;
|
||||
use Symfony\Contracts\Service\Attribute\Required;
|
||||
|
||||
class BankIdResourceOwner extends GenericOAuth2ResourceOwner implements ICustomResourceOwner
|
||||
{
|
||||
public const SANDBOX_URL = 'https://oidc.sandbox.bankid.cz/';
|
||||
public const PROD_URL = 'https://oidc.bankid.cz/';
|
||||
|
||||
private ?AgeVerifyUtil $ageVerifyUtil = null;
|
||||
|
||||
public function __construct(
|
||||
$httpClient,
|
||||
HttpUtils $httpUtils,
|
||||
array $options,
|
||||
$name,
|
||||
RequestDataStorageInterface $storage,
|
||||
) {
|
||||
if (!isLocalDevelopment()) {
|
||||
$options['client_id'] = $this->getClientId();
|
||||
$options['client_secret'] = $this->getClientSecret();
|
||||
}
|
||||
$options['access_token_url'] = $this->getUrl('token');
|
||||
$options['authorization_url'] = $this->getUrl('auth');
|
||||
$options['infos_url'] = $this->getUrl('userinfo');
|
||||
$options['csrf'] = true;
|
||||
|
||||
parent::__construct($httpClient, $httpUtils, $options, $name, $storage);
|
||||
}
|
||||
|
||||
public function updateUserData(\User $user, UserResponseInterface $response)
|
||||
{
|
||||
$data = [];
|
||||
if ($birthdate = $response->getBirthdate()) {
|
||||
$data['birthdate'] = $birthdate;
|
||||
}
|
||||
|
||||
if ($name = $response->getFirstName()) {
|
||||
$data['name'] = $name;
|
||||
}
|
||||
|
||||
if ($surname = $response->getLastName()) {
|
||||
$data['surname'] = $surname;
|
||||
}
|
||||
|
||||
if (!empty($data)) {
|
||||
sqlQueryBuilder()->update('users')
|
||||
->directValues($data)
|
||||
->where(Operator::equals(['id' => $user->id]))
|
||||
->execute();
|
||||
}
|
||||
|
||||
$date = \DateTime::createFromFormat('Y-m-d', $birthdate)->add(\DateInterval::createFromDateString('+18YEARS'));
|
||||
$this->ageVerifyUtil?->setVerificationData(legalAge: $date <= (new \DateTime()) ? 'Y' : 'N', type: 'bankId', userId: $user->id);
|
||||
}
|
||||
|
||||
protected function getClientId()
|
||||
{
|
||||
if (isLocalDevelopment()) {
|
||||
return $this->options['client_id'];
|
||||
}
|
||||
$settings = \Settings::getDefault();
|
||||
|
||||
return $settings['oauth']['bank_id']['client_id'] ?? '';
|
||||
}
|
||||
|
||||
protected function getClientSecret()
|
||||
{
|
||||
if (isLocalDevelopment()) {
|
||||
return $this->options['client_secret'];
|
||||
}
|
||||
|
||||
$settings = \Settings::getDefault();
|
||||
|
||||
return $settings['oauth']['bank_id']['client_secret'] ?? '';
|
||||
}
|
||||
|
||||
protected function getUrl($path)
|
||||
{
|
||||
if (isDevelopment() || \Settings::getDefault()['oauth']['bank_id']['sandbox']) {
|
||||
return self::SANDBOX_URL.$path;
|
||||
}
|
||||
|
||||
return self::PROD_URL.$path;
|
||||
}
|
||||
|
||||
protected function getRedirectUri()
|
||||
{
|
||||
if (isDevelopment()) {
|
||||
return Config::get()['Addr']['full_original'].'login/check-bankid';
|
||||
}
|
||||
|
||||
/** @var DomainContext $domainContext */
|
||||
$domainContext = Contexts::get(DomainContext::class);
|
||||
|
||||
return $domainContext->getActiveWithScheme().'/login/check-bankid';
|
||||
}
|
||||
|
||||
public function getAuthorizationUrl($redirectUri, array $extraParameters = [])
|
||||
{
|
||||
$extraParameters['redirect_uri'] = $this->getRedirectUri();
|
||||
$extraParameters['nonce'] = NonceGenerator::generate();
|
||||
|
||||
return parent::getAuthorizationUrl($redirectUri, $extraParameters);
|
||||
}
|
||||
|
||||
protected function doGetTokenRequest($url, array $parameters = [])
|
||||
{
|
||||
$parameters['client_id'] = $this->getClientId();
|
||||
$parameters['client_secret'] = $this->getClientSecret();
|
||||
$parameters['redirect_uri'] = $this->getRedirectUri();
|
||||
|
||||
return $this->httpRequest($url, http_build_query($parameters, '', '&'));
|
||||
}
|
||||
|
||||
#[Required]
|
||||
public function setAgeVerifyUtil(?AgeVerifyUtil $ageVerifyUtil): void
|
||||
{
|
||||
$this->ageVerifyUtil = $ageVerifyUtil;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace KupShop\UserOauthBundle\ResourceOwner;
|
||||
|
||||
use HWI\Bundle\OAuthBundle\OAuth\RequestDataStorageInterface;
|
||||
use HWI\Bundle\OAuthBundle\OAuth\ResourceOwner\AppleResourceOwner;
|
||||
use HWI\Bundle\OAuthBundle\OAuth\Response\UserResponseInterface;
|
||||
use Symfony\Component\HttpFoundation\Request as HttpRequest;
|
||||
use Symfony\Component\Security\Http\HttpUtils;
|
||||
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
||||
|
||||
class CustomAppleResourceOwner extends CustomResourceOwner
|
||||
{
|
||||
public function __construct(
|
||||
HttpClientInterface $httpClient,
|
||||
HttpUtils $httpUtils,
|
||||
array $options,
|
||||
string $name,
|
||||
RequestDataStorageInterface $storage,
|
||||
) {
|
||||
$options['client_id'] = $this->getClientId($options);
|
||||
$options['team_id'] = $this->getTeamId($options);
|
||||
$options['key_id'] = $this->getKeyId($options);
|
||||
$options['auth_key'] = $this->getAuthKey($options);
|
||||
|
||||
parent::__construct($httpClient, $httpUtils, $options, $name, $storage);
|
||||
}
|
||||
|
||||
public function createResourceOwner($httpClient, $httpUtils, $options, $name, $storage)
|
||||
{
|
||||
return new AppleResourceOwner($httpClient, $httpUtils, $options, $name, $storage);
|
||||
}
|
||||
|
||||
protected function getClientId(array $options): string
|
||||
{
|
||||
if (isLocalDevelopment()) {
|
||||
return $options['client_id'];
|
||||
}
|
||||
|
||||
$settings = \Settings::getDefault();
|
||||
|
||||
return $settings['oauth']['apple']['client_id'] ?? '';
|
||||
}
|
||||
|
||||
protected function getTeamId(array $options): string
|
||||
{
|
||||
if (isLocalDevelopment()) {
|
||||
return $options['options']['team_id'];
|
||||
}
|
||||
|
||||
$settings = \Settings::getDefault();
|
||||
|
||||
return $settings['oauth']['apple']['team_id'] ?? '';
|
||||
}
|
||||
|
||||
protected function getKeyId(array $options): string
|
||||
{
|
||||
if (isLocalDevelopment()) {
|
||||
return $options['options']['key_id'];
|
||||
}
|
||||
|
||||
$settings = \Settings::getDefault();
|
||||
|
||||
return $settings['oauth']['apple']['key_id'] ?? '';
|
||||
}
|
||||
|
||||
protected function getAuthKey(array $options): string
|
||||
{
|
||||
if (isLocalDevelopment()) {
|
||||
return $options['options']['auth_key'];
|
||||
}
|
||||
|
||||
$settings = \Settings::getDefault();
|
||||
|
||||
$path = $settings['oauth']['apple']['auth_key'] ?? '';
|
||||
|
||||
return file_get_contents(substr($path, 1)) ?? '';
|
||||
}
|
||||
|
||||
public function getAuthorizationUrl($redirectUri, array $extraParameters = [])
|
||||
{
|
||||
$extraParameters['skip_tolocalhost'] = true;
|
||||
|
||||
return parent::getAuthorizationUrl($redirectUri, $extraParameters);
|
||||
}
|
||||
|
||||
public function getAccessToken(HttpRequest $request, $redirectUri, array $extraParameters = [])
|
||||
{
|
||||
$extraParameters['skip_tolocalhost'] = true;
|
||||
|
||||
return parent::getAccessToken($request, $redirectUri, $extraParameters);
|
||||
}
|
||||
|
||||
public function updateUserData(\User $user, UserResponseInterface $response)
|
||||
{
|
||||
// TODO: Implement updateUserData() method.
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\UserOauthBundle\ResourceOwner;
|
||||
|
||||
use HWI\Bundle\OAuthBundle\OAuth\ResourceOwner\FacebookResourceOwner;
|
||||
use HWI\Bundle\OAuthBundle\OAuth\Response\UserResponseInterface;
|
||||
|
||||
class CustomFacebookResourceOwner extends CustomResourceOwner
|
||||
{
|
||||
public function createResourceOwner($httpClient, $httpUtils, $options, $name, $storage)
|
||||
{
|
||||
return new FacebookResourceOwner($httpClient, $httpUtils, $options, $name, $storage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the url to the profile picture.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
protected function getProfilePicture(?string $user_name = null)
|
||||
{
|
||||
if ($user_name) {
|
||||
return 'https://graph.facebook.com/'.$user_name.'/picture?type=square';
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function updateUserData(\User $user, UserResponseInterface $response)
|
||||
{
|
||||
$profilePicture = $this->getProfilePicture($response->getUsername());
|
||||
if ($profilePicture) {
|
||||
$user->setCustomData('profilePicture', $profilePicture);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\UserOauthBundle\ResourceOwner;
|
||||
|
||||
use HWI\Bundle\OAuthBundle\OAuth\ResourceOwner\GoogleResourceOwner;
|
||||
use HWI\Bundle\OAuthBundle\OAuth\Response\UserResponseInterface;
|
||||
|
||||
class CustomGoogleResourceOwner extends CustomResourceOwner
|
||||
{
|
||||
public function createResourceOwner($httpClient, $httpUtils, $options, $name, $storage)
|
||||
{
|
||||
return new GoogleResourceOwner($httpClient, $httpUtils, $options, $name, $storage);
|
||||
}
|
||||
|
||||
public function updateUserData(\User $user, UserResponseInterface $response)
|
||||
{
|
||||
$profilePicture = $response->getProfilePicture();
|
||||
if ($profilePicture) {
|
||||
$user->setCustomData('profilePicture', $profilePicture);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace KupShop\UserOauthBundle\ResourceOwner;
|
||||
|
||||
use HWI\Bundle\OAuthBundle\OAuth\RequestDataStorageInterface;
|
||||
use HWI\Bundle\OAuthBundle\OAuth\ResourceOwnerInterface;
|
||||
use HWI\Bundle\OAuthBundle\OAuth\Response\UserResponseInterface;
|
||||
use HWI\Bundle\OAuthBundle\OAuth\StateInterface;
|
||||
use Symfony\Component\HttpFoundation\Request as HttpRequest;
|
||||
use Symfony\Component\Security\Http\HttpUtils;
|
||||
|
||||
abstract class CustomResourceOwner implements ICustomResourceOwner, ResourceOwnerInterface
|
||||
{
|
||||
protected ResourceOwnerInterface $resourceOwner;
|
||||
|
||||
public function __construct(
|
||||
$httpClient,
|
||||
HttpUtils $httpUtils,
|
||||
array $options,
|
||||
$name,
|
||||
RequestDataStorageInterface $storage,
|
||||
) {
|
||||
if (!isLocalDevelopment()) {
|
||||
$settings = \Settings::getDefault();
|
||||
if (!empty($settings['oauth'][$name]['client_id'])) {
|
||||
$options['client_id'] = $settings['oauth'][$name]['client_id'];
|
||||
}
|
||||
if (!empty($settings['oauth'][$name]['client_secret'])) {
|
||||
$options['client_secret'] = $settings['oauth'][$name]['client_secret'];
|
||||
}
|
||||
}
|
||||
|
||||
$this->resourceOwner = $this->createResourceOwner($httpClient, $httpUtils, $options, $name, $storage);
|
||||
}
|
||||
|
||||
abstract public function createResourceOwner($httpClient, $httpUtils, $options, $name, $storage);
|
||||
|
||||
public function getUserInformation(array $accessToken, array $extraParameters = [])
|
||||
{
|
||||
return $this->resourceOwner->getUserInformation($accessToken, $extraParameters);
|
||||
}
|
||||
|
||||
public function getAuthorizationUrl($redirectUri, array $extraParameters = [])
|
||||
{
|
||||
if (isLocalDevelopment() && !($extraParameters['skip_tolocalhost'] ?? false)) {
|
||||
// Na locale využijeme tolocalhost.com služby, aby nám poskytla veřejnou doménu a pak přesměovala na kupshop.local
|
||||
$redirectUri = str_replace('www.kupshop.local', 'tolocalhost.com', $redirectUri);
|
||||
}
|
||||
|
||||
return $this->resourceOwner->getAuthorizationUrl($redirectUri, $extraParameters);
|
||||
}
|
||||
|
||||
public function getAccessToken(HttpRequest $request, $redirectUri, array $extraParameters = [])
|
||||
{
|
||||
if (isLocalDevelopment() && !($extraParameters['skip_tolocalhost'] ?? false)) {
|
||||
// Na locale využijeme tolocalhost.com služby, aby nám poskytla veřejnou doménu a pak přesměovala na kupshop.local
|
||||
$redirectUri = str_replace('www.kupshop.local', 'tolocalhost.com', $redirectUri);
|
||||
}
|
||||
|
||||
return $this->resourceOwner->getAccessToken($request, $redirectUri, $extraParameters);
|
||||
}
|
||||
|
||||
public function isCsrfTokenValid($csrfToken)
|
||||
{
|
||||
return $this->resourceOwner->isCsrfTokenValid($csrfToken);
|
||||
}
|
||||
|
||||
public function getName(?UserResponseInterface $response = null)
|
||||
{
|
||||
return $this->resourceOwner->getName();
|
||||
}
|
||||
|
||||
public function getOption($name)
|
||||
{
|
||||
return $this->resourceOwner->getOption($name);
|
||||
}
|
||||
|
||||
public function handles(HttpRequest $request)
|
||||
{
|
||||
return $this->resourceOwner->handles($request);
|
||||
}
|
||||
|
||||
public function setName($name)
|
||||
{
|
||||
$this->resourceOwner->setName($name);
|
||||
}
|
||||
|
||||
public function addPaths(array $paths)
|
||||
{
|
||||
$this->resourceOwner->addPaths($paths);
|
||||
}
|
||||
|
||||
public function refreshAccessToken($refreshToken, array $extraParameters = [])
|
||||
{
|
||||
$this->resourceOwner->refreshAccessToken($refreshToken, $extraParameters);
|
||||
}
|
||||
|
||||
public function getState(): StateInterface
|
||||
{
|
||||
return $this->resourceOwner->getState();
|
||||
}
|
||||
|
||||
public function storeState(?StateInterface $state = null)
|
||||
{
|
||||
$this->resourceOwner->storeState($state);
|
||||
}
|
||||
|
||||
public function addStateParameter(string $key, string $value): void
|
||||
{
|
||||
$this->resourceOwner->addStateParameter($key, $value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\UserOauthBundle\ResourceOwner;
|
||||
|
||||
use HWI\Bundle\OAuthBundle\OAuth\Response\UserResponseInterface;
|
||||
|
||||
interface ICustomResourceOwner
|
||||
{
|
||||
public function updateUserData(\User $user, UserResponseInterface $response);
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace KupShop\UserOauthBundle\ResourceOwner;
|
||||
|
||||
use HWI\Bundle\OAuthBundle\OAuth\RequestDataStorageInterface;
|
||||
use HWI\Bundle\OAuthBundle\OAuth\ResourceOwner\GenericOAuth2ResourceOwner;
|
||||
use HWI\Bundle\OAuthBundle\OAuth\Response\UserResponseInterface;
|
||||
use KupShop\AgeVerifyBundle\Utils\AgeVerifyUtil;
|
||||
use Query\Operator;
|
||||
use Symfony\Component\Security\Http\HttpUtils;
|
||||
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
||||
use Symfony\Contracts\Service\Attribute\Required;
|
||||
|
||||
class MojeIDResourceOwner extends GenericOAuth2ResourceOwner implements ICustomResourceOwner
|
||||
{
|
||||
// pro testování lze pouzit testovaci ucet https://mojeid.regtest.nic.cz/index.html
|
||||
public const SANDBOX_URL = 'https://mojeid.regtest.nic.cz/oidc/';
|
||||
public const PROD_URL = 'https://mojeid.cz/oidc/';
|
||||
|
||||
private ?AgeVerifyUtil $ageVerifyUtil = null;
|
||||
|
||||
public function __construct(
|
||||
HttpClientInterface $httpClient,
|
||||
HttpUtils $httpUtils,
|
||||
array $options,
|
||||
string $name,
|
||||
RequestDataStorageInterface $storage,
|
||||
) {
|
||||
if (!isLocalDevelopment()) {
|
||||
$options['client_id'] = $this->getClientId();
|
||||
$options['client_secret'] = $this->getClientSecret();
|
||||
}
|
||||
$options['access_token_url'] = $this->getUrl('token/');
|
||||
$options['authorization_url'] = $this->getUrl('authorization/');
|
||||
$options['infos_url'] = $this->getUrl('userinfo/');
|
||||
|
||||
parent::__construct($httpClient, $httpUtils, $options, $name, $storage);
|
||||
}
|
||||
|
||||
protected function getUrl($path): string
|
||||
{
|
||||
if (isDevelopment()) {
|
||||
return self::SANDBOX_URL.$path;
|
||||
}
|
||||
|
||||
return self::PROD_URL.$path;
|
||||
}
|
||||
|
||||
protected function getClientId()
|
||||
{
|
||||
if (isLocalDevelopment()) {
|
||||
return $this->options['client_id'];
|
||||
}
|
||||
$settings = \Settings::getDefault();
|
||||
|
||||
return $settings['oauth']['mojeid']['client_id'] ?? '';
|
||||
}
|
||||
|
||||
protected function getClientSecret()
|
||||
{
|
||||
if (isLocalDevelopment()) {
|
||||
return $this->options['client_secret'];
|
||||
}
|
||||
|
||||
$settings = \Settings::getDefault();
|
||||
|
||||
return $settings['oauth']['mojeid']['client_secret'] ?? '';
|
||||
}
|
||||
|
||||
protected function doGetTokenRequest($url, array $parameters = [])
|
||||
{
|
||||
$parameters['client_id'] = $this->getClientId();
|
||||
$parameters['client_secret'] = $this->getClientSecret();
|
||||
|
||||
return $this->httpRequest($url, http_build_query($parameters, '', '&'));
|
||||
}
|
||||
|
||||
public function getAuthorizationUrl($redirectUri, array $extraParameters = [])
|
||||
{
|
||||
return parent::getAuthorizationUrl($redirectUri, [
|
||||
'claims' => json_encode([
|
||||
'id_token' => [
|
||||
'birthdate' => [
|
||||
'essential' => true,
|
||||
],
|
||||
'name' => [
|
||||
'essential' => true,
|
||||
],
|
||||
'given_name' => [
|
||||
'essential' => true,
|
||||
],
|
||||
'family_name' => [
|
||||
'essential' => true,
|
||||
],
|
||||
'email' => [
|
||||
'essential' => true,
|
||||
],
|
||||
'address' => [
|
||||
'essential' => false,
|
||||
],
|
||||
'mojeid_valid' => ['essential' => true],
|
||||
],
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
public function updateUserData(\User $user, UserResponseInterface $response)
|
||||
{
|
||||
$data = [];
|
||||
if ($birthdate = $response->getBirthdate()) {
|
||||
$data['birthdate'] = $birthdate;
|
||||
}
|
||||
|
||||
if ($name = $response->getFirstName()) {
|
||||
$data['name'] = $name;
|
||||
}
|
||||
|
||||
if ($surname = $response->getLastName()) {
|
||||
$data['surname'] = $surname;
|
||||
}
|
||||
|
||||
if ($address = $response->getAddress()) {
|
||||
$data['street'] = $address['street_address'] ?? '';
|
||||
$data['city'] = $address['locality'] ?? '';
|
||||
$data['zip'] = $address['postal_code'] ?? '';
|
||||
$data['country'] = $address['country'] ?? '';
|
||||
}
|
||||
|
||||
if (!empty($data)) {
|
||||
sqlQueryBuilder()->update('users')
|
||||
->directValues($data)
|
||||
->where(Operator::equals(['id' => $user->id]))
|
||||
->execute();
|
||||
}
|
||||
|
||||
if ($birthdate) {
|
||||
$date = \DateTime::createFromFormat('Y-m-d', $birthdate)->add(\DateInterval::createFromDateString('+18YEARS'));
|
||||
$this->ageVerifyUtil?->setVerificationData(legalAge: $date <= (new \DateTime()) ? 'Y' : 'N', type: 'mojeid', userId: $user->id);
|
||||
}
|
||||
}
|
||||
|
||||
#[Required]
|
||||
public function setAgeVerifyUtil(?AgeVerifyUtil $ageVerifyUtil): void
|
||||
{
|
||||
$this->ageVerifyUtil = $ageVerifyUtil;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace KupShop\UserOauthBundle\ResourceOwner;
|
||||
|
||||
use HWI\Bundle\OAuthBundle\OAuth\RequestDataStorageInterface;
|
||||
use HWI\Bundle\OAuthBundle\OAuth\ResourceOwner\GenericOAuth2ResourceOwner;
|
||||
use HWI\Bundle\OAuthBundle\OAuth\Response\UserResponseInterface;
|
||||
use KupShop\KupShopBundle\Config;
|
||||
use KupShop\KupShopBundle\Context\DomainContext;
|
||||
use KupShop\KupShopBundle\Util\Contexts;
|
||||
use Query\Operator;
|
||||
use Symfony\Component\Security\Http\HttpUtils;
|
||||
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
||||
|
||||
class SeznamResourceOwner extends GenericOAuth2ResourceOwner implements ICustomResourceOwner
|
||||
{
|
||||
public const URL = 'https://login.szn.cz/api/v1/';
|
||||
|
||||
public function __construct(
|
||||
HttpClientInterface $httpClient,
|
||||
HttpUtils $httpUtils,
|
||||
array $options,
|
||||
string $name,
|
||||
RequestDataStorageInterface $storage,
|
||||
) {
|
||||
if (!isLocalDevelopment()) {
|
||||
$options['client_id'] = $this->getClientId();
|
||||
$options['client_secret'] = $this->getClientSecret();
|
||||
}
|
||||
$options['access_token_url'] = $this->getUrl('oauth/token');
|
||||
$options['authorization_url'] = $this->getUrl('oauth/auth');
|
||||
$options['infos_url'] = $this->getUrl('user');
|
||||
|
||||
parent::__construct($httpClient, $httpUtils, $options, $name, $storage);
|
||||
}
|
||||
|
||||
public function updateUserData(\User $user, UserResponseInterface $response)
|
||||
{
|
||||
$data = [];
|
||||
|
||||
if ($firstName = $response->getData()['firstname']) {
|
||||
$data['name'] = $firstName;
|
||||
}
|
||||
|
||||
if ($lastName = $response->getData()['lastname']) {
|
||||
$data['surname'] = $lastName;
|
||||
}
|
||||
|
||||
if (!empty($data)) {
|
||||
sqlQueryBuilder()->update('users')
|
||||
->directValues($data)
|
||||
->where(Operator::equals(['id' => $user->id]))
|
||||
->execute();
|
||||
}
|
||||
}
|
||||
|
||||
protected function getClientId(): string
|
||||
{
|
||||
if (isLocalDevelopment()) {
|
||||
return $this->options['client_id'];
|
||||
}
|
||||
|
||||
$settings = \Settings::getDefault();
|
||||
|
||||
return $settings['oauth']['seznam']['client_id'] ?? '';
|
||||
}
|
||||
|
||||
protected function getClientSecret(): string
|
||||
{
|
||||
if (isLocalDevelopment()) {
|
||||
return $this->options['client_secret'];
|
||||
}
|
||||
|
||||
$settings = \Settings::getDefault();
|
||||
|
||||
return $settings['oauth']['seznam']['client_secret'] ?? '';
|
||||
}
|
||||
|
||||
protected function getUrl(string $path): string
|
||||
{
|
||||
return self::URL.$path;
|
||||
}
|
||||
|
||||
protected function getRedirectUri(): string
|
||||
{
|
||||
if (isDevelopment()) {
|
||||
return Config::get()['Addr']['full'].'login/check-seznam/';
|
||||
}
|
||||
|
||||
/** @var DomainContext $domainContext */
|
||||
$domainContext = Contexts::get(DomainContext::class);
|
||||
|
||||
return $domainContext->getActiveWithScheme().'/login/check-seznam/';
|
||||
}
|
||||
|
||||
public function getAuthorizationUrl($redirectUri, array $extraParameters = [])
|
||||
{
|
||||
$extraParameters['redirect_uri'] = $this->getRedirectUri();
|
||||
|
||||
return parent::getAuthorizationUrl($redirectUri, $extraParameters);
|
||||
}
|
||||
|
||||
protected function doGetTokenRequest($url, array $parameters = [])
|
||||
{
|
||||
$parameters['client_id'] = $this->getClientId();
|
||||
$parameters['client_secret'] = $this->getClientSecret();
|
||||
$parameters['redirect_uri'] = $this->getRedirectUri();
|
||||
|
||||
return $this->httpRequest($url, http_build_query($parameters, '', '&'));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
imports:
|
||||
- { resource: 'security.yml' }
|
||||
- { resource: 'hwiOauth.yml' }
|
||||
113
bundles/KupShop/UserOauthBundle/Resources/config/hwiOauth.yml
Normal file
113
bundles/KupShop/UserOauthBundle/Resources/config/hwiOauth.yml
Normal file
@@ -0,0 +1,113 @@
|
||||
parameters:
|
||||
facebook_client_id: 947379488985980
|
||||
facebook_client_secret: b3fb9b6cd21e52ea79e19a5a18179410
|
||||
google_client_id: '787722845021-vspi8iechcta8c67esethe2oue9qifdd.apps.googleusercontent.com'
|
||||
google_client_secret: 'lzMuLFodGN1dk3zkgY0v1E_t'
|
||||
bankid_client_id: '8bac41a4-e6d5-455b-bea1-83ea0fdc65a5'
|
||||
bankid_client_secret: 'ANWPPe1MivCVHtqFPlBZhVZNSGmH0uYKoKwfLD1uVONpYd86us4jSu23EbzabTEwxFZ-soqzhvuyN_s5TYX0zxM'
|
||||
mojeid_client_id: 'UG315IdkvnQ6'
|
||||
mojeid_client_secret: '6f5a8ae93b96050ab7a6a6dc8d1222ea1de5e5cde06d6fde0d208e73'
|
||||
seznam_client_id: '373b52f07568beba6122c1ab386f06340befe6076be51d30'
|
||||
seznam_client_secret: '046f01b7c6ed1cf39ae7b6dded8189afd593e3196fdd1b67'
|
||||
amazon_client_id: 'amzn1.application-oa2-client.cb5d9d73b8c4464fa53a2aeaa5684e3f'
|
||||
amazon_client_secret: 'amzn1.oa2-cs.v1.307eccb59d9a78627985e051f335cf37290b936282d8f4f2a01bb537ef2a6190'
|
||||
apple_client_id: 'local.kupshop'
|
||||
env(APPLE_AUTH_KEY_PATH): "%kernel.project_dir%/AuthKey_PY9XTX36J3.p8"
|
||||
hwi_oauth.resource_owner.facebook.class: 'KupShop\UserOauthBundle\ResourceOwner\CustomFacebookResourceOwner'
|
||||
hwi_oauth.resource_owner.google.class: 'KupShop\UserOauthBundle\ResourceOwner\CustomGoogleResourceOwner'
|
||||
hwi_oauth.resource_owner.bankid.class: 'KupShop\UserOauthBundle\ResourceOwner\BankIdResourceOwner'
|
||||
hwi_oauth.resource_owner.mojeid.class: 'KupShop\UserOauthBundle\ResourceOwner\MojeIDResourceOwner'
|
||||
hwi_oauth.resource_owner.seznam.class: 'KupShop\UserOauthBundle\ResourceOwner\SeznamResourceOwner'
|
||||
hwi_oauth.resource_owner.apple.class: 'KupShop\UserOauthBundle\ResourceOwner\CustomAppleResourceOwner'
|
||||
|
||||
hwi_oauth:
|
||||
# list of names of the firewalls in which this bundle is active, this setting MUST be set
|
||||
firewall_names: [main]
|
||||
target_path_parameter: next
|
||||
resource_owners:
|
||||
facebook:
|
||||
type: facebook
|
||||
client_id: '%facebook_client_id%'
|
||||
client_secret: '%facebook_client_secret%'
|
||||
scope: "email"
|
||||
infos_url: "https://graph.facebook.com/me?fields=id,name,first_name,last_name,email,picture.type(square)"
|
||||
paths:
|
||||
email: email
|
||||
profilepicture: picture.data.url
|
||||
options:
|
||||
auth_type: rerequest # Re-asking for Declined Permissions
|
||||
google:
|
||||
type: google
|
||||
client_id: '%google_client_id%'
|
||||
client_secret: '%google_client_secret%'
|
||||
scope: 'email profile'
|
||||
paths:
|
||||
email: email
|
||||
profilepicture: picture
|
||||
bankid:
|
||||
type: oauth2
|
||||
client_id: '%bankid_client_id%'
|
||||
client_secret: '%bankid_client_secret%'
|
||||
class: KupShop\UserOauthBundle\ResourceOwner\BankIdResourceOwner
|
||||
scope: "openid profile.birthdate profile.email profile.name profile.phonenumber"
|
||||
user_response_class: KupShop\UserOauthBundle\Response\BankIdPathUserResponse
|
||||
paths:
|
||||
identifier: sub
|
||||
realname: name
|
||||
email: email
|
||||
phone: phonenumber
|
||||
birthdate: birthdate
|
||||
firstname: given_name
|
||||
lastname: family_name
|
||||
mojeid:
|
||||
type: oauth2
|
||||
client_id: '%mojeid_client_id%'
|
||||
client_secret: '%mojeid_client_secret%'
|
||||
class: KupShop\UserOauthBundle\ResourceOwner\MojeIDResourceOwner
|
||||
scope: 'openid profile birthdate email address'
|
||||
user_response_class: KupShop\UserOauthBundle\Response\MojeIDPathUserResponse
|
||||
paths:
|
||||
identifier: sub
|
||||
realname: name
|
||||
email: email
|
||||
firstname: given_name
|
||||
lastname: family_name
|
||||
birthdate: birthdate
|
||||
address: address
|
||||
seznam:
|
||||
type: oauth2
|
||||
client_id: '%seznam_client_id%'
|
||||
client_secret: '%seznam_client_secret%'
|
||||
class: KupShop\UserOauthBundle\ResourceOwner\SeznamResourceOwner
|
||||
scope: "openid, email, identity"
|
||||
paths:
|
||||
identifier: oauth_user_id
|
||||
email: email
|
||||
firstname: firstname
|
||||
lastname: lastname
|
||||
amazon:
|
||||
type: oauth2
|
||||
client_id: '%amazon_client_id%'
|
||||
client_secret: '%amazon_client_secret%'
|
||||
class: HWI\Bundle\OAuthBundle\OAuth\ResourceOwner\AmazonResourceOwner
|
||||
scope: "profile"
|
||||
user_response_class: KupShop\UserOauthBundle\Response\AmazonPathUserResponse
|
||||
paths:
|
||||
identifier: user_id
|
||||
email: email
|
||||
apple:
|
||||
type: apple
|
||||
client_id: '%apple_client_id%'
|
||||
client_secret: 'auto'
|
||||
scope: "name email"
|
||||
class: KupShop\UserOauthBundle\ResourceOwner\CustomAppleResourceOwner
|
||||
options:
|
||||
auth_key: |
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgMG1ueHW5U4HeHgHX
|
||||
xDQiegpjNOkHJt5oil0CFujR/6CgCgYIKoZIzj0DAQehRANCAAR0l8D5/hsL5kHH
|
||||
Q0FMIyd+Yuvx4R18ykyoSJ1r/FuM8Jn8aQ3NPMpaBcMTTbIjkrhtAHMHDI8r3ZYm
|
||||
7eEe7yw+
|
||||
-----END PRIVATE KEY-----
|
||||
key_id: 'PY9XTX36J3'
|
||||
team_id: '3GJ63RH8PG'
|
||||
26
bundles/KupShop/UserOauthBundle/Resources/config/routing.yml
Normal file
26
bundles/KupShop/UserOauthBundle/Resources/config/routing.yml
Normal file
@@ -0,0 +1,26 @@
|
||||
hwi_oauth_redirect:
|
||||
resource: "@HWIOAuthBundle/Resources/config/routing/redirect.xml"
|
||||
prefix: /connect
|
||||
|
||||
facebook_check:
|
||||
path: /login/check-facebook
|
||||
|
||||
google_check:
|
||||
path: /login/check-google
|
||||
|
||||
bankid_check:
|
||||
path: /login/check-bankid
|
||||
|
||||
mojeid_check:
|
||||
path: /login/check-mojeid
|
||||
|
||||
seznam_check:
|
||||
path: /login/check-seznam
|
||||
|
||||
apple_check:
|
||||
path: /login/check-apple
|
||||
|
||||
|
||||
content:
|
||||
resource: "@UserOauthBundle/Controller/"
|
||||
type: annotation
|
||||
@@ -0,0 +1,24 @@
|
||||
security:
|
||||
providers:
|
||||
kupshop_useroauthbundle:
|
||||
id: KupShop\UserOauthBundle\Security\OauthUserProvider
|
||||
|
||||
firewalls:
|
||||
admin:
|
||||
pattern: ^/(admin|_z)/
|
||||
main:
|
||||
oauth:
|
||||
provider: kupshop_useroauthbundle
|
||||
resource_owners:
|
||||
facebook: "/login/check-facebook"
|
||||
google: "/login/check-google"
|
||||
bankid: "/login/check-bankid"
|
||||
mojeid: "/login/check-mojeid"
|
||||
seznam: "/login/check-seznam"
|
||||
amazon: "/login/check-amazon"
|
||||
apple: "/login/check-apple"
|
||||
login_path: /
|
||||
failure_path: kupshop_user_login_login
|
||||
oauth_user_provider:
|
||||
service: KupShop\UserOauthBundle\Security\OauthUserProvider
|
||||
access_denied_handler: KupShop\UserOauthBundle\Security\AccessDeniedHandler
|
||||
@@ -0,0 +1,12 @@
|
||||
services:
|
||||
_defaults:
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
|
||||
KupShop\UserOauthBundle\:
|
||||
resource: ../../{Admin/Tabs,EventSubscriber}
|
||||
|
||||
KupShop\UserOauthBundle\Security\OauthUserProvider: ~
|
||||
KupShop\UserOauthBundle\Security\AccessDeniedHandler: ~
|
||||
KupShop\UserOauthBundle\Controller\BindExternalAccountController: ~
|
||||
KupShop\UserOauthBundle\Controller\CartRegisterController: ~
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
|
||||
|
||||
function smarty_function_get_logged_user_provider_ids($params, &$smarty)
|
||||
{
|
||||
/** @var $tokenStorage TokenStorage */
|
||||
$tokenStorage = ServiceContainer::getService('security.token_storage');
|
||||
$token = $tokenStorage->getToken();
|
||||
|
||||
if ($token && ($user = $token->getUser())) {
|
||||
if (method_exists($user, 'getID')) {
|
||||
$providers = sqlQueryBuilder()->select('*')->from('users_provider_ids')
|
||||
->where('id_user=:id_user')->setParameter('id_user', $user->getID())
|
||||
->orderBy('provider')->addOrderBy('email')->execute()->fetchAll();
|
||||
|
||||
if (!empty($params['assign'])) {
|
||||
$smarty->assign($params['assign'], $providers);
|
||||
} else {
|
||||
return $providers;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\UserOauthBundle\Resources\upgrade;
|
||||
|
||||
class UserOauthUpgrade extends \UpgradeNew
|
||||
{
|
||||
public function check_usersProviderIDs()
|
||||
{
|
||||
return $this->checkTableExists('users_provider_ids');
|
||||
}
|
||||
|
||||
/** Add table users_provider_ids */
|
||||
public function upgrade_usersProviderIDs()
|
||||
{
|
||||
sqlQuery('CREATE TABLE IF NOT EXISTS users_provider_ids
|
||||
(
|
||||
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||||
id_user INT(11) UNSIGNED NOT NULL,
|
||||
provider VARCHAR(255) NOT NULL,
|
||||
client_id VARCHAR(255) NOT NULL,
|
||||
email VARCHAR(255) DEFAULT NULL,
|
||||
FOREIGN KEY (id_user)
|
||||
REFERENCES users(id)
|
||||
ON DELETE CASCADE ON UPDATE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
CREATE INDEX users_provider_ids_provider_index ON users_provider_ids (provider);
|
||||
|
||||
CREATE UNIQUE INDEX users_provider_ids_provider_client_id_uindex
|
||||
ON users_provider_ids (provider, client_id);
|
||||
');
|
||||
$this->upgradeOK();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace KupShop\UserOauthBundle\Response;
|
||||
|
||||
use HWI\Bundle\OAuthBundle\OAuth\Response\PathUserResponse;
|
||||
|
||||
class AmazonPathUserResponse extends PathUserResponse
|
||||
{
|
||||
public function getFirstName()
|
||||
{
|
||||
return explode(' ', $this->getData()['name'])[0] ?? '';
|
||||
}
|
||||
|
||||
public function getLastName()
|
||||
{
|
||||
$lastName = explode(' ', $this->getData()['name']);
|
||||
|
||||
return end($lastName) ?? '';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace KupShop\UserOauthBundle\Response;
|
||||
|
||||
use HWI\Bundle\OAuthBundle\OAuth\Response\PathUserResponse;
|
||||
|
||||
class BankIdPathUserResponse extends PathUserResponse
|
||||
{
|
||||
public function getBirthdate()
|
||||
{
|
||||
return $this->getValueForPath('birthdate');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace KupShop\UserOauthBundle\Response;
|
||||
|
||||
use HWI\Bundle\OAuthBundle\OAuth\Response\PathUserResponse;
|
||||
|
||||
class MojeIDPathUserResponse extends PathUserResponse
|
||||
{
|
||||
public function getBirthdate()
|
||||
{
|
||||
return $this->getValueForPath('birthdate');
|
||||
}
|
||||
|
||||
public function getAddress()
|
||||
{
|
||||
return $this->getValueForPath('address');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\UserOauthBundle\Security;
|
||||
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
|
||||
use Symfony\Component\Security\Http\Authorization\AccessDeniedHandlerInterface;
|
||||
|
||||
class AccessDeniedHandler implements AccessDeniedHandlerInterface
|
||||
{
|
||||
public function handle(Request $request, AccessDeniedException $accessDeniedException): ?Response
|
||||
{
|
||||
if ($accessDeniedException instanceof OauthBindFailedException) {
|
||||
addUserMessage(translate('oauth', 'login')['bind_failed']);
|
||||
|
||||
return new RedirectResponse(path('settings'));
|
||||
} elseif ($accessDeniedException instanceof OauthBindRefusedException) {
|
||||
addUserMessage(translate('oauth', 'login')['bind_refused']);
|
||||
|
||||
return new RedirectResponse(path('settings'));
|
||||
} elseif ($accessDeniedException instanceof OauthBindSuccessException) {
|
||||
return new RedirectResponse(path('settings', ['wpj_utm' => 'auth']));
|
||||
} elseif ($accessDeniedException instanceof ShouldLogOutException) {
|
||||
addUserMessage(translate('oauth', 'login')['should_logout']);
|
||||
|
||||
return new RedirectResponse(path('account'));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\UserOauthBundle\Security;
|
||||
|
||||
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
|
||||
|
||||
/**
|
||||
* Throw this exception if clientID is not found but email is known.
|
||||
*/
|
||||
class ClientIDNotFoundException extends UserNotFoundException
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\UserOauthBundle\Security;
|
||||
|
||||
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
|
||||
|
||||
class OauthBindFailedException extends AccessDeniedException
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\UserOauthBundle\Security;
|
||||
|
||||
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
|
||||
|
||||
class OauthBindRefusedException extends AccessDeniedException
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\UserOauthBundle\Security;
|
||||
|
||||
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
|
||||
|
||||
class OauthBindSuccessException extends AccessDeniedException
|
||||
{
|
||||
}
|
||||
44
bundles/KupShop/UserOauthBundle/Security/OauthUser.php
Normal file
44
bundles/KupShop/UserOauthBundle/Security/OauthUser.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\UserOauthBundle\Security;
|
||||
|
||||
use KupShop\UserBundle\Security\User;
|
||||
|
||||
class OauthUser extends User
|
||||
{
|
||||
protected $provider;
|
||||
protected $clientID;
|
||||
|
||||
public function __construct(
|
||||
int $id,
|
||||
string $email,
|
||||
?string $provider = null,
|
||||
?string $clientID = null,
|
||||
array $roles,
|
||||
$kupshopUser,
|
||||
) {
|
||||
parent::__construct($id, $email, null, $roles, $kupshopUser);
|
||||
|
||||
$this->id = $id;
|
||||
$this->email = $email;
|
||||
$this->provider = $provider;
|
||||
$this->clientID = $clientID;
|
||||
$this->roles = $roles;
|
||||
$this->kupshopUser = $kupshopUser;
|
||||
}
|
||||
|
||||
public function getPassword(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function getProvider()
|
||||
{
|
||||
return $this->provider;
|
||||
}
|
||||
|
||||
public function getClientID()
|
||||
{
|
||||
return $this->clientID;
|
||||
}
|
||||
}
|
||||
312
bundles/KupShop/UserOauthBundle/Security/OauthUserProvider.php
Normal file
312
bundles/KupShop/UserOauthBundle/Security/OauthUserProvider.php
Normal file
@@ -0,0 +1,312 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\UserOauthBundle\Security;
|
||||
|
||||
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
|
||||
use HWI\Bundle\OAuthBundle\OAuth\Response\UserResponseInterface;
|
||||
use HWI\Bundle\OAuthBundle\Security\Core\User\OAuthAwareUserProviderInterface;
|
||||
use KupShop\GraphQLBundle\EventListener\JsShopRefreshListener;
|
||||
use KupShop\KupShopBundle\Context\CurrencyContext;
|
||||
use KupShop\KupShopBundle\Context\LanguageContext;
|
||||
use KupShop\KupShopBundle\Util\Contexts;
|
||||
use KupShop\UserBundle\Event\UserRegisteredEvent;
|
||||
use KupShop\UserOauthBundle\ResourceOwner\ICustomResourceOwner;
|
||||
use Query\Operator;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\HttpFoundation\Session\SessionInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
|
||||
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
use Symfony\Component\Security\Core\User\UserProviderInterface;
|
||||
|
||||
class OauthUserProvider implements UserProviderInterface, OAuthAwareUserProviderInterface
|
||||
{
|
||||
use \DatabaseCommunication;
|
||||
|
||||
/** @var EventDispatcherInterface */
|
||||
protected $eventDispatcher;
|
||||
|
||||
public function __construct(
|
||||
protected TokenStorageInterface $tokenStorage,
|
||||
protected SessionInterface $session,
|
||||
protected RequestStack $requestStack,
|
||||
) {
|
||||
}
|
||||
|
||||
public function loadUserByUsername($username)
|
||||
{
|
||||
return $this->loadUserByIdentifier($username);
|
||||
}
|
||||
|
||||
public function loadUserByIdentifier(string $identifier): UserInterface
|
||||
{
|
||||
throw new UserNotFoundException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes the user for the account interface.
|
||||
*
|
||||
* It is up to the implementation to decide if the user data should be
|
||||
* totally reloaded (e.g. from the database), or if the UserInterface
|
||||
* object can just be merged into some internal array of users / identity
|
||||
* map.
|
||||
*
|
||||
* @throws UnsupportedUserException if the account is not supported
|
||||
*/
|
||||
public function refreshUser(UserInterface $user): UserInterface
|
||||
{
|
||||
if ($user instanceof OauthUser) {
|
||||
$userObject = $this->getUserByClientID($user->getProvider(), $user->getClientID());
|
||||
if ($userObject) {
|
||||
$userObject->activateUser();
|
||||
|
||||
return new OauthUser(
|
||||
$userObject->id,
|
||||
$userObject->email,
|
||||
$user->getProvider(),
|
||||
$user->getClientID(),
|
||||
['ROLE_USER'],
|
||||
$userObject
|
||||
);
|
||||
} else {
|
||||
// this usually happens when user unbinds his fb/google account and is currently logged in with it
|
||||
$this->tokenStorage->setToken(null);
|
||||
// hack to preserve userMessages
|
||||
$userMessages = $this->session->get('userMessages');
|
||||
$this->session->invalidate();
|
||||
$this->session->set('userMessages', $userMessages);
|
||||
if (findModule(\Modules::JS_SHOP)) {
|
||||
// set `jsShopReload: true` session to notify js-cart
|
||||
$this->session->set(JsShopRefreshListener::SESSION_NAME, true);
|
||||
}
|
||||
addUserMessage(translate('oauth', 'login')['invalid_login']);
|
||||
redirection(path('kupshop_user_login_login'));
|
||||
}
|
||||
}
|
||||
|
||||
throw new UnsupportedUserException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this provider supports the given user class.
|
||||
*
|
||||
* @param string $class
|
||||
*/
|
||||
public function supportsClass($class): bool
|
||||
{
|
||||
return $class === OauthUser::class;
|
||||
}
|
||||
|
||||
private function getUserByClientID(string $provider, string $clientID)
|
||||
{
|
||||
$providerRow = $this->selectSQL('users_provider_ids', [
|
||||
'provider' => $provider,
|
||||
'client_id' => $clientID,
|
||||
])->fetch();
|
||||
if ($providerRow) {
|
||||
$user = \User::createFromId($providerRow['id_user']);
|
||||
}
|
||||
|
||||
return $user ?? false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the user by a given UserResponseInterface object.
|
||||
*
|
||||
* @return UserInterface
|
||||
*
|
||||
* @throws UserNotFoundException if the user is not found
|
||||
*/
|
||||
public function loadUserByOAuthUserResponse(UserResponseInterface $response)
|
||||
{
|
||||
$email = $response->getEmail();
|
||||
$resourceOwner = $response->getResourceOwner();
|
||||
$provider = $resourceOwner->getName();
|
||||
$clientID = $response->getUsername();
|
||||
$user = $this->getUserByClientID($provider, $clientID ?? '');
|
||||
$token = $this->tokenStorage->getToken();
|
||||
|
||||
if ($user && !$user->isActive()) {
|
||||
throw new UserNotFoundException();
|
||||
}
|
||||
|
||||
if ($user && $token?->getUser()) {
|
||||
if ($this->session->get('bind_external_account') === $provider) {
|
||||
// external account is already linked so refuse bind
|
||||
$this->session->remove('bind_external_account');
|
||||
throw new OauthBindRefusedException('Account already binded.');
|
||||
} else {
|
||||
// unintended bind (eg: when user is already logged in, but goes to /connect/google without proper session)
|
||||
throw new ShouldLogOutException('Unintended bind.');
|
||||
}
|
||||
}
|
||||
|
||||
// bind account to current user
|
||||
// to restrict binding for non logged users add condition: $token && $token->isAuthenticated()
|
||||
if (!$user) {
|
||||
$tokenUsername = $token?->getUser() ? $token->getUserIdentifier() : null;
|
||||
// unintended bind check
|
||||
if ($tokenUsername && $this->session->get('bind_external_account') !== $provider) {
|
||||
throw new OauthBindRefusedException('Unintended bind.');
|
||||
}
|
||||
$this->session->remove('bind_external_account');
|
||||
|
||||
$user = \User::createFromLogin($tokenUsername ?? $email);
|
||||
if ($user) {
|
||||
try {
|
||||
$user = sqlGetConnection()->transactional(function () use ($user, $provider, $clientID, $email) {
|
||||
$this->insertSQL(
|
||||
'users_provider_ids',
|
||||
[
|
||||
'id_user' => $user->id,
|
||||
'provider' => $provider,
|
||||
'client_id' => $clientID,
|
||||
'email' => $email,
|
||||
]
|
||||
);
|
||||
|
||||
return $this->getUserByClientID($provider, $clientID);
|
||||
});
|
||||
|
||||
if ($token?->getUser()) {
|
||||
if ($user) {
|
||||
addUserMessage(
|
||||
sprintf(
|
||||
translate('oauth', 'login')['bind_success'],
|
||||
ucfirst($provider),
|
||||
$email
|
||||
),
|
||||
'success'
|
||||
);
|
||||
if ($resourceOwner instanceof ICustomResourceOwner) {
|
||||
$resourceOwner->updateUserData($user, $response);
|
||||
}
|
||||
throw new OauthBindSuccessException();
|
||||
} else {
|
||||
throw new OauthBindFailedException('User not found.');
|
||||
}
|
||||
}
|
||||
} catch (UniqueConstraintViolationException $e) {
|
||||
throw new OauthBindFailedException('OAuth already binded.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add new user
|
||||
if (!$user && !empty($email) && !empty($response->getFirstName()) && !empty($response->getLastName())
|
||||
&& !empty($clientID)
|
||||
) {
|
||||
try {
|
||||
$user = sqlGetConnection()->transactional(function () use ($email, $response, $provider, $clientID) {
|
||||
$insert = [
|
||||
'email' => $email,
|
||||
'name' => $response->getFirstName(),
|
||||
'surname' => $response->getLastName(),
|
||||
'date_reg' => date('Y-m-d H:i:s'),
|
||||
];
|
||||
|
||||
if (findModule(\Modules::CURRENCIES)) {
|
||||
$currencyContext = Contexts::get(CurrencyContext::class);
|
||||
$insert['currency'] = $currencyContext->getActiveId();
|
||||
}
|
||||
|
||||
if (findModule(\Modules::TRANSLATIONS)) {
|
||||
$languageContext = Contexts::get(LanguageContext::class);
|
||||
$insert['id_language'] = $languageContext->getActiveId();
|
||||
}
|
||||
|
||||
try {
|
||||
$this->insertSQL('users', $insert);
|
||||
$userId = sqlInsertId();
|
||||
} catch (UniqueConstraintViolationException) {
|
||||
if (!($userId = $this->checkNewsletterUser($insert['email'], $insert))) {
|
||||
// pokud uzivatel existuje a je neaktivni z jineho duvodu, nez newsletter, tak ho nedovolim sparovat/prihlasit
|
||||
throw new UserNotFoundException();
|
||||
}
|
||||
}
|
||||
|
||||
$this->insertSQL(
|
||||
'users_provider_ids',
|
||||
[
|
||||
'id_user' => $userId,
|
||||
'provider' => $provider,
|
||||
'client_id' => $clientID,
|
||||
'email' => $email,
|
||||
]
|
||||
);
|
||||
|
||||
$this->eventDispatcher->dispatch(
|
||||
new UserRegisteredEvent(\User::createFromId($userId), $response->getResourceOwner()->getName())
|
||||
);
|
||||
|
||||
return $this->getUserByClientID($provider, $clientID);
|
||||
});
|
||||
// redirect to user account
|
||||
addUserMessage(translate('oauth', 'login')['registration_success'], 'success');
|
||||
$this->requestStack->getMainRequest()->attributes->set('gtm_registration', [
|
||||
'email' => $email ?? 'no-email',
|
||||
'firstname' => $response->getFirstName() ?? 'no-firstname',
|
||||
]);
|
||||
// force redirection to user settings
|
||||
$this->session->set('_security.main.target_path', path('settings'));
|
||||
} catch (UniqueConstraintViolationException $e) {
|
||||
}
|
||||
}
|
||||
|
||||
// user was not found by clientID, but we already have his email, so we can't register him
|
||||
// LoginView catches this error and displays translatable message:
|
||||
// translate('oauth', 'login')['unknown_clientid_with_known_email']
|
||||
if (!$user) {
|
||||
throw new ClientIDNotFoundException($email ?? '');
|
||||
}
|
||||
|
||||
if ($resourceOwner instanceof ICustomResourceOwner) {
|
||||
$resourceOwner->updateUserData($user, $response);
|
||||
}
|
||||
|
||||
if ($this->session->get('oauth_register_redirect')) {
|
||||
$this->session->set('_security.main.target_path', $this->session->get('oauth_register_redirect'));
|
||||
$this->session->remove('oauth_register_redirect');
|
||||
}
|
||||
|
||||
// user found or successfully created
|
||||
return new OauthUser($user->id, $user->email, $provider, $clientID, ['ROLE_USER'], $user);
|
||||
}
|
||||
|
||||
private function checkNewsletterUser(string $email, array $update = []): ?int
|
||||
{
|
||||
$user = sqlQueryBuilder()
|
||||
->select('id, figure, passw, get_news, date_subscribe, date_unsubscribe')
|
||||
->from('users')
|
||||
->where(Operator::equals(['email' => $email]))
|
||||
->execute()->fetchAssociative();
|
||||
|
||||
if (!$user) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// pokud je to neaktivni uzivatel, kterej nejspis vznikl pres newsletter, tak ho rovnou zaktivuju at to prihlaseni pres socky vubec funguje
|
||||
if ($user['figure'] === 'N' && empty($user['passw']) && ($user['get_news'] === 'Y' || !empty($user['date_subscribe']) || !empty($user['date_unsubscribe']))) {
|
||||
sqlQueryBuilder()
|
||||
->update('users')
|
||||
->directValues(array_merge($update, ['figure' => 'Y']))
|
||||
->where(Operator::equals(['id' => $user['id']]))
|
||||
->execute();
|
||||
} else {
|
||||
// pokud to neni newsletter uzivatel, tak vracim null
|
||||
return null;
|
||||
}
|
||||
|
||||
return $user['id'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @required
|
||||
*/
|
||||
public function setEventDispatcher(EventDispatcherInterface $eventDispatcher): void
|
||||
{
|
||||
$this->eventDispatcher = $eventDispatcher;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\UserOauthBundle\Security;
|
||||
|
||||
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
|
||||
|
||||
class ShouldLogOutException extends AccessDeniedException
|
||||
{
|
||||
}
|
||||
14
bundles/KupShop/UserOauthBundle/UserOauthBundle.php
Normal file
14
bundles/KupShop/UserOauthBundle/UserOauthBundle.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\UserOauthBundle;
|
||||
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\HttpKernel\Bundle\Bundle;
|
||||
|
||||
class UserOauthBundle extends Bundle
|
||||
{
|
||||
public function build(ContainerBuilder $container)
|
||||
{
|
||||
$container->addCompilerPass(new DependencyInjection\Compiler\ResourceOwnerPass());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user