v2026.06.03 — Media3 like button + Bluetooth/UPnP picker + system playlist daily rotation #77
+12
-4
@@ -14,6 +14,8 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
|
||||
"git.fabledsword.com/bvandeusen/minstrel/internal/apierror"
|
||||
"git.fabledsword.com/bvandeusen/minstrel/internal/auth"
|
||||
"git.fabledsword.com/bvandeusen/minstrel/internal/coverart"
|
||||
@@ -163,15 +165,21 @@ func (h *handlers) streamAuthOk(r *http.Request, trackID string) bool {
|
||||
// permissive middleware the route is wrapped with) OR a signed token
|
||||
// (UPnP slice). streamAuthOk gates both paths.
|
||||
func (h *handlers) handleGetStream(w http.ResponseWriter, r *http.Request) {
|
||||
// Auth check before the DB lookup: a 404 ahead of the auth check
|
||||
// would let unauth callers probe which track IDs exist via the
|
||||
// 404/401 response differential. streamAuthOk is keyed on the
|
||||
// path's id directly (the HMAC token is signed over the same id
|
||||
// string, so we don't need the resolved row yet).
|
||||
rawID := chi.URLParam(r, "id")
|
||||
if !h.streamAuthOk(r, rawID) {
|
||||
writeErr(w, apierror.ErrUnauthorized)
|
||||
return
|
||||
}
|
||||
track, apiErr := resolveByID(r, "id", dbq.New(h.pool).GetTrackByID, "track")
|
||||
if apiErr != nil {
|
||||
writeErr(w, apiErr)
|
||||
return
|
||||
}
|
||||
if !h.streamAuthOk(r, uuidToString(track.ID)) {
|
||||
writeErr(w, apierror.ErrUnauthorized)
|
||||
return
|
||||
}
|
||||
f, err := os.Open(track.FilePath)
|
||||
if err != nil {
|
||||
// File vanished (scanner indexed it, filesystem lost it). Treat as
|
||||
|
||||
Reference in New Issue
Block a user