Filter based on state at to_token

This commit is contained in:
Eric Eastwood 2024-06-10 14:33:04 -05:00
parent 578b44af4c
commit 7dec9307dc
2 changed files with 38 additions and 23 deletions

View file

@ -35,6 +35,7 @@ from synapse.api.constants import AccountDataTypes, EventTypes, Membership
from synapse.events import EventBase
from synapse.rest.client.models import SlidingSyncBody
from synapse.types import JsonMapping, Requester, RoomStreamToken, StreamToken, UserID
from synapse.types.state import StateFilter
if TYPE_CHECKING:
from synapse.server import HomeServer
@ -340,7 +341,7 @@ class SlidingSyncHandler:
# from/to tokens but some of the streams don't support looking back
# in time (like global account_data).
filtered_room_ids = await self.filter_rooms(
sync_config.user, room_id_set, list_config.filters
sync_config.user, room_id_set, list_config.filters, to_token
)
# TODO: Apply sorts
sorted_room_ids = sorted(filtered_room_ids)
@ -619,9 +620,15 @@ class SlidingSyncHandler:
user: UserID,
room_id_set: AbstractSet[str],
filters: SlidingSyncConfig.SlidingSyncList.Filters,
to_token: StreamToken,
) -> AbstractSet[str]:
"""
Filter rooms based on the sync request.
Args:
user:
room_id_set: The set of room IDs to filter down
filters: The filters to apply
"""
user_id = user.to_string()
@ -664,15 +671,18 @@ class SlidingSyncHandler:
# Filter for encrypted rooms
if filters.is_encrypted is not None:
# Make a copy so we don't run into an error: `Set changed size during iteration`
# Make a copy so we don't run into an error: `Set changed size during
# iteration`, when we filter out and remove items
for room_id in list(filtered_room_id_set):
# TODO: Is there a good method to look up all rooms at once? (N+1 query problem)
is_encrypted = (
# TODO: Get state at the `to_token` instead of the current state
await self.storage_controllers.state.get_current_state_event(
room_id, EventTypes.RoomEncryption, ""
)
state_at_to_token = await self.storage_controllers.state.get_state_at(
room_id,
to_token,
state_filter=StateFilter.from_types(
[(EventTypes.RoomEncryption, "")]
),
)
is_encrypted = state_at_to_token.get((EventTypes.RoomEncryption, ""))
# If we're looking for encrypted rooms, filter out rooms that are not
# encrypted and vice versa

View file

@ -1140,6 +1140,7 @@ class FilterRoomsTestCase(HomeserverTestCase):
def prepare(self, reactor: MemoryReactor, clock: Clock, hs: HomeServer) -> None:
self.sliding_sync_handler = self.hs.get_sliding_sync_handler()
self.store = self.hs.get_datastores().main
self.event_sources = hs.get_event_sources()
def _create_dm_room(
self,
@ -1213,6 +1214,8 @@ class FilterRoomsTestCase(HomeserverTestCase):
invitee_tok=user2_tok,
)
after_rooms_token = self.event_sources.get_current_token()
# TODO: Better way to avoid the circular import? (see
# https://github.com/element-hq/synapse/pull/17187#discussion_r1619492779)
from synapse.handlers.sliding_sync import SlidingSyncConfig
@ -1226,7 +1229,10 @@ class FilterRoomsTestCase(HomeserverTestCase):
# Filter the rooms
truthy_filtered_room_ids = self.get_success(
self.sliding_sync_handler.filter_rooms(
UserID.from_string(user1_id), {room_id, dm_room_id}, truthy_filters
UserID.from_string(user1_id),
{room_id, dm_room_id},
truthy_filters,
after_rooms_token,
)
)
@ -1241,7 +1247,10 @@ class FilterRoomsTestCase(HomeserverTestCase):
# Filter the rooms
falsy_filtered_room_ids = self.get_success(
self.sliding_sync_handler.filter_rooms(
UserID.from_string(user1_id), {room_id, dm_room_id}, falsy_filters
UserID.from_string(user1_id),
{room_id, dm_room_id},
falsy_filters,
after_rooms_token,
)
)
@ -1274,39 +1283,35 @@ class FilterRoomsTestCase(HomeserverTestCase):
tok=user1_tok,
)
after_rooms_token = self.event_sources.get_current_token()
# TODO: Better way to avoid the circular import? (see
# https://github.com/element-hq/synapse/pull/17187#discussion_r1619492779)
from synapse.handlers.sliding_sync import SlidingSyncConfig
# Try with `is_encrypted=True`
# -----------------------------
truthy_filters = SlidingSyncConfig.SlidingSyncList.Filters(
is_encrypted=True,
)
# Filter the rooms
truthy_filtered_room_ids = self.get_success(
self.sliding_sync_handler.filter_rooms(
UserID.from_string(user1_id),
{room_id, encrypted_room_id},
truthy_filters,
SlidingSyncConfig.SlidingSyncList.Filters(
is_encrypted=True,
),
after_rooms_token,
)
)
self.assertEqual(truthy_filtered_room_ids, {encrypted_room_id})
# Try with `is_encrypted=False`
# -----------------------------
falsy_filters = SlidingSyncConfig.SlidingSyncList.Filters(
is_encrypted=False,
)
# Filter the rooms
falsy_filtered_room_ids = self.get_success(
self.sliding_sync_handler.filter_rooms(
UserID.from_string(user1_id),
{room_id, encrypted_room_id},
falsy_filters,
SlidingSyncConfig.SlidingSyncList.Filters(
is_encrypted=False,
),
after_rooms_token,
)
)