From 1a29ec8fa3d4c453716f08daa655372131a91397 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Schoenenberger?= Date: Thu, 5 Jan 2023 16:16:23 +0100 Subject: [PATCH 01/50] feat: allow disabling ssl cert check from config --- src/Provider/OAuth2/Oauth2ClientShopProvider.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/Provider/OAuth2/Oauth2ClientShopProvider.php b/src/Provider/OAuth2/Oauth2ClientShopProvider.php index 6c03c231c..67957f573 100644 --- a/src/Provider/OAuth2/Oauth2ClientShopProvider.php +++ b/src/Provider/OAuth2/Oauth2ClientShopProvider.php @@ -55,6 +55,12 @@ public function __construct(array $options = [], array $collaborators = []) $this->context = $module->getContext(); $this->configuration = $module->getService(ConfigurationRepository::class); + // Disable certificate verification from local configuration + $options['verify'] = $this->getParameter( + 'ps_accounts.check_api_ssl_cert', + true + ); + parent::__construct(array_merge([ 'clientId' => $this->configuration->getOauth2ClientId(), 'clientSecret' => $this->configuration->getOauth2ClientSecret(), @@ -62,6 +68,13 @@ public function __construct(array $options = [], array $collaborators = []) ], $options), $collaborators); } + protected function getAllowedClientOptions(array $options) + { + return array_merge(parent::getAllowedClientOptions($options), [ + 'verify', + ]); + } + public static function create(): PrestaShop { return new self(); From 92a58a9be48163c573a7875d5ecc59e6a4dbc08e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Schoenenberger?= Date: Thu, 5 Jan 2023 16:17:28 +0100 Subject: [PATCH 02/50] feat: analytics service --- composer.json | 3 +- composer.lock | 57 ++++++++++++++++++++++++- config/common.yml | 6 +++ config/config.yml.dist | 3 +- src/Service/AnalyticsService.php | 73 ++++++++++++++++++++++++++++++++ 5 files changed, 139 insertions(+), 3 deletions(-) create mode 100644 src/Service/AnalyticsService.php diff --git a/composer.json b/composer.json index 9692f5252..3604df74e 100644 --- a/composer.json +++ b/composer.json @@ -32,7 +32,8 @@ "prestashop/module-lib-service-container": "^1.2", "sentry/sentry": "^1.0", "league/oauth2-client": "^2.6", - "prestashopcorp/oauth2-prestashop": "dev-main" + "prestashopcorp/oauth2-prestashop": "dev-main", + "segmentio/analytics-php": "^1.8" }, "require-dev": { "phpunit/phpunit": "^8.5", diff --git a/composer.lock b/composer.lock index 2c19fe8de..428161755 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "ed14555b806ff75706a0827cb6ed8362", + "content-hash": "ca7afa28314387c23520c7a4f6f5facf", "packages": [ { "name": "guzzlehttp/guzzle", @@ -1237,6 +1237,61 @@ }, "time": "2019-03-08T08:55:37+00:00" }, + { + "name": "segmentio/analytics-php", + "version": "1.8.0", + "source": { + "type": "git", + "url": "https://github.com/segmentio/analytics-php.git", + "reference": "7e25b2f6094632bbfb79e33ca024d533899a2ffe" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/segmentio/analytics-php/zipball/7e25b2f6094632bbfb79e33ca024d533899a2ffe", + "reference": "7e25b2f6094632bbfb79e33ca024d533899a2ffe", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "overtrue/phplint": "^1.1", + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "^3.3" + }, + "bin": [ + "bin/analytics" + ], + "type": "library", + "autoload": { + "files": [ + "lib/Segment.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Segment.io ", + "homepage": "https://segment.com/" + } + ], + "description": "Segment Analytics PHP Library", + "homepage": "https://segment.com/libraries/php", + "keywords": [ + "analytics", + "analytics.js", + "segment", + "segmentio" + ], + "support": { + "issues": "https://github.com/segmentio/analytics-php/issues", + "source": "https://github.com/segmentio/analytics-php/tree/1.8.0" + }, + "time": "2021-05-31T22:44:22+00:00" + }, { "name": "sentry/sentry", "version": "1.11.0", diff --git a/config/common.yml b/config/common.yml index 2887d7ff3..5ef85f91a 100644 --- a/config/common.yml +++ b/config/common.yml @@ -81,6 +81,12 @@ services: - '@PrestaShop\Module\PsAccounts\Repository\ShopTokenRepository' - '@PrestaShop\Module\PsAccounts\Repository\ConfigurationRepository' + PrestaShop\Module\PsAccounts\Service\AnalyticsService: + class: PrestaShop\Module\PsAccounts\Service\AnalyticsService + public: true + arguments: + - '%ps_accounts.segment_write_key%' + ##################### # providers diff --git a/config/config.yml.dist b/config/config.yml.dist index 1388fa4a4..5ab26a77d 100644 --- a/config/config.yml.dist +++ b/config/config.yml.dist @@ -16,7 +16,8 @@ parameters: ps_accounts.sso_resend_verification_email_url: 'https://prestashop-newsso-staging.appspot.com/account/send-verification-email' ps_accounts.billing_api_url: 'https://billing-api.psessentials-integration.net' ps_accounts.sentry_credentials: 'https://4c7f6c8dd5aa405b8401a35f5cf26ada@o298402.ingest.sentry.io/5354585' - ps_accounts.segment_api_key: 'yO1sKx3Xe9upW4bRDoRXEB0TZEXQm2y3' + #ps_accounts.segment_api_key: 'yO1sKx3Xe9upW4bRDoRXEB0TZEXQm2y3' + ps_accounts.segment_write_key: '' ps_accounts.check_api_ssl_cert: false ps_accounts.verify_account_tokens: false ps_accounts.accounts_vue_cdn_url: 'https://unpkg.com/prestashop_accounts_vue_components@3/dist/psaccountsVue.umd.min.js' diff --git a/src/Service/AnalyticsService.php b/src/Service/AnalyticsService.php new file mode 100644 index 000000000..f23528348 --- /dev/null +++ b/src/Service/AnalyticsService.php @@ -0,0 +1,73 @@ +track([ + "event" => "User Signed Into App", + "userId"=> $userUid, + "context"=> [ + "groupId"=> $shopUid, + ], + "properties" => [ + "application"=> $application, + ], + ]); + } + + public function trackUserSignedIntoBackOfficeLocally($userUid, $userEmail, $shopUid) + { + $this->track([ + "event" => "User Signed Into Back Office Locally", + "email" => $userEmail, + "userId" => $userUid, + "context" => [ + "groupId" => $shopUid, + ], + ]); + } + + public function trackBackOfficeSSOSignInFailed($userUid, $shopUid, $type, $description) + { + $this->track([ + "event" => "Back Office SSO Sign In Failed", + "userId" => $userUid, + "context" => [ + "groupId" => $shopUid, + ], + "properties" => [ + "type" => $type, + "description" => $description, + ], + ]); + } + + public function page($path, $referrer, $search, $title, $url) + { + Segment::page([ + "path" => $path, + "referrer" => $referrer, + "search" => $search, + "title" => $title, + "url" => $url, + ]); + Segment::flush(); + } +} From bbacbf730f0ca565e59ec02612978501ef311989 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Schoenenberger?= Date: Thu, 5 Jan 2023 17:09:33 +0100 Subject: [PATCH 03/50] fix: set verify option the right way --- src/Provider/OAuth2/Oauth2ClientShopProvider.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Provider/OAuth2/Oauth2ClientShopProvider.php b/src/Provider/OAuth2/Oauth2ClientShopProvider.php index 67957f573..a9165eac7 100644 --- a/src/Provider/OAuth2/Oauth2ClientShopProvider.php +++ b/src/Provider/OAuth2/Oauth2ClientShopProvider.php @@ -56,9 +56,8 @@ public function __construct(array $options = [], array $collaborators = []) $this->configuration = $module->getService(ConfigurationRepository::class); // Disable certificate verification from local configuration - $options['verify'] = $this->getParameter( - 'ps_accounts.check_api_ssl_cert', - true + $options['verify'] = (bool) $this->module->getParameter( + 'ps_accounts.check_api_ssl_cert' ); parent::__construct(array_merge([ From c93d463da25802ec80dc7459c198983c000a084e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Schoenenberger?= Date: Thu, 5 Jan 2023 17:11:00 +0100 Subject: [PATCH 04/50] feat: start plugin event tracks --- config/config.yml.dist | 4 ++-- controllers/admin/AdminOAuth2PsAccountsController.php | 7 +++++++ src/Service/AnalyticsService.php | 1 - 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/config/config.yml.dist b/config/config.yml.dist index 5ab26a77d..4f8261bdb 100644 --- a/config/config.yml.dist +++ b/config/config.yml.dist @@ -16,8 +16,8 @@ parameters: ps_accounts.sso_resend_verification_email_url: 'https://prestashop-newsso-staging.appspot.com/account/send-verification-email' ps_accounts.billing_api_url: 'https://billing-api.psessentials-integration.net' ps_accounts.sentry_credentials: 'https://4c7f6c8dd5aa405b8401a35f5cf26ada@o298402.ingest.sentry.io/5354585' - #ps_accounts.segment_api_key: 'yO1sKx3Xe9upW4bRDoRXEB0TZEXQm2y3' - ps_accounts.segment_write_key: '' + ps_accounts.segment_api_key: 'yO1sKx3Xe9upW4bRDoRXEB0TZEXQm2y3' + ps_accounts.segment_write_key: 'UITzSdsFTgYsXaiJG09hsCiupUPwgJQB' ps_accounts.check_api_ssl_cert: false ps_accounts.verify_account_tokens: false ps_accounts.accounts_vue_cdn_url: 'https://unpkg.com/prestashop_accounts_vue_components@3/dist/psaccountsVue.umd.min.js' diff --git a/controllers/admin/AdminOAuth2PsAccountsController.php b/controllers/admin/AdminOAuth2PsAccountsController.php index 661905c78..951898f3b 100644 --- a/controllers/admin/AdminOAuth2PsAccountsController.php +++ b/controllers/admin/AdminOAuth2PsAccountsController.php @@ -25,6 +25,7 @@ use PrestaShop\Module\PsAccounts\Exception\EmployeeAccountNotFoundException; use PrestaShop\Module\PsAccounts\Provider\OAuth2\Oauth2ClientShopProvider; use PrestaShop\Module\PsAccounts\Provider\OAuth2\Oauth2LoginTrait; +use PrestaShop\Module\PsAccounts\Service\AnalyticsService; use PrestaShop\OAuth2\Client\Provider\PrestaShop; use PrestaShop\OAuth2\Client\Provider\PrestaShopUser; use PrestaShop\PrestaShop\Core\Exception\ContainerNotFoundException; @@ -127,6 +128,12 @@ private function initUserSession(PrestaShopUser $user): bool $cookie->write(); + if (true /* TODO: only track smb-edition */) { + /** @var AnalyticsService $analytics */ + $analytics = $this->module->getService(AnalyticsService::class); + $analytics->trackUserSignedIntoApp($user->getId(), $user->getEmail(), 'smb-edition'); + } + return true; } diff --git a/src/Service/AnalyticsService.php b/src/Service/AnalyticsService.php index f23528348..9c09916cb 100644 --- a/src/Service/AnalyticsService.php +++ b/src/Service/AnalyticsService.php @@ -8,7 +8,6 @@ class AnalyticsService { public function __construct(string $segmentWriteKey) { - // TODO: getShopEditionStatus Segment::init($segmentWriteKey); } From db2bcbe124c2b30da94929b7dabc8e7fbb084be6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Schoenenberger?= Date: Thu, 5 Jan 2023 18:01:09 +0100 Subject: [PATCH 05/50] feat: check for smb_edition and fix track parameters --- .../admin/AdminOAuth2PsAccountsController.php | 29 ++++++++++++++++--- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/controllers/admin/AdminOAuth2PsAccountsController.php b/controllers/admin/AdminOAuth2PsAccountsController.php index 951898f3b..f845f74bc 100644 --- a/controllers/admin/AdminOAuth2PsAccountsController.php +++ b/controllers/admin/AdminOAuth2PsAccountsController.php @@ -26,6 +26,7 @@ use PrestaShop\Module\PsAccounts\Provider\OAuth2\Oauth2ClientShopProvider; use PrestaShop\Module\PsAccounts\Provider\OAuth2\Oauth2LoginTrait; use PrestaShop\Module\PsAccounts\Service\AnalyticsService; +use PrestaShop\Module\PsAccounts\Service\PsAccountsService; use PrestaShop\OAuth2\Client\Provider\PrestaShop; use PrestaShop\OAuth2\Client\Provider\PrestaShopUser; use PrestaShop\PrestaShop\Core\Exception\ContainerNotFoundException; @@ -44,10 +45,27 @@ class AdminOAuth2PsAccountsController extends ModuleAdminController */ public $module; + /** + * @var AnalyticsService + */ + private $analyticsService; + + /** + * @var PsAccountsService + */ + private $psAccountsService; + + /** + * @throws PrestaShopException + * @throws Exception + */ public function __construct() { parent::__construct(); + $this->analyticsService = $this->module->getService(AnalyticsService::class); + $this->psAccountsService = $this->module->getService(PsAccountsService::class); + $this->ajax = true; $this->content_only = true; } @@ -128,10 +146,13 @@ private function initUserSession(PrestaShopUser $user): bool $cookie->write(); - if (true /* TODO: only track smb-edition */) { - /** @var AnalyticsService $analytics */ - $analytics = $this->module->getService(AnalyticsService::class); - $analytics->trackUserSignedIntoApp($user->getId(), $user->getEmail(), 'smb-edition'); + // Only track smb-edition + if (Module::isEnabled('smb_edition')) { + $this->analyticsService->trackUserSignedIntoApp( + $user->getId(), + $this->psAccountsService->getShopUuid(), + 'smb-edition' + ); } return true; From ac8b0ab4b13fbca6b43b61c6393f49282f316ed3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Schoenenberger?= Date: Thu, 5 Jan 2023 18:19:57 +0100 Subject: [PATCH 06/50] chore: phpstan & php-cs-fixer --- .../admin/AdminOAuth2PsAccountsController.php | 2 +- src/Service/AnalyticsService.php | 56 +++++++++---------- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/controllers/admin/AdminOAuth2PsAccountsController.php b/controllers/admin/AdminOAuth2PsAccountsController.php index f845f74bc..b50968ee3 100644 --- a/controllers/admin/AdminOAuth2PsAccountsController.php +++ b/controllers/admin/AdminOAuth2PsAccountsController.php @@ -150,7 +150,7 @@ private function initUserSession(PrestaShopUser $user): bool if (Module::isEnabled('smb_edition')) { $this->analyticsService->trackUserSignedIntoApp( $user->getId(), - $this->psAccountsService->getShopUuid(), + (string) $this->psAccountsService->getShopUuid() ?? null, 'smb-edition' ); } diff --git a/src/Service/AnalyticsService.php b/src/Service/AnalyticsService.php index 9c09916cb..a752b8659 100644 --- a/src/Service/AnalyticsService.php +++ b/src/Service/AnalyticsService.php @@ -11,61 +11,61 @@ public function __construct(string $segmentWriteKey) Segment::init($segmentWriteKey); } - public function track(array $properties) + public function track(array $properties): void { Segment::track($properties); Segment::flush(); } - public function trackUserSignedIntoApp($userUid, $shopUid, $application) + public function trackUserSignedIntoApp(string $userUid, ?string $shopUid, string $application): void { $this->track([ - "event" => "User Signed Into App", - "userId"=> $userUid, - "context"=> [ - "groupId"=> $shopUid, + 'event' => 'User Signed Into App', + 'userId' => $userUid, + 'context' => [ + 'groupId' => $shopUid, ], - "properties" => [ - "application"=> $application, + 'properties' => [ + 'application' => $application, ], ]); } - public function trackUserSignedIntoBackOfficeLocally($userUid, $userEmail, $shopUid) + public function trackUserSignedIntoBackOfficeLocally(string $userEmail, ?string $userUid, string $shopUid): void { $this->track([ - "event" => "User Signed Into Back Office Locally", - "email" => $userEmail, - "userId" => $userUid, - "context" => [ - "groupId" => $shopUid, + 'event' => 'User Signed Into Back Office Locally', + 'email' => $userEmail, + 'userId' => $userUid, + 'context' => [ + 'groupId' => $shopUid, ], ]); } - public function trackBackOfficeSSOSignInFailed($userUid, $shopUid, $type, $description) + public function trackBackOfficeSSOSignInFailed(string $userUid, ?string $shopUid, ?string $type, ?string $description): void { $this->track([ - "event" => "Back Office SSO Sign In Failed", - "userId" => $userUid, - "context" => [ - "groupId" => $shopUid, + 'event' => 'Back Office SSO Sign In Failed', + 'userId' => $userUid, + 'context' => [ + 'groupId' => $shopUid, ], - "properties" => [ - "type" => $type, - "description" => $description, + 'properties' => [ + 'type' => $type, + 'description' => $description, ], ]); } - public function page($path, $referrer, $search, $title, $url) + public function page(string $path, ?string $referrer, ?string $search, string $title, string $url): void { Segment::page([ - "path" => $path, - "referrer" => $referrer, - "search" => $search, - "title" => $title, - "url" => $url, + 'path' => $path, + 'referrer' => $referrer, + 'search' => $search, + 'title' => $title, + 'url' => $url, ]); Segment::flush(); } From 2b014ddffa9efb85a1c94e6f960c237f684ac526 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Schoenenberger?= Date: Mon, 9 Jan 2023 18:17:45 +0100 Subject: [PATCH 07/50] feat: local login tracking --- .../admin/AdminOAuth2PsAccountsController.php | 3 +- ps_accounts.php | 49 ++++++++++++++++--- 2 files changed, 42 insertions(+), 10 deletions(-) diff --git a/controllers/admin/AdminOAuth2PsAccountsController.php b/controllers/admin/AdminOAuth2PsAccountsController.php index b50968ee3..4578f88ee 100644 --- a/controllers/admin/AdminOAuth2PsAccountsController.php +++ b/controllers/admin/AdminOAuth2PsAccountsController.php @@ -146,8 +146,7 @@ private function initUserSession(PrestaShopUser $user): bool $cookie->write(); - // Only track smb-edition - if (Module::isEnabled('smb_edition')) { + if ($this->module->isShopEdition()) { $this->analyticsService->trackUserSignedIntoApp( $user->getId(), (string) $this->psAccountsService->getShopUuid() ?? null, diff --git a/ps_accounts.php b/ps_accounts.php index 12003cf42..fa847a740 100644 --- a/ps_accounts.php +++ b/ps_accounts.php @@ -49,6 +49,7 @@ class Ps_accounts extends Module 'actionObjectShopUrlUpdateAfter', 'displayDashboardTop', 'displayAccountUpdateWarning', + 'actionAdminLoginControllerLoginAfter', ]; /** @@ -189,7 +190,7 @@ public function getServiceContainer() { if (null === $this->serviceContainer) { $this->serviceContainer = new \PrestaShop\Module\PsAccounts\DependencyInjection\ServiceContainer( - // append version number to force cache generation (1.6 Core won't clear it) + // append version number to force cache generation (1.6 Core won't clear it) $this->name . str_replace(['.', '-'], '', $this->version), $this->getLocalPath(), $this->getModuleEnv() @@ -246,7 +247,7 @@ public function addCustomHooks($customHooks) foreach ($customHooks as $customHook) { $verify = true; - if ((bool) Hook::getIdByName($customHook['name']) === false) { + if ((bool)Hook::getIdByName($customHook['name']) === false) { $hook = new Hook(); $hook->name = $customHook['name']; $hook->title = $customHook['title']; @@ -345,7 +346,7 @@ private function renderAdminShopUrlWarningIfLinked($shopContext, $accountsServic return; } - $shopId = $shopContext->getShopIdFromShopUrlId((int) $_GET['id_shop_url']); + $shopId = $shopContext->getShopIdFromShopUrlId((int)$_GET['id_shop_url']); return $shopContext->execInShopContext($shopId, function () use ($accountsService) { if ($accountsService->isAccountLinked()) { @@ -446,7 +447,7 @@ public function hookActionObjectShopUrlUpdateAfter($params) /** @var \PrestaShop\Module\PsAccounts\Adapter\Link $link */ $link = $this->getService(\PrestaShop\Module\PsAccounts\Adapter\Link::class); - Cache::clean('Shop::setUrl_' . (int) $params['object']->id); + Cache::clean('Shop::setUrl_' . (int)$params['object']->id); $shop = new \Shop($params['object']->id); @@ -454,7 +455,7 @@ public function hookActionObjectShopUrlUpdateAfter($params) $sslDomain = $params['object']->domain_ssl; $response = $accountsApi->updateUserShop(new \PrestaShop\Module\PsAccounts\DTO\UpdateShop([ - 'shopId' => (string) $params['object']->id, + 'shopId' => (string)$params['object']->id, 'name' => $shop->name, 'domain' => 'http://' . $domain, 'sslDomain' => 'https://' . $sslDomain, @@ -525,7 +526,7 @@ public function hookActionObjectShopUpdateAfter($params) $sslDomain = $params['object']->domain_ssl; $response = $accountsApi->updateUserShop(new \PrestaShop\Module\PsAccounts\DTO\UpdateShop([ - 'shopId' => (string) $params['object']->id, + 'shopId' => (string)$params['object']->id, 'name' => $params['object']->name, 'domain' => 'http://' . $shop->domain, 'sslDomain' => 'https://' . $shop->domain_ssl, @@ -604,12 +605,39 @@ public function hookActionObjectShopDeleteBefore($params) return true; } + /** + * @param array $params + * + * @return void + */ + public function hookActionAdminLoginControllerLoginAfter($params) + { + /** @var Employee $employee */ + $employee = $params['employee']; + + /** @var \PrestaShop\Module\PsAccounts\Service\AnalyticsService $analyticsService */ + $analyticsService = $this->getService(\PrestaShop\Module\PsAccounts\Service\AnalyticsService::class); + + /** @var \PrestaShop\Module\PsAccounts\Service\PsAccountsService $psAccountsService */ + $psAccountsService = $this->getService(\PrestaShop\Module\PsAccounts\Service\PsAccountsService::class); + + $account = $psAccountsService->getEmployeeAccount(); + + if ($this->isShopEdition()) { + $analyticsService->trackUserSignedIntoBackOfficeLocally( + $account->getEmail(), + $account->getUid(), + $psAccountsService->getShopUuid() + ); + } + } + /** * @return string */ public function getModuleEnvVar() { - return strtoupper((string) $this->name) . '_ENV'; + return strtoupper((string)$this->name) . '_ENV'; } /** @@ -660,7 +688,7 @@ protected function loadAssets() $psAccountsPresenter = $this->getService(\PrestaShop\Module\PsAccounts\Presenter\PsAccountsPresenter::class); Media::addJsDef([ - 'contextPsAccounts' => $psAccountsPresenter->present((string) $this->name), + 'contextPsAccounts' => $psAccountsPresenter->present((string)$this->name), ]); } @@ -727,4 +755,9 @@ public function getCustomHooks() { return $this->customHooks; } + + public function isShopEdition(): bool + { + return Module::isEnabled('smb_edition'); + } } From 0b3cc3e0345636520d738e4054f50b7ae1be8e29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Schoenenberger?= Date: Mon, 9 Jan 2023 18:27:12 +0100 Subject: [PATCH 08/50] chore: phpstan & php-cs-fixer --- ps_accounts.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/ps_accounts.php b/ps_accounts.php index fa847a740..6c287cd3e 100644 --- a/ps_accounts.php +++ b/ps_accounts.php @@ -247,7 +247,7 @@ public function addCustomHooks($customHooks) foreach ($customHooks as $customHook) { $verify = true; - if ((bool)Hook::getIdByName($customHook['name']) === false) { + if ((bool) Hook::getIdByName($customHook['name']) === false) { $hook = new Hook(); $hook->name = $customHook['name']; $hook->title = $customHook['title']; @@ -346,7 +346,7 @@ private function renderAdminShopUrlWarningIfLinked($shopContext, $accountsServic return; } - $shopId = $shopContext->getShopIdFromShopUrlId((int)$_GET['id_shop_url']); + $shopId = $shopContext->getShopIdFromShopUrlId((int) $_GET['id_shop_url']); return $shopContext->execInShopContext($shopId, function () use ($accountsService) { if ($accountsService->isAccountLinked()) { @@ -447,7 +447,7 @@ public function hookActionObjectShopUrlUpdateAfter($params) /** @var \PrestaShop\Module\PsAccounts\Adapter\Link $link */ $link = $this->getService(\PrestaShop\Module\PsAccounts\Adapter\Link::class); - Cache::clean('Shop::setUrl_' . (int)$params['object']->id); + Cache::clean('Shop::setUrl_' . (int) $params['object']->id); $shop = new \Shop($params['object']->id); @@ -455,7 +455,7 @@ public function hookActionObjectShopUrlUpdateAfter($params) $sslDomain = $params['object']->domain_ssl; $response = $accountsApi->updateUserShop(new \PrestaShop\Module\PsAccounts\DTO\UpdateShop([ - 'shopId' => (string)$params['object']->id, + 'shopId' => (string) $params['object']->id, 'name' => $shop->name, 'domain' => 'http://' . $domain, 'sslDomain' => 'https://' . $sslDomain, @@ -526,7 +526,7 @@ public function hookActionObjectShopUpdateAfter($params) $sslDomain = $params['object']->domain_ssl; $response = $accountsApi->updateUserShop(new \PrestaShop\Module\PsAccounts\DTO\UpdateShop([ - 'shopId' => (string)$params['object']->id, + 'shopId' => (string) $params['object']->id, 'name' => $params['object']->name, 'domain' => 'http://' . $shop->domain, 'sslDomain' => 'https://' . $shop->domain_ssl, @@ -627,7 +627,7 @@ public function hookActionAdminLoginControllerLoginAfter($params) $analyticsService->trackUserSignedIntoBackOfficeLocally( $account->getEmail(), $account->getUid(), - $psAccountsService->getShopUuid() + (string) $psAccountsService->getShopUuid() ?? null ); } } @@ -637,7 +637,7 @@ public function hookActionAdminLoginControllerLoginAfter($params) */ public function getModuleEnvVar() { - return strtoupper((string)$this->name) . '_ENV'; + return strtoupper((string) $this->name) . '_ENV'; } /** @@ -688,7 +688,7 @@ protected function loadAssets() $psAccountsPresenter = $this->getService(\PrestaShop\Module\PsAccounts\Presenter\PsAccountsPresenter::class); Media::addJsDef([ - 'contextPsAccounts' => $psAccountsPresenter->present((string)$this->name), + 'contextPsAccounts' => $psAccountsPresenter->present((string) $this->name), ]); } From 1d9785a212e463cb238cf6095cad16fdcf066a8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Schoenenberger?= Date: Tue, 10 Jan 2023 14:18:06 +0100 Subject: [PATCH 09/50] feat: failed login tracking --- .../admin/AdminOAuth2PsAccountsController.php | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/controllers/admin/AdminOAuth2PsAccountsController.php b/controllers/admin/AdminOAuth2PsAccountsController.php index 4578f88ee..edc54986c 100644 --- a/controllers/admin/AdminOAuth2PsAccountsController.php +++ b/controllers/admin/AdminOAuth2PsAccountsController.php @@ -80,17 +80,13 @@ public function display(): void try { $this->oauth2Login(); } catch (IdentityProviderException $e) { - $this->oauth2ErrorLog($e->getMessage()); - $this->redirectWithError('error_from_hydra'); + $this->onLoginFailed( 'error_from_hydra', $e); } catch (EmployeeAccountEmailNotVerifiedException $e) { - $this->oauth2ErrorLog($e->getMessage()); - $this->redirectWithError('email_not_verified'); + $this->onLoginFailed( 'email_not_verified', $e); } catch (EmployeeAccountNotFoundException $e) { - $this->oauth2ErrorLog($e->getMessage()); - $this->redirectWithError('employee_not_found'); + $this->onLoginFailed( 'employee_not_found', $e); } catch (Exception $e) { - $this->oauth2ErrorLog($e->getMessage()); - $this->redirectWithError('error_other'); + $this->onLoginFailed( 'error_other', $e); } } @@ -211,6 +207,16 @@ private function redirectWithError(string $error): void ); } + private function onLoginFailed(string $type, Exception $e): void + { + $this->oauth2ErrorLog($e->getMessage()); + $this->redirectWithError($type); + + if ($this->module->isShopEdition()) { + $this->analyticsService->trackBackOfficeSSOSignInFailed(); + } + } + private function getProvider(): Oauth2ClientShopProvider { return $this->module->getService(PrestaShop::class); From f707c23cc511cf10dc6be15bcbdd1496b5ebd825 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Schoenenberger?= Date: Tue, 10 Jan 2023 18:49:22 +0100 Subject: [PATCH 10/50] refactor: account login exceptions and tracking --- .../admin/AdminOAuth2PsAccountsController.php | 57 +++++++++--------- .../AccountLogin/AccountLoginException.php | 60 +++++++++++++++++++ .../EmailNotVerifiedException.php | 34 +++++++++++ .../EmployeeNotFoundException.php | 34 +++++++++++ .../HydraErrorException.php} | 13 +++- .../OtherErrorException.php} | 13 +++- 6 files changed, 178 insertions(+), 33 deletions(-) create mode 100644 src/Exception/AccountLogin/AccountLoginException.php create mode 100644 src/Exception/AccountLogin/EmailNotVerifiedException.php create mode 100644 src/Exception/AccountLogin/EmployeeNotFoundException.php rename src/Exception/{EmployeeAccountNotFoundException.php => AccountLogin/HydraErrorException.php} (67%) rename src/Exception/{EmployeeAccountEmailNotVerifiedException.php => AccountLogin/OtherErrorException.php} (67%) diff --git a/controllers/admin/AdminOAuth2PsAccountsController.php b/controllers/admin/AdminOAuth2PsAccountsController.php index edc54986c..0f6a15084 100644 --- a/controllers/admin/AdminOAuth2PsAccountsController.php +++ b/controllers/admin/AdminOAuth2PsAccountsController.php @@ -21,8 +21,11 @@ use Doctrine\ORM\EntityManagerInterface; use League\OAuth2\Client\Provider\Exception\IdentityProviderException; use PrestaShop\Module\PsAccounts\Entity\EmployeeAccount; -use PrestaShop\Module\PsAccounts\Exception\EmployeeAccountEmailNotVerifiedException; -use PrestaShop\Module\PsAccounts\Exception\EmployeeAccountNotFoundException; +use PrestaShop\Module\PsAccounts\Exception\AccountLogin\AccountLoginException; +use PrestaShop\Module\PsAccounts\Exception\AccountLogin\EmailNotVerifiedException; +use PrestaShop\Module\PsAccounts\Exception\AccountLogin\EmployeeNotFoundException; +use PrestaShop\Module\PsAccounts\Exception\AccountLogin\HydraErrorException; +use PrestaShop\Module\PsAccounts\Exception\AccountLogin\OtherErrorException; use PrestaShop\Module\PsAccounts\Provider\OAuth2\Oauth2ClientShopProvider; use PrestaShop\Module\PsAccounts\Provider\OAuth2\Oauth2LoginTrait; use PrestaShop\Module\PsAccounts\Service\AnalyticsService; @@ -80,13 +83,11 @@ public function display(): void try { $this->oauth2Login(); } catch (IdentityProviderException $e) { - $this->onLoginFailed( 'error_from_hydra', $e); - } catch (EmployeeAccountEmailNotVerifiedException $e) { - $this->onLoginFailed( 'email_not_verified', $e); - } catch (EmployeeAccountNotFoundException $e) { - $this->onLoginFailed( 'employee_not_found', $e); + $this->onLoginFailed(new HydraErrorException(null, $e->getMessage())); + } catch (EmailNotVerifiedException | EmployeeNotFoundException $e) { + $this->onLoginFailed($e); } catch (Exception $e) { - $this->onLoginFailed( 'error_other', $e); + $this->onLoginFailed(new OtherErrorException(null, $e->getMessage())); } } @@ -96,8 +97,8 @@ public function display(): void * @return bool * * @throws ContainerNotFoundException - * @throws EmployeeAccountEmailNotVerifiedException - * @throws EmployeeAccountNotFoundException + * @throws EmailNotVerifiedException + * @throws EmployeeNotFoundException * @throws CoreException */ private function initUserSession(PrestaShopUser $user): bool @@ -112,9 +113,9 @@ private function initUserSession(PrestaShopUser $user): bool $context->employee->logout(); if (empty($emailVerified)) { - throw new EmployeeAccountEmailNotVerifiedException('Your account email is not verified'); + throw new EmailNotVerifiedException($user); } - throw new EmployeeAccountNotFoundException('The email address is not associated to a PrestaShop backoffice account.'); + throw new EmployeeNotFoundException($user); } $context->employee->remote_addr = (int) ip2long(Tools::getRemoteAddr()); @@ -192,31 +193,29 @@ private function getEmployeeByUidOrEmail(string $uid, string $email): Employee return $employee; } - /** - * @param string $error - * - * @return void - */ - private function redirectWithError(string $error): void + private function onLoginFailed(AccountLoginException $e): void { + if ($this->module->isShopEdition() && ( + $e instanceof EmployeeNotFoundException || + $e instanceof EmailNotVerifiedException + )) { + $this->analyticsService->trackBackOfficeSSOSignInFailed( + $e->getPrestaShopUser()->getId(), + (string) $this->psAccountsService->getShopUuid() ?? null, + $e->getType(), + $e->getMessage() + ); + } + + $this->oauth2ErrorLog($e->getMessage()); Tools::redirectAdmin( $this->context->link->getAdminLink('AdminLogin', true, [], [ 'logout' => 1, - 'loginError' => $error, + 'loginError' => $e->getType(), ]) ); } - private function onLoginFailed(string $type, Exception $e): void - { - $this->oauth2ErrorLog($e->getMessage()); - $this->redirectWithError($type); - - if ($this->module->isShopEdition()) { - $this->analyticsService->trackBackOfficeSSOSignInFailed(); - } - } - private function getProvider(): Oauth2ClientShopProvider { return $this->module->getService(PrestaShop::class); diff --git a/src/Exception/AccountLogin/AccountLoginException.php b/src/Exception/AccountLogin/AccountLoginException.php new file mode 100644 index 000000000..bc2987612 --- /dev/null +++ b/src/Exception/AccountLogin/AccountLoginException.php @@ -0,0 +1,60 @@ + + * @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\Exception\AccountLogin; + +use PrestaShop\OAuth2\Client\Provider\PrestaShopUser; + +abstract class AccountLoginException extends \Exception +{ + /** + * @var PrestaShopUser|null + */ + private $user; + + /** + * @var string + */ + private $type; + + public function __construct(?PrestaShopUser $user, string $message = '', string $type = '') + { + parent::__construct($message); + + $this->user = $user; + $this->type = $type; + } + + /** + * @return PrestaShopUser|null + */ + public function getPrestaShopUser(): ?PrestaShopUser + { + return $this->user; + } + + /** + * @return string + */ + public function getType(): string + { + return $this->type; + } +} diff --git a/src/Exception/AccountLogin/EmailNotVerifiedException.php b/src/Exception/AccountLogin/EmailNotVerifiedException.php new file mode 100644 index 000000000..c00069758 --- /dev/null +++ b/src/Exception/AccountLogin/EmailNotVerifiedException.php @@ -0,0 +1,34 @@ + + * @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\Exception\AccountLogin; + +use PrestaShop\OAuth2\Client\Provider\PrestaShopUser; + +class EmailNotVerifiedException extends AccountLoginException +{ + public function __construct( + ?PrestaShopUser $user, + string $message = 'Your account email is not verified', + string $type = 'email_not_verified' + ) { + parent::__construct($user, $message, $type); + } +} diff --git a/src/Exception/AccountLogin/EmployeeNotFoundException.php b/src/Exception/AccountLogin/EmployeeNotFoundException.php new file mode 100644 index 000000000..d9038e712 --- /dev/null +++ b/src/Exception/AccountLogin/EmployeeNotFoundException.php @@ -0,0 +1,34 @@ + + * @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\Exception\AccountLogin; + +use PrestaShop\OAuth2\Client\Provider\PrestaShopUser; + +class EmployeeNotFoundException extends AccountLoginException +{ + public function __construct( + ?PrestaShopUser $user, + string $message = 'The email address is not associated to a PrestaShop backoffice account.', + string $type = 'employee_not_found' + ) { + parent::__construct($user, $message, $type); + } +} diff --git a/src/Exception/EmployeeAccountNotFoundException.php b/src/Exception/AccountLogin/HydraErrorException.php similarity index 67% rename from src/Exception/EmployeeAccountNotFoundException.php rename to src/Exception/AccountLogin/HydraErrorException.php index 8dea74c71..e39fc2f2e 100644 --- a/src/Exception/EmployeeAccountNotFoundException.php +++ b/src/Exception/AccountLogin/HydraErrorException.php @@ -18,8 +18,17 @@ * @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0 */ -namespace PrestaShop\Module\PsAccounts\Exception; +namespace PrestaShop\Module\PsAccounts\Exception\AccountLogin; -class EmployeeAccountNotFoundException extends \Exception +use PrestaShop\OAuth2\Client\Provider\PrestaShopUser; + +class HydraErrorException extends AccountLoginException { + public function __construct( + ?PrestaShopUser $user, + string $message = 'Your account email is not verified', + string $type = 'error_from_hydra' + ) { + parent::__construct($user, $message, $type); + } } diff --git a/src/Exception/EmployeeAccountEmailNotVerifiedException.php b/src/Exception/AccountLogin/OtherErrorException.php similarity index 67% rename from src/Exception/EmployeeAccountEmailNotVerifiedException.php rename to src/Exception/AccountLogin/OtherErrorException.php index eca8c81b4..b5f41baf3 100644 --- a/src/Exception/EmployeeAccountEmailNotVerifiedException.php +++ b/src/Exception/AccountLogin/OtherErrorException.php @@ -18,8 +18,17 @@ * @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0 */ -namespace PrestaShop\Module\PsAccounts\Exception; +namespace PrestaShop\Module\PsAccounts\Exception\AccountLogin; -class EmployeeAccountEmailNotVerifiedException extends \Exception +use PrestaShop\OAuth2\Client\Provider\PrestaShopUser; + +class OtherErrorException extends AccountLoginException { + public function __construct( + ?PrestaShopUser $user, + string $message = 'Your account email is not verified', + string $type = 'error_other' + ) { + parent::__construct($user, $message, $type); + } } From 3e6027225277ecf859cb0e076dd6be0cff98576b Mon Sep 17 00:00:00 2001 From: Antoine Metifeu Date: Thu, 12 Jan 2023 09:09:02 +0100 Subject: [PATCH 11/50] fix: translations --- translations/en.php | 3 +-- views/templates/override/controllers/login/content.tpl | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/translations/en.php b/translations/en.php index 470a56121..8713fe859 100644 --- a/translations/en.php +++ b/translations/en.php @@ -39,8 +39,7 @@ $_MODULE['<{ps_accounts}prestashop>content_1ab1f34b16d32fa54b90ee0f91f39dfd'] = 'Welcome,'; $_MODULE['<{ps_accounts}prestashop>content_474684646f833216fdaf79c606af208b'] = 'Access your back office to manage your store.'; $_MODULE['<{ps_accounts}prestashop>content_6ed6a381a1de805e2b807f88a95faa2b'] = 'Go to the back office'; -$_MODULE['<{ps_accounts}prestashop>content_1483546116fd85ebd65dcc595c69e73e'] = 'Connect with another method'; -$_MODULE['<{ps_accounts}prestashop>content_653f49dc0e643470e7b4ae9855974bbd'] = 'The email address is not associated to a PrestaShop backoffice account. To learn more, go to the [1]FAQ[/1]'; +$_MODULE['<{ps_accounts}prestashop>content_8905a5daaa6744846452108776efa036'] = 'Connect with another method'; $_MODULE['<{ps_accounts}prestashop>content_729f27762821b8ec88f1a656be7dff72'] = 'You need to activate your account first by clicking the link in the email. If you need to receive a new activation link,[1]please click here[/1]'; $_MODULE['<{ps_accounts}prestashop>content_476ff05d1175f9a35d268828caf300f2'] = 'An error occured during login, please contact PrestaShop support'; $_MODULE['<{ps_accounts}prestashop>content_c8fc2e859e06da33e96d200b0106cfa3'] = 'You cannot access the back office with this account. Try another account or contact your administrator. [1]Go to Help Center[/1]'; diff --git a/views/templates/override/controllers/login/content.tpl b/views/templates/override/controllers/login/content.tpl index a8dfe7f2e..4b45f93ba 100755 --- a/views/templates/override/controllers/login/content.tpl +++ b/views/templates/override/controllers/login/content.tpl @@ -51,7 +51,7 @@ {l s='All the essentials for your business' mod='ps_accounts'}

