Subida del módulo y tema de PrestaShop

This commit is contained in:
Kaloyan
2026-04-09 18:31:51 +02:00
parent 12c253296f
commit 16b3ff9424
39262 changed files with 7418797 additions and 0 deletions

172
modules/ps_accounts/LICENSE Normal file
View File

@@ -0,0 +1,172 @@
Open Software License ("OSL") v. 3.0
This Open Software License (the "License") applies to any original work of
authorship (the "Original Work") whose owner (the "Licensor") has placed the
following licensing notice adjacent to the copyright notice for the Original
Work:
Licensed under the Open Software License version 3.0
1. Grant of Copyright License. Licensor grants You a worldwide, royalty-free,
non-exclusive, sublicensable license, for the duration of the copyright, to do
the following:
a) to reproduce the Original Work in copies, either alone or as part of a
collective work;
b) to translate, adapt, alter, transform, modify, or arrange the Original
Work, thereby creating derivative works ("Derivative Works") based upon the
Original Work;
c) to distribute or communicate copies of the Original Work and Derivative
Works to the public, with the proviso that copies of Original Work or
Derivative Works that You distribute or communicate shall be licensed under
this Open Software License;
d) to perform the Original Work publicly; and
e) to display the Original Work publicly.
2. Grant of Patent License. Licensor grants You a worldwide, royalty-free,
non-exclusive, sublicensable license, under patent claims owned or controlled
by the Licensor that are embodied in the Original Work as furnished by the
Licensor, for the duration of the patents, to make, use, sell, offer for sale,
have made, and import the Original Work and Derivative Works.
3. Grant of Source Code License. The term "Source Code" means the preferred
form of the Original Work for making modifications to it and all available
documentation describing how to modify the Original Work. Licensor agrees to
provide a machine-readable copy of the Source Code of the Original Work along
with each copy of the Original Work that Licensor distributes. Licensor
reserves the right to satisfy this obligation by placing a machine-readable
copy of the Source Code in an information repository reasonably calculated to
permit inexpensive and convenient access by You for as long as Licensor
continues to distribute the Original Work.
4. Exclusions From License Grant. Neither the names of Licensor, nor the names
of any contributors to the Original Work, nor any of their trademarks or
service marks, may be used to endorse or promote products derived from this
Original Work without express prior permission of the Licensor. Except as
expressly stated herein, nothing in this License grants any license to
Licensor's trademarks, copyrights, patents, trade secrets or any other
intellectual property. No patent license is granted to make, use, sell, offer
for sale, have made, or import embodiments of any patent claims other than the
licensed claims defined in Section 2. No license is granted to the trademarks
of Licensor even if such marks are included in the Original Work. Nothing in
this License shall be interpreted to prohibit Licensor from licensing under
terms different from this License any Original Work that Licensor otherwise
would have a right to license.
5. External Deployment. The term "External Deployment" means the use,
distribution, or communication of the Original Work or Derivative Works in any
way such that the Original Work or Derivative Works may be used by anyone
other than You, whether those works are distributed or communicated to those
persons or made available as an application intended for use over a network.
As an express condition for the grants of license hereunder, You must treat
any External Deployment by You of the Original Work or a Derivative Work as a
distribution under section 1(c).
6. Attribution Rights. You must retain, in the Source Code of any Derivative
Works that You create, all copyright, patent, or trademark notices from the
Source Code of the Original Work, as well as any notices of licensing and any
descriptive text identified therein as an "Attribution Notice." You must cause
the Source Code for any Derivative Works that You create to carry a prominent
Attribution Notice reasonably calculated to inform recipients that You have
modified the Original Work.
7. Warranty of Provenance and Disclaimer of Warranty. Licensor warrants that
the copyright in and to the Original Work and the patent rights granted herein
by Licensor are owned by the Licensor or are sublicensed to You under the
terms of this License with the permission of the contributor(s) of those
copyrights and patent rights. Except as expressly stated in the immediately
preceding sentence, the Original Work is provided under this License on an "AS
IS" BASIS and WITHOUT WARRANTY, either express or implied, including, without
limitation, the warranties of non-infringement, merchantability or fitness for
a particular purpose. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL WORK
IS WITH YOU. This DISCLAIMER OF WARRANTY constitutes an essential part of this
License. No license to the Original Work is granted by this License except
under this disclaimer.
8. Limitation of Liability. Under no circumstances and under no legal theory,
whether in tort (including negligence), contract, or otherwise, shall the
Licensor be liable to anyone for any indirect, special, incidental, or
consequential damages of any character arising as a result of this License or
the use of the Original Work including, without limitation, damages for loss
of goodwill, work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses. This limitation of liability shall not
apply to the extent applicable law prohibits such limitation.
9. Acceptance and Termination. If, at any time, You expressly assented to this
License, that assent indicates your clear and irrevocable acceptance of this
License and all of its terms and conditions. If You distribute or communicate
copies of the Original Work or a Derivative Work, You must make a reasonable
effort under the circumstances to obtain the express assent of recipients to
the terms of this License. This License conditions your rights to undertake
the activities listed in Section 1, including your right to create Derivative
Works based upon the Original Work, and doing so without honoring these terms
and conditions is prohibited by copyright law and international treaty.
Nothing in this License is intended to affect copyright exceptions and
limitations (including "fair use" or "fair dealing"). This License shall
terminate immediately and You may no longer exercise any of the rights granted
to You by this License upon your failure to honor the conditions in Section
1(c).
10. Termination for Patent Action. This License shall terminate automatically
and You may no longer exercise any of the rights granted to You by this
License as of the date You commence an action, including a cross-claim or
counterclaim, against Licensor or any licensee alleging that the Original Work
infringes a patent. This termination provision shall not apply for an action
alleging patent infringement by combinations of the Original Work with other
software or hardware.
11. Jurisdiction, Venue and Governing Law. Any action or suit relating to this
License may be brought only in the courts of a jurisdiction wherein the
Licensor resides or in which Licensor conducts its primary business, and under
the laws of that jurisdiction excluding its conflict-of-law provisions. The
application of the United Nations Convention on Contracts for the
International Sale of Goods is expressly excluded. Any use of the Original
Work outside the scope of this License or after its termination shall be
subject to the requirements and penalties of copyright or patent law in the
appropriate jurisdiction. This section shall survive the termination of this
License.
12. Attorneys' Fees. In any action to enforce the terms of this License or
seeking damages relating thereto, the prevailing party shall be entitled to
recover its costs and expenses, including, without limitation, reasonable
attorneys' fees and costs incurred in connection with such action, including
any appeal of such action. This section shall survive the termination of this
License.
13. Miscellaneous. If any provision of this License is held to be
unenforceable, such provision shall be reformed only to the extent necessary
to make it enforceable.
14. Definition of "You" in This License. "You" throughout this License,
whether in upper or lower case, means an individual or a legal entity
exercising rights under, and complying with all of the terms of, this License.
For legal entities, "You" includes any entity that controls, is controlled by,
or is under common control with you. For purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the direction or
management of such entity, whether by contract or otherwise, or (ii) ownership
of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial
ownership of such entity.
15. Right to Use. You may use the Original Work in all ways not otherwise
restricted or conditioned by this License or by law, and Licensor promises not
to interfere with or be responsible for such uses by You.
16. Modification of This License. This License is Copyright © 2005 Lawrence
Rosen. Permission is granted to copy, distribute, or communicate this License
without modification. Nothing in this License permits You to modify this
License as applied to the Original Work or to Derivative Works. However, You
may modify the text of this License and copy, distribute or communicate your
modified version (the "Modified License") and apply it to other original works
of authorship subject to the following conditions: (i) You may not indicate in
any way that your Modified License is the "Open Software License" or "OSL" and
you may not use those names in the name of your Modified License; (ii) You
must replace the notice specified in the first paragraph above with the notice
"Licensed under <insert your license name here>" or with a notice of your own
that is not confusingly similar to the notice in this License; and (iii) You
may not claim that your original works are open source software unless your
Modified License has been approved by Open Source Initiative (OSI) and You
comply with its license review and certification process.

View File

@@ -0,0 +1,47 @@
<?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
*/
return [
'ps_accounts.environment' => 'production',
'ps_accounts.accounts_api_url' => 'https://accounts-api.distribution.prestashop.net/',
'ps_accounts.accounts_ui_url' => 'https://accounts.distribution.prestashop.net',
'ps_accounts.sso_api_url' => 'https://auth.prestashop.com/api/v1/',
'ps_accounts.sso_account_url' => 'https://auth.prestashop.com/login',
'ps_accounts.sso_resend_verification_email_url' => 'https://auth.prestashop.com/account/send-verification-email',
'ps_accounts.billing_api_url' => 'https://billing-api.distribution.prestashop.net/',
'ps_accounts.indirect_channel_api_url' => 'https://indirect-channel-api.prestashop.net',
'ps_accounts.sentry_credentials' => 'https://cd2a5f089edb6d6efe742c0cbe004106@o298402.ingest.us.sentry.io/5354585',
'ps_accounts.segment_write_key' => 'pEJGnRxw47CU01efFjMyl1S7YcxshLxl',
'ps_accounts.check_api_ssl_cert' => true,
'ps_accounts.verify_account_tokens' => true,
'ps_accounts.accounts_vue_cdn_url' => 'https://unpkg.com/prestashop_accounts_vue_components@3/dist/psaccountsVue.umd.min.js',
'ps_accounts.accounts_cdn_url' => 'https://assets.prestashop3.com/accounts-components/1/psaccountsVue.js',
'ps_accounts.cors_allowed_origins' => [
'https://integration-assets.prestashop3.com',
'https://preproduction-assets.prestashop3.com',
'https://assets.prestashop3.com',
],
'ps_accounts.svc_accounts_ui_url' => 'https://accounts.psessentials.net',
'ps_accounts.oauth2_url' => 'https://oauth.prestashop.com',
'ps_accounts.token_audience' => 'https://accounts-api.distribution.prestashop.net',
'ps_accounts.token_validator_leeway' => 900,
'ps_accounts.testimonials_url' => 'https://assets.prestashop3.com/dst/accounts/assets/testimonials.json',
];

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8" ?>
<module>
<name>ps_accounts</name>
<displayName><![CDATA[PrestaShop Account]]></displayName>
<version><![CDATA[8.0.13]]></version>
<description><![CDATA[Link your store to your PrestaShop account to activate and manage your subscriptions in your back office. Do not uninstall this module if you have a current subscription.]]></description>
<author><![CDATA[PrestaShop]]></author>
<tab><![CDATA[administration]]></tab>
<confirmUninstall><![CDATA[This action will prevent immediately your PrestaShop services and Community services from working as they are using PrestaShop Accounts module for authentication.]]></confirmUninstall>
<is_configurable>1</is_configurable>
<need_instance>0</need_instance>
</module>

View File

@@ -0,0 +1,11 @@
<?php
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;

View File

@@ -0,0 +1,3 @@
imports:
- { resource: ../common.yml }

View File

@@ -0,0 +1,35 @@
services:
##########################
# Shared Services :
# Those services might be accessed directly from the core container
# by some modules.
# Doing so we maintain compatibility & ensure the same instance is provided.
PrestaShop\Module\PsAccounts\Service\PsAccountsService:
class: PrestaShop\Module\PsAccounts\Service\PsAccountsService
public: true
factory: ['PrestaShop\Module\PsAccounts\ServiceProvider\StaticProvider', 'provide']
arguments:
- 'PrestaShop\Module\PsAccounts\Service\PsAccountsService'
PrestaShop\Module\PsAccounts\Service\PsBillingService:
class: PrestaShop\Module\PsAccounts\Service\PsBillingService
public: true
factory: [ 'PrestaShop\Module\PsAccounts\ServiceProvider\StaticProvider', 'provide' ]
arguments:
- 'PrestaShop\Module\PsAccounts\Service\PsBillingService'
PrestaShop\Module\PsAccounts\Repository\UserTokenRepository:
class: PrestaShop\Module\PsAccounts\Repository\UserTokenRepository
public: true
factory: ['PrestaShop\Module\PsAccounts\ServiceProvider\StaticProvider', 'provide']
arguments:
- 'PrestaShop\Module\PsAccounts\Repository\UserTokenRepository'
PrestaShop\Module\PsAccounts\Presenter\PsAccountsPresenter:
class: PrestaShop\Module\PsAccounts\Presenter\PsAccountsPresenter
public: true
factory: ['PrestaShop\Module\PsAccounts\ServiceProvider\StaticProvider', 'provide']
arguments:
- 'PrestaShop\Module\PsAccounts\Presenter\PsAccountsPresenter'

View File

@@ -0,0 +1,11 @@
<?php
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;

View File

@@ -0,0 +1,2 @@
imports:
- { resource: ../common.yml }

View File

@@ -0,0 +1,11 @@
<?php
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;

View File

@@ -0,0 +1,18 @@
ps_accounts_oauth2:
path: ps_accounts/oauth2
methods: [GET]
defaults:
_controller: 'PrestaShop\Module\PsAccounts\Controller\Admin\OAuth2Controller::initOAuth2FlowAction'
_anonymous_controller: true
_legacy_controller: SfAdminOAuth2PsAccounts
_legacy_link: SfAdminOAuth2PsAccounts
ps_accounts_login:
path: ps_accounts/login
methods: [GET]
defaults:
_controller: 'PrestaShop\Module\PsAccounts\Controller\Admin\OAuth2Controller::displayLoginAction'
_anonymous_controller: true
_legacy_controller: SfAdminLoginPsAccounts
_legacy_link: SfAdminLoginPsAccounts
# _disable_module_prefix: true

View File

@@ -0,0 +1,5 @@
services:
PrestaShop\Module\PsAccounts\Controller\Admin\OAuth2Controller:
class: PrestaShop\Module\PsAccounts\Controller\Admin\OAuth2Controller
# autowire: true
# autoconfigure: true

View File

@@ -0,0 +1,368 @@
<?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
*/
require_once __DIR__ . '/../../src/Polyfill/Traits/Controller/AjaxRender.php';
use PrestaShop\Module\PsAccounts\Account\Exception\UnknownStatusException;
use PrestaShop\Module\PsAccounts\Account\Session\Firebase\ShopSession;
use PrestaShop\Module\PsAccounts\Account\ShopUrl;
use PrestaShop\Module\PsAccounts\Account\StatusManager;
use PrestaShop\Module\PsAccounts\AccountLogin\OAuth2Session;
use PrestaShop\Module\PsAccounts\Adapter\Link as AccountsLink;
use PrestaShop\Module\PsAccounts\Installer\Installer;
use PrestaShop\Module\PsAccounts\Log\Logger;
use PrestaShop\Module\PsAccounts\Polyfill\Traits\Controller\AjaxRender;
use PrestaShop\Module\PsAccounts\Provider\ShopProvider;
use PrestaShop\Module\PsAccounts\Service\SentryService;
use PrestaShop\Module\PsAccounts\Service\UpgradeService;
/**
* Controller for all ajax calls.
*/
class AdminAjaxPsAccountsController extends \ModuleAdminController
{
use AjaxRender;
/**
* @var Ps_accounts
*/
public $module;
/**
* @var string
*/
private $alertCss = '
<style>
.acc-flex
{
display: flex !important;
}
.acc-btn
{
display: inline-block !important;
text-align: center !important;
vertical-align: middle !important;
user-select: none !important;
border: 1px solid transparent !important;
padding: .5rem 1rem !important;
font-size: .875rem !important;
line-height: 1.5 !important;
font-weight: 600 !important;
border-width: 1px !important;
transition: color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out !important;
cursor: pointer !important;
}
.acc-btn-warning
{
width: max-content !important;
color: #1d1d1b !important;
background-color: #FFF5E5 !important;
border-color: #ffb000 !important;
}
.acc-btn-warning:hover
{
background-color: #ffeccc !important;
}
.acc-btn-warning:focus, .acc-btn-warning.focus
{
background-color: #ffeccc !important;
}
.acc-btn-danger
{
width: max-content !important;
color: #1d1d1b !important;
background-color: #ffe4e6 !important;
border-color: #ba151a !important;
}
.acc-btn-danger:hover
{
background-color: #fdbfbf !important;
}
.acc-btn-danger:focus, .acc-btn-danger.focus
{
background-color: #fdbfbf !important;
}
@media(max-width: 768px)
{
.acc-flex {
flex-direction: column !important;
}
.acc-btn-warning,
.acc-btn-danger
{
margin-top: 1em !important;
}
}
.acc-flex-grow-1
{
-webkit-box-flex: 1 !important;
-ms-flex-positive: 1 !important;
flex-grow: 1 !important;
}
.acc-alert-title
{
font-weight: bold !important;
margin-bottom: .9375rem !important;
}
.acc-list
{
list-style-type: none;
padding-left: 0 !important;
}
.acc-alert
{
}
.acc-alert-warning
{
background-color: #FFF5E5 !important;
position: relative !important;
padding: 16px 15px 16px 56px !important;
font-size: 14px !important;
border: solid 1px #ffb000 !important;
color: #1d1d1b !important;
}
.acc-alert-danger
{
background-color: #ffe4e6 !important;
position: relative !important;
padding: 16px 15px 16px 56px !important;
font-size: 14px !important;
border: solid 1px #ba151a !important;
color: #1d1d1b !important;
}
</style>
';
/**
* @var string
*/
private $translationClass;
/**
* AdminAjaxPsAccountsController constructor.
*
* @throws Exception
*/
public function __construct()
{
parent::__construct();
$this->ajax = true;
$this->content_only = true;
$this->translationClass = self::class;
}
/**
* @return void
*
* @throws Exception
*/
public function ajaxProcessGetOrRefreshToken()
{
try {
/** @var ShopSession $shopSession */
$shopSession = $this->module->getService(ShopSession::class);
header('Content-Type: text/json');
$token = $shopSession->getValidToken();
$this->ajaxRender(
(string) json_encode([
'token' => (string) $token->getJwt(),
'refreshToken' => $token->getRefreshToken(),
])
);
} catch (Exception $e) {
SentryService::captureAndRethrow($e);
}
}
/**
* @return void
*
* @throws Exception
*/
public function ajaxProcessGetOrRefreshAccessToken()
{
try {
/** @var OAuth2Session $oauth2Session */
$oauth2Session = $this->module->getService(OAuth2Session::class);
header('Content-Type: text/json');
$this->ajaxRender(
(string) json_encode([
'token' => (string) $oauth2Session->getOrRefreshAccessToken(),
])
);
} catch (Exception $e) {
SentryService::captureAndRethrow($e);
}
}
/**
* @return void
*/
public function ajaxProcessGetNotifications()
{
$notifications = [];
try {
$notifications = array_merge(
$this->getNotificationsUpgradeFailed(),
$this->getNotificationsUrlMismatch()
);
} catch (\Exception $e) {
Logger::getInstance()->error($e->getMessage());
} catch (\Throwable $e) {
Logger::getInstance()->error($e->getMessage());
}
$this->ajaxRender(
(string) json_encode($notifications ?: [])
);
}
/**
* @return array|array[]
*
* @throws UnknownStatusException
*/
protected function getNotificationsUrlMismatch()
{
/** @var StatusManager $statusManager */
$statusManager = $this->module->getService(StatusManager::class);
if (!$statusManager->identityCreated()) {
return [];
}
$status = $statusManager->getStatus();
$shopId = $this->context->shop->id;
$cloudShopUrl = ShopUrl::createFromStatus($status, $shopId)->trimmed();
/** @var ShopProvider $shopProvider */
$shopProvider = $this->module->getService(ShopProvider::class);
$localShopUrl = $shopProvider->getUrl($shopId)->trimmed();
try {
if ($cloudShopUrl->frontendUrlEquals($localShopUrl)) {
return [];
}
} catch (\InvalidArgumentException $e) {
Logger::getInstance()->error($e->getMessage());
return [];
}
/** @var AccountsLink $link */
$link = $this->module->getService(AccountsLink::class);
$moduleLink = $link->getAdminLink('AdminModules', true, [], [
'configure' => 'ps_accounts',
]);
return [[
'html' => $this->alertCss . '
<div class="alert alert-warning acc-alert acc-alert-warning acc-flex">
<div class="acc-flex-grow-1">
<div class="acc-alert-title">
' . $this->module->l('Action required: confirm your store URL', $this->translationClass) . '
</div>
<p>
' . $this->module->l('We\'ve noticed that your store\'s URL no longer matches the one registered in your PrestaShop Account.', $this->translationClass) . '
<br>
' . $this->module->l('For your services to function properly, you must either confirm this change or create a new identity for your store.', $this->translationClass) . '
</p>
<ul class="acc-list">
<li>- ' . $this->module->l('Current store URL', $this->translationClass) . ': <em>' . $localShopUrl->getFrontendUrl() . '</em></li>
<li>- ' . $this->module->l('URL registered in PrestaShop Account', $this->translationClass) . ': <em>' . $cloudShopUrl->getFrontendUrl() . '</em></li>
</ul>
</div>
<div>
<button class="btn warning btn-outline-warning acc-btn btn-warning acc-btn-warning" onclick="document.location=\'' . $moduleLink . '\'">
' . $this->module->l('Review settings', $this->translationClass) . '
</button>
</div>
</div>
',
]];
}
/**
* @return array|array[]
*/
protected function getNotificationsUpgradeFailed()
{
/** @var StatusManager $statusManager */
$statusManager = $this->module->getService(StatusManager::class);
/** @var UpgradeService $upgradeService */
$upgradeService = $this->module->getService(UpgradeService::class);
if ($upgradeService->getCoreRegisteredVersion() === \Ps_accounts::VERSION &&
(!$statusManager->identityCreated() || $upgradeService->getRegisteredVersion() === \Ps_accounts::VERSION)) {
return [];
}
/** @var AccountsLink $link */
$link = $this->module->getService(AccountsLink::class);
$resetLink = $link->getAdminLink('AdminAjaxPsAccounts', true, [], ['ajax' => 1, 'action' => 'resetModule']);
return [[
'html' => $this->alertCss . '
<div class="alert alert-danger acc-alert acc-alert-danger acc-flex">
<div class="acc-flex-grow-1">
<div class="acc-alert-title">
' . $this->module->l('Action required: reset your PS Account module', $this->translationClass) . '
</div>
<p>' . $this->module->l('A simple reset is needed to finish the update and ensure all your modules are working correctly.', $this->translationClass) . '</p>
</div>
<div>
<button class="btn danger btn-outline-danger acc-btn btn-danger acc-btn-danger"
onclick="this.disabled = true; this.innerHTML = \'' . $this->module->l('Resetting module...', $this->translationClass) . '\'; fetch(\'' . $resetLink . '\').then(response => {document.location.reload();})">
' . $this->module->l('Reset module', $this->translationClass) . '
</button>
</div>
</div>
',
]];
}
/**
* @return void
*/
public function ajaxProcessResetModule()
{
$status = false;
try {
/** @var Installer $installer */
$installer = $this->module->getService(Installer::class);
$status = $installer->resetModule('ps_accounts');
} catch (\Exception $e) {
Logger::getInstance()->error($e->getMessage());
} catch (\Throwable $e) {
Logger::getInstance()->error($e->getMessage());
}
$this->ajaxRender(
(string) json_encode([
'status' => $status,
])
);
}
}

