users: Refactor get_profile_backend to be based on format_user_row.

This commit changes get_profile_backend to be based on format_user_row
such that it's a superset of the fields for our other endpoints for
getting data on a user.

To be clear, this does not removes any of the exisiting fields, that
were returned by this endpoint.

This change adds some fields to the User object returned by the
endpoint. API docs are updated accordingly for the added fields.
This commit is contained in:
sahil839 2020-06-08 03:59:47 +05:30 committed by Tim Abbott
parent 08ddeca8a5
commit 1f5778bad7
5 changed files with 62 additions and 26 deletions

View File

@ -12,6 +12,9 @@ below features are supported.
**Feature level 10** **Feature level 10**
* [`GET users/me`](/api/get-profile): Added `avatar_version`, `is_guest`,
`is_active`, `timezone`, and `date_joined` fields to the User objects.
**Feature level 9** **Feature level 9**
* [`POST users/me/subscriptions`](/api/add-subscriptions), [`DELETE * [`POST users/me/subscriptions`](/api/add-subscriptions), [`DELETE

View File

@ -1836,6 +1836,16 @@ paths:
**Changes**: New in Zulip 2.1.0. **Changes**: New in Zulip 2.1.0.
example: "x" example: "x"
avatar_version:
type: integer
description: |
Version for the the user's avatar. Used for cache-busting requests
for the user's avatar. Clients generally shouldn't need to use this;
most avatar URLs sent by Zulip will already end with `?v={avatar_version}`.
**Changes**: New in Zulip 2.2 (feature level 10). Previous
versions do not return this field.
example: 1
client_id: client_id:
type: string type: string
description: | description: |
@ -1864,11 +1874,43 @@ paths:
**Changes**: New in Zulip 2.2 (feature level 8). **Changes**: New in Zulip 2.2 (feature level 8).
example: false example: false
is_guest:
type: boolean
description: |
A boolean indicating if the requesting user is a guest.
**Changes**: New in Zulip 2.2 (feature level 10). Previous
versions do not return this field.
example: false
is_bot: is_bot:
type: boolean type: boolean
description: | description: |
A boolean indicating if the requesting user is a bot. A boolean indicating if the requesting user is a bot.
example: false example: false
is_active:
type: boolean
description: |
A boolean specifying whether the user account has been deactivated.
**Changes**: New in Zulip 2.2 (feature level 10). Previous
versions do not return this field.
example: true
timezone:
type: string
description: |
The time zone of the user.
**Changes**: New in Zulip 2.2 (feature level 10). Previous
versions do not return this field.
example: ""
date_joined:
type: string
description: |
The time the user account was created.
**Changes**: New in Zulip 2.2 (feature level 10). Previous
versions do not return this field.
example: "2019-10-20T07:50:53.728864+00:00"
max_message_id: max_message_id:
type: integer type: integer
description: | description: |
@ -1899,12 +1941,17 @@ paths:
- example: - example:
{ {
"avatar_url": "https://secure.gravatar.com/avatar/af4f06322c177ef4e1e9b2c424986b54?d=identicon&version=1", "avatar_url": "https://secure.gravatar.com/avatar/af4f06322c177ef4e1e9b2c424986b54?d=identicon&version=1",
"avatar_version": 1,
"client_id": "74c768b081076fdb3c4326256c17467e", "client_id": "74c768b081076fdb3c4326256c17467e",
"email": "iago@zulip.com", "email": "iago@zulip.com",
"full_name": "Iago", "full_name": "Iago",
"is_admin": true, "is_admin": true,
"is_owner": false, "is_owner": false,
"is_guest": false,
"is_bot": false, "is_bot": false,
"is_active": true,
"timezone": "",
"date_joined": "2019-10-20T07:50:53.728864+00:00",
"max_message_id": 30, "max_message_id": 30,
"msg": "", "msg": "",
"pointer": -1, "pointer": -1,

View File

@ -698,7 +698,8 @@ class ListCustomProfileFieldTest(CustomProfileFieldTestCase):
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", "is_owner", "avatar_url", "full_name", "email", "is_bot", "is_admin", "is_owner",
"short_name", "profile_data"} "short_name", "profile_data", "avatar_version", "timezone", "delivery_email",
"is_active", "is_guest", "date_joined"}
url = "/json/users/me" url = "/json/users/me"
response = self.client_get(url) response = self.client_get(url)

View File

@ -1379,6 +1379,7 @@ class GetProfileTest(ZulipTestCase):
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(result['is_owner'])
self.assertFalse(result['is_guest'])
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 +1389,7 @@ class GetProfileTest(ZulipTestCase):
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.assertFalse(result['is_owner'])
self.assertFalse(result['is_guest'])
self.login('desdemona') self.login('desdemona')
result = ujson.loads(self.client_get('/json/users/me').content) result = ujson.loads(self.client_get('/json/users/me').content)
self.assertEqual(result['short_name'], 'desdemona') self.assertEqual(result['short_name'], 'desdemona')
@ -1395,6 +1397,7 @@ class GetProfileTest(ZulipTestCase):
self.assertFalse(result['is_bot']) self.assertFalse(result['is_bot'])
self.assertTrue(result['is_admin']) self.assertTrue(result['is_admin'])
self.assertTrue(result['is_owner']) self.assertTrue(result['is_owner'])
self.assertFalse(result['is_guest'])
# Tests the GET ../users/{id} api endpoint. # Tests the GET ../users/{id} api endpoint.
user = self.example_user('hamlet') user = self.example_user('hamlet')

View File

@ -458,32 +458,14 @@ def generate_client_id() -> str:
return generate_random_token(32) return generate_random_token(32)
def get_profile_backend(request: HttpRequest, user_profile: UserProfile) -> HttpResponse: def get_profile_backend(request: HttpRequest, user_profile: UserProfile) -> HttpResponse:
result = dict(pointer = user_profile.pointer, raw_user_data = get_raw_user_data(user_profile.realm, user_profile,
client_id = generate_client_id(), client_gravatar=False, target_user=user_profile)
max_message_id = -1, result: Dict[str, Any] = raw_user_data[user_profile.id]
user_id = user_profile.id,
avatar_url = avatar_url(user_profile),
full_name = user_profile.full_name,
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: result['client_id'] = generate_client_id()
custom_profile_field_values = user_profile.customprofilefieldvalue_set.all() result['short_name'] = user_profile.short_name
profile_data: Dict[int, Dict[str, Any]] = dict() result['max_message_id'] = -1
for profile_field in custom_profile_field_values: result['pointer'] = user_profile.pointer
if profile_field.field.is_renderable():
profile_data[profile_field.field_id] = {
"value": profile_field.value,
"rendered_value": profile_field.rendered_value
}
else:
profile_data[profile_field.field_id] = {
"value": profile_field.value
}
result["profile_data"] = profile_data
messages = Message.objects.filter(usermessage__user_profile=user_profile).order_by('-id')[:1] messages = Message.objects.filter(usermessage__user_profile=user_profile).order_by('-id')[:1]
if messages: if messages: