From 86b52ef7bf8f206bcb0fad4ced94d607dff690a6 Mon Sep 17 00:00:00 2001 From: sahil839 Date: Thu, 11 Jun 2020 02:03:48 +0530 Subject: [PATCH] users: Owners can only be deactivated by other organization owners. This commit adds restriction on deactivation of organization owners. Only owners can deactivate other organization owners. --- .../zerver/help/deactivate-or-reactivate-a-user.md | 2 ++ templates/zerver/security.md | 7 ++++--- zerver/tests/test_users.py | 11 ++++++++--- zerver/views/users.py | 2 ++ 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/templates/zerver/help/deactivate-or-reactivate-a-user.md b/templates/zerver/help/deactivate-or-reactivate-a-user.md index 75fe811e75..e6090c3f25 100644 --- a/templates/zerver/help/deactivate-or-reactivate-a-user.md +++ b/templates/zerver/help/deactivate-or-reactivate-a-user.md @@ -10,6 +10,8 @@ email system, since the user’s API key and bot API keys will still be active. Instead, you need to deactivate the user’s account using the Zulip administrative interface. +Note that organization administrators cannot deactivate organization owners. + {start_tabs} {settings_tab|user-list-admin} diff --git a/templates/zerver/security.md b/templates/zerver/security.md index f9d0567700..b5f487c05e 100644 --- a/templates/zerver/security.md +++ b/templates/zerver/security.md @@ -78,9 +78,10 @@ priority. - Users can rotate their accounts’ credentials, blocking further access from any compromised Zulip credentials. With Zulip on-premise, server administrators can additionally revoke and reset any user’s credentials. -- Owners and administrators can deactivate any - [user](/help/deactivate-or-reactivate-a-user), - [bot, or integration](/help/deactivate-or-reactivate-a-bot). +- Owners can deactivate any [user](/help/deactivate-or-reactivate-a-user), + [bot, or integration](/help/deactivate-or-reactivate-a-bot). Administrators + can also deactivate any [user](/help/deactivate-or-reactivate-a-user), + [bot, or integration](/help/deactivate-or-reactivate-a-bot) except owners. - With Zulip on-premise, [session length](https://github.com/zulip/zulip/blob/master/zproject/prod_settings_template.py#L206) and idle timeouts can be configured to match your organization’s security diff --git a/zerver/tests/test_users.py b/zerver/tests/test_users.py index 432f41e614..dd51c50c97 100644 --- a/zerver/tests/test_users.py +++ b/zerver/tests/test_users.py @@ -1120,9 +1120,14 @@ class ActivateTest(ZulipTestCase): self.assertTrue(user.is_active) def test_api_with_nonexistent_user(self) -> None: - self.login('desdemona') + self.login('iago') + + # Organization Administrator cannot deactivate organization owner. + result = self.client_delete(f'/json/users/{self.example_user("desdemona").id}') + self.assert_json_error(result, 'Only owners can deactivate other organization owners.') iago = self.example_user('iago') + desdemona = self.example_user('desdemona') do_change_user_role(iago, UserProfile.ROLE_REALM_OWNER) # Cannot deactivate a user with the bot api @@ -1137,10 +1142,10 @@ class ActivateTest(ZulipTestCase): result = self.client_delete('/json/users/{}'.format(self.example_user("webhook_bot").id)) self.assert_json_error(result, 'No such user') - result = self.client_delete('/json/users/{}'.format(iago.id)) + result = self.client_delete('/json/users/{}'.format(desdemona.id)) self.assert_json_success(result) - result = self.client_delete(f'/json/users/{self.example_user("desdemona").id}') + result = self.client_delete(f'/json/users/{iago.id}') self.assert_json_error(result, 'Cannot deactivate the only organization owner') # Cannot reactivate a nonexistent user. diff --git a/zerver/views/users.py b/zerver/views/users.py index 26b08d5e8a..a4b13d9465 100644 --- a/zerver/views/users.py +++ b/zerver/views/users.py @@ -46,6 +46,8 @@ def check_last_owner(user_profile: UserProfile) -> bool: def deactivate_user_backend(request: HttpRequest, user_profile: UserProfile, user_id: int) -> HttpResponse: target = access_user_by_id(user_profile, user_id) + if target.is_realm_owner and not user_profile.is_realm_owner: + return json_error(_('Only owners can deactivate other organization owners.')) if check_last_owner(target): return json_error(_('Cannot deactivate the only organization owner')) return _deactivate_user_profile_backend(request, user_profile, target)