SansanandClaude Sonnet 5 7fbd403d30 Make the platform list shared across users; keep games private
Platforms no longer have a user_id: there's one global list, unique by
name, that every authenticated user reads from and writes to. Games are
unchanged - still private per user, still referencing platform_id.

- Migration: dropped platform.user_id and its FK, UNIQUE(user_id, name) ->
  UNIQUE(name), index on change_seq alone instead of (user_id, change_seq).
  Amended the one init migration in place rather than stacking a second one,
  since nothing is deployed yet.
- db/query.sql: platform queries no longer take a user_id parameter.
  DeletePlatform's NOT EXISTS guard already checked games from any user (it
  never filtered the subquery by user_id), so deleting a shared platform is
  correctly blocked by any user's games on it, not just the deleter's.
- routes.go: platform handlers still require auth (the list isn't public to
  anonymous requests) but no longer scope by user.
- Tests: updated the mocks for the new signatures, added
  TestListPlatformsIsSharedAcrossUsers.

Verified against a real Postgres: user A creates "PC", user B sees it
immediately, both can add games against it, each only sees their own
games, deleting the platform is blocked while either user has a game on
it, and the name stays globally unique.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-03 11:34:47 +02:00

Completed

A tracker for a video game collection: what you own, which platform it's on, your score for it, and whether (and when) you finished it.

Status

Each account has its own private collection. The API is usable; there's no GUI yet beyond two read-only clients (see below).

Running it

just docker-up    # starts Postgres and the API on :8080
just docker-down  # stops them

Or against a Postgres you already have running locally:

export DATABASE_URL="postgres://postgres:password@localhost:5432/gamedb?sslmode=disable"
just run-api

The API creates its database and runs migrations on startup if needed. Browse http://localhost:8080/docs for the generated API docs.

Using the API

# Register (also logs you in)
curl -X POST localhost:8080/api/auth/register -H 'Content-Type: application/json' \
  -d '{"email":"you@example.com","password":"a long password","name":"You"}'
# -> {"token": "...", "user": {...}}

TOKEN=... # the token from above

curl -X POST localhost:8080/api/platforms -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' -d '{"name":"PC"}'

curl localhost:8080/api/games -H "Authorization: Bearer $TOKEN"

A browser-based client can skip the Authorization header: register/login also set an httpOnly session cookie.

Other clients

  • just run-tui — a read-only terminal viewer of /games (no login yet)
  • just run-gui — a read-only raylib desktop viewer of /games (no login yet; planned to move to Fyne)

Development

just test   # go test ./...
just sqlc   # regenerate internal/db after changing db/query.sql or a migration

Schema changes go in db/migrations as a new <timestamp>_<name>.up.sql / .down.sql pair; sqlc.yaml reads the schema from that directory directly, so there's no separate schema file to keep in sync.

S
Description
No description provided
Readme
229 KiB
0 Stars 1 Watchers 0 Forks
v0.0.3
Latest
2026-10-03 20:24:31 +02:00
Languages
TypeScript 47.1%
Go 46.3%
HTML 2%
PLpgSQL 1.9%
Dockerfile 0.9%
Other 1.8%