mirror of https://github.com/zulip/zulip.git
api: Add REALM_DEACTIVATED error code.
In `validate_account_and_subdomain` we check if user's realm is not deactivated. In case of failure of this check, we raise our standard JsonableError. While this works well in most cases but it creates difficulties in handling of users with deactivated realms for non-browser clients. So we register a new REALM_DEACTIVATED error code so that clients can distinguish if error is because of deactivated account. Following these changes `validate_account_and_subdomain` raises RealmDeactivatedError if user's realm is deactivated. This error is also documented in `/api/rest-error-handling`. Testing: I have mostly relied on automated backend tests to test this. Fixes #17763.
This commit is contained in:
parent
2eeb82edba
commit
aea31eb31f
|
@ -42,3 +42,9 @@ for a query:
|
|||
A typical failed json response for when user's account is deactivated:
|
||||
|
||||
{generate_code_example|/rest-error-handling:post|fixture(403_0)}
|
||||
|
||||
## Realm deactivated
|
||||
|
||||
A typical failed json response for when user's organization is deactivated:
|
||||
|
||||
{generate_code_example|/rest-error-handling:post|fixture(403_1)}
|
||||
|
|
|
@ -31,13 +31,20 @@ with test_server_running(
|
|||
):
|
||||
# Zerver imports should happen after `django.setup()` is run
|
||||
# by the test_server_running decorator.
|
||||
from zerver.lib.actions import change_user_is_active, do_create_user, do_reactivate_user
|
||||
from zerver.lib.actions import (
|
||||
change_user_is_active,
|
||||
do_create_user,
|
||||
do_deactivate_realm,
|
||||
do_reactivate_realm,
|
||||
do_reactivate_user,
|
||||
)
|
||||
from zerver.lib.test_helpers import reset_emails_in_zulip_realm
|
||||
from zerver.lib.users import get_api_key
|
||||
from zerver.models import get_realm, get_user
|
||||
from zerver.openapi.javascript_examples import test_js_bindings
|
||||
from zerver.openapi.python_examples import (
|
||||
test_invalid_api_key,
|
||||
test_realm_deactivated,
|
||||
test_the_api,
|
||||
test_user_account_deactivated,
|
||||
)
|
||||
|
@ -122,5 +129,16 @@ with test_server_running(
|
|||
# reactivate user to avoid any side-effects in other tests.
|
||||
do_reactivate_user(guest_user, acting_user=None)
|
||||
|
||||
# Test realm deactivated error
|
||||
do_deactivate_realm(guest_user.realm, acting_user=None)
|
||||
|
||||
client = Client(
|
||||
email=email,
|
||||
api_key=api_key,
|
||||
site=site,
|
||||
)
|
||||
test_realm_deactivated(client)
|
||||
do_reactivate_realm(guest_user.realm)
|
||||
|
||||
|
||||
print("API tests passed!")
|
||||
|
|
|
@ -32,6 +32,7 @@ from zerver.lib.exceptions import (
|
|||
OrganizationAdministratorRequired,
|
||||
OrganizationMemberRequired,
|
||||
OrganizationOwnerRequired,
|
||||
RealmDeactivatedError,
|
||||
UnsupportedWebhookEventType,
|
||||
UserDeactivatedError,
|
||||
)
|
||||
|
@ -269,7 +270,7 @@ def validate_api_key(
|
|||
|
||||
def validate_account_and_subdomain(request: HttpRequest, user_profile: UserProfile) -> None:
|
||||
if user_profile.realm.deactivated:
|
||||
raise JsonableError(_("This organization has been deactivated"))
|
||||
raise RealmDeactivatedError()
|
||||
if not user_profile.is_active:
|
||||
raise UserDeactivatedError()
|
||||
|
||||
|
|
|
@ -51,6 +51,7 @@ class ErrorCode(AbstractEnum):
|
|||
NONEXISTENT_SUBDOMAIN = ()
|
||||
RATE_LIMIT_HIT = ()
|
||||
USER_DEACTIVATED = ()
|
||||
REALM_DEACTIVATED = ()
|
||||
|
||||
|
||||
class JsonableError(Exception):
|
||||
|
@ -284,6 +285,18 @@ class UserDeactivatedError(JsonableError):
|
|||
return _("Account is deactivated")
|
||||
|
||||
|
||||
class RealmDeactivatedError(JsonableError):
|
||||
code: ErrorCode = ErrorCode.REALM_DEACTIVATED
|
||||
http_status_code = 403
|
||||
|
||||
def __init__(self) -> None:
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def msg_format() -> str:
|
||||
return _("This organization has been deactivated")
|
||||
|
||||
|
||||
class MarkdownRenderingException(Exception):
|
||||
pass
|
||||
|
||||
|
|
|
@ -1233,6 +1233,15 @@ def test_user_account_deactivated(client: Client) -> None:
|
|||
validate_against_openapi_schema(result, "/rest-error-handling", "post", "403_0")
|
||||
|
||||
|
||||
def test_realm_deactivated(client: Client) -> None:
|
||||
request = {
|
||||
"content": "**foo**",
|
||||
}
|
||||
result = client.render_message(request)
|
||||
|
||||
validate_against_openapi_schema(result, "/rest-error-handling", "post", "403_1")
|
||||
|
||||
|
||||
def test_invalid_stream_error(client: Client) -> None:
|
||||
result = client.get_stream_id("nonexistent")
|
||||
|
||||
|
|
|
@ -9274,6 +9274,7 @@ paths:
|
|||
schema:
|
||||
oneOf:
|
||||
- $ref: "#/components/schemas/UserDeactivatedError"
|
||||
- $ref: "#/components/schemas/RealmDeactivatedError"
|
||||
/zulip-outgoing-webhook:
|
||||
post:
|
||||
operationId: zulip_outgoing_webhooks
|
||||
|
@ -10872,6 +10873,15 @@ components:
|
|||
"msg": "Account is deactivated",
|
||||
"result": "error",
|
||||
}
|
||||
RealmDeactivatedError:
|
||||
allOf:
|
||||
- $ref: "#/components/schemas/CodedError"
|
||||
- example:
|
||||
{
|
||||
"code": "REALM_DEACTIVATED",
|
||||
"msg": "This organization is deactivated",
|
||||
"result": "error",
|
||||
}
|
||||
|
||||
###################
|
||||
# Shared responses
|
||||
|
|
|
@ -1066,7 +1066,9 @@ class DeactivatedRealmTest(ZulipTestCase):
|
|||
"to": self.example_email("othello"),
|
||||
},
|
||||
)
|
||||
self.assert_json_error_contains(result, "has been deactivated", status_code=400)
|
||||
self.assert_json_error_contains(
|
||||
result, "This organization has been deactivated", status_code=403
|
||||
)
|
||||
|
||||
result = self.api_post(
|
||||
self.example_user("hamlet"),
|
||||
|
@ -1078,7 +1080,9 @@ class DeactivatedRealmTest(ZulipTestCase):
|
|||
"to": self.example_email("othello"),
|
||||
},
|
||||
)
|
||||
self.assert_json_error_contains(result, "has been deactivated", status_code=401)
|
||||
self.assert_json_error_contains(
|
||||
result, "This organization has been deactivated", status_code=401
|
||||
)
|
||||
|
||||
def test_fetch_api_key_deactivated_realm(self) -> None:
|
||||
"""
|
||||
|
@ -1094,7 +1098,9 @@ class DeactivatedRealmTest(ZulipTestCase):
|
|||
realm.deactivated = True
|
||||
realm.save()
|
||||
result = self.client_post("/json/fetch_api_key", {"password": test_password})
|
||||
self.assert_json_error_contains(result, "has been deactivated", status_code=400)
|
||||
self.assert_json_error_contains(
|
||||
result, "This organization has been deactivated", status_code=403
|
||||
)
|
||||
|
||||
def test_webhook_deactivated_realm(self) -> None:
|
||||
"""
|
||||
|
@ -1107,7 +1113,9 @@ class DeactivatedRealmTest(ZulipTestCase):
|
|||
url = f"/api/v1/external/jira?api_key={api_key}&stream=jira_custom"
|
||||
data = self.webhook_fixture_data("jira", "created_v2")
|
||||
result = self.client_post(url, data, content_type="application/json")
|
||||
self.assert_json_error_contains(result, "has been deactivated", status_code=400)
|
||||
self.assert_json_error_contains(
|
||||
result, "This organization has been deactivated", status_code=403
|
||||
)
|
||||
|
||||
|
||||
class LoginRequiredTest(ZulipTestCase):
|
||||
|
@ -1659,7 +1667,9 @@ class TestAuthenticatedJsonPostViewDecorator(ZulipTestCase):
|
|||
user_profile.realm.deactivated = True
|
||||
user_profile.realm.save()
|
||||
self.assert_json_error_contains(
|
||||
self._do_test(user_profile), "This organization has been deactivated"
|
||||
self._do_test(user_profile),
|
||||
"This organization has been deactivated",
|
||||
status_code=403,
|
||||
)
|
||||
do_reactivate_realm(user_profile.realm)
|
||||
|
||||
|
|
Loading…
Reference in New Issue