View File

@@ -0,0 +1,241 @@
<?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
*/
require_once __DIR__ . '/../../src/Http/Controller/AbstractAdminAjaxCorsController.php';
use PrestaShop\Module\PsAccounts\Account\Command\CreateIdentityCommand;
use PrestaShop\Module\PsAccounts\Account\Command\MigrateOrCreateIdentityV8Command;
use PrestaShop\Module\PsAccounts\Account\Command\VerifyIdentityCommand;
use PrestaShop\Module\PsAccounts\Account\Exception\RefreshTokenException;
use PrestaShop\Module\PsAccounts\Account\Query\GetContextQuery;
use PrestaShop\Module\PsAccounts\Account\StatusManager;
use PrestaShop\Module\PsAccounts\Context\ShopContext;
use PrestaShop\Module\PsAccounts\Cqrs\CommandBus;
use PrestaShop\Module\PsAccounts\Cqrs\QueryBus;
use PrestaShop\Module\PsAccounts\Http\Controller\AbstractAdminAjaxCorsController;
use PrestaShop\Module\PsAccounts\Log\Logger;
use PrestaShop\Module\PsAccounts\Service\Accounts;
use PrestaShop\Module\PsAccounts\Service\Accounts\AccountsException;
use PrestaShop\Module\PsAccounts\Service\Accounts\AccountsService;
use PrestaShop\Module\PsAccounts\Service\OAuth2;
/**
* Controller for all ajax calls.
*/
class AdminAjaxV2PsAccountsController extends AbstractAdminAjaxCorsController
{
/**
* @var CommandBus
*/
private $commandBus;
/**
* @var QueryBus
*/
private $queryBus;
/**
* @var ShopContext
*/
private $shopContext;
/**
* AdminAjaxV2PsAccountsController constructor.
*
* @throws Exception
*/
public function __construct()
{
parent::__construct();
$this->commandBus = $this->module->getService(CommandBus::class);
$this->queryBus = $this->module->getService(QueryBus::class);
$this->shopContext = $this->module->getService(ShopContext::class);
}
/**
* @return void
*
* @throws Exception
*/
public function ajaxProcessGetContext()
{
$command = new GetContextQuery(
Tools::getValue('source', 'ps_accounts'),
Tools::getValue('context_type', null),
Tools::getValue('context_id', null),
filter_var(Tools::getValue('refresh', false), FILTER_VALIDATE_BOOLEAN)
);
$this->ajaxRender(
(string) json_encode($this->queryBus->handle($command))
);
}
/**
* @return void
*
* @throws Exception
*/
public function ajaxProcessFallbackCreateIdentity()
{
$shopId = Tools::getValue('shop_id', null);
$source = Tools::getValue('source', 'ps_accounts');
if (!$shopId) {
throw new Exception('Shop ID is required for migration or creation.');
}
$this->shopContext->execInShopContext($shopId, function () use ($shopId, $source) {
/** @var StatusManager $statusManager */
$statusManager = $this->module->getService(StatusManager::class);
$statusManager->withThrowException(true);
$command = (new MigrateOrCreateIdentityV8Command($shopId))
->withOrigin(AccountsService::ORIGIN_FALLBACK)
->withSource($source);
$this->commandBus->handle($command);
$statusManager->resetThrowException();
});
$this->ajaxRender(
(string) json_encode([
'success' => true,
])
);
}
/**
* @return void
*
* @throws Exception
*/
public function ajaxProcessRenewIdentity()
{
$shopId = Tools::getValue('shop_id', null);
$source = Tools::getValue('source', 'ps_accounts');
if (!$shopId) {
throw new Exception('Shop ID is required for renew.');
}
$this->shopContext->execInShopContext($shopId, function () use ($shopId, $source) {
$command = (new CreateIdentityCommand($shopId, true))
->withOrigin(AccountsService::ORIGIN_MISMATCH_CREATE)
->withSource($source);
$this->commandBus->handle($command);
});
$this->ajaxRender(
(string) json_encode([
'success' => true,
])
);
}
/**
* @return void
*
* @throws Exception
*/
public function ajaxProcessUpdateIdentity()
{
$shopId = Tools::getValue('shop_id', null);
$source = Tools::getValue('source', 'ps_accounts');
if (!$shopId) {
throw new Exception('Shop ID is required for update.');
}
$this->shopContext->execInShopContext($shopId, function () use ($shopId, $source) {
$command = (new VerifyIdentityCommand($shopId, true))
->withOrigin(AccountsService::ORIGIN_MISMATCH_UPDATE)
->withSource($source);
$this->commandBus->handle($command);
});
$this->ajaxRender(
(string) json_encode([
'success' => true,
])
);
}
/**
* @param \Throwable|\Exception $e
*
* @return void
*/
protected function handleError($e)
{
Logger::getInstance()->error($e);
if ($e instanceof RefreshTokenException) {
$e = $e->getPrevious();
}
if ($e instanceof OAuth2\Exception\ConnectException) {
http_response_code(400);
$this->ajaxRender(
(string) json_encode([
'message' => $e->getMessage(),
'code' => 'oauth-server/connect-error',
//'details' => $e->getDetails(),
])
);
return;
}
if ($e instanceof Accounts\Exception\ConnectException) {
http_response_code(400);
$this->ajaxRender(
(string) json_encode([
'message' => $e->getMessage(),
'code' => 'accounts-api/connect-error',
//'details' => $e->getDetails(),
])
);
return;
}
if ($e instanceof AccountsException) {
http_response_code(400);
$this->ajaxRender(
(string) json_encode([
'message' => $e->getMessage(),
'code' => $e->getErrorCode(),
'details' => $e->getDetails(),
])
);
return;
}
parent::handleError($e);
}
}

View File

@@ -0,0 +1,26 @@
<?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
*/
/**
* @deprecated removed starting ps_accounts 8.0.0
*/
class AdminDebugPsAccountsController extends \ModuleAdminController
{
}

View File

@@ -0,0 +1,26 @@
<?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
*/
/**
* @deprecated removed starting ps_accounts 7.0.0
*/
class AdminLoginController extends \AdminLoginControllerCore
{
}

View File

@@ -0,0 +1,181 @@
<?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
*/
use PrestaShop\Module\PsAccounts\Api\Client\ExternalAssetsClient;
use PrestaShop\Module\PsAccounts\Polyfill\Traits\AdminController\IsAnonymousAllowed;
use PrestaShop\Module\PsAccounts\Service\OAuth2\OAuth2Client;
class AdminLoginPsAccountsController extends \AdminController
{
use IsAnonymousAllowed;
const PARAM_MODE_LOCAL = 'local';
/**
* @var string
*/
public $template = 'login.tpl';
/**
* @var Ps_accounts
*/
public $module;
/**
* @var ExternalAssetsClient
*/
private $externalAssetsClient;
/**
* @throws Exception
*/
public function __construct()
{
$this->bootstrap = true;
parent::__construct();
$this->errors = [];
$this->display_header = false;
/* @phpstan-ignore-next-line */
$this->display_footer = false;
/** @var Ps_accounts $module */
$module = Module::getInstanceByName('ps_accounts');
$this->module = $module;
$this->externalAssetsClient = $this->module->getService(ExternalAssetsClient::class);
if (!headers_sent()) {
header('Login: true');
}
}
/**
* @return void
*/
public function initContent()
{
if ($nb_errors = count($this->errors)) {
$this->context->smarty->assign([
'errors' => $this->errors,
'nbErrors' => $nb_errors,
'shop_name' => Tools::safeOutput((string) Configuration::get('PS_SHOP_NAME')),
'disableDefaultErrorOutPut' => true,
]);
}
$this->setMedia($isNewTheme = false);
$this->initHeader();
parent::initContent();
$this->initFooter();
//force to disable modals
$this->context->smarty->assign('modals', null);
}
/**
* @return bool
*/
public function checkToken()
{
return true;
}
/**
* All BO users can access the login page
*
* @param bool $disable
*
* @return bool
*/
public function viewAccess($disable = false)
{
return true;
}
/**
* @param bool $isNewTheme
*
* @return void
*/
public function setMedia($isNewTheme = false)
{
$this->addCss($this->module->getLocalPath() . '/views/css/login.css' .
'?v=' . urlencode($this->module->version)
);
$this->addJS($this->module->getLocalPath() . '/views/js/login.js' .
'?v=' . urlencode($this->module->version)
);
}
/**
* @param string $tpl_name
*
* @phpstan-ignore-next-line
*
* @return Smarty_Internal_Template
*/
public function createTemplate($tpl_name)
{
/** @var Oauth2Client $oAuth2Client */
$oAuth2Client = $this->module->getService(Oauth2Client::class);
$session = $this->module->getSession();
/* @phpstan-ignore-next-line */
$isoCode = $this->context->currentLocale->getCode();
$this->context->smarty->assign([
/* @phpstan-ignore-next-line */
'shopUrl' => $this->context->shop->getBaseUrl(true),
'oauthRedirectUri' => $oAuth2Client->getRedirectUri(),
'legacyLoginUri' => $this->context->link->getAdminLink(
'AdminLogin', true, [], [
'mode' => self::PARAM_MODE_LOCAL,
]),
'isoCode' => substr($isoCode, 0, 2),
'defaultIsoCode' => 'en',
'testimonials' => $this->getTestimonials(),
'loginError' => $session->remove('loginError'),
'meta_title' => '',
'ssoResendVerificationEmail' => $this->module->getParameter(
'ps_accounts.sso_resend_verification_email_url'
),
]);
/* @phpstan-ignore-next-line */
return $this->context->smarty->createTemplate(
$this->module->getLocalPath() . '/views/templates/admin/' . $this->template,
$this->context->smarty
);
}
/**
* @return array
*/
private function getTestimonials()
{
$res = $this->externalAssetsClient->getTestimonials();
return $res->isSuccessful ? $res->body : [];
}
}

View File

@@ -0,0 +1,310 @@
<?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
*/
require_once __DIR__ . '/../../src/AccountLogin/OAuth2LoginTrait.php';
require_once __DIR__ . '/../../src/Polyfill/Traits/AdminController/IsAnonymousAllowed.php';
use PrestaShop\Module\PsAccounts\Account\Command\IdentifyContactCommand;
use PrestaShop\Module\PsAccounts\AccountLogin\Exception\AccountLoginException;
use PrestaShop\Module\PsAccounts\AccountLogin\Exception\EmailNotVerifiedException;
use PrestaShop\Module\PsAccounts\AccountLogin\Exception\EmployeeNotFoundException;
use PrestaShop\Module\PsAccounts\AccountLogin\OAuth2LoginTrait;
use PrestaShop\Module\PsAccounts\AccountLogin\OAuth2Session;
use PrestaShop\Module\PsAccounts\Cqrs\CommandBus;
use PrestaShop\Module\PsAccounts\Log\Logger;
use PrestaShop\Module\PsAccounts\Polyfill\ConfigurationStorageSession;
use PrestaShop\Module\PsAccounts\Polyfill\Traits\AdminController\IsAnonymousAllowed;
use PrestaShop\Module\PsAccounts\Service\AnalyticsService;
use PrestaShop\Module\PsAccounts\Service\OAuth2\OAuth2Service;
use PrestaShop\Module\PsAccounts\Service\OAuth2\Resource\AccessToken;
use PrestaShop\Module\PsAccounts\Service\PsAccountsService;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
class AdminOAuth2PsAccountsController extends \ModuleAdminController
{
use OAuth2LoginTrait;
use IsAnonymousAllowed;
/**
* @var Ps_accounts
*/
public $module;
/**
* @var AnalyticsService
*/
private $analyticsService;
/**
* @var PsAccountsService
*/
private $psAccountsService;
/**
* @var CommandBus
*/
private $commandBus;
/**
* @throws PrestaShopException
* @throws Exception
*/
public function __construct()
{
parent::__construct();
$this->analyticsService = $this->module->getService(AnalyticsService::class);
$this->psAccountsService = $this->module->getService(PsAccountsService::class);
$this->commandBus = $this->module->getService(CommandBus::class);
$this->ajax = true;
$this->content_only = true;
}
/**
* @return bool
*/
public function checkToken()
{
return true;
}
/**
* All BO users can access the login page
*
* @param bool $disable
*
* @return bool
*/
public function viewAccess($disable = false)
{
return true;
}
/**
* @return void
*
* @throws PrestaShopException
*/
//public function display()
public function init()
{
try {
$this->oauth2Login();
} catch (AccountLoginException $e) {
$this->onLoginFailed($e);
} catch (Exception $e) {
$this->onLoginFailed(new AccountLoginException($e->getMessage(), null, $e));
}
// why do this at the end of the method ?
parent::init();
}
/**
* @param AccessToken $accessToken
*
* @return bool
*
* @throws EmailNotVerifiedException
* @throws EmployeeNotFoundException
*/
protected function initUserSession(AccessToken $accessToken)
{
$user = $this->getOAuth2Service()->getUserInfo($accessToken->access_token);
Logger::getInstance()->info(
'[OAuth2] ' . (string) print_r($user, true)
);
if ($this->getOAuthAction() === 'identifyPointOfContact') {
$this->commandBus->handle(
(new IdentifyContactCommand($accessToken, $user))
->withSource($this->getSource())
);
return true;
}
$this->getOauth2Session()->setTokenProvider($accessToken);
//$user = $oauth2Session->getUserInfo();
Logger::getInstance()->info(
'[OAuth2] ' . (string) print_r($user, true)
);
$context = $this->context;
$emailVerified = $user->email_verified;
$context->employee = $this->getEmployeeByUidOrEmail($user->sub, $user->email);
if (!$context->employee->id || empty($emailVerified)) {
$context->employee->logout();
if (empty($emailVerified)) {
throw new EmailNotVerifiedException('Your account email is not verified', $user);
}
throw new EmployeeNotFoundException('The email address is not associated to a PrestaShop backoffice account.', $user);
}
$context->employee->remote_addr = (int) ip2long(Tools::getRemoteAddr());
$cookie = $context->cookie;
/* @phpstan-ignore-next-line */
$cookie->id_employee = $context->employee->id;
/* @phpstan-ignore-next-line */
$cookie->email = $context->employee->email;
/* @phpstan-ignore-next-line */
$cookie->profile = $context->employee->id_profile;
/* @phpstan-ignore-next-line */
$cookie->passwd = $context->employee->passwd;
/* @phpstan-ignore-next-line */
$cookie->remote_addr = $context->employee->remote_addr;
if (class_exists('EmployeeSession') && method_exists($cookie, 'registerSession')) {
$cookie->registerSession(new EmployeeSession());
}
if (!Tools::getValue('stay_logged_in')) {
/* @phpstan-ignore-next-line */
$cookie->last_activity = time();
}
$cookie->write();
$this->trackEditionLoginEvent($user);
return true;
}
/**
* @return OAuth2Service
*
* @throws Exception
*/
protected function getOAuth2Service()
{
return $this->module->getService(OAuth2Service::class);
}
/**
* @return mixed
*/
protected function redirectAfterLogin()
{
if ($this->getOAuthAction() === 'identifyPointOfContact') {
$forceSignup = $this->getForceSignup();
$this->getSession()->clear();
$this->closePopup($forceSignup);
}
$returnTo = $this->getReturnTo() ?: 'AdminDashboard';
if (preg_match('/^([A-Z][a-z0-9]+)+$/', $returnTo)) {
$returnTo = $this->context->link->getAdminLink($returnTo);
}
Tools::redirectAdmin($returnTo);
}
/**
* @return mixed
*/
protected function logout()
{
Tools::redirectAdmin(
$this->context->link->getAdminLink('AdminLogin', true, [], [
'logout' => 1,
])
);
}
/**
* @return mixed
*/
protected function onLoginFailedRedirect()
{
if ($this->getOAuthAction() === 'identifyPointOfContact') {
$this->closePopup();
}
$this->logout();
}
/**
* @return SessionInterface
*/
protected function getSession()
{
if (\Context::getContext()->employee->id) {
// FIXME: fallback only for setPointOfContact
return $this->module->getService(ConfigurationStorageSession::class);
}
return $this->module->getSession();
}
/**
* @return OAuth2Session
*/
protected function getOauth2Session()
{
return $this->module->getService(OAuth2Session::class);
}
/**
* @return AnalyticsService
*/
protected function getAnalyticsService()
{
return $this->analyticsService;
}
/**
* @return PsAccountsService
*/
protected function getPsAccountsService()
{
return $this->psAccountsService;
}
/**
* @param bool $forceSignup
*
* @return void
*/
protected function closePopup($forceSignup = false)
{
if ($forceSignup) {
Tools::redirect($this->getSignupUrl());
} else {
echo '
<script type="text/javascript">
window.close();
</script>
';
exit;
}
}
/**
* @return string
*/
protected function getSignupUrl()
{
return $this->module->getParameter('ps_accounts.accounts_ui_url') .
'?signupContext=popup';
}
}

View File

@@ -0,0 +1,11 @@
<?php
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;

View File

