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 +108,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'); + } +}