feat: add user feed centric subscription endpoints - #1807
Conversation
There was a problem hiding this comment.
Pull request overview
Adds “feed-centric” subscription read endpoints to the User Service so clients can retrieve notification subscriptions grouped by feed_stable_id, with feed metadata resolved at read time (and nullable when no longer resolvable).
Changes:
- Extended the User Service OpenAPI spec with
GET /v1/user/subscriptions/feedsandGET /v1/user/subscriptions/feeds/{id}, plus new response schemas for feed-grouped subscriptions. - Implemented the query/grouping logic in
UsersApiImpland introduced aSubscriptionFeedGroupImplmodel builder to assemble API models from ORM rows + resolved feed metadata. - Added unit + DB-backed tests for the new endpoints; updated documentation and performed minor Operations API spec formatting cleanup.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| docs/UserServiceAPI.yaml | Adds the two new endpoints and introduces FeedSubscriptionSummary / SubscriptionFeedGroup schemas. |
| docs/OperationsAPI.yaml | Reflows/cleans up description formatting in several schema fields. |
| docs/notifications-subscription-flows.md | Documents that {id} means “feed stable ID” for the new .../feeds/{id} endpoints. |
| api/tests/unittest/user_service/test_users_api_impl.py | Adds mock-based unit tests for feed-grouped subscription queries. |
| api/tests/unittest/user_service/test_subscription_feeds.py | Adds DB-backed tests validating grouping behavior, isolation per user, and null-metadata behavior. |
| api/src/user_service/impl/users_api_impl.py | Implements the two new endpoints and shared query/grouping helper. |
| api/src/shared/db_models/subscription_feed_group_impl.py | New helper model to construct SubscriptionFeedGroup responses from ORM subscriptions + metadata. |
| api/.openapi-generator/FILES | Tracks newly generated model files for OpenAPI generator output. |
Suppressed comments (1)
docs/UserServiceAPI.yaml:239
- This endpoint can return 403 for guest users (the implementation calls
_require_user_id()), but the OpenAPI responses only document 401/404. Also, since the implementation returns 404 based on “no subscription targets this feed” (not feeds-DB existence), the 404 description should avoid implying a feeds-DB existence check.
"401":
description: Unauthorized.
"404":
description: Feed not found, or the user has no subscription targeting it.
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
| "401": | ||
| description: Unauthorized. | ||
|
|
||
| /v1/user/subscriptions/feeds: |
There was a problem hiding this comment.
[question] aren't these endpoints duplicating what's in the user description endpoint? is it only to avoid having the ui group the information from /v1/user/subscriptions?
There was a problem hiding this comment.
It's the same information, but the response helps the consumer to get all the subscriptions from a specific feed without having to iterate over all subscriptions.
Summary:
Closes MobilityData/product-tasks#212
Adds two feed-centric read endpoints to the User Service API, so clients can ask "which feeds am I subscribed to?" instead of listing subscriptions and grouping client-side.
GET /v1/user/subscriptions/feeds— the feeds the caller has at least onenotification subscription targeting, each with the subscriptions that target it.
GET /v1/user/subscriptions/feeds/{id}— same shape for a single feed stable ID(note:
{id}here is a feed stable ID, e.g.mdb-1, not a subscription UUIDlike every other
/v1/user/subscriptions/{id}path).Both are read-only and additive; no existing endpoint, response shape, or DB column changes.
Changes
Spec (
docs/UserServiceAPI.yaml, +128)getUserSubscriptionFeeds/getUserSubscriptionFeedById.SubscriptionFeedGroup(feed_id + resolved metadata + nestedsubscriptions) and
FeedSubscriptionSummary(trimmed subscription view that omitsuser_idandfeeds, both redundant in this context).Implementation
api/src/user_service/impl/users_api_impl.py— the two handlers plus a shared_query_subscription_feed_groupshelper that joinsnotification_subscription_feed→notification_subscription, filters by theauthenticated user, orders by
(feed_stable_id, created_at), and groups in Python.api/src/shared/db_models/subscription_feed_group_impl.py— new impl wrapperbuilding the grouped view from ORM rows.
Behavior notes
Expected behavior:
activestate are included, matchingGET /v1/user/subscriptions.data_type,provider,feed_name) is resolved from the feeds DBat read time via
resolve_feed_metadata, not persisted. A feed that no longerexists there still appears, with those fields
null.404on the by-ID endpoint deliberately collapses "feed doesn't exist" and "userhas no subscription targeting it" — both are just "no matching join rows", so no
separate feeds-DB existence check is made.
403; results are scoped to the caller'suser_id.Testing tips:
This can be tested locally or in DEV. Below the response from dev(my account)
Request:
Response
Request:
Response
Request:
Response
Please make sure these boxes are checked before submitting your pull request - thanks!
./scripts/api-tests.shto make sure you didn't break anything