- {l s='GMarketing, payment and performance analysis: the PrestaShop Essentials suite includes all the features you need to make your store successful.' mod='ps_accounts'} + {l s='Marketing, payment and performance analysis: the PrestaShop Essentials suite includes all the features you need to make your store successful.' mod='ps_accounts'}

From 1d7c6a267f9d182fef782caa61b1489e3b401a23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Schoenenberger?= Date: Thu, 12 Jan 2023 10:53:37 +0100 Subject: [PATCH 12/50] feat: login page tracking --- controllers/admin/AdminLoginController.php | 12 ++++ .../admin/AdminOAuth2PsAccountsController.php | 5 ++ src/Service/AnalyticsService.php | 57 ++++++++++++++++--- 3 files changed, 66 insertions(+), 8 deletions(-) diff --git a/controllers/admin/AdminLoginController.php b/controllers/admin/AdminLoginController.php index a3998ff8d..ec54ad414 100644 --- a/controllers/admin/AdminLoginController.php +++ b/controllers/admin/AdminLoginController.php @@ -18,6 +18,7 @@ * @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0 */ +use PrestaShop\Module\PsAccounts\Service\AnalyticsService; use PrestaShop\Module\PsAccounts\Service\PsAccountsService; /** @@ -51,6 +52,9 @@ class AdminLoginController extends AdminLoginControllerCore /** @var Ps_accounts */ private $psAccountsModule; + /** @var AnalyticsService */ + private $analyticsService; + /** * @throws Exception */ @@ -69,6 +73,8 @@ public function __construct() if (self::PS_ACCOUNTS_LOGIN_MODE_LOCAL !== $this->getPsAccountsLoginMode()) { $this->psAccountsLoginEnabled = $moduleService->getLoginActivated(); } + + $this->analyticsService = $this->psAccountsModule->getService(AnalyticsService::class); } /* @phpstan-ignore-next-line */ @@ -95,6 +101,12 @@ public function setMedia($isNewTheme = false) */ public function createTemplate($tpl_name) { + if ($this->psAccountsModule->isShopEdition()) { + $this->psAccountsLoginEnabled ? + $this->analyticsService->pageAccountsBoLogin() : + $this->analyticsService->pageLocalBoLogin(); + } + if ($this->psAccountsLoginEnabled && $tpl_name === $this->template) { return $this->createPsAccountsLoginTemplate(); } diff --git a/controllers/admin/AdminOAuth2PsAccountsController.php b/controllers/admin/AdminOAuth2PsAccountsController.php index 0f6a15084..b70567672 100644 --- a/controllers/admin/AdminOAuth2PsAccountsController.php +++ b/controllers/admin/AdminOAuth2PsAccountsController.php @@ -144,6 +144,11 @@ private function initUserSession(PrestaShopUser $user): bool $cookie->write(); if ($this->module->isShopEdition()) { +// $this->analyticsService->identify( +// $user->getId(), +// $user->getName(), +// $user->getEmail() +// ); $this->analyticsService->trackUserSignedIntoApp( $user->getId(), (string) $this->psAccountsService->getShopUuid() ?? null, diff --git a/src/Service/AnalyticsService.php b/src/Service/AnalyticsService.php index a752b8659..f085dfb92 100644 --- a/src/Service/AnalyticsService.php +++ b/src/Service/AnalyticsService.php @@ -13,6 +13,9 @@ public function __construct(string $segmentWriteKey) public function track(array $properties): void { + // TODO: lazy identify + // TODO: remove old segment key and vue_component validation + // $this->identify(); Segment::track($properties); Segment::flush(); } @@ -58,15 +61,53 @@ public function trackBackOfficeSSOSignInFailed(string $userUid, ?string $shopUid ]); } - public function page(string $path, ?string $referrer, ?string $search, string $title, string $url): void - { - Segment::page([ - 'path' => $path, - 'referrer' => $referrer, - 'search' => $search, - 'title' => $title, - 'url' => $url, + public function page( + string $name, + ?string $userId = null, + ?string $path = null, + ?string $referrer = null, + ?string $search = null, + ?string $title = null, + ?string $url = null + ): void { + $data = []; + if ($userId) { + $data['userId'] = $userId; + } else { + $data['anonymousId'] = session_id(); + } + + Segment::page($data + [ + 'name' => $name, + 'properties' => [ + 'path' => $path !== null ? $path : $_SERVER['PATH_INFO'], + 'referrer' => $referrer !== null ? $referrer : $_SERVER['HTTP_REFERER'], + 'search' => $search, + 'title' => $title, + 'url' => $url !== null ? $url : $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'], + ], ]); Segment::flush(); } + + public function pageAccountsBoLogin(): void + { + $this->page('Accounts Backoffice Login Page'); + } + + public function pageLocalBoLogin(): void + { + $this->page('Local Backoffice Login Page'); + } + + public function identify(string $userUid, string $name, string $email): void + { + Segment::identify([ + 'userId' => $userUid, + 'traits' => [ + 'name' => $name, + 'email' => $email, + ], + ]); + } } From 08e981dbf28989be934427d5fb3ad4f75b661eda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Schoenenberger?= Date: Thu, 12 Jan 2023 10:56:06 +0100 Subject: [PATCH 13/50] fix: no tracking for local login with local user --- ps_accounts.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ps_accounts.php b/ps_accounts.php index 6c287cd3e..f32fb5b0f 100644 --- a/ps_accounts.php +++ b/ps_accounts.php @@ -623,7 +623,7 @@ public function hookActionAdminLoginControllerLoginAfter($params) $account = $psAccountsService->getEmployeeAccount(); - if ($this->isShopEdition()) { + if ($this->isShopEdition() && !empty($account)) { $analyticsService->trackUserSignedIntoBackOfficeLocally( $account->getEmail(), $account->getUid(), From 8f2d487049fd89e88f068c714d64da9ab8816c63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Schoenenberger?= Date: Thu, 12 Jan 2023 11:25:06 +0100 Subject: [PATCH 14/50] chore: set oauth2-prestashop version --- composer.json | 2 +- composer.lock | 147 ++++++++++++++++++++++++++++++++------------------ 2 files changed, 97 insertions(+), 52 deletions(-) diff --git a/composer.json b/composer.json index 3604df74e..ef7cc2a66 100644 --- a/composer.json +++ b/composer.json @@ -32,7 +32,7 @@ "prestashop/module-lib-service-container": "^1.2", "sentry/sentry": "^1.0", "league/oauth2-client": "^2.6", - "prestashopcorp/oauth2-prestashop": "dev-main", + "prestashopcorp/oauth2-prestashop": "^1.0.0", "segmentio/analytics-php": "^1.8" }, "require-dev": { diff --git a/composer.lock b/composer.lock index 428161755..d66d25db4 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "ca7afa28314387c23520c7a4f6f5facf", + "content-hash": "a268db00ecdb9ebfab162cc10f77c09f", "packages": [ { "name": "guzzlehttp/guzzle", @@ -618,16 +618,16 @@ }, { "name": "phpseclib/phpseclib", - "version": "2.0.39", + "version": "2.0.41", "source": { "type": "git", "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "f3a0e2b715c40cf1fd270d444901b63311725d63" + "reference": "7e763c6f97ec1fcb37c46aa8ecfc20a2c71d9c1b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/f3a0e2b715c40cf1fd270d444901b63311725d63", - "reference": "f3a0e2b715c40cf1fd270d444901b63311725d63", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/7e763c6f97ec1fcb37c46aa8ecfc20a2c71d9c1b", + "reference": "7e763c6f97ec1fcb37c46aa8ecfc20a2c71d9c1b", "shasum": "" }, "require": { @@ -708,7 +708,7 @@ ], "support": { "issues": "https://github.com/phpseclib/phpseclib/issues", - "source": "https://github.com/phpseclib/phpseclib/tree/2.0.39" + "source": "https://github.com/phpseclib/phpseclib/tree/2.0.41" }, "funding": [ { @@ -724,7 +724,7 @@ "type": "tidelift" } ], - "time": "2022-10-24T10:49:03+00:00" + "time": "2022-12-23T16:44:18+00:00" }, { "name": "prestashop/module-lib-cache-directory-provider", @@ -831,16 +831,16 @@ }, { "name": "prestashopcorp/oauth2-prestashop", - "version": "dev-main", + "version": "v1.0.0", "source": { "type": "git", "url": "https://github.com/PrestaShopCorp/oauth2-prestashop.git", - "reference": "30cb923042320a88601045beec685ff2a18630f8" + "reference": "2b29979c066db9f1b5a06102b6843d25525adb00" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PrestaShopCorp/oauth2-prestashop/zipball/30cb923042320a88601045beec685ff2a18630f8", - "reference": "30cb923042320a88601045beec685ff2a18630f8", + "url": "https://api.github.com/repos/PrestaShopCorp/oauth2-prestashop/zipball/2b29979c066db9f1b5a06102b6843d25525adb00", + "reference": "2b29979c066db9f1b5a06102b6843d25525adb00", "shasum": "" }, "require": { @@ -852,7 +852,6 @@ "phpunit/phpunit": "^8.0 || ^9.0", "prestashop/php-dev-tools": "^4.2" }, - "default-branch": true, "type": "library", "autoload": { "psr-4": { @@ -882,9 +881,9 @@ ], "support": { "issues": "https://github.com/PrestaShopCorp/oauth2-prestashop/issues", - "source": "https://github.com/PrestaShopCorp/oauth2-prestashop/tree/main" + "source": "https://github.com/PrestaShopCorp/oauth2-prestashop/tree/v1.0.0" }, - "time": "2022-11-08T17:58:41+00:00" + "time": "2022-10-04T15:35:08+00:00" }, { "name": "psr/cache", @@ -2283,16 +2282,16 @@ }, { "name": "symfony/var-exporter", - "version": "v5.4.10", + "version": "v5.4.17", "source": { "type": "git", "url": "https://github.com/symfony/var-exporter.git", - "reference": "8fc03ee75eeece3d9be1ef47d26d79bea1afb340" + "reference": "2adac0a9b55f9fb40b983b790509581dc3db0fff" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/8fc03ee75eeece3d9be1ef47d26d79bea1afb340", - "reference": "8fc03ee75eeece3d9be1ef47d26d79bea1afb340", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/2adac0a9b55f9fb40b983b790509581dc3db0fff", + "reference": "2adac0a9b55f9fb40b983b790509581dc3db0fff", "shasum": "" }, "require": { @@ -2336,7 +2335,7 @@ "serialize" ], "support": { - "source": "https://github.com/symfony/var-exporter/tree/v5.4.10" + "source": "https://github.com/symfony/var-exporter/tree/v5.4.17" }, "funding": [ { @@ -2352,7 +2351,7 @@ "type": "tidelift" } ], - "time": "2022-05-27T12:56:18+00:00" + "time": "2022-12-22T10:10:04+00:00" }, { "name": "symfony/yaml", @@ -2647,32 +2646,35 @@ }, { "name": "doctrine/annotations", - "version": "1.13.3", + "version": "1.14.2", "source": { "type": "git", "url": "https://github.com/doctrine/annotations.git", - "reference": "648b0343343565c4a056bfc8392201385e8d89f0" + "reference": "ad785217c1e9555a7d6c6c8c9f406395a5e2882b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/648b0343343565c4a056bfc8392201385e8d89f0", - "reference": "648b0343343565c4a056bfc8392201385e8d89f0", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/ad785217c1e9555a7d6c6c8c9f406395a5e2882b", + "reference": "ad785217c1e9555a7d6c6c8c9f406395a5e2882b", "shasum": "" }, "require": { - "doctrine/lexer": "1.*", + "doctrine/lexer": "^1 || ^2", "ext-tokenizer": "*", "php": "^7.1 || ^8.0", "psr/cache": "^1 || ^2 || ^3" }, "require-dev": { "doctrine/cache": "^1.11 || ^2.0", - "doctrine/coding-standard": "^6.0 || ^8.1", - "phpstan/phpstan": "^1.4.10 || ^1.8.0", - "phpunit/phpunit": "^7.5 || ^8.0 || ^9.1.5", - "symfony/cache": "^4.4 || ^5.2", + "doctrine/coding-standard": "^9 || ^10", + "phpstan/phpstan": "~1.4.10 || ^1.8.0", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "symfony/cache": "^4.4 || ^5.4 || ^6", "vimeo/psalm": "^4.10" }, + "suggest": { + "php": "PHP 8.0 or higher comes with attributes, a native replacement for annotations" + }, "type": "library", "autoload": { "psr-4": { @@ -2714,36 +2716,79 @@ ], "support": { "issues": "https://github.com/doctrine/annotations/issues", - "source": "https://github.com/doctrine/annotations/tree/1.13.3" + "source": "https://github.com/doctrine/annotations/tree/1.14.2" }, - "time": "2022-07-02T10:48:51+00:00" + "time": "2022-12-15T06:48:22+00:00" + }, + { + "name": "doctrine/deprecations", + "version": "v1.0.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/deprecations.git", + "reference": "0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de", + "reference": "0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de", + "shasum": "" + }, + "require": { + "php": "^7.1|^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9", + "phpunit/phpunit": "^7.5|^8.5|^9.5", + "psr/log": "^1|^2|^3" + }, + "suggest": { + "psr/log": "Allows logging deprecations via PSR-3 logger implementation" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", + "homepage": "https://www.doctrine-project.org/", + "support": { + "issues": "https://github.com/doctrine/deprecations/issues", + "source": "https://github.com/doctrine/deprecations/tree/v1.0.0" + }, + "time": "2022-05-02T15:47:09+00:00" }, { "name": "doctrine/instantiator", - "version": "1.4.1", + "version": "1.5.0", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc" + "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/10dcfce151b967d20fde1b34ae6640712c3891bc", - "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b", + "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b", "shasum": "" }, "require": { "php": "^7.1 || ^8.0" }, "require-dev": { - "doctrine/coding-standard": "^9", + "doctrine/coding-standard": "^9 || ^11", "ext-pdo": "*", "ext-phar": "*", "phpbench/phpbench": "^0.16 || ^1", "phpstan/phpstan": "^1.4", "phpstan/phpstan-phpunit": "^1", "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "vimeo/psalm": "^4.22" + "vimeo/psalm": "^4.30 || ^5.4" }, "type": "library", "autoload": { @@ -2770,7 +2815,7 @@ ], "support": { "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/1.4.1" + "source": "https://github.com/doctrine/instantiator/tree/1.5.0" }, "funding": [ { @@ -2786,35 +2831,37 @@ "type": "tidelift" } ], - "time": "2022-03-03T08:28:38+00:00" + "time": "2022-12-30T00:15:36+00:00" }, { "name": "doctrine/lexer", - "version": "1.2.3", + "version": "2.1.0", "source": { "type": "git", "url": "https://github.com/doctrine/lexer.git", - "reference": "c268e882d4dbdd85e36e4ad69e02dc284f89d229" + "reference": "39ab8fcf5a51ce4b85ca97c7a7d033eb12831124" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/c268e882d4dbdd85e36e4ad69e02dc284f89d229", - "reference": "c268e882d4dbdd85e36e4ad69e02dc284f89d229", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/39ab8fcf5a51ce4b85ca97c7a7d033eb12831124", + "reference": "39ab8fcf5a51ce4b85ca97c7a7d033eb12831124", "shasum": "" }, "require": { + "doctrine/deprecations": "^1.0", "php": "^7.1 || ^8.0" }, "require-dev": { - "doctrine/coding-standard": "^9.0", + "doctrine/coding-standard": "^9 || ^10", "phpstan/phpstan": "^1.3", "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "vimeo/psalm": "^4.11" + "psalm/plugin-phpunit": "^0.18.3", + "vimeo/psalm": "^4.11 || ^5.0" }, "type": "library", "autoload": { "psr-4": { - "Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer" + "Doctrine\\Common\\Lexer\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -2846,7 +2893,7 @@ ], "support": { "issues": "https://github.com/doctrine/lexer/issues", - "source": "https://github.com/doctrine/lexer/tree/1.2.3" + "source": "https://github.com/doctrine/lexer/tree/2.1.0" }, "funding": [ { @@ -2862,7 +2909,7 @@ "type": "tidelift" } ], - "time": "2022-02-28T11:07:21+00:00" + "time": "2022-12-14T08:49:07+00:00" }, { "name": "friendsofphp/php-cs-fixer", @@ -5412,9 +5459,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "prestashopcorp/oauth2-prestashop": 20 - }, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { From 10de1bae61998e7858ed80c5087f32fc1fddb466 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Schoenenberger?= Date: Thu, 12 Jan 2023 14:26:38 +0100 Subject: [PATCH 15/50] chore: remove segment_api_key parameter --- config/config.yml.dist | 1 - src/Presenter/PsAccountsPresenter.php | 1 - 2 files changed, 2 deletions(-) diff --git a/config/config.yml.dist b/config/config.yml.dist index 4f8261bdb..1ef947aef 100644 --- a/config/config.yml.dist +++ b/config/config.yml.dist @@ -16,7 +16,6 @@ parameters: ps_accounts.sso_resend_verification_email_url: 'https://prestashop-newsso-staging.appspot.com/account/send-verification-email' ps_accounts.billing_api_url: 'https://billing-api.psessentials-integration.net' ps_accounts.sentry_credentials: 'https://4c7f6c8dd5aa405b8401a35f5cf26ada@o298402.ingest.sentry.io/5354585' - ps_accounts.segment_api_key: 'yO1sKx3Xe9upW4bRDoRXEB0TZEXQm2y3' ps_accounts.segment_write_key: 'UITzSdsFTgYsXaiJG09hsCiupUPwgJQB' ps_accounts.check_api_ssl_cert: false ps_accounts.verify_account_tokens: false diff --git a/src/Presenter/PsAccountsPresenter.php b/src/Presenter/PsAccountsPresenter.php index 16d5446a3..8bc83ee39 100644 --- a/src/Presenter/PsAccountsPresenter.php +++ b/src/Presenter/PsAccountsPresenter.php @@ -166,7 +166,6 @@ public function present($psxName = 'ps_accounts') 'adminAjaxLink' => $this->psAccountsService->getAdminAjaxUrl(), 'accountsUiUrl' => $this->module->getParameter('ps_accounts.accounts_ui_url'), - 'segmentApiKey' => $this->module->getParameter('ps_accounts.segment_api_key'), ], (new DependenciesPresenter())->present($psxName) ); From 89b220863b8483a1f1384a5266680702501a075c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Schoenenberger?= Date: Thu, 12 Jan 2023 14:42:58 +0100 Subject: [PATCH 16/50] chore: cleanup --- src/Service/AnalyticsService.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Service/AnalyticsService.php b/src/Service/AnalyticsService.php index f085dfb92..1ade3da3e 100644 --- a/src/Service/AnalyticsService.php +++ b/src/Service/AnalyticsService.php @@ -13,9 +13,6 @@ public function __construct(string $segmentWriteKey) public function track(array $properties): void { - // TODO: lazy identify - // TODO: remove old segment key and vue_component validation - // $this->identify(); Segment::track($properties); Segment::flush(); } From 2934db60450104cab6fe471b22b01606fe2343d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Schoenenberger?= Date: Thu, 12 Jan 2023 17:20:05 +0100 Subject: [PATCH 17/50] chore: rename for clarity --- src/Service/AnalyticsService.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Service/AnalyticsService.php b/src/Service/AnalyticsService.php index 1ade3da3e..07f2db50a 100644 --- a/src/Service/AnalyticsService.php +++ b/src/Service/AnalyticsService.php @@ -11,9 +11,9 @@ public function __construct(string $segmentWriteKey) Segment::init($segmentWriteKey); } - public function track(array $properties): void + public function track(array $message): void { - Segment::track($properties); + Segment::track($message); Segment::flush(); } From f6f92c668aef16d04e4c54cd81ca51efbca6fc54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Schoenenberger?= Date: Thu, 12 Jan 2023 17:24:40 +0100 Subject: [PATCH 18/50] fix: email as property --- src/Service/AnalyticsService.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Service/AnalyticsService.php b/src/Service/AnalyticsService.php index 07f2db50a..4d2d1522c 100644 --- a/src/Service/AnalyticsService.php +++ b/src/Service/AnalyticsService.php @@ -35,11 +35,13 @@ public function trackUserSignedIntoBackOfficeLocally(string $userEmail, ?string { $this->track([ 'event' => 'User Signed Into Back Office Locally', - 'email' => $userEmail, 'userId' => $userUid, 'context' => [ 'groupId' => $shopUid, ], + 'properties' => [ + 'email' => $userEmail, + ], ]); } From de1c2bce863abe74c67bad9e6fcc8bb77c993741 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Schoenenberger?= Date: Tue, 17 Jan 2023 11:40:13 +0100 Subject: [PATCH 19/50] chore: test hook --- composer.json | 2 +- ps_accounts.php | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 9692f5252..25b77b8ad 100644 --- a/composer.json +++ b/composer.json @@ -32,7 +32,7 @@ "prestashop/module-lib-service-container": "^1.2", "sentry/sentry": "^1.0", "league/oauth2-client": "^2.6", - "prestashopcorp/oauth2-prestashop": "dev-main" + "prestashopcorp/oauth2-prestashop": "dev-feat/get-session-logout-url" }, "require-dev": { "phpunit/phpunit": "^8.5", diff --git a/ps_accounts.php b/ps_accounts.php index 12003cf42..9b064b444 100644 --- a/ps_accounts.php +++ b/ps_accounts.php @@ -49,6 +49,7 @@ class Ps_accounts extends Module 'actionObjectShopUrlUpdateAfter', 'displayDashboardTop', 'displayAccountUpdateWarning', + 'actionAdminControllerInitBefore', ]; /** @@ -604,6 +605,22 @@ public function hookActionObjectShopDeleteBefore($params) return true; } + /** + * @param $params + * + * @return void + * + * @throws Exception + */ + public function hookActionAdminControllerInitBefore($params) + { + if (isset($_GET['logout'])) { + // TODO: redirect to oauth2 session logout + // http://prestashop8.docker.localhost/administration/index.php?controller=AdminLogin&logout=1&token=609a85a247efa8eef5f87fb1f148ff37 + $this->getLogger()->error('### LOGOUT'); + } + } + /** * @return string */ From 2bce2fe93306cb0b3f5123da2ef178682248e0b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Schoenenberger?= Date: Tue, 17 Jan 2023 16:51:59 +0100 Subject: [PATCH 20/50] chore: update dependencies --- composer.lock | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/composer.lock b/composer.lock index d66d25db4..3f3bfb9da 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "a268db00ecdb9ebfab162cc10f77c09f", + "content-hash": "da582ff3cb5a0df9396cb0ac65fb722e", "packages": [ { "name": "guzzlehttp/guzzle", @@ -831,16 +831,16 @@ }, { "name": "prestashopcorp/oauth2-prestashop", - "version": "v1.0.0", + "version": "dev-feat/get-session-logout-url", "source": { "type": "git", "url": "https://github.com/PrestaShopCorp/oauth2-prestashop.git", - "reference": "2b29979c066db9f1b5a06102b6843d25525adb00" + "reference": "54513dbb33aa2e3c6fd6b8c6011d4e18af326273" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PrestaShopCorp/oauth2-prestashop/zipball/2b29979c066db9f1b5a06102b6843d25525adb00", - "reference": "2b29979c066db9f1b5a06102b6843d25525adb00", + "url": "https://api.github.com/repos/PrestaShopCorp/oauth2-prestashop/zipball/54513dbb33aa2e3c6fd6b8c6011d4e18af326273", + "reference": "54513dbb33aa2e3c6fd6b8c6011d4e18af326273", "shasum": "" }, "require": { @@ -881,9 +881,9 @@ ], "support": { "issues": "https://github.com/PrestaShopCorp/oauth2-prestashop/issues", - "source": "https://github.com/PrestaShopCorp/oauth2-prestashop/tree/v1.0.0" + "source": "https://github.com/PrestaShopCorp/oauth2-prestashop/tree/feat/get-session-logout-url" }, - "time": "2022-10-04T15:35:08+00:00" + "time": "2022-12-15T15:23:49+00:00" }, { "name": "psr/cache", @@ -5459,7 +5459,9 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": { + "prestashopcorp/oauth2-prestashop": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { From ead9a3556528d43b522f7ac13df5b88182d80b7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Schoenenberger?= Date: Tue, 17 Jan 2023 17:15:59 +0100 Subject: [PATCH 21/50] fix: oauth2 session logout url & callback url without token --- config/config.yml.dist | 1 + src/Provider/OAuth2/Oauth2ClientShopProvider.php | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/config/config.yml.dist b/config/config.yml.dist index 1ef947aef..2ba862a1a 100644 --- a/config/config.yml.dist +++ b/config/config.yml.dist @@ -30,6 +30,7 @@ parameters: ps_accounts.oauth2_url_authorize: 'http://hydra:4444/oauth2/auth' ps_accounts.oauth2_url_access_token: 'http://hydra:4444/oauth2/token' ps_accounts.oauth2_url_resource_owner_details: 'http://hydra:4444/userinfo' + ps_accounts.oauth2_url_session_logout: 'http://hydra:4444/oauth2/sessions/logout' ps_accounts.uri_help_center_en: "https://help-center.prestashop.com/en/articles/8087001455634-i-cannot-log-in-to-the-back-office-of-my-edition-shop-with-my-prestashop-account" ps_accounts.uri_help_center_fr: "https://help-center.prestashop.com/fr/articles/8087001455634-je-ne-peux-pas-me-connecter-au-back-office-de-ma-boutique-edition-avec-mon-compte-prestashop" diff --git a/src/Provider/OAuth2/Oauth2ClientShopProvider.php b/src/Provider/OAuth2/Oauth2ClientShopProvider.php index cc3814d61..1ccecdd21 100644 --- a/src/Provider/OAuth2/Oauth2ClientShopProvider.php +++ b/src/Provider/OAuth2/Oauth2ClientShopProvider.php @@ -135,7 +135,7 @@ public function getBaseSessionLogoutUrl(): string public function getPostLogoutRedirectUri(): string { // return 'https://' . _FRONTOFFICE_SERVER_ . '/en?logout&' . self::QUERY_LOGOUT_CALLBACK_PARAM; - return $this->context->link->getAdminLink('AdminLogin', true, [], [ + return $this->context->link->getAdminLink('AdminLogin', false, [], [ 'logout' => 1, self::QUERY_LOGOUT_CALLBACK_PARAM => 1, ]); From 2c7a5368b31101fb05db9f5c15137e58580a8aad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Schoenenberger?= Date: Tue, 17 Jan 2023 17:23:09 +0100 Subject: [PATCH 22/50] chore: rollback disable ssl cert for dev --- src/Provider/OAuth2/Oauth2ClientShopProvider.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/Provider/OAuth2/Oauth2ClientShopProvider.php b/src/Provider/OAuth2/Oauth2ClientShopProvider.php index 1ccecdd21..8f4d7893c 100644 --- a/src/Provider/OAuth2/Oauth2ClientShopProvider.php +++ b/src/Provider/OAuth2/Oauth2ClientShopProvider.php @@ -58,6 +58,11 @@ public function __construct(array $options = [], array $collaborators = []) $this->context = $module->getContext(); $this->configuration = $module->getService(ConfigurationRepository::class); + // Disable certificate verification from local configuration + $options['verify'] = (bool) $this->module->getParameter( + 'ps_accounts.check_api_ssl_cert' + ); + parent::__construct(array_merge([ 'clientId' => $this->configuration->getOauth2ClientId(), 'clientSecret' => $this->configuration->getOauth2ClientSecret(), @@ -66,6 +71,13 @@ public function __construct(array $options = [], array $collaborators = []) ], $options), $collaborators); } + protected function getAllowedClientOptions(array $options) + { + return array_merge(parent::getAllowedClientOptions($options), [ + 'verify', + ]); + } + public static function create(): PrestaShop { return new self(); From 7a03576ad407c82605b9907e517349a6f3b98bb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Schoenenberger?= Date: Tue, 17 Jan 2023 17:24:35 +0100 Subject: [PATCH 23/50] chore: todo --- ps_accounts.php | 1 + src/Provider/OAuth2/Oauth2ClientShopProvider.php | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/ps_accounts.php b/ps_accounts.php index 0905f6b37..42fbd75f3 100644 --- a/ps_accounts.php +++ b/ps_accounts.php @@ -653,6 +653,7 @@ public function hookActionAdminControllerInitBefore($params) /** @var \Symfony\Component\HttpFoundation\Session\SessionInterface $session */ $session = $this->getContainer()->get('session'); + // FIXME: create accessors on provider /** @var \League\OAuth2\Client\Token\AccessToken $accessToken */ $accessToken = $session->get('accessToken'); diff --git a/src/Provider/OAuth2/Oauth2ClientShopProvider.php b/src/Provider/OAuth2/Oauth2ClientShopProvider.php index 8f4d7893c..efa6b3c52 100644 --- a/src/Provider/OAuth2/Oauth2ClientShopProvider.php +++ b/src/Provider/OAuth2/Oauth2ClientShopProvider.php @@ -146,7 +146,6 @@ public function getBaseSessionLogoutUrl(): string public function getPostLogoutRedirectUri(): string { - // return 'https://' . _FRONTOFFICE_SERVER_ . '/en?logout&' . self::QUERY_LOGOUT_CALLBACK_PARAM; return $this->context->link->getAdminLink('AdminLogin', false, [], [ 'logout' => 1, self::QUERY_LOGOUT_CALLBACK_PARAM => 1, From 5557e61cfb73f7d46def27442c8fe645936e92e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Schoenenberger?= Date: Tue, 17 Jan 2023 17:27:10 +0100 Subject: [PATCH 24/50] chore: todo --- ps_accounts.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ps_accounts.php b/ps_accounts.php index 42fbd75f3..e06d5abcb 100644 --- a/ps_accounts.php +++ b/ps_accounts.php @@ -645,6 +645,7 @@ public function hookActionAdminLoginControllerLoginAfter($params) public function hookActionAdminControllerInitBefore($params) { if (isset($_GET['logout']) + // FIXME: create a dedicated logout controller && !isset($_GET[\PrestaShop\Module\PsAccounts\Provider\OAuth2\Oauth2ClientShopProvider::QUERY_LOGOUT_CALLBACK_PARAM])) { /** @var \PrestaShop\Module\PsAccounts\Provider\OAuth2\Oauth2ClientShopProvider $provider */ @@ -653,7 +654,7 @@ public function hookActionAdminControllerInitBefore($params) /** @var \Symfony\Component\HttpFoundation\Session\SessionInterface $session */ $session = $this->getContainer()->get('session'); - // FIXME: create accessors on provider + // FIXME: create accessToken accessors on provider /** @var \League\OAuth2\Client\Token\AccessToken $accessToken */ $accessToken = $session->get('accessToken'); From 1d85e777da7e58b7fdb7d9d10187807f206acc6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Schoenenberger?= Date: Tue, 17 Jan 2023 17:28:41 +0100 Subject: [PATCH 25/50] chore: cleanup logs --- ps_accounts.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/ps_accounts.php b/ps_accounts.php index e06d5abcb..e28eeefa1 100644 --- a/ps_accounts.php +++ b/ps_accounts.php @@ -666,8 +666,6 @@ public function hookActionAdminControllerInitBefore($params) 'id_token_hint' => $accessToken->getValues()['id_token'] ]); - $this->getLogger()->error('### LOGOUT ' . $logoutUrl); - // Redirect the user to the authorization URL. header('Location: ' . $logoutUrl); exit; From d8a45e8f9689b26855d0fcea8c949d7335dbed1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Schoenenberger?= Date: Tue, 17 Jan 2023 17:35:39 +0100 Subject: [PATCH 26/50] feat: strictly checks login activation before attempting oauth2 logout --- ps_accounts.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ps_accounts.php b/ps_accounts.php index e28eeefa1..64d3ac344 100644 --- a/ps_accounts.php +++ b/ps_accounts.php @@ -644,6 +644,13 @@ public function hookActionAdminLoginControllerLoginAfter($params) */ public function hookActionAdminControllerInitBefore($params) { + /** @var \PrestaShop\Module\PsAccounts\Service\PsAccountsService $moduleService */ + $moduleService = $this->getService(\PrestaShop\Module\PsAccounts\Service\PsAccountsService::class); + + if (!$moduleService->getLoginActivated()) { + return; + } + if (isset($_GET['logout']) // FIXME: create a dedicated logout controller && !isset($_GET[\PrestaShop\Module\PsAccounts\Provider\OAuth2\Oauth2ClientShopProvider::QUERY_LOGOUT_CALLBACK_PARAM])) { From aaf746cf188eb8fcd6e50093b3a16e455351fda0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Schoenenberger?= Date: Tue, 17 Jan 2023 19:40:19 +0100 Subject: [PATCH 27/50] refactor: move logout code to a trait --- ps_accounts.php | 54 +++++++++++------------ src/Provider/OAuth2/Oauth2LogoutTrait.php | 51 +++++++++++++++++++++ 2 files changed, 77 insertions(+), 28 deletions(-) create mode 100644 src/Provider/OAuth2/Oauth2LogoutTrait.php diff --git a/ps_accounts.php b/ps_accounts.php index 64d3ac344..3649af40d 100644 --- a/ps_accounts.php +++ b/ps_accounts.php @@ -24,6 +24,8 @@ class Ps_accounts extends Module { + use \PrestaShop\Module\PsAccounts\Provider\OAuth2\Oauth2LogoutTrait; + const DEFAULT_ENV = ''; // Needed in order to retrieve the module version easier (in api call headers) than instanciate @@ -644,38 +646,15 @@ public function hookActionAdminLoginControllerLoginAfter($params) */ public function hookActionAdminControllerInitBefore($params) { - /** @var \PrestaShop\Module\PsAccounts\Service\PsAccountsService $moduleService */ - $moduleService = $this->getService(\PrestaShop\Module\PsAccounts\Service\PsAccountsService::class); + /** @var \PrestaShop\Module\PsAccounts\Service\PsAccountsService $psAccountsService */ + $psAccountsService = $this->getService(\PrestaShop\Module\PsAccounts\Service\PsAccountsService::class); - if (!$moduleService->getLoginActivated()) { + if (!$psAccountsService->getLoginActivated()) { return; } - if (isset($_GET['logout']) - // FIXME: create a dedicated logout controller - && !isset($_GET[\PrestaShop\Module\PsAccounts\Provider\OAuth2\Oauth2ClientShopProvider::QUERY_LOGOUT_CALLBACK_PARAM])) { - - /** @var \PrestaShop\Module\PsAccounts\Provider\OAuth2\Oauth2ClientShopProvider $provider */ - $provider = $this->getService(\PrestaShop\OAuth2\Client\Provider\PrestaShop::class); - - /** @var \Symfony\Component\HttpFoundation\Session\SessionInterface $session */ - $session = $this->getContainer()->get('session'); - - // FIXME: create accessToken accessors on provider - /** @var \League\OAuth2\Client\Token\AccessToken $accessToken */ - $accessToken = $session->get('accessToken'); - - if (empty($accessToken)) { - return; - } - - $logoutUrl = $provider->getLogoutUrl([ - 'id_token_hint' => $accessToken->getValues()['id_token'] - ]); - - // Redirect the user to the authorization URL. - header('Location: ' . $logoutUrl); - exit; + if (isset($_GET['logout'])) { + $this->oauth2Logout(); } } @@ -807,4 +786,23 @@ public function isShopEdition(): bool { return Module::isEnabled('smb_edition'); } + + protected function getProvider(): PrestaShop\Module\PsAccounts\Provider\OAuth2\Oauth2ClientShopProvider + { + /** @var \PrestaShop\Module\PsAccounts\Provider\OAuth2\Oauth2ClientShopProvider $provider */ + $provider = $this->getService(\PrestaShop\OAuth2\Client\Provider\PrestaShop::class); + + return $provider; + } + + protected function getAccessToken(): League\OAuth2\Client\Token\AccessToken + { + /** @var \Symfony\Component\HttpFoundation\Session\SessionInterface $session */ + $session = $this->getContainer()->get('session'); + + /** @var \League\OAuth2\Client\Token\AccessToken $accessToken */ + $accessToken = $session->get('accessToken'); + + return $accessToken; + } } diff --git a/src/Provider/OAuth2/Oauth2LogoutTrait.php b/src/Provider/OAuth2/Oauth2LogoutTrait.php new file mode 100644 index 000000000..2bde9b43a --- /dev/null +++ b/src/Provider/OAuth2/Oauth2LogoutTrait.php @@ -0,0 +1,51 @@ + + * @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\Provider\OAuth2; + +use League\OAuth2\Client\Token\AccessToken; + +trait Oauth2LogoutTrait +{ + abstract protected function getProvider(): Oauth2ClientShopProvider; + + abstract protected function getAccessToken(): AccessToken; + + /** + * @throws \Exception + */ + public function oauth2Logout(): void + { + if (!isset($_GET[Oauth2ClientShopProvider::QUERY_LOGOUT_CALLBACK_PARAM])) { + $accessToken = $this->getAccessToken(); + + if (empty($accessToken)) { + return; + } + + $logoutUrl = $this->getProvider()->getLogoutUrl([ + 'id_token_hint' => $accessToken->getValues()['id_token'], + ]); + + header('Location: ' . $logoutUrl); + exit; + } + } +} From e810de151fa5b3ed0a9efa8b6c76f6313bfb582d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Schoenenberger?= Date: Tue, 24 Jan 2023 14:53:33 +0100 Subject: [PATCH 28/50] fix: WIP manage interaction between login & logout flows --- ps_accounts.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ps_accounts.php b/ps_accounts.php index 3649af40d..9360dd79f 100644 --- a/ps_accounts.php +++ b/ps_accounts.php @@ -653,7 +653,8 @@ public function hookActionAdminControllerInitBefore($params) return; } - if (isset($_GET['logout'])) { + if (isset($_GET['logout']) && !isset($_GET['loginError'])) { + // FIXME: display login error $this->oauth2Logout(); } } From 071305656d1551f95757a05672b55708262acf15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Schoenenberger?= Date: Tue, 24 Jan 2023 17:55:30 +0100 Subject: [PATCH 29/50] fix: store login error into session to deal with logout redirect --- controllers/admin/AdminLoginController.php | 6 +++- .../admin/AdminOAuth2PsAccountsController.php | 28 +++++++++++++++++-- ps_accounts.php | 5 ++-- 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/controllers/admin/AdminLoginController.php b/controllers/admin/AdminLoginController.php index ec54ad414..9990822dd 100644 --- a/controllers/admin/AdminLoginController.php +++ b/controllers/admin/AdminLoginController.php @@ -20,6 +20,7 @@ use PrestaShop\Module\PsAccounts\Service\AnalyticsService; use PrestaShop\Module\PsAccounts\Service\PsAccountsService; +use Symfony\Component\HttpFoundation\Session\SessionInterface; /** * Copyright since 2007 PrestaShop SA and Contributors @@ -124,6 +125,9 @@ public function createPsAccountsLoginTemplate() /** @var \PrestaShop\Module\PsAccounts\Provider\OAuth2\Oauth2ClientShopProvider $provider */ $provider = $this->psAccountsModule->getService(\PrestaShop\OAuth2\Client\Provider\PrestaShop::class); + /** @var SessionInterface $session */ + $session = $this->psAccountsModule->getContainer()->get('session'); + $this->context->smarty->assign('oauthRedirectUri', $provider->getRedirectUri()); $this->context->smarty->assign('legacyLoginUri', $this->context->link->getAdminLink('AdminLogin', true, [], [ 'mode' => self::PS_ACCOUNTS_LOGIN_MODE_LOCAL, @@ -132,7 +136,7 @@ public function createPsAccountsLoginTemplate() $isoCode = $this->context->currentLocale->getCode(); $this->context->smarty->assign('uriHelpCenter', $this->getUriHelpCenter($isoCode)); - $this->context->smarty->assign('loginError', Tools::getValue('loginError')); + $this->context->smarty->assign('loginError', $session->get('loginError')); $this->context->smarty->assign('meta_title', ''); $this->context->smarty->assign('ssoResendVerificationEmail', $this->psAccountsModule->getParameter('ps_accounts.sso_resend_verification_email_url') diff --git a/controllers/admin/AdminOAuth2PsAccountsController.php b/controllers/admin/AdminOAuth2PsAccountsController.php index b70567672..287353249 100644 --- a/controllers/admin/AdminOAuth2PsAccountsController.php +++ b/controllers/admin/AdminOAuth2PsAccountsController.php @@ -143,6 +143,8 @@ private function initUserSession(PrestaShopUser $user): bool $cookie->write(); + $this->unsetLoginError(); + if ($this->module->isShopEdition()) { // $this->analyticsService->identify( // $user->getId(), @@ -198,6 +200,9 @@ private function getEmployeeByUidOrEmail(string $uid, string $email): Employee return $employee; } + /** + * @throws ContainerNotFoundException + */ private function onLoginFailed(AccountLoginException $e): void { if ($this->module->isShopEdition() && ( @@ -213,14 +218,17 @@ private function onLoginFailed(AccountLoginException $e): void } $this->oauth2ErrorLog($e->getMessage()); + $this->setLoginError($e->getType()); Tools::redirectAdmin( $this->context->link->getAdminLink('AdminLogin', true, [], [ 'logout' => 1, - 'loginError' => $e->getType(), ]) ); } + /** + * @throws Exception + */ private function getProvider(): Oauth2ClientShopProvider { return $this->module->getService(PrestaShop::class); @@ -239,7 +247,23 @@ private function redirectAfterLogin(): void */ private function getSession(): SessionInterface { - /* @phpstan-ignore-next-line */ + /* @phpstan-ignore-next-line */ return $this->module->getContainer()->get('session'); } + + /** + * @throws ContainerNotFoundException + */ + private function setLoginError(string $error): void + { + $this->getSession()->set('loginError', $error); + } + + /** + * @throws ContainerNotFoundException + */ + private function unsetLoginError(): void + { + $this->getSession()->remove('loginError'); + } } diff --git a/ps_accounts.php b/ps_accounts.php index 9360dd79f..c30f14973 100644 --- a/ps_accounts.php +++ b/ps_accounts.php @@ -653,8 +653,7 @@ public function hookActionAdminControllerInitBefore($params) return; } - if (isset($_GET['logout']) && !isset($_GET['loginError'])) { - // FIXME: display login error + if (isset($_GET['logout'])) { $this->oauth2Logout(); } } @@ -796,7 +795,7 @@ protected function getProvider(): PrestaShop\Module\PsAccounts\Provider\OAuth2\O return $provider; } - protected function getAccessToken(): League\OAuth2\Client\Token\AccessToken + protected function getAccessToken(): ?League\OAuth2\Client\Token\AccessToken { /** @var \Symfony\Component\HttpFoundation\Session\SessionInterface $session */ $session = $this->getContainer()->get('session'); From 8d05c32505daedd4c799b602527670eeb5abe453 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Schoenenberger?= Date: Tue, 24 Jan 2023 18:05:54 +0100 Subject: [PATCH 30/50] fix: method signature typehint --- src/Provider/OAuth2/Oauth2LogoutTrait.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Provider/OAuth2/Oauth2LogoutTrait.php b/src/Provider/OAuth2/Oauth2LogoutTrait.php index 2bde9b43a..3393f2a17 100644 --- a/src/Provider/OAuth2/Oauth2LogoutTrait.php +++ b/src/Provider/OAuth2/Oauth2LogoutTrait.php @@ -26,7 +26,7 @@ trait Oauth2LogoutTrait { abstract protected function getProvider(): Oauth2ClientShopProvider; - abstract protected function getAccessToken(): AccessToken; + abstract protected function getAccessToken(): ?AccessToken; /** * @throws \Exception From 76b43791660fa3203c7a4a810d561541c3f8dfd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Schoenenberger?= Date: Thu, 26 Jan 2023 18:09:28 +0100 Subject: [PATCH 31/50] fix: identify and anonymous id --- .gitignore | 1 - controllers/admin/AdminLoginController.php | 9 ++++- .../admin/AdminOAuth2PsAccountsController.php | 18 ++++++--- phpunit.xml | 2 +- ps_accounts.php | 17 +++++++-- src/Service/AnalyticsService.php | 38 ++++++++++--------- tests/local_config.php.dist | 24 ------------ 7 files changed, 54 insertions(+), 55 deletions(-) delete mode 100644 tests/local_config.php.dist diff --git a/.gitignore b/.gitignore index 84f946611..063827353 100644 --- a/.gitignore +++ b/.gitignore @@ -54,4 +54,3 @@ yarn-debug.log* yarn-error.log* .vscode -/tests/local_config.php diff --git a/controllers/admin/AdminLoginController.php b/controllers/admin/AdminLoginController.php index ec54ad414..8b0a14050 100644 --- a/controllers/admin/AdminLoginController.php +++ b/controllers/admin/AdminLoginController.php @@ -102,9 +102,14 @@ public function setMedia($isNewTheme = false) public function createTemplate($tpl_name) { if ($this->psAccountsModule->isShopEdition()) { + /** @var PsAccountsService $psAccountsService */ + $psAccountsService = $this->psAccountsModule->getService(PsAccountsService::class); + $account = $psAccountsService->getEmployeeAccount(); + $userId = $account ? $account->getUid() : null; + $this->psAccountsLoginEnabled ? - $this->analyticsService->pageAccountsBoLogin() : - $this->analyticsService->pageLocalBoLogin(); + $this->analyticsService->pageAccountsBoLogin($userId) : + $this->analyticsService->pageLocalBoLogin($userId); } if ($this->psAccountsLoginEnabled && $tpl_name === $this->template) { diff --git a/controllers/admin/AdminOAuth2PsAccountsController.php b/controllers/admin/AdminOAuth2PsAccountsController.php index b70567672..484f042f0 100644 --- a/controllers/admin/AdminOAuth2PsAccountsController.php +++ b/controllers/admin/AdminOAuth2PsAccountsController.php @@ -144,11 +144,11 @@ private function initUserSession(PrestaShopUser $user): bool $cookie->write(); if ($this->module->isShopEdition()) { -// $this->analyticsService->identify( -// $user->getId(), -// $user->getName(), -// $user->getEmail() -// ); + $this->analyticsService->identify( + $user->getId(), + $user->getName(), + $user->getEmail() + ); $this->analyticsService->trackUserSignedIntoApp( $user->getId(), (string) $this->psAccountsService->getShopUuid() ?? null, @@ -204,8 +204,14 @@ private function onLoginFailed(AccountLoginException $e): void $e instanceof EmployeeNotFoundException || $e instanceof EmailNotVerifiedException )) { + $user = $e->getPrestaShopUser(); + $this->analyticsService->identify( + $user->getId(), + $user->getName(), + $user->getEmail() + ); $this->analyticsService->trackBackOfficeSSOSignInFailed( - $e->getPrestaShopUser()->getId(), + $user->getId(), (string) $this->psAccountsService->getShopUuid() ?? null, $e->getType(), $e->getMessage() diff --git a/phpunit.xml b/phpunit.xml index 48c703ad8..bc0671a12 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -6,7 +6,7 @@ convertErrorsToExceptions="true" convertNoticesToExceptions="true" convertWarningsToExceptions="true" - defaultTestSuite="unit" + defaultTestSuite="all" > diff --git a/ps_accounts.php b/ps_accounts.php index f32fb5b0f..4b23e5e3f 100644 --- a/ps_accounts.php +++ b/ps_accounts.php @@ -623,10 +623,18 @@ public function hookActionAdminLoginControllerLoginAfter($params) $account = $psAccountsService->getEmployeeAccount(); - if ($this->isShopEdition() && !empty($account)) { + if ($this->isShopEdition()) { + $uid = null; + if ($account) { + $uid = $account->getUid(); + $email = $account->getEmail(); + } else { + $email = $employee->email; + } + $analyticsService->identify($uid, null, $email); $analyticsService->trackUserSignedIntoBackOfficeLocally( - $account->getEmail(), - $account->getUid(), + $email, + $uid, (string) $psAccountsService->getShopUuid() ?? null ); } @@ -758,6 +766,7 @@ public function getCustomHooks() public function isShopEdition(): bool { - return Module::isEnabled('smb_edition'); + return true; + //return Module::isEnabled('smb_edition'); } } diff --git a/src/Service/AnalyticsService.php b/src/Service/AnalyticsService.php index 4d2d1522c..52b1998a9 100644 --- a/src/Service/AnalyticsService.php +++ b/src/Service/AnalyticsService.php @@ -22,6 +22,7 @@ public function trackUserSignedIntoApp(string $userUid, ?string $shopUid, string $this->track([ 'event' => 'User Signed Into App', 'userId' => $userUid, + 'anonymousId' => $this->getAnonymousId(), 'context' => [ 'groupId' => $shopUid, ], @@ -36,6 +37,7 @@ public function trackUserSignedIntoBackOfficeLocally(string $userEmail, ?string $this->track([ 'event' => 'User Signed Into Back Office Locally', 'userId' => $userUid, + 'anonymousId' => $this->getAnonymousId(), 'context' => [ 'groupId' => $shopUid, ], @@ -50,6 +52,7 @@ public function trackBackOfficeSSOSignInFailed(string $userUid, ?string $shopUid $this->track([ 'event' => 'Back Office SSO Sign In Failed', 'userId' => $userUid, + 'anonymousId' => $this->getAnonymousId(), 'context' => [ 'groupId' => $shopUid, ], @@ -69,14 +72,9 @@ public function page( ?string $title = null, ?string $url = null ): void { - $data = []; - if ($userId) { - $data['userId'] = $userId; - } else { - $data['anonymousId'] = session_id(); - } - - Segment::page($data + [ + Segment::page([ + 'userId' => $userId, + 'anonymousId' => $this->getAnonymousId(), 'name' => $name, 'properties' => [ 'path' => $path !== null ? $path : $_SERVER['PATH_INFO'], @@ -89,24 +87,30 @@ public function page( Segment::flush(); } - public function pageAccountsBoLogin(): void + public function pageAccountsBoLogin(?string $userUid=null): void { - $this->page('Accounts Backoffice Login Page'); + $this->page('Accounts Backoffice Login Page', $userUid); } - public function pageLocalBoLogin(): void + public function pageLocalBoLogin(?string $userUid=null): void { - $this->page('Local Backoffice Login Page'); + $this->page('Local Backoffice Login Page', $userUid); } - public function identify(string $userUid, string $name, string $email): void + public function identify(?string $userUid, ?string $name, ?string $email): void { Segment::identify([ 'userId' => $userUid, - 'traits' => [ - 'name' => $name, - 'email' => $email, - ], + // aggregate any previous anonymous call + 'anonymous_id' => $this->getAnonymousId(), + 'traits' => + [$name ? ['name' => $name] : []] + + [$email ? ['email' => $email] : []], ]); } + + protected function getAnonymousId(): ?string + { + return $_COOKIE['ajs_anonymous_id'] ?? session_id(); + } } diff --git a/tests/local_config.php.dist b/tests/local_config.php.dist deleted file mode 100644 index 65772de9c..000000000 --- a/tests/local_config.php.dist +++ /dev/null @@ -1,24 +0,0 @@ - Date: Thu, 26 Jan 2023 18:14:22 +0100 Subject: [PATCH 32/50] fix: cs-fixer --- src/Service/AnalyticsService.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Service/AnalyticsService.php b/src/Service/AnalyticsService.php index 52b1998a9..00e678249 100644 --- a/src/Service/AnalyticsService.php +++ b/src/Service/AnalyticsService.php @@ -87,12 +87,12 @@ public function page( Segment::flush(); } - public function pageAccountsBoLogin(?string $userUid=null): void + public function pageAccountsBoLogin(?string $userUid = null): void { $this->page('Accounts Backoffice Login Page', $userUid); } - public function pageLocalBoLogin(?string $userUid=null): void + public function pageLocalBoLogin(?string $userUid = null): void { $this->page('Local Backoffice Login Page', $userUid); } @@ -103,8 +103,7 @@ public function identify(?string $userUid, ?string $name, ?string $email): void 'userId' => $userUid, // aggregate any previous anonymous call 'anonymous_id' => $this->getAnonymousId(), - 'traits' => - [$name ? ['name' => $name] : []] + + 'traits' => [$name ? ['name' => $name] : []] + [$email ? ['email' => $email] : []], ]); } From 9f4fab6e126e560e1ef219e4400431e5a25c9f18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Schoenenberger?= Date: Tue, 31 Jan 2023 16:12:41 +0100 Subject: [PATCH 33/50] chore: deps for production --- composer.json | 2 +- composer.lock | 78 +++++++++++++++++++++++++-------------------------- 2 files changed, 39 insertions(+), 41 deletions(-) diff --git a/composer.json b/composer.json index e633d1048..e106b665a 100644 --- a/composer.json +++ b/composer.json @@ -32,7 +32,7 @@ "prestashop/module-lib-service-container": "^1.2", "sentry/sentry": "^1.0", "league/oauth2-client": "^2.6", - "prestashopcorp/oauth2-prestashop": "dev-feat/get-session-logout-url", + "prestashopcorp/oauth2-prestashop": "^1.1.0", "segmentio/analytics-php": "^1.8" }, "require-dev": { diff --git a/composer.lock b/composer.lock index 3f3bfb9da..9b126120f 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "da582ff3cb5a0df9396cb0ac65fb722e", + "content-hash": "0c75cc0ac5b4efd2762b593db9c56824", "packages": [ { "name": "guzzlehttp/guzzle", @@ -831,16 +831,16 @@ }, { "name": "prestashopcorp/oauth2-prestashop", - "version": "dev-feat/get-session-logout-url", + "version": "v1.1.0", "source": { "type": "git", "url": "https://github.com/PrestaShopCorp/oauth2-prestashop.git", - "reference": "54513dbb33aa2e3c6fd6b8c6011d4e18af326273" + "reference": "d3b065a3b8a118400a62433cacde8b3712c3f548" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PrestaShopCorp/oauth2-prestashop/zipball/54513dbb33aa2e3c6fd6b8c6011d4e18af326273", - "reference": "54513dbb33aa2e3c6fd6b8c6011d4e18af326273", + "url": "https://api.github.com/repos/PrestaShopCorp/oauth2-prestashop/zipball/d3b065a3b8a118400a62433cacde8b3712c3f548", + "reference": "d3b065a3b8a118400a62433cacde8b3712c3f548", "shasum": "" }, "require": { @@ -881,9 +881,9 @@ ], "support": { "issues": "https://github.com/PrestaShopCorp/oauth2-prestashop/issues", - "source": "https://github.com/PrestaShopCorp/oauth2-prestashop/tree/feat/get-session-logout-url" + "source": "https://github.com/PrestaShopCorp/oauth2-prestashop/tree/v1.1.0" }, - "time": "2022-12-15T15:23:49+00:00" + "time": "2023-01-23T13:59:29+00:00" }, { "name": "psr/cache", @@ -2282,16 +2282,16 @@ }, { "name": "symfony/var-exporter", - "version": "v5.4.17", + "version": "v5.4.19", "source": { "type": "git", "url": "https://github.com/symfony/var-exporter.git", - "reference": "2adac0a9b55f9fb40b983b790509581dc3db0fff" + "reference": "2a1d06fcf2b30829d6c01dae8e6e188424d1f8f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/2adac0a9b55f9fb40b983b790509581dc3db0fff", - "reference": "2adac0a9b55f9fb40b983b790509581dc3db0fff", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/2a1d06fcf2b30829d6c01dae8e6e188424d1f8f6", + "reference": "2a1d06fcf2b30829d6c01dae8e6e188424d1f8f6", "shasum": "" }, "require": { @@ -2335,7 +2335,7 @@ "serialize" ], "support": { - "source": "https://github.com/symfony/var-exporter/tree/v5.4.17" + "source": "https://github.com/symfony/var-exporter/tree/v5.4.19" }, "funding": [ { @@ -2351,7 +2351,7 @@ "type": "tidelift" } ], - "time": "2022-12-22T10:10:04+00:00" + "time": "2023-01-12T16:39:29+00:00" }, { "name": "symfony/yaml", @@ -3655,16 +3655,16 @@ }, { "name": "phpunit/phpunit", - "version": "8.5.31", + "version": "8.5.32", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "33c126b09a42de5c99e5e8032b54e8221264a74e" + "reference": "375686930d05c9fd7d20f6e5fc38121e8d7a9d55" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/33c126b09a42de5c99e5e8032b54e8221264a74e", - "reference": "33c126b09a42de5c99e5e8032b54e8221264a74e", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/375686930d05c9fd7d20f6e5fc38121e8d7a9d55", + "reference": "375686930d05c9fd7d20f6e5fc38121e8d7a9d55", "shasum": "" }, "require": { @@ -3732,7 +3732,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "source": "https://github.com/sebastianbergmann/phpunit/tree/8.5.31" + "source": "https://github.com/sebastianbergmann/phpunit/tree/8.5.32" }, "funding": [ { @@ -3748,7 +3748,7 @@ "type": "tidelift" } ], - "time": "2022-10-28T05:57:37+00:00" + "time": "2023-01-26T08:30:25+00:00" }, { "name": "prestashop/autoindex", @@ -5056,16 +5056,16 @@ }, { "name": "symfony/options-resolver", - "version": "v5.4.11", + "version": "v5.4.19", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "54f14e36aa73cb8f7261d7686691fd4d75ea2690" + "reference": "b03c99236445492f20c61666e8f7e5d388b078e5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/54f14e36aa73cb8f7261d7686691fd4d75ea2690", - "reference": "54f14e36aa73cb8f7261d7686691fd4d75ea2690", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/b03c99236445492f20c61666e8f7e5d388b078e5", + "reference": "b03c99236445492f20c61666e8f7e5d388b078e5", "shasum": "" }, "require": { @@ -5105,7 +5105,7 @@ "options" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v5.4.11" + "source": "https://github.com/symfony/options-resolver/tree/v5.4.19" }, "funding": [ { @@ -5121,7 +5121,7 @@ "type": "tidelift" } ], - "time": "2022-07-20T13:00:38+00:00" + "time": "2023-01-01T08:32:19+00:00" }, { "name": "symfony/polyfill-mbstring", @@ -5284,16 +5284,16 @@ }, { "name": "symfony/process", - "version": "v5.4.11", + "version": "v5.4.19", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "6e75fe6874cbc7e4773d049616ab450eff537bf1" + "reference": "c5ba874c9b636dbccf761e22ce750e88ec3f55e1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/6e75fe6874cbc7e4773d049616ab450eff537bf1", - "reference": "6e75fe6874cbc7e4773d049616ab450eff537bf1", + "url": "https://api.github.com/repos/symfony/process/zipball/c5ba874c9b636dbccf761e22ce750e88ec3f55e1", + "reference": "c5ba874c9b636dbccf761e22ce750e88ec3f55e1", "shasum": "" }, "require": { @@ -5326,7 +5326,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v5.4.11" + "source": "https://github.com/symfony/process/tree/v5.4.19" }, "funding": [ { @@ -5342,20 +5342,20 @@ "type": "tidelift" } ], - "time": "2022-06-27T16:58:25+00:00" + "time": "2023-01-01T08:32:19+00:00" }, { "name": "symfony/stopwatch", - "version": "v5.4.13", + "version": "v5.4.19", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "6df7a3effde34d81717bbef4591e5ffe32226d69" + "reference": "bd2b066090fd6a67039371098fa25a84cb2679ec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/6df7a3effde34d81717bbef4591e5ffe32226d69", - "reference": "6df7a3effde34d81717bbef4591e5ffe32226d69", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/bd2b066090fd6a67039371098fa25a84cb2679ec", + "reference": "bd2b066090fd6a67039371098fa25a84cb2679ec", "shasum": "" }, "require": { @@ -5388,7 +5388,7 @@ "description": "Provides a way to profile code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/stopwatch/tree/v5.4.13" + "source": "https://github.com/symfony/stopwatch/tree/v5.4.19" }, "funding": [ { @@ -5404,7 +5404,7 @@ "type": "tidelift" } ], - "time": "2022-09-28T13:19:49+00:00" + "time": "2023-01-01T08:32:19+00:00" }, { "name": "theseer/tokenizer", @@ -5459,9 +5459,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "prestashopcorp/oauth2-prestashop": 20 - }, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { From 5f10010a9019a1c6b56f755048b409ea65ab7e60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Schoenenberger?= Date: Tue, 31 Jan 2023 16:25:53 +0100 Subject: [PATCH 34/50] fix: restore code for production --- ps_accounts.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ps_accounts.php b/ps_accounts.php index 4b23e5e3f..298e84a29 100644 --- a/ps_accounts.php +++ b/ps_accounts.php @@ -766,7 +766,6 @@ public function getCustomHooks() public function isShopEdition(): bool { - return true; - //return Module::isEnabled('smb_edition'); + return Module::isEnabled('smb_edition'); } } From 0ba5a6059c5f20aa61c01d8ae9c079bb9e1be8fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Schoenenberger?= Date: Tue, 31 Jan 2023 16:53:21 +0100 Subject: [PATCH 35/50] refactor: rename exception --- controllers/admin/AdminOAuth2PsAccountsController.php | 4 ++-- .../{HydraErrorException.php => Oauth2Exception.php} | 4 ++-- src/Exception/AccountLogin/OtherErrorException.php | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) rename src/Exception/AccountLogin/{HydraErrorException.php => Oauth2Exception.php} (90%) diff --git a/controllers/admin/AdminOAuth2PsAccountsController.php b/controllers/admin/AdminOAuth2PsAccountsController.php index 484f042f0..9fa8b64df 100644 --- a/controllers/admin/AdminOAuth2PsAccountsController.php +++ b/controllers/admin/AdminOAuth2PsAccountsController.php @@ -24,7 +24,7 @@ use PrestaShop\Module\PsAccounts\Exception\AccountLogin\AccountLoginException; use PrestaShop\Module\PsAccounts\Exception\AccountLogin\EmailNotVerifiedException; use PrestaShop\Module\PsAccounts\Exception\AccountLogin\EmployeeNotFoundException; -use PrestaShop\Module\PsAccounts\Exception\AccountLogin\HydraErrorException; +use PrestaShop\Module\PsAccounts\Exception\AccountLogin\Oauth2Exception; use PrestaShop\Module\PsAccounts\Exception\AccountLogin\OtherErrorException; use PrestaShop\Module\PsAccounts\Provider\OAuth2\Oauth2ClientShopProvider; use PrestaShop\Module\PsAccounts\Provider\OAuth2\Oauth2LoginTrait; @@ -83,7 +83,7 @@ public function display(): void try { $this->oauth2Login(); } catch (IdentityProviderException $e) { - $this->onLoginFailed(new HydraErrorException(null, $e->getMessage())); + $this->onLoginFailed(new Oauth2Exception(null, $e->getMessage())); } catch (EmailNotVerifiedException | EmployeeNotFoundException $e) { $this->onLoginFailed($e); } catch (Exception $e) { diff --git a/src/Exception/AccountLogin/HydraErrorException.php b/src/Exception/AccountLogin/Oauth2Exception.php similarity index 90% rename from src/Exception/AccountLogin/HydraErrorException.php rename to src/Exception/AccountLogin/Oauth2Exception.php index e39fc2f2e..965fb3aa7 100644 --- a/src/Exception/AccountLogin/HydraErrorException.php +++ b/src/Exception/AccountLogin/Oauth2Exception.php @@ -22,11 +22,11 @@ use PrestaShop\OAuth2\Client\Provider\PrestaShopUser; -class HydraErrorException extends AccountLoginException +class Oauth2Exception extends AccountLoginException { public function __construct( ?PrestaShopUser $user, - string $message = 'Your account email is not verified', + string $message = 'OAuth2 error', string $type = 'error_from_hydra' ) { parent::__construct($user, $message, $type); diff --git a/src/Exception/AccountLogin/OtherErrorException.php b/src/Exception/AccountLogin/OtherErrorException.php index b5f41baf3..e54d05139 100644 --- a/src/Exception/AccountLogin/OtherErrorException.php +++ b/src/Exception/AccountLogin/OtherErrorException.php @@ -26,7 +26,7 @@ class OtherErrorException extends AccountLoginException { public function __construct( ?PrestaShopUser $user, - string $message = 'Your account email is not verified', + string $message = 'Other error', string $type = 'error_other' ) { parent::__construct($user, $message, $type); From eb3cfd4c70680a108f3d7cdd4a62df05d4a17142 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Schoenenberger?= Date: Tue, 31 Jan 2023 18:30:02 +0100 Subject: [PATCH 36/50] refactor: implement group call instead of track context key --- .../admin/AdminOAuth2PsAccountsController.php | 10 +++++-- ps_accounts.php | 10 +++---- src/Service/AnalyticsService.php | 27 ++++++++++--------- 3 files changed, 27 insertions(+), 20 deletions(-) diff --git a/controllers/admin/AdminOAuth2PsAccountsController.php b/controllers/admin/AdminOAuth2PsAccountsController.php index 9fa8b64df..956d1476e 100644 --- a/controllers/admin/AdminOAuth2PsAccountsController.php +++ b/controllers/admin/AdminOAuth2PsAccountsController.php @@ -151,9 +151,12 @@ private function initUserSession(PrestaShopUser $user): bool ); $this->analyticsService->trackUserSignedIntoApp( $user->getId(), - (string) $this->psAccountsService->getShopUuid() ?? null, 'smb-edition' ); + $this->analyticsService->group( + $user->getId(), + (string) $this->psAccountsService->getShopUuid() + ); } return true; @@ -212,10 +215,13 @@ private function onLoginFailed(AccountLoginException $e): void ); $this->analyticsService->trackBackOfficeSSOSignInFailed( $user->getId(), - (string) $this->psAccountsService->getShopUuid() ?? null, $e->getType(), $e->getMessage() ); + $this->analyticsService->group( + $user->getId(), + (string) $this->psAccountsService->getShopUuid() + ); } $this->oauth2ErrorLog($e->getMessage()); diff --git a/ps_accounts.php b/ps_accounts.php index 298e84a29..3fa9d5ddc 100644 --- a/ps_accounts.php +++ b/ps_accounts.php @@ -632,11 +632,8 @@ public function hookActionAdminLoginControllerLoginAfter($params) $email = $employee->email; } $analyticsService->identify($uid, null, $email); - $analyticsService->trackUserSignedIntoBackOfficeLocally( - $email, - $uid, - (string) $psAccountsService->getShopUuid() ?? null - ); + $analyticsService->trackUserSignedIntoBackOfficeLocally($uid, $email); + $analyticsService->group($uid, (string) $psAccountsService->getShopUuid()); } } @@ -766,6 +763,7 @@ public function getCustomHooks() public function isShopEdition(): bool { - return Module::isEnabled('smb_edition'); + return true; + //return Module::isEnabled('smb_edition'); } } diff --git a/src/Service/AnalyticsService.php b/src/Service/AnalyticsService.php index 00e678249..f00134d37 100644 --- a/src/Service/AnalyticsService.php +++ b/src/Service/AnalyticsService.php @@ -17,45 +17,36 @@ public function track(array $message): void Segment::flush(); } - public function trackUserSignedIntoApp(string $userUid, ?string $shopUid, string $application): void + public function trackUserSignedIntoApp(?string $userUid, string $application): void { $this->track([ 'event' => 'User Signed Into App', 'userId' => $userUid, 'anonymousId' => $this->getAnonymousId(), - 'context' => [ - 'groupId' => $shopUid, - ], 'properties' => [ 'application' => $application, ], ]); } - public function trackUserSignedIntoBackOfficeLocally(string $userEmail, ?string $userUid, string $shopUid): void + public function trackUserSignedIntoBackOfficeLocally(?string $userUid, string $userEmail): void { $this->track([ 'event' => 'User Signed Into Back Office Locally', 'userId' => $userUid, 'anonymousId' => $this->getAnonymousId(), - 'context' => [ - 'groupId' => $shopUid, - ], 'properties' => [ 'email' => $userEmail, ], ]); } - public function trackBackOfficeSSOSignInFailed(string $userUid, ?string $shopUid, ?string $type, ?string $description): void + public function trackBackOfficeSSOSignInFailed(?string $userUid, ?string $type, ?string $description): void { $this->track([ 'event' => 'Back Office SSO Sign In Failed', 'userId' => $userUid, 'anonymousId' => $this->getAnonymousId(), - 'context' => [ - 'groupId' => $shopUid, - ], 'properties' => [ 'type' => $type, 'description' => $description, @@ -108,6 +99,18 @@ public function identify(?string $userUid, ?string $name, ?string $email): void ]); } + public function group(?string $userUid, string $shopUid): void + { + Segment::group([ + 'userId' => $userUid, + 'groupId' => $shopUid, + 'anonymous_id' => $this->getAnonymousId(), +// "traits" => [ +// "name" => $shopName, +// ] + ]); + } + protected function getAnonymousId(): ?string { return $_COOKIE['ajs_anonymous_id'] ?? session_id(); From 9c71048f2db4f1b1cb06f59c8ff429b61313fc70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Schoenenberger?= Date: Tue, 31 Jan 2023 18:30:59 +0100 Subject: [PATCH 37/50] refactor: implement group call instead of track context key --- ps_accounts.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ps_accounts.php b/ps_accounts.php index 3fa9d5ddc..0e3e83183 100644 --- a/ps_accounts.php +++ b/ps_accounts.php @@ -763,7 +763,6 @@ public function getCustomHooks() public function isShopEdition(): bool { - return true; - //return Module::isEnabled('smb_edition'); + return Module::isEnabled('smb_edition'); } } From b376d0548a9d3deddfaaeea97d72909cf78fe791 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Schoenenberger?= Date: Tue, 31 Jan 2023 20:17:05 +0100 Subject: [PATCH 38/50] fix: failsafe group call --- src/Service/AnalyticsService.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/Service/AnalyticsService.php b/src/Service/AnalyticsService.php index f00134d37..deb196d73 100644 --- a/src/Service/AnalyticsService.php +++ b/src/Service/AnalyticsService.php @@ -101,14 +101,16 @@ public function identify(?string $userUid, ?string $name, ?string $email): void public function group(?string $userUid, string $shopUid): void { - Segment::group([ - 'userId' => $userUid, - 'groupId' => $shopUid, - 'anonymous_id' => $this->getAnonymousId(), + if (!empty($shopUid)) { + Segment::group([ + 'userId' => $userUid, + 'groupId' => $shopUid, + 'anonymous_id' => $this->getAnonymousId(), // "traits" => [ // "name" => $shopName, // ] - ]); + ]); + } } protected function getAnonymousId(): ?string From e47f799d722a9510373106e0feceac37510bffcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Schoenenberger?= Date: Wed, 1 Feb 2023 10:38:24 +0100 Subject: [PATCH 39/50] feat: catch and trace locally tracking exceptions fix: typo in anonymousId case --- config/common.yml | 1 + .../admin/AdminOAuth2PsAccountsController.php | 16 +++--- src/Service/AnalyticsService.php | 56 +++++++++++++------ 3 files changed, 49 insertions(+), 24 deletions(-) diff --git a/config/common.yml b/config/common.yml index 5ef85f91a..be9947b72 100644 --- a/config/common.yml +++ b/config/common.yml @@ -86,6 +86,7 @@ services: public: true arguments: - '%ps_accounts.segment_write_key%' + - '@ps_accounts.logger' ##################### # providers diff --git a/controllers/admin/AdminOAuth2PsAccountsController.php b/controllers/admin/AdminOAuth2PsAccountsController.php index 905007053..44eb5514f 100644 --- a/controllers/admin/AdminOAuth2PsAccountsController.php +++ b/controllers/admin/AdminOAuth2PsAccountsController.php @@ -151,14 +151,14 @@ private function initUserSession(PrestaShopUser $user): bool $user->getName(), $user->getEmail() ); - $this->analyticsService->trackUserSignedIntoApp( - $user->getId(), - 'smb-edition' - ); $this->analyticsService->group( $user->getId(), (string) $this->psAccountsService->getShopUuid() ); + $this->analyticsService->trackUserSignedIntoApp( + $user->getId(), + 'smb-edition' + ); } return true; @@ -218,15 +218,15 @@ private function onLoginFailed(AccountLoginException $e): void $user->getName(), $user->getEmail() ); + $this->analyticsService->group( + $user->getId(), + (string) $this->psAccountsService->getShopUuid() + ); $this->analyticsService->trackBackOfficeSSOSignInFailed( $user->getId(), $e->getType(), $e->getMessage() ); - $this->analyticsService->group( - $user->getId(), - (string) $this->psAccountsService->getShopUuid() - ); } $this->oauth2ErrorLog($e->getMessage()); diff --git a/src/Service/AnalyticsService.php b/src/Service/AnalyticsService.php index deb196d73..a8c524879 100644 --- a/src/Service/AnalyticsService.php +++ b/src/Service/AnalyticsService.php @@ -2,19 +2,30 @@ namespace PrestaShop\Module\PsAccounts\Service; +use Monolog\Logger; use Segment; class AnalyticsService { - public function __construct(string $segmentWriteKey) + /** + * @var Logger + */ + private $logger; + + public function __construct(string $segmentWriteKey, Logger $logger) { Segment::init($segmentWriteKey); + $this->logger = $logger; } public function track(array $message): void { - Segment::track($message); - Segment::flush(); + try { + Segment::track($message); + Segment::flush(); + } catch (\Exception $e) { + $this->logger->error($e->getMessage(), $message); + } } public function trackUserSignedIntoApp(?string $userUid, string $application): void @@ -63,7 +74,7 @@ public function page( ?string $title = null, ?string $url = null ): void { - Segment::page([ + $message = [ 'userId' => $userId, 'anonymousId' => $this->getAnonymousId(), 'name' => $name, @@ -74,8 +85,14 @@ public function page( 'title' => $title, 'url' => $url !== null ? $url : $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'], ], - ]); - Segment::flush(); + ]; + try { + Segment::page($message); + Segment::flush(); + } catch (\Exception $e) { + $this->logger->error($e->getMessage(), $message); + } + } public function pageAccountsBoLogin(?string $userUid = null): void @@ -90,26 +107,33 @@ public function pageLocalBoLogin(?string $userUid = null): void public function identify(?string $userUid, ?string $name, ?string $email): void { - Segment::identify([ + $message = [ 'userId' => $userUid, - // aggregate any previous anonymous call - 'anonymous_id' => $this->getAnonymousId(), + 'anonymousId' => $this->getAnonymousId(), 'traits' => [$name ? ['name' => $name] : []] + [$email ? ['email' => $email] : []], - ]); + ]; + try { + Segment::identify($message); + } catch (\Exception $e) { + $this->logger->error($e->getMessage(), $message); + } } public function group(?string $userUid, string $shopUid): void { - if (!empty($shopUid)) { - Segment::group([ - 'userId' => $userUid, - 'groupId' => $shopUid, - 'anonymous_id' => $this->getAnonymousId(), + $message = [ + 'userId' => $userUid, + 'groupId' => $shopUid, + 'anonymousId' => $this->getAnonymousId(), // "traits" => [ // "name" => $shopName, // ] - ]); + ]; + try { + Segment::group($message); + } catch (\Exception $e) { + $this->logger->error($e->getMessage(), $message); } } From ba145bcc2134d9d941b00233a91caba504ac3df8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Schoenenberger?= Date: Wed, 1 Feb 2023 10:41:05 +0100 Subject: [PATCH 40/50] chore: cs-fixer --- ps_accounts.php | 2 +- src/Service/AnalyticsService.php | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/ps_accounts.php b/ps_accounts.php index ecda2bb84..89c776950 100644 --- a/ps_accounts.php +++ b/ps_accounts.php @@ -637,8 +637,8 @@ public function hookActionAdminLoginControllerLoginAfter($params) $email = $employee->email; } $analyticsService->identify($uid, null, $email); - $analyticsService->trackUserSignedIntoBackOfficeLocally($uid, $email); $analyticsService->group($uid, (string) $psAccountsService->getShopUuid()); + $analyticsService->trackUserSignedIntoBackOfficeLocally($uid, $email); } } diff --git a/src/Service/AnalyticsService.php b/src/Service/AnalyticsService.php index a8c524879..5ce9faea2 100644 --- a/src/Service/AnalyticsService.php +++ b/src/Service/AnalyticsService.php @@ -92,7 +92,6 @@ public function page( } catch (\Exception $e) { $this->logger->error($e->getMessage(), $message); } - } public function pageAccountsBoLogin(?string $userUid = null): void From c7ffe4a3f06b8f3bdbf0bb2cb12af8141283a202 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Schoenenberger?= Date: Wed, 1 Feb 2023 18:22:52 +0100 Subject: [PATCH 41/50] feat: manage ajs_anonymous_id from backend --- src/Service/AnalyticsService.php | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/Service/AnalyticsService.php b/src/Service/AnalyticsService.php index 5ce9faea2..f21477649 100644 --- a/src/Service/AnalyticsService.php +++ b/src/Service/AnalyticsService.php @@ -7,6 +7,8 @@ class AnalyticsService { + const COOKIE_ANONYMOUS_ID = 'ajs_anonymous_id'; + /** * @var Logger */ @@ -16,6 +18,7 @@ public function __construct(string $segmentWriteKey, Logger $logger) { Segment::init($segmentWriteKey); $this->logger = $logger; + $this->initAnonymousId(); } public function track(array $message): void @@ -136,8 +139,20 @@ public function group(?string $userUid, string $shopUid): void } } - protected function getAnonymousId(): ?string + public function initAnonymousId(): void + { + if (empty($_COOKIE[self::COOKIE_ANONYMOUS_ID])) { + $this->refreshAnonymousId(); + } + } + + public function getAnonymousId(): string + { + return $_COOKIE[self::COOKIE_ANONYMOUS_ID]; + } + + public function refreshAnonymousId(): void { - return $_COOKIE['ajs_anonymous_id'] ?? session_id(); + setcookie(self::COOKIE_ANONYMOUS_ID, uniqid("", true), time()+3600); } } From b6c62ad3ceadd37184066d99aa87ab12856df298 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Schoenenberger?= Date: Wed, 1 Feb 2023 18:23:45 +0100 Subject: [PATCH 42/50] feat: disable oauth2 logout based on config parameter availability --- src/Provider/OAuth2/Oauth2LogoutTrait.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/Provider/OAuth2/Oauth2LogoutTrait.php b/src/Provider/OAuth2/Oauth2LogoutTrait.php index 3393f2a17..91af5a28b 100644 --- a/src/Provider/OAuth2/Oauth2LogoutTrait.php +++ b/src/Provider/OAuth2/Oauth2LogoutTrait.php @@ -28,11 +28,22 @@ abstract protected function getProvider(): Oauth2ClientShopProvider; abstract protected function getAccessToken(): ?AccessToken; + public function isOauth2LogoutEnabled() + { +// $prop = 'oauth2LogoutEnabled'; +// return property_exists($this, $prop) && (bool)$this->$prop; + return $this->hasParameter('ps_accounts.oauth2_url_session_logout'); + } + /** * @throws \Exception */ public function oauth2Logout(): void { + if (!$this->isOauth2LogoutEnabled()) { + return; + } + if (!isset($_GET[Oauth2ClientShopProvider::QUERY_LOGOUT_CALLBACK_PARAM])) { $accessToken = $this->getAccessToken(); From 27b7002c37170bfff2e5dfc08749aba3f1d8b7fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Schoenenberger?= Date: Wed, 1 Feb 2023 18:30:55 +0100 Subject: [PATCH 43/50] refactor: better implementation of logout disable --- ps_accounts.php | 5 +++++ src/Provider/OAuth2/Oauth2LogoutTrait.php | 7 +------ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ps_accounts.php b/ps_accounts.php index 89c776950..6e1351417 100644 --- a/ps_accounts.php +++ b/ps_accounts.php @@ -810,4 +810,9 @@ protected function getAccessToken(): ?League\OAuth2\Client\Token\AccessToken return $accessToken; } + + protected function isOauth2LogoutEnabled(): bool + { + return $this->hasParameter('ps_accounts.oauth2_url_session_logout'); + } } diff --git a/src/Provider/OAuth2/Oauth2LogoutTrait.php b/src/Provider/OAuth2/Oauth2LogoutTrait.php index 91af5a28b..91cf584c4 100644 --- a/src/Provider/OAuth2/Oauth2LogoutTrait.php +++ b/src/Provider/OAuth2/Oauth2LogoutTrait.php @@ -28,12 +28,7 @@ abstract protected function getProvider(): Oauth2ClientShopProvider; abstract protected function getAccessToken(): ?AccessToken; - public function isOauth2LogoutEnabled() - { -// $prop = 'oauth2LogoutEnabled'; -// return property_exists($this, $prop) && (bool)$this->$prop; - return $this->hasParameter('ps_accounts.oauth2_url_session_logout'); - } + abstract protected function isOauth2LogoutEnabled(): bool; /** * @throws \Exception From 438ab829127136820687eb5dbb18cb45355f9f6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Schoenenberger?= Date: Thu, 2 Feb 2023 11:09:16 +0100 Subject: [PATCH 44/50] chore: cs-fixer --- src/Service/AnalyticsService.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Service/AnalyticsService.php b/src/Service/AnalyticsService.php index f21477649..b7bf4ef00 100644 --- a/src/Service/AnalyticsService.php +++ b/src/Service/AnalyticsService.php @@ -153,6 +153,6 @@ public function getAnonymousId(): string public function refreshAnonymousId(): void { - setcookie(self::COOKIE_ANONYMOUS_ID, uniqid("", true), time()+3600); + setcookie(self::COOKIE_ANONYMOUS_ID, uniqid('', true), time() + 3600); } } From 4d0d0ab1dec52d2e9f6cb89a73fa22b4243cb70a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Schoenenberger?= Date: Thu, 2 Feb 2023 11:20:46 +0100 Subject: [PATCH 45/50] chore: callback uris examples --- src/Provider/OAuth2/Oauth2ClientShopProvider.php | 10 ++++++++++ src/Service/AnalyticsService.php | 2 ++ 2 files changed, 12 insertions(+) diff --git a/src/Provider/OAuth2/Oauth2ClientShopProvider.php b/src/Provider/OAuth2/Oauth2ClientShopProvider.php index efa6b3c52..f272c46ad 100644 --- a/src/Provider/OAuth2/Oauth2ClientShopProvider.php +++ b/src/Provider/OAuth2/Oauth2ClientShopProvider.php @@ -126,6 +126,11 @@ public function getResourceOwnerDetailsUrl(AccessToken $token): string ); } + /** + * @example http://my-shop.mydomain/admin-path/index.php?controller=AdminOAuth2PsAccounts + * + * @return string + */ public function getRedirectUri(): string { return $this->context->link->getAdminLink('AdminOAuth2PsAccounts', false); @@ -144,6 +149,11 @@ public function getBaseSessionLogoutUrl(): string ); } + /** + * @example http://my-shop.mydomain/admin-path/index.php?controller=AdminLogin&logout=1&oauth2Callback=1 + * + * @return string + */ public function getPostLogoutRedirectUri(): string { return $this->context->link->getAdminLink('AdminLogin', false, [], [ diff --git a/src/Service/AnalyticsService.php b/src/Service/AnalyticsService.php index b7bf4ef00..435056f75 100644 --- a/src/Service/AnalyticsService.php +++ b/src/Service/AnalyticsService.php @@ -153,6 +153,8 @@ public function getAnonymousId(): string public function refreshAnonymousId(): void { + // FIXME: UUID v5 + // FIXME: lifetime based on session setcookie(self::COOKIE_ANONYMOUS_ID, uniqid('', true), time() + 3600); } } From 0685e9acad5ca1791411cc41cc578d0d85eeb6ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Schoenenberger?= Date: Thu, 2 Feb 2023 15:48:01 +0100 Subject: [PATCH 46/50] refactor: uuid v4 for anonymous id --- composer.json | 3 +- composer.lock | 237 ++++++++++++++++++++++++++++++- src/Service/AnalyticsService.php | 5 +- 3 files changed, 240 insertions(+), 5 deletions(-) diff --git a/composer.json b/composer.json index e106b665a..7e8db7a28 100644 --- a/composer.json +++ b/composer.json @@ -33,7 +33,8 @@ "sentry/sentry": "^1.0", "league/oauth2-client": "^2.6", "prestashopcorp/oauth2-prestashop": "^1.1.0", - "segmentio/analytics-php": "^1.8" + "segmentio/analytics-php": "^1.8", + "ramsey/uuid": "^4.2" }, "require-dev": { "phpunit/phpunit": "^8.5", diff --git a/composer.lock b/composer.lock index 9b126120f..994e7228c 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,68 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "0c75cc0ac5b4efd2762b593db9c56824", + "content-hash": "27c9bc897688029c658642906984f059", "packages": [ + { + "name": "brick/math", + "version": "0.9.3", + "source": { + "type": "git", + "url": "https://github.com/brick/math.git", + "reference": "ca57d18f028f84f777b2168cd1911b0dee2343ae" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/brick/math/zipball/ca57d18f028f84f777b2168cd1911b0dee2343ae", + "reference": "ca57d18f028f84f777b2168cd1911b0dee2343ae", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.2", + "phpunit/phpunit": "^7.5.15 || ^8.5 || ^9.0", + "vimeo/psalm": "4.9.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "Brick\\Math\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Arbitrary-precision arithmetic library", + "keywords": [ + "Arbitrary-precision", + "BigInteger", + "BigRational", + "arithmetic", + "bigdecimal", + "bignum", + "brick", + "math" + ], + "support": { + "issues": "https://github.com/brick/math/issues", + "source": "https://github.com/brick/math/tree/0.9.3" + }, + "funding": [ + { + "url": "https://github.com/BenMorel", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/brick/math", + "type": "tidelift" + } + ], + "time": "2021-08-15T20:50:18+00:00" + }, { "name": "guzzlehttp/guzzle", "version": "7.5.0", @@ -1236,6 +1296,181 @@ }, "time": "2019-03-08T08:55:37+00:00" }, + { + "name": "ramsey/collection", + "version": "1.1.4", + "source": { + "type": "git", + "url": "https://github.com/ramsey/collection.git", + "reference": "ab2237657ad99667a5143e32ba2683c8029563d4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ramsey/collection/zipball/ab2237657ad99667a5143e32ba2683c8029563d4", + "reference": "ab2237657ad99667a5143e32ba2683c8029563d4", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8" + }, + "require-dev": { + "captainhook/captainhook": "^5.3", + "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0", + "ergebnis/composer-normalize": "^2.6", + "fakerphp/faker": "^1.5", + "hamcrest/hamcrest-php": "^2", + "jangregor/phpstan-prophecy": "^0.8", + "mockery/mockery": "^1.3", + "phpstan/extension-installer": "^1", + "phpstan/phpstan": "^0.12.32", + "phpstan/phpstan-mockery": "^0.12.5", + "phpstan/phpstan-phpunit": "^0.12.11", + "phpunit/phpunit": "^8.5 || ^9", + "psy/psysh": "^0.10.4", + "slevomat/coding-standard": "^6.3", + "squizlabs/php_codesniffer": "^3.5", + "vimeo/psalm": "^4.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Ramsey\\Collection\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ben Ramsey", + "email": "ben@benramsey.com", + "homepage": "https://benramsey.com" + } + ], + "description": "A PHP 7.2+ library for representing and manipulating collections.", + "keywords": [ + "array", + "collection", + "hash", + "map", + "queue", + "set" + ], + "support": { + "issues": "https://github.com/ramsey/collection/issues", + "source": "https://github.com/ramsey/collection/tree/1.1.4" + }, + "funding": [ + { + "url": "https://github.com/ramsey", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/ramsey/collection", + "type": "tidelift" + } + ], + "time": "2021-07-30T00:58:27+00:00" + }, + { + "name": "ramsey/uuid", + "version": "4.2.3", + "source": { + "type": "git", + "url": "https://github.com/ramsey/uuid.git", + "reference": "fc9bb7fb5388691fd7373cd44dcb4d63bbcf24df" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/fc9bb7fb5388691fd7373cd44dcb4d63bbcf24df", + "reference": "fc9bb7fb5388691fd7373cd44dcb4d63bbcf24df", + "shasum": "" + }, + "require": { + "brick/math": "^0.8 || ^0.9", + "ext-json": "*", + "php": "^7.2 || ^8.0", + "ramsey/collection": "^1.0", + "symfony/polyfill-ctype": "^1.8", + "symfony/polyfill-php80": "^1.14" + }, + "replace": { + "rhumsaa/uuid": "self.version" + }, + "require-dev": { + "captainhook/captainhook": "^5.10", + "captainhook/plugin-composer": "^5.3", + "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0", + "doctrine/annotations": "^1.8", + "ergebnis/composer-normalize": "^2.15", + "mockery/mockery": "^1.3", + "moontoast/math": "^1.1", + "paragonie/random-lib": "^2", + "php-mock/php-mock": "^2.2", + "php-mock/php-mock-mockery": "^1.3", + "php-parallel-lint/php-parallel-lint": "^1.1", + "phpbench/phpbench": "^1.0", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^0.12", + "phpstan/phpstan-mockery": "^0.12", + "phpstan/phpstan-phpunit": "^0.12", + "phpunit/phpunit": "^8.5 || ^9", + "slevomat/coding-standard": "^7.0", + "squizlabs/php_codesniffer": "^3.5", + "vimeo/psalm": "^4.9" + }, + "suggest": { + "ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.", + "ext-ctype": "Enables faster processing of character classification using ctype functions.", + "ext-gmp": "Enables faster math with arbitrary-precision integers using GMP.", + "ext-uuid": "Enables the use of PeclUuidTimeGenerator and PeclUuidRandomGenerator.", + "paragonie/random-lib": "Provides RandomLib for use with the RandomLibAdapter", + "ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.x-dev" + }, + "captainhook": { + "force-install": true + } + }, + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Ramsey\\Uuid\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A PHP library for generating and working with universally unique identifiers (UUIDs).", + "keywords": [ + "guid", + "identifier", + "uuid" + ], + "support": { + "issues": "https://github.com/ramsey/uuid/issues", + "source": "https://github.com/ramsey/uuid/tree/4.2.3" + }, + "funding": [ + { + "url": "https://github.com/ramsey", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/ramsey/uuid", + "type": "tidelift" + } + ], + "time": "2021-09-25T23:10:38+00:00" + }, { "name": "segmentio/analytics-php", "version": "1.8.0", diff --git a/src/Service/AnalyticsService.php b/src/Service/AnalyticsService.php index 435056f75..b0d062fbd 100644 --- a/src/Service/AnalyticsService.php +++ b/src/Service/AnalyticsService.php @@ -3,6 +3,7 @@ namespace PrestaShop\Module\PsAccounts\Service; use Monolog\Logger; +use Ramsey\Uuid\Uuid; use Segment; class AnalyticsService @@ -153,8 +154,6 @@ public function getAnonymousId(): string public function refreshAnonymousId(): void { - // FIXME: UUID v5 - // FIXME: lifetime based on session - setcookie(self::COOKIE_ANONYMOUS_ID, uniqid('', true), time() + 3600); + setcookie(self::COOKIE_ANONYMOUS_ID, Uuid::uuid4(), time() + 3600); } } From 6545b456d9551da74811357c7064de9d32edb722 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Schoenenberger?= Date: Fri, 3 Feb 2023 16:41:23 +0100 Subject: [PATCH 47/50] refactor: anonymous id management --- src/Service/AnalyticsService.php | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/src/Service/AnalyticsService.php b/src/Service/AnalyticsService.php index b0d062fbd..e14f503c4 100644 --- a/src/Service/AnalyticsService.php +++ b/src/Service/AnalyticsService.php @@ -15,11 +15,16 @@ class AnalyticsService */ private $logger; + /** + * @var string + */ + private static $anonymousId; + public function __construct(string $segmentWriteKey, Logger $logger) { Segment::init($segmentWriteKey); - $this->logger = $logger; $this->initAnonymousId(); + $this->logger = $logger; } public function track(array $message): void @@ -140,20 +145,24 @@ public function group(?string $userUid, string $shopUid): void } } - public function initAnonymousId(): void - { - if (empty($_COOKIE[self::COOKIE_ANONYMOUS_ID])) { - $this->refreshAnonymousId(); - } - } - public function getAnonymousId(): string { - return $_COOKIE[self::COOKIE_ANONYMOUS_ID]; + $this->initAnonymousId(); + return self::$anonymousId; } - public function refreshAnonymousId(): void + /** + * @return void + */ + private function initAnonymousId(): void { - setcookie(self::COOKIE_ANONYMOUS_ID, Uuid::uuid4(), time() + 3600); + if (!isset(self::$anonymousId)) { + if (!isset($_COOKIE[self::COOKIE_ANONYMOUS_ID])) { + self::$anonymousId = Uuid::uuid4(); + setcookie(self::COOKIE_ANONYMOUS_ID, self::$anonymousId, time() + 3600); + } else { + self::$anonymousId = $_COOKIE[self::COOKIE_ANONYMOUS_ID]; + } + } } } From d032d57b46b49307989e75226924b8844b99d13d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Schoenenberger?= Date: Fri, 3 Feb 2023 16:43:00 +0100 Subject: [PATCH 48/50] chore: cs-fixer --- src/Service/AnalyticsService.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Service/AnalyticsService.php b/src/Service/AnalyticsService.php index e14f503c4..577714a9e 100644 --- a/src/Service/AnalyticsService.php +++ b/src/Service/AnalyticsService.php @@ -148,6 +148,7 @@ public function group(?string $userUid, string $shopUid): void public function getAnonymousId(): string { $this->initAnonymousId(); + return self::$anonymousId; } From bdcd330b3dec3738d507d8b1b047925b97a74136 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Schoenenberger?= Date: Fri, 3 Feb 2023 16:46:33 +0100 Subject: [PATCH 49/50] chore: cs-fixer --- src/Service/AnalyticsService.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Service/AnalyticsService.php b/src/Service/AnalyticsService.php index 577714a9e..8fde771be 100644 --- a/src/Service/AnalyticsService.php +++ b/src/Service/AnalyticsService.php @@ -152,9 +152,6 @@ public function getAnonymousId(): string return self::$anonymousId; } - /** - * @return void - */ private function initAnonymousId(): void { if (!isset(self::$anonymousId)) { From 5e46fb8e9474ce855737f3434a8cb227727404e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Schoenenberger?= Date: Mon, 6 Feb 2023 11:37:57 +0100 Subject: [PATCH 50/50] fix: persistent login error --- controllers/admin/AdminLoginController.php | 2 +- controllers/admin/AdminOAuth2PsAccountsController.php | 10 ---------- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/controllers/admin/AdminLoginController.php b/controllers/admin/AdminLoginController.php index cf4ea0093..4c66e4ef0 100644 --- a/controllers/admin/AdminLoginController.php +++ b/controllers/admin/AdminLoginController.php @@ -141,7 +141,7 @@ public function createPsAccountsLoginTemplate() $isoCode = $this->context->currentLocale->getCode(); $this->context->smarty->assign('uriHelpCenter', $this->getUriHelpCenter($isoCode)); - $this->context->smarty->assign('loginError', $session->get('loginError')); + $this->context->smarty->assign('loginError', $session->remove('loginError')); $this->context->smarty->assign('meta_title', ''); $this->context->smarty->assign('ssoResendVerificationEmail', $this->psAccountsModule->getParameter('ps_accounts.sso_resend_verification_email_url') diff --git a/controllers/admin/AdminOAuth2PsAccountsController.php b/controllers/admin/AdminOAuth2PsAccountsController.php index 44eb5514f..c5ef43314 100644 --- a/controllers/admin/AdminOAuth2PsAccountsController.php +++ b/controllers/admin/AdminOAuth2PsAccountsController.php @@ -143,8 +143,6 @@ private function initUserSession(PrestaShopUser $user): bool $cookie->write(); - $this->unsetLoginError(); - if ($this->module->isShopEdition()) { $this->analyticsService->identify( $user->getId(), @@ -270,12 +268,4 @@ private function setLoginError(string $error): void { $this->getSession()->set('loginError', $error); } - - /** - * @throws ContainerNotFoundException - */ - private function unsetLoginError(): void - { - $this->getSession()->remove('loginError'); - } }