🏡 index : quine-global/quintodrome.git

package public

import (
	"bytes"
	"context"
	"io"
	"net/http"
	"net/http/httptest"
	"net/url"

	"github.com/go-chi/jwtauth/v5"
	"github.com/navidrome/navidrome/core/artwork"
	"github.com/navidrome/navidrome/core/auth"
	"github.com/navidrome/navidrome/model"
	"github.com/navidrome/navidrome/tests"
	. "github.com/onsi/ginkgo/v2"
	. "github.com/onsi/gomega"
)

var _ = Describe("decodeArtworkID", func() {
	BeforeEach(func() {
		auth.PublicTokenAuth = jwtauth.New("HS256", []byte("super secret"), nil)
	})

	It("fails to decode an invalid token", func() {
		_, err := decodeArtworkID("xx-123")
		Expect(err).To(HaveOccurred())
	})

	It("fails to decode a token without an id", func() {
		token, _ := auth.CreatePublicToken(auth.Claims{})
		_, err := decodeArtworkID(token)
		Expect(err).To(HaveOccurred())
	})
})

type fakeArtwork struct {
	artwork.Artwork
	img *artwork.Image
	err error
}

func (f *fakeArtwork) Get(context.Context, model.ArtworkID, int, bool) (*artwork.Image, error) {
	return f.img, f.err
}

var _ = Describe("handleImages", func() {
	var w *httptest.ResponseRecorder

	newImageRequest := func(claimID string) *http.Request {
		auth.PublicTokenAuth = jwtauth.New("HS256", []byte("super secret"), nil)
		token, _ := auth.CreatePublicToken(auth.Claims{ID: claimID})
		return httptest.NewRequest("GET", "/img?:id="+url.QueryEscape(token), nil)
	}

	// The handler re-checks that the entity behind the token still exists, so "1" must be live.
	var ds *tests.MockDataStore

	BeforeEach(func() {
		w = httptest.NewRecorder()
		albumRepo := tests.CreateMockAlbumRepo()
		albumRepo.SetData(model.Albums{{ID: "1"}})
		ds = &tests.MockDataStore{MockedAlbum: albumRepo}
	})

	It("returns 404 when the artwork is unavailable", func() {
		pub := &Router{ds: ds, artwork: &fakeArtwork{err: artwork.ErrUnavailable}}
		pub.handleImages(w, newImageRequest("al-1"))
		Expect(w.Code).To(Equal(http.StatusNotFound))
	})

	It("returns 404 when the artwork is not found", func() {
		pub := &Router{ds: ds, artwork: &fakeArtwork{err: model.ErrNotFound}}
		pub.handleImages(w, newImageRequest("al-1"))
		Expect(w.Code).To(Equal(http.StatusNotFound))
	})

	It("serves the image immutable when the token asserts the current hash", func() {
		const hash = "0123456789abcdef"
		img := &artwork.Image{ReadCloser: io.NopCloser(bytes.NewReader([]byte("IMG"))), Hash: hash}
		pub := &Router{ds: ds, artwork: &fakeArtwork{img: img}}
		pub.handleImages(w, newImageRequest("al-1_"+hash))
		Expect(w.Code).To(Equal(http.StatusOK))
		Expect(w.Header().Get("Cache-Control")).To(Equal("public, max-age=31536000, immutable"))
		Expect(w.Header().Get("ETag")).To(Equal(`"` + hash + `"`))
	})

})