diff --git a/changelog.d/15563.misc b/changelog.d/15563.misc new file mode 100644 index 000000000..8bfecf2b9 --- /dev/null +++ b/changelog.d/15563.misc @@ -0,0 +1 @@ +Implement [MSC3821](https://github.com/matrix-org/matrix-spec-proposals/pull/3821) to update the redaction rules. diff --git a/synapse/api/room_versions.py b/synapse/api/room_versions.py index e65b9a028..7030b133d 100644 --- a/synapse/api/room_versions.py +++ b/synapse/api/room_versions.py @@ -103,6 +103,8 @@ class RoomVersion: msc3787_knock_restricted_join_rule: bool # MSC3667: Enforce integer power levels msc3667_int_only_power_levels: bool + # MSC3821: Do not redact the third_party_invite content field for membership events. + msc3821_redaction_rules: bool # MSC3931: Adds a push rule condition for "room version feature flags", making # some push rules room version dependent. Note that adding a flag to this list # is not enough to mark it "supported": the push rule evaluator also needs to @@ -133,6 +135,7 @@ class RoomVersions: msc3389_relation_redactions=False, msc3787_knock_restricted_join_rule=False, msc3667_int_only_power_levels=False, + msc3821_redaction_rules=False, msc3931_push_features=(), msc3989_redaction_rules=False, ) @@ -155,6 +158,7 @@ class RoomVersions: msc3389_relation_redactions=False, msc3787_knock_restricted_join_rule=False, msc3667_int_only_power_levels=False, + msc3821_redaction_rules=False, msc3931_push_features=(), msc3989_redaction_rules=False, ) @@ -177,6 +181,7 @@ class RoomVersions: msc3389_relation_redactions=False, msc3787_knock_restricted_join_rule=False, msc3667_int_only_power_levels=False, + msc3821_redaction_rules=False, msc3931_push_features=(), msc3989_redaction_rules=False, ) @@ -199,6 +204,7 @@ class RoomVersions: msc3389_relation_redactions=False, msc3787_knock_restricted_join_rule=False, msc3667_int_only_power_levels=False, + msc3821_redaction_rules=False, msc3931_push_features=(), msc3989_redaction_rules=False, ) @@ -221,6 +227,7 @@ class RoomVersions: msc3389_relation_redactions=False, msc3787_knock_restricted_join_rule=False, msc3667_int_only_power_levels=False, + msc3821_redaction_rules=False, msc3931_push_features=(), msc3989_redaction_rules=False, ) @@ -243,6 +250,7 @@ class RoomVersions: msc3389_relation_redactions=False, msc3787_knock_restricted_join_rule=False, msc3667_int_only_power_levels=False, + msc3821_redaction_rules=False, msc3931_push_features=(), msc3989_redaction_rules=False, ) @@ -265,6 +273,7 @@ class RoomVersions: msc3389_relation_redactions=False, msc3787_knock_restricted_join_rule=False, msc3667_int_only_power_levels=False, + msc3821_redaction_rules=False, msc3931_push_features=(), msc3989_redaction_rules=False, ) @@ -287,6 +296,7 @@ class RoomVersions: msc3389_relation_redactions=False, msc3787_knock_restricted_join_rule=False, msc3667_int_only_power_levels=False, + msc3821_redaction_rules=False, msc3931_push_features=(), msc3989_redaction_rules=False, ) @@ -309,6 +319,7 @@ class RoomVersions: msc3389_relation_redactions=False, msc3787_knock_restricted_join_rule=False, msc3667_int_only_power_levels=False, + msc3821_redaction_rules=False, msc3931_push_features=(), msc3989_redaction_rules=False, ) @@ -331,6 +342,7 @@ class RoomVersions: msc3389_relation_redactions=False, msc3787_knock_restricted_join_rule=False, msc3667_int_only_power_levels=False, + msc3821_redaction_rules=False, msc3931_push_features=(), msc3989_redaction_rules=False, ) @@ -353,6 +365,30 @@ class RoomVersions: msc3389_relation_redactions=False, msc3787_knock_restricted_join_rule=True, msc3667_int_only_power_levels=False, + msc3821_redaction_rules=False, + msc3931_push_features=(), + msc3989_redaction_rules=False, + ) + MSC3821 = RoomVersion( + "org.matrix.msc3821.opt1", + RoomDisposition.UNSTABLE, + EventFormatVersions.ROOM_V4_PLUS, + StateResolutionVersions.V2, + enforce_key_validity=True, + special_case_aliases_auth=False, + strict_canonicaljson=True, + limit_notifications_power_levels=True, + msc2175_implicit_room_creator=False, + msc2176_redaction_rules=False, + msc3083_join_rules=True, + msc3375_redaction_rules=True, + msc2403_knocking=True, + msc2716_historical=False, + msc2716_redactions=False, + msc3389_relation_redactions=False, + msc3787_knock_restricted_join_rule=False, + msc3667_int_only_power_levels=False, + msc3821_redaction_rules=True, msc3931_push_features=(), msc3989_redaction_rules=False, ) @@ -375,6 +411,7 @@ class RoomVersions: msc3389_relation_redactions=False, msc3787_knock_restricted_join_rule=True, msc3667_int_only_power_levels=True, + msc3821_redaction_rules=False, msc3931_push_features=(), msc3989_redaction_rules=False, ) @@ -397,6 +434,7 @@ class RoomVersions: msc3389_relation_redactions=False, msc3787_knock_restricted_join_rule=False, msc3667_int_only_power_levels=False, + msc3821_redaction_rules=False, msc3931_push_features=(), msc3989_redaction_rules=False, ) @@ -420,6 +458,7 @@ class RoomVersions: msc3389_relation_redactions=False, msc3787_knock_restricted_join_rule=True, msc3667_int_only_power_levels=True, + msc3821_redaction_rules=False, msc3931_push_features=(PushRuleRoomFlag.EXTENSIBLE_EVENTS,), msc3989_redaction_rules=False, ) @@ -442,6 +481,7 @@ class RoomVersions: msc3389_relation_redactions=False, msc3787_knock_restricted_join_rule=True, msc3667_int_only_power_levels=True, + msc3821_redaction_rules=False, msc3931_push_features=(), msc3989_redaction_rules=True, ) diff --git a/synapse/events/utils.py b/synapse/events/utils.py index e540f1582..e6d040176 100644 --- a/synapse/events/utils.py +++ b/synapse/events/utils.py @@ -130,6 +130,16 @@ def prune_event_dict(room_version: RoomVersion, event_dict: JsonDict) -> JsonDic add_fields("membership") if room_version.msc3375_redaction_rules: add_fields(EventContentFields.AUTHORISING_USER) + if room_version.msc3821_redaction_rules: + # Preserve the signed field under third_party_invite. + third_party_invite = event_dict["content"].get("third_party_invite") + if isinstance(third_party_invite, collections.abc.Mapping): + new_content["third_party_invite"] = {} + if "signed" in third_party_invite: + new_content["third_party_invite"]["signed"] = third_party_invite[ + "signed" + ] + elif event_type == EventTypes.Create: # MSC2176 rules state that create events cannot be redacted. if room_version.msc2176_redaction_rules: diff --git a/tests/events/test_utils.py b/tests/events/test_utils.py index 02f0800a3..e40eac2eb 100644 --- a/tests/events/test_utils.py +++ b/tests/events/test_utils.py @@ -394,7 +394,7 @@ class PruneEventTestCase(stdlib_unittest.TestCase): ) def test_member(self) -> None: - """Member events have changed behavior starting with MSC3375.""" + """Member events have changed behavior in MSC3375 and MSC3821.""" self.run_test( { "type": "m.room.member", @@ -437,6 +437,79 @@ class PruneEventTestCase(stdlib_unittest.TestCase): room_version=RoomVersions.V9, ) + # After MSC3821, the signed key under third_party_invite is protected + # from redaction. + THIRD_PARTY_INVITE = { + "display_name": "alice", + "signed": { + "mxid": "@alice:example.org", + "signatures": { + "magic.forest": { + "ed25519:3": "fQpGIW1Snz+pwLZu6sTy2aHy/DYWWTspTJRPyNp0PKkymfIsNffysMl6ObMMFdIJhk6g6pwlIqZ54rxo8SLmAg" + } + }, + "token": "abc123", + }, + } + + self.run_test( + { + "type": "m.room.member", + "content": { + "membership": "invite", + "third_party_invite": THIRD_PARTY_INVITE, + "other_key": "stripped", + }, + }, + { + "type": "m.room.member", + "content": { + "membership": "invite", + "third_party_invite": {"signed": THIRD_PARTY_INVITE["signed"]}, + }, + "signatures": {}, + "unsigned": {}, + }, + room_version=RoomVersions.MSC3821, + ) + + # Ensure this doesn't break if an invalid field is sent. + self.run_test( + { + "type": "m.room.member", + "content": { + "membership": "invite", + "third_party_invite": {}, + "other_key": "stripped", + }, + }, + { + "type": "m.room.member", + "content": {"membership": "invite", "third_party_invite": {}}, + "signatures": {}, + "unsigned": {}, + }, + room_version=RoomVersions.MSC3821, + ) + + self.run_test( + { + "type": "m.room.member", + "content": { + "membership": "invite", + "third_party_invite": "stripped", + "other_key": "stripped", + }, + }, + { + "type": "m.room.member", + "content": {"membership": "invite"}, + "signatures": {}, + "unsigned": {}, + }, + room_version=RoomVersions.MSC3821, + ) + def test_relations(self) -> None: """Event relations get redacted until MSC3389.""" # Normally the m._relates_to field is redacted.