feat: add JSON REST API under /api/v1/

Phase 6 — JSON API:
- POST /api/v1/auth/login — returns session token
- POST /api/v1/auth/logout
- GET/POST /api/v1/faves — list own faves (paginated), create fave
- GET/PUT/DELETE /api/v1/faves/{id} — get, update, delete fave
- GET /api/v1/tags?q= — search tags
- GET /api/v1/users/{username} — public profile
- GET /api/v1/users/{username}/faves — public faves (paginated)
- GET /api/v1/export/json — export own faves
- POST /api/v1/import — import faves from JSON

All endpoints return JSON. Auth via session cookie (same as web UI).
Privacy-aware: private faves hidden from non-owners.
Respects profile visibility settings.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ole-Morten Duesund 2026-03-29 16:13:23 +02:00
commit fe4c751289
2 changed files with 470 additions and 0 deletions

View file

@ -16,6 +16,7 @@ import (
"kode.naiv.no/olemd/favoritter/internal/config"
"kode.naiv.no/olemd/favoritter/internal/database"
"kode.naiv.no/olemd/favoritter/internal/handler"
"kode.naiv.no/olemd/favoritter/internal/handler/api"
"kode.naiv.no/olemd/favoritter/internal/middleware"
"kode.naiv.no/olemd/favoritter/internal/render"
"kode.naiv.no/olemd/favoritter/internal/store"
@ -104,8 +105,18 @@ func main() {
Renderer: renderer,
})
// Register JSON API routes on the same mux.
apiHandler := api.New(api.Deps{
Config: cfg,
Users: users,
Sessions: sessions,
Faves: faves,
Tags: tags,
})
// Build the middleware chain.
mux := h.Routes()
apiHandler.Routes(mux)
chain := middleware.Chain(
mux,
middleware.Recovery,