Nobody has started this yet — be first.
Business impact
A client rendering a single saved city (a "city details" view, or confirming a delete before it happens) has no way to fetch one city's record -- it has to fetch and filter the caller's entire saved-city list client-side just to check whether one id still exists and belongs to them, wasted work that won't scale if a user saves many cities.
Problem
cities.Store has Create, List, Delete -- no Get. No route for GET /cities/{id} exists; today that URL returns 405 Method Not Allowed (DELETE /cities/{id} is already registered, so the mux recognizes the path but not GET).
Current behavior
GET /cities/{id} returns 405 Method Not Allowed for any id, including the caller's own city, a city belonging to another user, and a nonexistent id.
Expected behavior
GET /cities/{id} returns the city if (and only if) it belongs to the requesting user (the same X-User-ID-header-based scoping every other cities endpoint already uses), 404 otherwise -- matching Delete's existing "scoped by user_id, not found otherwise" behavior exactly.
Steps to reproduce
curl -X POST http://localhost:8083/cities -H 'X-User-ID: alice' -d '{"name": "London"}' # -> {"id":1,...} curl http://localhost:8083/cities/1 -H 'X-User-ID: alice'
Why this matters
This is the same ownership-scoping discipline the rest of the project applies to weather-fetching concurrency and cache correctness, applied here to a plain CRUD read -- the WHERE clause (id = $1 AND user_id = $2) is the enforcement point, mirroring cities.Store.Delete a few lines above where this method belongs.
Suggested approach
Add a Store method alongside Delete with the same two-argument shape (userID, id) and an analogous WHERE clause, returning (City, error) with ErrNotFound on no match; add the handler and route the same way handleDeleteCity and DELETE /cities/{id} are wired in server.go/handlers.go.
Acceptance criteria
Verification
WD_TEST_DATABASE_URL=postgresql://... go test ./practicetickets/... -run TestTicket04 -v
Hints (0/2)
Try it without hints first — the reading is the exercise.
Working on this ticket
Work on a branch named for the ticket — that's what you'll submit.
Branch off your fork
$git checkout -b feat/city-getFix it and commit
Meet every acceptance criterion, and add a test that would have caught this.
Push the branch
$git push -u origin feat/city-getSubmit it below
Paste your fork URL and the branch name, with a short write-up of the root cause.
Questions
Ask about anything unclear in the ticket — the maintainer and anyone who has solved it can answer. Please don't post full solutions.
Sign in to ask a question or reply.
Sign inweather_dashboarddbappmockweatherWEATHER_API_BASE_URL=https://api.openweathermap.orgWEATHER_API_KEYdocker-compose.prod.ymlRun the project's own test suite:
make test # go test ./...
make test-race # go test -race ./... (includes the concurrency/partial-failure test)
Work the tickets in PRACTICE_TICKETS.md (TICKET-01 through TICKET-10); each names one Go test in practicetickets/:
./practice_tickets_run.sh # all 10, pass/fail summary
go test ./practicetickets/... -run TestTicket01 -v # a single ticket
go test -race ./practicetickets/... -run TestTicket10 -v # ticket 10 needs -race to observe its bug
Tickets 03, 04, 05, and 06 touch the saved-cities Postgres store and need a reachable test database, set via WD_TEST_DATABASE_URL (defaults to postgres://postgres:postgres@localhost:5436/weather_dashboard_test if unset). Tickets 01, 02, 07, 08, 09, and 10 need no database at all.
Level 2
Implement a feature
Extend the system within its own patterns.