first commit

This commit is contained in:
2024-12-17 13:43:22 +01:00
commit 8e6cd8b410
21292 changed files with 3514826 additions and 0 deletions

View File

@@ -0,0 +1,159 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsAccounts\Service;
use PrestaShop\Module\PsAccounts\Adapter\Link;
use PrestaShop\Module\PsAccounts\Repository\ConfigurationRepository;
/**
* Class PsAccountsService
*/
class PsAccountsService
{
/**
* @var Link
*/
protected $link;
/**
* @var ConfigurationRepository
*/
private $configuration;
/**
* @var \Ps_accounts
*/
private $module;
/**
* @var ShopTokenService
*/
private $shopTokenService;
/**
* PsAccountsService constructor.
*
* @param \Ps_accounts $module
* @param ShopTokenService $shopTokenService
* @param ConfigurationRepository $configuration
* @param Link $link
*/
public function __construct(
\Ps_accounts $module,
ShopTokenService $shopTokenService,
ConfigurationRepository $configuration,
Link $link
) {
$this->configuration = $configuration;
$this->shopTokenService = $shopTokenService;
$this->module = $module;
$this->link = $link;
}
/**
* @return string
*/
public function getSuperAdminEmail()
{
return (new \Employee(1))->email;
}
/**
* @return string | false
*/
public function getShopUuidV4()
{
return $this->configuration->getShopUuid();
}
/**
* Get the user firebase token.
*
* @return string
*
* @throws \Exception
*/
public function getOrRefreshToken()
{
return $this->shopTokenService->getOrRefreshToken();
}
/**
* @return string|null
*/
public function getRefreshToken()
{
return $this->shopTokenService->getRefreshToken();
}
/**
* @return string|null
*/
public function getToken()
{
return $this->shopTokenService->getToken();
}
/**
* @return bool
*/
public function isEmailValidated()
{
return $this->configuration->firebaseEmailIsVerified();
}
/**
* @return string|null
*/
public function getEmail()
{
return $this->configuration->getFirebaseEmail();
}
/**
* @return bool
*
* @throws \Exception
*/
public function isAccountLinked()
{
/** @var ShopLinkAccountService $shopLinkAccountService */
$shopLinkAccountService = $this->module->getService(ShopLinkAccountService::class);
return $shopLinkAccountService->isAccountLinked();
}
/**
* Generate ajax admin link with token
* available via PsAccountsPresenter into page dom,
* ex :
* let url = window.contextPsAccounts.adminAjaxLink + '&action=unlinkShop'
*
* @return string
*
* @throws \PrestaShopException
*/
public function getAdminAjaxUrl()
{
// Tools::getAdminTokenLite('AdminAjaxPsAccounts'));
return $this->link->getAdminLink('AdminAjaxPsAccounts', true, [], ['ajax' => 1]);
}
}

View File

