Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/17782.misc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Improve event filtering for Simplified Sliding Sync.
2 changes: 0 additions & 2 deletions synapse/handlers/sliding_sync/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -761,8 +761,6 @@ async def get_room_sync_data(
!= Membership.JOIN,
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()`)

Expand Down
12 changes: 1 addition & 11 deletions synapse/handlers/sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
Direction,
EventContentFields,
EventTypes,
JoinRules,
Membership,
)
from synapse.api.filtering import FilterCollection
Expand Down Expand Up @@ -790,22 +789,13 @@ async def _load_filtered_recents(
)
)

filtered_recents = await filter_events_for_client(
loaded_recents = await filter_events_for_client(
self._storage_controllers,
sync_config.user.to_string(),
loaded_recents,
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)})

loaded_recents.extend(recents)
Expand Down
36 changes: 34 additions & 2 deletions synapse/visibility.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
EventTypes,
EventUnsignedContentFields,
HistoryVisibility,
JoinRules,
Membership,
)
from synapse.events import EventBase
Expand Down Expand Up @@ -111,7 +112,17 @@ async def filter_events_for_client(
# happen within the function.
events_before_filtering = events.copy()
# 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)
if filter_send_to_client and await storage.main.is_server_admin(user_id):
if client_config.return_soft_failed_events:
Expand Down Expand Up @@ -139,7 +150,11 @@ async def filter_events_for_client(
[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
event_id_to_state = await storage.state.get_state_for_events(
Expand Down Expand Up @@ -178,6 +193,23 @@ def allowed(event: EventBase) -> EventBase | None:
if filtered is 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 call invites should not be outliers.
assert state_after_event is not None
Comment on lines +199 to +206
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs a comment why

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dug into this more and updated the comment with some more reassurances in cf78c05.


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
Comment thread
MadLittleMods marked this conversation as resolved.

# 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
Expand Down
Loading