mirror of
https://git.anonymousland.org/anonymousland/synapse.git
synced 2025-08-10 23:10:10 -04:00
Implement MSC3827: Filtering of /publicRooms
by room type (#13031)
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
This commit is contained in:
parent
e714b8a057
commit
13e359aec8
11 changed files with 345 additions and 13 deletions
|
@ -18,7 +18,7 @@
|
|||
"""Tests REST events for /rooms paths."""
|
||||
|
||||
import json
|
||||
from typing import Any, Dict, Iterable, List, Optional, Union
|
||||
from typing import Any, Dict, Iterable, List, Optional, Tuple, Union
|
||||
from unittest.mock import Mock, call
|
||||
from urllib import parse as urlparse
|
||||
|
||||
|
@ -33,7 +33,9 @@ from synapse.api.constants import (
|
|||
EventContentFields,
|
||||
EventTypes,
|
||||
Membership,
|
||||
PublicRoomsFilterFields,
|
||||
RelationTypes,
|
||||
RoomTypes,
|
||||
)
|
||||
from synapse.api.errors import Codes, HttpResponseException
|
||||
from synapse.handlers.pagination import PurgeStatus
|
||||
|
@ -1858,6 +1860,90 @@ class PublicRoomsRestrictedTestCase(unittest.HomeserverTestCase):
|
|||
self.assertEqual(channel.code, 200, channel.result)
|
||||
|
||||
|
||||
class PublicRoomsRoomTypeFilterTestCase(unittest.HomeserverTestCase):
|
||||
|
||||
servlets = [
|
||||
synapse.rest.admin.register_servlets_for_client_rest_resource,
|
||||
room.register_servlets,
|
||||
login.register_servlets,
|
||||
]
|
||||
|
||||
def make_homeserver(self, reactor: MemoryReactor, clock: Clock) -> HomeServer:
|
||||
|
||||
config = self.default_config()
|
||||
config["allow_public_rooms_without_auth"] = True
|
||||
config["experimental_features"] = {"msc3827_enabled": True}
|
||||
self.hs = self.setup_test_homeserver(config=config)
|
||||
self.url = b"/_matrix/client/r0/publicRooms"
|
||||
|
||||
return self.hs
|
||||
|
||||
def prepare(self, reactor: MemoryReactor, clock: Clock, hs: HomeServer) -> None:
|
||||
user = self.register_user("alice", "pass")
|
||||
self.token = self.login(user, "pass")
|
||||
|
||||
# Create a room
|
||||
self.helper.create_room_as(
|
||||
user,
|
||||
is_public=True,
|
||||
extra_content={"visibility": "public"},
|
||||
tok=self.token,
|
||||
)
|
||||
# Create a space
|
||||
self.helper.create_room_as(
|
||||
user,
|
||||
is_public=True,
|
||||
extra_content={
|
||||
"visibility": "public",
|
||||
"creation_content": {EventContentFields.ROOM_TYPE: RoomTypes.SPACE},
|
||||
},
|
||||
tok=self.token,
|
||||
)
|
||||
|
||||
def make_public_rooms_request(
|
||||
self, room_types: Union[List[Union[str, None]], None]
|
||||
) -> Tuple[List[Dict[str, Any]], int]:
|
||||
channel = self.make_request(
|
||||
"POST",
|
||||
self.url,
|
||||
{"filter": {PublicRoomsFilterFields.ROOM_TYPES: room_types}},
|
||||
self.token,
|
||||
)
|
||||
chunk = channel.json_body["chunk"]
|
||||
count = channel.json_body["total_room_count_estimate"]
|
||||
|
||||
self.assertEqual(len(chunk), count)
|
||||
|
||||
return chunk, count
|
||||
|
||||
def test_returns_both_rooms_and_spaces_if_no_filter(self) -> None:
|
||||
chunk, count = self.make_public_rooms_request(None)
|
||||
|
||||
self.assertEqual(count, 2)
|
||||
|
||||
def test_returns_only_rooms_based_on_filter(self) -> None:
|
||||
chunk, count = self.make_public_rooms_request([None])
|
||||
|
||||
self.assertEqual(count, 1)
|
||||
self.assertEqual(chunk[0].get("org.matrix.msc3827.room_type", None), None)
|
||||
|
||||
def test_returns_only_space_based_on_filter(self) -> None:
|
||||
chunk, count = self.make_public_rooms_request(["m.space"])
|
||||
|
||||
self.assertEqual(count, 1)
|
||||
self.assertEqual(chunk[0].get("org.matrix.msc3827.room_type", None), "m.space")
|
||||
|
||||
def test_returns_both_rooms_and_space_based_on_filter(self) -> None:
|
||||
chunk, count = self.make_public_rooms_request(["m.space", None])
|
||||
|
||||
self.assertEqual(count, 2)
|
||||
|
||||
def test_returns_both_rooms_and_spaces_if_array_is_empty(self) -> None:
|
||||
chunk, count = self.make_public_rooms_request([])
|
||||
|
||||
self.assertEqual(count, 2)
|
||||
|
||||
|
||||
class PublicRoomsTestRemoteSearchFallbackTestCase(unittest.HomeserverTestCase):
|
||||
"""Test that we correctly fallback to local filtering if a remote server
|
||||
doesn't support search.
|
||||
|
@ -1882,7 +1968,7 @@ class PublicRoomsTestRemoteSearchFallbackTestCase(unittest.HomeserverTestCase):
|
|||
"Simple test for searching rooms over federation"
|
||||
self.federation_client.get_public_rooms.return_value = make_awaitable({}) # type: ignore[attr-defined]
|
||||
|
||||
search_filter = {"generic_search_term": "foobar"}
|
||||
search_filter = {PublicRoomsFilterFields.GENERIC_SEARCH_TERM: "foobar"}
|
||||
|
||||
channel = self.make_request(
|
||||
"POST",
|
||||
|
@ -1911,7 +1997,7 @@ class PublicRoomsTestRemoteSearchFallbackTestCase(unittest.HomeserverTestCase):
|
|||
make_awaitable({}),
|
||||
)
|
||||
|
||||
search_filter = {"generic_search_term": "foobar"}
|
||||
search_filter = {PublicRoomsFilterFields.GENERIC_SEARCH_TERM: "foobar"}
|
||||
|
||||
channel = self.make_request(
|
||||
"POST",
|
||||
|
|
|
@ -12,6 +12,9 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import json
|
||||
|
||||
from synapse.api.constants import RoomTypes
|
||||
from synapse.rest import admin
|
||||
from synapse.rest.client import login, room
|
||||
from synapse.storage.databases.main.room import _BackgroundUpdates
|
||||
|
@ -91,3 +94,69 @@ class RoomBackgroundUpdateStoreTestCase(HomeserverTestCase):
|
|||
)
|
||||
)
|
||||
self.assertEqual(room_creator_after, self.user_id)
|
||||
|
||||
def test_background_add_room_type_column(self):
|
||||
"""Test that the background update to populate the `room_type` column in
|
||||
`room_stats_state` works properly.
|
||||
"""
|
||||
|
||||
# Create a room without a type
|
||||
room_id = self._generate_room()
|
||||
|
||||
# Get event_id of the m.room.create event
|
||||
event_id = self.get_success(
|
||||
self.store.db_pool.simple_select_one_onecol(
|
||||
table="current_state_events",
|
||||
keyvalues={
|
||||
"room_id": room_id,
|
||||
"type": "m.room.create",
|
||||
},
|
||||
retcol="event_id",
|
||||
)
|
||||
)
|
||||
|
||||
# Fake a room creation event with a room type
|
||||
event = {
|
||||
"content": {
|
||||
"creator": "@user:server.org",
|
||||
"room_version": "9",
|
||||
"type": RoomTypes.SPACE,
|
||||
},
|
||||
"type": "m.room.create",
|
||||
}
|
||||
self.get_success(
|
||||
self.store.db_pool.simple_update(
|
||||
table="event_json",
|
||||
keyvalues={"event_id": event_id},
|
||||
updatevalues={"json": json.dumps(event)},
|
||||
desc="test",
|
||||
)
|
||||
)
|
||||
|
||||
# Insert and run the background update
|
||||
self.get_success(
|
||||
self.store.db_pool.simple_insert(
|
||||
"background_updates",
|
||||
{
|
||||
"update_name": _BackgroundUpdates.ADD_ROOM_TYPE_COLUMN,
|
||||
"progress_json": "{}",
|
||||
},
|
||||
)
|
||||
)
|
||||
|
||||
# ... and tell the DataStore that it hasn't finished all updates yet
|
||||
self.store.db_pool.updates._all_done = False
|
||||
|
||||
# Now let's actually drive the updates to completion
|
||||
self.wait_for_background_updates()
|
||||
|
||||
# Make sure the background update filled in the room type
|
||||
room_type_after = self.get_success(
|
||||
self.store.db_pool.simple_select_one_onecol(
|
||||
table="room_stats_state",
|
||||
keyvalues={"room_id": room_id},
|
||||
retcol="room_type",
|
||||
allow_none=True,
|
||||
)
|
||||
)
|
||||
self.assertEqual(room_type_after, RoomTypes.SPACE)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue