Implement message forward pagination from start when no from is given, fixes #12383 (#14149)

Fixes https://github.com/matrix-org/synapse/issues/12383
pull/14574/head
Benjamin Kampmann 2022-11-24 09:10:51 +00:00 committed by GitHub
parent 9af2be192a
commit f6c74d1cb2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 60 additions and 0 deletions

1
changelog.d/14149.bugfix Normal file
View File

@ -0,0 +1 @@
Fix #12383: paginate room messages from the start if no from is given. Contributed by @gnunicorn .

View File

@ -448,6 +448,12 @@ class PaginationHandler:
if pagin_config.from_token: if pagin_config.from_token:
from_token = pagin_config.from_token from_token = pagin_config.from_token
elif pagin_config.direction == "f":
from_token = (
await self.hs.get_event_sources().get_start_token_for_pagination(
room_id
)
)
else: else:
from_token = ( from_token = (
await self.hs.get_event_sources().get_current_token_for_pagination( await self.hs.get_event_sources().get_current_token_for_pagination(

View File

@ -73,6 +73,19 @@ class EventSources:
) )
return token return token
@trace
async def get_start_token_for_pagination(self, room_id: str) -> StreamToken:
"""Get the start token for a given room to be used to paginate
events.
The returned token does not have the current values for fields other
than `room`, since they are not used during pagination.
Returns:
The start token for pagination.
"""
return StreamToken.START
@trace @trace
async def get_current_token_for_pagination(self, room_id: str) -> StreamToken: async def get_current_token_for_pagination(self, room_id: str) -> StreamToken:
"""Get the current token for a given room to be used to paginate """Get the current token for a given room to be used to paginate

View File

@ -1857,6 +1857,46 @@ class RoomMessagesTestCase(unittest.HomeserverTestCase):
self.assertIn("chunk", channel.json_body) self.assertIn("chunk", channel.json_body)
self.assertIn("end", channel.json_body) self.assertIn("end", channel.json_body)
def test_room_messages_backward(self) -> None:
"""Test room messages can be retrieved by an admin that isn't in the room."""
latest_event_id = self.helper.send(
self.room_id, body="message 1", tok=self.user_tok
)["event_id"]
# Check that we get the first and second message when querying /messages.
channel = self.make_request(
"GET",
"/_synapse/admin/v1/rooms/%s/messages?dir=b" % (self.room_id,),
access_token=self.admin_user_tok,
)
self.assertEqual(channel.code, 200, channel.json_body)
chunk = channel.json_body["chunk"]
self.assertEqual(len(chunk), 6, [event["content"] for event in chunk])
# in backwards, this is the first event
self.assertEqual(chunk[0]["event_id"], latest_event_id)
def test_room_messages_forward(self) -> None:
"""Test room messages can be retrieved by an admin that isn't in the room."""
latest_event_id = self.helper.send(
self.room_id, body="message 1", tok=self.user_tok
)["event_id"]
# Check that we get the first and second message when querying /messages.
channel = self.make_request(
"GET",
"/_synapse/admin/v1/rooms/%s/messages?dir=f" % (self.room_id,),
access_token=self.admin_user_tok,
)
self.assertEqual(channel.code, 200, channel.json_body)
chunk = channel.json_body["chunk"]
self.assertEqual(len(chunk), 6, [event["content"] for event in chunk])
# in forward, this is the last event
self.assertEqual(chunk[5]["event_id"], latest_event_id)
def test_room_messages_purge(self) -> None: def test_room_messages_purge(self) -> None:
"""Test room messages can be retrieved by an admin that isn't in the room.""" """Test room messages can be retrieved by an admin that isn't in the room."""
store = self.hs.get_datastores().main store = self.hs.get_datastores().main