mirror of https://github.com/zulip/zulip.git
realm: Allow only organization owners to deactivate a realm.
We now allow only organization owners to deactivate a realm. 'require_realm_owner' decorator has been added for this purpose.
This commit is contained in:
parent
86b52ef7bf
commit
81c28c1d3e
|
@ -1,6 +1,6 @@
|
||||||
# Deactivate your organization
|
# Deactivate your organization
|
||||||
|
|
||||||
{!admin-only.md!}
|
{!owner-only.md!}
|
||||||
|
|
||||||
{start_tabs}
|
{start_tabs}
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ from zerver.lib.timestamp import datetime_to_timestamp, timestamp_to_datetime
|
||||||
from zerver.lib.utils import statsd, has_api_key_format
|
from zerver.lib.utils import statsd, has_api_key_format
|
||||||
from zerver.lib.exceptions import JsonableError, ErrorCode, \
|
from zerver.lib.exceptions import JsonableError, ErrorCode, \
|
||||||
InvalidJSONError, InvalidAPIKeyError, InvalidAPIKeyFormatError, \
|
InvalidJSONError, InvalidAPIKeyError, InvalidAPIKeyFormatError, \
|
||||||
OrganizationAdministratorRequired
|
OrganizationAdministratorRequired, OrganizationOwnerRequired
|
||||||
from zerver.lib.types import ViewFuncT
|
from zerver.lib.types import ViewFuncT
|
||||||
|
|
||||||
from zerver.lib.rate_limiter import RateLimitedUser
|
from zerver.lib.rate_limiter import RateLimitedUser
|
||||||
|
@ -104,6 +104,14 @@ def require_post(func: ViewFuncT) -> ViewFuncT:
|
||||||
return func(request, *args, **kwargs)
|
return func(request, *args, **kwargs)
|
||||||
return wrapper # type: ignore[return-value] # https://github.com/python/mypy/issues/1927
|
return wrapper # type: ignore[return-value] # https://github.com/python/mypy/issues/1927
|
||||||
|
|
||||||
|
def require_realm_owner(func: ViewFuncT) -> ViewFuncT:
|
||||||
|
@wraps(func)
|
||||||
|
def wrapper(request: HttpRequest, user_profile: UserProfile, *args: Any, **kwargs: Any) -> HttpResponse:
|
||||||
|
if not user_profile.is_realm_owner:
|
||||||
|
raise OrganizationOwnerRequired()
|
||||||
|
return func(request, user_profile, *args, **kwargs)
|
||||||
|
return wrapper # type: ignore[return-value] # https://github.com/python/mypy/issues/1927
|
||||||
|
|
||||||
def require_realm_admin(func: ViewFuncT) -> ViewFuncT:
|
def require_realm_admin(func: ViewFuncT) -> ViewFuncT:
|
||||||
@wraps(func)
|
@wraps(func)
|
||||||
def wrapper(request: HttpRequest, user_profile: UserProfile, *args: Any, **kwargs: Any) -> HttpResponse:
|
def wrapper(request: HttpRequest, user_profile: UserProfile, *args: Any, **kwargs: Any) -> HttpResponse:
|
||||||
|
|
|
@ -202,6 +202,18 @@ class OrganizationAdministratorRequired(JsonableError):
|
||||||
def msg_format() -> str:
|
def msg_format() -> str:
|
||||||
return OrganizationAdministratorRequired.ADMIN_REQUIRED_MESSAGE
|
return OrganizationAdministratorRequired.ADMIN_REQUIRED_MESSAGE
|
||||||
|
|
||||||
|
class OrganizationOwnerRequired(JsonableError):
|
||||||
|
code: ErrorCode = ErrorCode.UNAUTHORIZED_PRINCIPAL
|
||||||
|
|
||||||
|
OWNER_REQUIRED_MESSAGE = _("Must be an organization owner")
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
super().__init__(self.OWNER_REQUIRED_MESSAGE)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def msg_format() -> str:
|
||||||
|
return OrganizationOwnerRequired.OWNER_REQUIRED_MESSAGE
|
||||||
|
|
||||||
class BugdownRenderingException(Exception):
|
class BugdownRenderingException(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
@ -351,8 +351,8 @@ class RealmTest(ZulipTestCase):
|
||||||
realm = get_realm('zulip')
|
realm = get_realm('zulip')
|
||||||
self.assertNotEqual(realm.default_language, invalid_lang)
|
self.assertNotEqual(realm.default_language, invalid_lang)
|
||||||
|
|
||||||
def test_deactivate_realm_by_admin(self) -> None:
|
def test_deactivate_realm_by_owner(self) -> None:
|
||||||
self.login('iago')
|
self.login('desdemona')
|
||||||
realm = get_realm('zulip')
|
realm = get_realm('zulip')
|
||||||
self.assertFalse(realm.deactivated)
|
self.assertFalse(realm.deactivated)
|
||||||
|
|
||||||
|
@ -361,13 +361,13 @@ class RealmTest(ZulipTestCase):
|
||||||
realm = get_realm('zulip')
|
realm = get_realm('zulip')
|
||||||
self.assertTrue(realm.deactivated)
|
self.assertTrue(realm.deactivated)
|
||||||
|
|
||||||
def test_deactivate_realm_by_non_admin(self) -> None:
|
def test_deactivate_realm_by_non_owner(self) -> None:
|
||||||
self.login('hamlet')
|
self.login('iago')
|
||||||
realm = get_realm('zulip')
|
realm = get_realm('zulip')
|
||||||
self.assertFalse(realm.deactivated)
|
self.assertFalse(realm.deactivated)
|
||||||
|
|
||||||
result = self.client_post('/json/realm/deactivate')
|
result = self.client_post('/json/realm/deactivate')
|
||||||
self.assert_json_error(result, "Must be an organization administrator")
|
self.assert_json_error(result, "Must be an organization owner")
|
||||||
realm = get_realm('zulip')
|
realm = get_realm('zulip')
|
||||||
self.assertFalse(realm.deactivated)
|
self.assertFalse(realm.deactivated)
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ from django.utils.translation import ugettext as _
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.views.decorators.http import require_safe
|
from django.views.decorators.http import require_safe
|
||||||
|
|
||||||
from zerver.decorator import require_realm_admin
|
from zerver.decorator import require_realm_admin, require_realm_owner
|
||||||
from zerver.lib.actions import (
|
from zerver.lib.actions import (
|
||||||
do_set_realm_message_editing,
|
do_set_realm_message_editing,
|
||||||
do_set_realm_message_deleting,
|
do_set_realm_message_deleting,
|
||||||
|
@ -184,7 +184,7 @@ def update_realm(
|
||||||
|
|
||||||
return json_success(data)
|
return json_success(data)
|
||||||
|
|
||||||
@require_realm_admin
|
@require_realm_owner
|
||||||
@has_request_variables
|
@has_request_variables
|
||||||
def deactivate_realm(request: HttpRequest, user: UserProfile) -> HttpResponse:
|
def deactivate_realm(request: HttpRequest, user: UserProfile) -> HttpResponse:
|
||||||
realm = user.realm
|
realm = user.realm
|
||||||
|
|
Loading…
Reference in New Issue