exceptions: Raise InvalidSubdomainError when realm is invalid.

When user requests for a realm that doesn't exists, we raise
a InvalidSubdomainError.

This reduces our effort at repeatedly ensuring realm is valid
in request in web-public queries.
This commit is contained in:
Aman Agrawal 2020-09-01 17:26:15 +05:30 committed by Tim Abbott
parent dad0073331
commit d9431a5e66
4 changed files with 24 additions and 8 deletions

View File

@ -11,6 +11,7 @@ from version import (
ZULIP_VERSION,
)
from zerver.decorator import get_client_name
from zerver.lib.exceptions import InvalidSubdomainError
from zerver.lib.realm_description import get_realm_rendered_description, get_realm_text_description
from zerver.lib.realm_icon import get_realm_icon_url
from zerver.lib.send_email import FromAddress
@ -54,6 +55,12 @@ def get_realm_from_request(request: HttpRequest) -> Optional[Realm]:
request.realm = None
return request.realm
def get_valid_realm_from_request(request: HttpRequest) -> Realm:
realm = get_realm_from_request(request)
if realm is None:
raise InvalidSubdomainError()
return realm
def zulip_default_context(request: HttpRequest) -> Dict[str, Any]:
"""Context available to all Zulip Jinja2 templates that have a request
passed in. Designed to provide the long list of variables at the

View File

@ -46,6 +46,7 @@ class ErrorCode(AbstractEnum):
INVALID_API_KEY = ()
INVALID_ZOOM_TOKEN = ()
UNAUTHENTICATED_USER = ()
NONEXISTENT_SUBDOMAIN = ()
class JsonableError(Exception):
'''A standardized error format we can turn into a nice JSON HTTP response.
@ -277,3 +278,14 @@ class MissingAuthenticationError(JsonableError):
# No msg_format is defined since this exception is caught and
# converted into json_unauthorized in Zulip's middleware.
class InvalidSubdomainError(JsonableError):
code = ErrorCode.NONEXISTENT_SUBDOMAIN
http_status_code = 404
def __init__(self) -> None:
pass
@staticmethod
def msg_format() -> str:
return _("Invalid subdomain")

View File

@ -1212,10 +1212,10 @@ class GetOldMessagesTest(ZulipTestCase):
"narrow": orjson.dumps([dict(operator='streams', operand="web-public")]).decode(),
}
with mock.patch('zerver.views.message_fetch.get_realm_from_request', return_value=None):
with mock.patch('zerver.context_processors.get_realm', side_effect=Realm.DoesNotExist):
result = self.client_get("/json/messages", dict(post_params))
self.assert_json_error(result, "Invalid subdomain.",
status_code=400)
self.assert_json_error(result, "Invalid subdomain",
status_code=404)
def test_unauthenticated_get_messages_without_web_public(self) -> None:
"""

View File

@ -27,7 +27,7 @@ from sqlalchemy.sql import (
union_all,
)
from zerver.context_processors import get_realm_from_request
from zerver.context_processors import get_valid_realm_from_request
from zerver.decorator import REQ, has_request_variables
from zerver.lib.actions import recipient_for_user_profiles
from zerver.lib.addressee import get_user_profiles, get_user_profiles_by_ids
@ -870,10 +870,7 @@ def get_messages_backend(request: HttpRequest,
if not is_web_public_compatible(narrow):
return json_unauthorized()
realm = get_realm_from_request(request)
if realm is None:
return json_error(_("Invalid subdomain."))
realm = get_valid_realm_from_request(request)
# We use None to indicate unauthenticated requests as it's more
# readable than using AnonymousUser, and the lack of Django
# stubs means that mypy can't check AnonymousUser well.