@@ -0,0 +1,278 @@
<?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
*/
use PrestaShop\Module\PsAccounts\Account\Exception\RefreshTokenException;
use PrestaShop\Module\PsAccounts\Account\Session\Firebase;
use PrestaShop\Module\PsAccounts\Account\Session\ShopSession;
use PrestaShop\Module\PsAccounts\Account\StatusManager;
use PrestaShop\Module\PsAccounts\Account\Token\NullToken;
use PrestaShop\Module\PsAccounts\Account\Token\Token;
use PrestaShop\Module\PsAccounts\Http\Controller\AbstractV2ShopRestController;
use PrestaShop\Module\PsAccounts\Http\Request\ShopHealthCheckRequest;
use PrestaShop\Module\PsAccounts\Service\Accounts\AccountsService;
use PrestaShop\Module\PsAccounts\Service\OAuth2\OAuth2Client;
use PrestaShop\Module\PsAccounts\Service\OAuth2\OAuth2Exception;
use PrestaShop\Module\PsAccounts\Service\OAuth2\OAuth2Service;
use PrestaShop\Module\PsAccounts\Service\PsAccountsService;
class ps_AccountsApiV2ShopHealthCheckModuleFrontController extends AbstractV2ShopRestController
{
/**
* @var StatusManager
*/
private $statusManager;
/**
* @var OAuth2Client
*/
private $oauth2Client;
/**
* @var ShopSession
*/
private $shopSession;
/**
* @var Firebase\ShopSession
*/
private $firebaseShopSession;
/**
* @var Firebase\OwnerSession
*/
private $firebaseOwnerSession;
/**
* @var PsAccountsService
*/
private $psAccountsService;
/**
* @var AccountsService
*/
private $accountsService;
/**
* @var OAuth2Service
*/
private $oauth2Service;
/**
* @return array
*/
public function getScope()
{
return [
'shop.health',
];
}
/**
* @return array
*/
public function getAudience()
{
return [
'ps_accounts/' . $this->statusManager->getCloudShopId(),
];
}
public function __construct()
{
parent::__construct();
// public healthcheck
$this->authenticated = false;
if ($this->getRequestHeader(self::HEADER_AUTHORIZATION) !== null) {
$this->authenticated = true;
}
$this->statusManager = $this->module->getService(StatusManager::class);
$this->oauth2Client = $this->module->getService(OAuth2Client::class);
$this->shopSession = $this->module->getService(ShopSession::class);
$this->firebaseShopSession = $this->module->getService(Firebase\ShopSession::class);
$this->firebaseOwnerSession = $this->module->getService(Firebase\OwnerSession::class);
$this->accountsService = $this->module->getService(AccountsService::class);
$this->psAccountsService = $this->module->getService(PsAccountsService::class);
$this->oauth2Service = $this->module->getService(OAuth2Service::class);
}
/**
* ?fc=module&module=ps_accounts&controller=apiV1ShopHealthCheck&shop_id=1&autoheal
*
* @param Shop $shop
* @param ShopHealthCheckRequest $request
*
* @return array
*/
public function show(Shop $shop, ShopHealthCheckRequest $request)
{
// $this->assertAudience([
// 'ps_accounts/' . $this->shopIdentity->getShopUuid(),
// ]);
// $this->assertScope([
// 'shop.health',
// ]);
if ($request->autoheal) {
try {
$this->firebaseShopSession->getValidToken();
$this->firebaseOwnerSession->getValidToken();
} catch (RefreshTokenException $e) {
}
}
$firebaseShopToken = $this->firebaseShopSession->getToken();
$firebaseOwnerToken = $this->firebaseOwnerSession->getToken();
$shopToken = $this->shopSession->getToken();
$healthCheckMessage = [
'oauth2Client' => $this->oauth2Client->exists(),
'shopLinked' => (bool) $this->statusManager->getCloudShopId(),
'isSsoEnabled' => $this->psAccountsService->getLoginActivated(),
'oauthToken' => $this->tokenInfos($shopToken),
'firebaseOwnerToken' => $this->tokenInfos($firebaseOwnerToken),
'firebaseShopToken' => $this->tokenInfos($firebaseShopToken),
'fopenActive' => (bool) ini_get('allow_url_fopen'),
'curlActive' => extension_loaded('curl'), //function_exists('curl_version'),
'oauthApiConnectivity' => $this->getOauthApiStatus(),
'accountsApiConnectivity' => $this->getAccountsApiStatus(),
'serverUTC' => time(),
'mysqlUTC' => $this->getDatabaseTimestamp(),
'env' => [
'oauth2Url' => $this->module->getParameter('ps_accounts.oauth2_url'),
'accountsApiUrl' => $this->module->getParameter('ps_accounts.accounts_api_url'),
'accountsUiUrl' => $this->module->getParameter('ps_accounts.accounts_ui_url'),
'accountsCdnUrl' => $this->module->getParameter('ps_accounts.accounts_cdn_url'),
'testimonialsUrl' => $this->module->getParameter('ps_accounts.testimonials_url'),
'checkApiSslCert' => $this->module->getParameter('ps_accounts.check_api_ssl_cert'),
],
];
if ($this->authenticated) {
$healthCheckMessage = array_merge($healthCheckMessage, [
// 'shopId' => $shop->id,
// 'shopBoUri' => '',
'psVersion' => _PS_VERSION_,
'moduleVersion' => Ps_accounts::VERSION,
'phpVersion' => phpversion(),
'cloudShopId' => (string) $this->statusManager->getCloudShopId(),
'shopName' => $shop->name,
'ownerEmail' => (string) $this->statusManager->getPointOfContactEmail(),
]);
}
return $healthCheckMessage;
}
/**
* {
* "aud": ["shop_58d..."],
* "client_id": "374c21dd-8b34-...",
* "exp": {
* "date": "2024-06-11 17:53:26.000000",
* "timezone_type": 1,
* "timezone": "+00:00"
* },
* "ext": {
* },
* "iat": {
* "date": "2024-06-11 16:53:26.000000",
* "timezone_type": 1,
* "timezone": "+00:00"
* },
* "iss": "https://oauth.prestashop.com",
* "jti": "bd21ec1d-bc08-458a-bc2b-c29b7cc5abcd",
* "nbf": {
* "date": "2024-06-11 16:53:26.000000",
* "timezone_type": 1,
* "timezone": "+00:00"
* },
* "scp": [],
* "sub": "374c21dd-8b34-..."
* }
*
* @param Token $token
*
* @return array
*/
private function tokenInfos(Token $token)
{
$jwt = $token->getJwt();
if ($jwt instanceof NullToken) {
return [];
}
$claims = $jwt->claims();
/** @var DateTimeImmutable $iat */
$iat = $claims->get('iat');
/** @var DateTimeImmutable $exp */
$exp = $claims->get('exp');
return [
'issuer' => $claims->get('iss'),
'issuedAt' => $iat->getTimestamp(),
'expireAt' => $exp->getTimestamp(),
'isExpired' => $token->isExpired(),
];
}
/**
* @return bool
*/
private function getAccountsApiStatus()
{
$response = $this->accountsService->healthCheck();
return $response->isSuccessful;
}
/**
* @return bool
*/
public function getOauthApiStatus()
{
try {
$this->oauth2Service->getWellKnown();
return true;
} catch (OAuth2Exception $e) {
return false;
}
}
/**
* @return int
*/
private function getDatabaseTimestamp()
{
try {
$row = \Db::getInstance()->getRow('SELECT NOW() AS utc');
if (is_array($row) && isset($row['utc'])) {
return (new DateTime($row['utc']))->getTimestamp();
}
} catch (Exception $e) {
}
return 0;
}
}

View File

@@ -0,0 +1,84 @@
<?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
*/
use PrestaShop\Module\PsAccounts\Account\ProofManager;
use PrestaShop\Module\PsAccounts\Account\StatusManager;
use PrestaShop\Module\PsAccounts\Http\Controller\AbstractV2ShopRestController;
class ps_AccountsApiV2ShopProofModuleFrontController extends AbstractV2ShopRestController
{
/**
* @var bool
*/
protected $authenticated = true;
/**
* @var ProofManager
*/
private $proofManager;
/**
* @var StatusManager
*/
private $statusManager;
/**
* @return array
*/
public function getScope()
{
return [
'shop.proof.read',
];
}
/**
* @return array
*/
public function getAudience()
{
return [
'ps_accounts/' . $this->statusManager->getCloudShopId(),
];
}
public function __construct()
{
parent::__construct();
$this->proofManager = $this->module->getService(ProofManager::class);
$this->statusManager = $this->module->getService(StatusManager::class);
}
/**
* @param Shop $shop
* @param array $payload
*
* @return array
*/
public function show(Shop $shop, array $payload)
{
$this->statusManager->invalidateCache();
return [
'proof' => $this->proofManager->getProof(),
];
}
}

View File

@@ -0,0 +1,11 @@
<?php
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;

View File

@@ -0,0 +1,11 @@
<?php
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;

View File

@@ -0,0 +1,11 @@
<?php
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;

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -0,0 +1,493 @@
<?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
*/
if (!defined('_PS_VERSION_')) {
exit;
}
require_once __DIR__ . '/vendor/autoload.php';
if (!class_exists('\PrestaShop\Module\PsAccounts\Hook\HookableTrait')) {
ps_accounts_fix_upgrade();
}
class Ps_accounts extends Module
{
use \PrestaShop\Module\PsAccounts\Hook\HookableTrait;
// Needed in order to retrieve the module version easier (in api call headers) than instanciate
// the module each time to get the version
const VERSION = '8.0.13';
/**
* Admin tabs
*
* @var array class names
*/
private $adminControllers = [
'AdminAjaxPsAccountsController',
'AdminAjaxV2PsAccountsController',
'AdminOAuth2PsAccountsController',
'AdminLoginPsAccountsController',
];
/**
* Hooks exposed by the module
*
* @var array
*/
private $customHooks = [
[
'name' => 'actionShopAccessTokenRefreshAfter',
'title' => 'Shop access token refreshed event',
'description' => 'Shop access token refreshed event',
'position' => 1,
],
];
/**
* Hooks to register
*
* @var array hook or class names
*/
private $hooks = [
//\PrestaShop\Module\PsAccounts\Hook\ActionAdminLoginControllerLoginAfter::class,
'actionAdminLoginControllerLoginAfter',
'actionAdminLoginControllerSetMedia',
//'actionAdminControllerSetMedia',
'displayBackOfficeHeader',
'actionObjectEmployeeDeleteAfter',
'actionObjectShopAddAfter',
'actionObjectShopDeleteAfter',
'actionShopAccessTokenRefreshAfter',
'displayBackOfficeEmployeeMenu',
];
/**
* @var \PrestaShop\Module\PsAccounts\ServiceContainer\PsAccountsContainer
*/
private $moduleContainer;
/**
* Ps_accounts constructor.
*/
public function __construct()
{
$this->name = 'ps_accounts';
$this->tab = 'administration';
$this->author = 'PrestaShop';
$this->need_instance = 0;
$this->bootstrap = true;
// We cannot use the const VERSION because the const is not computed by addons marketplace
// when the zip is uploaded
$this->version = '8.0.13';
$this->module_key = 'abf2cd758b4d629b2944d3922ef9db73';
parent::__construct();
$this->displayName = $this->l('PrestaShop Account');
$this->description = $this->l(
'Link your store to your PrestaShop account to activate and manage your subscriptions in your ' .
'back office. Do not uninstall this module if you have a current subscription.'
);
$this->description_full = $this->l(
'Link your store to your PrestaShop account to activate and manage your subscriptions in your ' .
'back office. Do not uninstall this module if you have a current subscription.'
);
$this->confirmUninstall = $this->l(
'This action will prevent immediately your PrestaShop services and Community services from ' .
'working as they are using PrestaShop Accounts module for authentication.'
);
$this->ps_versions_compliancy = ['min' => '1.6.1', 'max' => _PS_VERSION_];
}
/**
* @return \PrestaShop\Module\PsAccounts\Vendor\Monolog\Logger
*/
public function getLogger()
{
return $this->getService('ps_accounts.logger');
}
/**
* @return \Context
*/
public function getContext()
{
return $this->context;
}
/**
* @return bool
*
* @throws PrestaShopDatabaseException
* @throws PrestaShopException
* @throws Exception
*/
public function install()
{
$installer = new PrestaShop\Module\PsAccounts\Module\Install($this, Db::getInstance());
$status = $installer->installInMenu()
&& $installer->installDatabaseTables()
&& parent::install()
&& $this->addCustomHooks($this->customHooks)
&& $this->registerHook($this->getHooksToRegister());
// FIXME: implement safe "reset" method
$this->onModuleReset();
return $status;
}
/**
* @return bool
*
* @throws PrestaShopDatabaseException
* @throws PrestaShopException
*/
public function uninstall()
{
$uninstaller = new PrestaShop\Module\PsAccounts\Module\Uninstall($this, Db::getInstance());
return $uninstaller->uninstallMenu()
&& $uninstaller->uninstallDatabaseTables()
&& parent::uninstall();
}
/**
* @phpstan-ignore-next-line
*
* @return \PrestaShop\PrestaShop\Adapter\SymfonyContainer|\Symfony\Component\DependencyInjection\ContainerInterface|null
*/
public function getCoreServiceContainer()
{
/* @phpstan-ignore-next-line */
if (method_exists($this, 'getContainer')) {
return $this->getContainer();
}
if (class_exists('\PrestaShop\PrestaShop\Adapter\SymfonyContainer')) {
return \PrestaShop\PrestaShop\Adapter\SymfonyContainer::getInstance();
}
return null;
}
/**
* @return \PrestaShop\Module\PsAccounts\ServiceContainer\PsAccountsContainer
*
* @throws Exception
*/
public function getServiceContainer()
{
if (null === $this->moduleContainer) {
$this->moduleContainer = (new \PrestaShop\Module\PsAccounts\ServiceContainer\PsAccountsContainer(
__DIR__ . '/config.php'
))->init();
}
return $this->moduleContainer;
}
/**
* @param string $serviceName
*
* @return mixed
*/
public function getService($serviceName)
{
return $this->getServiceContainer()->getService($serviceName);
}
/**
* @param string $serviceName
*
* @return bool
*/
public function hasService($serviceName)
{
return $this->getServiceContainer()->has($serviceName);
}
/**
* @param string $name
* @param mixed $default
*
* @return mixed
*/
public function getParameter($name, $default = null)
{
return $this->getServiceContainer()->getParameter($name, $default);
}
/**
* @param string $name
*
* @return bool
*/
public function hasParameter($name)
{
return $this->getServiceContainer()->hasParameter($name);
}
/**
* @return array
*/
public function getAdminControllers()
{
return array_map(function ($className) {
return preg_replace('/^.*?(\w+)Controller$/', '\1', $className);
//return preg_replace('/^(.*?)Controller$/', '\1', $className);
}, $this->adminControllers);
}
/**
* @return array
*/
public function getHooksToRegister()
{
return array_map(function ($className) {
return is_a($className, '\PrestaShop\Module\PsAccounts\Hook\Hook', true) ?
$className::getName() : $className;
}, $this->hooks);
}
/**
* @return array
*/
public function getCustomHooks()
{
return $this->customHooks;
}
/**
* @param array $customHooks
*
* @return bool
*/
public function addCustomHooks($customHooks)
{
$ret = true;
foreach ($customHooks as $customHook) {
try {
$verify = true;
if ((bool) Hook::getIdByName($customHook['name']) === false) {
$hook = new Hook();
$hook->name = $customHook['name'];
$hook->title = $customHook['title'];
$hook->description = $customHook['description'];
$hook->position = $customHook['position'];
$verify = $hook->add(); // return true on success
}
$ret = $ret && $verify;
} catch (\Throwable $e) {
/* @phpstan-ignore-next-line */
} catch (\Exception $e) {
}
}
return $ret;
}
/**
* Render the configuration form.
*
* @return string
*
* @throws PrestaShopException
*/
public function getContent()
{
if (!empty($settingsForm = (new \PrestaShop\Module\PsAccounts\Settings\SettingsForm($this))->render())) {
return $settingsForm;
}
/** @var \PrestaShop\Module\PsAccounts\Service\PsAccountsService $psAccountsService */
$psAccountsService = $this->getService(\PrestaShop\Module\PsAccounts\Service\PsAccountsService::class);
//$this->context->smarty->assign('pathVendor', $this->_path . 'views/js/chunk-vendors.' . $this->version . '.js');
$this->context->smarty->assign('urlAccountsCdn', $this->getParameter('ps_accounts.accounts_cdn_url'));
$this->context->smarty->assign('componentInitParams', $psAccountsService->getComponentInitParams());
return $this->display(__FILE__, 'views/templates/admin/app.tpl');
}
/**
* @param array $params
*
* @return void
*/
public function redirectSettingsPage(array $params = [])
{
Tools::redirectAdmin($this->getSettingsPageUrl($params));
}
/**
* @param array $params
*
* @return string
*/
public function getSettingsPageUrl(array $params = [])
{
if (version_compare(_PS_VERSION_, '1.7', '>')) {
return $this->context->link->getAdminLink(
'AdminModules',
true,
[],
array_merge($params, [
'configure' => $this->name,
])
);
} else {
return AdminController::$currentIndex . '&' . http_build_query(array_merge($params, [
'configure' => $this->name,
'token' => Tools::getAdminTokenLite('AdminModules'),
]));
}
}
/**
* @return string
*/
public function getAccountsUiUrl()
{
return $this->getParameter('ps_accounts.accounts_ui_url');
}
/**
* @return string
*/
public function getSsoAccountUrl()
{
$url = $this->getParameter('ps_accounts.sso_account_url');
$langIsoCode = $this->getContext()->language->iso_code;
return $url . '?lang=' . substr($langIsoCode, 0, 2);
}
/**
* @return \PrestaShop\Module\PsAccounts\Context\ShopContext
*/
public function getShopContext()
{
return $this->getService(\PrestaShop\Module\PsAccounts\Context\ShopContext::class);
}
/**
* @return bool
*/
public function isShopEdition()
{
return Module::isEnabled('smb_edition');
}
/**
* @return \Symfony\Component\HttpFoundation\Session\SessionInterface
*
* @throws Exception
*/
public function getSession()
{
// Class name must be literal here in case interface is not present (PrestaShop 1.6)
return $this->getService('\Symfony\Component\HttpFoundation\Session\SessionInterface');
}
/**
* @return void
*
* @throws Exception
*/
public function onModuleReset()
{
/** @var \PrestaShop\Module\PsAccounts\Repository\ConfigurationRepository $configurationRepository */
$configurationRepository = $this->getService(\PrestaShop\Module\PsAccounts\Repository\ConfigurationRepository::class);
$configurationRepository->fixMultiShopConfig(true);
/** @var \PrestaShop\Module\PsAccounts\Http\Client\CircuitBreaker\Factory $circuitBreakerFactory */
$circuitBreakerFactory = $this->getService(\PrestaShop\Module\PsAccounts\Http\Client\CircuitBreaker\Factory::class);
$circuitBreakerFactory->resetAll();
/** @var \PrestaShop\Module\PsAccounts\Service\OAuth2\OAuth2Service $oAuth2Service */
$oAuth2Service = $this->getService(\PrestaShop\Module\PsAccounts\Service\OAuth2\OAuth2Service::class);
$oAuth2Service->clearCache();
// FIXME: this wont prevent from re-implanting override on reset of module
$uninstaller = new PrestaShop\Module\PsAccounts\Module\Uninstall($this, Db::getInstance());
$uninstaller->deleteAdminTab('AdminLogin');
/** @var \PrestaShop\Module\PsAccounts\Cqrs\CommandBus $commandBus */
$commandBus = $this->getService(\PrestaShop\Module\PsAccounts\Cqrs\CommandBus::class);
// Verification flow
$commandBus->handle(new \PrestaShop\Module\PsAccounts\Account\Command\MigrateOrCreateIdentitiesV8Command());
}
/**
* @return string
*/
public function getCloudShopId()
{
/** @var \PrestaShop\Module\PsAccounts\Account\StatusManager $statusManager */
$statusManager = $this->getService(\PrestaShop\Module\PsAccounts\Account\StatusManager::class);
return $statusManager->getCloudShopId();
}
/**
* @param string $source
*
* @return bool
*/
public function getVerifiedStatus($source = 'ps_accounts')
{
/** @var \PrestaShop\Module\PsAccounts\Account\StatusManager $statusManager */
$statusManager = $this->getService(\PrestaShop\Module\PsAccounts\Account\StatusManager::class);
try {
if ($statusManager->withSource($source)->getStatus()->isVerified) {
return true;
}
} catch (\PrestaShop\Module\PsAccounts\Account\Exception\UnknownStatusException $e) {
}
return false;
}
}
/**
* @return void
*/
function ps_accounts_fix_upgrade()
{
$root = __DIR__;
$requires = array_merge([
$root . '/src/Module/Install.php',
//$root . '/src/Hook/Hook.php',
$root . '/src/Hook/HookableTrait.php',
$root . '/src/Settings/SettingsForm.php',
], []/*, glob($root . '/src/Hook/*.php')*/);
foreach ($requires as $filename) {
require_once $filename;
}
}

View File

