Support room version 11 (#15912)

And fix a bug in the implementation of the updated redaction
format (MSC2174) where the top-level redacts field was not
properly added for backwards-compatibility.
This commit is contained in:
Patrick Cloke 2023-07-18 08:44:59 -04:00 committed by GitHub
parent 199c270947
commit 6d81aec09f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 190 additions and 290 deletions

View file

@ -0,0 +1 @@
Support room version 11 from [MSC3820](https://github.com/matrix-org/matrix-spec-proposals/pull/3820).

View file

@ -214,7 +214,7 @@ fi
extra_test_args=() extra_test_args=()
test_tags="synapse_blacklist,msc3787,msc3874,msc3890,msc3391,msc3930,faster_joins" test_tags="synapse_blacklist,msc3874,msc3890,msc3391,msc3930,faster_joins"
# All environment variables starting with PASS_ will be shared. # All environment variables starting with PASS_ will be shared.
# (The prefix is stripped off before reaching the container.) # (The prefix is stripped off before reaching the container.)

View file

@ -78,36 +78,29 @@ class RoomVersion:
# MSC2209: Check 'notifications' key while verifying # MSC2209: Check 'notifications' key while verifying
# m.room.power_levels auth rules. # m.room.power_levels auth rules.
limit_notifications_power_levels: bool limit_notifications_power_levels: bool
# MSC2175: No longer include the creator in m.room.create events. # No longer include the creator in m.room.create events.
msc2175_implicit_room_creator: bool implicit_room_creator: bool
# MSC2174/MSC2176: Apply updated redaction rules algorithm, move redacts to # Apply updated redaction rules algorithm from room version 11.
# content property. updated_redaction_rules: bool
msc2176_redaction_rules: bool # Support the 'restricted' join rule.
# MSC3083: Support the 'restricted' join_rule. restricted_join_rule: bool
msc3083_join_rules: bool # Support for the proper redaction rules for the restricted join rule. This requires
# MSC3375: Support for the proper redaction rules for MSC3083. This mustn't # restricted_join_rule to be enabled.
# be enabled if MSC3083 is not. restricted_join_rule_fix: bool
msc3375_redaction_rules: bool # Support the 'knock' join rule.
# MSC2403: Allows join_rules to be set to 'knock', changes auth rules to allow sending knock_join_rule: bool
# m.room.membership event with membership 'knock'.
msc2403_knocking: bool
# MSC3389: Protect relation information from redaction. # MSC3389: Protect relation information from redaction.
msc3389_relation_redactions: bool msc3389_relation_redactions: bool
# MSC3787: Adds support for a `knock_restricted` join rule, mixing concepts of # Support the 'knock_restricted' join rule.
# knocks and restricted join rules into the same join condition. knock_restricted_join_rule: bool
msc3787_knock_restricted_join_rule: bool # Enforce integer power levels
# MSC3667: Enforce integer power levels enforce_int_power_levels: bool
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 # 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 # 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 # is not enough to mark it "supported": the push rule evaluator also needs to
# support the flag. Unknown flags are ignored by the evaluator, making conditions # support the flag. Unknown flags are ignored by the evaluator, making conditions
# fail if used. # fail if used.
msc3931_push_features: Tuple[str, ...] # values from PushRuleRoomFlag msc3931_push_features: Tuple[str, ...] # values from PushRuleRoomFlag
# MSC3989: Redact the origin field.
msc3989_redaction_rules: bool
class RoomVersions: class RoomVersions:
@ -120,17 +113,15 @@ class RoomVersions:
special_case_aliases_auth=True, special_case_aliases_auth=True,
strict_canonicaljson=False, strict_canonicaljson=False,
limit_notifications_power_levels=False, limit_notifications_power_levels=False,
msc2175_implicit_room_creator=False, implicit_room_creator=False,
msc2176_redaction_rules=False, updated_redaction_rules=False,
msc3083_join_rules=False, restricted_join_rule=False,
msc3375_redaction_rules=False, restricted_join_rule_fix=False,
msc2403_knocking=False, knock_join_rule=False,
msc3389_relation_redactions=False, msc3389_relation_redactions=False,
msc3787_knock_restricted_join_rule=False, knock_restricted_join_rule=False,
msc3667_int_only_power_levels=False, enforce_int_power_levels=False,
msc3821_redaction_rules=False,
msc3931_push_features=(), msc3931_push_features=(),
msc3989_redaction_rules=False,
) )
V2 = RoomVersion( V2 = RoomVersion(
"2", "2",
@ -141,17 +132,15 @@ class RoomVersions:
special_case_aliases_auth=True, special_case_aliases_auth=True,
strict_canonicaljson=False, strict_canonicaljson=False,
limit_notifications_power_levels=False, limit_notifications_power_levels=False,
msc2175_implicit_room_creator=False, implicit_room_creator=False,
msc2176_redaction_rules=False, updated_redaction_rules=False,
msc3083_join_rules=False, restricted_join_rule=False,
msc3375_redaction_rules=False, restricted_join_rule_fix=False,
msc2403_knocking=False, knock_join_rule=False,
msc3389_relation_redactions=False, msc3389_relation_redactions=False,
msc3787_knock_restricted_join_rule=False, knock_restricted_join_rule=False,
msc3667_int_only_power_levels=False, enforce_int_power_levels=False,
msc3821_redaction_rules=False,
msc3931_push_features=(), msc3931_push_features=(),
msc3989_redaction_rules=False,
) )
V3 = RoomVersion( V3 = RoomVersion(
"3", "3",
@ -162,17 +151,15 @@ class RoomVersions:
special_case_aliases_auth=True, special_case_aliases_auth=True,
strict_canonicaljson=False, strict_canonicaljson=False,
limit_notifications_power_levels=False, limit_notifications_power_levels=False,
msc2175_implicit_room_creator=False, implicit_room_creator=False,
msc2176_redaction_rules=False, updated_redaction_rules=False,
msc3083_join_rules=False, restricted_join_rule=False,
msc3375_redaction_rules=False, restricted_join_rule_fix=False,
msc2403_knocking=False, knock_join_rule=False,
msc3389_relation_redactions=False, msc3389_relation_redactions=False,
msc3787_knock_restricted_join_rule=False, knock_restricted_join_rule=False,
msc3667_int_only_power_levels=False, enforce_int_power_levels=False,
msc3821_redaction_rules=False,
msc3931_push_features=(), msc3931_push_features=(),
msc3989_redaction_rules=False,
) )
V4 = RoomVersion( V4 = RoomVersion(
"4", "4",
@ -183,17 +170,15 @@ class RoomVersions:
special_case_aliases_auth=True, special_case_aliases_auth=True,
strict_canonicaljson=False, strict_canonicaljson=False,
limit_notifications_power_levels=False, limit_notifications_power_levels=False,
msc2175_implicit_room_creator=False, implicit_room_creator=False,
msc2176_redaction_rules=False, updated_redaction_rules=False,
msc3083_join_rules=False, restricted_join_rule=False,
msc3375_redaction_rules=False, restricted_join_rule_fix=False,
msc2403_knocking=False, knock_join_rule=False,
msc3389_relation_redactions=False, msc3389_relation_redactions=False,
msc3787_knock_restricted_join_rule=False, knock_restricted_join_rule=False,
msc3667_int_only_power_levels=False, enforce_int_power_levels=False,
msc3821_redaction_rules=False,
msc3931_push_features=(), msc3931_push_features=(),
msc3989_redaction_rules=False,
) )
V5 = RoomVersion( V5 = RoomVersion(
"5", "5",
@ -204,17 +189,15 @@ class RoomVersions:
special_case_aliases_auth=True, special_case_aliases_auth=True,
strict_canonicaljson=False, strict_canonicaljson=False,
limit_notifications_power_levels=False, limit_notifications_power_levels=False,
msc2175_implicit_room_creator=False, implicit_room_creator=False,
msc2176_redaction_rules=False, updated_redaction_rules=False,
msc3083_join_rules=False, restricted_join_rule=False,
msc3375_redaction_rules=False, restricted_join_rule_fix=False,
msc2403_knocking=False, knock_join_rule=False,
msc3389_relation_redactions=False, msc3389_relation_redactions=False,
msc3787_knock_restricted_join_rule=False, knock_restricted_join_rule=False,
msc3667_int_only_power_levels=False, enforce_int_power_levels=False,
msc3821_redaction_rules=False,
msc3931_push_features=(), msc3931_push_features=(),
msc3989_redaction_rules=False,
) )
V6 = RoomVersion( V6 = RoomVersion(
"6", "6",
@ -225,38 +208,15 @@ class RoomVersions:
special_case_aliases_auth=False, special_case_aliases_auth=False,
strict_canonicaljson=True, strict_canonicaljson=True,
limit_notifications_power_levels=True, limit_notifications_power_levels=True,
msc2175_implicit_room_creator=False, implicit_room_creator=False,
msc2176_redaction_rules=False, updated_redaction_rules=False,
msc3083_join_rules=False, restricted_join_rule=False,
msc3375_redaction_rules=False, restricted_join_rule_fix=False,
msc2403_knocking=False, knock_join_rule=False,
msc3389_relation_redactions=False, msc3389_relation_redactions=False,
msc3787_knock_restricted_join_rule=False, knock_restricted_join_rule=False,
msc3667_int_only_power_levels=False, enforce_int_power_levels=False,
msc3821_redaction_rules=False,
msc3931_push_features=(), msc3931_push_features=(),
msc3989_redaction_rules=False,
)
MSC2176 = RoomVersion(
"org.matrix.msc2176",
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=True,
msc3083_join_rules=False,
msc3375_redaction_rules=False,
msc2403_knocking=False,
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,
) )
V7 = RoomVersion( V7 = RoomVersion(
"7", "7",
@ -267,17 +227,15 @@ class RoomVersions:
special_case_aliases_auth=False, special_case_aliases_auth=False,
strict_canonicaljson=True, strict_canonicaljson=True,
limit_notifications_power_levels=True, limit_notifications_power_levels=True,
msc2175_implicit_room_creator=False, implicit_room_creator=False,
msc2176_redaction_rules=False, updated_redaction_rules=False,
msc3083_join_rules=False, restricted_join_rule=False,
msc3375_redaction_rules=False, restricted_join_rule_fix=False,
msc2403_knocking=True, knock_join_rule=True,
msc3389_relation_redactions=False, msc3389_relation_redactions=False,
msc3787_knock_restricted_join_rule=False, knock_restricted_join_rule=False,
msc3667_int_only_power_levels=False, enforce_int_power_levels=False,
msc3821_redaction_rules=False,
msc3931_push_features=(), msc3931_push_features=(),
msc3989_redaction_rules=False,
) )
V8 = RoomVersion( V8 = RoomVersion(
"8", "8",
@ -288,17 +246,15 @@ class RoomVersions:
special_case_aliases_auth=False, special_case_aliases_auth=False,
strict_canonicaljson=True, strict_canonicaljson=True,
limit_notifications_power_levels=True, limit_notifications_power_levels=True,
msc2175_implicit_room_creator=False, implicit_room_creator=False,
msc2176_redaction_rules=False, updated_redaction_rules=False,
msc3083_join_rules=True, restricted_join_rule=True,
msc3375_redaction_rules=False, restricted_join_rule_fix=False,
msc2403_knocking=True, knock_join_rule=True,
msc3389_relation_redactions=False, msc3389_relation_redactions=False,
msc3787_knock_restricted_join_rule=False, knock_restricted_join_rule=False,
msc3667_int_only_power_levels=False, enforce_int_power_levels=False,
msc3821_redaction_rules=False,
msc3931_push_features=(), msc3931_push_features=(),
msc3989_redaction_rules=False,
) )
V9 = RoomVersion( V9 = RoomVersion(
"9", "9",
@ -309,59 +265,15 @@ class RoomVersions:
special_case_aliases_auth=False, special_case_aliases_auth=False,
strict_canonicaljson=True, strict_canonicaljson=True,
limit_notifications_power_levels=True, limit_notifications_power_levels=True,
msc2175_implicit_room_creator=False, implicit_room_creator=False,
msc2176_redaction_rules=False, updated_redaction_rules=False,
msc3083_join_rules=True, restricted_join_rule=True,
msc3375_redaction_rules=True, restricted_join_rule_fix=True,
msc2403_knocking=True, knock_join_rule=True,
msc3389_relation_redactions=False, msc3389_relation_redactions=False,
msc3787_knock_restricted_join_rule=False, knock_restricted_join_rule=False,
msc3667_int_only_power_levels=False, enforce_int_power_levels=False,
msc3821_redaction_rules=False,
msc3931_push_features=(), msc3931_push_features=(),
msc3989_redaction_rules=False,
)
MSC3787 = RoomVersion(
"org.matrix.msc3787",
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,
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,
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,
) )
V10 = RoomVersion( V10 = RoomVersion(
"10", "10",
@ -372,17 +284,15 @@ class RoomVersions:
special_case_aliases_auth=False, special_case_aliases_auth=False,
strict_canonicaljson=True, strict_canonicaljson=True,
limit_notifications_power_levels=True, limit_notifications_power_levels=True,
msc2175_implicit_room_creator=False, implicit_room_creator=False,
msc2176_redaction_rules=False, updated_redaction_rules=False,
msc3083_join_rules=True, restricted_join_rule=True,
msc3375_redaction_rules=True, restricted_join_rule_fix=True,
msc2403_knocking=True, knock_join_rule=True,
msc3389_relation_redactions=False, msc3389_relation_redactions=False,
msc3787_knock_restricted_join_rule=True, knock_restricted_join_rule=True,
msc3667_int_only_power_levels=True, enforce_int_power_levels=True,
msc3821_redaction_rules=False,
msc3931_push_features=(), msc3931_push_features=(),
msc3989_redaction_rules=False,
) )
MSC1767v10 = RoomVersion( MSC1767v10 = RoomVersion(
# MSC1767 (Extensible Events) based on room version "10" # MSC1767 (Extensible Events) based on room version "10"
@ -394,60 +304,34 @@ class RoomVersions:
special_case_aliases_auth=False, special_case_aliases_auth=False,
strict_canonicaljson=True, strict_canonicaljson=True,
limit_notifications_power_levels=True, limit_notifications_power_levels=True,
msc2175_implicit_room_creator=False, implicit_room_creator=False,
msc2176_redaction_rules=False, updated_redaction_rules=False,
msc3083_join_rules=True, restricted_join_rule=True,
msc3375_redaction_rules=True, restricted_join_rule_fix=True,
msc2403_knocking=True, knock_join_rule=True,
msc3389_relation_redactions=False, msc3389_relation_redactions=False,
msc3787_knock_restricted_join_rule=True, knock_restricted_join_rule=True,
msc3667_int_only_power_levels=True, enforce_int_power_levels=True,
msc3821_redaction_rules=False,
msc3931_push_features=(PushRuleRoomFlag.EXTENSIBLE_EVENTS,), msc3931_push_features=(PushRuleRoomFlag.EXTENSIBLE_EVENTS,),
msc3989_redaction_rules=False,
) )
MSC3989 = RoomVersion( V11 = RoomVersion(
"org.matrix.msc3989", "11",
RoomDisposition.UNSTABLE, RoomDisposition.STABLE,
EventFormatVersions.ROOM_V4_PLUS, EventFormatVersions.ROOM_V4_PLUS,
StateResolutionVersions.V2, StateResolutionVersions.V2,
enforce_key_validity=True, enforce_key_validity=True,
special_case_aliases_auth=False, special_case_aliases_auth=False,
strict_canonicaljson=True, strict_canonicaljson=True,
limit_notifications_power_levels=True, limit_notifications_power_levels=True,
msc2175_implicit_room_creator=False, implicit_room_creator=True, # Used by MSC3820
msc2176_redaction_rules=False, updated_redaction_rules=True, # Used by MSC3820
msc3083_join_rules=True, restricted_join_rule=True,
msc3375_redaction_rules=True, restricted_join_rule_fix=True,
msc2403_knocking=True, knock_join_rule=True,
msc3389_relation_redactions=False, msc3389_relation_redactions=False,
msc3787_knock_restricted_join_rule=True, knock_restricted_join_rule=True,
msc3667_int_only_power_levels=True, enforce_int_power_levels=True,
msc3821_redaction_rules=False,
msc3931_push_features=(), msc3931_push_features=(),
msc3989_redaction_rules=True,
)
MSC3820opt2 = RoomVersion(
# Based upon v10
"org.matrix.msc3820.opt2",
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=True, # Used by MSC3820
msc2176_redaction_rules=True, # Used by MSC3820
msc3083_join_rules=True,
msc3375_redaction_rules=True,
msc2403_knocking=True,
msc3389_relation_redactions=False,
msc3787_knock_restricted_join_rule=True,
msc3667_int_only_power_levels=True,
msc3821_redaction_rules=True, # Used by MSC3820
msc3931_push_features=(),
msc3989_redaction_rules=True, # Used by MSC3820
) )
@ -460,14 +344,11 @@ KNOWN_ROOM_VERSIONS: Dict[str, RoomVersion] = {
RoomVersions.V4, RoomVersions.V4,
RoomVersions.V5, RoomVersions.V5,
RoomVersions.V6, RoomVersions.V6,
RoomVersions.MSC2176,
RoomVersions.V7, RoomVersions.V7,
RoomVersions.V8, RoomVersions.V8,
RoomVersions.V9, RoomVersions.V9,
RoomVersions.MSC3787,
RoomVersions.V10, RoomVersions.V10,
RoomVersions.MSC3989, RoomVersions.V11,
RoomVersions.MSC3820opt2,
) )
} }
@ -496,12 +377,12 @@ MSC3244_CAPABILITIES = {
RoomVersionCapability( RoomVersionCapability(
"knock", "knock",
RoomVersions.V7, RoomVersions.V7,
lambda room_version: room_version.msc2403_knocking, lambda room_version: room_version.knock_join_rule,
), ),
RoomVersionCapability( RoomVersionCapability(
"restricted", "restricted",
RoomVersions.V9, RoomVersions.V9,
lambda room_version: room_version.msc3083_join_rules, lambda room_version: room_version.restricted_join_rule,
), ),
) )
} }