@@ -0,0 +1,168 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsAccounts\Service;
use Context;
use PrestaShop\Module\PsAccounts\Api\Client\ServicesBillingClient;
use PrestaShop\Module\PsAccounts\Exception\BillingException;
use PrestaShop\Module\PsAccounts\Repository\ConfigurationRepository;
/**
* Construct the psbilling service.
*/
class PsBillingService
{
// /**
// * @var \Symfony\Component\DependencyInjection\ContainerInterface
// */
// protected $container;
/**
* @var ConfigurationRepository
*/
private $configuration;
/**
* @var ShopTokenService
*/
private $shopTokenService;
/**
* @var ServicesBillingClient
*/
private $servicesBillingClient;
/**
* PsBillingService constructor.
*
* @param ServicesBillingClient $servicesBillingClient
* @param ShopTokenService $shopTokenService
* @param ConfigurationRepository $configuration
*/
public function __construct(
ServicesBillingClient $servicesBillingClient,
ShopTokenService $shopTokenService,
ConfigurationRepository $configuration
) {
$this->servicesBillingClient = $servicesBillingClient;
$this->shopTokenService = $shopTokenService;
$this->configuration = $configuration;
}
// /**
// * Override of native function to always retrieve Symfony container instead of legacy admin container on legacy context.
// *
// * @param string $serviceName
// *
// * @return mixed
// */
// public function get($serviceName)
// {
// if (null === $this->container) {
// $this->container = \PrestaShop\PrestaShop\Adapter\SymfonyContainer::getInstance();
// }
//
// return $this->container->get($serviceName);
// }
/**
* Create a Billing customer if needed, and subscribe to $planName.
* The $module and $planName must exist in PrestaShop Billing.
* The $ip parameter will help PS Billing to preselect a tax rate and a currency
* from the geolocalized IP. This IP should be the browser IP displaying the backoffice.
*
* @param string $module the name of the module
* @param string $planName The label of the existing plan for this module
* @param mixed $shopId an optional shop ID in multishop context. If left false, the current shop will be selected.
* @param mixed $customerIp an optional element to help Billing choosing the currency and tax rate (depending on the IP's country) for later paying plan
*
* @return mixed An array with subscription identifiers if succeed
*
* @throws \Exception in case of error
*/
public function subscribeToFreePlan($module, $planName, $shopId = false, $customerIp = null)
{
if ($shopId !== false) {
$this->configuration->setShopId($shopId);
}
$uuid = $this->configuration->getShopUuid();
$toReturn = ['shopAccountId' => $uuid];
if ($uuid && strlen($uuid) > 0) {
$billingClient = $this->servicesBillingClient;
$response = $billingClient->getBillingCustomer($uuid);
if (!$response || !array_key_exists('httpCode', $response)) {
throw new BillingException('Billing customer request failed.', 50);
}
if ($response['httpCode'] === 404) {
$response = $billingClient->createBillingCustomer(
$uuid,
$customerIp ? ['created_from_ip' => $customerIp] : []
);
if (!$response || !array_key_exists('httpCode', $response) || $response['httpCode'] !== 201) {
throw new BillingException('Billing customer creation failed.', 60);
}
}
$toReturn['customerId'] = $response['body']['customer']['id'];
$response = $billingClient->getBillingSubscriptions($uuid, $module);
if (!$response || !array_key_exists('httpCode', $response) || $response['httpCode'] >= 500) {
throw new BillingException('Billing subscriptions request failed.', 51);
}
if ($response['httpCode'] === 404) {
$response = $billingClient->createBillingSubscriptions($uuid, $module, ['plan_id' => $planName, 'module' => $module]);
if (!$response || !array_key_exists('httpCode', $response) || $response['httpCode'] >= 400) {
if ($response && array_key_exists('body', $response)
&& array_key_exists('message', $response['body'])
&& array_key_exists(0, $response['body']['message'])
) {
throw new BillingException($response['body']['message'][0]);
}
throw new BillingException('Billing subscription creation failed.', 65);
}
$toReturn['subscriptionId'] = $response['body']['subscription']['id'];
return $toReturn;
} else {
// There is existing subscription. Testing if planName matches the right one.
if (array_key_exists('body', $response) && $response['body']
&& array_key_exists('subscription', $response['body'])
&& array_key_exists('plan_id', $response['body']['subscription'])
&& $response['body']['subscription']['plan_id'] === $planName
) {
$toReturn['subscriptionId'] = $response['body']['subscription']['id'];
$this->shopTokenService->getOrRefreshToken();
return $toReturn;
} else {
throw new BillingException('Subscription plan name mismatch.', 20);
}
}
}
throw new \Exception('Shop account unknown.', 10);
}
}

View File

