From e8060a4ef7dd2d980f152892f903c6dfc79b7a4b Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Thu, 1 Jul 2021 14:26:51 -0400 Subject: [PATCH 1/7] Show joinable rooms in the spaces summary. --- changelog.d/10298.feature | 1 + synapse/handlers/space_summary.py | 49 +++++++++++++------- tests/handlers/test_space_summary.py | 67 ++++++++++++++++++++++++---- 3 files changed, 93 insertions(+), 24 deletions(-) create mode 100644 changelog.d/10298.feature diff --git a/changelog.d/10298.feature b/changelog.d/10298.feature new file mode 100644 index 000000000000..7059db507512 --- /dev/null +++ b/changelog.d/10298.feature @@ -0,0 +1 @@ +The spaces summary API now returns any joinable rooms, not only rooms which are world-readable. diff --git a/synapse/handlers/space_summary.py b/synapse/handlers/space_summary.py index b585057ec3a5..facc31a00296 100644 --- a/synapse/handlers/space_summary.py +++ b/synapse/handlers/space_summary.py @@ -24,6 +24,7 @@ EventContentFields, EventTypes, HistoryVisibility, + JoinRules, Membership, RoomTypes, ) @@ -420,9 +421,8 @@ async def _is_room_accessible( It should be included if: - * The requester is joined or invited to the room. - * The requester can join without an invite (per MSC3083). - * The origin server has any user that is joined or invited to the room. + * The requester is joined or can join the room (per MSC3173). + * The origin server has any user that is joined or can join the room. * The history visibility is set to world readable. Args: @@ -446,8 +446,30 @@ async def _is_room_accessible( room_version = await self._store.get_room_version(room_id) - # if we have an authenticated requesting user, first check if they are able to view - # stripped state in the room. + # Include the room if it has join rules of public or knock. + join_rules_event_id = state_ids.get((EventTypes.JoinRules, "")) + 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 + ): + return True + + # Include the room if it is peekable. + hist_vis_event_id = state_ids.get((EventTypes.RoomHistoryVisibility, "")) + if hist_vis_event_id: + hist_vis_ev = await self._store.get_event(hist_vis_event_id) + hist_vis = hist_vis_ev.content.get("history_visibility") + if hist_vis == HistoryVisibility.WORLD_READABLE: + return True + + # Otherwise we need to check information specific to the user or server. + + # If we have an authenticated requesting user, check if they are a member + # of the room (or can join the room). if requester: member_event_id = state_ids.get((EventTypes.Member, requester), None) @@ -470,11 +492,14 @@ async def _is_room_accessible( return True # If this is a request over federation, check if the host is in the room or - # is in one of the spaces specified via the join rules. + # has a user who could join the room. elif origin: if await self._event_auth_handler.check_host_in_room(room_id, origin): return True + # TODO This does not handle if a server has a pending invite to the + # room. + # Alternately, if the host has a user in any of the spaces specified # for access, then the host can see this room (and should do filtering # if the requester cannot see it). @@ -490,18 +515,10 @@ async def _is_room_accessible( ): return True - # otherwise, check if the room is peekable - hist_vis_event_id = state_ids.get((EventTypes.RoomHistoryVisibility, ""), None) - if hist_vis_event_id: - hist_vis_ev = await self._store.get_event(hist_vis_event_id) - hist_vis = hist_vis_ev.content.get("history_visibility") - if hist_vis == HistoryVisibility.WORLD_READABLE: - return True - logger.info( - "room %s is unpeekable and user %s is not a member / not allowed to join, omitting from summary", + "room %s is unpeekable and requester %s is not a member / not allowed to join, omitting from summary", room_id, - requester, + requester or origin, ) return False diff --git a/tests/handlers/test_space_summary.py b/tests/handlers/test_space_summary.py index 9771d3fb3b48..fbee532ae908 100644 --- a/tests/handlers/test_space_summary.py +++ b/tests/handlers/test_space_summary.py @@ -14,7 +14,13 @@ from typing import Any, Iterable, Optional, Tuple from unittest import mock -from synapse.api.constants import EventContentFields, RoomTypes +from synapse.api.constants import ( + EventContentFields, + EventTypes, + HistoryVisibility, + JoinRules, + RoomTypes, +) from synapse.api.errors import AuthError from synapse.handlers.space_summary import _child_events_comparison_key from synapse.rest import admin @@ -117,7 +123,7 @@ def _add_child(self, space_id: str, room_id: str, token: str) -> None: """Add a child room to a space.""" self.helper.send_state( space_id, - event_type="m.space.child", + event_type=EventTypes.SpaceChild, body={"via": [self.hs.hostname]}, tok=token, state_key=room_id, @@ -148,7 +154,11 @@ def test_simple_space(self): self._assert_events(result, [(self.space, self.room)]) def test_visibility(self): - """A user not in a space cannot inspect it.""" + """ + A user not in a space cannot inspect it. + + Once in the space, they only see joined & joinable rooms. + """ user2 = self.register_user("user2", "pass") token2 = self.login("user2", "pass") @@ -159,22 +169,63 @@ def test_visibility(self): self.helper.join(self.space, user2, tok=token2) result = self.get_success(self.handler.get_space_summary(user2, self.space)) - # The result should only have the space, but includes the link to the room. + # The result should have the space and room. + self._assert_rooms(result, [self.space, self.room]) + self._assert_events(result, [(self.space, self.room)]) + + # Make the room's state only viewable to those in it. + self.helper.send_state( + self.room, + event_type=EventTypes.RoomHistoryVisibility, + body={"history_visibility": HistoryVisibility.JOINED}, + tok=self.token, + ) + + # If the room is made invite-only, it disappears... + self.helper.send_state( + self.room, + event_type=EventTypes.JoinRules, + body={"join_rule": JoinRules.INVITE}, + tok=self.token, + ) + result = self.get_success(self.handler.get_space_summary(user2, self.space)) self._assert_rooms(result, [self.space]) self._assert_events(result, [(self.space, self.room)]) + # Until the user has an invite. + self.helper.invite(self.room, targ=user2, tok=self.token) + result = self.get_success(self.handler.get_space_summary(user2, self.space)) + self._assert_rooms(result, [self.space, self.room]) + self._assert_events(result, [(self.space, self.room)]) + + # Or joins it. + self.helper.join(self.room, user2, tok=token2) + result = self.get_success(self.handler.get_space_summary(user2, self.space)) + self._assert_rooms(result, [self.space, self.room]) + self._assert_events(result, [(self.space, self.room)]) + def test_world_readable(self): - """A world-readable room is visible to everyone.""" + """A world-readable space is visible to everyone.""" self.helper.send_state( self.space, - event_type="m.room.history_visibility", - body={"history_visibility": "world_readable"}, + event_type=EventTypes.JoinRules, + body={"join_rule": JoinRules.INVITE}, tok=self.token, ) user2 = self.register_user("user2", "pass") + # The space should not be visible. + self.get_failure(self.handler.get_space_summary(user2, self.space), AuthError) + + self.helper.send_state( + self.space, + event_type=EventTypes.RoomHistoryVisibility, + body={"history_visibility": HistoryVisibility.WORLD_READABLE}, + tok=self.token, + ) + # The space should be visible, as well as the link to the room. result = self.get_success(self.handler.get_space_summary(user2, self.space)) - self._assert_rooms(result, [self.space]) + self._assert_rooms(result, [self.space, self.room]) self._assert_events(result, [(self.space, self.room)]) From d7b277426519a68860bf1863209dfcfe84e55a8f Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Fri, 2 Jul 2021 07:49:24 -0400 Subject: [PATCH 2/7] Review comments. --- synapse/handlers/space_summary.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/synapse/handlers/space_summary.py b/synapse/handlers/space_summary.py index facc31a00296..57940ecd3210 100644 --- a/synapse/handlers/space_summary.py +++ b/synapse/handlers/space_summary.py @@ -451,10 +451,8 @@ async def _is_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 + if join_rule == JoinRules.PUBLIC or ( + room_version.msc2403_knocking and join_rule == JoinRules.KNOCK ): return True From 70c0b5c80708c7570c9b7e574a92140810c6ec50 Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Fri, 2 Jul 2021 08:01:37 -0400 Subject: [PATCH 3/7] Check the join rule returned over federation. --- synapse/handlers/space_summary.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/synapse/handlers/space_summary.py b/synapse/handlers/space_summary.py index 57940ecd3210..981649659ab9 100644 --- a/synapse/handlers/space_summary.py +++ b/synapse/handlers/space_summary.py @@ -151,14 +151,21 @@ async def get_space_summary( # The room should only be included in the summary if: # a. the user is in the room; # b. the room is world readable; or - # c. the user is in a space that has been granted access to - # the room. + # c. the user could join the room, e.g. the join rules + # are set to public or the user is in a space that + # has been granted access to the room. # # Note that we know the user is not in the root room (which is # why the remote call was made in the first place), but the user # could be in one of the children rooms and we just didn't know # about the link. - include_room = room.get("world_readable") is True + + # The API doesn't return the room version so assume that a + # join rule of knock is valid. + include_room = ( + room.get("join_rules") in (JoinRules.PUBLIC, JoinRules.KNOCK) + or room.get("world_readable") is True + ) # Check if the user is a member of any of the allowed spaces # from the response. @@ -550,6 +557,7 @@ async def _build_room_entry(self, room_id: str) -> JsonDict: "canonical_alias": stats["canonical_alias"], "num_joined_members": stats["joined_members"], "avatar_url": stats["avatar"], + "join_rules": stats["join_rules"], "world_readable": ( stats["history_visibility"] == HistoryVisibility.WORLD_READABLE ), From 1922d02afd1d2291338f4bbdffd112c34b5edc0c Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Fri, 2 Jul 2021 12:17:41 -0400 Subject: [PATCH 4/7] Update tests for filtering federation results. --- tests/handlers/test_space_summary.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/handlers/test_space_summary.py b/tests/handlers/test_space_summary.py index 44b048b0b8fa..81ff5e9c6ce9 100644 --- a/tests/handlers/test_space_summary.py +++ b/tests/handlers/test_space_summary.py @@ -343,6 +343,8 @@ def test_fed_filtering(self): subspace = "#subspace:" + fed_hostname # Create a few rooms which will have different properties. + public_room = "#public:" + fed_hostname + knock_room = "#knock:" + fed_hostname restricted_room = "#restricted:" + fed_hostname restricted_accessible_room = "#restricted_accessible:" + fed_hostname world_readable_room = "#world_readable:" + fed_hostname @@ -353,6 +355,18 @@ async def summarize_remote_room( ): # Note that these entries are brief, but should contain enough info. rooms = [ + { + "room_id": public_room, + "world_readable": False, + "join_rules": JoinRules.PUBLIC, + "allowed_spaces": [], + }, + { + "room_id": knock_room, + "world_readable": False, + "join_rules": JoinRules.KNOCK, + "allowed_spaces": [], + }, { "room_id": restricted_room, "world_readable": False, @@ -415,6 +429,8 @@ async def summarize_remote_room( self.space, self.room, subspace, + public_room, + knock_room, restricted_accessible_room, world_readable_room, joined_room, @@ -425,6 +441,8 @@ async def summarize_remote_room( [ (self.space, self.room), (self.space, subspace), + (subspace, public_room), + (subspace, knock_room), (subspace, restricted_room), (subspace, restricted_accessible_room), (subspace, world_readable_room), From b7b8c28fbb10bc7d136af8a27c86d6263e211c10 Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Fri, 2 Jul 2021 12:35:59 -0400 Subject: [PATCH 5/7] Test more situations for local rooms. --- tests/handlers/test_space_summary.py | 136 ++++++++++++++++++--------- 1 file changed, 93 insertions(+), 43 deletions(-) diff --git a/tests/handlers/test_space_summary.py b/tests/handlers/test_space_summary.py index 81ff5e9c6ce9..61d0c3d5bd71 100644 --- a/tests/handlers/test_space_summary.py +++ b/tests/handlers/test_space_summary.py @@ -19,9 +19,11 @@ EventTypes, HistoryVisibility, JoinRules, + RestrictedJoinRuleTypes, RoomTypes, ) from synapse.api.errors import AuthError +from synapse.api.room_versions import RoomVersions from synapse.handlers.space_summary import _child_events_comparison_key from synapse.rest import admin from synapse.rest.client.v1 import login, room @@ -154,81 +156,129 @@ def test_simple_space(self): self._assert_events(result, [(self.space, self.room)]) def test_visibility(self): - """ - A user not in a space cannot inspect it. - - Once in the space, they only see joined & joinable rooms. - """ + """A user not in a space cannot inspect it.""" user2 = self.register_user("user2", "pass") token2 = self.login("user2", "pass") # The user cannot see the space. self.get_failure(self.handler.get_space_summary(user2, self.space), AuthError) - # Joining the room causes it to be visible. - self.helper.join(self.space, user2, tok=token2) + # If the space is made world-readable it should return a result. + self.helper.send_state( + self.space, + event_type=EventTypes.RoomHistoryVisibility, + body={"history_visibility": HistoryVisibility.WORLD_READABLE}, + tok=self.token, + ) result = self.get_success(self.handler.get_space_summary(user2, self.space)) - - # The result should have the space and room. self._assert_rooms(result, [self.space, self.room]) self._assert_events(result, [(self.space, self.room)]) - # Make the room's state only viewable to those in it. + # Make it not world-readable again and confirm it results in an error. self.helper.send_state( - self.room, + self.space, event_type=EventTypes.RoomHistoryVisibility, body={"history_visibility": HistoryVisibility.JOINED}, tok=self.token, ) + self.get_failure(self.handler.get_space_summary(user2, self.space), AuthError) - # If the room is made invite-only, it disappears... - self.helper.send_state( - self.room, - event_type=EventTypes.JoinRules, - body={"join_rule": JoinRules.INVITE}, - tok=self.token, - ) - result = self.get_success(self.handler.get_space_summary(user2, self.space)) - self._assert_rooms(result, [self.space]) - self._assert_events(result, [(self.space, self.room)]) - - # Until the user has an invite. - self.helper.invite(self.room, targ=user2, tok=self.token) - result = self.get_success(self.handler.get_space_summary(user2, self.space)) - self._assert_rooms(result, [self.space, self.room]) - self._assert_events(result, [(self.space, self.room)]) - - # Or joins it. - self.helper.join(self.room, user2, tok=token2) + # Join the space and results should be returned. + self.helper.join(self.space, user2, tok=token2) result = self.get_success(self.handler.get_space_summary(user2, self.space)) self._assert_rooms(result, [self.space, self.room]) self._assert_events(result, [(self.space, self.room)]) - def test_world_readable(self): - """A world-readable space is visible to everyone.""" - self.helper.send_state( - self.space, - event_type=EventTypes.JoinRules, - body={"join_rule": JoinRules.INVITE}, + def _create_room_with_join_rule( + self, join_rule: str, room_version: Optional[str] = None, **extra_content + ) -> str: + """Create a room with the given join rule and add it to the space.""" + room_id = self.helper.create_room_as( + self.user, + room_version=room_version, tok=self.token, + extra_content={ + "initial_state": [ + { + "type": EventTypes.JoinRules, + "state_key": "", + "content": { + "join_rule": join_rule, + **extra_content, + }, + } + ] + }, ) + self._add_child(self.space, room_id, self.token) + return room_id + def test_filtering(self): + """ + Rooms should be properly filtered to only include rooms the user has access to. + """ user2 = self.register_user("user2", "pass") + token2 = self.login("user2", "pass") - # The space should not be visible. - self.get_failure(self.handler.get_space_summary(user2, self.space), AuthError) - + # Create a few rooms which will have different properties. + public_room = self._create_room_with_join_rule(JoinRules.PUBLIC) + knock_room = self._create_room_with_join_rule( + JoinRules.KNOCK, room_version=RoomVersions.V7.identifier + ) + restricted_room = self._create_room_with_join_rule( + JoinRules.MSC3083_RESTRICTED, + room_version=RoomVersions.MSC3083.identifier, + allow=[], + ) + restricted_accessible_room = self._create_room_with_join_rule( + JoinRules.MSC3083_RESTRICTED, + room_version=RoomVersions.MSC3083.identifier, + allow=[ + { + "type": RestrictedJoinRuleTypes.ROOM_MEMBERSHIP, + "room_id": self.space, + "via": [self.hs.hostname], + } + ], + ) + world_readable_room = self._create_room_with_join_rule(JoinRules.INVITE) self.helper.send_state( - self.space, + world_readable_room, event_type=EventTypes.RoomHistoryVisibility, body={"history_visibility": HistoryVisibility.WORLD_READABLE}, tok=self.token, ) + joined_room = self._create_room_with_join_rule(JoinRules.PUBLIC) + self.helper.join(joined_room, user2, tok=token2) - # The space should be visible, as well as the link to the room. + # Join the space. + self.helper.join(self.space, user2, tok=token2) result = self.get_success(self.handler.get_space_summary(user2, self.space)) - self._assert_rooms(result, [self.space, self.room]) - self._assert_events(result, [(self.space, self.room)]) + + self._assert_rooms( + result, + [ + self.space, + self.room, + public_room, + knock_room, + restricted_accessible_room, + world_readable_room, + joined_room, + ], + ) + self._assert_events( + result, + [ + (self.space, self.room), + (self.space, public_room), + (self.space, knock_room), + (self.space, restricted_room), + (self.space, restricted_accessible_room), + (self.space, world_readable_room), + (self.space, joined_room), + ], + ) def test_complex_space(self): """ From 5a5ab5b28b99f6565ca432239305e4e6c78f8795 Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Fri, 2 Jul 2021 12:55:56 -0400 Subject: [PATCH 6/7] Ensure that invited rooms are properly included. --- synapse/handlers/space_summary.py | 13 ++++-- synapse/storage/databases/main/roommember.py | 13 +++++- tests/handlers/test_space_summary.py | 48 ++++++++++++++++++-- 3 files changed, 65 insertions(+), 9 deletions(-) diff --git a/synapse/handlers/space_summary.py b/synapse/handlers/space_summary.py index 981649659ab9..366e6211e56d 100644 --- a/synapse/handlers/space_summary.py +++ b/synapse/handlers/space_summary.py @@ -448,6 +448,12 @@ async def _is_room_accessible( # If there's no state for the room, it isn't known. if not state_ids: + # The user might have a pending invite for the room. + if requester and await self._store.get_invite_for_local_user_in_room( + requester, room_id + ): + return True + logger.info("room %s is unknown, omitting from summary", room_id) return False @@ -499,12 +505,11 @@ async def _is_room_accessible( # If this is a request over federation, check if the host is in the room or # has a user who could join the room. elif origin: - if await self._event_auth_handler.check_host_in_room(room_id, origin): + if await self._event_auth_handler.check_host_in_room( + room_id, origin + ) or await self._store.is_host_invited(room_id, origin): return True - # TODO This does not handle if a server has a pending invite to the - # room. - # Alternately, if the host has a user in any of the spaces specified # for access, then the host can see this room (and should do filtering # if the requester cannot see it). diff --git a/synapse/storage/databases/main/roommember.py b/synapse/storage/databases/main/roommember.py index 2796354a1f58..4d82c4c26d0f 100644 --- a/synapse/storage/databases/main/roommember.py +++ b/synapse/storage/databases/main/roommember.py @@ -703,13 +703,22 @@ async def _get_joined_profiles_from_event_ids(self, event_ids: Iterable[str]): @cached(max_entries=10000) async def is_host_joined(self, room_id: str, host: str) -> bool: + return await self._check_host_room_membership(room_id, host, Membership.JOIN) + + @cached(max_entries=10000) + async def is_host_invited(self, room_id: str, host: str) -> bool: + return await self._check_host_room_membership(room_id, host, Membership.INVITE) + + async def _check_host_room_membership( + self, room_id: str, host: str, membership: str + ) -> bool: if "%" in host or "_" in host: raise Exception("Invalid host name") sql = """ SELECT state_key FROM current_state_events AS c INNER JOIN room_memberships AS m USING (event_id) - WHERE m.membership = 'join' + WHERE m.membership = ? AND type = 'm.room.member' AND c.room_id = ? AND state_key LIKE ? @@ -722,7 +731,7 @@ async def is_host_joined(self, room_id: str, host: str) -> bool: like_clause = "%:" + host rows = await self.db_pool.execute( - "is_host_joined", None, sql, room_id, like_clause + "is_host_joined", None, sql, membership, room_id, like_clause ) if not rows: diff --git a/tests/handlers/test_space_summary.py b/tests/handlers/test_space_summary.py index 61d0c3d5bd71..3f73ad7f9478 100644 --- a/tests/handlers/test_space_summary.py +++ b/tests/handlers/test_space_summary.py @@ -19,11 +19,13 @@ EventTypes, HistoryVisibility, JoinRules, + Membership, RestrictedJoinRuleTypes, RoomTypes, ) from synapse.api.errors import AuthError from synapse.api.room_versions import RoomVersions +from synapse.events import make_event_from_dict from synapse.handlers.space_summary import _child_events_comparison_key from synapse.rest import admin from synapse.rest.client.v1 import login, room @@ -225,6 +227,9 @@ def test_filtering(self): knock_room = self._create_room_with_join_rule( JoinRules.KNOCK, room_version=RoomVersions.V7.identifier ) + not_invited_room = self._create_room_with_join_rule(JoinRules.INVITE) + invited_room = self._create_room_with_join_rule(JoinRules.INVITE) + self.helper.invite(invited_room, targ=user2, tok=self.token) restricted_room = self._create_room_with_join_rule( JoinRules.MSC3083_RESTRICTED, room_version=RoomVersions.MSC3083.identifier, @@ -248,7 +253,8 @@ def test_filtering(self): body={"history_visibility": HistoryVisibility.WORLD_READABLE}, tok=self.token, ) - joined_room = self._create_room_with_join_rule(JoinRules.PUBLIC) + joined_room = self._create_room_with_join_rule(JoinRules.INVITE) + self.helper.invite(joined_room, targ=user2, tok=self.token) self.helper.join(joined_room, user2, tok=token2) # Join the space. @@ -262,6 +268,7 @@ def test_filtering(self): self.room, public_room, knock_room, + invited_room, restricted_accessible_room, world_readable_room, joined_room, @@ -273,6 +280,8 @@ def test_filtering(self): (self.space, self.room), (self.space, public_room), (self.space, knock_room), + (self.space, not_invited_room), + (self.space, invited_room), (self.space, restricted_room), (self.space, restricted_accessible_room), (self.space, world_readable_room), @@ -395,11 +404,33 @@ def test_fed_filtering(self): # Create a few rooms which will have different properties. public_room = "#public:" + fed_hostname knock_room = "#knock:" + fed_hostname + not_invited_room = "#not_invited:" + fed_hostname + invited_room = "#invited:" + fed_hostname restricted_room = "#restricted:" + fed_hostname restricted_accessible_room = "#restricted_accessible:" + fed_hostname world_readable_room = "#world_readable:" + fed_hostname joined_room = self.helper.create_room_as(self.user, tok=self.token) + # Poke an invite over federation into the database. + fed_handler = self.hs.get_federation_handler() + event = make_event_from_dict( + { + "room_id": invited_room, + "event_id": "!abcd:" + fed_hostname, + "type": EventTypes.Member, + "sender": "@remote:" + fed_hostname, + "state_key": self.user, + "content": {"membership": Membership.INVITE}, + "prev_events": [], + "auth_events": [], + "depth": 1, + "origin_server_ts": 1234, + } + ) + self.get_success( + fed_handler.on_invite_request(fed_hostname, event, RoomVersions.V6) + ) + async def summarize_remote_room( _self, room, suggested_only, max_children, exclude_rooms ): @@ -409,13 +440,21 @@ async def summarize_remote_room( "room_id": public_room, "world_readable": False, "join_rules": JoinRules.PUBLIC, - "allowed_spaces": [], }, { "room_id": knock_room, "world_readable": False, "join_rules": JoinRules.KNOCK, - "allowed_spaces": [], + }, + { + "room_id": not_invited_room, + "world_readable": False, + "join_rules": JoinRules.INVITE, + }, + { + "room_id": invited_room, + "world_readable": False, + "join_rules": JoinRules.INVITE, }, { "room_id": restricted_room, @@ -481,6 +520,7 @@ async def summarize_remote_room( subspace, public_room, knock_room, + invited_room, restricted_accessible_room, world_readable_room, joined_room, @@ -493,6 +533,8 @@ async def summarize_remote_room( (self.space, subspace), (subspace, public_room), (subspace, knock_room), + (subspace, not_invited_room), + (subspace, invited_room), (subspace, restricted_room), (subspace, restricted_accessible_room), (subspace, world_readable_room), From 49cbfb1a71d127786686db26f7f4f81c7d42d378 Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Tue, 13 Jul 2021 07:42:50 -0400 Subject: [PATCH 7/7] Rework changelog entry. --- changelog.d/10305.feature | 1 + changelog.d/10305.misc | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 changelog.d/10305.feature delete mode 100644 changelog.d/10305.misc diff --git a/changelog.d/10305.feature b/changelog.d/10305.feature new file mode 100644 index 000000000000..7059db507512 --- /dev/null +++ b/changelog.d/10305.feature @@ -0,0 +1 @@ +The spaces summary API now returns any joinable rooms, not only rooms which are world-readable. diff --git a/changelog.d/10305.misc b/changelog.d/10305.misc deleted file mode 100644 index 8488d47f6fc3..000000000000 --- a/changelog.d/10305.misc +++ /dev/null @@ -1 +0,0 @@ -Additional unit tests for the spaces summary API.