mirror of https://github.com/zulip/zulip.git
102 lines
3.3 KiB
Python
102 lines
3.3 KiB
Python
from collections import defaultdict
|
|
from collections.abc import MutableMapping
|
|
from dataclasses import dataclass, field
|
|
from typing import Any, Optional
|
|
|
|
from django.conf import settings
|
|
from django.http import HttpRequest, HttpResponse
|
|
from django.utils.translation import gettext as _
|
|
from typing_extensions import override
|
|
|
|
from zerver.lib import rate_limiter
|
|
from zerver.lib.exceptions import ErrorCode, JsonableError
|
|
from zerver.lib.notes import BaseNotes
|
|
from zerver.models import Client, Realm
|
|
|
|
if settings.ZILENCER_ENABLED:
|
|
from zilencer.models import RemoteZulipServer
|
|
|
|
|
|
@dataclass
|
|
class RequestNotes(BaseNotes[HttpRequest, "RequestNotes"]):
|
|
"""This class contains extra metadata that Zulip associated with a
|
|
Django HttpRequest object. See the docstring for BaseNotes for
|
|
details on how it works.
|
|
|
|
Note that most Optional fields will be definitely not None once
|
|
middleware has run. In the future, we may want to express that in
|
|
the types by having different types EarlyRequestNotes and
|
|
post-middleware RequestNotes types, but for now we have a lot
|
|
of `assert request_notes.foo is not None` when accessing them.
|
|
"""
|
|
|
|
client: Client | None = None
|
|
client_name: str | None = None
|
|
client_version: str | None = None
|
|
log_data: MutableMapping[str, Any] | None = None
|
|
rate_limit: str | None = None
|
|
requester_for_logs: str | None = None
|
|
# We use realm_cached to indicate whether the realm is cached or not.
|
|
# Because the default value of realm is None, which can indicate "unset"
|
|
# and "nonexistence" at the same time.
|
|
realm: Realm | None = None
|
|
has_fetched_realm: bool = False
|
|
set_language: str | None = None
|
|
ratelimits_applied: list[rate_limiter.RateLimitResult] = field(default_factory=list)
|
|
query: str | None = None
|
|
error_format: str | None = None
|
|
saved_response: HttpResponse | None = None
|
|
tornado_handler_id: int | None = None
|
|
processed_parameters: set[str] = field(default_factory=set)
|
|
remote_server: Optional["RemoteZulipServer"] = None
|
|
is_webhook_view: bool = False
|
|
|
|
@classmethod
|
|
@override
|
|
def init_notes(cls) -> "RequestNotes":
|
|
return RequestNotes()
|
|
|
|
|
|
class RequestConfusingParamsError(JsonableError):
|
|
code = ErrorCode.REQUEST_CONFUSING_VAR
|
|
data_fields = ["var_name1", "var_name2"]
|
|
|
|
def __init__(self, var_name1: str, var_name2: str) -> None:
|
|
self.var_name1: str = var_name1
|
|
self.var_name2: str = var_name2
|
|
|
|
@staticmethod
|
|
@override
|
|
def msg_format() -> str:
|
|
return _("Can't decide between '{var_name1}' and '{var_name2}' arguments")
|
|
|
|
|
|
class RequestVariableMissingError(JsonableError):
|
|
code = ErrorCode.REQUEST_VARIABLE_MISSING
|
|
data_fields = ["var_name"]
|
|
|
|
def __init__(self, var_name: str) -> None:
|
|
self.var_name: str = var_name
|
|
|
|
@staticmethod
|
|
@override
|
|
def msg_format() -> str:
|
|
return _("Missing '{var_name}' argument")
|
|
|
|
|
|
class RequestVariableConversionError(JsonableError):
|
|
code = ErrorCode.REQUEST_VARIABLE_INVALID
|
|
data_fields = ["var_name", "bad_value"]
|
|
|
|
def __init__(self, var_name: str, bad_value: Any) -> None:
|
|
self.var_name: str = var_name
|
|
self.bad_value = bad_value
|
|
|
|
@staticmethod
|
|
@override
|
|
def msg_format() -> str:
|
|
return _("Bad value for '{var_name}': {bad_value}")
|
|
|
|
|
|
arguments_map: dict[str, list[str]] = defaultdict(list)
|