@@ -0,0 +1,155 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsAccounts\Service;
use phpseclib\Crypt\RSA;
use PrestaShop\Module\PsAccounts\Exception\SshKeysNotFoundException;
use PrestaShop\Module\PsAccounts\Repository\ConfigurationRepository;
/**
* Manage RSA
*/
class ShopKeysService
{
const SIGNATURE_DATA = 'data';
/**
* @var RSA
*/
private $rsa;
/**
* @var ConfigurationRepository
*/
private $configuration;
public function __construct(ConfigurationRepository $configuration)
{
$this->rsa = new RSA();
$this->rsa->setHash('sha256');
$this->rsa->setSignatureMode(RSA::SIGNATURE_PKCS1);
$this->configuration = $configuration;
}
/**
* @return array
*/
public function createPair()
{
$this->rsa->setPrivateKeyFormat(RSA::PRIVATE_FORMAT_PKCS1);
$this->rsa->setPublicKeyFormat(RSA::PUBLIC_FORMAT_PKCS1);
return $this->rsa->createKey();
}
/**
* @param string $privateKey
* @param string $data
*
* @return string
*/
public function signData($privateKey, $data)
{
$this->rsa->loadKey($privateKey, RSA::PRIVATE_FORMAT_PKCS1);
return base64_encode($this->rsa->sign($data));
}
/**
* @param string $publicKey
* @param string $signature
* @param string $data
*
* @return bool
*/
public function verifySignature($publicKey, $signature, $data)
{
$this->rsa->loadKey($publicKey, RSA::PUBLIC_FORMAT_PKCS1);
return $this->rsa->verify($data, base64_decode($signature));
}
/**
* @param bool $refresh
*
* @return void
*
* @throws SshKeysNotFoundException
*/
public function generateKeys($refresh = true)
{
if ($refresh || false === $this->hasKeys()) {
$key = $this->createPair();
$this->configuration->updateAccountsRsaPrivateKey($key['privatekey']);
$this->configuration->updateAccountsRsaPublicKey($key['publickey']);
$this->configuration->updateAccountsRsaSignData(
$this->signData(
$this->configuration->getAccountsRsaPrivateKey(),
self::SIGNATURE_DATA
)
);
if (false === $this->hasKeys()) {
throw new SshKeysNotFoundException('No RSA keys found for the shop');
}
}
}
/**
* @return void
*
* @throws SshKeysNotFoundException
*/
public function regenerateKeys()
{
$this->generateKeys(true);
}
/**
* @return bool
*/
public function hasKeys()
{
return false === (
empty($this->configuration->getAccountsRsaPublicKey())
|| empty($this->configuration->getAccountsRsaPrivateKey())
|| empty($this->configuration->getAccountsRsaSignData())
);
}
/**
* @return string
*/
public function getPublicKey()
{
return $this->configuration->getAccountsRsaPublicKey();
}
/**
* @return string
*/
public function getSignature()
{
return $this->configuration->getAccountsRsaSignData();
}
}

View File

