2020-06-13 05:24:42 +02:00
|
|
|
from typing import Any, Mapping, Sequence
|
2020-06-11 00:54:34 +02:00
|
|
|
from unittest import mock
|
2017-10-26 03:14:53 +02:00
|
|
|
|
2021-03-23 10:34:55 +01:00
|
|
|
from django.conf import settings
|
|
|
|
|
2021-06-05 02:38:54 +02:00
|
|
|
import zerver.lib.upload
|
2021-03-23 10:34:55 +01:00
|
|
|
from zerver.lib.subdomains import get_subdomain, is_static_or_current_realm_url
|
2020-07-01 04:19:54 +02:00
|
|
|
from zerver.lib.test_classes import ZulipTestCase
|
2021-06-05 02:38:54 +02:00
|
|
|
from zerver.lib.test_helpers import create_s3_buckets, use_s3_backend
|
2017-10-26 03:14:53 +02:00
|
|
|
from zerver.models import Realm
|
|
|
|
|
2020-06-11 00:54:34 +02:00
|
|
|
|
2020-07-01 04:19:54 +02:00
|
|
|
class SubdomainsTest(ZulipTestCase):
|
2017-11-05 10:51:25 +01:00
|
|
|
def test_get_subdomain(self) -> None:
|
|
|
|
def request_mock(host: str) -> Any:
|
2021-02-12 08:20:45 +01:00
|
|
|
request = mock.Mock(spec=["get_host"])
|
|
|
|
request.attach_mock(mock.Mock(return_value=host), "get_host")
|
2017-10-26 03:14:53 +02:00
|
|
|
return request
|
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
def test(
|
|
|
|
expected: str,
|
|
|
|
host: str,
|
|
|
|
*,
|
|
|
|
plusport: bool = True,
|
2021-02-12 08:20:45 +01:00
|
|
|
external_host: str = "example.org",
|
2021-02-12 08:19:30 +01:00
|
|
|
realm_hosts: Mapping[str, str] = {},
|
|
|
|
root_aliases: Sequence[str] = [],
|
|
|
|
) -> None:
|
|
|
|
with self.settings(
|
|
|
|
EXTERNAL_HOST=external_host,
|
|
|
|
REALM_HOSTS=realm_hosts,
|
|
|
|
ROOT_SUBDOMAIN_ALIASES=root_aliases,
|
|
|
|
):
|
2017-10-26 03:14:53 +02:00
|
|
|
self.assertEqual(get_subdomain(request_mock(host)), expected)
|
2021-02-12 08:20:45 +01:00
|
|
|
if plusport and ":" not in host:
|
|
|
|
self.assertEqual(get_subdomain(request_mock(host + ":443")), expected)
|
2017-10-26 03:14:53 +02:00
|
|
|
|
|
|
|
ROOT = Realm.SUBDOMAIN_FOR_ROOT_DOMAIN
|
2017-10-20 06:30:34 +02:00
|
|
|
|
|
|
|
# Basics
|
2021-02-12 08:20:45 +01:00
|
|
|
test(ROOT, "example.org")
|
|
|
|
test("foo", "foo.example.org")
|
|
|
|
test(ROOT, "www.example.org", root_aliases=["www"])
|
2017-10-20 06:30:34 +02:00
|
|
|
|
|
|
|
# Unrecognized patterns fall back to root
|
2021-02-12 08:20:45 +01:00
|
|
|
test(ROOT, "arbitrary.com")
|
|
|
|
test(ROOT, "foo.example.org.evil.com")
|
2017-10-20 06:30:34 +02:00
|
|
|
|
alias domains: Add a v1 of this feature.
The main limitation of this version is that it's controlled entirely
from settings, with nothing in the database and no web UI or even
management command to control it. That makes it a bit more of a
burden for the server admins than it'd ideally be, but that's fine
for now.
Relatedly, the web flow for realm creation still requires choosing a
subdomain even if the realm is destined to live at an alias domain.
Specific to the dev environment, there is an annoying quirk: the
special dev login flow doesn't work on a REALM_HOSTS realm. Also,
in this version the `add_new_realm` and `add_new_user` management
commands, which are intended for use in development environments only,
don't support this feature.
In manual testing, I've confirmed that a REALM_HOSTS realm works for
signup and login, with email/password, Google SSO, or GitHub SSO.
Most of that was in dev; I used zulipstaging.com to also test
* logging in with email and password;
* logging in with Google SSO... far enough to correctly determine
that my email address is associated with some other realm.
2017-10-20 06:36:50 +02:00
|
|
|
# REALM_HOSTS adds a name,
|
2021-02-12 08:20:45 +01:00
|
|
|
test("bar", "chat.barbar.com", realm_hosts={"bar": "chat.barbar.com"})
|
alias domains: Add a v1 of this feature.
The main limitation of this version is that it's controlled entirely
from settings, with nothing in the database and no web UI or even
management command to control it. That makes it a bit more of a
burden for the server admins than it'd ideally be, but that's fine
for now.
Relatedly, the web flow for realm creation still requires choosing a
subdomain even if the realm is destined to live at an alias domain.
Specific to the dev environment, there is an annoying quirk: the
special dev login flow doesn't work on a REALM_HOSTS realm. Also,
in this version the `add_new_realm` and `add_new_user` management
commands, which are intended for use in development environments only,
don't support this feature.
In manual testing, I've confirmed that a REALM_HOSTS realm works for
signup and login, with email/password, Google SSO, or GitHub SSO.
Most of that was in dev; I used zulipstaging.com to also test
* logging in with email and password;
* logging in with Google SSO... far enough to correctly determine
that my email address is associated with some other realm.
2017-10-20 06:36:50 +02:00
|
|
|
# ... exactly, ...
|
2021-02-12 08:20:45 +01:00
|
|
|
test(ROOT, "surchat.barbar.com", realm_hosts={"bar": "chat.barbar.com"})
|
|
|
|
test(ROOT, "foo.chat.barbar.com", realm_hosts={"bar": "chat.barbar.com"})
|
alias domains: Add a v1 of this feature.
The main limitation of this version is that it's controlled entirely
from settings, with nothing in the database and no web UI or even
management command to control it. That makes it a bit more of a
burden for the server admins than it'd ideally be, but that's fine
for now.
Relatedly, the web flow for realm creation still requires choosing a
subdomain even if the realm is destined to live at an alias domain.
Specific to the dev environment, there is an annoying quirk: the
special dev login flow doesn't work on a REALM_HOSTS realm. Also,
in this version the `add_new_realm` and `add_new_user` management
commands, which are intended for use in development environments only,
don't support this feature.
In manual testing, I've confirmed that a REALM_HOSTS realm works for
signup and login, with email/password, Google SSO, or GitHub SSO.
Most of that was in dev; I used zulipstaging.com to also test
* logging in with email and password;
* logging in with Google SSO... far enough to correctly determine
that my email address is associated with some other realm.
2017-10-20 06:36:50 +02:00
|
|
|
# ... and leaves the subdomain in place too.
|
2021-02-12 08:20:45 +01:00
|
|
|
test("bar", "bar.example.org", realm_hosts={"bar": "chat.barbar.com"})
|
alias domains: Add a v1 of this feature.
The main limitation of this version is that it's controlled entirely
from settings, with nothing in the database and no web UI or even
management command to control it. That makes it a bit more of a
burden for the server admins than it'd ideally be, but that's fine
for now.
Relatedly, the web flow for realm creation still requires choosing a
subdomain even if the realm is destined to live at an alias domain.
Specific to the dev environment, there is an annoying quirk: the
special dev login flow doesn't work on a REALM_HOSTS realm. Also,
in this version the `add_new_realm` and `add_new_user` management
commands, which are intended for use in development environments only,
don't support this feature.
In manual testing, I've confirmed that a REALM_HOSTS realm works for
signup and login, with email/password, Google SSO, or GitHub SSO.
Most of that was in dev; I used zulipstaging.com to also test
* logging in with email and password;
* logging in with Google SSO... far enough to correctly determine
that my email address is associated with some other realm.
2017-10-20 06:36:50 +02:00
|
|
|
|
|
|
|
# Any port is fine in Host if there's none in EXTERNAL_HOST, ...
|
2021-02-12 08:20:45 +01:00
|
|
|
test("foo", "foo.example.org:443", external_host="example.org")
|
|
|
|
test("foo", "foo.example.org:12345", external_host="example.org")
|
alias domains: Add a v1 of this feature.
The main limitation of this version is that it's controlled entirely
from settings, with nothing in the database and no web UI or even
management command to control it. That makes it a bit more of a
burden for the server admins than it'd ideally be, but that's fine
for now.
Relatedly, the web flow for realm creation still requires choosing a
subdomain even if the realm is destined to live at an alias domain.
Specific to the dev environment, there is an annoying quirk: the
special dev login flow doesn't work on a REALM_HOSTS realm. Also,
in this version the `add_new_realm` and `add_new_user` management
commands, which are intended for use in development environments only,
don't support this feature.
In manual testing, I've confirmed that a REALM_HOSTS realm works for
signup and login, with email/password, Google SSO, or GitHub SSO.
Most of that was in dev; I used zulipstaging.com to also test
* logging in with email and password;
* logging in with Google SSO... far enough to correctly determine
that my email address is associated with some other realm.
2017-10-20 06:36:50 +02:00
|
|
|
# ... but an explicit port in EXTERNAL_HOST must be explicitly matched in Host.
|
2021-02-12 08:20:45 +01:00
|
|
|
test(ROOT, "foo.example.org", external_host="example.org:12345")
|
|
|
|
test(ROOT, "foo.example.org", external_host="example.org:443", plusport=False)
|
|
|
|
test("foo", "foo.example.org:443", external_host="example.org:443")
|
2021-03-23 10:34:55 +01:00
|
|
|
|
|
|
|
def test_is_static_or_current_realm_url(self) -> None:
|
|
|
|
realm = self.example_user("hamlet").realm
|
|
|
|
|
|
|
|
def test(url: str) -> bool:
|
|
|
|
return is_static_or_current_realm_url(url, realm)
|
|
|
|
|
|
|
|
self.assertTrue(test("/static/images/logo/zulip-org-logo.svg"))
|
|
|
|
self.assertTrue(test("/anything"))
|
|
|
|
self.assertFalse(test("https://zulip.com"))
|
|
|
|
self.assertFalse(test("http://zulip.com"))
|
|
|
|
self.assertTrue(test(f"{realm.uri}"))
|
|
|
|
|
|
|
|
self.assertFalse(test(f"{realm.uri}@www.google.com"))
|
|
|
|
|
|
|
|
# We don't have an existing configuration STATIC_URL with this
|
|
|
|
# format, but it's worth testing in case that changes.
|
|
|
|
with self.settings(STATIC_URL="https://zulipstatic.example.com"):
|
|
|
|
evil_url = f"{settings.STATIC_URL}@evil.example.com"
|
|
|
|
self.assertEqual(evil_url, "https://zulipstatic.example.com@evil.example.com")
|
|
|
|
self.assertTrue(test(f"{settings.STATIC_URL}/x"))
|
|
|
|
self.assertFalse(test(evil_url))
|
|
|
|
self.assertFalse(test(f"{evil_url}/x"))
|
2021-06-05 02:38:54 +02:00
|
|
|
|
|
|
|
@use_s3_backend
|
|
|
|
def test_is_static_or_current_realm_url_with_s3(self) -> None:
|
|
|
|
create_s3_buckets(settings.S3_AVATAR_BUCKET)[0]
|
|
|
|
|
|
|
|
realm = self.example_user("hamlet").realm
|
|
|
|
|
|
|
|
def test(url: str) -> bool:
|
|
|
|
return is_static_or_current_realm_url(url, realm)
|
|
|
|
|
|
|
|
upload_backend = zerver.lib.upload.upload_backend
|
|
|
|
self.assertTrue(test(upload_backend.get_realm_icon_url(realm.id, version=1)))
|
|
|
|
self.assertTrue(test(upload_backend.get_realm_logo_url(realm.id, version=1, night=False)))
|
|
|
|
self.assertTrue(test(upload_backend.get_avatar_url("deadbeefcafe")))
|
|
|
|
self.assertTrue(test(upload_backend.get_emoji_url("emoji.gif", realm.id)))
|