mirror of https://github.com/zulip/zulip.git
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:
parent
7959ae3fab
commit
0364d0c8ca
|
@ -17,6 +17,12 @@ below features are supported.
|
||||||
`user_settings`. The previous `update_display_settings` and
|
`user_settings`. The previous `update_display_settings` and
|
||||||
`update_global_notifications` event types are still supported
|
`update_global_notifications` event types are still supported
|
||||||
for backwards compatibility, but will be removed in future.
|
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**
|
**Feature level 88**
|
||||||
|
|
||||||
|
|
|
@ -1217,6 +1217,7 @@ def do_events_register(
|
||||||
"user_avatar_url_field_optional", False
|
"user_avatar_url_field_optional", False
|
||||||
)
|
)
|
||||||
stream_typing_notifications = client_capabilities.get("stream_typing_notifications", 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 user_profile.realm.email_address_visibility != Realm.EMAIL_ADDRESS_VISIBILITY_EVERYONE:
|
||||||
# If real email addresses are not available to the user, their
|
# If real email addresses are not available to the user, their
|
||||||
|
@ -1248,6 +1249,7 @@ def do_events_register(
|
||||||
narrow=narrow,
|
narrow=narrow,
|
||||||
bulk_message_deletion=bulk_message_deletion,
|
bulk_message_deletion=bulk_message_deletion,
|
||||||
stream_typing_notifications=stream_typing_notifications,
|
stream_typing_notifications=stream_typing_notifications,
|
||||||
|
user_settings_object=user_settings_object,
|
||||||
)
|
)
|
||||||
|
|
||||||
if queue_id is None:
|
if queue_id is None:
|
||||||
|
|
|
@ -135,6 +135,7 @@ def build_page_params_for_home_page_load(
|
||||||
"bulk_message_deletion": True,
|
"bulk_message_deletion": True,
|
||||||
"user_avatar_url_field_optional": True,
|
"user_avatar_url_field_optional": True,
|
||||||
"stream_typing_notifications": False, # Set this to True when frontend support is implemented.
|
"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:
|
if user_profile is not None:
|
||||||
|
|
|
@ -242,7 +242,9 @@ paths:
|
||||||
- type: object
|
- type: object
|
||||||
description: |
|
description: |
|
||||||
Event sent to a user's clients when that user's display settings
|
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
|
**Changes**: Deprecated in Zulip 5.0 (feature level 89), replaced by
|
||||||
the `user_settings` event type.
|
the `user_settings` event type.
|
||||||
|
@ -283,7 +285,10 @@ paths:
|
||||||
- type: object
|
- type: object
|
||||||
description: |
|
description: |
|
||||||
Event sent to a user's clients when that user's [notification
|
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
|
**Changes**: Deprecated in Zulip 5.0 (feature level 89), replaced by
|
||||||
the `user_settings` event type.
|
the `user_settings` event type.
|
||||||
|
@ -8260,6 +8265,14 @@ paths:
|
||||||
New in Zulip 4.0 (feature level 58). This capability is
|
New in Zulip 4.0 (feature level 58). This capability is
|
||||||
for backwards-compatibility; it will be required in a
|
for backwards-compatibility; it will be required in a
|
||||||
future server release.
|
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:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
|
|
|
@ -241,6 +241,7 @@ class BaseAction(ZulipTestCase):
|
||||||
num_events: int = 1,
|
num_events: int = 1,
|
||||||
bulk_message_deletion: bool = True,
|
bulk_message_deletion: bool = True,
|
||||||
stream_typing_notifications: bool = True,
|
stream_typing_notifications: bool = True,
|
||||||
|
user_settings_object: bool = False,
|
||||||
) -> List[Dict[str, Any]]:
|
) -> List[Dict[str, Any]]:
|
||||||
"""
|
"""
|
||||||
Make sure we have a clean slate of client descriptors for these tests.
|
Make sure we have a clean slate of client descriptors for these tests.
|
||||||
|
@ -267,6 +268,7 @@ class BaseAction(ZulipTestCase):
|
||||||
narrow=[],
|
narrow=[],
|
||||||
bulk_message_deletion=bulk_message_deletion,
|
bulk_message_deletion=bulk_message_deletion,
|
||||||
stream_typing_notifications=stream_typing_notifications,
|
stream_typing_notifications=stream_typing_notifications,
|
||||||
|
user_settings_object=user_settings_object,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -2057,6 +2059,31 @@ class NormalActionsTest(BaseAction):
|
||||||
with self.assertRaises(RestartEventException):
|
with self.assertRaises(RestartEventException):
|
||||||
self.verify_action(lambda: send_restart_events(immediate=True))
|
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):
|
class RealmPropertyActionTest(BaseAction):
|
||||||
def do_set_realm_property_test(self, name: str) -> None:
|
def do_set_realm_property_test(self, name: str) -> None:
|
||||||
|
|
|
@ -75,6 +75,7 @@ def request_event_queue(
|
||||||
narrow: Iterable[Sequence[str]] = [],
|
narrow: Iterable[Sequence[str]] = [],
|
||||||
bulk_message_deletion: bool = False,
|
bulk_message_deletion: bool = False,
|
||||||
stream_typing_notifications: bool = False,
|
stream_typing_notifications: bool = False,
|
||||||
|
user_settings_object: bool = False,
|
||||||
) -> Optional[str]:
|
) -> Optional[str]:
|
||||||
|
|
||||||
if not settings.USING_TORNADO:
|
if not settings.USING_TORNADO:
|
||||||
|
@ -95,6 +96,7 @@ def request_event_queue(
|
||||||
"lifespan_secs": queue_lifespan_secs,
|
"lifespan_secs": queue_lifespan_secs,
|
||||||
"bulk_message_deletion": orjson.dumps(bulk_message_deletion),
|
"bulk_message_deletion": orjson.dumps(bulk_message_deletion),
|
||||||
"stream_typing_notifications": orjson.dumps(stream_typing_notifications),
|
"stream_typing_notifications": orjson.dumps(stream_typing_notifications),
|
||||||
|
"user_settings_object": orjson.dumps(user_settings_object),
|
||||||
}
|
}
|
||||||
|
|
||||||
if event_types is not None:
|
if event_types is not None:
|
||||||
|
|
|
@ -95,6 +95,7 @@ class ClientDescriptor:
|
||||||
narrow: Collection[Sequence[str]] = [],
|
narrow: Collection[Sequence[str]] = [],
|
||||||
bulk_message_deletion: bool = False,
|
bulk_message_deletion: bool = False,
|
||||||
stream_typing_notifications: bool = False,
|
stream_typing_notifications: bool = False,
|
||||||
|
user_settings_object: bool = False,
|
||||||
) -> None:
|
) -> None:
|
||||||
# These objects are serialized on shutdown and restored on restart.
|
# These objects are serialized on shutdown and restored on restart.
|
||||||
# If fields are added or semantics are changed, temporary code must be
|
# 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.narrow_filter = build_narrow_filter(narrow)
|
||||||
self.bulk_message_deletion = bulk_message_deletion
|
self.bulk_message_deletion = bulk_message_deletion
|
||||||
self.stream_typing_notifications = stream_typing_notifications
|
self.stream_typing_notifications = stream_typing_notifications
|
||||||
|
self.user_settings_object = user_settings_object
|
||||||
|
|
||||||
# Default for lifespan_secs is DEFAULT_EVENT_QUEUE_TIMEOUT_SECS;
|
# Default for lifespan_secs is DEFAULT_EVENT_QUEUE_TIMEOUT_SECS;
|
||||||
# but users can set it as high as MAX_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,
|
client_type_name=self.client_type_name,
|
||||||
bulk_message_deletion=self.bulk_message_deletion,
|
bulk_message_deletion=self.bulk_message_deletion,
|
||||||
stream_typing_notifications=self.stream_typing_notifications,
|
stream_typing_notifications=self.stream_typing_notifications,
|
||||||
|
user_settings_object=self.user_settings_object,
|
||||||
)
|
)
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
|
@ -174,6 +177,7 @@ class ClientDescriptor:
|
||||||
d.get("narrow", []),
|
d.get("narrow", []),
|
||||||
d.get("bulk_message_deletion", False),
|
d.get("bulk_message_deletion", False),
|
||||||
d.get("stream_typing_notifications", False),
|
d.get("stream_typing_notifications", False),
|
||||||
|
d.get("user_settings_object", False),
|
||||||
)
|
)
|
||||||
ret.last_connection_time = d["last_connection_time"]
|
ret.last_connection_time = d["last_connection_time"]
|
||||||
return ret
|
return ret
|
||||||
|
@ -217,6 +221,14 @@ class ClientDescriptor:
|
||||||
# delivered if the stream_typing_notifications
|
# delivered if the stream_typing_notifications
|
||||||
# client_capability is enabled, for backwards compatibility.
|
# client_capability is enabled, for backwards compatibility.
|
||||||
return self.stream_typing_notifications
|
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
|
return True
|
||||||
|
|
||||||
# TODO: Refactor so we don't need this function
|
# TODO: Refactor so we don't need this function
|
||||||
|
|
|
@ -103,6 +103,9 @@ def get_events_backend(
|
||||||
stream_typing_notifications: bool = REQ(
|
stream_typing_notifications: bool = REQ(
|
||||||
default=False, json_validator=check_bool, intentionally_undocumented=True
|
default=False, json_validator=check_bool, intentionally_undocumented=True
|
||||||
),
|
),
|
||||||
|
user_settings_object: bool = REQ(
|
||||||
|
default=False, json_validator=check_bool, intentionally_undocumented=True
|
||||||
|
),
|
||||||
) -> HttpResponse:
|
) -> HttpResponse:
|
||||||
if all_public_streams and not user_profile.can_access_public_streams():
|
if all_public_streams and not user_profile.can_access_public_streams():
|
||||||
raise JsonableError(_("User not authorized for this query"))
|
raise JsonableError(_("User not authorized for this query"))
|
||||||
|
@ -147,6 +150,7 @@ def get_events_backend(
|
||||||
narrow=narrow,
|
narrow=narrow,
|
||||||
bulk_message_deletion=bulk_message_deletion,
|
bulk_message_deletion=bulk_message_deletion,
|
||||||
stream_typing_notifications=stream_typing_notifications,
|
stream_typing_notifications=stream_typing_notifications,
|
||||||
|
user_settings_object=user_settings_object,
|
||||||
)
|
)
|
||||||
|
|
||||||
result = fetch_events(events_query)
|
result = fetch_events(events_query)
|
||||||
|
|
|
@ -54,6 +54,7 @@ def events_register_backend(
|
||||||
("bulk_message_deletion", check_bool),
|
("bulk_message_deletion", check_bool),
|
||||||
("user_avatar_url_field_optional", check_bool),
|
("user_avatar_url_field_optional", check_bool),
|
||||||
("stream_typing_notifications", check_bool),
|
("stream_typing_notifications", check_bool),
|
||||||
|
("user_settings_object", check_bool),
|
||||||
],
|
],
|
||||||
value_validator=check_bool,
|
value_validator=check_bool,
|
||||||
),
|
),
|
||||||
|
|
Loading…
Reference in New Issue