mirror of
https://github.com/element-hq/synapse.git
synced 2024-12-27 09:58:41 +00:00
Include user membership on events (#17282)
MSC4115 has now completed FCP, so we can enable it by default and switch to the stable identifier.
This commit is contained in:
parent
c12ee0d5ba
commit
2c36a679ae
1
changelog.d/17282.feature
Normal file
1
changelog.d/17282.feature
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Include user membership in events served to clients, per MSC4115.
|
|
@ -105,8 +105,6 @@ experimental_features:
|
||||||
# Expose a room summary for public rooms
|
# Expose a room summary for public rooms
|
||||||
msc3266_enabled: true
|
msc3266_enabled: true
|
||||||
|
|
||||||
msc4115_membership_on_events: true
|
|
||||||
|
|
||||||
server_notices:
|
server_notices:
|
||||||
system_mxid_localpart: _server
|
system_mxid_localpart: _server
|
||||||
system_mxid_display_name: "Server Alert"
|
system_mxid_display_name: "Server Alert"
|
||||||
|
|
|
@ -223,7 +223,6 @@ test_packages=(
|
||||||
./tests/msc3930
|
./tests/msc3930
|
||||||
./tests/msc3902
|
./tests/msc3902
|
||||||
./tests/msc3967
|
./tests/msc3967
|
||||||
./tests/msc4115
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Enable dirty runs, so tests will reuse the same container where possible.
|
# Enable dirty runs, so tests will reuse the same container where possible.
|
||||||
|
|
|
@ -238,7 +238,7 @@ class EventUnsignedContentFields:
|
||||||
"""Fields found inside the 'unsigned' data on events"""
|
"""Fields found inside the 'unsigned' data on events"""
|
||||||
|
|
||||||
# Requesting user's membership, per MSC4115
|
# Requesting user's membership, per MSC4115
|
||||||
MSC4115_MEMBERSHIP: Final = "io.element.msc4115.membership"
|
MEMBERSHIP: Final = "membership"
|
||||||
|
|
||||||
|
|
||||||
class RoomTypes:
|
class RoomTypes:
|
||||||
|
|
|
@ -436,10 +436,6 @@ class ExperimentalConfig(Config):
|
||||||
("experimental", "msc4108_delegation_endpoint"),
|
("experimental", "msc4108_delegation_endpoint"),
|
||||||
)
|
)
|
||||||
|
|
||||||
self.msc4115_membership_on_events = experimental.get(
|
|
||||||
"msc4115_membership_on_events", False
|
|
||||||
)
|
|
||||||
|
|
||||||
self.msc3916_authenticated_media_enabled = experimental.get(
|
self.msc3916_authenticated_media_enabled = experimental.get(
|
||||||
"msc3916_authenticated_media_enabled", False
|
"msc3916_authenticated_media_enabled", False
|
||||||
)
|
)
|
||||||
|
|
|
@ -42,7 +42,6 @@ class AdminHandler:
|
||||||
self._device_handler = hs.get_device_handler()
|
self._device_handler = hs.get_device_handler()
|
||||||
self._storage_controllers = hs.get_storage_controllers()
|
self._storage_controllers = hs.get_storage_controllers()
|
||||||
self._state_storage_controller = self._storage_controllers.state
|
self._state_storage_controller = self._storage_controllers.state
|
||||||
self._hs_config = hs.config
|
|
||||||
self._msc3866_enabled = hs.config.experimental.msc3866.enabled
|
self._msc3866_enabled = hs.config.experimental.msc3866.enabled
|
||||||
|
|
||||||
async def get_whois(self, user: UserID) -> JsonMapping:
|
async def get_whois(self, user: UserID) -> JsonMapping:
|
||||||
|
@ -215,7 +214,6 @@ class AdminHandler:
|
||||||
self._storage_controllers,
|
self._storage_controllers,
|
||||||
user_id,
|
user_id,
|
||||||
events,
|
events,
|
||||||
msc4115_membership_on_events=self._hs_config.experimental.msc4115_membership_on_events,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
writer.write_events(room_id, events)
|
writer.write_events(room_id, events)
|
||||||
|
|
|
@ -148,7 +148,6 @@ class EventHandler:
|
||||||
def __init__(self, hs: "HomeServer"):
|
def __init__(self, hs: "HomeServer"):
|
||||||
self.store = hs.get_datastores().main
|
self.store = hs.get_datastores().main
|
||||||
self._storage_controllers = hs.get_storage_controllers()
|
self._storage_controllers = hs.get_storage_controllers()
|
||||||
self._config = hs.config
|
|
||||||
|
|
||||||
async def get_event(
|
async def get_event(
|
||||||
self,
|
self,
|
||||||
|
@ -194,7 +193,6 @@ class EventHandler:
|
||||||
user.to_string(),
|
user.to_string(),
|
||||||
[event],
|
[event],
|
||||||
is_peeking=is_peeking,
|
is_peeking=is_peeking,
|
||||||
msc4115_membership_on_events=self._config.experimental.msc4115_membership_on_events,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if not filtered:
|
if not filtered:
|
||||||
|
|
|
@ -224,7 +224,6 @@ class InitialSyncHandler:
|
||||||
self._storage_controllers,
|
self._storage_controllers,
|
||||||
user_id,
|
user_id,
|
||||||
messages,
|
messages,
|
||||||
msc4115_membership_on_events=self.hs.config.experimental.msc4115_membership_on_events,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
start_token = now_token.copy_and_replace(StreamKeyType.ROOM, token)
|
start_token = now_token.copy_and_replace(StreamKeyType.ROOM, token)
|
||||||
|
@ -383,7 +382,6 @@ class InitialSyncHandler:
|
||||||
requester.user.to_string(),
|
requester.user.to_string(),
|
||||||
messages,
|
messages,
|
||||||
is_peeking=is_peeking,
|
is_peeking=is_peeking,
|
||||||
msc4115_membership_on_events=self.hs.config.experimental.msc4115_membership_on_events,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
start_token = StreamToken.START.copy_and_replace(StreamKeyType.ROOM, token)
|
start_token = StreamToken.START.copy_and_replace(StreamKeyType.ROOM, token)
|
||||||
|
@ -498,7 +496,6 @@ class InitialSyncHandler:
|
||||||
requester.user.to_string(),
|
requester.user.to_string(),
|
||||||
messages,
|
messages,
|
||||||
is_peeking=is_peeking,
|
is_peeking=is_peeking,
|
||||||
msc4115_membership_on_events=self.hs.config.experimental.msc4115_membership_on_events,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
start_token = now_token.copy_and_replace(StreamKeyType.ROOM, token)
|
start_token = now_token.copy_and_replace(StreamKeyType.ROOM, token)
|
||||||
|
|
|
@ -623,7 +623,6 @@ class PaginationHandler:
|
||||||
user_id,
|
user_id,
|
||||||
events,
|
events,
|
||||||
is_peeking=(member_event_id is None),
|
is_peeking=(member_event_id is None),
|
||||||
msc4115_membership_on_events=self.hs.config.experimental.msc4115_membership_on_events,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# if after the filter applied there are no more events
|
# if after the filter applied there are no more events
|
||||||
|
|
|
@ -95,7 +95,6 @@ class RelationsHandler:
|
||||||
self._event_handler = hs.get_event_handler()
|
self._event_handler = hs.get_event_handler()
|
||||||
self._event_serializer = hs.get_event_client_serializer()
|
self._event_serializer = hs.get_event_client_serializer()
|
||||||
self._event_creation_handler = hs.get_event_creation_handler()
|
self._event_creation_handler = hs.get_event_creation_handler()
|
||||||
self._config = hs.config
|
|
||||||
|
|
||||||
async def get_relations(
|
async def get_relations(
|
||||||
self,
|
self,
|
||||||
|
@ -164,7 +163,6 @@ class RelationsHandler:
|
||||||
user_id,
|
user_id,
|
||||||
events,
|
events,
|
||||||
is_peeking=(member_event_id is None),
|
is_peeking=(member_event_id is None),
|
||||||
msc4115_membership_on_events=self._config.experimental.msc4115_membership_on_events,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# The relations returned for the requested event do include their
|
# The relations returned for the requested event do include their
|
||||||
|
@ -610,7 +608,6 @@ class RelationsHandler:
|
||||||
user_id,
|
user_id,
|
||||||
events,
|
events,
|
||||||
is_peeking=(member_event_id is None),
|
is_peeking=(member_event_id is None),
|
||||||
msc4115_membership_on_events=self._config.experimental.msc4115_membership_on_events,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
aggregations = await self.get_bundled_aggregations(
|
aggregations = await self.get_bundled_aggregations(
|
||||||
|
|
|
@ -1476,7 +1476,6 @@ class RoomContextHandler:
|
||||||
user.to_string(),
|
user.to_string(),
|
||||||
events,
|
events,
|
||||||
is_peeking=is_peeking,
|
is_peeking=is_peeking,
|
||||||
msc4115_membership_on_events=self.hs.config.experimental.msc4115_membership_on_events,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
event = await self.store.get_event(
|
event = await self.store.get_event(
|
||||||
|
|
|
@ -483,7 +483,6 @@ class SearchHandler:
|
||||||
self._storage_controllers,
|
self._storage_controllers,
|
||||||
user.to_string(),
|
user.to_string(),
|
||||||
filtered_events,
|
filtered_events,
|
||||||
msc4115_membership_on_events=self.hs.config.experimental.msc4115_membership_on_events,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
events.sort(key=lambda e: -rank_map[e.event_id])
|
events.sort(key=lambda e: -rank_map[e.event_id])
|
||||||
|
@ -585,7 +584,6 @@ class SearchHandler:
|
||||||
self._storage_controllers,
|
self._storage_controllers,
|
||||||
user.to_string(),
|
user.to_string(),
|
||||||
filtered_events,
|
filtered_events,
|
||||||
msc4115_membership_on_events=self.hs.config.experimental.msc4115_membership_on_events,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
room_events.extend(events)
|
room_events.extend(events)
|
||||||
|
@ -673,14 +671,12 @@ class SearchHandler:
|
||||||
self._storage_controllers,
|
self._storage_controllers,
|
||||||
user.to_string(),
|
user.to_string(),
|
||||||
res.events_before,
|
res.events_before,
|
||||||
msc4115_membership_on_events=self.hs.config.experimental.msc4115_membership_on_events,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
events_after = await filter_events_for_client(
|
events_after = await filter_events_for_client(
|
||||||
self._storage_controllers,
|
self._storage_controllers,
|
||||||
user.to_string(),
|
user.to_string(),
|
||||||
res.events_after,
|
res.events_after,
|
||||||
msc4115_membership_on_events=self.hs.config.experimental.msc4115_membership_on_events,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
context: JsonDict = {
|
context: JsonDict = {
|
||||||
|
|
|
@ -844,7 +844,6 @@ class SyncHandler:
|
||||||
sync_config.user.to_string(),
|
sync_config.user.to_string(),
|
||||||
recents,
|
recents,
|
||||||
always_include_ids=current_state_ids,
|
always_include_ids=current_state_ids,
|
||||||
msc4115_membership_on_events=self.hs_config.experimental.msc4115_membership_on_events,
|
|
||||||
)
|
)
|
||||||
log_kv({"recents_after_visibility_filtering": len(recents)})
|
log_kv({"recents_after_visibility_filtering": len(recents)})
|
||||||
else:
|
else:
|
||||||
|
@ -930,7 +929,6 @@ class SyncHandler:
|
||||||
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,
|
||||||
msc4115_membership_on_events=self.hs_config.experimental.msc4115_membership_on_events,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
loaded_recents = []
|
loaded_recents = []
|
||||||
|
|
|
@ -721,7 +721,6 @@ class Notifier:
|
||||||
user.to_string(),
|
user.to_string(),
|
||||||
new_events,
|
new_events,
|
||||||
is_peeking=is_peeking,
|
is_peeking=is_peeking,
|
||||||
msc4115_membership_on_events=self.hs.config.experimental.msc4115_membership_on_events,
|
|
||||||
)
|
)
|
||||||
elif keyname == StreamKeyType.PRESENCE:
|
elif keyname == StreamKeyType.PRESENCE:
|
||||||
now = self.clock.time_msec()
|
now = self.clock.time_msec()
|
||||||
|
|
|
@ -532,7 +532,6 @@ class Mailer:
|
||||||
self._storage_controllers,
|
self._storage_controllers,
|
||||||
user_id,
|
user_id,
|
||||||
results.events_before,
|
results.events_before,
|
||||||
msc4115_membership_on_events=self.hs.config.experimental.msc4115_membership_on_events,
|
|
||||||
)
|
)
|
||||||
the_events.append(notif_event)
|
the_events.append(notif_event)
|
||||||
|
|
||||||
|
|
|
@ -82,7 +82,6 @@ async def filter_events_for_client(
|
||||||
is_peeking: bool = False,
|
is_peeking: bool = False,
|
||||||
always_include_ids: FrozenSet[str] = frozenset(),
|
always_include_ids: FrozenSet[str] = frozenset(),
|
||||||
filter_send_to_client: bool = True,
|
filter_send_to_client: bool = True,
|
||||||
msc4115_membership_on_events: bool = False,
|
|
||||||
) -> List[EventBase]:
|
) -> List[EventBase]:
|
||||||
"""
|
"""
|
||||||
Check which events a user is allowed to see. If the user can see the event but its
|
Check which events a user is allowed to see. If the user can see the event but its
|
||||||
|
@ -101,12 +100,10 @@ async def filter_events_for_client(
|
||||||
filter_send_to_client: Whether we're checking an event that's going to be
|
filter_send_to_client: Whether we're checking an event that's going to be
|
||||||
sent to a client. This might not always be the case since this function can
|
sent to a client. This might not always be the case since this function can
|
||||||
also be called to check whether a user can see the state at a given point.
|
also be called to check whether a user can see the state at a given point.
|
||||||
msc4115_membership_on_events: Whether to include the requesting user's
|
|
||||||
membership in the "unsigned" data, per MSC4115.
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
The filtered events. If `msc4115_membership_on_events` is true, the `unsigned`
|
The filtered events. The `unsigned` data is annotated with the membership state
|
||||||
data is annotated with the membership state of `user_id` at each event.
|
of `user_id` at each event.
|
||||||
"""
|
"""
|
||||||
# Filter out events that have been soft failed so that we don't relay them
|
# Filter out events that have been soft failed so that we don't relay them
|
||||||
# to clients.
|
# to clients.
|
||||||
|
@ -159,9 +156,6 @@ async def filter_events_for_client(
|
||||||
if filtered is None:
|
if filtered is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if not msc4115_membership_on_events:
|
|
||||||
return filtered
|
|
||||||
|
|
||||||
# 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
|
||||||
|
@ -186,7 +180,7 @@ async def filter_events_for_client(
|
||||||
# Copy the event before updating the unsigned data: this shouldn't be persisted
|
# Copy the event before updating the unsigned data: this shouldn't be persisted
|
||||||
# to the cache!
|
# to the cache!
|
||||||
cloned = clone_event(filtered)
|
cloned = clone_event(filtered)
|
||||||
cloned.unsigned[EventUnsignedContentFields.MSC4115_MEMBERSHIP] = user_membership
|
cloned.unsigned[EventUnsignedContentFields.MEMBERSHIP] = user_membership
|
||||||
|
|
||||||
return cloned
|
return cloned
|
||||||
|
|
||||||
|
|
|
@ -167,7 +167,6 @@ class RetentionTestCase(unittest.HomeserverTestCase):
|
||||||
storage_controllers,
|
storage_controllers,
|
||||||
self.user_id,
|
self.user_id,
|
||||||
events,
|
events,
|
||||||
msc4115_membership_on_events=True,
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -336,7 +336,6 @@ class FilterEventsForClientTestCase(HomeserverTestCase):
|
||||||
self.hs.get_storage_controllers(),
|
self.hs.get_storage_controllers(),
|
||||||
"@joiner:test",
|
"@joiner:test",
|
||||||
events_to_filter,
|
events_to_filter,
|
||||||
msc4115_membership_on_events=True,
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
resident_filtered_events = self.get_success(
|
resident_filtered_events = self.get_success(
|
||||||
|
@ -344,7 +343,6 @@ class FilterEventsForClientTestCase(HomeserverTestCase):
|
||||||
self.hs.get_storage_controllers(),
|
self.hs.get_storage_controllers(),
|
||||||
"@resident:test",
|
"@resident:test",
|
||||||
events_to_filter,
|
events_to_filter,
|
||||||
msc4115_membership_on_events=True,
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -357,7 +355,7 @@ class FilterEventsForClientTestCase(HomeserverTestCase):
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
["join", "join", "leave"],
|
["join", "join", "leave"],
|
||||||
[
|
[
|
||||||
e.unsigned[EventUnsignedContentFields.MSC4115_MEMBERSHIP]
|
e.unsigned[EventUnsignedContentFields.MEMBERSHIP]
|
||||||
for e in joiner_filtered_events
|
for e in joiner_filtered_events
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@ -379,7 +377,7 @@ class FilterEventsForClientTestCase(HomeserverTestCase):
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
["join", "join", "join", "join", "join"],
|
["join", "join", "join", "join", "join"],
|
||||||
[
|
[
|
||||||
e.unsigned[EventUnsignedContentFields.MSC4115_MEMBERSHIP]
|
e.unsigned[EventUnsignedContentFields.MEMBERSHIP]
|
||||||
for e in resident_filtered_events
|
for e in resident_filtered_events
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@ -441,7 +439,6 @@ class FilterEventsOutOfBandEventsForClientTestCase(
|
||||||
self.hs.get_storage_controllers(),
|
self.hs.get_storage_controllers(),
|
||||||
"@user:test",
|
"@user:test",
|
||||||
[invite_event, reject_event],
|
[invite_event, reject_event],
|
||||||
msc4115_membership_on_events=True,
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
|
@ -451,7 +448,7 @@ class FilterEventsOutOfBandEventsForClientTestCase(
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
["invite", "leave"],
|
["invite", "leave"],
|
||||||
[
|
[
|
||||||
e.unsigned[EventUnsignedContentFields.MSC4115_MEMBERSHIP]
|
e.unsigned[EventUnsignedContentFields.MEMBERSHIP]
|
||||||
for e in filtered_events
|
for e in filtered_events
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@ -463,7 +460,6 @@ class FilterEventsOutOfBandEventsForClientTestCase(
|
||||||
self.hs.get_storage_controllers(),
|
self.hs.get_storage_controllers(),
|
||||||
"@other:test",
|
"@other:test",
|
||||||
[invite_event, reject_event],
|
[invite_event, reject_event],
|
||||||
msc4115_membership_on_events=True,
|
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
[],
|
[],
|
||||||
|
|
Loading…
Reference in a new issue