feat: add admin trip detail endpoint and user_id trip filter - #80
feat: add admin trip detail endpoint and user_id trip filter#80diveshpatil9104 wants to merge 1 commit into
Conversation
Code reviewNo issues found. Checked for bugs and CLAUDE.md compliance. 🤖 Generated with Claude Code |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Team Run ID: 📒 Files selected for processing (6)
Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review. 📝 WalkthroughWalkthroughThe change adds optional driver filtering to admin trip listings and adds an admin-only endpoint for retrieving a trip summary by ID. Handlers validate query and path parameters, map store errors to HTTP responses, and include route authorization tests. ChangesAdmin trip API
Estimated code review effort: 3 (Moderate) | ~20 minutes Merge Risk: ⚪ Minimal · up to This change adds admin-only trip retrieval and optional driver filtering for trip listings. No concrete merge-blocking risk remains. Sequence Diagram(s)sequenceDiagram
participant AdminClient
participant AdminRoute
participant handleGetTrip
participant TripSummaryGetter
AdminClient->>AdminRoute: GET /api/v1/admin/trips/{id}
AdminRoute->>handleGetTrip: pass path id
handleGetTrip->>TripSummaryGetter: request trip summary
TripSummaryGetter-->>handleGetTrip: return summary or store error
handleGetTrip-->>AdminClient: return JSON, 404, or 500
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
db/query.sql (1)
107-115: 🚀 Performance & Scalability | 🔵 TrivialPagination and filter performance risk on a growing
tripstable.ListTripsFiltereduses anIS NULL OR column = parampattern for optional filters and orders bystart_time DESC, while the HTTP layer allows an unboundedoffset. Together these can force full or large partial scans as the table grows.
db/query.sql#L107-L115: verify indexes exist to support thestatus/vehicle_id/user_idpredicates and thestart_time DESCsort; add composite indexes if missing.trip_list_handlers.go#L58-L67: capoffsetto a reasonable maximum, or plan a move to keyset (cursor-based) pagination once trip volume grows.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@db/query.sql` around lines 107 - 115, Improve pagination performance across db/query.sql lines 107-115 and trip_list_handlers.go lines 58-67: add or verify indexes supporting ListTripsFiltered’s status, vehicle_id, user_id filters and start_time DESC ordering, and cap the HTTP offset to a reasonable maximum while preserving existing filtering and limit behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@db/query.sql`:
- Around line 107-115: Improve pagination performance across db/query.sql lines
107-115 and trip_list_handlers.go lines 58-67: add or verify indexes supporting
ListTripsFiltered’s status, vehicle_id, user_id filters and start_time DESC
ordering, and cap the HTTP offset to a reasonable maximum while preserving
existing filtering and limit behavior.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 163cad48-8fd8-4a3d-9d1e-510463ec8e59
📒 Files selected for processing (12)
db/query.sqldb/query.sql.gomain.goroute_wiring_test.gostore_trips.gostore_trips_test.gotrip_handlers.gotrip_handlers_test.gotrip_list_handlers.gotrip_list_handlers_test.gotrip_list_store.gotrip_list_store_test.go
3f237cf to
1406ba8
Compare
Code reviewFound 1 issue:
Lines 83 to 87 in 1406ba8 🤖 Generated with Claude Code - If this code review was useful, please react with 👍. Otherwise, react with 👎. |
aaronbrethorst
left a comment
There was a problem hiding this comment.
Thank you for this, and apologies that it sat long enough for main to move underneath it. The code itself holds up well: both routes are correctly gated behind authMiddleware(adminMiddleware(...)) and covered by the route_wiring_test.go driver-rejected/admin-allowed tables, all SQL goes through sqlc so there is no injection surface, limit is capped, there is no N+1, and the ~28 tests are real tests. None of what follows is a criticism of the work.
The list half of this PR has been superseded. 6ba0338 landed GET /api/v1/admin/trips on main on 2026-08-24, eleven days after this branch's last commit, with a somewhat richer implementation (driver and vehicle label joins, a q search parameter, has_more, and a deterministic start_time DESC, id DESC ordering).
The important part: this is not only the merge conflict GitHub is showing you. The conflicting hunks are just main.go, db/query.sql.go and store_trips.go — but trip_list_handlers.go and trip_list_store.go are new files that git merges cleanly. So even after resolving every conflict textually, package main ends up with handleListTrips, TripLister, and (*Store).ListTrips each declared twice, which will not compile, plus a duplicate mux.Handle pattern that http.ServeMux panics on at startup. Resolving the conflicts is not enough here.
What is still genuinely new and worth keeping:
GET /api/v1/admin/trips/{id}—mainonly has/{id}/locations, there is no plain detail endpoint.- The
user_idfilter, which main's version does not have.
Could you rebase onto main and rescope this to just those two? Drop trip_list_store.go/trip_list_handlers.go in favor of extending the existing handleListTrips and TripLister in admin_live_handlers.go/store_trips.go. That should be a much smaller PR than this one and I would be glad to land it.
Two notes for the rescoped version, both matching patterns already in the repo: fetch limit+1 and report has_more rather than returning count: len(trips) (see location_history_handlers.go and admin_live_handlers.go), and give the ORDER BY a unique tiebreaker so LIMIT/OFFSET paging cannot skip or duplicate rows.
main gained GET /api/v1/admin/trips in 6ba0338, superseding the list endpoint this branch originally added. Keeping both would have declared handleListTrips, TripLister and (*Store).ListTrips twice and registered a duplicate mux pattern that http.ServeMux panics on at startup, so the list half is dropped rather than merged. What main still lacks, and what this keeps: - GET /api/v1/admin/trips/{id}, a trail-free trip detail endpoint. main only has /{id}/locations, which fetches up to 10k location points for callers that only want trip metadata. It reuses the existing GetTripSummary, so it adds no SQL, store method, or interface. - A user_id filter on the trips list, so an admin can review a single driver's history. A present user_id must be >= 1; 0 and negatives are rejected rather than silently collapsing into the "all drivers" sentinel and returning every trip. has_more via limit+1 and the ORDER BY t.start_time DESC, t.id DESC tiebreaker already come from main's implementation and are left intact.
1406ba8 to
8ca5e30
Compare
|
Thanks for the detailed review — and for spelling out that the duplicate declarations wouldn't surface as merge conflicts. That saved me from "resolving" this into something that doesn't compile. Rebased onto What's left is the two things
On your two notes — both already come from your implementation, so I left them alone rather than reimplementing them: The PR is now +238 lines (184 of them tests) against the original 977. Tests: 9 handler tests covering the filter passthrough, the rejected Both new routes are in the |
Summary
Adds the two pieces of admin trip functionality that
mainstill lacks after6ba0338landedGET /api/v1/admin/trips: a trip detail endpoint, and auser_idfilter on the trips list.This PR originally added a full list+get implementation. That was superseded mid-review, so it has been rescoped down to the remaining delta — from 977 lines to 238.
Endpoints
GET/api/v1/admin/trips/{id}GET/api/v1/admin/trips?user_id=Both are behind
authMiddleware(adminMiddleware(...))and covered by theroute_wiring_test.godriver-rejected / admin-allowed tables.Why these two
GET /api/v1/admin/trips/{id}—mainonly has/{id}/locations, which joins the trip summary to its full trail and is capped at 10k points. A caller that just wants trip metadata (status, driver, vehicle, times) shouldn't pay for that. This is the same handler shape minus the trail, reusing the existingGetTripSummary, so it adds no SQL, no store method, and no new interface —appStorealready embedsTripSummaryGetter.user_idfilter — lets an admin review one driver's history.main's list filters on status, vehicle, and a text query, but not driver.A present
user_idmust be >= 1.0and negatives are rejected with a 400 rather than falling through to the0= "all drivers" sentinel, which would silently return every trip instead of the caller's filter — the zero-value bug this avoids is covered by a test.What changed
Modified (4):
store_trips.go—UserIDfield onTripFilter, one condition inListTripsadmin_live_handlers.go—user_idparsing/validation inhandleListTrips; newhandleGetTripmain.go— one route registrationroute_wiring_test.go— new route in both admin wiring tablesTests (2):
admin_live_handlers_test.go— 9 tests: filter passthrough, absent/invaliduser_id, and the detail endpoint's happy path, omittedend_time, non-numeric id, not-found, nil-without-error guard, and store error (asserting the underlying error isn't leaked)store_trips_test.go—TestListTripsUserIDFilter: narrows to one driver, composes withstatus, returns empty for a driver with no trips, and treats0as no filterNotes on the review feedback
has_morevialimit+1and theORDER BY t.start_time DESC, t.id DESCtiebreaker both already exist inmain's implementation. Theuser_idfilter composes with the existing conditions and inherits both, so neither needed changing.Verified with
go fmt,go vet,go mod tidy, and the full suite run against a live Postgres so the DB integration tests execute rather than skip.