@@ -0,0 +1,388 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsAccounts\Service;
use Module;
use PrestaShop\Module\PsAccounts\Adapter\Link;
use PrestaShop\Module\PsAccounts\Api\Client\ServicesAccountsClient;
use PrestaShop\Module\PsAccounts\Configuration\ConfigOptionsResolver;
use PrestaShop\Module\PsAccounts\Configuration\Configurable;
use PrestaShop\Module\PsAccounts\Exception\HmacException;
use PrestaShop\Module\PsAccounts\Exception\OptionResolutionException;
use PrestaShop\Module\PsAccounts\Exception\QueryParamsException;
use PrestaShop\Module\PsAccounts\Exception\RsaSignedDataNotFoundException;
use PrestaShop\Module\PsAccounts\Exception\SshKeysNotFoundException;
use PrestaShop\Module\PsAccounts\Provider\ShopProvider;
use PrestaShop\Module\PsAccounts\Repository\ConfigurationRepository;
use Ps_accounts;
class ShopLinkAccountService implements Configurable
{
/**
* @var ShopKeysService
*/
private $shopKeysService;
/**
* @var ShopProvider
*/
private $shopProvider;
/**
* @var ShopTokenService
*/
private $shopTokenService;
/**
* @var ConfigurationRepository
*/
private $configuration;
/**
* @var Link
*/
private $link;
/**
* @var string
*/
private $accountsUiUrl;
/**
* ShopLinkAccountService constructor.
*
* @param array $config
* @param ShopProvider $shopProvider
* @param ShopKeysService $shopKeysService
* @param ShopTokenService $shopTokenService
* @param ConfigurationRepository $configuration
* @param Link $link
*
* @throws OptionResolutionException
*/
public function __construct(
array $config,
ShopProvider $shopProvider,
ShopKeysService $shopKeysService,
ShopTokenService $shopTokenService,
ConfigurationRepository $configuration,
Link $link
) {
$this->accountsUiUrl = $this->resolveConfig($config)['accounts_ui_url'];
$this->shopProvider = $shopProvider;
$this->shopKeysService = $shopKeysService;
$this->shopTokenService = $shopTokenService;
$this->configuration = $configuration;
$this->link = $link;
}
/**
* @return ServicesAccountsClient
*/
public function getServicesAccountsClient()
{
/** @var Ps_accounts $module */
$module = Module::getInstanceByName('ps_accounts');
return $module->getService(ServicesAccountsClient::class);
}
/**
* @param array $bodyHttp
* @param string $trigger
*
* @return mixed
*
* @throws \Exception
*/
public function updateShopUrl($bodyHttp, $trigger)
{
if (array_key_exists('shop_id', $bodyHttp)) {
// id for multishop
$this->configuration->setShopId($bodyHttp['shop_id']);
}
$sslEnabled = $this->shopProvider->getShopContext()->sslEnabled();
$protocol = $this->shopProvider->getShopContext()->getProtocol();
$domain = $sslEnabled ? $bodyHttp['domain_ssl'] : $bodyHttp['domain'];
$uuid = $this->configuration->getShopUuid();
$response = false;
$boUrl = $this->replaceScheme(
$this->link->getAdminLink('AdminModules', true),
$protocol . '://' . $domain
);
if ($uuid && strlen($uuid) > 0) {
$response = $this->getServicesAccountsClient()->updateShopUrl(
$uuid,
[
'protocol' => $protocol,
'domain' => $domain,
'boUrl' => $boUrl,
'trigger' => $trigger,
]
);
}
return $response;
}
/**
* @param string $psxName
*
* @return string
*
* @throws \PrestaShopException
*/
public function getLinkAccountUrl($psxName)
{
$callback = $this->replaceScheme(
$this->link->getAdminLink('AdminModules', true) . '&configure=' . $psxName
);
$protocol = $this->shopProvider->getShopContext()->getProtocol();
$currentShop = $this->shopProvider->getCurrentShop($psxName);
$domainName = $this->shopProvider->getShopContext()->sslEnabled() ? $currentShop['domainSsl'] : $currentShop['domain'];
$queryParams = [
'bo' => $callback,
'pubKey' => $this->shopKeysService->getPublicKey(),
'next' => $this->replaceScheme(
$this->link->getAdminLink('AdminConfigureHmacPsAccounts')
),
'name' => $currentShop['name'],
'lang' => $this->shopProvider->getShopContext()->getContext()->language->iso_code,
];
$queryParamsArray = [];
foreach ($queryParams as $key => $value) {
$queryParamsArray[] = $key . '=' . urlencode($value);
}
$strQueryParams = implode('&', $queryParamsArray);
return $this->accountsUiUrl . '/shop/account/link/' . $protocol . '/' . $domainName
. '/' . $protocol . '/' . $domainName . '/' . $psxName . '?' . $strQueryParams;
}
/**
* @param array $queryParams
* @param string $rootDir
*
* @return string
*
* @throws HmacException
* @throws QueryParamsException
* @throws RsaSignedDataNotFoundException
*/
public function getVerifyAccountUrl(array $queryParams, $rootDir)
{
foreach (
[
'hmac' => '/[a-zA-Z0-9]{8,64}/',
'uid' => '/[a-zA-Z0-9]{8,64}/',
'slug' => '/[-_a-zA-Z0-9]{8,255}/',
] as $key => $value
) {
if (!array_key_exists($key, $queryParams)) {
throw new QueryParamsException('Missing query params');
}
if (!preg_match($value, $queryParams[$key])) {
throw new QueryParamsException('Invalid query params');
}
}
$this->writeHmac($queryParams['hmac'], $queryParams['uid'], $rootDir . '/upload/');
if (empty($this->shopKeysService->getSignature())) {
throw new RsaSignedDataNotFoundException('RSA signature not found');
}
$url = $this->accountsUiUrl;
if ('/' === substr($url, -1)) {
$url = substr($url, 0, -1);
}
return $url . '/shop/account/verify/' . $queryParams['uid']
. '?shopKey=' . urlencode($this->shopKeysService->getSignature());
}
/**
* @return array
*
* @throws SshKeysNotFoundException
*/
public function unlinkShop()
{
$response = $this->getServicesAccountsClient()->deleteShop((string) $this->configuration->getShopUuid());
// Réponse: 200: Shop supprimé avec payload contenant un message de confirmation
// Réponse: 404: La shop n'existe pas (not found)
// Réponse: 401: L'utilisateur n'est pas autorisé à supprimer cette shop
if ($response['status'] && 200 === $response['httpCode']
|| 404 === $response['httpCode']) {
$this->resetOnboardingData();
// FIXME regenerate rsa keys
$this->shopKeysService->regenerateKeys();
}
return $response;
}
/**
* Empty onboarding configuration values
*
* @return void
*/
public function resetOnboardingData()
{
$this->configuration->updateAccountsRsaPrivateKey('');
$this->configuration->updateAccountsRsaPublicKey('');
$this->configuration->updateAccountsRsaSignData('');
$this->configuration->updateFirebaseIdAndRefreshTokens('', '');
$this->configuration->updateFirebaseEmail('');
$this->configuration->updateFirebaseEmailIsVerified(false);
$this->configuration->updateShopUuid('');
}
/**
* @param string $psxName
*
* @return void
*
* @throws SshKeysNotFoundException
* @throws \PrestaShopException
*/
public function manageOnboarding($psxName)
{
$this->shopKeysService->generateKeys();
$this->updateOnboardingData($psxName);
}
/**
* Only callable during onboarding
*
* Prepare onboarding data
*
* @param string $psxName
*
* @return void
*
* @throws \PrestaShopException
* @throws \Exception
*/
public function updateOnboardingData($psxName)
{
$email = \Tools::getValue('email');
$emailVerified = \Tools::getValue('emailVerified');
$customToken = \Tools::getValue('adminToken');
if (is_string($customToken)) {
if (false === $this->shopKeysService->hasKeys()) {
throw new \Exception('SSH keys were not found');
}
if (!$this->shopTokenService->exchangeCustomTokenForIdAndRefreshToken($customToken)) {
throw new \Exception('Unable to get Firebase token');
}
if (!empty($email)) {
$this->configuration->updateFirebaseEmail($email);
if (!empty($emailVerified)) {
$this->configuration->updateFirebaseEmailIsVerified('true' === $emailVerified);
}
// FIXME : quick and dirty fix
\Tools::redirectAdmin(
$this->link->getAdminLink('AdminModules', true, [], [
'configure' => $psxName,
])
);
}
}
}
/**
* @return bool
*/
public function isAccountLinked()
{
return $this->shopTokenService->getToken()
&& $this->configuration->getFirebaseEmail();
}
/**
* @param array $config
* @param array $defaults
*
* @return array|mixed
*
* @throws OptionResolutionException
*/
public function resolveConfig(array $config, array $defaults = [])
{
return (new ConfigOptionsResolver([
'accounts_ui_url',
]))->resolve($config, $defaults);
}
/**
* @param string $hmac
* @param string $uid
* @param string $path
*
* @return void
*
* @throws HmacException
*/
private function writeHmac($hmac, $uid, $path)
{
if (!is_dir($path)) {
mkdir($path);
}
if (!is_writable($path)) {
throw new HmacException('Directory isn\'t writable');
}
file_put_contents($path . $uid . '.txt', $hmac);
}
/**
* @param string $url
* @param string $replacement
*
* @return string
*/
private function replaceScheme($url, $replacement = '')
{
return preg_replace('/^https?:\/\/[^\/]+/', $replacement, $url);
}
}

