request_notes: Set the realm appropriately for the root subdomain.

Requests to the root subdomain weren't getting request_notes.realm set
even if a realm exists on the root subdomain - which is actually a
common scenario, because simply having one organization, on the root
subdomain, is the simplest and common way for self-hosted deployments.
This commit is contained in:
Mateusz Mandera 2021-09-26 18:54:45 +02:00 committed by Tim Abbott
parent 0f7d0a23c9
commit 8b906b5d2f
2 changed files with 61 additions and 10 deletions

View File

@ -576,16 +576,22 @@ class HostDomainMiddleware(MiddlewareMixin):
return None return None
subdomain = get_subdomain(request) subdomain = get_subdomain(request)
if ( if subdomain == settings.SOCIAL_AUTH_SUBDOMAIN:
subdomain != Realm.SUBDOMAIN_FOR_ROOT_DOMAIN # Realms are not supposed to exist on SOCIAL_AUTH_SUBDOMAIN.
and subdomain != settings.SOCIAL_AUTH_SUBDOMAIN return None
):
request_notes = RequestNotes.get_notes(request) request_notes = RequestNotes.get_notes(request)
try: try:
request_notes.realm = get_realm(subdomain) request_notes.realm = get_realm(subdomain)
except Realm.DoesNotExist:
return render(request, "zerver/invalid_realm.html", status=404)
request_notes.has_fetched_realm = True request_notes.has_fetched_realm = True
except Realm.DoesNotExist:
if subdomain == Realm.SUBDOMAIN_FOR_ROOT_DOMAIN:
# The root domain is used for creating new
# organizations even if it does not host a realm.
return None
return render(request, "zerver/invalid_realm.html", status=404)
return None return None

View File

@ -2,7 +2,7 @@ import base64
import os import os
import re import re
from collections import defaultdict from collections import defaultdict
from typing import Any, Callable, Dict, List, Sequence, Tuple from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple
from unittest import mock, skipUnless from unittest import mock, skipUnless
import orjson import orjson
@ -29,6 +29,7 @@ from zerver.decorator import (
from zerver.forms import OurAuthenticationForm from zerver.forms import OurAuthenticationForm
from zerver.lib.actions import ( from zerver.lib.actions import (
change_user_is_active, change_user_is_active,
do_create_realm,
do_deactivate_realm, do_deactivate_realm,
do_deactivate_user, do_deactivate_user,
do_reactivate_realm, do_reactivate_realm,
@ -2061,3 +2062,47 @@ class TestIgnoreUnhashableLRUCache(ZulipTestCase):
self.assertEqual(hits, 0) self.assertEqual(hits, 0)
self.assertEqual(misses, 0) self.assertEqual(misses, 0)
self.assertEqual(currsize, 0) self.assertEqual(currsize, 0)
class TestRequestNotes(ZulipTestCase):
def test_request_notes_realm(self) -> None:
"""
This test verifies that .realm gets set correctly on the request notes
depending on the subdomain.
"""
def mock_home(expected_realm: Optional[Realm]) -> Callable[[HttpRequest], HttpResponse]:
def inner(request: HttpRequest) -> HttpResponse:
self.assertEqual(RequestNotes.get_notes(request).realm, expected_realm)
return HttpResponse()
return inner
zulip_realm = get_realm("zulip")
with mock.patch("zerver.views.home.home_real", new=mock_home(zulip_realm)):
result = self.client_get("/", subdomain="zulip")
self.assertEqual(result.status_code, 200)
# When a request is made to the root subdomain and there is no realm on it,
# no realm can be set on the request notes.
with mock.patch("zerver.views.home.home_real", new=mock_home(None)):
result = self.client_get("/", subdomain="")
self.assertEqual(result.status_code, 200)
root_subdomain_realm = do_create_realm("", "Root Domain")
# Now test that that realm does get set, if it exists, for requests
# to the root subdomain.
with mock.patch("zerver.views.home.home_real", new=mock_home(root_subdomain_realm)):
result = self.client_get("/", subdomain="")
self.assertEqual(result.status_code, 200)
# Only the root subdomain allows requests to it without having a realm.
# Requests to non-root subdomains get stopped by the middleware and
# an error page is returned before the request hits the view.
with mock.patch("zerver.views.home.home_real") as mock_home_real:
result = self.client_get("/", subdomain="invalid")
self.assertEqual(result.status_code, 404)
self.assert_in_response(
"There is no Zulip organization hosted at this subdomain.", result
)
mock_home_real.assert_not_called()