View file

@ -126,7 +126,7 @@ def validate_event_for_room_version(event: "EventBase") -> None:
raise AuthError(403, "Event not signed by sending server") raise AuthError(403, "Event not signed by sending server")
is_invite_via_allow_rule = ( is_invite_via_allow_rule = (
event.room_version.msc3083_join_rules event.room_version.restricted_join_rule
and event.type == EventTypes.Member and event.type == EventTypes.Member
and event.membership == Membership.JOIN and event.membership == Membership.JOIN
and EventContentFields.AUTHORISING_USER in event.content and EventContentFields.AUTHORISING_USER in event.content
@ -352,11 +352,9 @@ LENIENT_EVENT_BYTE_LIMITS_ROOM_VERSIONS = {
RoomVersions.V4, RoomVersions.V4,
RoomVersions.V5, RoomVersions.V5,
RoomVersions.V6, RoomVersions.V6,
RoomVersions.MSC2176,
RoomVersions.V7, RoomVersions.V7,
RoomVersions.V8, RoomVersions.V8,
RoomVersions.V9, RoomVersions.V9,
RoomVersions.MSC3787,
RoomVersions.V10, RoomVersions.V10,
RoomVersions.MSC1767v10, RoomVersions.MSC1767v10,
} }
@ -449,7 +447,7 @@ def _check_create(event: "EventBase") -> None:
# 1.4 If content has no creator field, reject if the room version requires it. # 1.4 If content has no creator field, reject if the room version requires it.
if ( if (
not event.room_version.msc2175_implicit_room_creator not event.room_version.implicit_room_creator
and EventContentFields.ROOM_CREATOR not in event.content and EventContentFields.ROOM_CREATOR not in event.content
): ):
raise AuthError(403, "Create event lacks a 'creator' property") raise AuthError(403, "Create event lacks a 'creator' property")
@ -486,7 +484,7 @@ def _is_membership_change_allowed(
key = (EventTypes.Create, "") key = (EventTypes.Create, "")
create = auth_events.get(key) create = auth_events.get(key)
if create and event.prev_event_ids()[0] == create.event_id: if create and event.prev_event_ids()[0] == create.event_id:
if room_version.msc2175_implicit_room_creator: if room_version.implicit_room_creator:
creator = create.sender creator = create.sender
else: else:
creator = create.content[EventContentFields.ROOM_CREATOR] creator = create.content[EventContentFields.ROOM_CREATOR]
@ -509,7 +507,7 @@ def _is_membership_change_allowed(
caller_invited = caller and caller.membership == Membership.INVITE caller_invited = caller and caller.membership == Membership.INVITE
caller_knocked = ( caller_knocked = (
caller caller
and room_version.msc2403_knocking and room_version.knock_join_rule
and caller.membership == Membership.KNOCK and caller.membership == Membership.KNOCK
) )
@ -609,9 +607,9 @@ def _is_membership_change_allowed(
elif join_rule == JoinRules.PUBLIC: elif join_rule == JoinRules.PUBLIC:
pass pass
elif ( elif (
room_version.msc3083_join_rules and join_rule == JoinRules.RESTRICTED room_version.restricted_join_rule and join_rule == JoinRules.RESTRICTED
) or ( ) or (
room_version.msc3787_knock_restricted_join_rule room_version.knock_restricted_join_rule
and join_rule == JoinRules.KNOCK_RESTRICTED and join_rule == JoinRules.KNOCK_RESTRICTED
): ):
# This is the same as public, but the event must contain a reference # This is the same as public, but the event must contain a reference
@ -641,9 +639,9 @@ def _is_membership_change_allowed(
elif ( elif (
join_rule == JoinRules.INVITE join_rule == JoinRules.INVITE
or (room_version.msc2403_knocking and join_rule == JoinRules.KNOCK) or (room_version.knock_join_rule and join_rule == JoinRules.KNOCK)
or ( or (
room_version.msc3787_knock_restricted_join_rule room_version.knock_restricted_join_rule
and join_rule == JoinRules.KNOCK_RESTRICTED and join_rule == JoinRules.KNOCK_RESTRICTED
) )
): ):
@ -677,9 +675,9 @@ def _is_membership_change_allowed(
"You don't have permission to ban", "You don't have permission to ban",
errcode=Codes.INSUFFICIENT_POWER, errcode=Codes.INSUFFICIENT_POWER,
) )
elif room_version.msc2403_knocking and Membership.KNOCK == membership: elif room_version.knock_join_rule and Membership.KNOCK == membership:
if join_rule != JoinRules.KNOCK and ( if join_rule != JoinRules.KNOCK and (
not room_version.msc3787_knock_restricted_join_rule not room_version.knock_restricted_join_rule
or join_rule != JoinRules.KNOCK_RESTRICTED or join_rule != JoinRules.KNOCK_RESTRICTED
): ):
raise AuthError(403, "You don't have permission to knock") raise AuthError(403, "You don't have permission to knock")
@ -836,7 +834,7 @@ def _check_power_levels(
# Reject events with stringy power levels if required by room version # Reject events with stringy power levels if required by room version
if ( if (
event.type == EventTypes.PowerLevels event.type == EventTypes.PowerLevels
and room_version_obj.msc3667_int_only_power_levels and room_version_obj.enforce_int_power_levels
): ):
for k, v in event.content.items(): for k, v in event.content.items():
if k in { if k in {
@ -972,7 +970,7 @@ def get_user_power_level(user_id: str, auth_events: StateMap["EventBase"]) -> in
key = (EventTypes.Create, "") key = (EventTypes.Create, "")
create_event = auth_events.get(key) create_event = auth_events.get(key)
if create_event is not None: if create_event is not None:
if create_event.room_version.msc2175_implicit_room_creator: if create_event.room_version.implicit_room_creator:
creator = create_event.sender creator = create_event.sender
else: else:
creator = create_event.content[EventContentFields.ROOM_CREATOR] creator = create_event.content[EventContentFields.ROOM_CREATOR]
@ -1110,7 +1108,7 @@ def auth_types_for_event(
) )
auth_types.add(key) auth_types.add(key)
if room_version.msc3083_join_rules and membership == Membership.JOIN: if room_version.restricted_join_rule and membership == Membership.JOIN:
if EventContentFields.AUTHORISING_USER in event.content: if EventContentFields.AUTHORISING_USER in event.content:
key = ( key = (
EventTypes.Member, EventTypes.Member,

View file

@ -346,7 +346,7 @@ class EventBase(metaclass=abc.ABCMeta):
@property @property
def redacts(self) -> Optional[str]: def redacts(self) -> Optional[str]:
"""MSC2176 moved the redacts field into the content.""" """MSC2176 moved the redacts field into the content."""
if self.room_version.msc2176_redaction_rules: if self.room_version.updated_redaction_rules:
return self.content.get("redacts") return self.content.get("redacts")
return self.get("redacts") return self.get("redacts")

View file

@ -175,7 +175,7 @@ class EventBuilder:
# MSC2174 moves the redacts property to the content, it is invalid to # MSC2174 moves the redacts property to the content, it is invalid to
# provide it as a top-level property. # provide it as a top-level property.
if self._redacts is not None and not self.room_version.msc2176_redaction_rules: if self._redacts is not None and not self.room_version.updated_redaction_rules:
event_dict["redacts"] = self._redacts event_dict["redacts"] = self._redacts
if self._origin_server_ts is not None: if self._origin_server_ts is not None:

View file

@ -108,13 +108,9 @@ def prune_event_dict(room_version: RoomVersion, event_dict: JsonDict) -> JsonDic
"origin_server_ts", "origin_server_ts",
] ]
# Room versions from before MSC2176 had additional allowed keys. # Earlier room versions from had additional allowed keys.
if not room_version.msc2176_redaction_rules: if not room_version.updated_redaction_rules:
allowed_keys.extend(["prev_state", "membership"]) allowed_keys.extend(["prev_state", "membership", "origin"])
# Room versions before MSC3989 kept the origin field.
if not room_version.msc3989_redaction_rules:
allowed_keys.append("origin")
event_type = event_dict["type"] event_type = event_dict["type"]
@ -127,9 +123,9 @@ def prune_event_dict(room_version: RoomVersion, event_dict: JsonDict) -> JsonDic
if event_type == EventTypes.Member: if event_type == EventTypes.Member:
add_fields("membership") add_fields("membership")
if room_version.msc3375_redaction_rules: if room_version.restricted_join_rule_fix:
add_fields(EventContentFields.AUTHORISING_USER) add_fields(EventContentFields.AUTHORISING_USER)
if room_version.msc3821_redaction_rules: if room_version.updated_redaction_rules:
# Preserve the signed field under third_party_invite. # Preserve the signed field under third_party_invite.
third_party_invite = event_dict["content"].get("third_party_invite") third_party_invite = event_dict["content"].get("third_party_invite")
if isinstance(third_party_invite, collections.abc.Mapping): if isinstance(third_party_invite, collections.abc.Mapping):
@ -141,13 +137,13 @@ def prune_event_dict(room_version: RoomVersion, event_dict: JsonDict) -> JsonDic
elif event_type == EventTypes.Create: elif event_type == EventTypes.Create:
# MSC2176 rules state that create events cannot be redacted. # MSC2176 rules state that create events cannot be redacted.
if room_version.msc2176_redaction_rules: if room_version.updated_redaction_rules:
return event_dict return event_dict
add_fields("creator") add_fields("creator")
elif event_type == EventTypes.JoinRules: elif event_type == EventTypes.JoinRules:
add_fields("join_rule") add_fields("join_rule")
if room_version.msc3083_join_rules: if room_version.restricted_join_rule:
add_fields("allow") add_fields("allow")
elif event_type == EventTypes.PowerLevels: elif event_type == EventTypes.PowerLevels:
add_fields( add_fields(
@ -161,14 +157,14 @@ def prune_event_dict(room_version: RoomVersion, event_dict: JsonDict) -> JsonDic
"redact", "redact",
) )
if room_version.msc2176_redaction_rules: if room_version.updated_redaction_rules:
add_fields("invite") add_fields("invite")
elif event_type == EventTypes.Aliases and room_version.special_case_aliases_auth: elif event_type == EventTypes.Aliases and room_version.special_case_aliases_auth:
add_fields("aliases") add_fields("aliases")
elif event_type == EventTypes.RoomHistoryVisibility: elif event_type == EventTypes.RoomHistoryVisibility:
add_fields("history_visibility") add_fields("history_visibility")
elif event_type == EventTypes.Redaction and room_version.msc2176_redaction_rules: elif event_type == EventTypes.Redaction and room_version.updated_redaction_rules:
add_fields("redacts") add_fields("redacts")
# Protect the rel_type and event_id fields under the m.relates_to field. # Protect the rel_type and event_id fields under the m.relates_to field.
@ -477,6 +473,15 @@ def serialize_event(
if config.as_client_event: if config.as_client_event:
d = config.event_format(d) d = config.event_format(d)
# If the event is a redaction, copy the redacts field from the content to
# top-level for backwards compatibility.
if (
e.type == EventTypes.Redaction
and e.room_version.updated_redaction_rules
and e.redacts is not None
):
d["redacts"] = e.redacts
only_event_fields = config.only_event_fields only_event_fields = config.only_event_fields
if only_event_fields: if only_event_fields:
if not isinstance(only_event_fields, list) or not all( if not isinstance(only_event_fields, list) or not all(

View file

@ -231,7 +231,7 @@ async def _check_sigs_on_pdu(
# If this is a join event for a restricted room it may have been authorised # If this is a join event for a restricted room it may have been authorised
# via a different server from the sending server. Check those signatures. # via a different server from the sending server. Check those signatures.
if ( if (
room_version.msc3083_join_rules room_version.restricted_join_rule
and pdu.type == EventTypes.Member and pdu.type == EventTypes.Member
and pdu.membership == Membership.JOIN and pdu.membership == Membership.JOIN
and EventContentFields.AUTHORISING_USER in pdu.content and EventContentFields.AUTHORISING_USER in pdu.content

View file

@ -983,7 +983,7 @@ class FederationClient(FederationBase):
if not room_version: if not room_version:
raise UnsupportedRoomVersionError() raise UnsupportedRoomVersionError()
if not room_version.msc2403_knocking and membership == Membership.KNOCK: if not room_version.knock_join_rule and membership == Membership.KNOCK:
raise SynapseError( raise SynapseError(
400, 400,
"This room version does not support knocking", "This room version does not support knocking",
@ -1069,7 +1069,7 @@ class FederationClient(FederationBase):
# * Ensure the signatures are good. # * Ensure the signatures are good.
# #
# Otherwise, fallback to the provided event. # Otherwise, fallback to the provided event.
if room_version.msc3083_join_rules and response.event: if room_version.restricted_join_rule and response.event:
event = response.event event = response.event
valid_pdu = await self._check_sigs_and_hash_and_fetch_one( valid_pdu = await self._check_sigs_and_hash_and_fetch_one(
@ -1195,7 +1195,7 @@ class FederationClient(FederationBase):
# MSC3083 defines additional error codes for room joins. # MSC3083 defines additional error codes for room joins.
failover_errcodes = None failover_errcodes = None
if room_version.msc3083_join_rules: if room_version.restricted_join_rule:
failover_errcodes = ( failover_errcodes = (
Codes.UNABLE_AUTHORISE_JOIN, Codes.UNABLE_AUTHORISE_JOIN,
Codes.UNABLE_TO_GRANT_JOIN, Codes.UNABLE_TO_GRANT_JOIN,

View file

@ -806,7 +806,7 @@ class FederationServer(FederationBase):
raise IncompatibleRoomVersionError(room_version=room_version.identifier) raise IncompatibleRoomVersionError(room_version=room_version.identifier)
# Check that this room supports knocking as defined by its room version # Check that this room supports knocking as defined by its room version
if not room_version.msc2403_knocking: if not room_version.knock_join_rule:
raise SynapseError( raise SynapseError(
403, 403,
"This room version does not support knocking", "This room version does not support knocking",
@ -909,7 +909,7 @@ class FederationServer(FederationBase):
errcode=Codes.NOT_FOUND, errcode=Codes.NOT_FOUND,
) )
if membership_type == Membership.KNOCK and not room_version.msc2403_knocking: if membership_type == Membership.KNOCK and not room_version.knock_join_rule:
raise SynapseError( raise SynapseError(
403, 403,
"This room version does not support knocking", "This room version does not support knocking",
@ -933,7 +933,7 @@ class FederationServer(FederationBase):
# the event is valid to be sent into the room. Currently this is only done # the event is valid to be sent into the room. Currently this is only done
# if the user is being joined via restricted join rules. # if the user is being joined via restricted join rules.
if ( if (
room_version.msc3083_join_rules room_version.restricted_join_rule
and event.membership == Membership.JOIN and event.membership == Membership.JOIN
and EventContentFields.AUTHORISING_USER in event.content and EventContentFields.AUTHORISING_USER in event.content
): ):

View file

@ -277,7 +277,7 @@ class EventAuthHandler:
True if the proper room version and join rules are set for restricted access. True if the proper room version and join rules are set for restricted access.
""" """
# This only applies to room versions which support the new join rule. # This only applies to room versions which support the new join rule.
if not room_version.msc3083_join_rules: if not room_version.restricted_join_rule:
return False return False
# If there's no join rule, then it defaults to invite (so this doesn't apply). # If there's no join rule, then it defaults to invite (so this doesn't apply).
@ -292,7 +292,7 @@ class EventAuthHandler:
return True return True
# also check for MSC3787 behaviour # also check for MSC3787 behaviour
if room_version.msc3787_knock_restricted_join_rule: if room_version.knock_restricted_join_rule:
return content_join_rule == JoinRules.KNOCK_RESTRICTED return content_join_rule == JoinRules.KNOCK_RESTRICTED
return False return False

View file

@ -957,7 +957,7 @@ class FederationHandler:
# Note that this requires the /send_join request to come back to the # Note that this requires the /send_join request to come back to the
# same server. # same server.
prev_event_ids = None prev_event_ids = None
if room_version.msc3083_join_rules: if room_version.restricted_join_rule:
# Note that the room's state can change out from under us and render our # Note that the room's state can change out from under us and render our
# nice join rules-conformant event non-conformant by the time we build the # nice join rules-conformant event non-conformant by the time we build the
# event. When this happens, our validation at the end fails and we respond # event. When this happens, our validation at the end fails and we respond

View file

@ -1116,7 +1116,7 @@ class RoomCreationHandler:
preset_config, config = self._room_preset_config(room_config) preset_config, config = self._room_preset_config(room_config)
# MSC2175 removes the creator field from the create event. # MSC2175 removes the creator field from the create event.
if not room_version.msc2175_implicit_room_creator: if not room_version.implicit_room_creator:
creation_content["creator"] = creator_id creation_content["creator"] = creator_id
creation_event, unpersisted_creation_context = await create_event( creation_event, unpersisted_creation_context = await create_event(
EventTypes.Create, creation_content, False EventTypes.Create, creation_content, False

View file

@ -564,9 +564,9 @@ class RoomSummaryHandler:
join_rule = join_rules_event.content.get("join_rule") join_rule = join_rules_event.content.get("join_rule")
if ( if (
join_rule == JoinRules.PUBLIC join_rule == JoinRules.PUBLIC
or (room_version.msc2403_knocking and join_rule == JoinRules.KNOCK) or (room_version.knock_join_rule and join_rule == JoinRules.KNOCK)
or ( or (
room_version.msc3787_knock_restricted_join_rule room_version.knock_restricted_join_rule
and join_rule == JoinRules.KNOCK_RESTRICTED and join_rule == JoinRules.KNOCK_RESTRICTED
) )
): ):

View file

@ -375,7 +375,7 @@ class BulkPushRuleEvaluator:
# _get_power_levels_and_sender_level in its call to get_user_power_level # _get_power_levels_and_sender_level in its call to get_user_power_level
# (even for room V10.) # (even for room V10.)
notification_levels = power_levels.get("notifications", {}) notification_levels = power_levels.get("notifications", {})
if not event.room_version.msc3667_int_only_power_levels: if not event.room_version.enforce_int_power_levels:
keys = list(notification_levels.keys()) keys = list(notification_levels.keys())
for key in keys: for key in keys:
level = notification_levels.get(key, SENTINEL) level = notification_levels.get(key, SENTINEL)

View file

@ -1117,7 +1117,7 @@ class RoomRedactEventRestServlet(TransactionRestServlet):
# Ensure the redacts property in the content matches the one provided in # Ensure the redacts property in the content matches the one provided in
# the URL. # the URL.
room_version = await self._store.get_room_version(room_id) room_version = await self._store.get_room_version(room_id)
if room_version.msc2176_redaction_rules: if room_version.updated_redaction_rules:
if "redacts" in content and content["redacts"] != event_id: if "redacts" in content and content["redacts"] != event_id:
raise SynapseError( raise SynapseError(
400, 400,
@ -1151,7 +1151,7 @@ class RoomRedactEventRestServlet(TransactionRestServlet):
"sender": requester.user.to_string(), "sender": requester.user.to_string(),
} }
# Earlier room versions had a top-level redacts property. # Earlier room versions had a top-level redacts property.
if not room_version.msc2176_redaction_rules: if not room_version.updated_redaction_rules:
event_dict["redacts"] = event_id event_dict["redacts"] = event_id
( (

View file

@ -2136,7 +2136,7 @@ class RoomStore(RoomBackgroundUpdateStore, RoomWorkerStore):
raise StoreError(400, "No create event in state") raise StoreError(400, "No create event in state")
# Before MSC2175, the room creator was a separate field. # Before MSC2175, the room creator was a separate field.
if not room_version.msc2175_implicit_room_creator: if not room_version.implicit_room_creator:
room_creator = create_event.content.get(EventContentFields.ROOM_CREATOR) room_creator = create_event.content.get(EventContentFields.ROOM_CREATOR)
if not isinstance(room_creator, str): if not isinstance(room_creator, str):

View file

@ -140,18 +140,16 @@ class PruneEventTestCase(stdlib_unittest.TestCase):
}, },
) )
# As of MSC2176 we now redact the membership and prev_states keys. # As of room versions we now redact the membership, prev_states, and origin keys.
self.run_test( self.run_test(
{"type": "A", "prev_state": "prev_state", "membership": "join"}, {
"type": "A",
"prev_state": "prev_state",
"membership": "join",
"origin": "example.com",
},
{"type": "A", "content": {}, "signatures": {}, "unsigned": {}}, {"type": "A", "content": {}, "signatures": {}, "unsigned": {}},
room_version=RoomVersions.MSC2176, room_version=RoomVersions.V11,
)
# As of MSC3989 we now redact the origin key.
self.run_test(
{"type": "A", "origin": "example.com"},
{"type": "A", "content": {}, "signatures": {}, "unsigned": {}},
room_version=RoomVersions.MSC3989,
) )
def test_unsigned(self) -> None: def test_unsigned(self) -> None:
@ -236,7 +234,7 @@ class PruneEventTestCase(stdlib_unittest.TestCase):
"signatures": {}, "signatures": {},
"unsigned": {}, "unsigned": {},
}, },
room_version=RoomVersions.MSC2176, room_version=RoomVersions.V11,
) )
def test_power_levels(self) -> None: def test_power_levels(self) -> None:
@ -286,7 +284,7 @@ class PruneEventTestCase(stdlib_unittest.TestCase):
"signatures": {}, "signatures": {},
"unsigned": {}, "unsigned": {},
}, },
room_version=RoomVersions.MSC2176, room_version=RoomVersions.V11,
) )
def test_alias_event(self) -> None: def test_alias_event(self) -> None:
@ -349,7 +347,7 @@ class PruneEventTestCase(stdlib_unittest.TestCase):
"signatures": {}, "signatures": {},
"unsigned": {}, "unsigned": {},
}, },
room_version=RoomVersions.MSC2176, room_version=RoomVersions.V11,
) )
def test_join_rules(self) -> None: def test_join_rules(self) -> None:
@ -472,7 +470,7 @@ class PruneEventTestCase(stdlib_unittest.TestCase):
"signatures": {}, "signatures": {},
"unsigned": {}, "unsigned": {},
}, },
room_version=RoomVersions.MSC3821, room_version=RoomVersions.V11,
) )
# Ensure this doesn't break if an invalid field is sent. # Ensure this doesn't break if an invalid field is sent.
@ -491,7 +489,7 @@ class PruneEventTestCase(stdlib_unittest.TestCase):
"signatures": {}, "signatures": {},
"unsigned": {}, "unsigned": {},
}, },
room_version=RoomVersions.MSC3821, room_version=RoomVersions.V11,
) )
self.run_test( self.run_test(
@ -509,7 +507,7 @@ class PruneEventTestCase(stdlib_unittest.TestCase):
"signatures": {}, "signatures": {},
"unsigned": {}, "unsigned": {},
}, },
room_version=RoomVersions.MSC3821, room_version=RoomVersions.V11,
) )
def test_relations(self) -> None: def test_relations(self) -> None:

