From 9ef1c5b1a642701489486f821824157e434e463d Mon Sep 17 00:00:00 2001 From: sahil839 Date: Tue, 2 Jun 2020 01:17:18 +0530 Subject: [PATCH] users: Add is_owner field to user objects returned by get endpoints. This commit adds 'is_owner' field to the user object returned by '/users', 'users/{user_id}', and '/users/me' endpoints. --- templates/zerver/api/changelog.md | 5 +++++ version.py | 2 +- zerver/lib/users.py | 2 ++ zerver/openapi/zulip.yaml | 20 ++++++++++++++++++++ zerver/tests/test_custom_profile_data.py | 10 +++++----- zerver/tests/test_events.py | 2 ++ zerver/tests/test_home.py | 3 +++ zerver/tests/test_users.py | 11 +++++++++++ zerver/views/users.py | 1 + 9 files changed, 50 insertions(+), 6 deletions(-) diff --git a/templates/zerver/api/changelog.md b/templates/zerver/api/changelog.md index ec971da35e..34268fb034 100644 --- a/templates/zerver/api/changelog.md +++ b/templates/zerver/api/changelog.md @@ -10,6 +10,11 @@ below features are supported. ## Changes in Zulip 2.2 +**Feature level 8** +* [`GET /users`](/api/get-all-users), [`GET /users/{user_id}`](/api/get-user) + and [`GET /users/me`](/api/get-profile): User objects now contain the + `is_owner` field as well. + **Feature level 7** * [`GET /events`](/api/get-events-from-queue): `realm_user` and `realm_bot` events no longer contain an `email` field to identify diff --git a/version.py b/version.py index 217ae48653..f852ede715 100644 --- a/version.py +++ b/version.py @@ -29,7 +29,7 @@ DESKTOP_WARNING_VERSION = "5.2.0" # # Changes should be accompanied by documentation explaining what the # new level means in templates/zerver/api/changelog.md. -API_FEATURE_LEVEL = 7 +API_FEATURE_LEVEL = 8 # Bump the minor PROVISION_VERSION to indicate that folks should provision # only when going from an old version of the code to a newer version. Bump diff --git a/zerver/lib/users.py b/zerver/lib/users.py index 06e45d4a52..c024093a4d 100644 --- a/zerver/lib/users.py +++ b/zerver/lib/users.py @@ -311,6 +311,7 @@ def format_user_row(realm: Realm, acting_user: UserProfile, row: Dict[str, Any], client_gravatar=client_gravatar,) is_admin = is_administrator_role(row['role']) + is_owner = row['role'] == UserProfile.ROLE_REALM_OWNER is_guest = row['role'] == UserProfile.ROLE_GUEST is_bot = row['is_bot'] # This format should align with get_cross_realm_dicts() and notify_created_user @@ -320,6 +321,7 @@ def format_user_row(realm: Realm, acting_user: UserProfile, row: Dict[str, Any], avatar_url=avatar_url, avatar_version=row['avatar_version'], is_admin=is_admin, + is_owner=is_owner, is_guest=is_guest, is_bot=is_bot, full_name=row['full_name'], diff --git a/zerver/openapi/zulip.yaml b/zerver/openapi/zulip.yaml index 1bbcb5065a..cd97b5e9c1 100644 --- a/zerver/openapi/zulip.yaml +++ b/zerver/openapi/zulip.yaml @@ -1353,6 +1353,7 @@ paths: "is_active": true, "email": "AARON@zulip.com", "is_admin": false, + "is_owner": false, "avatar_url": "https://secure.gravatar.com/avatar/818c212b9f8830dfef491b3f7da99a14?d=identicon&version=1", "bot_type": null, "timezone": "", @@ -1401,6 +1402,7 @@ paths: "bot_type": null, "timezone": "", "is_admin": false, + "is_owner": false, "avatar_url": "https://secure.gravatar.com/avatar/6d8cad0fd00256e7b40691d27ddfd466?d=identicon&version=1", "is_active": true, "email": "hamlet@zulip.com" @@ -1414,6 +1416,7 @@ paths: "is_active": true, "avatar_url": "https://secure.gravatar.com/avatar/7328586831cdbb1627649bd857b1ee8c?d=identicon&version=1", "is_admin": false, + "is_owner": false, "user_id": 23, "bot_type": 1, "timezone": "", @@ -1550,6 +1553,7 @@ paths: "bot_type": null, "timezone": "", "is_admin": false, + "is_owner": false, "avatar_url": "https://secure.gravatar.com/avatar/6d8cad0fd00256e7b40691d27ddfd466?d=identicon&version=1", "is_active": true, "email": "hamlet@zulip.com" @@ -1830,6 +1834,14 @@ paths: description: | A boolean indicating if the requesting user is an admin. example: true + is_owner: + type: boolean + description: | + A boolean indicating if the requesting user is + an organization owner. + + **Changes**: New in Zulip 2.2 (feature level 8). + example: false is_bot: type: boolean description: | @@ -1875,6 +1887,7 @@ paths: "email": "iago@zulip.com", "full_name": "Iago", "is_admin": true, + "is_owner": false, "is_bot": false, "max_message_id": 30, "msg": "", @@ -3966,6 +3979,13 @@ components: type: boolean description: | A boolean specifying whether the user is an organization administrator. + is_owner: + type: boolean + description: | + A boolean specifying whether the user is an organization owner. + If true, is_admin will also be true. + + **Changes**: New in Zulip 2.2 (feature level 8). bot_type: type: integer nullable: true diff --git a/zerver/tests/test_custom_profile_data.py b/zerver/tests/test_custom_profile_data.py index a51d7fad7b..5fd9d3fd06 100644 --- a/zerver/tests/test_custom_profile_data.py +++ b/zerver/tests/test_custom_profile_data.py @@ -672,15 +672,15 @@ class ListCustomProfileFieldTest(CustomProfileFieldTestCase): expected_keys_for_iago = { "delivery_email", - "email", "user_id", "avatar_url", "avatar_version", "is_admin", "is_guest", "is_bot", + "email", "user_id", "avatar_url", "avatar_version", "is_admin", "is_guest", "is_bot", "is_owner", "full_name", "timezone", "is_active", "date_joined", "profile_data"} self.assertEqual(set(iago_raw_data.keys()), expected_keys_for_iago) self.assertNotEqual(iago_raw_data["profile_data"], {}) expected_keys_for_test_bot = { "delivery_email", - "email", "user_id", "avatar_url", "avatar_version", "is_admin", "is_guest", "is_bot", "full_name", - "timezone", "is_active", "date_joined", "bot_type", "bot_owner_id"} + "email", "user_id", "avatar_url", "avatar_version", "is_admin", "is_guest", "is_bot", "is_owner", + "full_name", "timezone", "is_active", "date_joined", "bot_type", "bot_owner_id"} self.assertEqual(set(test_bot_raw_data.keys()), expected_keys_for_test_bot) self.assertEqual(test_bot_raw_data["bot_type"], 1) self.assertEqual(test_bot_raw_data["bot_owner_id"], iago_raw_data["user_id"]) @@ -697,8 +697,8 @@ class ListCustomProfileFieldTest(CustomProfileFieldTestCase): self.login('iago') expected_keys = { "result", "msg", "pointer", "client_id", "max_message_id", "user_id", - "avatar_url", "full_name", "email", "is_bot", "is_admin", "short_name", - "profile_data"} + "avatar_url", "full_name", "email", "is_bot", "is_admin", "is_owner", + "short_name", "profile_data"} url = "/json/users/me" response = self.client_get(url) diff --git a/zerver/tests/test_events.py b/zerver/tests/test_events.py index 4d2054b76d..908033478d 100644 --- a/zerver/tests/test_events.py +++ b/zerver/tests/test_events.py @@ -1248,6 +1248,7 @@ class EventsRegisterTest(ZulipTestCase): ('avatar_version', check_int), ('full_name', check_string), ('is_admin', check_bool), + ('is_owner', check_bool), ('is_bot', check_bool), ('is_guest', check_bool), ('is_active', check_bool), @@ -1276,6 +1277,7 @@ class EventsRegisterTest(ZulipTestCase): ('full_name', check_string), ('is_active', check_bool), ('is_admin', check_bool), + ('is_owner', check_bool), ('is_bot', check_bool), ('is_guest', check_bool), ('profile_data', check_dict_only([])), diff --git a/zerver/tests/test_home.py b/zerver/tests/test_home.py index c53f6bb3bd..438fc4637a 100644 --- a/zerver/tests/test_home.py +++ b/zerver/tests/test_home.py @@ -614,6 +614,7 @@ class HomeTest(ZulipTestCase): is_active=True, is_bot=True, is_admin=False, + is_owner=False, is_cross_realm_bot=True, is_guest=False ), @@ -627,6 +628,7 @@ class HomeTest(ZulipTestCase): is_active=True, is_bot=True, is_admin=False, + is_owner=False, is_cross_realm_bot=True, is_guest=False ), @@ -640,6 +642,7 @@ class HomeTest(ZulipTestCase): is_active=True, is_bot=True, is_admin=False, + is_owner=False, is_cross_realm_bot=True, is_guest=False ), diff --git a/zerver/tests/test_users.py b/zerver/tests/test_users.py index c2c85c0e4c..23e947f056 100644 --- a/zerver/tests/test_users.py +++ b/zerver/tests/test_users.py @@ -1371,6 +1371,7 @@ class GetProfileTest(ZulipTestCase): def test_get_user_profile(self) -> None: hamlet = self.example_user('hamlet') iago = self.example_user('iago') + desdemona = self.example_user('desdemona') self.login('hamlet') result = ujson.loads(self.client_get('/json/users/me').content) @@ -1380,6 +1381,7 @@ class GetProfileTest(ZulipTestCase): self.assertIn("user_id", result) self.assertFalse(result['is_bot']) self.assertFalse(result['is_admin']) + self.assertFalse(result['is_owner']) self.assertFalse('delivery_email' in result) self.login('iago') result = ujson.loads(self.client_get('/json/users/me').content) @@ -1388,6 +1390,14 @@ class GetProfileTest(ZulipTestCase): self.assertEqual(result['full_name'], 'Iago') self.assertFalse(result['is_bot']) self.assertTrue(result['is_admin']) + self.assertFalse(result['is_owner']) + self.login('desdemona') + result = ujson.loads(self.client_get('/json/users/me').content) + self.assertEqual(result['short_name'], 'desdemona') + self.assertEqual(result['email'], desdemona.email) + self.assertFalse(result['is_bot']) + self.assertTrue(result['is_admin']) + self.assertTrue(result['is_owner']) # Tests the GET ../users/{id} api endpoint. user = self.example_user('hamlet') @@ -1398,6 +1408,7 @@ class GetProfileTest(ZulipTestCase): self.assertNotIn("profile_data", result['user']) self.assertFalse(result['user']['is_bot']) self.assertFalse(result['user']['is_admin']) + self.assertFalse(result['user']['is_owner']) result = ujson.loads(self.client_get('/json/users/{}?include_custom_profile_fields=true'.format(user.id)).content) diff --git a/zerver/views/users.py b/zerver/views/users.py index ce3c101a34..5d4cee2752 100644 --- a/zerver/views/users.py +++ b/zerver/views/users.py @@ -467,6 +467,7 @@ def get_profile_backend(request: HttpRequest, user_profile: UserProfile) -> Http email = user_profile.email, is_bot = user_profile.is_bot, is_admin = user_profile.is_realm_admin, + is_owner = user_profile.is_realm_owner, short_name = user_profile.short_name) if not user_profile.is_bot: