Files
b2b.redline.com.pl/modules/ps_accounts/classes/Repository/AbstractTokenRepository.php
2025-06-24 14:14:35 +02:00

244 lines
6.2 KiB
PHP

<?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\Repository;
use Exception;
use Lcobucci\JWT\Parser;
use Lcobucci\JWT\Token;
use Lcobucci\JWT\Token\InvalidTokenStructure;
use Module;
use PrestaShop\Module\PsAccounts\Exception\RefreshTokenException;
use PrestaShop\Module\PsAccounts\Log\Logger;
use PrestaShop\Module\PsAccounts\Service\ShopLinkAccountService;
use Ps_accounts;
/**
* Class AbstractTokenRepository
*/
abstract class AbstractTokenRepository
{
const MAX_TRIES_BEFORE_CLEAN_CREDENTIALS_ON_REFRESH_TOKEN_FAILURE = 3;
const TOKEN_TYPE = '';
const TOKEN_KEY = '';
/**
* @var ConfigurationRepository
*/
protected $configuration;
/**
* @var string
*/
protected $tokenType;
/**
* AbstractTokenRepository constructor.
*
* @param ConfigurationRepository $configuration
*/
public function __construct(
ConfigurationRepository $configuration
) {
$this->configuration = $configuration;
}
/**
* @return TokenClientInterface
*
* @throws Exception
*/
abstract protected function client();
/**
* @return Token|null
*/
abstract public function getToken();
/**
* @return string
*/
abstract public function getTokenUuid();
/**
* @return string
*/
abstract public function getRefreshToken();
/**
* @return void
*/
abstract public function cleanupCredentials();
/**
* @param string $idToken
* @param string $refreshToken
*
* @return void
*/
abstract public function updateCredentials($idToken, $refreshToken);
/**
* @param bool $forceRefresh
*
* @return Token|null
*
* @throws \Throwable
*/
public function getOrRefreshToken($forceRefresh = false)
{
if (true === $forceRefresh || $this->isTokenExpired()) {
$refreshToken = $this->getRefreshToken();
if (is_string($refreshToken) && '' != $refreshToken) {
try {
$token = $this->refreshToken($refreshToken);
$this->updateCredentials(
(string) $token,
$refreshToken
);
} catch (RefreshTokenException $e) {
Logger::getInstance()->debug($e);
}
}
}
return $this->getToken();
}
/**
* @return bool
*
* @throws Exception
*/
public function isTokenExpired()
{
$token = $this->getToken();
return $token ? $token->isExpired(new \DateTime()) : true;
}
/**
* @param string $token
*
* @return Token|null
*/
public function parseToken($token)
{
try {
return (new Parser())->parse((string) $token);
} catch (InvalidTokenStructure $e) {
return null;
}
}
/**
* @param string $refreshToken
*
* @return Token|null idToken
*
* @throws RefreshTokenException
* @throws Exception
*/
public function refreshToken($refreshToken)
{
$response = $this->client()->refreshToken($refreshToken);
if ($response && true === $response['status']) {
$token = $this->parseToken($response['body'][static::TOKEN_KEY]);
$this->onRefreshTokenSuccess();
return $token;
}
if ($response['httpCode'] >= 400 && $response['httpCode'] < 500) {
$this->onRefreshTokenFailure();
}
$errorMsg = isset($response['body']['message']) ? $response['body']['message'] : '';
throw new RefreshTokenException('Unable to refresh ' . static::TOKEN_TYPE . ' token : ' . $response['httpCode'] . ' ' . print_r($errorMsg, true));
}
/**
* @param string $idToken
* @param string $refreshToken
*
* @return Token|null verified or refreshed token on success
*
* @throws RefreshTokenException
* @throws Exception
*/
public function verifyToken($idToken, $refreshToken)
{
$response = $this->client()->verifyToken($idToken);
if ($response && true === $response['status']) {
return $this->parseToken($idToken);
}
return $this->refreshToken($refreshToken);
}
/**
* @return void
*/
protected function onRefreshTokenFailure()
{
$attempt = $this->configuration->getRefreshTokenFailure(static::TOKEN_TYPE);
if ($attempt >= (static::MAX_TRIES_BEFORE_CLEAN_CREDENTIALS_ON_REFRESH_TOKEN_FAILURE - 1)) {
$this->onMaxRefreshTokenAttempts();
$this->configuration->updateRefreshTokenFailure(static::TOKEN_TYPE, 0);
return;
}
$this->configuration->updateRefreshTokenFailure(
static::TOKEN_TYPE,
++$attempt
);
}
/**
* @return void
*/
protected function onRefreshTokenSuccess()
{
$this->configuration->updateRefreshTokenFailure(static::TOKEN_TYPE, 0);
}
/**
* @return void
*
* @throws Exception
*/
protected function onMaxRefreshTokenAttempts()
{
/** @var Ps_accounts $module */
$module = Module::getInstanceByName('ps_accounts');
/** @var ShopLinkAccountService $service */
$service = $module->getService(ShopLinkAccountService::class);
$service->resetLinkAccount();
}
}