@@ -0,0 +1,11 @@
CREATE TABLE IF NOT EXISTS `PREFIX_employee_account`
(
id_employee_account INT AUTO_INCREMENT NOT NULL,
id_employee INT NOT NULL,
email VARCHAR(64) NOT NULL,
uid VARCHAR(64) NOT NULL,
date_add DATETIME NOT NULL,
date_upd DATETIME NOT NULL,
PRIMARY KEY(id_employee_account)
) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci`
ENGINE = InnoDB;

View File

@@ -0,0 +1,11 @@
<?php
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;

View File

@@ -0,0 +1 @@
DROP TABLE IF EXISTS `PREFIX_employee_account`;

View File

@@ -0,0 +1,85 @@
<?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\Account;
use DateTime;
use PrestaShop\Module\PsAccounts\Http\Resource\Resource;
use PrestaShop\Module\PsAccounts\Service\Accounts\Resource\ShopStatus;
class CachedShopStatus extends Resource
{
/**
* @var ShopStatus
*/
public $shopStatus;
/**
* @var bool
*/
public $isValid = false;
/**
* @var DateTime|null
*/
public $updatedAt;
// /**
// * @var string[]
// */
// protected $required = [
// 'shopStatus',
// ];
public function __construct($values = [])
{
$this->castDateTime($values, [
'updatedAt',
]);
$this->castBool($values, [
'isValid',
]);
$this->castChildResource($values, ShopStatus::class, [
'shopStatus',
]);
parent::__construct($values);
}
/**
* @param bool $all
*
* @return array
*/
public function toArray($all = true)
{
$array = parent::toArray($all);
$this->uncastChildResource($array, ShopStatus::class, [
'shopStatus',
], $all);
$this->uncastDateTime($array, [
'updatedAt',
]);
return $array;
}
}

View File

@@ -0,0 +1,38 @@
<?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\Account\Command;
class CleanupIdentityCommand
{
/**
* @var int|null
*/
public $shopId;
/**
* @param int|null $shopId
*/
public function __construct($shopId = null)
{
$this->shopId = $shopId ?: \Shop::getContextShopID(true);
}
}

View File

@@ -0,0 +1,34 @@
<?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\Account\Command;
use PrestaShop\Module\PsAccounts\Traits\WithOriginAndSourceTrait;
class CreateIdentitiesCommand
{
use withOriginAndSourceTrait;
public function __construct()
{
$this->resetProperties();
}
}

View File

@@ -0,0 +1,51 @@
<?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\Account\Command;
use PrestaShop\Module\PsAccounts\Traits\WithOriginAndSourceTrait;
class CreateIdentityCommand
{
use WithOriginAndSourceTrait;
/**
* @var int|null
*/
public $shopId;
/**
* @var bool
*/
public $renew;
/**
* @param int|null $shopId
* @param bool $renew
*/
public function __construct($shopId, $renew = false
) {
$this->shopId = $shopId;
$this->renew = $renew;
$this->resetProperties();
}
}

View File

@@ -0,0 +1,53 @@
<?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\Account\Command;
use PrestaShop\Module\PsAccounts\Service\OAuth2\Resource\AccessToken;
use PrestaShop\Module\PsAccounts\Service\OAuth2\Resource\UserInfo;
use PrestaShop\Module\PsAccounts\Traits\WithOriginAndSourceTrait;
class IdentifyContactCommand
{
use WithOriginAndSourceTrait;
/**
* @var AccessToken
*/
public $accessToken;
/**
* @var UserInfo
*/
public $userInfo;
/**
* @param AccessToken $accessToken
* @param UserInfo $userInfo
*/
public function __construct($accessToken, $userInfo)
{
$this->accessToken = $accessToken;
$this->userInfo = $userInfo;
$this->resetProperties();
}
}

View File

@@ -0,0 +1,34 @@
<?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\Account\Command;
use PrestaShop\Module\PsAccounts\Traits\WithOriginAndSourceTrait;
class MigrateOrCreateIdentitiesV8Command
{
use WithOriginAndSourceTrait;
public function __construct()
{
$this->resetProperties();
}
}

View File

@@ -0,0 +1,44 @@
<?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\Account\Command;
use PrestaShop\Module\PsAccounts\Traits\WithOriginAndSourceTrait;
class MigrateOrCreateIdentityV8Command
{
use WithOriginAndSourceTrait;
/**
* @var int|null
*/
public $shopId;
/**
* @param int|null $shopId
*/
public function __construct($shopId)
{
$this->shopId = $shopId;
$this->resetProperties();
}
}

View File

@@ -0,0 +1,90 @@
<?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\Account\Command;
use PrestaShop\Module\PsAccounts\Traits\WithOriginAndSourceTrait;
class RestoreIdentityCommand
{
use WithOriginAndSourceTrait;
/**
* @var int|null
*/
public $shopId;
/**
* @var string
*/
public $cloudShopId;
/**
* @var string
*/
public $clientId;
/**
* @var string
*/
public $clientSecret;
/**
* @var bool
*/
public $verify;
/**
* @var bool
*/
public $migrate;
/**
* @var string|null
*/
public $migrateFrom;
/**
* @param string $cloudShopId
* @param string $clientId
* @param string $clientSecret
* @param bool $verify
* @param bool $migrate
* @param string $migrateFrom
*/
public function __construct(
$cloudShopId,
$clientId,
$clientSecret,
$verify = false,
$migrate = false,
$migrateFrom = null
) {
$this->cloudShopId = $cloudShopId;
$this->clientId = $clientId;
$this->clientSecret = $clientSecret;
$this->verify = $verify;
$this->migrate = $migrate;
$this->migrateFrom = $migrateFrom;
$this->resetProperties();
}
}

View File

@@ -0,0 +1,38 @@
<?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\Account\Command;
class UpdateBackOfficeUrlCommand
{
/**
* @var int
*/
public $shopId;
/**
* @param int $shopId
*/
public function __construct($shopId)
{
$this->shopId = $shopId;
}
}

View File

@@ -0,0 +1,26 @@
<?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\Account\Command;
class UpdateBackOfficeUrlsCommand
{
}

View File

@@ -0,0 +1,34 @@
<?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\Account\Command;
use PrestaShop\Module\PsAccounts\Traits\WithOriginAndSourceTrait;
class VerifyIdentitiesCommand
{
use WithOriginAndSourceTrait;
public function __construct()
{
$this->resetProperties();
}
}

View File

@@ -0,0 +1,51 @@
<?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\Account\Command;
use PrestaShop\Module\PsAccounts\Traits\WithOriginAndSourceTrait;
class VerifyIdentityCommand
{
use WithOriginAndSourceTrait;
/**
* @var int|null
*/
public $shopId;
/**
* @var bool
*/
public $force;
/**
* @param int|null $shopId
* @param bool $force
*/
public function __construct($shopId, $force = false)
{
$this->shopId = $shopId;
$this->force = $force;
$this->resetProperties();
}
}

View File

@@ -0,0 +1,11 @@
<?php
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;

View File

@@ -0,0 +1,42 @@
<?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\Account\CommandHandler;
use PrestaShop\Module\PsAccounts\Account\Command\CleanupIdentityCommand;
class CleanupIdentityHandler
{
/**
* @param CleanupIdentityCommand $command
*
* @return void
*/
public function handle(CleanupIdentityCommand $command)
{
$id_shop = $command->shopId;
\Db::getInstance()->execute(
'DELETE FROM `' . _DB_PREFIX_ . bqSQL('configuration') . '`'
. ' WHERE (name like \'PS_ACCOUNTS%\' or name = \'PSX_UUID_V4\' or name = \'PS_CHECKOUT_SHOP_UUID_V4\')'
. ' AND ' . ($id_shop ? 'id_shop = ' . (int) $id_shop : 'id_shop IS NULL')
);
}
}

View File

@@ -0,0 +1,52 @@
<?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\Account\CommandHandler;
use PrestaShop\Module\PsAccounts\Account\Command\CreateIdentitiesCommand;
use PrestaShop\Module\PsAccounts\Account\Command\CreateIdentityCommand;
use PrestaShop\Module\PsAccounts\Account\Exception\RefreshTokenException;
use PrestaShop\Module\PsAccounts\Log\Logger;
use PrestaShop\Module\PsAccounts\Service\Accounts\AccountsException;
class CreateIdentitiesHandler extends MultiShopHandler
{
/**
* @param CreateIdentitiesCommand $command
*
* @return void
*/
public function handle(CreateIdentitiesCommand $command)
{
$this->handleMulti(function ($multiShopId) use ($command) {
try {
$this->commandBus->handle(
(new CreateIdentityCommand($multiShopId, false))
->withOrigin($command->origin)
->withSource($command->source)
);
} catch (RefreshTokenException $e) {
Logger::getInstance()->error($e->getMessage());
} catch (AccountsException $e) {
Logger::getInstance()->error($e->getMessage());
}
});
}
}

View File

@@ -0,0 +1,136 @@
<?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\Account\CommandHandler;
use PrestaShop\Module\PsAccounts\Account\Command\CreateIdentityCommand;
use PrestaShop\Module\PsAccounts\Account\Command\VerifyIdentityCommand;
use PrestaShop\Module\PsAccounts\Account\Exception\RefreshTokenException;
use PrestaShop\Module\PsAccounts\Account\Exception\UnknownStatusException;
use PrestaShop\Module\PsAccounts\Account\StatusManager;
use PrestaShop\Module\PsAccounts\Cqrs\CommandBus;
use PrestaShop\Module\PsAccounts\Provider\ShopProvider;
use PrestaShop\Module\PsAccounts\Service\Accounts\AccountsException;
use PrestaShop\Module\PsAccounts\Service\Accounts\AccountsService;
use PrestaShop\Module\PsAccounts\Service\OAuth2\OAuth2Client;
class CreateIdentityHandler
{
/**
* @var AccountsService
*/
private $accountsService;
/**
* @var OAuth2Client
*/
private $oAuth2Client;
/**
* @var ShopProvider
*/
private $shopProvider;
/**
* @var StatusManager
*/
private $statusManager;
/**
* @var CommandBus
*/
private $commandBus;
/**
* @param AccountsService $accountsService
* @param ShopProvider $shopProvider
* @param OAuth2Client $oauth2Client
* @param StatusManager $shopStatus
* @param CommandBus $commandBus
*/
public function __construct(
AccountsService $accountsService,
ShopProvider $shopProvider,
OAuth2Client $oauth2Client,
StatusManager $shopStatus,
CommandBus $commandBus
) {
$this->accountsService = $accountsService;
$this->shopProvider = $shopProvider;
$this->oAuth2Client = $oauth2Client;
$this->statusManager = $shopStatus;
$this->commandBus = $commandBus;
}
/**
* @param CreateIdentityCommand $command
*
* @return void
*
* @throws RefreshTokenException
* @throws UnknownStatusException
* @throws AccountsException
*/
public function handle(CreateIdentityCommand $command)
{
if ($command->renew || !$this->isAlreadyCreated()) {
$shopId = $command->shopId;
$identityCreated = $this->accountsService
->withSource($command->source)
->withOrigin($command->origin)
->createShopIdentity(
$this->shopProvider->getUrl($shopId),
$this->shopProvider->getName($shopId)
);
$this->oAuth2Client->update(
$identityCreated->clientId,
$identityCreated->clientSecret
);
$this->statusManager->setCloudShopId($identityCreated->cloudShopId);
$this->statusManager->setIsVerified(false);
$this->statusManager->invalidateCache();
$this->commandBus->handle(
(new VerifyIdentityCommand($shopId, true))
->withOrigin($command->origin)
->withSource($command->source)
);
} else {
$this->commandBus->handle(
(new VerifyIdentityCommand($command->shopId))
->withOrigin($command->origin)
->withSource($command->source)
);
}
}
/**
* Idempotency check
*
* @return bool
*/
private function isAlreadyCreated()
{
// FIXME: define where this code belongs
return $this->oAuth2Client->exists() && $this->statusManager->identityCreated();
}
}

View File

@@ -0,0 +1,99 @@
<?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\Account\CommandHandler;
use PrestaShop\Module\PsAccounts\Account\Command\IdentifyContactCommand;
use PrestaShop\Module\PsAccounts\Account\Session\Firebase\OwnerSession;
use PrestaShop\Module\PsAccounts\Account\Session\ShopSession;
use PrestaShop\Module\PsAccounts\Account\StatusManager;
use PrestaShop\Module\PsAccounts\Service\Accounts\AccountsException;
use PrestaShop\Module\PsAccounts\Service\Accounts\AccountsService;
class IdentifyContactHandler
{
/**
* @var AccountsService
*/
private $accountsService;
/**
* @var StatusManager
*/
private $statusManager;
/**
* @var ShopSession
*/
private $shopSession;
/**
* @var OwnerSession
*/
private $ownerSession;
/**
* @param AccountsService $accountsService
* @param StatusManager $statusManager
* @param ShopSession $shopSession
* @param OwnerSession $ownerSession
*/
public function __construct(
AccountsService $accountsService,
StatusManager $statusManager,
ShopSession $shopSession,
OwnerSession $ownerSession
) {
$this->accountsService = $accountsService;
$this->statusManager = $statusManager;
$this->shopSession = $shopSession;
$this->ownerSession = $ownerSession;
}
/**
* @param IdentifyContactCommand $command
*
* @return void
*
* @throws AccountsException
*/
public function handle(IdentifyContactCommand $command)
{
$status = $this->statusManager->withSource($command->source)->getStatus();
if (!$status->isVerified) {
return;
}
$this->accountsService
->withSource($command->source)
->setPointOfContact(
$this->statusManager->getCloudShopId(),
$this->shopSession->getValidToken(),
$command->accessToken->access_token
);
// cleanup user token
$this->ownerSession->cleanup();
// optimistic update cached status
$this->statusManager->setPointOfContactUuid($command->userInfo->sub);
$this->statusManager->setPointOfContactEmail($command->userInfo->email);
}
}

View File

@@ -0,0 +1,49 @@
<?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\Account\CommandHandler;
use Exception;
use PrestaShop\Module\PsAccounts\Account\Command\MigrateOrCreateIdentitiesV8Command;
use PrestaShop\Module\PsAccounts\Account\Command\MigrateOrCreateIdentityV8Command;
use PrestaShop\Module\PsAccounts\Log\Logger;
class MigrateOrCreateIdentitiesV8Handler extends MultiShopHandler
{
/**
* @param MigrateOrCreateIdentitiesV8Command $command
*
* @return void
*/
public function handle(MigrateOrCreateIdentitiesV8Command $command)
{
$this->handleMulti(function ($multiShopId) use ($command) {
try {
$this->commandBus->handle(
(new MigrateOrCreateIdentityV8Command($multiShopId))
->withOrigin($command->origin)
->withSource($command->source)
);
} catch (Exception $e) {
Logger::getInstance()->error($e->getMessage());
}
});
}
}

View File

@@ -0,0 +1,274 @@
<?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\Account\CommandHandler;
use InvalidArgumentException;
use PrestaShop\Module\PsAccounts\Account\Command\CreateIdentityCommand;
use PrestaShop\Module\PsAccounts\Account\Command\MigrateOrCreateIdentityV8Command;
use PrestaShop\Module\PsAccounts\Account\Exception\RefreshTokenException;
use PrestaShop\Module\PsAccounts\Account\Exception\UnknownStatusException;
use PrestaShop\Module\PsAccounts\Account\ProofManager;
use PrestaShop\Module\PsAccounts\Account\StatusManager;
use PrestaShop\Module\PsAccounts\Cqrs\CommandBus;
use PrestaShop\Module\PsAccounts\Provider\ShopProvider;
use PrestaShop\Module\PsAccounts\Repository\ConfigurationRepository;
use PrestaShop\Module\PsAccounts\Service\Accounts\AccountsException;
use PrestaShop\Module\PsAccounts\Service\Accounts\AccountsService;
use PrestaShop\Module\PsAccounts\Service\Accounts\Exception\StoreLegacyNotFoundException;
use PrestaShop\Module\PsAccounts\Service\OAuth2\OAuth2Exception;
use PrestaShop\Module\PsAccounts\Service\OAuth2\OAuth2Service;
use PrestaShop\Module\PsAccounts\Service\UpgradeService;
class MigrateOrCreateIdentityV8Handler
{
/**
* @var AccountsService
*/
private $accountsService;
/**
* @var OAuth2Service
*/
protected $oAuth2Service;
/**
* @var ShopProvider
*/
private $shopProvider;
/**
* @var StatusManager
*/
private $statusManager;
/**
* @var ProofManager
*/
protected $proofManager;
/**
* @var ConfigurationRepository
*/
private $configurationRepository;
/**
* @var CommandBus
*/
private $commandBus;
/**
* @var UpgradeService
*/
private $upgradeService;
/**
* @param AccountsService $accountsService
* @param OAuth2Service $oAuth2Service
* @param ShopProvider $shopProvider
* @param StatusManager $shopStatus
* @param ProofManager $proofManager
* @param ConfigurationRepository $configurationRepository
* @param CommandBus $commandBus
* @param UpgradeService $upgradeService
*/
public function __construct(
AccountsService $accountsService,
OAuth2Service $oAuth2Service,
ShopProvider $shopProvider,
StatusManager $shopStatus,
ProofManager $proofManager,
ConfigurationRepository $configurationRepository,
CommandBus $commandBus,
UpgradeService $upgradeService
) {
$this->accountsService = $accountsService;
$this->oAuth2Service = $oAuth2Service;
$this->shopProvider = $shopProvider;
$this->statusManager = $shopStatus;
$this->proofManager = $proofManager;
$this->configurationRepository = $configurationRepository;
$this->commandBus = $commandBus;
$this->upgradeService = $upgradeService;
}
/**
* @param MigrateOrCreateIdentityV8Command $command
*
* @return void
*
* @throws AccountsException
* @throws RefreshTokenException
* @throws UnknownStatusException
*/
public function handle(MigrateOrCreateIdentityV8Command $command)
{
$shopId = $command->shopId;
$shopUuid = $this->configurationRepository->getShopUuid();
// FIXME: command can hold that property depending on context
$fromVersion = $this->upgradeService->getRegisteredVersion();
$migratedToV8 = version_compare($fromVersion, '8', '>=');
$notIdentified = !$shopUuid;
// FIXME: shouldn't this condition be a specific flag
if ($notIdentified || $migratedToV8) {
$this->registerLatestVersion();
$this->createOrVerifyIdentity($command);
return;
}
try {
// Register cloudShopId locally
$this->statusManager->setCloudShopId($shopUuid);
$identityCreated = $this->accountsService
->withSource($command->source)
->migrateShopIdentity(
$shopUuid,
$this->getTokenV6OrV7($shopUuid),
$this->shopProvider->getUrl($shopId),
$this->shopProvider->getName($shopId),
$fromVersion,
$this->proofManager->generateProof()
);
if (!empty($identityCreated->clientId) &&
!empty($identityCreated->clientSecret)) {
$this->oAuth2Service->getOAuth2Client()->update(
$identityCreated->clientId,
$identityCreated->clientSecret
);
}
$this->clearTokens();
$this->statusManager->invalidateCache();
$this->registerLatestVersion();
} catch (StoreLegacyNotFoundException $e) {
if ($command->origin !== AccountsService::ORIGIN_ADVANCED_SETTINGS) {
$this->registerLatestVersion();
$this->cleanupIdentity();
$this->createOrVerifyIdentity($command);
return;
} else {
throw $e;
}
}
}
/**
* @param string $shopUuid
*
* @return string
*
* @throws OAuth2Exception
*/
private function getAccessTokenV7($shopUuid)
{
return $this->oAuth2Service->getAccessTokenByClientCredentials([], [
// audience v7
'shop_' . $shopUuid,
])->access_token;
}
/**
* @param string $shopUuid
*
* @return string
*
* @throws AccountsException
* @throws InvalidArgumentException
*/
private function getFirebaseTokenV6($shopUuid)
{
return $this->accountsService->refreshShopToken(
$this->configurationRepository->getFirebaseRefreshToken(),
$shopUuid
)->token;
}
/**
* @param string $shopUuid
*
* @return string
*
* @throws AccountsException
*/
private function getTokenV6OrV7($shopUuid)
{
try {
return $this->getAccessTokenV7($shopUuid);
} catch (OAuth2Exception $e) {
return $this->getFirebaseTokenV6($shopUuid);
}
}
/**
* @return void
*/
private function cleanupIdentity()
{
// Will trigger reset banner
//$this->upgradeService->setVersion('');
$this->statusManager->clearStatus();
$this->oAuth2Service->getOAuth2Client()->delete();
$this->clearTokens();
}
/**
* Create Or Verify Or Do Nothing
*
* @param MigrateOrCreateIdentityV8Command $command
*
* @return void
*
* @throws RefreshTokenException
* @throws UnknownStatusException
* @throws AccountsException
*/
private function createOrVerifyIdentity(MigrateOrCreateIdentityV8Command $command)
{
$this->commandBus->handle(
(new CreateIdentityCommand($command->shopId, false))
->withOrigin($command->origin)
->withSource($command->source)
);
}
/**
* @return void
*/
private function clearTokens()
{
$this->configurationRepository->updateAccessToken('');
$this->configurationRepository->updateFirebaseIdAndRefreshTokens('', '');
$this->configurationRepository->updateUserFirebaseIdAndRefreshToken('', '');
}
/**
* @return void
*/
private function registerLatestVersion()
{
$this->upgradeService->setVersion();
}
}

View File

@@ -0,0 +1,71 @@
<?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\Account\CommandHandler;
use PrestaShop\Module\PsAccounts\Context\ShopContext;
use PrestaShop\Module\PsAccounts\Cqrs\CommandBus;
abstract class MultiShopHandler
{
/**
* @var ShopContext
*/
protected $shopContext;
/**
* @var CommandBus
*/
protected $commandBus;
public function __construct(
ShopContext $shopContext,
CommandBus $commandBus
) {
$this->shopContext = $shopContext;
$this->commandBus = $commandBus;
}
/**
* @param \Closure $handler
*
* @return void
*/
protected function handleMulti($handler)
{
foreach ($this->getShopIds() as $multiShopId) {
$this->shopContext->execInShopContext($multiShopId, function () use ($handler, $multiShopId) {
$handler($multiShopId);
});
}
}
/**
* @return int[]
*/
protected function getShopIds()
{
if ($this->shopContext->isMultishopActive()) {
return $this->shopContext->getMultiShopIds();
}
//return [\Shop::getContextShopID(true)];
return [\Shop::getContextShopID()];
}
}

View File

@@ -0,0 +1,158 @@
<?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\Account\CommandHandler;
use Exception;
use PrestaShop\Module\PsAccounts\Account\Command\MigrateOrCreateIdentityV8Command;
use PrestaShop\Module\PsAccounts\Account\Command\RestoreIdentityCommand;
use PrestaShop\Module\PsAccounts\Account\Command\VerifyIdentityCommand;
use PrestaShop\Module\PsAccounts\Account\Exception\UnknownStatusException;
use PrestaShop\Module\PsAccounts\Account\StatusManager;
use PrestaShop\Module\PsAccounts\Cqrs\CommandBus;
use PrestaShop\Module\PsAccounts\Log\Logger;
use PrestaShop\Module\PsAccounts\Service\Accounts\Resource\ShopStatus;
use PrestaShop\Module\PsAccounts\Service\OAuth2\OAuth2Client;
use PrestaShop\Module\PsAccounts\Service\UpgradeService;
use Throwable;
class RestoreIdentityHandler
{
/**
* @var OAuth2Client
*/
private $oAuth2Client;
/**
* @var StatusManager
*/
private $statusManager;
/**
* @var UpgradeService
*/
private $upgradeService;
/**
* @var CommandBus
*/
private $commandBus;
/**
* @param OAuth2Client $oauth2Client
* @param StatusManager $shopStatus
* @param UpgradeService $upgradeService
* @param CommandBus $commandBus
*/
public function __construct(
OAuth2Client $oauth2Client,
StatusManager $shopStatus,
UpgradeService $upgradeService,
CommandBus $commandBus
) {
$this->oAuth2Client = $oauth2Client;
$this->statusManager = $shopStatus;
$this->upgradeService = $upgradeService;
$this->commandBus = $commandBus;
}
/**
* @param RestoreIdentityCommand $command
*
* @return void
*
* @throws Exception|Throwable
*/
public function handle(RestoreIdentityCommand $command)
{
try {
$currentStatus = $this->statusManager->getStatus(true);
} catch (UnknownStatusException $e) {
$currentStatus = null;
}
$registeredVersion = $this->upgradeService->getRegisteredVersion();
$shopId = $command->shopId ?: \Shop::getContextShopID();
try {
$this->statusManager->clearStatus();
// Update OAuth client
$this->oAuth2Client->update(
$command->clientId,
$command->clientSecret ?: $this->oAuth2Client->getClientSecret()
);
// Update cloudShopId
$this->statusManager->setCloudShopId($command->cloudShopId);
// Fix version number when not set
$this->upgradeService->setVersion();
if ($command->migrate) {
// this will trigger migration
$this->upgradeService->setVersion($command->migrateFrom);
}
$this->commandBus->handle(
// FIXME: $cloudShopId (should not be necessary to read it from db)
(new MigrateOrCreateIdentityV8Command($shopId))
->withOrigin($command->origin)
->withSource($command->source)
);
if ($command->verify) {
// force verify
$this->commandBus->handle(
(new VerifyIdentityCommand($shopId, true))
->withOrigin($command->origin)
->withSource($command->source)
);
}
//$this->statusManager->invalidateCache();
} catch (Exception $e) {
$this->handleError($currentStatus, $registeredVersion, $e);
} catch (Throwable $e) {
$this->handleError($currentStatus, $registeredVersion, $e);
}
}
/**
* @param ShopStatus|null $currentStatus
* @param string $registeredVersion
* @param Exception|Throwable $e
*
* @return void
*
* @throws Exception|Throwable
*/
private function handleError($currentStatus, $registeredVersion, $e)
{
if (isset($currentStatus)) {
$this->statusManager->restoreStatus($currentStatus);
}
$this->upgradeService->setVersion($registeredVersion);
Logger::getInstance()->error($e);
throw $e;
}
}

View File

@@ -0,0 +1,109 @@
<?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\Account\CommandHandler;
use PrestaShop\Module\PsAccounts\Account\Command\UpdateBackOfficeUrlCommand;
use PrestaShop\Module\PsAccounts\Account\Session\ShopSession;
use PrestaShop\Module\PsAccounts\Account\ShopUrl;
use PrestaShop\Module\PsAccounts\Account\StatusManager;
use PrestaShop\Module\PsAccounts\Log\Logger;
use PrestaShop\Module\PsAccounts\Provider\ShopProvider;
use PrestaShop\Module\PsAccounts\Repository\ConfigurationRepository;
use PrestaShop\Module\PsAccounts\Service\Accounts\AccountsService;
class UpdateBackOfficeUrlHandler
{
/**
* @var AccountsService
*/
private $accountsService;
/**
* @var StatusManager
*/
private $statusManager;
/**
* @var ShopProvider
*/
private $shopProvider;
/**
* @var ShopSession
*/
private $shopSession;
/**
* @var ConfigurationRepository
*/
private $configurationRepository;
/**
* @param AccountsService $accountsService
* @param StatusManager $statusManager
* @param ShopProvider $shopProvider
* @param ShopSession $shopSession
* @param ConfigurationRepository $configurationRepository
*/
public function __construct(
AccountsService $accountsService,
StatusManager $statusManager,
ShopProvider $shopProvider,
ShopSession $shopSession,
ConfigurationRepository $configurationRepository
) {
$this->accountsService = $accountsService;
$this->statusManager = $statusManager;
$this->shopProvider = $shopProvider;
$this->shopSession = $shopSession;
$this->configurationRepository = $configurationRepository;
}
/**
* @param UpdateBackOfficeUrlCommand $command
*
* @return void
*/
public function handle(UpdateBackOfficeUrlCommand $command)
{
// On disconnected context with single shop mode, the contextual shop id is not defined.
$shopId = $command->shopId ?: $this->configurationRepository->getMainShopId();
// TODO: rework parameters priority
$status = $this->statusManager->withSource('ps_accounts')->getStatus();
$cloudShopUrl = ShopUrl::createFromStatus($status, $shopId);
$localShopUrl = $this->shopProvider->getUrl($shopId);
try {
// Check if BO url changed and urls aren't empty
if (!$cloudShopUrl->backOfficeUrlEquals($localShopUrl)) {
$this->accountsService->updateBackOfficeUrl(
$status->cloudShopId,
$this->shopSession->getValidToken(),
$localShopUrl
);
}
} catch (\InvalidArgumentException $e) {
Logger::getInstance()->error($e->getMessage());
}
}
}

View File

@@ -0,0 +1,49 @@
<?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\Account\CommandHandler;
use Exception;
use PrestaShop\Module\PsAccounts\Account\Command\UpdateBackOfficeUrlCommand;
use PrestaShop\Module\PsAccounts\Account\Command\UpdateBackOfficeUrlsCommand;
use PrestaShop\Module\PsAccounts\Log\Logger;
use Throwable;
class UpdateBackOfficeUrlsHandler extends MultiShopHandler
{
/**
* @param UpdateBackOfficeUrlsCommand $command
*
* @return void
*/
public function handle(UpdateBackOfficeUrlsCommand $command)
{
$this->handleMulti(function ($multiShopId) {
try {
$updateBackOfficeUrlCommand = new UpdateBackOfficeUrlCommand($multiShopId);
$this->commandBus->handle($updateBackOfficeUrlCommand);
} catch (Exception $e) {
Logger::getInstance()->error($e->getMessage());
} catch (Throwable $e) {
Logger::getInstance()->error($e->getMessage());
}
});
}
}

View File

@@ -0,0 +1,55 @@
<?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\Account\CommandHandler;
use PrestaShop\Module\PsAccounts\Account\Command\VerifyIdentitiesCommand;
use PrestaShop\Module\PsAccounts\Account\Command\VerifyIdentityCommand;
use PrestaShop\Module\PsAccounts\Account\Exception\RefreshTokenException;
use PrestaShop\Module\PsAccounts\Account\Exception\UnknownStatusException;
use PrestaShop\Module\PsAccounts\Log\Logger;
use PrestaShop\Module\PsAccounts\Service\Accounts\AccountsException;
class VerifyIdentitiesHandler extends MultiShopHandler
{
/**
* @param VerifyIdentitiesCommand $command
*
* @return void
*/
public function handle(VerifyIdentitiesCommand $command)
{
$this->handleMulti(function ($multiShopId) use ($command) {
try {
$this->commandBus->handle(
(new VerifyIdentityCommand($multiShopId, false))
->withOrigin($command->origin)
->withSource($command->source)
);
} catch (RefreshTokenException $e) {
Logger::getInstance()->error($e->getMessage());
} catch (AccountsException $e) {
Logger::getInstance()->error($e->getMessage());
} catch (UnknownStatusException $e) {
Logger::getInstance()->error($e->getMessage());
}
});
}
}

View File

@@ -0,0 +1,124 @@
<?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\Account\CommandHandler;
use PrestaShop\Module\PsAccounts\Account\Command\VerifyIdentityCommand;
use PrestaShop\Module\PsAccounts\Account\Exception\RefreshTokenException;
use PrestaShop\Module\PsAccounts\Account\Exception\UnknownStatusException;
use PrestaShop\Module\PsAccounts\Account\ProofManager;
use PrestaShop\Module\PsAccounts\Account\Session\ShopSession;
use PrestaShop\Module\PsAccounts\Account\ShopUrl;
use PrestaShop\Module\PsAccounts\Account\StatusManager;
use PrestaShop\Module\PsAccounts\Log\Logger;
use PrestaShop\Module\PsAccounts\Provider\ShopProvider;
use PrestaShop\Module\PsAccounts\Service\Accounts\AccountsException;
use PrestaShop\Module\PsAccounts\Service\Accounts\AccountsService;
class VerifyIdentityHandler
{
/**
* @var AccountsService
*/
private $accountsService;
/**
* @var StatusManager
*/
private $statusManager;
/**
* @var ShopProvider
*/
private $shopProvider;
/**
* @var ShopSession
*/
private $shopSession;
/**
* @var ProofManager
*/
private $proofManager;
/**
* @param AccountsService $accountsService
* @param ShopProvider $shopProvider
* @param StatusManager $statusManager
* @param ShopSession $shopSession
* @param ProofManager $proofManager
*/
public function __construct(
AccountsService $accountsService,
ShopProvider $shopProvider,
StatusManager $statusManager,
ShopSession $shopSession,
ProofManager $proofManager
) {
$this->accountsService = $accountsService;
$this->shopProvider = $shopProvider;
$this->statusManager = $statusManager;
$this->shopSession = $shopSession;
$this->proofManager = $proofManager;
}
/**
* @param VerifyIdentityCommand $command
*
* @return void
*
* @throws RefreshTokenException
* @throws UnknownStatusException
* @throws AccountsException
*/
public function handle(VerifyIdentityCommand $command)
{
$shopId = $command->shopId;
$status = $this->statusManager->withSource($command->source)->getStatus();
$cloudShopUrl = ShopUrl::createFromStatus($status, $shopId);
if (!$command->force && $status->isVerified) {
return;
}
try {
if (!$command->force && !$cloudShopUrl->frontendUrlEquals($this->shopProvider->getUrl($shopId))) {
return;
}
} catch (\InvalidArgumentException $e) {
Logger::getInstance()->error($e->getMessage());
return;
}
$this->accountsService
->withOrigin($command->origin)
->withSource($command->source)
->verifyShopIdentity(
$this->statusManager->getCloudShopId(),
$this->shopSession->getValidToken(),
$this->shopProvider->getUrl($shopId),
$this->shopProvider->getName($shopId),
$this->proofManager->generateProof()
);
$this->statusManager->invalidateCache();
}
}

View File

@@ -0,0 +1,11 @@
<?php
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;

View File

@@ -0,0 +1,75 @@
<?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\Account\Dto;
use PrestaShop\Module\PsAccounts\Type\Dto;
class Shop extends Dto
{
/** @var int */
public $id;
/** @var string */
public $name;
/** @var string */
public $domain;
/** @var string */
public $domainSsl;
/** @var string */
public $physicalUri;
/** @var string */
public $virtualUri;
/** @var string */
public $frontUrl;
/** @var string */
public $uuid;
/** @var string */
public $publicKey;
/** @var string */
public $employeeId;
/** @var User */
public $user;
/** @var string */
public $url;
/** @var bool */
public $isLinkedV4;
/** @var bool */
public $unlinkedAuto;
public function __construct($values = [])
{
if (isset($values['user']) && is_array($values['user'])) {
$values['user'] = new User($values['user']);
} else {
$values['user'] = new User();
}
parent::__construct($values);
}
/**
* @return array|mixed
*/
public function jsonSerialize()
{
return array_merge(parent::jsonSerialize(), [
'user' => $this->user->jsonSerialize(),
]);
}
}

View File

@@ -0,0 +1,74 @@
<?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\Account\Dto;
use PrestaShop\Module\PsAccounts\Type\Dto;
class UpdateShop extends Dto
{
/**
* @var string
*/
public $shopId;
/**
* @var string
*/
public $name;
/**
* @var string
*/
public $virtualUri;
/**
* @var string
*/
public $physicalUri;
/**
* @var string
*/
public $domain;
/**
* @var string
*/
public $sslDomain;
/**
* @var string
*/
public $boBaseUrl;
/**
* @var string[]
*/
public $required = [
'shopId',
'name',
'virtualUri',
'physicalUri',
'domain',
'sslDomain',
'boBaseUrl',
];
}

View File

@@ -0,0 +1,33 @@
<?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\Account\Dto;
use PrestaShop\Module\PsAccounts\Type\Dto;
class User extends Dto
{
/** @var string */
public $email;
/** @var bool */
public $emailIsValidated;
/** @var string */
public $uuid;
}

View File

@@ -0,0 +1,11 @@
<?php
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;

View File

@@ -0,0 +1,25 @@
<?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\Account\Exception;
class RefreshTokenException extends \PrestaShop\Module\PsAccounts\Exception\RefreshTokenException
{
}

View File

@@ -0,0 +1,25 @@
<?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\Account\Exception;
class UnknownStatusException extends \Exception
{
}

View File

@@ -0,0 +1,11 @@
<?php
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;

View File

@@ -0,0 +1,70 @@
<?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\Account;
use PrestaShop\Module\PsAccounts\Repository\ConfigurationRepository;
class ProofManager
{
/**
* @var ConfigurationRepository
*/
private $configuration;
/**
* ManageProof constructor.
*
* @param ConfigurationRepository $configuration
*/
public function __construct(
ConfigurationRepository $configuration
) {
$this->configuration = $configuration;
}
/**
* @return string
*/
public function generateProof()
{
$proof = bin2hex(openssl_random_pseudo_bytes(32));
$this->configuration->updateShopProof($proof);
return $proof;
}
/**
* @return string|null
*/
public function getProof()
{
return $this->configuration->getShopProof();
}
/**
* @return void
*/
public function deleteProof()
{
$this->configuration->updateShopProof(null);
}
}

View File

@@ -0,0 +1,59 @@
<?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\Account\Query;
class GetContextQuery
{
/**
* @var string|null
*/
public $source;
/**
* @var int
*/
public $contextType;
/**
* @var int|null
*/
public $contextId;
/**
* @var bool
*/
public $refresh;
/**
* @param string|null $source
* @param int|null $contextType
* @param int|null $contextId
* @param bool $refresh
*/
public function __construct($source = null, $contextType = \Shop::CONTEXT_ALL, $contextId = null, $refresh = false)
{
$this->source = $source;
$this->contextType = $contextType;
$this->contextId = $contextId;
$this->refresh = $refresh;
}
}

View File

@@ -0,0 +1,11 @@
<?php
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;

View File

@@ -0,0 +1,73 @@
<?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\Account\QueryHandler;
use PrestaShop\Module\PsAccounts\Account\Query\GetContextQuery;
use PrestaShop\Module\PsAccounts\Provider\ShopProvider;
use PrestaShop\Module\PsAccounts\Service\Accounts\AccountsException;
use PrestaShop\Module\PsAccounts\Service\UpgradeService;
class GetContextHandler
{
/**
* @var ShopProvider
*/
private $shopProvider;
/**
* @var UpgradeService
*/
private $upgradeService;
/**
* @param ShopProvider $shopProvider
*/
public function __construct(
ShopProvider $shopProvider,
UpgradeService $upgradeService
) {
$this->shopProvider = $shopProvider;
$this->upgradeService = $upgradeService;
}
/**
* @param GetContextQuery $query
*
* @return array
*
* @throws AccountsException
*/
public function handle(GetContextQuery $query)
{
return [
'ps_accounts' => [
'last_succeeded_upgrade_version' => $this->upgradeService->getVersion(),
'module_version_from_files' => \Ps_accounts::VERSION,
],
'groups' => $this->shopProvider->getShops(
$query->source,
$query->contextType,
$query->contextId,
$query->refresh
),
];
}
}

View File

@@ -0,0 +1,11 @@
<?php
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;

View File

@@ -0,0 +1,131 @@
<?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\Account\Session\Firebase;
use PrestaShop\Module\PsAccounts\Account\Exception\RefreshTokenException;
use PrestaShop\Module\PsAccounts\Account\Session\Firebase;
use PrestaShop\Module\PsAccounts\Account\Session\Session;
use PrestaShop\Module\PsAccounts\Account\Session\SessionInterface;
use PrestaShop\Module\PsAccounts\Account\Session\ShopSession;
use PrestaShop\Module\PsAccounts\Account\Token\Token;
use PrestaShop\Module\PsAccounts\Log\Logger;
use PrestaShop\Module\PsAccounts\Service\Accounts\AccountsException;
use PrestaShop\Module\PsAccounts\Service\Accounts\AccountsService;
abstract class FirebaseSession extends Session implements SessionInterface
{
/**
* @var ShopSession
*/
protected $shopSession;
public function __construct(ShopSession $shopSession)
{
parent::__construct();
$this->shopSession = $shopSession;
}
/**
* @return AccountsService
*/
public function getAccountsService()
{
return $this->module->getService(AccountsService::class);
}
/**
* @return Firebase\OwnerSession
*/
public function getOwnerSession()
{
return $this->module->getService(Firebase\OwnerSession::class);
}
/**
* @return Firebase\ShopSession
*/
public function getShopSession()
{
return $this->module->getService(Firebase\ShopSession::class);
}
/**
* @param string $refreshToken
* @param array $scope
* @param array $audience
*
* @return Token
*
* @throws RefreshTokenException
*/
public function refreshToken($refreshToken = null, array $scope = [], array $audience = [])
{
try {
$token = $this->shopSession->getValidToken();
$cloudShopId = $this->getStatusManager()->getCloudShopId();
$this->refreshFirebaseTokens($cloudShopId, $token);
} catch (RefreshTokenException $e) {
Logger::getInstance()->error('Unable to get or refresh owner/shop token : ' . $e->getMessage());
throw $e;
}
return $this->getToken();
}
/**
* @param string $cloudShopId
* @param Token $token
*
* @return void
*
* @throws RefreshTokenException
*/
protected function refreshFirebaseTokens($cloudShopId, $token)
{
try {
$firebaseTokens = $this->getAccountsService()->firebaseTokens($cloudShopId, $token);
} catch (AccountsException $e) {
throw new RefreshTokenException($e->getMessage());
}
$shopToken = new Token(
$firebaseTokens->shop->token,
$firebaseTokens->shop->refreshToken
);
$pointOfContactToken = null;
if (isset($firebaseTokens->pointOfContact->token) && isset($firebaseTokens->pointOfContact->refreshToken)) {
$pointOfContactToken = new Token(
$firebaseTokens->pointOfContact->token,
$firebaseTokens->pointOfContact->refreshToken
);
}
// saving both tokens here
$this->getShopSession()->setToken((string) $shopToken->getJwt(), $shopToken->getRefreshToken());
if (isset($pointOfContactToken)) {
$this->getOwnerSession()->setToken((string) $pointOfContactToken->getJwt(), $pointOfContactToken->getRefreshToken());
}
}
}

View File

@@ -0,0 +1,76 @@
<?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\Account\Session\Firebase;
use PrestaShop\Module\PsAccounts\Account\Session\SessionInterface;
use PrestaShop\Module\PsAccounts\Account\Token\Token;
use PrestaShop\Module\PsAccounts\Repository\ConfigurationRepository;
class OwnerSession extends FirebaseSession implements SessionInterface
{
/**
* @var ConfigurationRepository
*/
protected $configurationRepository;
/**
* @param ConfigurationRepository $configurationRepository
* @param \PrestaShop\Module\PsAccounts\Account\Session\ShopSession $shopSession
*/
public function __construct(
ConfigurationRepository $configurationRepository,
\PrestaShop\Module\PsAccounts\Account\Session\ShopSession $shopSession
) {
$this->configurationRepository = $configurationRepository;
parent::__construct($shopSession);
}
/**
* @return Token
*/
public function getToken()
{
return new Token(
$this->configurationRepository->getUserFirebaseIdToken(),
$this->configurationRepository->getUserFirebaseRefreshToken()
);
}
/**
* @return void
*/
public function cleanup()
{
$this->configurationRepository->updateUserFirebaseIdToken('');
}
/**
* @param string $token
* @param string $refreshToken
*
* @return void
*/
public function setToken($token, $refreshToken = null)
{
$this->configurationRepository->updateUserFirebaseIdAndRefreshToken($token, $refreshToken);
}
}

View File

@@ -0,0 +1,76 @@
<?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\Account\Session\Firebase;
use PrestaShop\Module\PsAccounts\Account\Session\SessionInterface;
use PrestaShop\Module\PsAccounts\Account\Token\Token;
use PrestaShop\Module\PsAccounts\Repository\ConfigurationRepository;
class ShopSession extends FirebaseSession implements SessionInterface
{
/**
* @var ConfigurationRepository
*/
protected $configurationRepository;
/**
* @param ConfigurationRepository $configurationRepository
* @param \PrestaShop\Module\PsAccounts\Account\Session\ShopSession $shopSession
*/
public function __construct(
ConfigurationRepository $configurationRepository,
\PrestaShop\Module\PsAccounts\Account\Session\ShopSession $shopSession
) {
$this->configurationRepository = $configurationRepository;
parent::__construct($shopSession);
}
/**
* @return Token
*/
public function getToken()
{
return new Token(
$this->configurationRepository->getFirebaseIdToken(),
$this->configurationRepository->getFirebaseRefreshToken()
);
}
/**
* @return void
*/
public function cleanup()
{
$this->configurationRepository->updateFirebaseIdAndRefreshTokens('', '');
}
/**
* @param string $token
* @param string $refreshToken
*
* @return void
*/
public function setToken($token, $refreshToken = null)
{
$this->configurationRepository->updateFirebaseIdAndRefreshTokens($token, $refreshToken);
}
}

View File

@@ -0,0 +1,11 @@
<?php
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;

View File

@@ -0,0 +1,161 @@
<?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\Account\Session;
use PrestaShop\Module\PsAccounts\Account\Exception\RefreshTokenException;
use PrestaShop\Module\PsAccounts\Account\StatusManager;
use PrestaShop\Module\PsAccounts\Account\Token\NullToken;
use PrestaShop\Module\PsAccounts\Account\Token\Token;
use PrestaShop\Module\PsAccounts\Log\Logger;
abstract class Session implements SessionInterface
{
/**
* @var array
*/
protected $refreshTokenErrors = [];
/**
* @var \Ps_accounts
*/
protected $module;
public function __construct()
{
/* @phpstan-ignore-next-line */
$this->module = \Module::getInstanceByName('ps_accounts');
}
/**
* @deprecated use getValidToken instead
*
* @param bool $forceRefresh
*
* @return Token
*/
public function getOrRefreshToken($forceRefresh = false)
{
return $this->getValidToken($forceRefresh, false);
}
/**
* @param bool $forceRefresh
* @param bool $throw
* @param array $scope
* @param array $audience
*
* @return Token
*
* @throws RefreshTokenException
*/
public function getValidToken($forceRefresh = false, $throw = true, array $scope = [], array $audience = [])
{
/*
* Avoid multiple refreshToken calls in the same runtime:
* if it fails once, it will subsequently fail
*/
if ($e = $this->getRefreshTokenError(static::class)) {
$this->setToken('');
if ($throw) {
throw $e;
}
return $this->getToken();
}
if (true === $forceRefresh || false === $this->getToken()->isValid($scope, $audience)) {
try {
$this->refreshToken(null, $scope, $audience);
} catch (RefreshTokenException $e) {
$this->setToken('');
$this->setRefreshTokenError(static::class, $e);
if ($throw) {
throw $e;
}
Logger::getInstance()->error($e->getMessage());
}
}
return $this->getToken();
}
/**
* @return bool
*
* @deprecated since v8.0.0
*/
public function isEmailVerified()
{
try {
$jwt = $this->getToken()->getJwt();
// FIXME : just query sso api and don't refresh token everytime
if (!$jwt instanceof NullToken &&
!$jwt->claims()->get('email_verified')
) {
$jwt = $this->getValidToken(true)->getJwt();
}
return (bool) $jwt->claims()->get('email_verified');
} catch (RefreshTokenException $e) {
return false;
}
}
/**
* @param string $className
*
* @return RefreshTokenException|false
*/
public function getRefreshTokenError($className)
{
return isset($this->refreshTokenErrors[$className]) ? $this->refreshTokenErrors[$className] : false;
}
/**
* @return void
*/
public function resetRefreshTokenErrors()
{
$this->refreshTokenErrors = [];
}
/**
* @param string $className
* @param RefreshTokenException $e
*
* @return void
*/
protected function setRefreshTokenError($className, RefreshTokenException $e)
{
$this->refreshTokenErrors[$className] = $e;
}
/**
* @return StatusManager
*/
protected function getStatusManager()
{
return $this->module->getService(StatusManager::class);
}
}

View File

@@ -0,0 +1,83 @@
<?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\Account\Session;
use PrestaShop\Module\PsAccounts\Account\Exception\RefreshTokenException;
use PrestaShop\Module\PsAccounts\Account\Token\Token;
interface SessionInterface
{
/**
* @return Token
*/
public function getToken();
/**
* @param string $token
* @param string $refreshToken
*
* @return void
*/
public function setToken($token, $refreshToken = null);
/**
* Refreshes and saves refreshed token
*
* @param string|null $refreshToken
* @param array $scope
* @param array $audience
*
* @return Token
*
* @throws RefreshTokenException
*/
public function refreshToken($refreshToken = null, array $scope = [], array $audience = []);
/**
* @deprecated use getValidToken instead
*
* Get or refreshes and saves token
*
* @param bool $forceRefresh
*
* @return Token
*/
public function getOrRefreshToken($forceRefresh = false);
/**
* Get or refreshes and saves token
*
* @param bool $forceRefresh
* @param bool $throw
* @param array $scope
* @param array $audience
*
* @return Token
*
* @throws RefreshTokenException
*/
public function getValidToken($forceRefresh = false, $throw = true, array $scope = [], array $audience = []);
/**
* @return void
*/
public function cleanup();
}

View File

@@ -0,0 +1,196 @@
<?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\Account\Session;
use PrestaShop\Module\PsAccounts\Account\Exception\RefreshTokenException;
use PrestaShop\Module\PsAccounts\Account\Token\Token;
use PrestaShop\Module\PsAccounts\Hook\ActionShopAccessTokenRefreshAfter;
use PrestaShop\Module\PsAccounts\Repository\ConfigurationRepository;
use PrestaShop\Module\PsAccounts\Service\OAuth2\Exception\InvalidScopeException;
use PrestaShop\Module\PsAccounts\Service\OAuth2\OAuth2Exception;
use PrestaShop\Module\PsAccounts\Service\OAuth2\OAuth2ServerException;
use PrestaShop\Module\PsAccounts\Service\OAuth2\OAuth2Service;
use PrestaShop\Module\PsAccounts\Service\OAuth2\Resource\AccessToken;
class ShopSession extends Session implements SessionInterface
{
/**
* @var ConfigurationRepository
*/
protected $configurationRepository;
/**
* @var OAuth2Service
*/
protected $oAuth2Service;
/**
* @var string
*/
protected $tokenAudience;
/**
* @param ConfigurationRepository $configurationRepository
* @param OAuth2Service $oAuth2Service
* @param string $tokenAudience
*/
public function __construct(
ConfigurationRepository $configurationRepository,
OAuth2Service $oAuth2Service,
$tokenAudience
) {
parent::__construct();
$this->configurationRepository = $configurationRepository;
$this->oAuth2Service = $oAuth2Service;
$this->tokenAudience = $tokenAudience;
}
/**
* @param bool $forceRefresh
* @param bool $throw
* @param array|null $scope
* @param array|null $audience
*
* @return Token
*
* @throws RefreshTokenException
*/
public function getValidToken($forceRefresh = false, $throw = true, array $scope = null, array $audience = null)
{
if ($scope === null) {
$scope = ($this->getStatusManager()->identityVerified() ? [
'shop.verified',
] : []);
}
if ($audience === null) {
$audience = [
'store/' . $this->getStatusManager()->getCloudShopId(),
$this->tokenAudience,
];
}
return parent::getValidToken($forceRefresh, $throw, $scope, $audience);
}
/**
* @param string $refreshToken
* @param array $scope
* @param array $audience
*
* @return Token
*
* @throws RefreshTokenException
*/
public function refreshToken($refreshToken = null, array $scope = [], array $audience = [])
{
try {
try {
$accessToken = $this->getAccessToken($scope, $audience);
} catch (InvalidScopeException $e) {
$accessToken = $this->fallbackRefresh($e, 'shop.verified', $scope, $audience);
}
$this->setToken(
$accessToken->access_token,
$accessToken->refresh_token
);
$token = $this->getToken();
\Hook::exec(ActionShopAccessTokenRefreshAfter::getName(), ['token' => $token]);
return $token;
} catch (OAuth2Exception $e) {
} catch (\Exception $e) {
} catch (\Throwable $e) {
}
throw new RefreshTokenException('Unable to refresh shop token : ' . $e->getMessage(), 0, $e);
}
/**
* @return Token
*/
public function getToken()
{
return new Token($this->configurationRepository->getAccessToken());
}
/**
* @param string $token
* @param string $refreshToken
*
* @return void
*/
public function setToken($token, $refreshToken = null)
{
$this->configurationRepository->updateAccessToken($token);
}
/**
* @return void
*/
public function cleanup()
{
$this->configurationRepository->updateAccessToken('');
}
/**
* @param array $scope
* @param array $audience
*
* @return AccessToken
*
* @throws OAuth2Exception
*/
protected function getAccessToken(array $scope = [], array $audience = [])
{
return $this->oAuth2Service->getAccessTokenByClientCredentials($scope, $audience);
}
/**
* @param OAuth2ServerException $e
* @param string $filterScope
* @param array $scope
* @param array $audience
*
* @return AccessToken
*
* @throws OAuth2Exception
*/
protected function fallbackRefresh($e, $filterScope, array $scope, array $audience)
{
if (in_array($filterScope, $scope) &&
str_contains($e->getMessage(), $filterScope)
) {
$this->getStatusManager()->setIsVerified(false);
$this->resetRefreshTokenErrors();
$accessToken = $this->getAccessToken(array_filter($scope, function ($scp) use ($filterScope) {
return $scp !== $filterScope;
}), $audience);
} else {
throw $e;
}
return $accessToken;
}
}

View File

@@ -0,0 +1,11 @@
<?php
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;

View File

@@ -0,0 +1,161 @@
<?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\Account;
use PrestaShop\Module\PsAccounts\Service\Accounts\Resource\ShopStatus;
class ShopUrl
{
/**
* @var string
*/
private $backOfficeUrl;
/**
* @var string
*/
private $frontendUrl;
/**
* @var int
*/
private $multiShopId;
/**
* ShopUrl constructor.
*
* @param string $backOfficeUrl
* @param string $frontendUrl
* @param int $multiShopId
*/
public function __construct($backOfficeUrl, $frontendUrl, $multiShopId)
{
$this->backOfficeUrl = $backOfficeUrl;
$this->frontendUrl = $frontendUrl;
$this->multiShopId = $multiShopId;
}
/**
* @param array $shop
*
* @return ShopUrl
*/
public static function createFromShopData($shop)
{
$backOfficeUrl = explode('/index.php', $shop['url'])[0];
$frontendUrl = rtrim($shop['frontUrl'], '/');
$multiShopId = (int) $shop['id'];
return new ShopUrl($backOfficeUrl, $frontendUrl, $multiShopId);
}
/**
* @return string
*/
public function getBackOfficeUrl()
{
return $this->backOfficeUrl;
}
/**
* @return string
*/
public function getFrontendUrl()
{
return $this->frontendUrl;
}
/**
* @return int
*/
public function getMultiShopId()
{
return $this->multiShopId;
}
/**
* Check if the frontend URL has changed compared to the remote status
*
* @param ShopUrl $shopUrl
*
* @return bool
*
* @throws \InvalidArgumentException
*/
public function frontendUrlEquals(ShopUrl $shopUrl)
{
$cloudFrontendUrl = rtrim($this->frontendUrl, '/');
$localFrontendUrl = rtrim($shopUrl->getFrontendUrl(), '/');
if (empty($cloudFrontendUrl) || empty($localFrontendUrl)) {
throw new \InvalidArgumentException('Frontend URL cannot be empty');
}
return $cloudFrontendUrl === $localFrontendUrl;
}
/**
* Check if the backOffice URL has changed compared to the remote status
* Returns true if backOfficeUrl changed
*
* @param ShopUrl $shopUrl
*
* @return bool
*
* @throws \InvalidArgumentException
*/
public function backOfficeUrlEquals(ShopUrl $shopUrl)
{
$cloudBackOfficeUrl = rtrim($this->getBackOfficeUrl(), '/');
$localBackOfficeUrl = rtrim($shopUrl->getBackOfficeUrl(), '/');
if (empty($cloudBackOfficeUrl) || empty($localBackOfficeUrl)) {
throw new \InvalidArgumentException('BackOffice URL cannot be empty');
}
return $cloudBackOfficeUrl === $localBackOfficeUrl;
}
/**
* @return ShopUrl
*/
public function trimmed()
{
return new ShopUrl(
rtrim($this->getBackOfficeUrl(), '/'),
rtrim($this->getFrontendUrl(), '/'),
$this->getMultiShopId()
);
}
/**
* Create a new ShopUrl from the status
*
* @param ShopStatus $status
* @param int $multiShopId
*
* @return ShopUrl
*/
public static function createFromStatus(ShopStatus $status, $multiShopId)
{
return new ShopUrl($status->backOfficeUrl, $status->frontendUrl, $multiShopId);
}
}

View File

@@ -0,0 +1,408 @@
<?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\Account;
use DateTime;
use PrestaShop\Module\PsAccounts\Account\Exception\RefreshTokenException;
use PrestaShop\Module\PsAccounts\Account\Exception\UnknownStatusException;
use PrestaShop\Module\PsAccounts\Account\Session\ShopSession;
use PrestaShop\Module\PsAccounts\Log\Logger;
use PrestaShop\Module\PsAccounts\Repository\ConfigurationRepository;
use PrestaShop\Module\PsAccounts\Service\Accounts\AccountsException;
use PrestaShop\Module\PsAccounts\Service\Accounts\AccountsService;
use PrestaShop\Module\PsAccounts\Service\Accounts\Resource\ShopStatus;
use PrestaShop\Module\PsAccounts\Traits\WithOriginAndSourceTrait;
/**
* @method $this withThrowException(bool $throwException)
* @method bool getThrowException(bool $restoreDefault = true)
* @method void resetThrowException()
*/
class StatusManager
{
use WithOriginAndSourceTrait {
getDefaults as WithOriginAndSourceTrait_getDefaults;
}
/**
* Status Cache TTL in seconds
*/
const CACHE_TTL = 30;
/**
* Infinite Status Cache
*/
const CACHE_TTL_INFINITE = -1;
/**
* @var ConfigurationRepository
*/
private $repository;
/**
* @var ShopSession
*/
private $shopSession;
/**
* @var AccountsService
*/
private $accountsService;
/**
* @var bool
*/
private $throwException;
/**
* @param ShopSession $shopSession
* @param AccountsService $accountsService
* @param ConfigurationRepository $repository
*/
public function __construct(
ShopSession $shopSession,
AccountsService $accountsService,
ConfigurationRepository $repository
) {
$this->repository = $repository;
$this->shopSession = $shopSession;
$this->accountsService = $accountsService;
$this->resetProperties();
}
/**
* @return array
*/
public function getDefaults()
{
return array_merge($this->WithOriginAndSourceTrait_getDefaults(), [
'throwException' => false,
]);
}
/**
* @return bool
*/
public function identityCreated()
{
return !empty($this->getCloudShopId());
}
/**
* @param bool $cachedStatus
*
* @return bool
*/
public function identityVerified($cachedStatus = true)
{
try {
return $this->getStatus($cachedStatus)->isVerified;
} catch (UnknownStatusException $e) {
return false;
}
}
/**
* @param bool $cachedOnly
* @param int $cacheTtl
*
* @return ShopStatus
*
* @throws AccountsException
* @throws RefreshTokenException
* @throws UnknownStatusException
*/
public function getStatus($cachedOnly = false, $cacheTtl = self::CACHE_TTL)
{
$handleException = function ($e) {
Logger::getInstance()->error($e->getMessage());
if ($this->getThrowException(false)) {
throw $e;
}
};
if (!$cachedOnly) {
try {
$cachedShopStatus = $this->getCachedStatus();
} catch (UnknownStatusException $e) {
$cachedShopStatus = null;
}
if (!$cachedShopStatus ||
$this->cacheInvalidated($cachedShopStatus) ||
$this->cacheExpired($cachedShopStatus, $cacheTtl)
) {
try {
$this->upsetCachedStatus(new CachedShopStatus([
'isValid' => true,
'updatedAt' => date('Y-m-d H:i:s'),
'shopStatus' => $this->accountsService
->withSource($this->getSource())
->shopStatus(
$this->getCloudShopId(),
$this->shopSession->getValidToken()
),
]));
} catch (AccountsException $e) {
$handleException($e);
} catch (RefreshTokenException $e) {
$handleException($e);
}
}
}
return $this->getCachedStatus()->shopStatus;
}
/**
* @return void
*/
public function invalidateCache()
{
$this->upsetCachedStatus(new CachedShopStatus([
'isValid' => false,
]));
}
/**
* @param CachedShopStatus $cachedStatus
*
* @return bool
*/
public function cacheInvalidated(CachedShopStatus $cachedStatus = null)
{
try {
$cachedStatus = $cachedStatus ?: $this->getCachedStatus();
$isValid = $cachedStatus->isValid;
} catch (UnknownStatusException $e) {
$isValid = false;
}
return !$isValid;
}
/**
* @param CachedShopStatus $cachedStatus
* @param int $cacheTtl
*
* @return bool
*/
public function cacheExpired(CachedShopStatus $cachedStatus = null, $cacheTtl = self::CACHE_TTL)
{
try {
//$dateUpd = $this->getCacheDateUpd();
$cachedStatus = $cachedStatus ?: $this->getCachedStatus();
$dateUpd = $cachedStatus->updatedAt;
return $dateUpd instanceof DateTime &&
$cacheTtl != self::CACHE_TTL_INFINITE &&
time() - $dateUpd->getTimestamp() >= $cacheTtl;
} catch (UnknownStatusException $e) {
return true;
}
}
// /**
// * @return \DateTime|null
// */
// public function getCacheDateUpd()
// {
// return $this->repository->getCachedShopStatusDateUpd();
// }
/**
* @param bool $cachedStatus
*
* @return string|null
*/
public function getCloudShopId($cachedStatus = true)
{
try {
return $this->getStatus($cachedStatus)->cloudShopId;
} catch (UnknownStatusException $e) {
return null;
}
}
/**
* @param string $cloudShopId
*
* @return void
*/
public function setCloudShopId($cloudShopId)
{
$this->upsetCachedStatus(new CachedShopStatus([
'shopStatus' => [
'cloudShopId' => $cloudShopId,
],
]));
}
/**
* @param bool $cachedStatus
*
* @return string|null
*/
public function getPointOfContactUuid($cachedStatus = true)
{
try {
return $this->getStatus($cachedStatus)->pointOfContactUuid;
} catch (UnknownStatusException $e) {
return null;
}
}
/**
* @param string $pointOfContactUuid
*
* @return void
*/
public function setPointOfContactUuid($pointOfContactUuid)
{
$this->upsetCachedStatus(new CachedShopStatus([
'shopStatus' => [
'pointOfContactUuid' => $pointOfContactUuid,
],
]));
}
/**
* @param bool $cachedStatus
*
* @return string|null
*/
public function getPointOfContactEmail($cachedStatus = true)
{
try {
return $this->getStatus($cachedStatus)->pointOfContactEmail;
} catch (UnknownStatusException $e) {
return null;
}
}
/**
* @param string $pointOfContactEmail
*
* @return void
*/
public function setPointOfContactEmail($pointOfContactEmail)
{
$this->upsetCachedStatus(new CachedShopStatus([
'shopStatus' => [
'pointOfContactEmail' => $pointOfContactEmail,
],
]));
}
/**
* @param bool $isVerified
*
* @return void
*/
public function setIsVerified($isVerified)
{
$this->upsetCachedStatus(new CachedShopStatus([
'shopStatus' => [
'isVerified' => (bool) $isVerified,
],
]));
}
/**
* @param ShopStatus $status
*
* @return void
*/
public function restoreStatus(ShopStatus $status)
{
$this->upsetCachedStatus(new CachedShopStatus([
'isValid' => true,
'updatedAt' => date('Y-m-d H:i:s'),
'shopStatus' => $status,
]));
}
/**
* @return void
*/
public function clearStatus()
{
$this->upsetCachedStatus(new CachedShopStatus([
'shopStatus' => [
'isVerified' => false,
'cloudShopId' => '',
'pointOfContactUuid' => '',
'pointOfContactEmail' => '',
'frontendUrl' => '',
'backOfficeUrl' => '',
'shopVerificationErrorCode' => '',
],
]));
$this->invalidateCache();
}
/**
* @return CachedShopStatus
*
* @throws UnknownStatusException
*/
protected function getCachedStatus()
{
$status = $this->repository->getCachedShopStatus();
if (!$status) {
throw new UnknownStatusException('Unknown status');
}
return new CachedShopStatus(json_decode($status, true));
}
/**
* @param CachedShopStatus $cachedShopStatus
*
* @return void
*/
protected function setCachedStatus(CachedShopStatus $cachedShopStatus)
{
$this->repository->updateCachedShopStatus(json_encode($cachedShopStatus->toArray()) ?: null);
$this->repository->updateShopUuid($cachedShopStatus->shopStatus->cloudShopId);
}
/**
* @param CachedShopStatus $cachedShopStatus
* @param bool $all all fields or only explicitly initialized fields
*
* @return void
*/
protected function upsetCachedStatus(CachedShopStatus $cachedShopStatus, $all = false)
{
try {
$this->setCachedStatus(new CachedShopStatus(array_replace_recursive(
$this->getCachedStatus()->toArray(),
$cachedShopStatus->toArray($all)
)));
} catch (UnknownStatusException $e) {
$this->setCachedStatus($cachedShopStatus);
}
}
}

View File

@@ -0,0 +1,32 @@
<?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\Account\Token;
class NullToken extends \PrestaShop\Module\PsAccounts\Vendor\Lcobucci\JWT\Token
{
/**
* @return string
*/
public function toString()
{
return '';
}
}

View File

@@ -0,0 +1,192 @@
<?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\Account\Token;
use PrestaShop\Module\PsAccounts\Log\Logger;
use PrestaShop\Module\PsAccounts\Vendor\Lcobucci\JWT\Parser;
use PrestaShop\Module\PsAccounts\Vendor\Lcobucci\JWT\Token\InvalidTokenStructure;
class Token
{
const ID_OWNER_CLAIM = 'sub';
/**
* @var string
*/
private $token;
/**
* @var string
*/
private $refreshToken;
/**
* @param string $token
* @param string $refreshToken
*/
public function __construct($token, $refreshToken = null)
{
$this->token = $token;
$this->refreshToken = $refreshToken;
}
/**
* @return NullToken|\PrestaShop\Module\PsAccounts\Vendor\Lcobucci\JWT\Token
*/
public function getJwt()
{
return $this->parseToken($this->token);
}
/**
* @return string
*/
public function getRefreshToken()
{
return $this->refreshToken;
}
/**
* @return bool
*/
public function isExpired()
{
$token = $this->getJwt();
return $token->isExpired(new \DateTime());
}
/**
* @param array $scope
*
* @return bool
*/
public function hasScope(array $scope)
{
if ($scope === []) {
return true;
}
$claims = $this->getJwt()->claims();
if (!$claims->has('scp')) {
return false;
}
$scp = $claims->get('scp');
return count(array_intersect($scope, $scp)) == count($scope);
}
/**
* @param array $audience
*
* @return bool
*/
public function hasAudience(array $audience)
{
if ($audience === []) {
return true;
}
$claims = $this->getJwt()->claims();
if (!$claims->has('aud')) {
return false;
}
$aud = $claims->get('aud');
return count(array_intersect($audience, $aud)) == count($audience);
}
/**
* @param array $scope
* @param array $audience
*
* @return bool
*/
public function isValid(array $scope, array $audience)
{
$isValid = true;
if ($this->isExpired()) {
Logger::getInstance()->info(__METHOD__ . ': token isExpired ');
$isValid = false;
}
if ($isValid && !$this->hasScope($scope)) {
Logger::getInstance()->info(__METHOD__ . ': token scope invalid ');
$isValid = false;
}
if ($isValid && !$this->hasAudience($audience)) {
Logger::getInstance()->info(__METHOD__ . ': token audience invalid ');
$isValid = false;
}
return $isValid;
}
/**
* @return string|null
*/
public function getUuid()
{
return $this->getJwt()->claims()->get(static::ID_OWNER_CLAIM);
}
/**
* @return string|null
*/
public function getEmail()
{
// return $this->configuration->getFirebaseEmail();
return $this->getJwt()->claims()->get('email');
}
/**
* @return string
*/
public function __toString()
{
return (string) $this->token;
}
/**
* @param string $token
*
* @return \PrestaShop\Module\PsAccounts\Vendor\Lcobucci\JWT\Token
*/
protected function parseToken($token)
{
try {
return (new Parser())->parse((string) $token);
} catch (InvalidTokenStructure $e) {
return $this->getNullToken();
}
}
/**
* @return \PrestaShop\Module\PsAccounts\Vendor\Lcobucci\JWT\Token
*/
protected function getNullToken()
{
//return new \Lcobucci\JWT\Token([], ['exp' => new \DateTime()]);
return new NullToken([], ['exp' => new \DateTime()]);
}
}

View File

@@ -0,0 +1,11 @@
<?php
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;

View File

@@ -0,0 +1,11 @@
<?php
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;

View File

@@ -0,0 +1,67 @@
<?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\AccountLogin\Exception;
use PrestaShop\Module\PsAccounts\Service\OAuth2\Resource\UserInfo;
class AccountLoginException extends \Exception
{
/**
* @var UserInfo|null
*/
protected $user;
/**
* @var string
*/
protected $type = 'error_other';
/**
* @param string $message
* @param UserInfo|null $user
* @param \Exception $previous
*/
public function __construct(
$message = '',
UserInfo $user = null,
\Exception $previous = null
) {
parent::__construct($message, 0, $previous);
$this->user = $user;
}
/**
* @return UserInfo|null
*/
public function getUser()
{
return $this->user;
}
/**
* @return string
*/
public function getType()
{
return $this->type;
}
}

View File

@@ -0,0 +1,41 @@
<?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\AccountLogin\Exception;
use PrestaShop\Module\PsAccounts\Service\OAuth2\Resource\UserInfo;
class EmailNotVerifiedException extends AccountLoginException
{
/**
* @param string $message
* @param UserInfo|null $user
* @param \Exception $previous
*/
public function __construct(
$message = 'Your account email is not verified',
UserInfo $user = null,
\Exception $previous = null
) {
parent::__construct($message, $user, $previous);
$this->type = 'email_not_verified';
}
}

View File

@@ -0,0 +1,41 @@
<?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\AccountLogin\Exception;
use PrestaShop\Module\PsAccounts\Service\OAuth2\Resource\UserInfo;
class EmployeeNotFoundException extends AccountLoginException
{
/**
* @param string $message
* @param UserInfo|null $user
* @param \Exception $previous
*/
public function __construct(
$message = 'The email address is not associated to a PrestaShop backoffice account.',
UserInfo $user = null,
\Exception $previous = null
) {
parent::__construct($message, $user, $previous);
$this->type = 'employee_not_found';
}
}

View File

@@ -0,0 +1,41 @@
<?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\AccountLogin\Exception;
use PrestaShop\Module\PsAccounts\Service\OAuth2\Resource\UserInfo;
class Oauth2LoginException extends AccountLoginException
{
/**
* @param string $message
* @param UserInfo|null $user
* @param \Exception $previous
*/
public function __construct(
$message = 'OAuth2 error',
UserInfo $user = null,
\Exception $previous = null
) {
parent::__construct($message, $user, $previous);
$this->type = 'error_from_hydra';
}
}

View File

@@ -0,0 +1,11 @@
<?php
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;

View File

@@ -0,0 +1,131 @@
<?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\AccountLogin\Middleware;
use Exception;
use PrestaShop\Module\PsAccounts\AccountLogin\OAuth2LogoutTrait;
use PrestaShop\Module\PsAccounts\AccountLogin\OAuth2Session;
use PrestaShop\Module\PsAccounts\Log\Logger;
use PrestaShop\Module\PsAccounts\Service\OAuth2\OAuth2Client;
use PrestaShop\Module\PsAccounts\Service\OAuth2\OAuth2Service;
use PrestaShop\Module\PsAccounts\Service\PsAccountsService;
use Ps_accounts;
class Oauth2Middleware
{
use OAuth2LogoutTrait;
/**
* @var PsAccountsService
*/
private $psAccountsService;
/**
* @var OAuth2Session
*/
private $oAuth2Session;
/**
* @var OAuth2Service
*/
private $oAuth2Service;
public function __construct(Ps_accounts $module)
{
$this->psAccountsService = $module->getService(PsAccountsService::class);
$this->oAuth2Session = $module->getService(OAuth2Session::class);
$this->oAuth2Service = $module->getService(OAuth2Service::class);
}
/**
* @return void
*
* @deprecated since v7.1.2
*/
public function execute()
{
try {
if (isset($_GET['logout'])) {
$this->executeLogout();
}
} catch (Exception $e) {
Logger::getInstance()->err($e->getMessage());
}
}
/**
* @return void
*/
public function handleLogout()
{
try {
if (isset($_GET['logout'])) {
$this->executeLogout();
}
} catch (Exception $e) {
Logger::getInstance()->err($e->getMessage());
}
}
/**
* @return void
*
* @throws Exception
*/
public function executeLogout()
{
if ($this->psAccountsService->getLoginActivated() &&
!isset($_GET[OAuth2Client::getQueryLogoutCallbackParam()])) {
$this->oauth2Logout();
}
$this->getOauth2Session()->clear();
}
/**
* @return OAuth2Service
*/
protected function getOAuth2Service()
{
return $this->oAuth2Service;
}
/**
* @return OAuth2Session
*
* @throws Exception
*/
protected function getOauth2Session()
{
return $this->oAuth2Session;
}
/**
* @return bool
*
* @throws Exception
*/
protected function isOauth2LogoutEnabled()
{
// return $this->module->hasParameter('ps_accounts.oauth2_url_session_logout');
// FIXME
return true;
}
}

View File

@@ -0,0 +1,11 @@
<?php
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;

View File

@@ -0,0 +1,448 @@
<?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\AccountLogin;
use Employee;
use PrestaShop\Module\PsAccounts\AccountLogin\Exception\AccountLoginException;
use PrestaShop\Module\PsAccounts\AccountLogin\Exception\EmailNotVerifiedException;
use PrestaShop\Module\PsAccounts\AccountLogin\Exception\EmployeeNotFoundException;
use PrestaShop\Module\PsAccounts\AccountLogin\Exception\Oauth2LoginException;
use PrestaShop\Module\PsAccounts\Context\ShopContext;
use PrestaShop\Module\PsAccounts\Entity\EmployeeAccount;
use PrestaShop\Module\PsAccounts\Log\Logger;
use PrestaShop\Module\PsAccounts\Repository\EmployeeAccountRepository;
use PrestaShop\Module\PsAccounts\Service\AnalyticsService;
use PrestaShop\Module\PsAccounts\Service\OAuth2\OAuth2Exception;
use PrestaShop\Module\PsAccounts\Service\OAuth2\OAuth2Service;
use PrestaShop\Module\PsAccounts\Service\OAuth2\Resource\AccessToken;
use PrestaShop\Module\PsAccounts\Service\OAuth2\Resource\UserInfo;
use PrestaShop\Module\PsAccounts\Service\PsAccountsService;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Tools;
trait OAuth2LoginTrait
{
/**
* @return OAuth2Service
*/
abstract protected function getOAuth2Service();
/**
* @param AccessToken $accessToken
*
* @return bool
*/
abstract protected function initUserSession(AccessToken $accessToken);
/**
* @return mixed
*/
abstract protected function redirectAfterLogin();
/**
* @return mixed
*/
abstract protected function logout();
/**
* @return mixed
*/
abstract protected function onLoginFailedRedirect();
/**
* @return SessionInterface
*/
abstract protected function getSession();
/**
* @return OAuth2Session
*/
abstract protected function getOauth2Session();
/**
* @return AnalyticsService
*/
abstract protected function getAnalyticsService();
/**
* @return PsAccountsService
*/
abstract protected function getPsAccountsService();
/**
* @return string
*/
abstract protected function getSignupUrl();
/**
* @return mixed
*
* @throws EmailNotVerifiedException
* @throws EmployeeNotFoundException
* @throws Oauth2LoginException
* @throws \Exception
*/
public function oauth2Login()
{
$shopId = Tools::getValue('shop_id', $this->getShopId() ?: \Context::getContext()->shop->id);
/** @var ShopContext $shopContext */
$shopContext = $this->module->getService(ShopContext::class);
return $shopContext->execInShopContext($shopId, function () use ($shopId) {
// FIXME: rework multishop context management
//\Shop::setContext(\Shop::CONTEXT_SHOP, $shopId);
$apiClient = $this->getOAuth2Service();
//$this->getSession()->start();
$session = $this->getSession();
$oauth2Session = $this->getOauth2Session();
$returnTo = Tools::getValue($this->getReturnToParam());
$error = Tools::getValue('error', '');
$state = Tools::getValue('state', '');
$code = Tools::getValue('code', '');
$action = Tools::getValue('action', 'login');
$source = Tools::getValue('source', 'ps_accounts');
$forceSignup = Tools::getValue('forceSignup', false);
if (!empty($error)) {
// Got an error, probably user denied access
throw new \Exception('Got error: ' . $error);
// If we don't have an authorization code then get one
} elseif (empty($code)) {
// cleanup existing accessToken
$oauth2Session->clear();
$this->setReturnTo($returnTo);
$this->setOAuthAction($action);
$this->setSource($source);
$this->setShopId($shopId);
$this->setForceSignup($forceSignup);
$this->oauth2Redirect(Tools::getValue('locale', 'en'), $shopId);
// Check given state against previously stored one to mitigate CSRF attack
} elseif (empty($state) || ($session->has('oauth2state') && $state !== $session->get('oauth2state'))) {
$session->remove('oauth2state');
throw new \Exception('Invalid state');
} else {
$this->assertValidCode($code);
try {
$accessToken = $apiClient->getAccessTokenByAuthorizationCode(
$code,
$this->getSession()->get('oauth2pkceCode'),
[],
[],
$shopId
);
} catch (OAuth2Exception $e) {
throw new Oauth2LoginException($e->getMessage(), null, $e);
}
if ($this->initUserSession($accessToken)) {
return $this->redirectAfterLogin();
}
}
});
}
/**
* @param string $locale
* @param int|null $shopId
*
* @return void
*
* @throws \Exception
*/
private function oauth2Redirect($locale, $shopId)
{
$apiClient = $this->getOAuth2Service();
$state = $apiClient->getRandomState();
$pkceCode = $apiClient->getRandomPkceCode();
$this->getSession()->set('oauth2state', $state);
$this->getSession()->set('oauth2pkceCode', $pkceCode);
$authorizationUrl = $apiClient->getAuthorizationUri(
$state,
$pkceCode,
'S256',
$locale,
'',
'login',
$shopId
);
// Redirect the user to the authorization URL.
header('Location: ' . $authorizationUrl);
exit;
}
/**
* @param string $code
*
* @return void
*/
private function assertValidCode($code)
{
if (!preg_match('/^[^\s\"\';\(\)]+$/', $code)) {
throw new \InvalidArgumentException('Invalid code');
}
}
/**
* @param string $msg
*
* @return void
*
* @throws \Exception
*/
private function oauth2ErrorLog($msg)
{
Logger::getInstance()->error('[OAuth2] ' . $msg);
}
/**
* @return string
*
* @throws \Exception
*/
private function getReturnTo()
{
return $this->getSession()->get($this->getReturnToParam(), '');
}
/**
* @param string $returnTo
*
* @return void
*
* @throws \Exception
*/
private function setReturnTo($returnTo)
{
$this->getSession()->set($this->getReturnToParam(), $returnTo);
}
/**
* @return string
*/
private function getReturnToParam()
{
return 'return_to';
}
/**
* @return string
*/
private function getOAuthAction()
{
return $this->getSession()->get('oauth2action');
}
/**
* @param string $action
*
* @return void
*/
private function setOAuthAction($action)
{
$this->getSession()->set('oauth2action', $action);
}
/**
* @return string
*/
private function getSource()
{
return $this->getSession()->get('source');
}
/**
* @param string $source
*
* @return void
*/
private function setSource($source)
{
$this->getSession()->set('source', $source);
}
/**
* @return string
*/
private function getShopId()
{
return $this->getSession()->get('shopId');
}
/**
* @param string $shopId
*
* @return void
*/
private function setShopId($shopId)
{
$this->getSession()->set('shopId', $shopId);
}
/**
* @return bool
*/
private function getForceSignup()
{
return (bool) $this->getSession()->get('forceSignup', false);
}
/**
* @param bool $forceSignup
*
* @return void
*/
private function setForceSignup($forceSignup)
{
$this->getSession()->set('forceSignup', $forceSignup);
}
/**
* @param string $uid
* @param string $email
*
* @return Employee
*/
protected function getEmployeeByUidOrEmail($uid, $email)
{
$repository = new EmployeeAccountRepository();
try {
$employeeAccount = $repository->findByUid($uid);
/* @phpstan-ignore-next-line */
if ($employeeAccount) {
$employee = new Employee($employeeAccount->getEmployeeId());
} else {
$employeeAccount = new EmployeeAccount();
$employee = new Employee();
if (Employee::employeeExists($email)) {
$employee->getByEmail($email);
}
}
// Update account
if ($employee->id) {
$repository->upsert(
$employeeAccount
->setEmployeeId($employee->id)
->setUid($uid)
->setEmail($email)
);
}
} catch (\Exception $e) {
$employee = new Employee();
$employee->getByEmail($email);
}
return $employee;
}
/**
* @param AccountLoginException $e
*
* @return mixed
*/
protected function onLoginFailed(AccountLoginException $e)
{
if ($this->module->isShopEdition() && (
$e instanceof EmployeeNotFoundException ||
$e instanceof EmailNotVerifiedException
)) {
$this->trackEditionLoginFailedEvent($e);
}
$this->oauth2ErrorLog($e->getMessage());
$this->setLoginError($e->getType());
return $this->onLoginFailedRedirect();
}
/**
* @param mixed $error
*
* @return void
*/
protected function setLoginError($error)
{
$this->getSession()->set('loginError', $error);
}
/**
* @param UserInfo $user
*
* @return void
*/
protected function trackEditionLoginEvent(UserInfo $user)
{
if ($this->module->isShopEdition()) {
$this->getAnalyticsService()->identify(
$user->sub,
$user->name,
$user->email
);
$this->getAnalyticsService()->group(
$user->sub,
(string) $this->getPsAccountsService()->getShopUuid()
);
$this->getAnalyticsService()->trackUserSignedIntoApp(
$user->sub,
'smb-edition'
);
}
}
/**
* @param EmployeeNotFoundException|EmailNotVerifiedException $e
*
* @return void
*/
protected function trackEditionLoginFailedEvent($e)
{
$user = $e->getUser();
$this->getAnalyticsService()->identify(
$user->sub,
$user->name,
$user->email
);
$this->getAnalyticsService()->group(
$user->sub,
(string) $this->getPsAccountsService()->getShopUuid()
);
$this->getAnalyticsService()->trackBackOfficeSSOSignInFailed(
$user->sub,
$e->getType(),
$e->getMessage()
);
}
}

View File

@@ -0,0 +1,69 @@
<?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\AccountLogin;
use PrestaShop\Module\PsAccounts\Service\OAuth2\OAuth2Service;
trait OAuth2LogoutTrait
{
/**
* @return OAuth2Service
*/
abstract protected function getOAuth2Service();
/**
* @return OAuth2Session
*/
abstract protected function getOauth2Session();
/**
* @return bool
*/
abstract protected function isOauth2LogoutEnabled();
/**
* @return void
*
* @throws \Exception
*/
public function oauth2Logout()
{
if (!$this->isOauth2LogoutEnabled()) {
return;
}
$idToken = $this->getOauth2Session()->getIdToken();
if (empty($idToken)) {
return;
}
$OAuth2Service = $this->getOAuth2Service();
$logoutUrl = $OAuth2Service->getLogoutUri(
$OAuth2Service->getOAuth2Client()->getPostLogoutRedirectUri(),
$idToken
);
header('Location: ' . $logoutUrl);
exit;
}
}

View File

@@ -0,0 +1,144 @@
<?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\AccountLogin;
use PrestaShop\Module\PsAccounts\Account\Token\Token;
use PrestaShop\Module\PsAccounts\Service\OAuth2\OAuth2Client;
use PrestaShop\Module\PsAccounts\Service\OAuth2\OAuth2Exception;
use PrestaShop\Module\PsAccounts\Service\OAuth2\OAuth2Service;
use PrestaShop\Module\PsAccounts\Service\OAuth2\Resource\AccessToken;
use PrestaShop\Module\PsAccounts\Service\OAuth2\Resource\UserInfo;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
class OAuth2Session
{
const TOKEN_NAME = 'accessToken';
/**
* @var SessionInterface|mixed
*/
private $session;
/**
* @var OAuth2Service
*/
private $oAuth2Service;
/**
* @var OAuth2Client
*/
private $oauth2Client;
/**
* @param mixed $session
* @param OAuth2Service $oAuth2Service
* @param OAuth2Client $oauth2Client
*/
public function __construct($session, OAuth2Service $oAuth2Service, OAuth2Client $oauth2Client)
{
$this->session = $session;
$this->oAuth2Service = $oAuth2Service;
$this->oauth2Client = $oauth2Client;
}
/**
* @return string|null
*/
public function getOrRefreshAccessToken()
{
$token = $this->getTokenProvider();
if ($token instanceof AccessToken && (new Token($token->access_token))->isExpired()) {
try {
$token = $this->oAuth2Service->refreshAccessToken($token->refresh_token);
$this->setTokenProvider($token);
} catch (OAuth2Exception $e) {
}
}
return $this->getAccessToken();
}
/**
* @return string|null
*/
public function getIdToken()
{
$token = $this->getTokenProvider();
return ($token instanceof AccessToken) ? $token->id_token : null;
}
/**
* @return string|null
*/
public function getAccessToken()
{
$token = $this->getTokenProvider();
return ($token instanceof AccessToken) ? $token->access_token : null;
}
/**
* @param AccessToken $token
*
* @return void
*/
public function setTokenProvider(AccessToken $token)
{
$this->session->set(self::TOKEN_NAME, $token);
}
/**
* @return bool
*/
public function isAuthenticated()
{
return $this->session->has(self::TOKEN_NAME);
}
/**
* @return UserInfo
*/
public function getUserInfo()
{
return $this->oAuth2Service->getUserInfo($this->getAccessToken());
}
/**
* @return void
*/
public function clear()
{
$this->session->remove(self::TOKEN_NAME);
}
/**
* @return AccessToken|null
*/
private function getTokenProvider()
{
if (!$this->oauth2Client->exists()) {
$this->clear();
}
return $this->session->get(self::TOKEN_NAME);
}
}

View File

@@ -0,0 +1,11 @@
<?php
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;

View File

@@ -0,0 +1,289 @@
<?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\Adapter;
use PrestaShop\Module\PsAccounts\Log\Logger;
class Configuration
{
/**
* @var int
*/
private $idShop = null;
/**
* @var int
*/
private $idShopGroup = null;
/**
* @var int
*/
private $idLang = null;
/**
* Configuration constructor.
*
* @param \Context $context
*/
public function __construct(\Context $context)
{
$this->setIdShop((int) $context->shop->id);
$this->setIdShopGroup((int) $context->shop->id_shop_group);
//$this->setIdLang((int) $context->language->id);
}
/**
* @return int
*/
public function getIdShop()
{
return $this->idShop;
}
/**
* @param int $idShop
*
* @return void
*/
public function setIdShop($idShop)
{
$this->idShop = $idShop;
}
/**
* @return int
*/
public function getIdShopGroup()
{
return $this->idShopGroup;
}
/**
* @param int $idShopGroup
*
* @return void
*/
public function setIdShopGroup($idShopGroup)
{
$this->idShopGroup = $idShopGroup;
}
/**
* @return int
*/
public function getIdLang()
{
return $this->idLang;
}
/**
* @param int $idLang
*
* @return void
*/
public function setIdLang($idLang)
{
$this->idLang = $idLang;
}
/**
* @param string $key
* @param string|bool $default
* @param bool $cached
*
* @return mixed
*
* @throws \PrestaShopDatabaseException
* @throws \PrestaShopException
*/
public function get($key, $default = false, $cached = true)
{
if ($cached) {
return $this->getRaw($key, $this->idLang, $this->idShopGroup, $this->idShop, $default);
} else {
// FIXME: idLang ??
// FIXME: beware in single shop context idShop must be set
return $this->getUncached($key, $this->idShopGroup, $this->idShop, $default);
}
}
/**
* @param string $key
* @param int|null $idLang
* @param int|null $idShopGroup
* @param int|null $idShop
* @param string|bool $default
*
* @return mixed
*/
protected function getRaw($key, $idLang = null, $idShopGroup = null, $idShop = null, $default = false)
{
$value = \Configuration::get($key, $idLang, $idShopGroup, $idShop);
return $value ?: ($default !== false ? $default : $value);
}
/**
* @param string $key
* @param string|array $values
* @param bool $html
*
* @return mixed
*/
public function set($key, $values, $html = false)
{
return $this->setRaw($key, $values, $html, $this->idShopGroup, $this->idShop);
}
/**
* @param string $key
* @param string|array $values
* @param bool $html
* @param int|null $idShopGroup
* @param int|null $idShop
*
* @return bool
*/
protected function setRaw($key, $values, $html = false, $idShopGroup = null, $idShop = null)
{
return \Configuration::updateValue($key, $values, $html, $idShopGroup, $idShop);
}
/**
* @param string $key
*
* @return mixed
*/
public function getGlobal($key)
{
return \Configuration::getGlobalValue($key);
}
/**
* @param string $key
* @param string|array $values
* @param bool $html
*
* @return void
*/
public function setGlobal($key, $values, $html = false)
{
\Configuration::updateGlobalValue($key, $values, $html);
}
/**
* @param string $key
* @param int|null $idShopGroup
* @param int|null $idShop
* @param string|bool $default
*
* @return mixed
*/
public function getUncached($key, $idShopGroup = null, $idShop = null, $default = false)
{
try {
return $this->getUncachedConfiguration($key, $idShopGroup, $idShop)->value;
} catch (\Exception $e) {
Logger::getInstance()->error(__METHOD__ . ': ' . $e->getMessage());
return $default;
}
}
/**
* @param string $key
* @param int|null $idShopGroup
* @param int|null $idShop
*
* @return \Configuration
*
* @throw \Exception
*/
public function getUncachedConfiguration($key, $idShopGroup = null, $idShop = null)
{
if (!$this->isMultishopActive()) {
// To avoid making 3 calls to the database in the single shop context
$idShopGroup = $idShop = null;
$id = \Configuration::getIdByName($key, $idShopGroup, $idShop);
} else {
// mimic the condition of the original \Configuration::get method
$id = \Configuration::getIdByName($key, 0, $idShop);
if (!$id) {
$id = \Configuration::getIdByName($key, $idShopGroup, 0);
}
if (!$id) {
$id = \Configuration::getIdByName($key, 0, 0);
}
}
if ($id > 0) {
$found = (new \Configuration($id));
$found->clearCache();
return $found;
}
throw new \Exception('Configuration entry not found: ' . $key . '|grp:' . $idShopGroup . '|shop:' . $idShop);
}
/**
* @param string $key
*
* @return \DateTime|null
*/
public function getDateUpd($key)
{
try {
$entry = $this->getUncachedConfiguration(
$key,
$this->getIdShopGroup(),
$this->getIdShop()
);
return new \DateTime($entry->date_upd);
} catch (\Exception $e) {
Logger::getInstance()->error(__METHOD__ . ': ' . $e->getMessage());
return null;
}
}
/**
* is multi-shop active "right now"
*
* @return bool
*/
public function isMultishopActive()
{
//return \Shop::isFeatureActive();
return \Db::getInstance()->getValue('SELECT value FROM `' . _DB_PREFIX_ . 'configuration` WHERE `name` = "PS_MULTISHOP_FEATURE_ACTIVE"')
&& (\Db::getInstance()->getValue('SELECT COUNT(*) FROM ' . _DB_PREFIX_ . 'shop') > 1);
}
/**
* @return int
*/
public function getMainShopId()
{
return (int) \Db::getInstance()->getValue('SELECT value FROM ' . _DB_PREFIX_ . "configuration WHERE name = 'PS_SHOP_DEFAULT'");
}
}

View File

@@ -0,0 +1,61 @@
<?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\Adapter;
use PrestaShop\Module\PsAccounts\Type\Enum;
class ConfigurationKeys extends Enum
{
const PSX_UUID_V4 = 'PSX_UUID_V4';
const PS_ACCOUNTS_LOGIN_ENABLED = 'PS_ACCOUNTS_LOGIN_ENABLED';
const PS_ACCOUNTS_OAUTH2_CLIENT_ID = 'PS_ACCOUNTS_OAUTH2_CLIENT_ID';
const PS_ACCOUNTS_OAUTH2_CLIENT_SECRET = 'PS_ACCOUNTS_OAUTH2_CLIENT_SECRET';
const PS_ACCOUNTS_ACCESS_TOKEN = 'PS_ACCOUNTS_ACCESS_TOKEN';
const PS_ACCOUNTS_LAST_UPGRADE = 'PS_ACCOUNTS_LAST_UPGRADE';
const PS_ACCOUNTS_SHOP_PROOF = 'PS_ACCOUNTS_SHOP_PROOF';
const PS_ACCOUNTS_CACHED_SHOP_STATUS = 'PS_ACCOUNTS_SHOP_STATUS';
const PS_ACCOUNTS_VALIDATION_LEEWAY = 'PS_ACCOUNTS_VALIDATION_LEEWAY';
/** @deprecated */
const PS_ACCOUNTS_FIREBASE_ID_TOKEN = 'PS_ACCOUNTS_FIREBASE_ID_TOKEN';
/* @deprecated */
const PS_ACCOUNTS_FIREBASE_REFRESH_TOKEN = 'PS_ACCOUNTS_FIREBASE_REFRESH_TOKEN';
/* @deprecated */
const PS_ACCOUNTS_USER_FIREBASE_ID_TOKEN = 'PS_ACCOUNTS_USER_FIREBASE_ID_TOKEN';
/* @deprecated */
const PS_ACCOUNTS_USER_FIREBASE_REFRESH_TOKEN = 'PS_ACCOUNTS_USER_FIREBASE_REFRESH_TOKEN';
/* @deprecated */
const PS_ACCOUNTS_USER_FIREBASE_UUID = 'PS_ACCOUNTS_USER_FIREBASE_UUID';
/* @deprecated */
const PS_ACCOUNTS_FIREBASE_EMAIL = 'PS_ACCOUNTS_FIREBASE_EMAIL';
/* @deprecated */
const PS_ACCOUNTS_EMPLOYEE_ID = 'PS_ACCOUNTS_EMPLOYEE_ID';
/* @deprecated */
const PS_CHECKOUT_SHOP_UUID_V4 = 'PS_CHECKOUT_SHOP_UUID_V4';
/* @deprecated */
const PS_PSX_FIREBASE_ID_TOKEN = 'PS_PSX_FIREBASE_ID_TOKEN';
/* @deprecated */
const PS_PSX_FIREBASE_REFRESH_TOKEN = 'PS_PSX_FIREBASE_REFRESH_TOKEN';
/* @deprecated */
const PS_PSX_FIREBASE_REFRESH_DATE = 'PS_PSX_FIREBASE_REFRESH_DATE';
/* @deprecated */
const PS_PSX_FIREBASE_EMAIL = 'PS_PSX_FIREBASE_EMAIL';
}

View File

@@ -0,0 +1,227 @@
<?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\Adapter;
use PrestaShop\Module\PsAccounts\Context\ShopContext;
/**
* Link adapter
*/
class Link
{
/**
* @var ShopContext
*/
private $shopContext;
/**
* Link object
*
* @var \Link
*/
private $link;
/**
* @param ShopContext $shopContext
* @param \Link|null $link
*/
public function __construct(
ShopContext $shopContext,
\Link $link = null
) {
if (null === $link) {
$link = new \Link();
}
$this->shopContext = $shopContext;
$this->link = $link;
}
/**
* Adapter for getAdminLink from prestashop link class
*
* @param string $controller controller name
* @param bool $withToken include or not the token in the url
* @param array $sfRouteParams
* @param array $params
* @param int|null $shopId generate uri for a specific multishop id
*
* @return string
*/
public function getAdminLink($controller, $withToken = true, $sfRouteParams = [], $params = [], $shopId = null)
{
// Cannot generate admin link from front
if (!defined('_PS_ADMIN_DIR_')) {
return '';
}
if ($this->shopContext->isShop17()) {
$uri = $this->link->getAdminLink($controller, $withToken, $sfRouteParams, $params);
} else {
$uri = $this->getAdminLink16($controller, $withToken, $params);
}
if (!$withToken) {
// FIXME: getAdminLink still adds the token (sometimes)
$uri = preg_replace('/&_token=[^&]*/', '', $uri);
}
if ($shopId) {
$uri = $this->fixVirtualUri($uri, $shopId);
}
return $uri;
}
/**
* @param int|null $shopId
* @param bool|null $ssl
* @param bool $relativeProtocol
*
* @return string
*/
public function getAdminBaseLink($shopId = null, $ssl = null, $relativeProtocol = false)
{
/* @phpstan-ignore-next-line */
if (method_exists($this->link, 'getAdminBaseLink')) {
return $this->link->getAdminBaseLink($shopId, $ssl, $relativeProtocol);
} else {
return $this->getAdminBaseLink16($shopId, $ssl, $relativeProtocol);
}
}
/**
* @param string $controller
* @param bool $withToken
* @param array $params
* @param int $shopId
*
* @return string
*/
public function getAdminLink16($controller, $withToken, array $params, $shopId = null)
{
$paramsAsString = '';
foreach ($params as $key => $value) {
$paramsAsString .= "&$key=$value";
}
return $this->getAdminBaseLink16($shopId) .
basename(_PS_ADMIN_DIR_) . '/' . // admin path
$this->link->getAdminLink($controller, $withToken) .
$paramsAsString;
}
/**
* @param int|null $shopId
* @param bool|null $ssl
* @param bool $relativeProtocol
*
* @return string
*/
public function getAdminBaseLink16($shopId = null, $ssl = null, $relativeProtocol = false)
{
$path = __PS_BASE_URI__; // physical + virtual
if ($shopId) {
$shop = new \Shop($shopId);
$path = $shop->physical_uri . $shop->virtual_uri;
}
return \Tools::getShopDomainSsl(true) . $path;
}
/**
* @return \Link
*/
public function getLink()
{
return $this->link;
}
/**
* @param bool $withToken
*
* @return string
*/
public function getDashboardLink($withToken = false)
{
return $this->getAdminLink('AdminDashboard', false);
}
/**
* @param int $shopId
* @param bool $withToken
* @param string $moduleName
*
* @return string
*/
public function getModuleContentsLink($shopId, $withToken = false, $moduleName = 'ps_accounts')
{
return $this->getAdminLink(
'AdminModules',
$withToken,
[],
[
'configure' => $moduleName,
'setShopContext' => 's-' . $shopId,
]
);
}
/**
* @param string $link
*
* @return string
*/
public function cleanSlashes($link)
{
$link = preg_replace('@^(http|https)://@', '\1:SCHEME_SLASHES', $link);
$link = preg_replace('/\/+/', '/', $link);
return preg_replace('@^(http|https):SCHEME_SLASHES@', '\1://', $link);
}
/**
* @param string $link
*
* @return string
*/
public function getTrailingSlash($link)
{
return preg_match('/\/(\?|$)/', $link) ? '/' : '';
}
/**
* @param string $uri
* @param int $shopId
*
* @return string
*/
private function fixVirtualUri($uri, $shopId)
{
$shop = new \Shop($shopId);
return preg_replace(
'@^(https://[^/]+)' . preg_quote($shop->physical_uri, '@') . '.*' . preg_quote(basename(_PS_ADMIN_DIR_), '@') . '@',
//'$1' . $shop->physical_uri . basename(_PS_ADMIN_DIR_),
'https://' . $shop->domain_ssl . $shop->physical_uri . basename(_PS_ADMIN_DIR_),
$uri
);
}
}

View File

@@ -0,0 +1,11 @@
<?php
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;

View File

@@ -0,0 +1,52 @@
<?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\Api\Client;
use PrestaShop\Module\PsAccounts\Service\Accounts\AccountsService;
/**
* @deprecated since v8.0.0 in favor of PrestaShop\Module\PsAccounts\Service\Accounts\AccountsService
*/
class AccountsClient
{
/**
* @var AccountsService
*/
protected $accountsService;
/**
* @param AccountsService $accountService
*/
public function __construct(AccountsService $accountService)
{
$this->accountsService = $accountService;
}
/**
* @param string $idToken
*
* @return array
*/
public function verifyToken($idToken)
{
return $this->accountsService->verifyToken($idToken)->toLegacy();
}
}

View File

@@ -0,0 +1,93 @@
<?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\Api\Client;
use PrestaShop\Module\PsAccounts\Http\Client\ClientConfig;
use PrestaShop\Module\PsAccounts\Http\Client\Curl\Client;
use PrestaShop\Module\PsAccounts\Http\Client\Factory;
use PrestaShop\Module\PsAccounts\Http\Client\Response;
class ExternalAssetsClient
{
/**
* @var \Ps_accounts
*/
private $module;
/**
* @var Client
*/
private $client;
/**
* @var array
*/
protected $clientConfig;
/**
* @param array $config
*/
public function __construct(array $config)
{
/** @var \Ps_accounts $module */
$module = \Module::getInstanceByName('ps_accounts');
$this->module = $module;
$this->clientConfig = array_merge([
ClientConfig::NAME => static::class,
ClientConfig::HEADERS => $this->getHeaders(),
], $config);
}
/**
* @return Client
*/
private function getClient()
{
if (null === $this->client) {
$this->client = (new Factory())->create($this->clientConfig);
}
return $this->client;
}
/**
* @param array $additionalHeaders
*
* @return array
*/
private function getHeaders($additionalHeaders = [])
{
return array_merge([
'Accept' => 'application/json',
], $additionalHeaders);
}
/**
* @return Response
*/
public function getTestimonials()
{
return $this->getClient()->get(
$this->module->getParameter('ps_accounts.testimonials_url')
);
}
}

View File

@@ -0,0 +1,139 @@
<?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\Api\Client;
use PrestaShop\Module\PsAccounts\Http\Client\ClientConfig;
use PrestaShop\Module\PsAccounts\Http\Client\Curl\Client;
use PrestaShop\Module\PsAccounts\Http\Client\Factory;
use PrestaShop\Module\PsAccounts\Http\Client\Request;
use PrestaShop\Module\PsAccounts\Provider\ShopProvider;
use PrestaShop\Module\PsAccounts\Service\PsAccountsService;
/**
* Handle call api Services
*
* @deprecated since v7.0.0
*/
class ServicesBillingClient
{
/**
* @var Client
*/
private $client;
/**
* ServicesBillingClient constructor.
*
* @param string $apiUrl
* @param PsAccountsService $psAccountsService
* @param ShopProvider $shopProvider
* @param Client|null $client
*
* @throws \PrestaShopException
*/
public function __construct(
$apiUrl,
PsAccountsService $psAccountsService,
ShopProvider $shopProvider,
Client $client = null
) {
$shopId = $shopProvider->getCurrentShop()['id'];
$token = $psAccountsService->getOrRefreshToken();
// Client can be provided for tests
if (null === $client) {
$client = (new Factory())->create([
ClientConfig::BASE_URI => $apiUrl,
ClientConfig::NAME => static::class,
ClientConfig::HEADERS => [
// Commented, else does not work anymore with API.
//'Content-Type' => 'application/vnd.accounts.v1+json', // api version to use
'Accept' => 'application/json',
'Authorization' => 'Bearer ' . (string) $token,
'Shop-Id' => $shopId,
'Module-Version' => \Ps_accounts::VERSION, // version of the module
'Prestashop-Version' => _PS_VERSION_, // prestashop version
],
ClientConfig::TIMEOUT => 20,
ClientConfig::SSL_CHECK => true,
]);
}
$this->client = $client;
}
/**
* @param mixed $shopUuidV4
*
* @return array
*/
public function getBillingCustomer($shopUuidV4)
{
return $this->client->get('/shops/' . $shopUuidV4)
->toLegacy();
}
/**
* @param mixed $shopUuidV4
* @param array $bodyHttp
*
* @return array
*/
public function createBillingCustomer($shopUuidV4, $bodyHttp)
{
return $this->client->post(
'/shops/' . $shopUuidV4,
[
Request::FORM => $bodyHttp,
]
)->toLegacy();
}
/**
* @param mixed $shopUuidV4
* @param string $module
*
* @return array
*/
public function getBillingSubscriptions($shopUuidV4, $module)
{
return $this->client->get('/shops/' . $shopUuidV4 . '/subscriptions/' . $module)
->toLegacy();
}
/**
* @param mixed $shopUuidV4
* @param string $module
* @param array $bodyHttp
*
* @return array
*/
public function createBillingSubscriptions($shopUuidV4, $module, $bodyHttp)
{
return $this->client->post(
'/shops/' . $shopUuidV4 . '/subscriptions/' . $module,
[
Request::FORM => $bodyHttp,
]
)->toLegacy();
}
}

View File

@@ -0,0 +1,11 @@
<?php
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;

View File

@@ -0,0 +1,11 @@
<?php
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;

Some files were not shown because too many files have changed in this diff Show More