View File

@@ -0,0 +1,150 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsAccounts\Service;
use Lcobucci\JWT\Parser;
use PrestaShop\Module\PsAccounts\Api\Client\FirebaseClient;
use PrestaShop\Module\PsAccounts\Repository\ConfigurationRepository;
class ShopTokenService
{
/**
* @var FirebaseClient
*/
private $firebaseClient;
/**
* @var ConfigurationRepository
*/
private $configuration;
/**
* ShopTokenService constructor.
*
* @param FirebaseClient $firebaseClient
* @param ConfigurationRepository $configuration
*/
public function __construct(
FirebaseClient $firebaseClient,
ConfigurationRepository $configuration
) {
$this->firebaseClient = $firebaseClient;
$this->configuration = $configuration;
}
/**
* @see https://firebase.google.com/docs/reference/rest/auth Firebase documentation
*
* @param string $customToken
*
* @return bool
*/
public function exchangeCustomTokenForIdAndRefreshToken($customToken)
{
$response = $this->firebaseClient->signInWithCustomToken($customToken);
if ($response && true === $response['status']) {
$uid = (new Parser())->parse((string) $customToken)->getClaim('uid');
$this->configuration->updateShopUuid($uid);
$this->configuration->updateFirebaseIdAndRefreshTokens(
$response['body']['idToken'],
$response['body']['refreshToken']
);
return true;
}
return false;
}
/**
* @return bool
*
* @throws \Exception
*/
public function refreshToken()
{
$response = $this->firebaseClient->exchangeRefreshTokenForIdToken(
$this->configuration->getFirebaseRefreshToken()
);
if ($response && true === $response['status']) {
$this->configuration->updateFirebaseIdAndRefreshTokens(
$response['body']['id_token'],
$response['body']['refresh_token']
);
return true;
}
return false;
}
/**
* Get the user firebase token.
*
* @return string
*
* @throws \Exception
*/
public function getOrRefreshToken()
{
if (
$this->configuration->hasFirebaseRefreshToken()
&& $this->isTokenExpired()
) {
$this->refreshToken();
}
return $this->configuration->getFirebaseIdToken();
}
/**
* @return string|null
*/
public function getRefreshToken()
{
return $this->configuration->getFirebaseRefreshToken() ?: null;
}
/**
* @return string|null
*/
public function getToken()
{
return $this->configuration->getFirebaseIdToken() ?: null;
}
/**
* @return bool
*
* @throws \Exception
*/
public function isTokenExpired()
{
// iat, exp
$token = (new Parser())->parse($this->configuration->getFirebaseIdToken());
return $token->isExpired(new \DateTime());
}
}

