mirror of https://github.com/zulip/zulip.git
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.
This commit is contained in:
parent
cf8c1cb357
commit
9ef1c5b1a6
|
@ -10,6 +10,11 @@ below features are supported.
|
||||||
|
|
||||||
## Changes in Zulip 2.2
|
## 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**
|
**Feature level 7**
|
||||||
* [`GET /events`](/api/get-events-from-queue): `realm_user` and
|
* [`GET /events`](/api/get-events-from-queue): `realm_user` and
|
||||||
`realm_bot` events no longer contain an `email` field to identify
|
`realm_bot` events no longer contain an `email` field to identify
|
||||||
|
|
|
@ -29,7 +29,7 @@ DESKTOP_WARNING_VERSION = "5.2.0"
|
||||||
#
|
#
|
||||||
# Changes should be accompanied by documentation explaining what the
|
# Changes should be accompanied by documentation explaining what the
|
||||||
# new level means in templates/zerver/api/changelog.md.
|
# 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
|
# 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
|
# only when going from an old version of the code to a newer version. Bump
|
||||||
|
|
|
@ -311,6 +311,7 @@ def format_user_row(realm: Realm, acting_user: UserProfile, row: Dict[str, Any],
|
||||||
client_gravatar=client_gravatar,)
|
client_gravatar=client_gravatar,)
|
||||||
|
|
||||||
is_admin = is_administrator_role(row['role'])
|
is_admin = is_administrator_role(row['role'])
|
||||||
|
is_owner = row['role'] == UserProfile.ROLE_REALM_OWNER
|
||||||
is_guest = row['role'] == UserProfile.ROLE_GUEST
|
is_guest = row['role'] == UserProfile.ROLE_GUEST
|
||||||
is_bot = row['is_bot']
|
is_bot = row['is_bot']
|
||||||
# This format should align with get_cross_realm_dicts() and notify_created_user
|
# 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_url=avatar_url,
|
||||||
avatar_version=row['avatar_version'],
|
avatar_version=row['avatar_version'],
|
||||||
is_admin=is_admin,
|
is_admin=is_admin,
|
||||||
|
is_owner=is_owner,
|
||||||
is_guest=is_guest,
|
is_guest=is_guest,
|
||||||
is_bot=is_bot,
|
is_bot=is_bot,
|
||||||
full_name=row['full_name'],
|
full_name=row['full_name'],
|
||||||
|
|
|
@ -1353,6 +1353,7 @@ paths:
|
||||||
"is_active": true,
|
"is_active": true,
|
||||||
"email": "AARON@zulip.com",
|
"email": "AARON@zulip.com",
|
||||||
"is_admin": false,
|
"is_admin": false,
|
||||||
|
"is_owner": false,
|
||||||
"avatar_url": "https://secure.gravatar.com/avatar/818c212b9f8830dfef491b3f7da99a14?d=identicon&version=1",
|
"avatar_url": "https://secure.gravatar.com/avatar/818c212b9f8830dfef491b3f7da99a14?d=identicon&version=1",
|
||||||
"bot_type": null,
|
"bot_type": null,
|
||||||
"timezone": "",
|
"timezone": "",
|
||||||
|
@ -1401,6 +1402,7 @@ paths:
|
||||||
"bot_type": null,
|
"bot_type": null,
|
||||||
"timezone": "",
|
"timezone": "",
|
||||||
"is_admin": false,
|
"is_admin": false,
|
||||||
|
"is_owner": false,
|
||||||
"avatar_url": "https://secure.gravatar.com/avatar/6d8cad0fd00256e7b40691d27ddfd466?d=identicon&version=1",
|
"avatar_url": "https://secure.gravatar.com/avatar/6d8cad0fd00256e7b40691d27ddfd466?d=identicon&version=1",
|
||||||
"is_active": true,
|
"is_active": true,
|
||||||
"email": "hamlet@zulip.com"
|
"email": "hamlet@zulip.com"
|
||||||
|
@ -1414,6 +1416,7 @@ paths:
|
||||||
"is_active": true,
|
"is_active": true,
|
||||||
"avatar_url": "https://secure.gravatar.com/avatar/7328586831cdbb1627649bd857b1ee8c?d=identicon&version=1",
|
"avatar_url": "https://secure.gravatar.com/avatar/7328586831cdbb1627649bd857b1ee8c?d=identicon&version=1",
|
||||||
"is_admin": false,
|
"is_admin": false,
|
||||||
|
"is_owner": false,
|
||||||
"user_id": 23,
|
"user_id": 23,
|
||||||
"bot_type": 1,
|
"bot_type": 1,
|
||||||
"timezone": "",
|
"timezone": "",
|
||||||
|
@ -1550,6 +1553,7 @@ paths:
|
||||||
"bot_type": null,
|
"bot_type": null,
|
||||||
"timezone": "",
|
"timezone": "",
|
||||||
"is_admin": false,
|
"is_admin": false,
|
||||||
|
"is_owner": false,
|
||||||
"avatar_url": "https://secure.gravatar.com/avatar/6d8cad0fd00256e7b40691d27ddfd466?d=identicon&version=1",
|
"avatar_url": "https://secure.gravatar.com/avatar/6d8cad0fd00256e7b40691d27ddfd466?d=identicon&version=1",
|
||||||
"is_active": true,
|
"is_active": true,
|
||||||
"email": "hamlet@zulip.com"
|
"email": "hamlet@zulip.com"
|
||||||
|
@ -1830,6 +1834,14 @@ paths:
|
||||||
description: |
|
description: |
|
||||||
A boolean indicating if the requesting user is an admin.
|
A boolean indicating if the requesting user is an admin.
|
||||||
example: true
|
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:
|
is_bot:
|
||||||
type: boolean
|
type: boolean
|
||||||
description: |
|
description: |
|
||||||
|
@ -1875,6 +1887,7 @@ paths:
|
||||||
"email": "iago@zulip.com",
|
"email": "iago@zulip.com",
|
||||||
"full_name": "Iago",
|
"full_name": "Iago",
|
||||||
"is_admin": true,
|
"is_admin": true,
|
||||||
|
"is_owner": false,
|
||||||
"is_bot": false,
|
"is_bot": false,
|
||||||
"max_message_id": 30,
|
"max_message_id": 30,
|
||||||
"msg": "",
|
"msg": "",
|
||||||
|
@ -3966,6 +3979,13 @@ components:
|
||||||
type: boolean
|
type: boolean
|
||||||
description: |
|
description: |
|
||||||
A boolean specifying whether the user is an organization administrator.
|
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:
|
bot_type:
|
||||||
type: integer
|
type: integer
|
||||||
nullable: true
|
nullable: true
|
||||||
|
|
|
@ -672,15 +672,15 @@ class ListCustomProfileFieldTest(CustomProfileFieldTestCase):
|
||||||
|
|
||||||
expected_keys_for_iago = {
|
expected_keys_for_iago = {
|
||||||
"delivery_email",
|
"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"}
|
"full_name", "timezone", "is_active", "date_joined", "profile_data"}
|
||||||
self.assertEqual(set(iago_raw_data.keys()), expected_keys_for_iago)
|
self.assertEqual(set(iago_raw_data.keys()), expected_keys_for_iago)
|
||||||
self.assertNotEqual(iago_raw_data["profile_data"], {})
|
self.assertNotEqual(iago_raw_data["profile_data"], {})
|
||||||
|
|
||||||
expected_keys_for_test_bot = {
|
expected_keys_for_test_bot = {
|
||||||
"delivery_email",
|
"delivery_email",
|
||||||
"email", "user_id", "avatar_url", "avatar_version", "is_admin", "is_guest", "is_bot", "full_name",
|
"email", "user_id", "avatar_url", "avatar_version", "is_admin", "is_guest", "is_bot", "is_owner",
|
||||||
"timezone", "is_active", "date_joined", "bot_type", "bot_owner_id"}
|
"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(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_type"], 1)
|
||||||
self.assertEqual(test_bot_raw_data["bot_owner_id"], iago_raw_data["user_id"])
|
self.assertEqual(test_bot_raw_data["bot_owner_id"], iago_raw_data["user_id"])
|
||||||
|
@ -697,8 +697,8 @@ class ListCustomProfileFieldTest(CustomProfileFieldTestCase):
|
||||||
self.login('iago')
|
self.login('iago')
|
||||||
expected_keys = {
|
expected_keys = {
|
||||||
"result", "msg", "pointer", "client_id", "max_message_id", "user_id",
|
"result", "msg", "pointer", "client_id", "max_message_id", "user_id",
|
||||||
"avatar_url", "full_name", "email", "is_bot", "is_admin", "short_name",
|
"avatar_url", "full_name", "email", "is_bot", "is_admin", "is_owner",
|
||||||
"profile_data"}
|
"short_name", "profile_data"}
|
||||||
|
|
||||||
url = "/json/users/me"
|
url = "/json/users/me"
|
||||||
response = self.client_get(url)
|
response = self.client_get(url)
|
||||||
|
|
|
@ -1248,6 +1248,7 @@ class EventsRegisterTest(ZulipTestCase):
|
||||||
('avatar_version', check_int),
|
('avatar_version', check_int),
|
||||||
('full_name', check_string),
|
('full_name', check_string),
|
||||||
('is_admin', check_bool),
|
('is_admin', check_bool),
|
||||||
|
('is_owner', check_bool),
|
||||||
('is_bot', check_bool),
|
('is_bot', check_bool),
|
||||||
('is_guest', check_bool),
|
('is_guest', check_bool),
|
||||||
('is_active', check_bool),
|
('is_active', check_bool),
|
||||||
|
@ -1276,6 +1277,7 @@ class EventsRegisterTest(ZulipTestCase):
|
||||||
('full_name', check_string),
|
('full_name', check_string),
|
||||||
('is_active', check_bool),
|
('is_active', check_bool),
|
||||||
('is_admin', check_bool),
|
('is_admin', check_bool),
|
||||||
|
('is_owner', check_bool),
|
||||||
('is_bot', check_bool),
|
('is_bot', check_bool),
|
||||||
('is_guest', check_bool),
|
('is_guest', check_bool),
|
||||||
('profile_data', check_dict_only([])),
|
('profile_data', check_dict_only([])),
|
||||||
|
|
|
@ -614,6 +614,7 @@ class HomeTest(ZulipTestCase):
|
||||||
is_active=True,
|
is_active=True,
|
||||||
is_bot=True,
|
is_bot=True,
|
||||||
is_admin=False,
|
is_admin=False,
|
||||||
|
is_owner=False,
|
||||||
is_cross_realm_bot=True,
|
is_cross_realm_bot=True,
|
||||||
is_guest=False
|
is_guest=False
|
||||||
),
|
),
|
||||||
|
@ -627,6 +628,7 @@ class HomeTest(ZulipTestCase):
|
||||||
is_active=True,
|
is_active=True,
|
||||||
is_bot=True,
|
is_bot=True,
|
||||||
is_admin=False,
|
is_admin=False,
|
||||||
|
is_owner=False,
|
||||||
is_cross_realm_bot=True,
|
is_cross_realm_bot=True,
|
||||||
is_guest=False
|
is_guest=False
|
||||||
),
|
),
|
||||||
|
@ -640,6 +642,7 @@ class HomeTest(ZulipTestCase):
|
||||||
is_active=True,
|
is_active=True,
|
||||||
is_bot=True,
|
is_bot=True,
|
||||||
is_admin=False,
|
is_admin=False,
|
||||||
|
is_owner=False,
|
||||||
is_cross_realm_bot=True,
|
is_cross_realm_bot=True,
|
||||||
is_guest=False
|
is_guest=False
|
||||||
),
|
),
|
||||||
|
|
|
@ -1371,6 +1371,7 @@ class GetProfileTest(ZulipTestCase):
|
||||||
def test_get_user_profile(self) -> None:
|
def test_get_user_profile(self) -> None:
|
||||||
hamlet = self.example_user('hamlet')
|
hamlet = self.example_user('hamlet')
|
||||||
iago = self.example_user('iago')
|
iago = self.example_user('iago')
|
||||||
|
desdemona = self.example_user('desdemona')
|
||||||
|
|
||||||
self.login('hamlet')
|
self.login('hamlet')
|
||||||
result = ujson.loads(self.client_get('/json/users/me').content)
|
result = ujson.loads(self.client_get('/json/users/me').content)
|
||||||
|
@ -1380,6 +1381,7 @@ class GetProfileTest(ZulipTestCase):
|
||||||
self.assertIn("user_id", result)
|
self.assertIn("user_id", result)
|
||||||
self.assertFalse(result['is_bot'])
|
self.assertFalse(result['is_bot'])
|
||||||
self.assertFalse(result['is_admin'])
|
self.assertFalse(result['is_admin'])
|
||||||
|
self.assertFalse(result['is_owner'])
|
||||||
self.assertFalse('delivery_email' in result)
|
self.assertFalse('delivery_email' in result)
|
||||||
self.login('iago')
|
self.login('iago')
|
||||||
result = ujson.loads(self.client_get('/json/users/me').content)
|
result = ujson.loads(self.client_get('/json/users/me').content)
|
||||||
|
@ -1388,6 +1390,14 @@ class GetProfileTest(ZulipTestCase):
|
||||||
self.assertEqual(result['full_name'], 'Iago')
|
self.assertEqual(result['full_name'], 'Iago')
|
||||||
self.assertFalse(result['is_bot'])
|
self.assertFalse(result['is_bot'])
|
||||||
self.assertTrue(result['is_admin'])
|
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.
|
# Tests the GET ../users/{id} api endpoint.
|
||||||
user = self.example_user('hamlet')
|
user = self.example_user('hamlet')
|
||||||
|
@ -1398,6 +1408,7 @@ class GetProfileTest(ZulipTestCase):
|
||||||
self.assertNotIn("profile_data", result['user'])
|
self.assertNotIn("profile_data", result['user'])
|
||||||
self.assertFalse(result['user']['is_bot'])
|
self.assertFalse(result['user']['is_bot'])
|
||||||
self.assertFalse(result['user']['is_admin'])
|
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)
|
result = ujson.loads(self.client_get('/json/users/{}?include_custom_profile_fields=true'.format(user.id)).content)
|
||||||
|
|
||||||
|
|
|
@ -467,6 +467,7 @@ def get_profile_backend(request: HttpRequest, user_profile: UserProfile) -> Http
|
||||||
email = user_profile.email,
|
email = user_profile.email,
|
||||||
is_bot = user_profile.is_bot,
|
is_bot = user_profile.is_bot,
|
||||||
is_admin = user_profile.is_realm_admin,
|
is_admin = user_profile.is_realm_admin,
|
||||||
|
is_owner = user_profile.is_realm_owner,
|
||||||
short_name = user_profile.short_name)
|
short_name = user_profile.short_name)
|
||||||
|
|
||||||
if not user_profile.is_bot:
|
if not user_profile.is_bot:
|
||||||
|
|
Loading…
Reference in New Issue