mirror of
https://mau.dev/maunium/synapse.git
synced 2024-11-11 20:42:23 +01:00
Stabilize the threads API. (#14175)
Stabilize the threads API (MSC3856) by supporting (only) the v1 path for the endpoint. This also marks the API as safe for workers since it is a read-only API.
This commit is contained in:
parent
9ff4155f6c
commit
c3e4edb4d6
7 changed files with 35 additions and 29 deletions
|
@ -1 +1 @@
|
||||||
Experimental support for [MSC3856](https://github.com/matrix-org/matrix-spec-proposals/pull/3856): threads list API.
|
Support for [MSC3856](https://github.com/matrix-org/matrix-spec-proposals/pull/3856): threads list API.
|
||||||
|
|
1
changelog.d/14175.feature
Normal file
1
changelog.d/14175.feature
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Support for [MSC3856](https://github.com/matrix-org/matrix-spec-proposals/pull/3856): threads list API.
|
|
@ -118,6 +118,7 @@ WORKERS_CONFIG: Dict[str, Dict[str, Any]] = {
|
||||||
"^/_matrix/client/(api/v1|r0|v3|unstable)/rooms/.*/state$",
|
"^/_matrix/client/(api/v1|r0|v3|unstable)/rooms/.*/state$",
|
||||||
"^/_matrix/client/v1/rooms/.*/hierarchy$",
|
"^/_matrix/client/v1/rooms/.*/hierarchy$",
|
||||||
"^/_matrix/client/(v1|unstable)/rooms/.*/relations/",
|
"^/_matrix/client/(v1|unstable)/rooms/.*/relations/",
|
||||||
|
"^/_matrix/client/v1/rooms/.*/threads$",
|
||||||
"^/_matrix/client/(api/v1|r0|v3|unstable)/login$",
|
"^/_matrix/client/(api/v1|r0|v3|unstable)/login$",
|
||||||
"^/_matrix/client/(api/v1|r0|v3|unstable)/account/3pid$",
|
"^/_matrix/client/(api/v1|r0|v3|unstable)/account/3pid$",
|
||||||
"^/_matrix/client/(api/v1|r0|v3|unstable)/account/whoami$",
|
"^/_matrix/client/(api/v1|r0|v3|unstable)/account/whoami$",
|
||||||
|
|
|
@ -204,6 +204,7 @@ information.
|
||||||
^/_matrix/client/(api/v1|r0|v3|unstable)/rooms/.*/state$
|
^/_matrix/client/(api/v1|r0|v3|unstable)/rooms/.*/state$
|
||||||
^/_matrix/client/v1/rooms/.*/hierarchy$
|
^/_matrix/client/v1/rooms/.*/hierarchy$
|
||||||
^/_matrix/client/(v1|unstable)/rooms/.*/relations/
|
^/_matrix/client/(v1|unstable)/rooms/.*/relations/
|
||||||
|
^/_matrix/client/v1/rooms/.*/threads$
|
||||||
^/_matrix/client/unstable/org.matrix.msc2716/rooms/.*/batch_send$
|
^/_matrix/client/unstable/org.matrix.msc2716/rooms/.*/batch_send$
|
||||||
^/_matrix/client/unstable/im.nheko.summary/rooms/.*/summary$
|
^/_matrix/client/unstable/im.nheko.summary/rooms/.*/summary$
|
||||||
^/_matrix/client/(r0|v3|unstable)/account/3pid$
|
^/_matrix/client/(r0|v3|unstable)/account/3pid$
|
||||||
|
|
|
@ -101,9 +101,6 @@ class ExperimentalConfig(Config):
|
||||||
# MSC3848: Introduce errcodes for specific event sending failures
|
# MSC3848: Introduce errcodes for specific event sending failures
|
||||||
self.msc3848_enabled: bool = experimental.get("msc3848_enabled", False)
|
self.msc3848_enabled: bool = experimental.get("msc3848_enabled", False)
|
||||||
|
|
||||||
# MSC3856: Threads list API
|
|
||||||
self.msc3856_enabled: bool = experimental.get("msc3856_enabled", False)
|
|
||||||
|
|
||||||
# MSC3852: Expose last seen user agent field on /_matrix/client/v3/devices.
|
# MSC3852: Expose last seen user agent field on /_matrix/client/v3/devices.
|
||||||
self.msc3852_enabled: bool = experimental.get("msc3852_enabled", False)
|
self.msc3852_enabled: bool = experimental.get("msc3852_enabled", False)
|
||||||
|
|
||||||
|
|
|
@ -82,11 +82,7 @@ class RelationPaginationServlet(RestServlet):
|
||||||
|
|
||||||
|
|
||||||
class ThreadsServlet(RestServlet):
|
class ThreadsServlet(RestServlet):
|
||||||
PATTERNS = (
|
PATTERNS = (re.compile("^/_matrix/client/v1/rooms/(?P<room_id>[^/]*)/threads"),)
|
||||||
re.compile(
|
|
||||||
"^/_matrix/client/unstable/org.matrix.msc3856/rooms/(?P<room_id>[^/]*)/threads"
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
def __init__(self, hs: "HomeServer"):
|
def __init__(self, hs: "HomeServer"):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
@ -126,5 +122,4 @@ class ThreadsServlet(RestServlet):
|
||||||
|
|
||||||
def register_servlets(hs: "HomeServer", http_server: HttpServer) -> None:
|
def register_servlets(hs: "HomeServer", http_server: HttpServer) -> None:
|
||||||
RelationPaginationServlet(hs).register(http_server)
|
RelationPaginationServlet(hs).register(http_server)
|
||||||
if hs.config.experimental.msc3856_enabled:
|
ThreadsServlet(hs).register(http_server)
|
||||||
ThreadsServlet(hs).register(http_server)
|
|
||||||
|
|
|
@ -1710,7 +1710,15 @@ class RelationRedactionTestCase(BaseRelationsTestCase):
|
||||||
|
|
||||||
|
|
||||||
class ThreadsTestCase(BaseRelationsTestCase):
|
class ThreadsTestCase(BaseRelationsTestCase):
|
||||||
@unittest.override_config({"experimental_features": {"msc3856_enabled": True}})
|
def _get_threads(self, body: JsonDict) -> List[Tuple[str, str]]:
|
||||||
|
return [
|
||||||
|
(
|
||||||
|
ev["event_id"],
|
||||||
|
ev["unsigned"]["m.relations"]["m.thread"]["latest_event"]["event_id"],
|
||||||
|
)
|
||||||
|
for ev in body["chunk"]
|
||||||
|
]
|
||||||
|
|
||||||
def test_threads(self) -> None:
|
def test_threads(self) -> None:
|
||||||
"""Create threads and ensure the ordering is due to their latest event."""
|
"""Create threads and ensure the ordering is due to their latest event."""
|
||||||
# Create 2 threads.
|
# Create 2 threads.
|
||||||
|
@ -1718,32 +1726,37 @@ class ThreadsTestCase(BaseRelationsTestCase):
|
||||||
res = self.helper.send(self.room, body="Thread Root!", tok=self.user_token)
|
res = self.helper.send(self.room, body="Thread Root!", tok=self.user_token)
|
||||||
thread_2 = res["event_id"]
|
thread_2 = res["event_id"]
|
||||||
|
|
||||||
self._send_relation(RelationTypes.THREAD, "m.room.test")
|
channel = self._send_relation(RelationTypes.THREAD, "m.room.test")
|
||||||
self._send_relation(RelationTypes.THREAD, "m.room.test", parent_id=thread_2)
|
reply_1 = channel.json_body["event_id"]
|
||||||
|
channel = self._send_relation(
|
||||||
|
RelationTypes.THREAD, "m.room.test", parent_id=thread_2
|
||||||
|
)
|
||||||
|
reply_2 = channel.json_body["event_id"]
|
||||||
|
|
||||||
# Request the threads in the room.
|
# Request the threads in the room.
|
||||||
channel = self.make_request(
|
channel = self.make_request(
|
||||||
"GET",
|
"GET",
|
||||||
f"/_matrix/client/unstable/org.matrix.msc3856/rooms/{self.room}/threads",
|
f"/_matrix/client/v1/rooms/{self.room}/threads",
|
||||||
access_token=self.user_token,
|
access_token=self.user_token,
|
||||||
)
|
)
|
||||||
self.assertEquals(200, channel.code, channel.json_body)
|
self.assertEquals(200, channel.code, channel.json_body)
|
||||||
thread_roots = [ev["event_id"] for ev in channel.json_body["chunk"]]
|
threads = self._get_threads(channel.json_body)
|
||||||
self.assertEqual(thread_roots, [thread_2, thread_1])
|
self.assertEqual(threads, [(thread_2, reply_2), (thread_1, reply_1)])
|
||||||
|
|
||||||
# Update the first thread, the ordering should swap.
|
# Update the first thread, the ordering should swap.
|
||||||
self._send_relation(RelationTypes.THREAD, "m.room.test")
|
channel = self._send_relation(RelationTypes.THREAD, "m.room.test")
|
||||||
|
reply_3 = channel.json_body["event_id"]
|
||||||
|
|
||||||
channel = self.make_request(
|
channel = self.make_request(
|
||||||
"GET",
|
"GET",
|
||||||
f"/_matrix/client/unstable/org.matrix.msc3856/rooms/{self.room}/threads",
|
f"/_matrix/client/v1/rooms/{self.room}/threads",
|
||||||
access_token=self.user_token,
|
access_token=self.user_token,
|
||||||
)
|
)
|
||||||
self.assertEquals(200, channel.code, channel.json_body)
|
self.assertEquals(200, channel.code, channel.json_body)
|
||||||
thread_roots = [ev["event_id"] for ev in channel.json_body["chunk"]]
|
# Tuple of (thread ID, latest event ID) for each thread.
|
||||||
self.assertEqual(thread_roots, [thread_1, thread_2])
|
threads = self._get_threads(channel.json_body)
|
||||||
|
self.assertEqual(threads, [(thread_1, reply_3), (thread_2, reply_2)])
|
||||||
|
|
||||||
@unittest.override_config({"experimental_features": {"msc3856_enabled": True}})
|
|
||||||
def test_pagination(self) -> None:
|
def test_pagination(self) -> None:
|
||||||
"""Create threads and paginate through them."""
|
"""Create threads and paginate through them."""
|
||||||
# Create 2 threads.
|
# Create 2 threads.
|
||||||
|
@ -1757,7 +1770,7 @@ class ThreadsTestCase(BaseRelationsTestCase):
|
||||||
# Request the threads in the room.
|
# Request the threads in the room.
|
||||||
channel = self.make_request(
|
channel = self.make_request(
|
||||||
"GET",
|
"GET",
|
||||||
f"/_matrix/client/unstable/org.matrix.msc3856/rooms/{self.room}/threads?limit=1",
|
f"/_matrix/client/v1/rooms/{self.room}/threads?limit=1",
|
||||||
access_token=self.user_token,
|
access_token=self.user_token,
|
||||||
)
|
)
|
||||||
self.assertEquals(200, channel.code, channel.json_body)
|
self.assertEquals(200, channel.code, channel.json_body)
|
||||||
|
@ -1771,7 +1784,7 @@ class ThreadsTestCase(BaseRelationsTestCase):
|
||||||
|
|
||||||
channel = self.make_request(
|
channel = self.make_request(
|
||||||
"GET",
|
"GET",
|
||||||
f"/_matrix/client/unstable/org.matrix.msc3856/rooms/{self.room}/threads?limit=1&from={next_batch}",
|
f"/_matrix/client/v1/rooms/{self.room}/threads?limit=1&from={next_batch}",
|
||||||
access_token=self.user_token,
|
access_token=self.user_token,
|
||||||
)
|
)
|
||||||
self.assertEquals(200, channel.code, channel.json_body)
|
self.assertEquals(200, channel.code, channel.json_body)
|
||||||
|
@ -1780,7 +1793,6 @@ class ThreadsTestCase(BaseRelationsTestCase):
|
||||||
|
|
||||||
self.assertNotIn("next_batch", channel.json_body, channel.json_body)
|
self.assertNotIn("next_batch", channel.json_body, channel.json_body)
|
||||||
|
|
||||||
@unittest.override_config({"experimental_features": {"msc3856_enabled": True}})
|
|
||||||
def test_include(self) -> None:
|
def test_include(self) -> None:
|
||||||
"""Filtering threads to all or participated in should work."""
|
"""Filtering threads to all or participated in should work."""
|
||||||
# Thread 1 has the user as the root event.
|
# Thread 1 has the user as the root event.
|
||||||
|
@ -1807,7 +1819,7 @@ class ThreadsTestCase(BaseRelationsTestCase):
|
||||||
# All threads in the room.
|
# All threads in the room.
|
||||||
channel = self.make_request(
|
channel = self.make_request(
|
||||||
"GET",
|
"GET",
|
||||||
f"/_matrix/client/unstable/org.matrix.msc3856/rooms/{self.room}/threads",
|
f"/_matrix/client/v1/rooms/{self.room}/threads",
|
||||||
access_token=self.user_token,
|
access_token=self.user_token,
|
||||||
)
|
)
|
||||||
self.assertEquals(200, channel.code, channel.json_body)
|
self.assertEquals(200, channel.code, channel.json_body)
|
||||||
|
@ -1819,14 +1831,13 @@ class ThreadsTestCase(BaseRelationsTestCase):
|
||||||
# Only participated threads.
|
# Only participated threads.
|
||||||
channel = self.make_request(
|
channel = self.make_request(
|
||||||
"GET",
|
"GET",
|
||||||
f"/_matrix/client/unstable/org.matrix.msc3856/rooms/{self.room}/threads?include=participated",
|
f"/_matrix/client/v1/rooms/{self.room}/threads?include=participated",
|
||||||
access_token=self.user_token,
|
access_token=self.user_token,
|
||||||
)
|
)
|
||||||
self.assertEquals(200, channel.code, channel.json_body)
|
self.assertEquals(200, channel.code, channel.json_body)
|
||||||
thread_roots = [ev["event_id"] for ev in channel.json_body["chunk"]]
|
thread_roots = [ev["event_id"] for ev in channel.json_body["chunk"]]
|
||||||
self.assertEqual(thread_roots, [thread_2, thread_1], channel.json_body)
|
self.assertEqual(thread_roots, [thread_2, thread_1], channel.json_body)
|
||||||
|
|
||||||
@unittest.override_config({"experimental_features": {"msc3856_enabled": True}})
|
|
||||||
def test_ignored_user(self) -> None:
|
def test_ignored_user(self) -> None:
|
||||||
"""Events from ignored users should be ignored."""
|
"""Events from ignored users should be ignored."""
|
||||||
# Thread 1 has a reply from an ignored user.
|
# Thread 1 has a reply from an ignored user.
|
||||||
|
@ -1852,7 +1863,7 @@ class ThreadsTestCase(BaseRelationsTestCase):
|
||||||
# Only thread 1 is returned.
|
# Only thread 1 is returned.
|
||||||
channel = self.make_request(
|
channel = self.make_request(
|
||||||
"GET",
|
"GET",
|
||||||
f"/_matrix/client/unstable/org.matrix.msc3856/rooms/{self.room}/threads",
|
f"/_matrix/client/v1/rooms/{self.room}/threads",
|
||||||
access_token=self.user_token,
|
access_token=self.user_token,
|
||||||
)
|
)
|
||||||
self.assertEquals(200, channel.code, channel.json_body)
|
self.assertEquals(200, channel.code, channel.json_body)
|
||||||
|
|
Loading…
Reference in a new issue