Skip to content

Land Slices 11-13 into main (stacked-PR base gap) - #36

Merged
rghvgrv merged 4 commits into
mainfrom
slice-10-subscriptions-create
Jul 11, 2026
Merged

Land Slices 11-13 into main (stacked-PR base gap)#36
rghvgrv merged 4 commits into
mainfrom
slice-10-subscriptions-create

Conversation

@rghvgrv

@rghvgrv rghvgrv commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

What

Corrective PR. PR #35 (Slices 11-13: List/Get/Update/Delete) was based on and merged into the slice-10-subscriptions-create branch (stacked-PR pattern), not main. PR #34 (Slice 10: Create) had already merged into main separately before that, so there was no open PR left to carry #35's commits forward into main - they landed on slice-10-subscriptions-create only.

Net effect: issues #12, #13, #14 show closed (their branches said "Closes #N" and did merge - just into the wrong ultimate target), but GET /api/v1/subscriptions, GET /api/v1/subscriptions/{id}, PUT /api/v1/subscriptions/{id}, and DELETE /api/v1/subscriptions/{id} do not exist on main right now.

Changes

None beyond what #35 already contained and already reviewed - this PR is main <- slice-10-subscriptions-create, bringing in exactly the 3 commits main is missing:

  • 2a3af85 feat: add GET /api/v1/subscriptions (list) and GET /api/v1/subscriptions/{id}
  • 2d774a8 feat: add PUT /api/v1/subscriptions/{id} (update)
  • 12dc89b feat: add DELETE /api/v1/subscriptions/{id}

Verification

Already verified in #35 (52/52 tests passing, 0 warnings) - no new code, just landing it in the right place. Re-ran locally after git fetch to confirm the branch state before opening this.

rghvgrv and others added 4 commits July 12, 2026 04:09
…ons/{id}

Implements Slice 11: authenticated user can list their own subscriptions
and fetch a single one. GetById returns 404 (not 403) for another user's
record, to avoid leaking existence.

- ISubscriptionRepository.GetAllForUserAsync/GetByIdAsync: query directly
  into SubscriptionDto via a left-joined LINQ projection (categories,
  payment_sources, subscription_catalog) rather than loading entities and
  mapping separately - one SQL round trip, no N+1
- SubscriptionDto: extended with CategoryName, PaymentSourceLabel,
  CatalogLogoUrl (all nullable - the joins are left joins since category/
  payment_source/catalog_id are all optional on user_subscriptions)
- SubscriptionsController: added GetAll/GetById; Create now re-fetches
  through GetByIdAsync after insert so its 201 response has the same
  resolved shape as the read endpoints, instead of a bare unresolved DTO
- Extracted the repeated Guid.Parse(User.FindFirstValue(...)) into a
  private GetUserId() helper, used by all three actions now

Tests cover the 3 required cases plus unauthenticated-list, nonexistent-id,
and a dedicated test proving the category/payment-source/catalog joins
actually resolve names and the logo URL end to end.

Closes #12
Implements Slice 12: authenticated owner can update their subscription's
editable fields; 404 for another user's record; 400 on invalid payload.

Reuses CreateSubscriptionRequest (and its validator) as the update body
type rather than introducing a near-duplicate UpdateSubscriptionRequest -
the editable field set is identical, so a second type would just be the
first one copy-pasted. Directly satisfies the issue's "extract shared
rules if duplicated" by not duplicating the type in the first place.

ISubscriptionRepository.UpdateAsync loads the tracked entity scoped to
(id, user_id), applies the request fields, saves, then re-queries through
the same joined DTO projection GetByIdAsync uses so the response has
resolved category/payment-source/catalog fields like every other read.

Tests cover the 3 required cases plus a nonexistent-id 404 case.

Closes #13
Implements Slice 13: authenticated owner can delete their subscription;
404 for another user's record or an already-deleted one (not 500).

ISubscriptionRepository.DeleteAsync loads the tracked entity scoped to
(id, user_id) - same ownership pattern as UpdateAsync - and removes it if
found. This completes subscriptions CRUD (create/read/update/delete).

Tests cover the 3 required cases plus an attacker-can't-affect-owner's-
record proof and unauthenticated-request rejection.

Closes #14
Slices 11-13: Subscriptions — List, Get, Update, Delete
@rghvgrv
rghvgrv merged commit 72a5eb3 into main Jul 11, 2026
@rghvgrv
rghvgrv deleted the slice-10-subscriptions-create branch July 12, 2026 12:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant