diff --git a/zerver/tests.py b/zerver/tests.py index 59939ae000..92fa9dfe22 100644 --- a/zerver/tests.py +++ b/zerver/tests.py @@ -729,7 +729,7 @@ class TestCrossRealmPMs(AuthedTestCase): self.send_message(user1_email, [user2_email, user3_email], Recipient.PERSONAL) -class PermissionTest(TestCase): +class PermissionTest(AuthedTestCase): def test_get_admin_users(self): user_profile = get_user_profile_by_email('hamlet@zulip.com') remove_perm('administer', user_profile, user_profile.realm) @@ -739,6 +739,33 @@ class PermissionTest(TestCase): admin_users = user_profile.realm.get_admin_users() self.assertTrue(user_profile in admin_users) + def test_admin_api(self): + self.login('hamlet@zulip.com') + admin = get_user_profile_by_email('hamlet@zulip.com') + user = get_user_profile_by_email('othello@zulip.com') + realm = admin.realm + assign_perm('administer', admin, realm) + remove_perm('administer', user, realm) + + # Giveth + req = dict(is_admin=ujson.dumps(True)) + result = self.client_patch('/json/users/othello@zulip.com', req) + self.assert_json_success(result) + admin_users = realm.get_admin_users() + self.assertTrue(user in admin_users) + + # Taketh away + req = dict(is_admin=ujson.dumps(False)) + result = self.client_patch('/json/users/othello@zulip.com', req) + self.assert_json_success(result) + admin_users = realm.get_admin_users() + self.assertFalse(user in admin_users) + + # Make sure only admins can patch other user's info. + self.login('othello@zulip.com') + result = self.client_patch('/json/users/hamlet@zulip.com', req) + self.assert_json_error(result, 'Insufficient permission') + class WorkerTest(TestCase): class FakeClient: def __init__(self): diff --git a/zerver/views/__init__.py b/zerver/views/__init__.py index f181dc9c2a..bdb8cee3e1 100644 --- a/zerver/views/__init__.py +++ b/zerver/views/__init__.py @@ -65,7 +65,7 @@ from zerver.lib.queue import queue_json_publish from zerver.lib.utils import statsd, generate_random_token, statsd_key from zerver import tornado_callbacks from zproject.backends import password_auth_enabled -from guardian.shortcuts import assign_perm +from guardian.shortcuts import assign_perm, remove_perm from confirmation.models import Confirmation @@ -1663,6 +1663,24 @@ def reactivate_user_backend(request, user_profile, email): do_reactivate_user(target) return json_success({}) +@has_request_variables +def update_user_backend(request, user_profile, email, + is_admin=REQ(default=None, converter=json_to_bool)): + try: + target = get_user_profile_by_email(email) + except UserProfile.DoesNotExist: + return json_error('No such user') + + if not user_profile.can_admin_user(target): + return json_error('Insufficient permission') + + if is_admin is not None: + if is_admin: + assign_perm('administer', target, target.realm) + else: + remove_perm('administer', target, target.realm) + return json_success({}) + @require_realm_admin def deactivate_stream_backend(request, user_profile, stream_name): try: diff --git a/zproject/urls.py b/zproject/urls.py index 866d30b007..404849cd82 100644 --- a/zproject/urls.py +++ b/zproject/urls.py @@ -212,7 +212,8 @@ v1_api_and_json_patterns = patterns('zerver.views', url(r'^users/(?P.*)/reactivate$', 'rest_dispatch', {'POST': 'reactivate_user_backend'}), url(r'^users/(?P.*)$', 'rest_dispatch', - {'DELETE': 'deactivate_user_backend'}), + {'PATCH': 'update_user_backend', + 'DELETE': 'deactivate_user_backend'}), url(r'^bots/(?P.*)/api_key/regenerate$', 'rest_dispatch', {'POST': 'regenerate_bot_api_key'}), url(r'^bots/(?P.*)$', 'rest_dispatch',