events: Add "user_settings_object" to client_capabilities.

This commit adds "user_settings_object" field to
client_capabilities which will be used to determine
if the client needs 'update_display_settings' and
'update_global_notifications' event.
This commit is contained in:
Sahil Batra 2021-07-24 23:21:25 +05:30 committed by Tim Abbott
parent 7959ae3fab
commit 0364d0c8ca
9 changed files with 70 additions and 2 deletions

View File

@ -17,6 +17,12 @@ below features are supported.
`user_settings`. The previous `update_display_settings` and
`update_global_notifications` event types are still supported
for backwards compatibility, but will be removed in future.
* [`POST /register`](/api/register-queue): Added the new
`user_settings_object` property to supported `client_capabilities`.
* [`GET /events`](/api/get-events): `update_display_settings` and
`update_global_notifications` are sent only when `user_settings_object`
is not included in the `client_capabilities` when registering the
event queue.
**Feature level 88**

View File

@ -1217,6 +1217,7 @@ def do_events_register(
"user_avatar_url_field_optional", False
)
stream_typing_notifications = client_capabilities.get("stream_typing_notifications", False)
user_settings_object = client_capabilities.get("user_settings_object", False)
if user_profile.realm.email_address_visibility != Realm.EMAIL_ADDRESS_VISIBILITY_EVERYONE:
# If real email addresses are not available to the user, their
@ -1248,6 +1249,7 @@ def do_events_register(
narrow=narrow,
bulk_message_deletion=bulk_message_deletion,
stream_typing_notifications=stream_typing_notifications,
user_settings_object=user_settings_object,
)
if queue_id is None:

View File

@ -135,6 +135,7 @@ def build_page_params_for_home_page_load(
"bulk_message_deletion": True,
"user_avatar_url_field_optional": True,
"stream_typing_notifications": False, # Set this to True when frontend support is implemented.
"user_settings_object": False, # Set this to True when frontend support is implemented.
}
if user_profile is not None:

View File

@ -242,7 +242,9 @@ paths:
- type: object
description: |
Event sent to a user's clients when that user's display settings
have changed.
have changed with an additional rule that it is only sent to
clients that did not include `user_settings_object` in their
`client_capabilities` when registering the event queue.
**Changes**: Deprecated in Zulip 5.0 (feature level 89), replaced by
the `user_settings` event type.
@ -283,7 +285,10 @@ paths:
- type: object
description: |
Event sent to a user's clients when that user's [notification
settings](/api/update-settings) have changed.
settings](/api/update-settings) have changed with an additional
rule that it is only sent to clients that did not include
`user_settings_object` in their `client_capabilities` when
registering the event queue.
**Changes**: Deprecated in Zulip 5.0 (feature level 89), replaced by
the `user_settings` event type.
@ -8260,6 +8265,14 @@ paths:
New in Zulip 4.0 (feature level 58). This capability is
for backwards-compatibility; it will be required in a
future server release.
* `user_settings_object`: Boolean for whether the client supports the modern
`user_settings` event type. If False, the server will additionally send the
legacy `update_display_settings` and `update_global_notifications` event
types for backwards-compatibility with clients that predate this API migration.
New in Zulip 4.0 (feature level 89). This capability is for
backwards-compatibility; it will be removed in a future server release.
content:
application/json:
schema:

View File

