-
Notifications
You must be signed in to change notification settings - Fork 700
feat(api2): Prefer: securedrop=x limits response shape to minor version 2.x
#7703
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
Conversation
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.
Pull Request Overview
This PR implements API versioning support for the SecureDrop API v2, allowing clients to specify a preferred minor version via the Prefer header. The changes conditionally include or exclude certain fields based on the requested API minor version.
- Added
minorparameter toto_api_v2()methods across models to support versioning - Implemented version-based conditional field inclusion (e.g.,
interaction_countonly in v2.2+) - Added logic to filter top-level response keys based on API minor version
Reviewed Changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| securedrop/models.py | Updated to_api_v2() methods to accept minor parameter and conditionally include interaction_count field for API v2.2+ |
| securedrop/journalist_app/api2/init.py | Added API minor version handling via Prefer header, conditional event processing for v2.3+, and response filtering based on client version |
Comments suppressed due to low confidence (1)
securedrop/journalist_app/api2/init.py:142
- Missing
minorparameter insource.to_api_v2()call. This is inconsistent with other calls in the same function (lines 134, 149, 158, 165) and means sources requested directly won't respect the client's API version preference. Change tosource.to_api_v2(minor).
response.sources[source.uuid] = source.to_api_v2()
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
02fba8b to
d3fe688
Compare
671af27 to
e670850
Compare
Prefer: securedrop=x limits response shape to minor version 2.x/data): Prefer: securedrop=x limits response shape to minor version 2.x
|
|
||
| # Process events in snowflake order. | ||
| for event in sorted(events, key=lambda e: int(e.id)): | ||
| result = handler.process(event) |
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.
Event handlers will need to be passed minor so that they can version-check consistently:
- current_version = json_version(source.to_api_v2())
+ current_version = json_version(source.to_api_v2(minor))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.
maybe we have it as a member variable on handler and turn the event handlers into normal methods instead of static ones?
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.
I tried it out, and I realized that there's a separation I'd like to preserve, in order to keep the actual handler methods as close to pure functions on (event received, current server state) as possible.
securedrop/securedrop/journalist_app/api2/events.py
Lines 43 to 49 in f241f6b
| def __init__(self, session: Session, redis: Redis) -> None: | |
| """ | |
| Configure the `EventHandler`. Attributes set here are for internal use | |
| by the `EventHandler`; handler methods are static and do not have access | |
| to them, which means they cannot influence the processing of a given | |
| event. | |
| """ |
legoktm
left a comment
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.
Overall I like the direction; the conditionals are quite simple right now, if it does get much more complicated we might want to have some explicit serialization class.
|
|
||
| # Process events in snowflake order. | ||
| for event in sorted(events, key=lambda e: int(e.id)): | ||
| result = handler.process(event) |
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.
maybe we have it as a member variable on handler and turn the event handlers into normal methods instead of static ones?
44445c7 to
218f01b
Compare
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.
Pull Request Overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
cfcfdb5 to
00b1677
Compare
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.
Pull Request Overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
00b1677 to
f241f6b
Compare
/data): Prefer: securedrop=x limits response shape to minor version 2.xPrefer: securedrop=x limits v2 Journalist API response shape to minor version 2.x
7ef0e42 to
88d5991
Compare
Prefer: securedrop=x limits v2 Journalist API response shape to minor version 2.xapi2): Prefer: securedrop=x limits response shape to minor version 2.x
legoktm
left a comment
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.
Test plan checks out, LGTM. Left two nits, but if you don't want to address them, feel free to merge right away.
…sion 2.x This avoids overloading the "Accept" header's syntax for content negotiation, since we don't care about its caching semantics.
…ns 2.1 ‒ 2.3 Thanks to ChatGPT.[^1] [^1]: https://chatgpt.com/share/691635a8-09a0-800f-a35f-a7ae98f9131e
88d5991 to
e888fef
Compare
legoktm
left a comment
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.
Thanks!
Closes #7639 (see context there) by letting the client specify an API minor version for the response shape it expects. Currently we have four minor versions:
securedrop/securedrop/journalist_app/api2/__init__.py
Lines 30 to 34 in 00b1677
Test plan
Prefer: securedrop=xversions defined so far.developworks as expected without sending aPreferheader.Checklist
This change accounts for:
I will add to #7713 (or a follow-up) once this this is merged.