View File

@@ -0,0 +1,91 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsAccounts\Service;
use Context;
use PrestaShop\Module\PsAccounts\Configuration\ConfigOptionsResolver;
use PrestaShop\Module\PsAccounts\Configuration\Configurable;
use PrestaShop\Module\PsAccounts\Exception\OptionResolutionException;
/**
* Class PsAccountsService
*/
class SsoService implements Configurable
{
/**
* @var string
*/
protected $ssoAccountUrl;
/**
* @var string
*/
protected $ssoResendVerificationEmailUrl;
/**
* PsAccountsService constructor.
*
* @param array $config
*
* @throws OptionResolutionException
*/
public function __construct(array $config)
{
$config = $this->resolveConfig($config);
$this->ssoAccountUrl = $config['sso_account_url'];
$this->ssoResendVerificationEmailUrl = $config['sso_resend_verification_email_url'];
}
/**
* @return string
*/
public function getSsoAccountUrl()
{
$url = $this->ssoAccountUrl;
$langIsoCode = Context::getContext()->language->iso_code;
return $url . '?lang=' . substr($langIsoCode, 0, 2);
}
/**
* @return string
*/
public function getSsoResendVerificationEmailUrl()
{
return $this->ssoResendVerificationEmailUrl;
}
/**
* @param array $config
* @param array $defaults
*
* @return array|mixed
*
* @throws OptionResolutionException
*/
public function resolveConfig(array $config, array $defaults = [])
{
return (new ConfigOptionsResolver([
'sso_account_url',
'sso_resend_verification_email_url',
]))->resolve($config, $defaults);
}
}

View File

@@ -0,0 +1,28 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../');
exit;