diff --git a/changelog.d/20438.bugfix b/changelog.d/20438.bugfix new file mode 100644 index 0000000000..0e8aed3c04 --- /dev/null +++ b/changelog.d/20438.bugfix @@ -0,0 +1 @@ +Fix a bug where a client using `state_after` ([MSC4222](https://github.com/matrix-org/matrix-spec-proposals/pull/4222)) would keep showing a room as invited or knocked after the user rejected the invite or rescinded the knock. diff --git a/synapse/handlers/sync.py b/synapse/handlers/sync.py index d635465e5c..3ada731e93 100644 --- a/synapse/handlers/sync.py +++ b/synapse/handlers/sync.py @@ -3570,6 +3570,25 @@ class SyncHandler: # An out of band room won't have any state changes. state = {} + # MSC4222 clients do not apply timeline events to room state, so + # the out-of-band membership has to appear in `state_after` or they + # never learn that the user rejected the invite or rescinded the + # knock. Sliding sync does the same in `get_room_sync_data`. + # + # `events` is unfiltered, so a client filter that hides the + # membership event still gets it in `state_after`. A filter that + # empties the timeline batch gets no room at all, as the shortcut + # above returns first (see the FIXME in + # `tests/handlers/test_sync.py`). + if sync_config.use_state_after: + for oob_event in events or (): + if ( + oob_event.type == EventTypes.Member + and oob_event.state_key == sync_config.user.to_string() + and oob_event.internal_metadata.is_out_of_band_membership() + ): + state[(oob_event.type, oob_event.state_key)] = oob_event + summary: JsonDict | None = {} # we include a summary in room responses when we're lazy loading