Repository: matrix-org/synapse

Issue:
all space members are able to see invite only rooms in spaces
### Description
After upgrading synapse from 1.34 to 1.35 (debian testing), space members with default power level in the space are able to see invite only rooms in the space's "Explore rooms"-view that they are not allowed to join.

### Steps to reproduce

- create a private space S with account A
- add/create a public room P in space S with account A
- add/create a room R in space S with account A set to:
  - "Who can access this room?": "Only people who have been invited"
  - "Who can read history?": "Members only (since they joined)"
- invite account B to space S

### Expected outcome
- account B is able to see room P in the "Explore rooms"-view of the space
- account B is *not* able to see room R in the "Explore rooms"-view

### Actual outcome
- account B is able to see room P in the "Explore rooms"-view and is able to join it.
- account B *is* able to see room R in the "Explore rooms"-view. However, when trying to join, account b is presented with the error message:
Failed to join room
You are not invited to this room.

As per https://gist.github.com/t3chguy/fdf541446d992d1fc96b8089b342fe7b#gistcomment-3755026, this does not seem to be the intended behavior.

### Version information
- **Homeserver**: matrix.pack.rocks (ran by me)
- **Version**:  1.35.0+bullseye1
- **Install method**: debs from https://matrix.org/packages/debian/
- **Platform**: qemu-VM on Debian 11, no containers involved
- **Default Room Version**: 6
I did set `experimental_features: { spaces_enabled: true }` in /etc/matrix-synapse/homeserver.yaml in 1.34 which is still present. Removing it does not change the behavior described above.



Discussion:
I observe something that fits this issue, but with a public space.

I think it's safe to say that not everyone who joins a public room should be able to see invite-only rooms. Even topic and avatar are shown!
It seems to happen when a user on a home server has access to Invite-Only rooms. Then other users from that same homeserver (without access) can see those rooms. 

This leads to the possibility that private rooms are displayed, but public rooms are not, if no user of your own home server is part of those rooms.
It also appears that it recurses down the whole tree, showing private rooms inside a private space inside a public one
Well, if room visibility in spaces is currently only dependent on whether another user on your Homeserver has access that doesn't surprise me. 

To my knowledge Spaces are more or less rooms, so whatever applies to private/invite only rooms should apply to spaces as well.
Thanks for the report. I'll take a look at it.
I was able to reproduce this -- thanks for the awesome steps! Note that it seems to only be an issue with users on the same homeserver.
This is a regression from all the refactoring done in #9922. 😢 

Resolving patch:
diff --git a/synapse/handlers/space_summary.py b/synapse/handlers/space_summary.py
--- a/synapse/handlers/space_summary.py
+++ b/synapse/handlers/space_summary.py
@@ -26,7 +26,6 @@
     HistoryVisibility,
     Membership,
 )
-from synapse.api.errors import AuthError
 from synapse.events import EventBase
 from synapse.events.utils import format_event_for_client_v2
 from synapse.types import JsonDict
@@ -456,16 +455,16 @@ async def _is_room_accessible(
                     return True
 
             # Otherwise, check if they should be allowed access via membership in a space.
-            try:
-                await self._event_auth_handler.check_restricted_join_rules(
-                    state_ids, room_version, requester, member_event
+            if self._event_auth_handler.has_restricted_join_rules(
+                state_ids, room_version
+            ):
+                allowed_spaces = (
+                    await self._event_auth_handler.get_spaces_that_allow_join(state_ids)
                 )
-            except AuthError:
-                # The user doesn't have access due to spaces, but might have access
-                # another way. Keep trying.
-                pass
-            else:
-                return True
+                if await self._event_auth_handler.is_user_in_rooms(
+                    allowed_spaces, requester
+                ):
+                    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.


Test patch: