From 5557ad8dea99ed9acbcefba9da83269dd573b1f3 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 3 May 2022 19:36:09 -0600 Subject: [PATCH 1/5] Add a new room version for MSC3787's knock+restricted join rule --- synapse/api/constants.py | 2 ++ synapse/api/room_versions.py | 32 ++++++++++++++++++++++++++++++++ synapse/event_auth.py | 15 +++++++++++++-- synapse/handlers/event_auth.py | 10 +++++++++- synapse/handlers/room_summary.py | 3 +++ 5 files changed, 59 insertions(+), 3 deletions(-) diff --git a/synapse/api/constants.py b/synapse/api/constants.py index 0172eb60b8dc..d39a9ef957d4 100644 --- a/synapse/api/constants.py +++ b/synapse/api/constants.py @@ -65,6 +65,8 @@ class JoinRules: PRIVATE: Final = "private" # As defined for MSC3083. RESTRICTED: Final = "restricted" + # As defined for MSC3787. + KNOCK_RESTRICTED: Final = "knock_restricted" class RestrictedJoinRuleTypes: diff --git a/synapse/api/room_versions.py b/synapse/api/room_versions.py index a747a4081497..3f85d61b4633 100644 --- a/synapse/api/room_versions.py +++ b/synapse/api/room_versions.py @@ -81,6 +81,9 @@ class RoomVersion: msc2716_historical: bool # MSC2716: Adds support for redacting "insertion", "chunk", and "marker" events msc2716_redactions: bool + # MSC3787: Adds support for a `knock_restricted` join rule, mixing concepts of + # knocks and restricted join rules into the same join condition. + msc3787_knock_restricted_join_rule: bool class RoomVersions: @@ -99,6 +102,7 @@ class RoomVersions: msc2403_knocking=False, msc2716_historical=False, msc2716_redactions=False, + msc3787_knock_restricted_join_rule=False, ) V2 = RoomVersion( "2", @@ -115,6 +119,7 @@ class RoomVersions: msc2403_knocking=False, msc2716_historical=False, msc2716_redactions=False, + msc3787_knock_restricted_join_rule=False, ) V3 = RoomVersion( "3", @@ -131,6 +136,7 @@ class RoomVersions: msc2403_knocking=False, msc2716_historical=False, msc2716_redactions=False, + msc3787_knock_restricted_join_rule=False, ) V4 = RoomVersion( "4", @@ -147,6 +153,7 @@ class RoomVersions: msc2403_knocking=False, msc2716_historical=False, msc2716_redactions=False, + msc3787_knock_restricted_join_rule=False, ) V5 = RoomVersion( "5", @@ -163,6 +170,7 @@ class RoomVersions: msc2403_knocking=False, msc2716_historical=False, msc2716_redactions=False, + msc3787_knock_restricted_join_rule=False, ) V6 = RoomVersion( "6", @@ -179,6 +187,7 @@ class RoomVersions: msc2403_knocking=False, msc2716_historical=False, msc2716_redactions=False, + msc3787_knock_restricted_join_rule=False, ) MSC2176 = RoomVersion( "org.matrix.msc2176", @@ -195,6 +204,7 @@ class RoomVersions: msc2403_knocking=False, msc2716_historical=False, msc2716_redactions=False, + msc3787_knock_restricted_join_rule=False, ) V7 = RoomVersion( "7", @@ -211,6 +221,7 @@ class RoomVersions: msc2403_knocking=True, msc2716_historical=False, msc2716_redactions=False, + msc3787_knock_restricted_join_rule=False, ) V8 = RoomVersion( "8", @@ -227,6 +238,7 @@ class RoomVersions: msc2403_knocking=True, msc2716_historical=False, msc2716_redactions=False, + msc3787_knock_restricted_join_rule=False, ) V9 = RoomVersion( "9", @@ -243,6 +255,7 @@ class RoomVersions: msc2403_knocking=True, msc2716_historical=False, msc2716_redactions=False, + msc3787_knock_restricted_join_rule=False, ) MSC2716v3 = RoomVersion( "org.matrix.msc2716v3", @@ -259,6 +272,24 @@ class RoomVersions: msc2403_knocking=True, msc2716_historical=True, msc2716_redactions=True, + msc3787_knock_restricted_join_rule=False, + ) + MSC3787 = RoomVersion( + "org.matrix.msc3787", + RoomDisposition.UNSTABLE, + EventFormatVersions.V3, + StateResolutionVersions.V2, + enforce_key_validity=True, + special_case_aliases_auth=False, + strict_canonicaljson=True, + limit_notifications_power_levels=True, + msc2176_redaction_rules=False, + msc3083_join_rules=True, + msc3375_redaction_rules=True, + msc2403_knocking=True, + msc2716_historical=False, + msc2716_redactions=False, + msc3787_knock_restricted_join_rule=True, ) @@ -276,6 +307,7 @@ class RoomVersions: RoomVersions.V8, RoomVersions.V9, RoomVersions.MSC2716v3, + RoomVersions.MSC3787, ) } diff --git a/synapse/event_auth.py b/synapse/event_auth.py index 621a3efcccec..c29034d738bb 100644 --- a/synapse/event_auth.py +++ b/synapse/event_auth.py @@ -414,7 +414,12 @@ def _is_membership_change_allowed( raise AuthError(403, "You are banned from this room") elif join_rule == JoinRules.PUBLIC: pass - elif room_version.msc3083_join_rules and join_rule == JoinRules.RESTRICTED: + elif ( + room_version.msc3083_join_rules and join_rule == JoinRules.RESTRICTED + ) or ( + room_version.msc3787_knock_restricted_join_rule + and join_rule == JoinRules.KNOCK_RESTRICTED + ): # This is the same as public, but the event must contain a reference # to the server who authorised the join. If the event does not contain # the proper content it is rejected. @@ -442,6 +447,9 @@ def _is_membership_change_allowed( elif join_rule == JoinRules.INVITE or ( room_version.msc2403_knocking and join_rule == JoinRules.KNOCK + ) or ( + room_version.msc3787_knock_restricted_join_rule + and join_rule == JoinRules.KNOCK_RESTRICTED ): if not caller_in_room and not caller_invited: raise AuthError(403, "You are not invited to this room.") @@ -462,7 +470,10 @@ def _is_membership_change_allowed( if user_level < ban_level or user_level <= target_level: raise AuthError(403, "You don't have permission to ban") elif room_version.msc2403_knocking and Membership.KNOCK == membership: - if join_rule != JoinRules.KNOCK: + if join_rule != JoinRules.KNOCK and ( + not room_version.msc3787_knock_restricted_join_rule + or join_rule != JoinRules.KNOCK_RESTRICTED + ): raise AuthError(403, "You don't have permission to knock") elif target_user_id != event.user_id: raise AuthError(403, "You cannot knock for other users") diff --git a/synapse/handlers/event_auth.py b/synapse/handlers/event_auth.py index d441ebb0ab3d..6bed46435135 100644 --- a/synapse/handlers/event_auth.py +++ b/synapse/handlers/event_auth.py @@ -241,7 +241,15 @@ async def has_restricted_join_rules( # If the join rule is not restricted, this doesn't apply. join_rules_event = await self._store.get_event(join_rules_event_id) - return join_rules_event.content.get("join_rule") == JoinRules.RESTRICTED + content_join_rule = join_rules_event.content.get("join_rule") + if content_join_rule == JoinRules.RESTRICTED: + return True + + # also check for MSC3787 behaviour + if room_version.msc3787_knock_restricted_join_rule: + return content_join_rule == JoinRules.KNOCK_RESTRICTED + + return False async def get_rooms_that_allow_join( self, state_ids: StateMap[str] diff --git a/synapse/handlers/room_summary.py b/synapse/handlers/room_summary.py index 486145f48aca..e019bb845be1 100644 --- a/synapse/handlers/room_summary.py +++ b/synapse/handlers/room_summary.py @@ -563,6 +563,9 @@ async def _is_local_room_accessible( join_rule = join_rules_event.content.get("join_rule") if join_rule == JoinRules.PUBLIC or ( room_version.msc2403_knocking and join_rule == JoinRules.KNOCK + ) or ( + room_version.msc3787_knock_restricted_join_rule + and join_rule == JoinRules.KNOCK_RESTRICTED ): return True From 77d477af4e23d7ae21729f0e4681a8ef2b32f9d0 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 3 May 2022 19:39:57 -0600 Subject: [PATCH 2/5] Changelog --- changelog.d/12623.feature | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/12623.feature diff --git a/changelog.d/12623.feature b/changelog.d/12623.feature new file mode 100644 index 000000000000..cdee19fafa36 --- /dev/null +++ b/changelog.d/12623.feature @@ -0,0 +1 @@ +Add support for [MSC3787: Allowing knocks to restricted rooms](https://github.com/matrix-org/matrix-spec-proposals/pull/3787). \ No newline at end of file From 12bdab5eaea61cdf9f66e3071203c2a0d7992552 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 3 May 2022 19:58:21 -0600 Subject: [PATCH 3/5] Appease the linter --- synapse/event_auth.py | 14 ++++++++------ synapse/handlers/room_summary.py | 14 ++++++++------ 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/synapse/event_auth.py b/synapse/event_auth.py index c29034d738bb..71cf671d86c6 100644 --- a/synapse/event_auth.py +++ b/synapse/event_auth.py @@ -445,12 +445,14 @@ def _is_membership_change_allowed( if authorising_user_level < invite_level: raise AuthError(403, "Join event authorised by invalid server.") - elif join_rule == JoinRules.INVITE or ( - room_version.msc2403_knocking and join_rule == JoinRules.KNOCK - ) or ( - room_version.msc3787_knock_restricted_join_rule - and join_rule == JoinRules.KNOCK_RESTRICTED - ): + elif ( + join_rule == JoinRules.INVITE + or (room_version.msc2403_knocking and join_rule == JoinRules.KNOCK) + or ( + room_version.msc3787_knock_restricted_join_rule + and join_rule == JoinRules.KNOCK_RESTRICTED + ) + ): if not caller_in_room and not caller_invited: raise AuthError(403, "You are not invited to this room.") else: diff --git a/synapse/handlers/room_summary.py b/synapse/handlers/room_summary.py index e019bb845be1..179c96697733 100644 --- a/synapse/handlers/room_summary.py +++ b/synapse/handlers/room_summary.py @@ -561,12 +561,14 @@ async def _is_local_room_accessible( if join_rules_event_id: join_rules_event = await self._store.get_event(join_rules_event_id) join_rule = join_rules_event.content.get("join_rule") - if join_rule == JoinRules.PUBLIC or ( - room_version.msc2403_knocking and join_rule == JoinRules.KNOCK - ) or ( - room_version.msc3787_knock_restricted_join_rule - and join_rule == JoinRules.KNOCK_RESTRICTED - ): + if ( + join_rule == JoinRules.PUBLIC + or (room_version.msc2403_knocking and join_rule == JoinRules.KNOCK) + or ( + room_version.msc3787_knock_restricted_join_rule + and join_rule == JoinRules.KNOCK_RESTRICTED + ) + ): return True # Include the room if it is peekable. From 8f7e29a57b310edf73a2e032f4b75ea12e172edb Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 3 May 2022 19:59:58 -0600 Subject: [PATCH 4/5] Appease the linter again --- synapse/event_auth.py | 2 +- synapse/handlers/room_summary.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/synapse/event_auth.py b/synapse/event_auth.py index 71cf671d86c6..4c0b587a7643 100644 --- a/synapse/event_auth.py +++ b/synapse/event_auth.py @@ -452,7 +452,7 @@ def _is_membership_change_allowed( room_version.msc3787_knock_restricted_join_rule and join_rule == JoinRules.KNOCK_RESTRICTED ) - ): + ): if not caller_in_room and not caller_invited: raise AuthError(403, "You are not invited to this room.") else: diff --git a/synapse/handlers/room_summary.py b/synapse/handlers/room_summary.py index 179c96697733..efda8b56c351 100644 --- a/synapse/handlers/room_summary.py +++ b/synapse/handlers/room_summary.py @@ -568,7 +568,7 @@ async def _is_local_room_accessible( room_version.msc3787_knock_restricted_join_rule and join_rule == JoinRules.KNOCK_RESTRICTED ) - ): + ): return True # Include the room if it is peekable. From 3e96272968fc5d586e15da4dec15478a4bd06c9c Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 3 May 2022 20:03:18 -0600 Subject: [PATCH 5/5] Add MSC3787 to complement tests --- scripts-dev/complement.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts-dev/complement.sh b/scripts-dev/complement.sh index e0feba05fa4f..4b72a5d9df23 100755 --- a/scripts-dev/complement.sh +++ b/scripts-dev/complement.sh @@ -64,4 +64,4 @@ docker build -t $COMPLEMENT_BASE_IMAGE -f "docker/complement/$COMPLEMENT_DOCKERF # Run the tests! echo "Images built; running complement" cd "$COMPLEMENT_DIR" -go test -v -tags synapse_blacklist,msc2716,msc3030,faster_joins -count=1 "$@" ./tests/... +go test -v -tags synapse_blacklist,msc2716,msc3030,faster_joins,msc3787 -count=1 "$@" ./tests/...