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/composer.json b/composer.json index 9692f5252..7e8db7a28 100644 --- a/composer.json +++ b/composer.json @@ -32,7 +32,9 @@ "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.1.0", + "segmentio/analytics-php": "^1.8", + "ramsey/uuid": "^4.2" }, "require-dev": { "phpunit/phpunit": "^8.5", diff --git a/composer.lock b/composer.lock index 2c19fe8de..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": "ed14555b806ff75706a0827cb6ed8362", + "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", @@ -618,16 +678,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 +768,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 +784,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 +891,16 @@ }, { "name": "prestashopcorp/oauth2-prestashop", - "version": "dev-main", + "version": "v1.1.0", "source": { "type": "git", "url": "https://github.com/PrestaShopCorp/oauth2-prestashop.git", - "reference": "30cb923042320a88601045beec685ff2a18630f8" + "reference": "d3b065a3b8a118400a62433cacde8b3712c3f548" }, "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/d3b065a3b8a118400a62433cacde8b3712c3f548", + "reference": "d3b065a3b8a118400a62433cacde8b3712c3f548", "shasum": "" }, "require": { @@ -852,7 +912,6 @@ "phpunit/phpunit": "^8.0 || ^9.0", "prestashop/php-dev-tools": "^4.2" }, - "default-branch": true, "type": "library", "autoload": { "psr-4": { @@ -882,9 +941,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.1.0" }, - "time": "2022-11-08T17:58:41+00:00" + "time": "2023-01-23T13:59:29+00:00" }, { "name": "psr/cache", @@ -1237,6 +1296,236 @@ }, "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", + "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", @@ -2228,16 +2517,16 @@ }, { "name": "symfony/var-exporter", - "version": "v5.4.10", + "version": "v5.4.19", "source": { "type": "git", "url": "https://github.com/symfony/var-exporter.git", - "reference": "8fc03ee75eeece3d9be1ef47d26d79bea1afb340" + "reference": "2a1d06fcf2b30829d6c01dae8e6e188424d1f8f6" }, "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/2a1d06fcf2b30829d6c01dae8e6e188424d1f8f6", + "reference": "2a1d06fcf2b30829d6c01dae8e6e188424d1f8f6", "shasum": "" }, "require": { @@ -2281,7 +2570,7 @@ "serialize" ], "support": { - "source": "https://github.com/symfony/var-exporter/tree/v5.4.10" + "source": "https://github.com/symfony/var-exporter/tree/v5.4.19" }, "funding": [ { @@ -2297,7 +2586,7 @@ "type": "tidelift" } ], - "time": "2022-05-27T12:56:18+00:00" + "time": "2023-01-12T16:39:29+00:00" }, { "name": "symfony/yaml", @@ -2592,32 +2881,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": { @@ -2659,36 +2951,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": { @@ -2715,7 +3050,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": [ { @@ -2731,35 +3066,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/", @@ -2791,7 +3128,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": [ { @@ -2807,7 +3144,7 @@ "type": "tidelift" } ], - "time": "2022-02-28T11:07:21+00:00" + "time": "2022-12-14T08:49:07+00:00" }, { "name": "friendsofphp/php-cs-fixer", @@ -3553,16 +3890,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": { @@ -3630,7 +3967,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": [ { @@ -3646,7 +3983,7 @@ "type": "tidelift" } ], - "time": "2022-10-28T05:57:37+00:00" + "time": "2023-01-26T08:30:25+00:00" }, { "name": "prestashop/autoindex", @@ -4954,16 +5291,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": { @@ -5003,7 +5340,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": [ { @@ -5019,7 +5356,7 @@ "type": "tidelift" } ], - "time": "2022-07-20T13:00:38+00:00" + "time": "2023-01-01T08:32:19+00:00" }, { "name": "symfony/polyfill-mbstring", @@ -5182,16 +5519,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": { @@ -5224,7 +5561,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": [ { @@ -5240,20 +5577,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": { @@ -5286,7 +5623,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": [ { @@ -5302,7 +5639,7 @@ "type": "tidelift" } ], - "time": "2022-09-28T13:19:49+00:00" + "time": "2023-01-01T08:32:19+00:00" }, { "name": "theseer/tokenizer", @@ -5357,9 +5694,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "prestashopcorp/oauth2-prestashop": 20 - }, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { diff --git a/config/common.yml b/config/common.yml index 2887d7ff3..be9947b72 100644 --- a/config/common.yml +++ b/config/common.yml @@ -81,6 +81,13 @@ 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%' + - '@ps_accounts.logger' + ##################### # providers diff --git a/config/config.yml.dist b/config/config.yml.dist index 1388fa4a4..2ba862a1a 100644 --- a/config/config.yml.dist +++ b/config/config.yml.dist @@ -16,7 +16,7 @@ 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 ps_accounts.accounts_vue_cdn_url: 'https://unpkg.com/prestashop_accounts_vue_components@3/dist/psaccountsVue.umd.min.js' @@ -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/controllers/admin/AdminLoginController.php b/controllers/admin/AdminLoginController.php index a3998ff8d..4c66e4ef0 100644 --- a/controllers/admin/AdminLoginController.php +++ b/controllers/admin/AdminLoginController.php @@ -18,7 +18,9 @@ * @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; +use Symfony\Component\HttpFoundation\Session\SessionInterface; /** * Copyright since 2007 PrestaShop SA and Contributors @@ -51,6 +53,9 @@ class AdminLoginController extends AdminLoginControllerCore /** @var Ps_accounts */ private $psAccountsModule; + /** @var AnalyticsService */ + private $analyticsService; + /** * @throws Exception */ @@ -69,6 +74,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 +102,17 @@ 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($userId) : + $this->analyticsService->pageLocalBoLogin($userId); + } + if ($this->psAccountsLoginEnabled && $tpl_name === $this->template) { return $this->createPsAccountsLoginTemplate(); } @@ -112,6 +130,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, @@ -120,7 +141,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->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 661905c78..c5ef43314 100644 --- a/controllers/admin/AdminOAuth2PsAccountsController.php +++ b/controllers/admin/AdminOAuth2PsAccountsController.php @@ -21,10 +21,15 @@ 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\Oauth2Exception; +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; +use PrestaShop\Module\PsAccounts\Service\PsAccountsService; use PrestaShop\OAuth2\Client\Provider\PrestaShop; use PrestaShop\OAuth2\Client\Provider\PrestaShopUser; use PrestaShop\PrestaShop\Core\Exception\ContainerNotFoundException; @@ -43,10 +48,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; } @@ -61,17 +83,11 @@ public function display(): void try { $this->oauth2Login(); } catch (IdentityProviderException $e) { - $this->oauth2ErrorLog($e->getMessage()); - $this->redirectWithError('error_from_hydra'); - } catch (EmployeeAccountEmailNotVerifiedException $e) { - $this->oauth2ErrorLog($e->getMessage()); - $this->redirectWithError('email_not_verified'); - } catch (EmployeeAccountNotFoundException $e) { - $this->oauth2ErrorLog($e->getMessage()); - $this->redirectWithError('employee_not_found'); + $this->onLoginFailed(new Oauth2Exception(null, $e->getMessage())); + } catch (EmailNotVerifiedException | EmployeeNotFoundException $e) { + $this->onLoginFailed($e); } catch (Exception $e) { - $this->oauth2ErrorLog($e->getMessage()); - $this->redirectWithError('error_other'); + $this->onLoginFailed(new OtherErrorException(null, $e->getMessage())); } } @@ -81,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 @@ -97,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()); @@ -127,6 +143,22 @@ private function initUserSession(PrestaShopUser $user): bool $cookie->write(); + if ($this->module->isShopEdition()) { + $this->analyticsService->identify( + $user->getId(), + $user->getName(), + $user->getEmail() + ); + $this->analyticsService->group( + $user->getId(), + (string) $this->psAccountsService->getShopUuid() + ); + $this->analyticsService->trackUserSignedIntoApp( + $user->getId(), + 'smb-edition' + ); + } + return true; } @@ -170,20 +202,43 @@ private function getEmployeeByUidOrEmail(string $uid, string $email): Employee } /** - * @param string $error - * - * @return void + * @throws ContainerNotFoundException */ - private function redirectWithError(string $error): void + private function onLoginFailed(AccountLoginException $e): void { + if ($this->module->isShopEdition() && ( + $e instanceof EmployeeNotFoundException || + $e instanceof EmailNotVerifiedException + )) { + $user = $e->getPrestaShopUser(); + $this->analyticsService->identify( + $user->getId(), + $user->getName(), + $user->getEmail() + ); + $this->analyticsService->group( + $user->getId(), + (string) $this->psAccountsService->getShopUuid() + ); + $this->analyticsService->trackBackOfficeSSOSignInFailed( + $user->getId(), + $e->getType(), + $e->getMessage() + ); + } + + $this->oauth2ErrorLog($e->getMessage()); + $this->setLoginError($e->getType()); Tools::redirectAdmin( $this->context->link->getAdminLink('AdminLogin', true, [], [ 'logout' => 1, - 'loginError' => $error, ]) ); } + /** + * @throws Exception + */ private function getProvider(): Oauth2ClientShopProvider { return $this->module->getService(PrestaShop::class); @@ -202,7 +257,15 @@ 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); + } } 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 12003cf42..6e1351417 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 @@ -49,6 +51,8 @@ class Ps_accounts extends Module 'actionObjectShopUrlUpdateAfter', 'displayDashboardTop', 'displayAccountUpdateWarning', + 'actionAdminLoginControllerLoginAfter', + 'actionAdminControllerInitBefore', ]; /** @@ -604,6 +608,61 @@ public function hookActionObjectShopDeleteBefore($params) return true; } + /** + * @param array $params + * + * @return void + * + * @throws Exception + */ + 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()) { + $uid = null; + if ($account) { + $uid = $account->getUid(); + $email = $account->getEmail(); + } else { + $email = $employee->email; + } + $analyticsService->identify($uid, null, $email); + $analyticsService->group($uid, (string) $psAccountsService->getShopUuid()); + $analyticsService->trackUserSignedIntoBackOfficeLocally($uid, $email); + } + } + + /** + * @param array $params + * + * @return void + * + * @throws Exception + */ + public function hookActionAdminControllerInitBefore($params) + { + /** @var \PrestaShop\Module\PsAccounts\Service\PsAccountsService $psAccountsService */ + $psAccountsService = $this->getService(\PrestaShop\Module\PsAccounts\Service\PsAccountsService::class); + + if (!$psAccountsService->getLoginActivated()) { + return; + } + + if (isset($_GET['logout'])) { + $this->oauth2Logout(); + } + } + /** * @return string */ @@ -727,4 +786,33 @@ public function getCustomHooks() { return $this->customHooks; } + + 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; + } + + protected function isOauth2LogoutEnabled(): bool + { + return $this->hasParameter('ps_accounts.oauth2_url_session_logout'); + } } 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/Oauth2Exception.php similarity index 68% rename from src/Exception/EmployeeAccountNotFoundException.php rename to src/Exception/AccountLogin/Oauth2Exception.php index 8dea74c71..965fb3aa7 100644 --- a/src/Exception/EmployeeAccountNotFoundException.php +++ b/src/Exception/AccountLogin/Oauth2Exception.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 Oauth2Exception extends AccountLoginException { + public function __construct( + ?PrestaShopUser $user, + string $message = 'OAuth2 error', + 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 68% rename from src/Exception/EmployeeAccountEmailNotVerifiedException.php rename to src/Exception/AccountLogin/OtherErrorException.php index eca8c81b4..e54d05139 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 = 'Other error', + string $type = 'error_other' + ) { + parent::__construct($user, $message, $type); + } } 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) ); diff --git a/src/Provider/OAuth2/Oauth2ClientShopProvider.php b/src/Provider/OAuth2/Oauth2ClientShopProvider.php index 6c03c231c..f272c46ad 100644 --- a/src/Provider/OAuth2/Oauth2ClientShopProvider.php +++ b/src/Provider/OAuth2/Oauth2ClientShopProvider.php @@ -26,6 +26,9 @@ class Oauth2ClientShopProvider extends PrestaShop { + public const SESSION_ACCESS_TOKEN_NAME = 'accessToken'; + public const QUERY_LOGOUT_CALLBACK_PARAM = 'oauth2Callback'; + /** * @var \Ps_accounts */ @@ -55,13 +58,26 @@ 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(), 'redirectUri' => $this->getRedirectUri(), + 'postLogoutCallbackUri' => $this->getPostLogoutRedirectUri(), ], $options), $collaborators); } + protected function getAllowedClientOptions(array $options) + { + return array_merge(parent::getAllowedClientOptions($options), [ + 'verify', + ]); + } + public static function create(): PrestaShop { return new self(); @@ -110,8 +126,39 @@ 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); } + + /** + * @return string + * + * @throws \Exception + */ + public function getBaseSessionLogoutUrl(): string + { + return $this->getParameter( + 'ps_accounts.oauth2_url_session_logout', + parent::getBaseSessionLogoutUrl() + ); + } + + /** + * @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, [], [ + 'logout' => 1, + self::QUERY_LOGOUT_CALLBACK_PARAM => 1, + ]); + } } diff --git a/src/Provider/OAuth2/Oauth2LogoutTrait.php b/src/Provider/OAuth2/Oauth2LogoutTrait.php new file mode 100644 index 000000000..91cf584c4 --- /dev/null +++ b/src/Provider/OAuth2/Oauth2LogoutTrait.php @@ -0,0 +1,57 @@ + + * @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; + + abstract protected function isOauth2LogoutEnabled(): bool; + + /** + * @throws \Exception + */ + public function oauth2Logout(): void + { + if (!$this->isOauth2LogoutEnabled()) { + return; + } + + 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; + } + } +} diff --git a/src/Service/AnalyticsService.php b/src/Service/AnalyticsService.php new file mode 100644 index 000000000..8fde771be --- /dev/null +++ b/src/Service/AnalyticsService.php @@ -0,0 +1,166 @@ +initAnonymousId(); + $this->logger = $logger; + } + + public function track(array $message): void + { + try { + Segment::track($message); + Segment::flush(); + } catch (\Exception $e) { + $this->logger->error($e->getMessage(), $message); + } + } + + public function trackUserSignedIntoApp(?string $userUid, string $application): void + { + $this->track([ + 'event' => 'User Signed Into App', + 'userId' => $userUid, + 'anonymousId' => $this->getAnonymousId(), + 'properties' => [ + 'application' => $application, + ], + ]); + } + + public function trackUserSignedIntoBackOfficeLocally(?string $userUid, string $userEmail): void + { + $this->track([ + 'event' => 'User Signed Into Back Office Locally', + 'userId' => $userUid, + 'anonymousId' => $this->getAnonymousId(), + 'properties' => [ + 'email' => $userEmail, + ], + ]); + } + + public function trackBackOfficeSSOSignInFailed(?string $userUid, ?string $type, ?string $description): void + { + $this->track([ + 'event' => 'Back Office SSO Sign In Failed', + 'userId' => $userUid, + 'anonymousId' => $this->getAnonymousId(), + 'properties' => [ + 'type' => $type, + 'description' => $description, + ], + ]); + } + + public function page( + string $name, + ?string $userId = null, + ?string $path = null, + ?string $referrer = null, + ?string $search = null, + ?string $title = null, + ?string $url = null + ): void { + $message = [ + 'userId' => $userId, + 'anonymousId' => $this->getAnonymousId(), + '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'], + ], + ]; + try { + Segment::page($message); + Segment::flush(); + } catch (\Exception $e) { + $this->logger->error($e->getMessage(), $message); + } + } + + public function pageAccountsBoLogin(?string $userUid = null): void + { + $this->page('Accounts Backoffice Login Page', $userUid); + } + + public function pageLocalBoLogin(?string $userUid = null): void + { + $this->page('Local Backoffice Login Page', $userUid); + } + + public function identify(?string $userUid, ?string $name, ?string $email): void + { + $message = [ + 'userId' => $userUid, + '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 + { + $message = [ + 'userId' => $userUid, + 'groupId' => $shopUid, + 'anonymousId' => $this->getAnonymousId(), +// "traits" => [ +// "name" => $shopName, +// ] + ]; + try { + Segment::group($message); + } catch (\Exception $e) { + $this->logger->error($e->getMessage(), $message); + } + } + + public function getAnonymousId(): string + { + $this->initAnonymousId(); + + return self::$anonymousId; + } + + private function initAnonymousId(): void + { + 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]; + } + } + } +} 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 @@ -