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.events import EventBase
from synapse.rest.client.models import SlidingSyncBody from synapse.rest.client.models import SlidingSyncBody
from synapse.types import JsonMapping, Requester, RoomStreamToken, StreamToken, UserID from synapse.types import JsonMapping, Requester, RoomStreamToken, StreamToken, UserID
from synapse.types.state import StateFilter
if TYPE_CHECKING: if TYPE_CHECKING:
from synapse.server import HomeServer from synapse.server import HomeServer
@ -340,7 +341,7 @@ class SlidingSyncHandler:
# from/to tokens but some of the streams don't support looking back # from/to tokens but some of the streams don't support looking back
# in time (like global account_data). # in time (like global account_data).
filtered_room_ids = await self.filter_rooms( 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 # TODO: Apply sorts
sorted_room_ids = sorted(filtered_room_ids) sorted_room_ids = sorted(filtered_room_ids)
@ -619,9 +620,15 @@ class SlidingSyncHandler:
user: UserID, user: UserID,
room_id_set: AbstractSet[str], room_id_set: AbstractSet[str],
filters: SlidingSyncConfig.SlidingSyncList.Filters, filters: SlidingSyncConfig.SlidingSyncList.Filters,
to_token: StreamToken,
) -> AbstractSet[str]: ) -> AbstractSet[str]:
""" """
Filter rooms based on the sync request. 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() user_id = user.to_string()
@ -664,15 +671,18 @@ class SlidingSyncHandler:
# Filter for encrypted rooms # Filter for encrypted rooms
if filters.is_encrypted is not None: 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): 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) # TODO: Is there a good method to look up all rooms at once? (N+1 query problem)
is_encrypted = ( state_at_to_token = await self.storage_controllers.state.get_state_at(
# TODO: Get state at the `to_token` instead of the current state room_id,
await self.storage_controllers.state.get_current_state_event( to_token,
room_id, EventTypes.RoomEncryption, "" 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 # If we're looking for encrypted rooms, filter out rooms that are not
# encrypted and vice versa # encrypted and vice versa

View file

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