View file

@ -20,6 +20,8 @@ from synapse.api.room_versions import RoomVersions
from synapse.rest import admin from synapse.rest import admin
from synapse.rest.client import login, room, sync from synapse.rest.client import login, room, sync
from synapse.server import HomeServer from synapse.server import HomeServer
from synapse.storage._base import db_to_json
from synapse.storage.database import LoggingTransaction
from synapse.types import JsonDict from synapse.types import JsonDict
from synapse.util import Clock from synapse.util import Clock
@ -573,7 +575,7 @@ class RedactionsTestCase(HomeserverTestCase):
room_id = self.helper.create_room_as( room_id = self.helper.create_room_as(
self.mod_user_id, self.mod_user_id,
tok=self.mod_access_token, tok=self.mod_access_token,
room_version=RoomVersions.MSC2176.identifier, room_version=RoomVersions.V11.identifier,
) )
# Create an event. # Create an event.
@ -597,5 +599,20 @@ class RedactionsTestCase(HomeserverTestCase):
redact_event = timeline[-1] redact_event = timeline[-1]
self.assertEqual(redact_event["type"], EventTypes.Redaction) self.assertEqual(redact_event["type"], EventTypes.Redaction)
# The redacts key should be in the content. # The redacts key should be in the content.
self.assertNotIn("redacts", redact_event)
self.assertEquals(redact_event["content"]["redacts"], event_id) self.assertEquals(redact_event["content"]["redacts"], event_id)
# It should also be copied as the top-level redacts field for backwards
# compatibility.
self.assertEquals(redact_event["redacts"], event_id)
# But it isn't actually part of the event.
def get_event(txn: LoggingTransaction) -> JsonDict:
return db_to_json(
main_datastore._fetch_event_rows(txn, [event_id])[event_id].json
)
main_datastore = self.hs.get_datastores().main
event_json = self.get_success(
main_datastore.db_pool.runInteraction("get_event", get_event)
)
self.assertNotIn("redacts", event_json)