@ -241,6 +241,7 @@ class BaseAction(ZulipTestCase):
num_events: int = 1,
bulk_message_deletion: bool = True,
stream_typing_notifications: bool = True,
user_settings_object: bool = False,
) -> List[Dict[str, Any]]:
"""
Make sure we have a clean slate of client descriptors for these tests.
@ -267,6 +268,7 @@ class BaseAction(ZulipTestCase):
narrow=[],
bulk_message_deletion=bulk_message_deletion,
stream_typing_notifications=stream_typing_notifications,
user_settings_object=user_settings_object,
)
)
@ -2057,6 +2059,31 @@ class NormalActionsTest(BaseAction):
with self.assertRaises(RestartEventException):
self.verify_action(lambda: send_restart_events(immediate=True))
def test_display_setting_event_not_sent(self) -> None:
events = self.verify_action(
lambda: do_set_user_display_setting(
self.user_profile,
"default_view",
"all_messages",
),
state_change_expected=True,
user_settings_object=True,
)
check_user_settings_update("events[0]", events[0])
def test_notification_setting_event_not_sent(self) -> None:
events = self.verify_action(
lambda: do_change_notification_settings(
self.user_profile,
"enable_sounds",
False,
acting_user=self.user_profile,
),
state_change_expected=True,
user_settings_object=True,
)
check_user_settings_update("events[0]", events[0])
class RealmPropertyActionTest(BaseAction):
def do_set_realm_property_test(self, name: str) -> None:

View File

@ -75,6 +75,7 @@ def request_event_queue(
narrow: Iterable[Sequence[str]] = [],
bulk_message_deletion: bool = False,
stream_typing_notifications: bool = False,
user_settings_object: bool = False,
) -> Optional[str]:
if not settings.USING_TORNADO:
@ -95,6 +96,7 @@ def request_event_queue(
"lifespan_secs": queue_lifespan_secs,
"bulk_message_deletion": orjson.dumps(bulk_message_deletion),
"stream_typing_notifications": orjson.dumps(stream_typing_notifications),
"user_settings_object": orjson.dumps(user_settings_object),
}
if event_types is not None:

View File

@ -95,6 +95,7 @@ class ClientDescriptor:
narrow: Collection[Sequence[str]] = [],
bulk_message_deletion: bool = False,
stream_typing_notifications: bool = False,
user_settings_object: bool = False,
) -> None:
# These objects are serialized on shutdown and restored on restart.
# If fields are added or semantics are changed, temporary code must be
@ -117,6 +118,7 @@ class ClientDescriptor:
self.narrow_filter = build_narrow_filter(narrow)
self.bulk_message_deletion = bulk_message_deletion
self.stream_typing_notifications = stream_typing_notifications
self.user_settings_object = user_settings_object
# Default for lifespan_secs is DEFAULT_EVENT_QUEUE_TIMEOUT_SECS;
# but users can set it as high as MAX_QUEUE_TIMEOUT_SECS.
@ -143,6 +145,7 @@ class ClientDescriptor:
client_type_name=self.client_type_name,
bulk_message_deletion=self.bulk_message_deletion,
stream_typing_notifications=self.stream_typing_notifications,
user_settings_object=self.user_settings_object,
)
def __repr__(self) -> str:
@ -174,6 +177,7 @@ class ClientDescriptor:
d.get("narrow", []),
d.get("bulk_message_deletion", False),
d.get("stream_typing_notifications", False),
d.get("user_settings_object", False),
)
ret.last_connection_time = d["last_connection_time"]
return ret
@ -217,6 +221,14 @@ class ClientDescriptor:
# delivered if the stream_typing_notifications
# client_capability is enabled, for backwards compatibility.
return self.stream_typing_notifications
if self.user_settings_object and event["type"] in [
"update_display_settings",
"update_global_notifications",
]:
# 'update_display_settings' and 'update_global_notifications'
# events are sent only if user_settings_object is False,
# otherwise only 'user_settings' event is sent.
return False
return True
# TODO: Refactor so we don't need this function

View File

@ -103,6 +103,9 @@ def get_events_backend(
stream_typing_notifications: bool = REQ(
default=False, json_validator=check_bool, intentionally_undocumented=True
),
user_settings_object: bool = REQ(
default=False, json_validator=check_bool, intentionally_undocumented=True
),
) -> HttpResponse:
if all_public_streams and not user_profile.can_access_public_streams():
raise JsonableError(_("User not authorized for this query"))
@ -147,6 +150,7 @@ def get_events_backend(
narrow=narrow,
bulk_message_deletion=bulk_message_deletion,
stream_typing_notifications=stream_typing_notifications,
user_settings_object=user_settings_object,
)
result = fetch_events(events_query)

View File

@ -54,6 +54,7 @@ def events_register_backend(
("bulk_message_deletion", check_bool),
("user_avatar_url_field_optional", check_bool),
("stream_typing_notifications", check_bool),
("user_settings_object", check_bool),
],
value_validator=check_bool,
),