feat(share): public share-link surface for playlists (Phase 1.g.1)#25
Conversation
Adds three endpoints split across the auth-vs-public boundary the
streaming module already uses:
- POST /api/v1/profiles/{p}/playlists/{pl}/share (JWT) — mints (or
echoes) an opaque 32-char URL-safe token. Idempotent via
COALESCE(share_token, $candidate) so a race between two parallel
mints lands a single value and both callers receive it.
- DELETE /api/v1/profiles/{p}/playlists/{pl}/share (JWT) — clears
the token, instantly closing the public URL.
- GET /api/v1/share/playlists/{token} (no auth) — public preview
with name + description + cover + brand tokens. tracks: [] until
server-side playlist_track materialisation lands in 1.g.2.
Tenant ownership is verified inline in every helper (user_id ->
profile_id -> playlist) so a proxy attack against a foreign
playlist surfaces as 404 with no existence leak.
Partial UNIQUE on share_token allows the vast majority of private
playlists to skip the index pages. 7 integration tests cover the
mint/revoke/public-get matrix incl. proxy attack + 401 gate.
Signed-off-by: InstaZDLL <github.105mh@8shield.net>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (6)
📝 WalkthroughRésuméCette PR ajoute une API complète de partage public de playlists via des jetons opaques. Les playlists peuvent être partagées (mint idempotent d'un jeton), révoquées immédiatement, et lues publiquement sans authentification JWT. Le jeton sert d'authentification implicite pour la lecture anonyme. Tous les endpoints sont testés end-to-end incluant isolation multi-tenant, contrôles d'authentification, et validations de non-fuite de données tenant. ModificationsPartage public de playlists
Diagrammes de séquencesequenceDiagram
participant User
participant API
participant DB
User->>API: POST /profiles/{profile_id}/playlists/{playlist_id}/share (JWT)
API->>DB: mint_or_get_token(user_id, profile_id, playlist_id)
DB-->>API: Ok(Some(token)) ou Ok(None) si accès refusé
API-->>User: 200 {token} ou 404
User->>API: DELETE /profiles/{profile_id}/playlists/{playlist_id}/share (JWT)
API->>DB: revoke_token(user_id, profile_id, playlist_id)
DB-->>API: Ok(true) ou Ok(false)
API-->>User: 204 ou 404
User->>API: GET /api/v1/share/playlists/{token} (sans JWT)
API->>DB: fetch_public_by_token(token)
DB-->>API: Ok(Some(metadata)) ou Ok(None)
API-->>User: 200 {playlist} ou 404
Estimation d'effort de revue🎯 3 (Modéré) | ⏱️ ~25 minutes PRs potentiellement liées
Poème
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
Summary
Phase 1.g.1 — the server side of the playlist sharing loop. Mints opaque share tokens, exposes a public read endpoint, and instant-revoke. Mirror the auth/public split the streaming surface uses.
What lands
20260603000000_playlist_share_token.sql— adds `share_token TEXT` to `playlist` + a partial UNIQUE index (`WHERE share_token IS NOT NULL`) so private playlists don't pay index bloat.Scope choices
Test plan
Next: web (1.g.2) → `/p/$token` SSR route + OG tags. Then desktop (1.g.3) → `ShareModal` with QR code.
Summary by CodeRabbit
Notes de version
Nouvelles fonctionnalités
Tests