Move call invite filtering logic to filter_events_for_client (#17782)
This commit is contained in:
1
changelog.d/17782.misc
Normal file
1
changelog.d/17782.misc
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Improve event filtering for Simplified Sliding Sync.
|
||||||
@@ -761,8 +761,6 @@ class SlidingSyncHandler:
|
|||||||
!= Membership.JOIN,
|
!= Membership.JOIN,
|
||||||
filter_send_to_client=True,
|
filter_send_to_client=True,
|
||||||
)
|
)
|
||||||
# TODO: Filter out `EventTypes.CallInvite` in public rooms,
|
|
||||||
# see https://github.com/element-hq/synapse/issues/17359
|
|
||||||
|
|
||||||
# TODO: Handle timeline gaps (`get_timeline_gaps()`)
|
# TODO: Handle timeline gaps (`get_timeline_gaps()`)
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ from synapse.api.constants import (
|
|||||||
Direction,
|
Direction,
|
||||||
EventContentFields,
|
EventContentFields,
|
||||||
EventTypes,
|
EventTypes,
|
||||||
JoinRules,
|
|
||||||
Membership,
|
Membership,
|
||||||
)
|
)
|
||||||
from synapse.api.filtering import FilterCollection
|
from synapse.api.filtering import FilterCollection
|
||||||
@@ -790,22 +789,13 @@ class SyncHandler:
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
filtered_recents = await filter_events_for_client(
|
loaded_recents = await filter_events_for_client(
|
||||||
self._storage_controllers,
|
self._storage_controllers,
|
||||||
sync_config.user.to_string(),
|
sync_config.user.to_string(),
|
||||||
loaded_recents,
|
loaded_recents,
|
||||||
always_include_ids=current_state_ids,
|
always_include_ids=current_state_ids,
|
||||||
)
|
)
|
||||||
|
|
||||||
loaded_recents = []
|
|
||||||
for event in filtered_recents:
|
|
||||||
if event.type == EventTypes.CallInvite:
|
|
||||||
room_info = await self.store.get_room_with_stats(event.room_id)
|
|
||||||
assert room_info is not None
|
|
||||||
if room_info.join_rules == JoinRules.PUBLIC:
|
|
||||||
continue
|
|
||||||
loaded_recents.append(event)
|
|
||||||
|
|
||||||
log_kv({"loaded_recents_after_client_filtering": len(loaded_recents)})
|
log_kv({"loaded_recents_after_client_filtering": len(loaded_recents)})
|
||||||
|
|
||||||
loaded_recents.extend(recents)
|
loaded_recents.extend(recents)
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ from synapse.api.constants import (
|
|||||||
EventTypes,
|
EventTypes,
|
||||||
EventUnsignedContentFields,
|
EventUnsignedContentFields,
|
||||||
HistoryVisibility,
|
HistoryVisibility,
|
||||||
|
JoinRules,
|
||||||
Membership,
|
Membership,
|
||||||
)
|
)
|
||||||
from synapse.events import EventBase
|
from synapse.events import EventBase
|
||||||
@@ -111,7 +112,17 @@ async def filter_events_for_client(
|
|||||||
# happen within the function.
|
# happen within the function.
|
||||||
events_before_filtering = events.copy()
|
events_before_filtering = events.copy()
|
||||||
# Default case is to *exclude* soft-failed events
|
# Default case is to *exclude* soft-failed events
|
||||||
events = [e for e in events if not e.internal_metadata.is_soft_failed()]
|
events = []
|
||||||
|
found_call_invite = False
|
||||||
|
for event in events_before_filtering:
|
||||||
|
if event.internal_metadata.is_soft_failed():
|
||||||
|
continue
|
||||||
|
|
||||||
|
if event.type == EventTypes.CallInvite and not event.is_state():
|
||||||
|
found_call_invite = True
|
||||||
|
|
||||||
|
events.append(event)
|
||||||
|
|
||||||
client_config = await storage.main.get_admin_client_config_for_user(user_id)
|
client_config = await storage.main.get_admin_client_config_for_user(user_id)
|
||||||
if filter_send_to_client and await storage.main.is_server_admin(user_id):
|
if filter_send_to_client and await storage.main.is_server_admin(user_id):
|
||||||
if client_config.return_soft_failed_events:
|
if client_config.return_soft_failed_events:
|
||||||
@@ -139,7 +150,11 @@ async def filter_events_for_client(
|
|||||||
[event.event_id for event in events],
|
[event.event_id for event in events],
|
||||||
)
|
)
|
||||||
|
|
||||||
types = (_HISTORY_VIS_KEY, (EventTypes.Member, user_id))
|
types = [_HISTORY_VIS_KEY, (EventTypes.Member, user_id)]
|
||||||
|
if found_call_invite:
|
||||||
|
# We need to fetch the room's join rules state to determine
|
||||||
|
# whether to allow call invites in public rooms.
|
||||||
|
types.append((EventTypes.JoinRules, ""))
|
||||||
|
|
||||||
# we exclude outliers at this point, and then handle them separately later
|
# we exclude outliers at this point, and then handle them separately later
|
||||||
event_id_to_state = await storage.state.get_state_for_events(
|
event_id_to_state = await storage.state.get_state_for_events(
|
||||||
@@ -178,6 +193,25 @@ async def filter_events_for_client(
|
|||||||
if filtered is None:
|
if filtered is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
# Filter out call invites in public rooms, as this would potentially
|
||||||
|
# ring a lot of users.
|
||||||
|
if event.type == EventTypes.CallInvite and not event.is_state():
|
||||||
|
# `state_after_event` should only be None if the event is an outlier,
|
||||||
|
# and earlier code should filter out outliers entirely.
|
||||||
|
#
|
||||||
|
# In addition, we only create outliers locally for out-of-band
|
||||||
|
# invite rejections, invites received over federation, or state
|
||||||
|
# events needed to authorise other events. None of this applies to
|
||||||
|
# call invites.
|
||||||
|
assert state_after_event is not None
|
||||||
|
|
||||||
|
room_join_rules = state_after_event.get((EventTypes.JoinRules, ""))
|
||||||
|
if (
|
||||||
|
room_join_rules is not None
|
||||||
|
and room_join_rules.content.get("join_rule") == JoinRules.PUBLIC
|
||||||
|
):
|
||||||
|
return None
|
||||||
|
|
||||||
# Annotate the event with the user's membership after the event.
|
# Annotate the event with the user's membership after the event.
|
||||||
#
|
#
|
||||||
# Normally we just look in `state_after_event`, but if the event is an outlier
|
# Normally we just look in `state_after_event`, but if the event is an outlier
|
||||||
|
|||||||
Reference in New Issue
Block a user