From e589bf1e8a0d5260f8751db29a1a51871cfe611d Mon Sep 17 00:00:00 2001 From: Stidges Date: Wed, 17 May 2023 16:55:54 +0200 Subject: [PATCH 1/2] Improve shop domain sanitization --- src/Exceptions/InvalidShopDomainException.php | 10 ++++ src/Objects/Values/ShopDomain.php | 19 ++++++-- tests/Objects/Values/ShopDomainTest.php | 47 +++++++++++++++++++ 3 files changed, 72 insertions(+), 4 deletions(-) create mode 100644 src/Exceptions/InvalidShopDomainException.php create mode 100644 tests/Objects/Values/ShopDomainTest.php diff --git a/src/Exceptions/InvalidShopDomainException.php b/src/Exceptions/InvalidShopDomainException.php new file mode 100644 index 00000000..45d0d675 --- /dev/null +++ b/src/Exceptions/InvalidShopDomainException.php @@ -0,0 +1,10 @@ +string = $this->sanitizeShopDomain($domain); + + if ($this->string === '') { + throw new InvalidShopDomainException("Invalid shop domain [{$domain}]"); + } } /** @@ -101,17 +107,22 @@ public static function fromRequest(Request $request): ShopDomainValue * * @return string */ - protected function sanitizeShopDomain(string $domain): ?string + protected function sanitizeShopDomain(string $domain): string { $configEndDomain = Util::getShopifyConfig('myshopify_domain'); - $domain = strtolower(preg_replace('/https?:\/\//i', '', trim($domain))); + $domain = strtolower(preg_replace('/^https?:\/\//i', '', trim($domain))); if (strpos($domain, $configEndDomain) === false && strpos($domain, '.') === false) { // No myshopify.com ($configEndDomain) in shop's name $domain .= ".{$configEndDomain}"; } - // Return the host after cleaned up - return parse_url("https://{$domain}", PHP_URL_HOST); + $hostname = parse_url("https://{$domain}", PHP_URL_HOST); + + if (! preg_match('/^[a-zA-Z0-9][a-zA-Z0-9\-]*\.'.preg_quote($configEndDomain, '/').'$/', $hostname)) { + return ''; + } + + return $hostname; } } diff --git a/tests/Objects/Values/ShopDomainTest.php b/tests/Objects/Values/ShopDomainTest.php new file mode 100644 index 00000000..de53a4c6 --- /dev/null +++ b/tests/Objects/Values/ShopDomainTest.php @@ -0,0 +1,47 @@ +assertEquals('test.myshopify.com', $shopDomain->toNative()); + } + + public function testDoesNotAddMyshopifyDomainIfContainsPeriod() + { + $shopDomain = ShopDomain::fromNative('test.myshopify.com'); + + $this->assertEquals('test.myshopify.com', $shopDomain->toNative()); + } + + public function testStripsTheProtocol() + { + $shopDomainA = ShopDomain::fromNative('https://test.myshopify.com'); + $shopDomainB = ShopDomain::fromNative('http://test.myshopify.com'); + + $this->assertEquals('test.myshopify.com', $shopDomainA->toNative()); + $this->assertEquals('test.myshopify.com', $shopDomainB->toNative()); + } + + public function testDoesNotAcceptNonMyshopifyDomains() + { + $this->expectException(InvalidShopDomainException::class); + + ShopDomain::fromNative('test.github.com'); + } + + public function testDoesNotAcceptNonMyshopifyDomainsWithSinglePeriod() + { + $this->expectException(InvalidShopDomainException::class); + + ShopDomain::fromNative('test.invalid-domain'); + } +} From 947232d542060459dae29911bdeeebca160fc5d5 Mon Sep 17 00:00:00 2001 From: Stidges Date: Wed, 17 May 2023 17:05:01 +0200 Subject: [PATCH 2/2] Fix phpdoc order --- src/Objects/Values/ShopDomain.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Objects/Values/ShopDomain.php b/src/Objects/Values/ShopDomain.php index a79836cc..9b61baea 100644 --- a/src/Objects/Values/ShopDomain.php +++ b/src/Objects/Values/ShopDomain.php @@ -23,8 +23,9 @@ final class ShopDomain implements ShopDomainValue * * @param string $domain The shop's domain. * - * @return void * @throws InvalidShopDomainException + * + * @return void */ public function __construct(string $domain) {