-
Notifications
You must be signed in to change notification settings - Fork 520
Add an API to list changes to quarantine state of media #19558
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
Changes from all commits
9a1c92f
c3a0e4a
7386f04
0f782ce
f1a35fa
780f13a
a78c03c
7963593
d77a76d
2ef406e
86a6a15
62261e0
d743711
81ce22c
282e670
616e9c8
914e252
090e220
cb71d46
07ec8f4
d288ef5
471b3dc
b5eafbc
373ed83
e5791a3
067f659
99b4bf2
5a4ac32
5eac826
b755aae
c157697
dbc3445
6688723
237f0a6
190bda8
ef63a72
519512c
c36311a
8d6d9c8
2de3744
2325d9b
2558b61
7469b49
8255d7b
455f749
cbc6ec3
79b7a8a
6006bc1
f4f7369
4a7f8fa
bf589b7
61ed17f
1a5d3b8
0851400
44ddb62
3c1f0ea
da290fa
35ac9dc
b4e3755
f4bbc99
d17a8f2
af05ff3
8c34804
78beb96
53752b0
0d086a4
22d8370
1e94897
9f03d60
045dfec
af5dd7a
c78e67f
5269e19
62c533a
083c00f
51f9f0e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| Add a ["Listing quarantined media changes" Admin API](https://element-hq.github.io/synapse/latest/admin_api/media_admin_api.html#listing-quarantined-media-changes) for retrieving a paginated record of when media became (un)quarantined. | ||
|
MadLittleMods marked this conversation as resolved.
|
||
|
turt2live marked this conversation as resolved.
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -230,6 +230,70 @@ async def on_POST( | |
| return HTTPStatus.OK, {} | ||
|
|
||
|
|
||
| class ListQuarantineChanges(RestServlet): | ||
| """Lists the quarantine changes to media. | ||
|
|
||
| Uses the pagination format described by https://spec.matrix.org/v1.18/appendices/#pagination | ||
| """ | ||
|
|
||
| PATTERNS = admin_patterns("/media/quarantine_changes$") | ||
|
|
||
| def __init__(self, hs: "HomeServer"): | ||
| self.store = hs.get_datastores().main | ||
| self.auth = hs.get_auth() | ||
| self.server_name = hs.hostname | ||
| self.replication = hs.get_replication_data_handler() | ||
|
|
||
| async def on_GET(self, request: SynapseRequest) -> tuple[int, JsonDict]: | ||
| await assert_requester_is_admin(self.auth, request) | ||
|
|
||
| from_id = parse_integer(request, "from", default=0) | ||
|
MadLittleMods marked this conversation as resolved.
turt2live marked this conversation as resolved.
|
||
| limit = 100 # arbitrary; not enough to cause problems (hopefully) | ||
|
MadLittleMods marked this conversation as resolved.
|
||
| to_id = await self.store.get_current_quarantined_media_stream_id() | ||
|
|
||
| if to_id < from_id: | ||
| # The caller is trying to get future data, which isn't possible. | ||
| raise SynapseError( | ||
| HTTPStatus.BAD_REQUEST, | ||
| "The `from` position is ahead of the currently persisted position.", | ||
| errcode=Codes.INVALID_PARAM, | ||
| ) | ||
|
|
||
| # We need to wait to ensure that our current worker is actually caught up with | ||
| # the stream position, otherwise we might not return what we think we're returning. | ||
| if not await self.store.wait_for_quarantined_media_stream_id(from_id): | ||
| raise SynapseError( | ||
| HTTPStatus.INTERNAL_SERVER_ERROR, | ||
| "Timed out while waiting for the worker serving this request to catch up to the given " | ||
| "`from` stream position. Assuming this is a valid `from` token, this indicates an issue " | ||
| "with Synapse or the worker deployment lagging behind the replication stream. Please try " | ||
| "the request again later.", | ||
| errcode=Codes.UNKNOWN, | ||
| ) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ideally, we'd also validate This kind of thing is mentioned in #19644 "tokens should be validated before it reaches this point." There isn't a helper for this so it would be a similar Since this is an admin endpoint we could forgo this but it would be nice to have a good example in the codebase.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should be covered in 51f9f0e - let me know if changes are needed
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (will follow up in a subsequent PR if required)
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The I think we want to compare to
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We'd then need to wait for that token too, I believe?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess we don't - if we're caught up on
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
|
||
| changes = await self.store.get_quarantined_media_changes( | ||
| from_id=from_id, | ||
| to_id=to_id, | ||
| limit=limit, | ||
| ) | ||
|
|
||
| serialized_changes = [ | ||
| { | ||
| "origin": c.origin if c.origin is not None else self.server_name, | ||
| "media_id": c.media_id, | ||
| "quarantined": c.quarantined, | ||
| } | ||
| for c in changes | ||
| ] | ||
|
|
||
| # We know the last record will have the highest stream ID, so use that one. If | ||
| # there aren't any records, just return the `to_id` value because it'll be the | ||
| # furthest stream position possible. | ||
| next_batch = changes[-1].stream_id if len(changes) > 0 else to_id | ||
|
|
||
| return HTTPStatus.OK, {"next_batch": next_batch, "changes": serialized_changes} | ||
|
|
||
|
|
||
| class ProtectMediaByID(RestServlet): | ||
| """Protect local media from being quarantined.""" | ||
|
|
||
|
|
@@ -529,6 +593,7 @@ def register_servlets_for_media_repo(hs: "HomeServer", http_server: HttpServer) | |
| QuarantineMediaByID(hs).register(http_server) | ||
| UnquarantineMediaByID(hs).register(http_server) | ||
| QuarantineMediaByUser(hs).register(http_server) | ||
| ListQuarantineChanges(hs).register(http_server) | ||
| ProtectMediaByID(hs).register(http_server) | ||
| UnprotectMediaByID(hs).register(http_server) | ||
| ListMediaInRoom(hs).register(http_server) | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.