mirror of https://github.com/zulip/zulip.git
decorator: Extract validate_remote_server.
Signed-off-by: Zixuan James Li <p359101898@gmail.com>
This commit is contained in:
parent
ac2185a2e8
commit
af88417847
|
@ -39,7 +39,6 @@ from typing_extensions import Concatenate, ParamSpec
|
||||||
from zerver.lib.exceptions import (
|
from zerver.lib.exceptions import (
|
||||||
AccessDeniedError,
|
AccessDeniedError,
|
||||||
AnomalousWebhookPayload,
|
AnomalousWebhookPayload,
|
||||||
ErrorCode,
|
|
||||||
InvalidAPIKeyError,
|
InvalidAPIKeyError,
|
||||||
InvalidAPIKeyFormatError,
|
InvalidAPIKeyFormatError,
|
||||||
InvalidJSONError,
|
InvalidJSONError,
|
||||||
|
@ -48,7 +47,6 @@ from zerver.lib.exceptions import (
|
||||||
OrganizationMemberRequired,
|
OrganizationMemberRequired,
|
||||||
OrganizationOwnerRequired,
|
OrganizationOwnerRequired,
|
||||||
RealmDeactivatedError,
|
RealmDeactivatedError,
|
||||||
RemoteServerDeactivatedError,
|
|
||||||
UnauthorizedError,
|
UnauthorizedError,
|
||||||
UnsupportedWebhookEventType,
|
UnsupportedWebhookEventType,
|
||||||
UserDeactivatedError,
|
UserDeactivatedError,
|
||||||
|
@ -62,10 +60,10 @@ from zerver.lib.subdomains import get_subdomain, user_matches_subdomain
|
||||||
from zerver.lib.timestamp import datetime_to_timestamp, timestamp_to_datetime
|
from zerver.lib.timestamp import datetime_to_timestamp, timestamp_to_datetime
|
||||||
from zerver.lib.users import is_2fa_verified
|
from zerver.lib.users import is_2fa_verified
|
||||||
from zerver.lib.utils import has_api_key_format, statsd
|
from zerver.lib.utils import has_api_key_format, statsd
|
||||||
from zerver.models import Realm, UserProfile, get_client, get_user_profile_by_api_key
|
from zerver.models import UserProfile, get_client, get_user_profile_by_api_key
|
||||||
|
|
||||||
if settings.ZILENCER_ENABLED:
|
if settings.ZILENCER_ENABLED:
|
||||||
from zilencer.models import RemoteZulipServer, get_remote_server_by_uuid
|
from zilencer.models import RemoteZulipServer
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from django.http.request import _ImmutableQueryDict
|
from django.http.request import _ImmutableQueryDict
|
||||||
|
@ -238,24 +236,6 @@ def process_client(
|
||||||
update_user_activity(request, user, query)
|
update_user_activity(request, user, query)
|
||||||
|
|
||||||
|
|
||||||
class InvalidZulipServerError(JsonableError):
|
|
||||||
code = ErrorCode.INVALID_ZULIP_SERVER
|
|
||||||
data_fields = ["role"]
|
|
||||||
|
|
||||||
def __init__(self, role: str) -> None:
|
|
||||||
self.role: str = role
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def msg_format() -> str:
|
|
||||||
return "Zulip server auth failure: {role} is not registered -- did you run `manage.py register_server`?"
|
|
||||||
|
|
||||||
|
|
||||||
class InvalidZulipServerKeyError(InvalidZulipServerError):
|
|
||||||
@staticmethod
|
|
||||||
def msg_format() -> str:
|
|
||||||
return "Zulip server auth failure: key does not match role {role}"
|
|
||||||
|
|
||||||
|
|
||||||
def validate_api_key(
|
def validate_api_key(
|
||||||
request: HttpRequest,
|
request: HttpRequest,
|
||||||
role: Optional[str],
|
role: Optional[str],
|
||||||
|
@ -270,21 +250,9 @@ def validate_api_key(
|
||||||
|
|
||||||
# If `role` doesn't look like an email, it might be a uuid.
|
# If `role` doesn't look like an email, it might be a uuid.
|
||||||
if settings.ZILENCER_ENABLED and role is not None and "@" not in role:
|
if settings.ZILENCER_ENABLED and role is not None and "@" not in role:
|
||||||
try:
|
from zilencer.auth import validate_remote_server
|
||||||
remote_server = get_remote_server_by_uuid(role)
|
|
||||||
except RemoteZulipServer.DoesNotExist:
|
|
||||||
raise InvalidZulipServerError(role)
|
|
||||||
if not constant_time_compare(api_key, remote_server.api_key):
|
|
||||||
raise InvalidZulipServerKeyError(role)
|
|
||||||
|
|
||||||
if remote_server.deactivated:
|
return validate_remote_server(request, role, api_key)
|
||||||
raise RemoteServerDeactivatedError()
|
|
||||||
|
|
||||||
if get_subdomain(request) != Realm.SUBDOMAIN_FOR_ROOT_DOMAIN:
|
|
||||||
raise JsonableError(_("Invalid subdomain for push notifications bouncer"))
|
|
||||||
RequestNotes.get_notes(request).remote_server = remote_server
|
|
||||||
process_client(request)
|
|
||||||
return remote_server
|
|
||||||
|
|
||||||
user_profile = access_user_by_api_key(request, api_key, email=role)
|
user_profile = access_user_by_api_key(request, api_key, email=role)
|
||||||
if user_profile.is_incoming_webhook and not allow_webhook_access:
|
if user_profile.is_incoming_webhook and not allow_webhook_access:
|
||||||
|
|
|
@ -2184,7 +2184,7 @@ class TestSendToPushBouncer(ZulipTestCase):
|
||||||
|
|
||||||
@responses.activate
|
@responses.activate
|
||||||
def test_400_error_invalid_server_key(self) -> None:
|
def test_400_error_invalid_server_key(self) -> None:
|
||||||
from zerver.decorator import InvalidZulipServerError
|
from zilencer.auth import InvalidZulipServerError
|
||||||
|
|
||||||
# This is the exception our decorator uses for an invalid Zulip server
|
# This is the exception our decorator uses for an invalid Zulip server
|
||||||
error_response = json_response_from_error(InvalidZulipServerError("testRole"))
|
error_response = json_response_from_error(InvalidZulipServerError("testRole"))
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
from django.http import HttpRequest
|
||||||
|
from django.utils.crypto import constant_time_compare
|
||||||
|
from django.utils.translation import gettext as _
|
||||||
|
|
||||||
|
from zerver.decorator import process_client
|
||||||
|
from zerver.lib.exceptions import ErrorCode, JsonableError, RemoteServerDeactivatedError
|
||||||
|
from zerver.lib.request import RequestNotes
|
||||||
|
from zerver.lib.subdomains import get_subdomain
|
||||||
|
from zerver.models import Realm
|
||||||
|
from zilencer.models import RemoteZulipServer, get_remote_server_by_uuid
|
||||||
|
|
||||||
|
|
||||||
|
class InvalidZulipServerError(JsonableError):
|
||||||
|
code = ErrorCode.INVALID_ZULIP_SERVER
|
||||||
|
data_fields = ["role"]
|
||||||
|
|
||||||
|
def __init__(self, role: str) -> None:
|
||||||
|
self.role: str = role
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def msg_format() -> str:
|
||||||
|
return "Zulip server auth failure: {role} is not registered -- did you run `manage.py register_server`?"
|
||||||
|
|
||||||
|
|
||||||
|
class InvalidZulipServerKeyError(InvalidZulipServerError):
|
||||||
|
@staticmethod
|
||||||
|
def msg_format() -> str:
|
||||||
|
return "Zulip server auth failure: key does not match role {role}"
|
||||||
|
|
||||||
|
|
||||||
|
def validate_remote_server(
|
||||||
|
request: HttpRequest,
|
||||||
|
role: str,
|
||||||
|
api_key: str,
|
||||||
|
) -> RemoteZulipServer:
|
||||||
|
try:
|
||||||
|
remote_server = get_remote_server_by_uuid(role)
|
||||||
|
except RemoteZulipServer.DoesNotExist:
|
||||||
|
raise InvalidZulipServerError(role)
|
||||||
|
if not constant_time_compare(api_key, remote_server.api_key):
|
||||||
|
raise InvalidZulipServerKeyError(role)
|
||||||
|
|
||||||
|
if remote_server.deactivated:
|
||||||
|
raise RemoteServerDeactivatedError()
|
||||||
|
|
||||||
|
if get_subdomain(request) != Realm.SUBDOMAIN_FOR_ROOT_DOMAIN:
|
||||||
|
raise JsonableError(_("Invalid subdomain for push notifications bouncer"))
|
||||||
|
RequestNotes.get_notes(request).remote_server = remote_server
|
||||||
|
process_client(request)
|
||||||
|
return remote_server
|
|
@ -16,7 +16,7 @@ from django.views.decorators.csrf import csrf_exempt
|
||||||
|
|
||||||
from analytics.lib.counts import COUNT_STATS
|
from analytics.lib.counts import COUNT_STATS
|
||||||
from corporate.lib.stripe import do_deactivate_remote_server
|
from corporate.lib.stripe import do_deactivate_remote_server
|
||||||
from zerver.decorator import InvalidZulipServerKeyError, require_post
|
from zerver.decorator import require_post
|
||||||
from zerver.lib.exceptions import JsonableError
|
from zerver.lib.exceptions import JsonableError
|
||||||
from zerver.lib.push_notifications import (
|
from zerver.lib.push_notifications import (
|
||||||
UserPushIndentityCompat,
|
UserPushIndentityCompat,
|
||||||
|
@ -38,6 +38,7 @@ from zerver.lib.validator import (
|
||||||
)
|
)
|
||||||
from zerver.models import UserProfile
|
from zerver.models import UserProfile
|
||||||
from zerver.views.push_notifications import validate_token
|
from zerver.views.push_notifications import validate_token
|
||||||
|
from zilencer.auth import InvalidZulipServerKeyError
|
||||||
from zilencer.models import (
|
from zilencer.models import (
|
||||||
RemoteInstallationCount,
|
RemoteInstallationCount,
|
||||||
RemotePushDeviceToken,
|
RemotePushDeviceToken,
|
||||||
|
|
Loading…
Reference in New Issue