-
Notifications
You must be signed in to change notification settings - Fork 395
Add an Admin API to fetch an event by ID #18963
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
+201
−0
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
edb2e18
add an admin API to fetch an event
H-Shay 996262f
newsfragment
H-Shay 472aaee
Merge branch 'develop' into shay/admin_event
H-Shay 8af1c33
fix lint
H-Shay c70d6f3
fix circular import
H-Shay 8536a4c
requested changes
H-Shay 1cbf632
don't return rejected events
H-Shay File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Add an Admin API to fetch an event by ID. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
# Fetch Event API | ||
|
||
The fetch event API allows admins to fetch an event regardless of their membership in the room it | ||
originated in. | ||
|
||
To use it, you will need to authenticate by providing an `access_token` | ||
for a server admin: see [Admin API](../usage/administration/admin_api/). | ||
|
||
Request: | ||
```http | ||
GET /_synapse/admin/v1/fetch_event/<event_id> | ||
``` | ||
|
||
The API returns a JSON body like the following: | ||
|
||
Response: | ||
```json | ||
{ | ||
"event": { | ||
"auth_events": [ | ||
"$WhLChbYg6atHuFRP7cUd95naUtc8L0f7fqeizlsUVvc", | ||
"$9Wj8dt02lrNEWweeq-KjRABUYKba0K9DL2liRvsAdtQ", | ||
"$qJxBFxBt8_ODd9b3pgOL_jXP98S_igc1_kizuPSZFi4" | ||
], | ||
"content": { | ||
"body": "Hey now", | ||
"msgtype": "m.text" | ||
}, | ||
"depth": 6, | ||
"event_id": "$hJ_kcXbVMcI82JDrbqfUJIHu61tJD86uIFJ_8hNHi7s", | ||
"hashes": { | ||
"sha256": "LiNw8DtrRVf55EgAH8R42Wz7WCJUqGsPt2We6qZO5Rg" | ||
}, | ||
"origin_server_ts": 799, | ||
"prev_events": [ | ||
"$cnSUrNMnC3Ywh9_W7EquFxYQjC_sT3BAAVzcUVxZq1g" | ||
], | ||
"room_id": "!aIhKToCqgPTBloWMpf:test", | ||
"sender": "@user:test", | ||
"signatures": { | ||
"test": { | ||
"ed25519:a_lPym": "7mqSDwK1k7rnw34Dd8Fahu0rhPW7jPmcWPRtRDoEN9Yuv+BCM2+Rfdpv2MjxNKy3AYDEBwUwYEuaKMBaEMiKAQ" | ||
} | ||
}, | ||
"type": "m.room.message", | ||
"unsigned": { | ||
"age_ts": 799 | ||
} | ||
} | ||
} | ||
``` | ||
|
||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
from http import HTTPStatus | ||
from typing import TYPE_CHECKING, Tuple | ||
|
||
from synapse.api.errors import NotFoundError | ||
from synapse.events.utils import ( | ||
SerializeEventConfig, | ||
format_event_raw, | ||
serialize_event, | ||
) | ||
from synapse.http.servlet import RestServlet | ||
from synapse.http.site import SynapseRequest | ||
from synapse.rest.admin import admin_patterns | ||
from synapse.rest.admin._base import assert_user_is_admin | ||
from synapse.storage.databases.main.events_worker import EventRedactBehaviour | ||
from synapse.types import JsonDict | ||
|
||
if TYPE_CHECKING: | ||
from synapse.server import HomeServer | ||
|
||
|
||
class EventRestServlet(RestServlet): | ||
""" | ||
Get an event that is known to the homeserver. | ||
The requester must have administrator access in Synapse. | ||
|
||
GET /_synapse/admin/v1/fetch_event/<event_id> | ||
returns: | ||
200 OK with event json if the event is known to the homeserver. Otherwise raises | ||
a NotFound error. | ||
|
||
Args: | ||
event_id: the id of the requested event. | ||
Returns: | ||
JSON blob of the event | ||
""" | ||
|
||
PATTERNS = admin_patterns("/fetch_event/(?P<event_id>[^/]*)$") | ||
|
||
def __init__(self, hs: "HomeServer"): | ||
self._auth = hs.get_auth() | ||
self._store = hs.get_datastores().main | ||
self._clock = hs.get_clock() | ||
|
||
async def on_GET( | ||
self, request: SynapseRequest, event_id: str | ||
) -> Tuple[int, JsonDict]: | ||
requester = await self._auth.get_user_by_req(request) | ||
await assert_user_is_admin(self._auth, requester) | ||
|
||
event = await self._store.get_event( | ||
event_id, | ||
EventRedactBehaviour.as_is, | ||
allow_none=True, | ||
) | ||
|
||
if event is None: | ||
raise NotFoundError("Event not found") | ||
|
||
config = SerializeEventConfig( | ||
as_client_event=False, | ||
event_format=format_event_raw, | ||
requester=requester, | ||
only_event_fields=None, | ||
include_stripped_room_state=True, | ||
include_admin_metadata=True, | ||
) | ||
res = {"event": serialize_event(event, self._clock.time_msec(), config=config)} | ||
|
||
return HTTPStatus.OK, res |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
from twisted.internet.testing import MemoryReactor | ||
|
||
import synapse.rest.admin | ||
from synapse.api.errors import Codes | ||
from synapse.rest.client import login, room | ||
from synapse.server import HomeServer | ||
from synapse.util.clock import Clock | ||
|
||
from tests import unittest | ||
|
||
|
||
class FetchEventTestCase(unittest.HomeserverTestCase): | ||
servlets = [ | ||
synapse.rest.admin.register_servlets, | ||
login.register_servlets, | ||
room.register_servlets, | ||
] | ||
|
||
def prepare(self, reactor: MemoryReactor, clock: Clock, hs: HomeServer) -> None: | ||
self.admin_user = self.register_user("admin", "pass", admin=True) | ||
self.admin_user_tok = self.login("admin", "pass") | ||
|
||
self.other_user = self.register_user("user", "pass") | ||
self.other_user_tok = self.login("user", "pass") | ||
|
||
self.room_id1 = self.helper.create_room_as( | ||
self.other_user, tok=self.other_user_tok, is_public=True | ||
) | ||
resp = self.helper.send(self.room_id1, body="Hey now", tok=self.other_user_tok) | ||
self.event_id = resp["event_id"] | ||
|
||
def test_no_auth(self) -> None: | ||
""" | ||
Try to get an event without authentication. | ||
""" | ||
channel = self.make_request( | ||
"GET", | ||
f"/_synapse/admin/v1/fetch_event/{self.event_id}", | ||
) | ||
|
||
self.assertEqual(401, channel.code, msg=channel.json_body) | ||
self.assertEqual(Codes.MISSING_TOKEN, channel.json_body["errcode"]) | ||
|
||
def test_requester_is_not_admin(self) -> None: | ||
""" | ||
If the user is not a server admin, an error 403 is returned. | ||
""" | ||
|
||
channel = self.make_request( | ||
"GET", | ||
f"/_synapse/admin/v1/fetch_event/{self.event_id}", | ||
access_token=self.other_user_tok, | ||
) | ||
|
||
self.assertEqual(403, channel.code, msg=channel.json_body) | ||
self.assertEqual(Codes.FORBIDDEN, channel.json_body["errcode"]) | ||
|
||
def test_fetch_event(self) -> None: | ||
""" | ||
Test that we can successfully fetch an event | ||
""" | ||
channel = self.make_request( | ||
"GET", | ||
f"/_synapse/admin/v1/fetch_event/{self.event_id}", | ||
access_token=self.admin_user_tok, | ||
) | ||
self.assertEqual(200, channel.code, msg=channel.json_body) | ||
self.assertEqual( | ||
channel.json_body["event"]["content"], | ||
{"body": "Hey now", "msgtype": "m.text"}, | ||
) | ||
self.assertEqual(channel.json_body["event"]["event_id"], self.event_id) | ||
self.assertEqual(channel.json_body["event"]["type"], "m.room.message") | ||
self.assertEqual(channel.json_body["event"]["sender"], self.other_user) |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Heads up this file wasn't added to SUMMARY.md, meaning the page wouldn't appear in the sidebar of the documentation website.
I did so in a commit during the 1.140.0rc1 release process.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh! Apologies for the oversight, thank you for adding it.