mirror of
https://github.com/zulip/zulip.git
synced 2025-10-24 08:33:43 +00: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.
This commit is contained in:
@@ -17,10 +17,10 @@ def get_subdomain(request):
|
||||
# X-Forwarded-Host, it passes right through the same way. So our
|
||||
# logic is a bit complicated to allow for that variation.
|
||||
#
|
||||
# For EXTERNAL_HOST, we take a missing port to mean that any port
|
||||
# should be accepted in Host. It's not totally clear that's the
|
||||
# right behavior, but it keeps compatibility with older versions
|
||||
# of Zulip, so that's a start.
|
||||
# For both EXTERNAL_HOST and REALM_HOSTS, we take a missing port
|
||||
# to mean that any port should be accepted in Host. It's not
|
||||
# totally clear that's the right behavior, but it keeps
|
||||
# compatibility with older versions of Zulip, so that's a start.
|
||||
|
||||
host = request.get_host().lower()
|
||||
|
||||
@@ -32,6 +32,11 @@ def get_subdomain(request):
|
||||
return Realm.SUBDOMAIN_FOR_ROOT_DOMAIN
|
||||
return subdomain
|
||||
|
||||
for subdomain, realm_host in settings.REALM_HOSTS.items():
|
||||
if re.search('^%s(:\d+)?$' % (realm_host,),
|
||||
host):
|
||||
return subdomain
|
||||
|
||||
return Realm.SUBDOMAIN_FOR_ROOT_DOMAIN
|
||||
|
||||
def is_subdomain_root_or_alias(request):
|
||||
|
||||
@@ -280,9 +280,10 @@ class Realm(models.Model):
|
||||
@staticmethod
|
||||
def host_for_subdomain(subdomain):
|
||||
# type: (str) -> str
|
||||
if subdomain not in [None, ""]:
|
||||
return "%s.%s" % (subdomain, settings.EXTERNAL_HOST)
|
||||
return settings.EXTERNAL_HOST
|
||||
if subdomain == Realm.SUBDOMAIN_FOR_ROOT_DOMAIN:
|
||||
return settings.EXTERNAL_HOST
|
||||
default_host = "%s.%s" % (subdomain, settings.EXTERNAL_HOST)
|
||||
return settings.REALM_HOSTS.get(subdomain, default_host)
|
||||
|
||||
@property
|
||||
def is_zephyr_mirror_realm(self):
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
import mock
|
||||
from typing import Any, List
|
||||
from typing import Any, Dict, List
|
||||
|
||||
from django.test import TestCase, override_settings
|
||||
|
||||
@@ -18,9 +18,10 @@ class SubdomainsTest(TestCase):
|
||||
return request
|
||||
|
||||
def test(expected, host, *, plusport=True,
|
||||
external_host='example.org', root_aliases=[]):
|
||||
# type: (str, str, bool, str, List[str]) -> None
|
||||
external_host='example.org', realm_hosts={}, root_aliases=[]):
|
||||
# type: (str, str, bool, str, Dict[str, str], List[str]) -> None
|
||||
with self.settings(EXTERNAL_HOST=external_host,
|
||||
REALM_HOSTS=realm_hosts,
|
||||
ROOT_SUBDOMAIN_ALIASES=root_aliases):
|
||||
self.assertEqual(get_subdomain(request_mock(host)), expected)
|
||||
if plusport and ':' not in host:
|
||||
@@ -38,11 +39,18 @@ class SubdomainsTest(TestCase):
|
||||
test(ROOT, 'arbitrary.com')
|
||||
test(ROOT, 'foo.example.org.evil.com')
|
||||
|
||||
# Any port is fine in Host if there's none in EXTERNAL_HOST
|
||||
# REALM_HOSTS adds a name,
|
||||
test('bar', 'chat.barbar.com', realm_hosts={'bar': 'chat.barbar.com'})
|
||||
# ... exactly, ...
|
||||
test(ROOT, 'surchat.barbar.com', realm_hosts={'bar': 'chat.barbar.com'})
|
||||
test(ROOT, 'foo.chat.barbar.com', realm_hosts={'bar': 'chat.barbar.com'})
|
||||
# ... and leaves the subdomain in place too.
|
||||
test('bar', 'bar.example.org', realm_hosts={'bar': 'chat.barbar.com'})
|
||||
|
||||
# Any port is fine in Host if there's none in EXTERNAL_HOST, ...
|
||||
test('foo', 'foo.example.org:443', external_host='example.org')
|
||||
test('foo', 'foo.example.org:12345', external_host='example.org')
|
||||
|
||||
# Explicit port in EXTERNAL_HOST must be explicitly matched in Host
|
||||
# ... but an explicit port in EXTERNAL_HOST must be explicitly matched in Host.
|
||||
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')
|
||||
|
||||
@@ -245,6 +245,12 @@ DEFAULT_SETTINGS.update({
|
||||
# purpose now that the REALMS_HAVE_SUBDOMAINS migration is finished.
|
||||
'SYSTEM_ONLY_REALMS': {"zulip"},
|
||||
|
||||
# Alternate hostnames to serve particular realms on, in addition to
|
||||
# their usual subdomains. Keys are realm string_ids (aka subdomains),
|
||||
# and values are alternate hosts.
|
||||
# The values will also be added to ALLOWED_HOSTS.
|
||||
'REALM_HOSTS': {},
|
||||
|
||||
# Whether the server is using the Pgroonga full-text search
|
||||
# backend. Plan is to turn this on for everyone after further
|
||||
# testing.
|
||||
@@ -411,9 +417,11 @@ USE_X_FORWARDED_HOST = True
|
||||
|
||||
# Extend ALLOWED_HOSTS with localhost (needed to RPC to Tornado),
|
||||
ALLOWED_HOSTS += ['127.0.0.1', 'localhost']
|
||||
# and with hosts corresponding to EXTERNAL_HOST.
|
||||
# ... with hosts corresponding to EXTERNAL_HOST,
|
||||
ALLOWED_HOSTS += [EXTERNAL_HOST.split(":")[0],
|
||||
'.' + EXTERNAL_HOST.split(":")[0]]
|
||||
# ... and with the hosts in REALM_HOSTS.
|
||||
ALLOWED_HOSTS += REALM_HOSTS.values()
|
||||
|
||||
MIDDLEWARE = (
|
||||
# With the exception of it's dependencies,
|
||||
|
||||
Reference in New Issue
Block a user