diff --git a/synapse/config/room_directory.py b/synapse/config/room_directory.py
index 9b897abe3c..3322cf2eea 100644
--- a/synapse/config/room_directory.py
+++ b/synapse/config/room_directory.py
@@ -52,6 +52,10 @@ class RoomDirectoryConfig(Config):
)
]
+ self.allow_non_federated_in_public_rooms = config.get(
+ "allow_non_federated_in_public_rooms", True,
+ )
+
def default_config(self, config_dir_path, server_name, **kwargs):
return """
# The `alias_creation` option controls who's allowed to create aliases
@@ -110,6 +114,14 @@ class RoomDirectoryConfig(Config):
# alias: "*"
# room_id: "*"
# action: allow
+
+ # Specify whether rooms that only allow local users to join should be
+ # shown in the federation public room directory.
+ #
+ # Note that this does not affect the room directory shown to users on
+ # this homeserver, only those on other homeservers.
+ #
+ #allow_non_federated_in_public_rooms: True
"""
def is_alias_creation_allowed(self, user_id, room_id, alias):
diff --git a/synapse/federation/transport/server.py b/synapse/federation/transport/server.py
index a2396ab466..5ba94be2ec 100644
--- a/synapse/federation/transport/server.py
+++ b/synapse/federation/transport/server.py
@@ -736,7 +736,8 @@ class PublicRoomList(BaseFederationServlet):
data = yield self.handler.get_local_public_room_list(
limit, since_token,
- network_tuple=network_tuple
+ network_tuple=network_tuple,
+ from_federation=True,
)
defer.returnValue((200, data))
diff --git a/synapse/groups/groups_server.py b/synapse/groups/groups_server.py
index 633c865ed8..691752a30c 100644
--- a/synapse/groups/groups_server.py
+++ b/synapse/groups/groups_server.py
@@ -113,7 +113,7 @@ class GroupsServerHandler(object):
room_id = room_entry["room_id"]
joined_users = yield self.store.get_users_in_room(room_id)
entry = yield self.room_list_handler.generate_room_entry(
- room_id, len(joined_users),
+ room_id, True, len(joined_users),
with_alias=False, allow_private=True,
)
entry = dict(entry) # so we don't change whats cached
@@ -544,7 +544,7 @@ class GroupsServerHandler(object):
joined_users = yield self.store.get_users_in_room(room_id)
entry = yield self.room_list_handler.generate_room_entry(
- room_id, len(joined_users),
+ room_id, True, len(joined_users),
with_alias=False, allow_private=True,
)
diff --git a/synapse/handlers/room_list.py b/synapse/handlers/room_list.py
index 13e212d669..810c624c2b 100644
--- a/synapse/handlers/room_list.py
+++ b/synapse/handlers/room_list.py
@@ -47,10 +47,12 @@ class RoomListHandler(BaseHandler):
self.response_cache = ResponseCache(hs, "room_list")
self.remote_response_cache = ResponseCache(hs, "remote_room_list",
timeout_ms=30 * 1000)
+ self.config = hs.get_config()
def get_local_public_room_list(self, limit=None, since_token=None,
search_filter=None,
- network_tuple=EMPTY_THIRD_PARTY_ID,):
+ network_tuple=EMPTY_THIRD_PARTY_ID,
+ from_federation=False):
"""Generate a local public room list.
There are multiple different lists: the main one plus one per third
@@ -87,14 +89,15 @@ class RoomListHandler(BaseHandler):
return self.response_cache.wrap(
key,
self._get_public_room_list,
- limit, since_token, network_tuple=network_tuple,
+ limit, since_token,
+ network_tuple=network_tuple, from_federation=from_federation,
)
@defer.inlineCallbacks
def _get_public_room_list(self, limit=None, since_token=None,
search_filter=None,
network_tuple=EMPTY_THIRD_PARTY_ID,
- timeout=None,):
+ from_federation=False, timeout=None,):
if since_token and since_token != "END":
since_token = RoomListNextBatch.from_token(since_token)
else:
@@ -217,7 +220,8 @@ class RoomListHandler(BaseHandler):
yield concurrently_execute(
lambda r: self._append_room_entry_to_chunk(
r, rooms_to_num_joined[r],
- chunk, limit, search_filter
+ chunk, limit, search_filter,
+ from_federation=from_federation,
),
batch, 5,
)
@@ -288,7 +292,7 @@ class RoomListHandler(BaseHandler):
@defer.inlineCallbacks
def _append_room_entry_to_chunk(self, room_id, num_joined_users, chunk, limit,
- search_filter):
+ search_filter, from_federation=False):
"""Generate the entry for a room in the public room list and append it
to the `chunk` if it matches the search filter
"""
@@ -296,15 +300,33 @@ class RoomListHandler(BaseHandler):
# We've already got enough, so lets just drop it.
return
- result = yield self.generate_room_entry(room_id, num_joined_users)
+ if from_federation:
+ result = yield self.generate_room_entry(room_id,
+ self.config.allow_non_federated_in_public_rooms,
+ num_joined_users)
+ else:
+ result = yield self.generate_room_entry(room_id, True, num_joined_users)
if result and _matches_room_entry(result, search_filter):
chunk.append(result)
- @cachedInlineCallbacks(num_args=1, cache_context=True)
- def generate_room_entry(self, room_id, num_joined_users, cache_context,
- with_alias=True, allow_private=False):
+ @cachedInlineCallbacks(num_args=2, cache_context=True)
+ def generate_room_entry(self, room_id, allow_non_federated, num_joined_users,
+ cache_context, with_alias=True, allow_private=False):
"""Returns the entry for a room
+
+ Args:
+ room_id (str): The room's ID.
+ allow_non_federated (bool): Whether rooms with federation
+ disabled should be shown.
+ num_joined_users (int): Number of users in the room.
+ cache_context: Information for cached responses.
+ with_alias (bool): Whether to return the room's aliases in the result.
+ allow_private (bool): Whether invite-only rooms should be shown.
+
+ Returns:
+ Deferred[dict|None]: Returns a room entry as a dictionary, or None if this
+ room was determined not to be shown publicly.
"""
result = {
"room_id": room_id,
@@ -318,6 +340,7 @@ class RoomListHandler(BaseHandler):
event_map = yield self.store.get_events([
event_id for key, event_id in iteritems(current_state_ids)
if key[0] in (
+ EventTypes.Create,
EventTypes.JoinRules,
EventTypes.Name,
EventTypes.Topic,
@@ -334,12 +357,21 @@ class RoomListHandler(BaseHandler):
}
# Double check that this is actually a public room.
+
join_rules_event = current_state.get((EventTypes.JoinRules, ""))
if join_rules_event:
join_rule = join_rules_event.content.get("join_rule", None)
if not allow_private and join_rule and join_rule != JoinRules.PUBLIC:
defer.returnValue(None)
+ if not allow_non_federated:
+ # Disallow non-federated from appearing
+ create_event = current_state.get((EventTypes.Create, ""))
+ if create_event:
+ federate = create_event.content.get("m.federate", True)
+ if federate == False:
+ defer.returnValue(None)
+
if with_alias:
aliases = yield self.store.get_aliases_for_room(
room_id, on_invalidate=cache_context.invalidate
|