mirror of https://github.com/zulip/zulip.git
api: Add "users/<int:user_id>/status" endpoint.
The documentation Creates a shared UserStatus schema that's used for the return value of this new endpoint and for the existing user_status objects returned by the register queue endpoint. Co-authored-by: Suyash Vardhan Mathur <suyash.mathur@research.iiit.ac.in> Fixes #19079.
This commit is contained in:
parent
d6672c57ff
commit
62dfd93a83
|
@ -20,6 +20,12 @@ format used by the Zulip server that they are interacting with.
|
||||||
|
|
||||||
## Changes in Zulip 9.0
|
## Changes in Zulip 9.0
|
||||||
|
|
||||||
|
**Feature level 262**:
|
||||||
|
|
||||||
|
* [`GET /users/{user_id}/status`](/api/get-user-status): Added a new
|
||||||
|
endpoint to fetch an individual user's currently set
|
||||||
|
[status](/help/status-and-availability).
|
||||||
|
|
||||||
**Feature level 261**
|
**Feature level 261**
|
||||||
|
|
||||||
* [`POST /invites`](/api/send-invites),
|
* [`POST /invites`](/api/send-invites),
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
* [Deactivate own user](/api/deactivate-own-user)
|
* [Deactivate own user](/api/deactivate-own-user)
|
||||||
* [Set "typing" status](/api/set-typing-status)
|
* [Set "typing" status](/api/set-typing-status)
|
||||||
* [Get user presence](/api/get-user-presence)
|
* [Get user presence](/api/get-user-presence)
|
||||||
|
* [Get a user's status](/api/get-user-status)
|
||||||
* [Get presence of all users](/api/get-presence)
|
* [Get presence of all users](/api/get-presence)
|
||||||
* [Get attachments](/api/get-attachments)
|
* [Get attachments](/api/get-attachments)
|
||||||
* [Delete an attachment](/api/remove-attachment)
|
* [Delete an attachment](/api/remove-attachment)
|
||||||
|
|
|
@ -33,7 +33,7 @@ DESKTOP_WARNING_VERSION = "5.9.3"
|
||||||
# Changes should be accompanied by documentation explaining what the
|
# Changes should be accompanied by documentation explaining what the
|
||||||
# new level means in api_docs/changelog.md, as well as "**Changes**"
|
# new level means in api_docs/changelog.md, as well as "**Changes**"
|
||||||
# entries in the endpoint's documentation in `zulip.yaml`.
|
# entries in the endpoint's documentation in `zulip.yaml`.
|
||||||
API_FEATURE_LEVEL = 261
|
API_FEATURE_LEVEL = 262
|
||||||
|
|
||||||
# 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
|
||||||
|
|
|
@ -113,3 +113,22 @@ def update_user_status(
|
||||||
user_profile_id=user_profile_id,
|
user_profile_id=user_profile_id,
|
||||||
defaults=defaults,
|
defaults=defaults,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def get_user_status(user_profile: UserProfile) -> UserInfoDict:
|
||||||
|
status_set_by_user = (
|
||||||
|
UserStatus.objects.filter(user_profile=user_profile)
|
||||||
|
.values(
|
||||||
|
"user_profile_id",
|
||||||
|
"user_profile__presence_enabled",
|
||||||
|
"status_text",
|
||||||
|
"emoji_name",
|
||||||
|
"emoji_code",
|
||||||
|
"reaction_type",
|
||||||
|
)
|
||||||
|
.first()
|
||||||
|
)
|
||||||
|
|
||||||
|
if not status_set_by_user:
|
||||||
|
return {}
|
||||||
|
return format_user_status(status_set_by_user)
|
||||||
|
|
|
@ -195,6 +195,20 @@ def get_user_presence(client: Client) -> None:
|
||||||
validate_against_openapi_schema(result, "/users/{user_id_or_email}/presence", "get", "200")
|
validate_against_openapi_schema(result, "/users/{user_id_or_email}/presence", "get", "200")
|
||||||
|
|
||||||
|
|
||||||
|
@openapi_test_function("/users/{user_id}/status:get")
|
||||||
|
def get_user_status(client: Client) -> None:
|
||||||
|
# {code_example|start}
|
||||||
|
# Get the status currently set by a user.
|
||||||
|
user_id = 11
|
||||||
|
result = client.call_endpoint(
|
||||||
|
url=f"/users/{user_id}/status",
|
||||||
|
method="GET",
|
||||||
|
)
|
||||||
|
# {code_example|end}
|
||||||
|
|
||||||
|
validate_against_openapi_schema(result, "/users/{user_id}/status", "get", "200")
|
||||||
|
|
||||||
|
|
||||||
@openapi_test_function("/users/me/presence:post")
|
@openapi_test_function("/users/me/presence:post")
|
||||||
def update_presence(client: Client) -> None:
|
def update_presence(client: Client) -> None:
|
||||||
request = {
|
request = {
|
||||||
|
@ -1701,6 +1715,7 @@ def test_users(client: Client, owner_client: Client) -> None:
|
||||||
reactivate_user(client)
|
reactivate_user(client)
|
||||||
update_user(client)
|
update_user(client)
|
||||||
update_status(client)
|
update_status(client)
|
||||||
|
get_user_status(client)
|
||||||
get_user_by_email(client)
|
get_user_by_email(client)
|
||||||
get_subscription_status(client)
|
get_subscription_status(client)
|
||||||
get_profile(client)
|
get_profile(client)
|
||||||
|
|
|
@ -8416,6 +8416,68 @@ paths:
|
||||||
"200":
|
"200":
|
||||||
$ref: "#/components/responses/SimpleSuccess"
|
$ref: "#/components/responses/SimpleSuccess"
|
||||||
|
|
||||||
|
/users/{user_id}/status:
|
||||||
|
get:
|
||||||
|
operationId: get-user-status
|
||||||
|
summary: Get a user's status
|
||||||
|
tags: ["users"]
|
||||||
|
description: |
|
||||||
|
Get the [status](/help/status-and-availability) currently set by a
|
||||||
|
user in the organization.
|
||||||
|
|
||||||
|
**Changes**: New in Zulip 9.0 (feature level 262). Previously,
|
||||||
|
user statuses could only be fetched via the [`POST
|
||||||
|
/register`](/api/register-queue) endpoint.
|
||||||
|
parameters:
|
||||||
|
- $ref: "#/components/parameters/UserId"
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: Success.
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
allOf:
|
||||||
|
- $ref: "#/components/schemas/JsonSuccessBase"
|
||||||
|
- additionalProperties: false
|
||||||
|
properties:
|
||||||
|
result: {}
|
||||||
|
msg: {}
|
||||||
|
ignored_parameters_unsupported: {}
|
||||||
|
status:
|
||||||
|
allOf:
|
||||||
|
- description: |
|
||||||
|
The status set by the user. Note that, if the user doesn't have a status
|
||||||
|
currently set, then the returned dictionary will be empty as none of the
|
||||||
|
keys listed below will be present.
|
||||||
|
- $ref: "#/components/schemas/UserStatus"
|
||||||
|
|
||||||
|
example:
|
||||||
|
{
|
||||||
|
"result": "success",
|
||||||
|
"msg": "",
|
||||||
|
"status":
|
||||||
|
{
|
||||||
|
"status_text": "on vacation",
|
||||||
|
"emoji_name": "car",
|
||||||
|
"emoji_code": "1f697",
|
||||||
|
"reaction_type": "unicode_emoji",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
"400":
|
||||||
|
description: Success.
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
allOf:
|
||||||
|
- $ref: "#/components/schemas/CodedError"
|
||||||
|
- example:
|
||||||
|
{
|
||||||
|
"result": "error",
|
||||||
|
"msg": "No such user",
|
||||||
|
"code": "BAD_REQUEST",
|
||||||
|
}
|
||||||
|
description: |
|
||||||
|
An example JSON error response when the user does not exist:
|
||||||
/users/{user_id_or_email}/presence:
|
/users/{user_id_or_email}/presence:
|
||||||
get:
|
get:
|
||||||
operationId: get-user-presence
|
operationId: get-user-presence
|
||||||
|
@ -13652,63 +13714,11 @@ paths:
|
||||||
**Changes**: The emoji parameters are new in Zulip 5.0 (feature level 86).
|
**Changes**: The emoji parameters are new in Zulip 5.0 (feature level 86).
|
||||||
Previously, Zulip did not support emoji associated with statuses.
|
Previously, Zulip did not support emoji associated with statuses.
|
||||||
additionalProperties:
|
additionalProperties:
|
||||||
description: |
|
allOf:
|
||||||
`{user_id}`: Object containing the status details of a user
|
- description: |
|
||||||
with the key of the object being the ID of the user.
|
`{user_id}`: Object containing the status details of a user
|
||||||
type: object
|
with the key of the object being the ID of the user.
|
||||||
additionalProperties: false
|
- $ref: "#/components/schemas/UserStatus"
|
||||||
properties:
|
|
||||||
away:
|
|
||||||
type: boolean
|
|
||||||
deprecated: true
|
|
||||||
description: |
|
|
||||||
If present, the user has marked themself "away".
|
|
||||||
|
|
||||||
**Changes**: Deprecated in Zulip 6.0 (feature level 148);
|
|
||||||
starting with that feature level, `away` is a legacy way to
|
|
||||||
access the user's `presence_enabled` setting, with
|
|
||||||
`away = !presence_enabled`. To be removed in a future release.
|
|
||||||
status_text:
|
|
||||||
type: string
|
|
||||||
description: |
|
|
||||||
If present, the text content of the user's status message.
|
|
||||||
emoji_name:
|
|
||||||
type: string
|
|
||||||
description: |
|
|
||||||
If present, the name for the emoji to associate with the user's status.
|
|
||||||
|
|
||||||
**Changes**: New in Zulip 5.0 (feature level 86).
|
|
||||||
emoji_code:
|
|
||||||
type: string
|
|
||||||
description: |
|
|
||||||
If present, a unique identifier, defining the specific emoji codepoint
|
|
||||||
requested, within the namespace of the `reaction_type`.
|
|
||||||
|
|
||||||
**Changes**: New in Zulip 5.0 (feature level 86).
|
|
||||||
reaction_type:
|
|
||||||
type: string
|
|
||||||
enum:
|
|
||||||
- unicode_emoji
|
|
||||||
- realm_emoji
|
|
||||||
- zulip_extra_emoji
|
|
||||||
description: |
|
|
||||||
If present, a string indicating the type of emoji. Each emoji
|
|
||||||
`reaction_type` has an independent namespace for values of `emoji_code`.
|
|
||||||
|
|
||||||
Must be one of the following values:
|
|
||||||
|
|
||||||
- `unicode_emoji` : In this namespace, `emoji_code` will be a
|
|
||||||
dash-separated hex encoding of the sequence of Unicode codepoints
|
|
||||||
that define this emoji in the Unicode specification.
|
|
||||||
|
|
||||||
- `realm_emoji` : In this namespace, `emoji_code` will be the ID of
|
|
||||||
the uploaded [custom emoji](/help/custom-emoji).
|
|
||||||
|
|
||||||
- `zulip_extra_emoji` : These are special emoji included with Zulip.
|
|
||||||
In this namespace, `emoji_code` will be the name of the emoji (e.g.
|
|
||||||
"zulip").
|
|
||||||
|
|
||||||
**Changes**: New in Zulip 5.0 (feature level 86).
|
|
||||||
user_settings:
|
user_settings:
|
||||||
type: object
|
type: object
|
||||||
description: |
|
description: |
|
||||||
|
@ -21100,6 +21110,61 @@ components:
|
||||||
**Changes**: Starting with Zulip 7.0 (feature level 178), always
|
**Changes**: Starting with Zulip 7.0 (feature level 178), always
|
||||||
`false` when present as the server no longer stores which client
|
`false` when present as the server no longer stores which client
|
||||||
submitted presence data.
|
submitted presence data.
|
||||||
|
UserStatus:
|
||||||
|
type: object
|
||||||
|
additionalProperties: false
|
||||||
|
properties:
|
||||||
|
away:
|
||||||
|
type: boolean
|
||||||
|
deprecated: true
|
||||||
|
description: |
|
||||||
|
If present, the user has marked themself "away".
|
||||||
|
|
||||||
|
**Changes**: Deprecated in Zulip 6.0 (feature level 148);
|
||||||
|
starting with that feature level, `away` is a legacy way to
|
||||||
|
access the user's `presence_enabled` setting, with
|
||||||
|
`away = !presence_enabled`. To be removed in a future release.
|
||||||
|
status_text:
|
||||||
|
type: string
|
||||||
|
description: |
|
||||||
|
If present, the text content of the user's status message.
|
||||||
|
emoji_name:
|
||||||
|
type: string
|
||||||
|
description: |
|
||||||
|
If present, the name for the emoji to associate with the user's status.
|
||||||
|
|
||||||
|
**Changes**: New in Zulip 5.0 (feature level 86).
|
||||||
|
emoji_code:
|
||||||
|
type: string
|
||||||
|
description: |
|
||||||
|
If present, a unique identifier, defining the specific emoji codepoint
|
||||||
|
requested, within the namespace of the `reaction_type`.
|
||||||
|
|
||||||
|
**Changes**: New in Zulip 5.0 (feature level 86).
|
||||||
|
reaction_type:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- unicode_emoji
|
||||||
|
- realm_emoji
|
||||||
|
- zulip_extra_emoji
|
||||||
|
description: |
|
||||||
|
If present, a string indicating the type of emoji. Each emoji
|
||||||
|
`reaction_type` has an independent namespace for values of `emoji_code`.
|
||||||
|
|
||||||
|
Must be one of the following values:
|
||||||
|
|
||||||
|
- `unicode_emoji` : In this namespace, `emoji_code` will be a
|
||||||
|
dash-separated hex encoding of the sequence of Unicode codepoints
|
||||||
|
that define this emoji in the Unicode specification.
|
||||||
|
|
||||||
|
- `realm_emoji` : In this namespace, `emoji_code` will be the ID of
|
||||||
|
the uploaded [custom emoji](/help/custom-emoji).
|
||||||
|
|
||||||
|
- `zulip_extra_emoji` : These are special emoji included with Zulip.
|
||||||
|
In this namespace, `emoji_code` will be the name of the emoji (e.g.
|
||||||
|
"zulip").
|
||||||
|
|
||||||
|
**Changes**: New in Zulip 5.0 (feature level 86).
|
||||||
Draft:
|
Draft:
|
||||||
type: object
|
type: object
|
||||||
description: |
|
description: |
|
||||||
|
|
|
@ -3,7 +3,12 @@ from typing import Any, Dict, Optional
|
||||||
import orjson
|
import orjson
|
||||||
|
|
||||||
from zerver.lib.test_classes import ZulipTestCase
|
from zerver.lib.test_classes import ZulipTestCase
|
||||||
from zerver.lib.user_status import UserInfoDict, get_all_users_status_dict, update_user_status
|
from zerver.lib.user_status import (
|
||||||
|
UserInfoDict,
|
||||||
|
get_all_users_status_dict,
|
||||||
|
get_user_status,
|
||||||
|
update_user_status,
|
||||||
|
)
|
||||||
from zerver.models import UserProfile, UserStatus
|
from zerver.models import UserProfile, UserStatus
|
||||||
from zerver.models.clients import get_client
|
from zerver.models.clients import get_client
|
||||||
|
|
||||||
|
@ -65,6 +70,17 @@ class UserStatusTest(ZulipTestCase):
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
fetched_status = get_user_status(hamlet)
|
||||||
|
self.assertEqual(
|
||||||
|
fetched_status,
|
||||||
|
dict(
|
||||||
|
status_text="out to lunch",
|
||||||
|
emoji_name="car",
|
||||||
|
emoji_code="1f697",
|
||||||
|
reaction_type=UserStatus.UNICODE_EMOJI,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
rec_count = UserStatus.objects.filter(user_profile_id=hamlet.id).count()
|
rec_count = UserStatus.objects.filter(user_profile_id=hamlet.id).count()
|
||||||
self.assertEqual(rec_count, 1)
|
self.assertEqual(rec_count, 1)
|
||||||
|
|
||||||
|
@ -88,6 +104,17 @@ class UserStatusTest(ZulipTestCase):
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
fetched_status = get_user_status(hamlet)
|
||||||
|
self.assertEqual(
|
||||||
|
fetched_status,
|
||||||
|
dict(
|
||||||
|
status_text="out to lunch",
|
||||||
|
emoji_name="car",
|
||||||
|
emoji_code="1f697",
|
||||||
|
reaction_type=UserStatus.UNICODE_EMOJI,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
# Clear the status_text and emoji_info now.
|
# Clear the status_text and emoji_info now.
|
||||||
update_user_status(
|
update_user_status(
|
||||||
user_profile_id=hamlet.id,
|
user_profile_id=hamlet.id,
|
||||||
|
@ -103,6 +130,12 @@ class UserStatusTest(ZulipTestCase):
|
||||||
{},
|
{},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
fetched_status = get_user_status(hamlet)
|
||||||
|
self.assertEqual(
|
||||||
|
fetched_status,
|
||||||
|
{},
|
||||||
|
)
|
||||||
|
|
||||||
# Set Hamlet to in a meeting.
|
# Set Hamlet to in a meeting.
|
||||||
update_user_status(
|
update_user_status(
|
||||||
user_profile_id=hamlet.id,
|
user_profile_id=hamlet.id,
|
||||||
|
@ -118,6 +151,12 @@ class UserStatusTest(ZulipTestCase):
|
||||||
dict(status_text="in a meeting"),
|
dict(status_text="in a meeting"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
fetched_status = get_user_status(hamlet)
|
||||||
|
self.assertEqual(
|
||||||
|
fetched_status,
|
||||||
|
dict(status_text="in a meeting"),
|
||||||
|
)
|
||||||
|
|
||||||
# Test user status for inaccessible users.
|
# Test user status for inaccessible users.
|
||||||
self.set_up_db_for_testing_user_access()
|
self.set_up_db_for_testing_user_access()
|
||||||
cordelia = self.example_user("cordelia")
|
cordelia = self.example_user("cordelia")
|
||||||
|
@ -204,6 +243,13 @@ class UserStatusTest(ZulipTestCase):
|
||||||
dict(away=True, status_text="on vacation"),
|
dict(away=True, status_text="on vacation"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
result = self.client_get(f"/json/users/{hamlet.id}/status")
|
||||||
|
result_dict = self.assert_json_success(result)
|
||||||
|
self.assertEqual(
|
||||||
|
result_dict["status"],
|
||||||
|
dict(away=True, status_text="on vacation"),
|
||||||
|
)
|
||||||
|
|
||||||
# Setting away is a deprecated way of accessing a user's presence_enabled
|
# Setting away is a deprecated way of accessing a user's presence_enabled
|
||||||
# setting. Can be removed when clients migrate "away" (also referred to as
|
# setting. Can be removed when clients migrate "away" (also referred to as
|
||||||
# "unavailable") feature to directly use the presence_enabled setting.
|
# "unavailable") feature to directly use the presence_enabled setting.
|
||||||
|
@ -234,6 +280,19 @@ class UserStatusTest(ZulipTestCase):
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
result = self.client_get(f"/json/users/{hamlet.id}/status")
|
||||||
|
result_dict = self.assert_json_success(result)
|
||||||
|
self.assertEqual(
|
||||||
|
result_dict["status"],
|
||||||
|
dict(
|
||||||
|
away=True,
|
||||||
|
status_text="on vacation",
|
||||||
|
emoji_name="car",
|
||||||
|
emoji_code="1f697",
|
||||||
|
reaction_type=UserStatus.UNICODE_EMOJI,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
# Server should remove emoji_code and reaction_type if emoji_name is empty.
|
# Server should remove emoji_code and reaction_type if emoji_name is empty.
|
||||||
self.update_status_and_assert_event(
|
self.update_status_and_assert_event(
|
||||||
payload=dict(
|
payload=dict(
|
||||||
|
@ -252,6 +311,13 @@ class UserStatusTest(ZulipTestCase):
|
||||||
dict(away=True, status_text="on vacation"),
|
dict(away=True, status_text="on vacation"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
result = self.client_get(f"/json/users/{hamlet.id}/status")
|
||||||
|
result_dict = self.assert_json_success(result)
|
||||||
|
self.assertEqual(
|
||||||
|
result_dict["status"],
|
||||||
|
dict(away=True, status_text="on vacation"),
|
||||||
|
)
|
||||||
|
|
||||||
# Now revoke "away" status.
|
# Now revoke "away" status.
|
||||||
self.update_status_and_assert_event(
|
self.update_status_and_assert_event(
|
||||||
payload=dict(away=orjson.dumps(False).decode()),
|
payload=dict(away=orjson.dumps(False).decode()),
|
||||||
|
@ -280,6 +346,13 @@ class UserStatusTest(ZulipTestCase):
|
||||||
dict(status_text="in office"),
|
dict(status_text="in office"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
result = self.client_get(f"/json/users/{hamlet.id}/status")
|
||||||
|
result_dict = self.assert_json_success(result)
|
||||||
|
self.assertEqual(
|
||||||
|
result_dict["status"],
|
||||||
|
dict(status_text="in office"),
|
||||||
|
)
|
||||||
|
|
||||||
# And finally clear your info.
|
# And finally clear your info.
|
||||||
self.update_status_and_assert_event(
|
self.update_status_and_assert_event(
|
||||||
payload=dict(status_text=""),
|
payload=dict(status_text=""),
|
||||||
|
@ -290,6 +363,13 @@ class UserStatusTest(ZulipTestCase):
|
||||||
{},
|
{},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
result = self.client_get(f"/json/users/{hamlet.id}/status")
|
||||||
|
result_dict = self.assert_json_success(result)
|
||||||
|
self.assertEqual(
|
||||||
|
result_dict["status"],
|
||||||
|
{},
|
||||||
|
)
|
||||||
|
|
||||||
# Turn on "away" status again.
|
# Turn on "away" status again.
|
||||||
self.update_status_and_assert_event(
|
self.update_status_and_assert_event(
|
||||||
payload=dict(away=orjson.dumps(True).decode()),
|
payload=dict(away=orjson.dumps(True).decode()),
|
||||||
|
@ -312,3 +392,23 @@ class UserStatusTest(ZulipTestCase):
|
||||||
user_status_info(hamlet),
|
user_status_info(hamlet),
|
||||||
dict(status_text="at the beach", away=True),
|
dict(status_text="at the beach", away=True),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
result = self.client_get(f"/json/users/{hamlet.id}/status")
|
||||||
|
result_dict = self.assert_json_success(result)
|
||||||
|
self.assertEqual(
|
||||||
|
result_dict["status"],
|
||||||
|
dict(status_text="at the beach", away=True),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Invalid user ID should fail
|
||||||
|
result = self.client_get("/json/users/12345/status")
|
||||||
|
self.assert_json_error(result, "No such user")
|
||||||
|
|
||||||
|
# Test status if the status has not been set
|
||||||
|
iago = self.example_user("iago")
|
||||||
|
result = self.client_get(f"/json/users/{iago.id}/status")
|
||||||
|
result_dict = self.assert_json_success(result)
|
||||||
|
self.assertEqual(
|
||||||
|
result_dict["status"],
|
||||||
|
{},
|
||||||
|
)
|
||||||
|
|
|
@ -18,7 +18,8 @@ from zerver.lib.request import RequestNotes
|
||||||
from zerver.lib.response import json_success
|
from zerver.lib.response import json_success
|
||||||
from zerver.lib.timestamp import datetime_to_timestamp
|
from zerver.lib.timestamp import datetime_to_timestamp
|
||||||
from zerver.lib.typed_endpoint import ApiParamConfig, typed_endpoint
|
from zerver.lib.typed_endpoint import ApiParamConfig, typed_endpoint
|
||||||
from zerver.lib.users import check_can_access_user
|
from zerver.lib.user_status import get_user_status
|
||||||
|
from zerver.lib.users import access_user_by_id, check_can_access_user
|
||||||
from zerver.models import UserActivity, UserPresence, UserProfile, UserStatus
|
from zerver.models import UserActivity, UserPresence, UserProfile, UserStatus
|
||||||
from zerver.models.users import get_active_user, get_active_user_profile_by_id_in_realm
|
from zerver.models.users import get_active_user, get_active_user_profile_by_id_in_realm
|
||||||
|
|
||||||
|
@ -66,6 +67,13 @@ def get_presence_backend(
|
||||||
return json_success(request, data=result)
|
return json_success(request, data=result)
|
||||||
|
|
||||||
|
|
||||||
|
def get_status_backend(
|
||||||
|
request: HttpRequest, user_profile: UserProfile, user_id: int
|
||||||
|
) -> HttpResponse:
|
||||||
|
target_user = access_user_by_id(user_profile, user_id, for_admin=False)
|
||||||
|
return json_success(request, data={"status": get_user_status(target_user)})
|
||||||
|
|
||||||
|
|
||||||
@human_users_only
|
@human_users_only
|
||||||
@typed_endpoint
|
@typed_endpoint
|
||||||
def update_user_status_backend(
|
def update_user_status_backend(
|
||||||
|
|
|
@ -89,6 +89,7 @@ from zerver.views.muted_users import mute_user, unmute_user
|
||||||
from zerver.views.onboarding_steps import mark_onboarding_step_as_read
|
from zerver.views.onboarding_steps import mark_onboarding_step_as_read
|
||||||
from zerver.views.presence import (
|
from zerver.views.presence import (
|
||||||
get_presence_backend,
|
get_presence_backend,
|
||||||
|
get_status_backend,
|
||||||
get_statuses_for_realm,
|
get_statuses_for_realm,
|
||||||
update_active_status_backend,
|
update_active_status_backend,
|
||||||
update_user_status_backend,
|
update_user_status_backend,
|
||||||
|
@ -396,6 +397,7 @@ v1_api_and_json_patterns = [
|
||||||
rest_path("users/<user_id_or_email>/presence", GET=get_presence_backend),
|
rest_path("users/<user_id_or_email>/presence", GET=get_presence_backend),
|
||||||
rest_path("realm/presence", GET=get_statuses_for_realm),
|
rest_path("realm/presence", GET=get_statuses_for_realm),
|
||||||
rest_path("users/me/status", POST=update_user_status_backend),
|
rest_path("users/me/status", POST=update_user_status_backend),
|
||||||
|
rest_path("users/<int:user_id>/status", GET=get_status_backend),
|
||||||
# user_groups -> zerver.views.user_groups
|
# user_groups -> zerver.views.user_groups
|
||||||
rest_path("user_groups", GET=get_user_group),
|
rest_path("user_groups", GET=get_user_group),
|
||||||
rest_path("user_groups/create", POST=add_user_group),
|
rest_path("user_groups/create", POST=add_user_group),
|
||||||
|
|
Loading…
Reference in New Issue