Add is_encrypted filtering to Sliding Sync /sync

Based on [MSC3575](https://github.com/matrix-org/matrix-spec-proposals/pull/3575): Sliding Sync
This commit is contained in:
Eric Eastwood 2024-05-30 16:34:48 -05:00
parent 813cda92df
commit 44deafca7a
2 changed files with 95 additions and 39 deletions

View file

@ -11,7 +11,7 @@ if TYPE_CHECKING or HAS_PYDANTIC_V2:
else:
from pydantic import Extra
from synapse.api.constants import AccountDataTypes, Membership
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
@ -576,8 +576,23 @@ class SlidingSyncHandler:
space_child_room_ids
)
if filters.is_encrypted:
raise NotImplementedError()
# 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`
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 = (
await self.storage_controllers.state.get_current_state_event(
room_id, EventTypes.RoomEncryption, ""
)
)
# If we're looking for encrypted rooms, filter out rooms that are not
# encrypted and vice versa
if (filters.is_encrypted and not is_encrypted) or (
not filters.is_encrypted and is_encrypted
):
filtered_room_id_set.remove(room_id)
if filters.is_invite:
raise NotImplementedError()

View file

@ -668,59 +668,35 @@ class FilterRoomsTestCase(HomeserverTestCase):
# https://github.com/element-hq/synapse/pull/17187#discussion_r1619492779)
from synapse.handlers.sliding_sync import SlidingSyncConfig
filters = SlidingSyncConfig.SlidingSyncList.Filters(
# Try with `is_dm=True`
# -----------------------------
truthy_filters = SlidingSyncConfig.SlidingSyncList.Filters(
is_dm=True,
)
# Try filtering the rooms
filtered_room_ids = self.get_success(
truthy_filtered_room_ids = self.get_success(
self.sliding_sync_handler.filter_rooms(
UserID.from_string(user1_id), {room_id, dm_room_id}, filters
UserID.from_string(user1_id), {room_id, dm_room_id}, truthy_filters
)
)
self.assertEqual(filtered_room_ids, {dm_room_id})
self.assertEqual(truthy_filtered_room_ids, {dm_room_id})
def test_filter_non_dm_rooms(self) -> None:
"""
Test `filter.is_dm` for non-DM rooms
"""
user1_id = self.register_user("user1", "pass")
user1_tok = self.login(user1_id, "pass")
user2_id = self.register_user("user2", "pass")
user2_tok = self.login(user2_id, "pass")
# Create a normal room
room_id = self.helper.create_room_as(
user1_id,
is_public=False,
tok=user1_tok,
)
# Create a DM room
dm_room_id = self._create_dm_room(
inviter_user_id=user1_id,
inviter_tok=user1_tok,
invitee_user_id=user2_id,
invitee_tok=user2_tok,
)
# 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
filters = SlidingSyncConfig.SlidingSyncList.Filters(
# Try with `is_dm=True`
# -----------------------------
falsy_filters = SlidingSyncConfig.SlidingSyncList.Filters(
is_dm=False,
)
# Try filtering the rooms
filtered_room_ids = self.get_success(
falsy_filtered_room_ids = self.get_success(
self.sliding_sync_handler.filter_rooms(
UserID.from_string(user1_id), {room_id, dm_room_id}, filters
UserID.from_string(user1_id), {room_id, dm_room_id}, falsy_filters
)
)
self.assertEqual(filtered_room_ids, {room_id})
self.assertEqual(falsy_filtered_room_ids, {room_id})
def test_filter_space_rooms(self) -> None:
"""
@ -894,3 +870,68 @@ class FilterRoomsTestCase(HomeserverTestCase):
)
self.assertEqual(filtered_room_ids, {room_id1})
def test_filter_encrypted_rooms(self) -> None:
"""
Test `filter.is_encrypted` for encrypted rooms
"""
user1_id = self.register_user("user1", "pass")
user1_tok = self.login(user1_id, "pass")
# Create a normal room
room_id = self.helper.create_room_as(
user1_id,
is_public=False,
tok=user1_tok,
)
# Create an encrypted room
encrypted_room_id = self.helper.create_room_as(
user1_id,
is_public=False,
tok=user1_tok,
)
self.helper.send_state(
encrypted_room_id,
EventTypes.RoomEncryption,
{"algorithm": "m.megolm.v1.aes-sha2"},
tok=user1_tok,
)
# 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,
)
# Try filtering 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,
)
)
self.assertEqual(truthy_filtered_room_ids, {encrypted_room_id})
# Try with `is_encrypted=False`
# -----------------------------
falsy_filters = SlidingSyncConfig.SlidingSyncList.Filters(
is_encrypted=False,
)
# Try filtering 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,
)
)
self.assertEqual(falsy_filtered_room_ids, {room_id})