Skip to content

Commit 984849a

Browse files
committed
Create sanitize_shop_domain utility method
1 parent 8bc8132 commit 984849a

File tree

4 files changed

+67
-4
lines changed

4 files changed

+67
-4
lines changed

shopify/session_token.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,14 @@
33
import six
44
import sys
55

6+
from shopify.utils import shop_url
7+
68
if sys.version_info[0] < 3: # Backwards compatibility for python < v3.0.0
79
from urlparse import urljoin
810
else:
911
from urllib.parse import urljoin
1012

1113

12-
HOSTNAME_PATTERN = r"[a-z0-9][a-z0-9-]*[a-z0-9]"
13-
SHOP_DOMAIN_RE = re.compile(r"^https://{h}\.myshopify\.com/$".format(h=HOSTNAME_PATTERN))
14-
1514
ALGORITHM = "HS256"
1615
PREFIX = "Bearer "
1716
REQUIRED_FIELDS = ["iss", "dest", "sub", "jti", "sid"]
@@ -69,7 +68,7 @@ def _validate_issuer(decoded_payload):
6968
def _validate_issuer_hostname(decoded_payload):
7069
issuer_root = urljoin(decoded_payload["iss"], "/")
7170

72-
if not SHOP_DOMAIN_RE.match(issuer_root):
71+
if not shop_url.sanitize_shop_domain(issuer_root):
7372
raise InvalidIssuerError("Invalid issuer")
7473

7574

shopify/utils/__init__.py

Whitespace-only changes.

shopify/utils/shop_url.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import re
2+
import sys
3+
4+
if sys.version_info[0] < 3: # Backwards compatibility for python < v3.0.0
5+
from urlparse import urlparse
6+
else:
7+
from urllib.parse import urlparse
8+
9+
HOSTNAME_PATTERN = r"[a-z0-9][a-z0-9-]*[a-z0-9]"
10+
11+
12+
def sanitize_shop_domain(shop_domain, myshopify_domain="myshopify.com"):
13+
name = str(shop_domain).lower().strip()
14+
if myshopify_domain not in name and "." not in name:
15+
name += ".{domain}".format(domain=myshopify_domain)
16+
name = re.sub(r"https?://", "", name)
17+
18+
uri = urlparse("http://{hostname}".format(hostname=name))
19+
if re.match(r"{h}\.{d}$".format(h=HOSTNAME_PATTERN, d=re.escape(myshopify_domain)), uri.netloc):
20+
return uri.netloc

test/utils/shop_url_test.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
from shopify.utils import shop_url
2+
from test.test_helper import TestCase
3+
4+
5+
class TestSanitizeShopDomain(TestCase):
6+
def test_returns_hostname_for_good_shop_domains(self):
7+
good_shop_domains = [
8+
"my-shop",
9+
"my-shop.myshopify.com",
10+
"http://my-shop.myshopify.com",
11+
"https://my-shop.myshopify.com",
12+
]
13+
sanitized_shops = [shop_url.sanitize_shop_domain(shop_domain) for shop_domain in good_shop_domains]
14+
15+
self.assertTrue(all(shop == "my-shop.myshopify.com" for shop in sanitized_shops))
16+
17+
def test_returns_none_for_bad_shop_domains(self):
18+
bad_shop_domains = [
19+
"myshop.com",
20+
"myshopify.com",
21+
"shopify.com",
22+
"two words",
23+
"store.myshopify.com.evil.com",
24+
"/foo/bar",
25+
"/foo.myshopify.io.evil.ru",
26+
"%0a123.myshopify.io ",
27+
"foo.bar.myshopify.io",
28+
]
29+
sanitized_shops = [shop_url.sanitize_shop_domain(shop_domain) for shop_domain in bad_shop_domains]
30+
31+
self.assertTrue(all(shop_domain is None for shop_domain in sanitized_shops))
32+
33+
def test_returns_hostname_for_custom_shop_domains(self):
34+
custom_shop_domains = [
35+
"my-shop",
36+
"my-shop.myshopify.io",
37+
"http://my-shop.myshopify.io",
38+
"https://my-shop.myshopify.io",
39+
]
40+
sanitized_shops = [
41+
shop_url.sanitize_shop_domain(shop_domain, "myshopify.io") for shop_domain in custom_shop_domains
42+
]
43+
44+
self.assertTrue(all(shop == "my-shop.myshopify.io" for shop in sanitized_shops))

0 commit comments

Comments
 (0)