mirror of
https://github.com/navidrome/navidrome.git
synced 2026-08-01 07:21:17 +00:00
feat(album): add cover upload/delete API endpoints
This commit is contained in:
parent
37c837425c
commit
940dbe4c0a
64
server/nativeapi/albums.go
Normal file
64
server/nativeapi/albums.go
Normal file
@ -0,0 +1,64 @@
|
||||
package nativeapi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/deluan/rest"
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/navidrome/navidrome/consts"
|
||||
"github.com/navidrome/navidrome/model"
|
||||
"github.com/navidrome/navidrome/server"
|
||||
)
|
||||
|
||||
func (api *Router) addAlbumRoute(r chi.Router) {
|
||||
constructor := func(ctx context.Context) rest.Repository {
|
||||
return api.ds.Resource(ctx, model.Album{})
|
||||
}
|
||||
r.Route("/album", func(r chi.Router) {
|
||||
r.Get("/", rest.GetAll(constructor))
|
||||
r.Route("/{id}", func(r chi.Router) {
|
||||
r.Use(server.URLParamsMiddleware)
|
||||
r.Get("/", rest.Get(constructor))
|
||||
r.Post("/image", api.uploadAlbumImage())
|
||||
r.Delete("/image", api.deleteAlbumImage())
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func (api *Router) uploadAlbumImage() http.HandlerFunc {
|
||||
return handleImageUpload(func(ctx context.Context, reader io.Reader, ext string) error {
|
||||
albumID := chi.URLParamFromCtx(ctx, "id")
|
||||
al, err := api.ds.Album(ctx).Get(albumID)
|
||||
if err != nil {
|
||||
if errors.Is(err, model.ErrNotFound) {
|
||||
return model.ErrNotFound
|
||||
}
|
||||
return err
|
||||
}
|
||||
filename, err := api.imgUpload.SetImage(ctx, consts.EntityAlbum, al.ID, al.Name, al.UploadedImagePath(), reader, ext)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return api.ds.Album(ctx).UpdateImage(al.ID, filename)
|
||||
})
|
||||
}
|
||||
|
||||
func (api *Router) deleteAlbumImage() http.HandlerFunc {
|
||||
return handleImageDelete(func(ctx context.Context) error {
|
||||
albumID := chi.URLParamFromCtx(ctx, "id")
|
||||
al, err := api.ds.Album(ctx).Get(albumID)
|
||||
if err != nil {
|
||||
if errors.Is(err, model.ErrNotFound) {
|
||||
return model.ErrNotFound
|
||||
}
|
||||
return err
|
||||
}
|
||||
if err := api.imgUpload.RemoveImage(ctx, al.UploadedImagePath()); err != nil {
|
||||
return err
|
||||
}
|
||||
return api.ds.Album(ctx).UpdateImage(al.ID, "")
|
||||
})
|
||||
}
|
||||
53
server/nativeapi/albums_test.go
Normal file
53
server/nativeapi/albums_test.go
Normal file
@ -0,0 +1,53 @@
|
||||
package nativeapi
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
|
||||
"github.com/navidrome/navidrome/conf"
|
||||
"github.com/navidrome/navidrome/conf/configtest"
|
||||
"github.com/navidrome/navidrome/core"
|
||||
"github.com/navidrome/navidrome/model"
|
||||
"github.com/navidrome/navidrome/model/request"
|
||||
"github.com/navidrome/navidrome/tests"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
var _ = Describe("Album Image Endpoints", func() {
|
||||
var api *Router
|
||||
BeforeEach(func() {
|
||||
DeferCleanup(configtest.SetupConfig())
|
||||
api = &Router{ds: &tests.MockDataStore{}, imgUpload: core.NewImageUploadService()}
|
||||
})
|
||||
|
||||
DescribeTable("uploadAlbumImage guard",
|
||||
func(enableArtworkUpload, isAdmin bool, expectedStatus int) {
|
||||
conf.Server.EnableArtworkUpload = enableArtworkUpload
|
||||
req := httptest.NewRequest("POST", "/album/al-1/image", nil)
|
||||
ctx := request.WithUser(GinkgoT().Context(), model.User{ID: "user-1", IsAdmin: isAdmin})
|
||||
w := httptest.NewRecorder()
|
||||
api.uploadAlbumImage().ServeHTTP(w, req.WithContext(ctx))
|
||||
Expect(w.Code).To(Equal(expectedStatus))
|
||||
},
|
||||
Entry("enabled, regular user passes guard", true, false, http.StatusBadRequest),
|
||||
Entry("enabled, admin passes guard", true, true, http.StatusBadRequest),
|
||||
Entry("disabled, admin passes guard", false, true, http.StatusBadRequest),
|
||||
Entry("disabled, regular user is forbidden", false, false, http.StatusForbidden),
|
||||
)
|
||||
|
||||
DescribeTable("deleteAlbumImage guard",
|
||||
func(enableArtworkUpload, isAdmin bool, expectedStatus int) {
|
||||
conf.Server.EnableArtworkUpload = enableArtworkUpload
|
||||
req := httptest.NewRequest("DELETE", "/album/al-1/image", nil)
|
||||
ctx := request.WithUser(GinkgoT().Context(), model.User{ID: "user-1", IsAdmin: isAdmin})
|
||||
w := httptest.NewRecorder()
|
||||
api.deleteAlbumImage().ServeHTTP(w, req.WithContext(ctx))
|
||||
Expect(w.Code).To(Equal(expectedStatus))
|
||||
},
|
||||
Entry("enabled, regular user passes guard", true, false, http.StatusNotFound),
|
||||
Entry("enabled, admin passes guard", true, true, http.StatusNotFound),
|
||||
Entry("disabled, admin passes guard", false, true, http.StatusNotFound),
|
||||
Entry("disabled, regular user is forbidden", false, false, http.StatusForbidden),
|
||||
)
|
||||
})
|
||||
@ -66,7 +66,7 @@ func (api *Router) routes() http.Handler {
|
||||
r.Use(server.UpdateLastAccessMiddleware(api.ds))
|
||||
api.RX(r, "/user", api.users.NewRepository, true)
|
||||
api.R(r, "/song", model.MediaFile{}, false)
|
||||
api.R(r, "/album", model.Album{}, false)
|
||||
api.addAlbumRoute(r)
|
||||
api.addArtistRoute(r)
|
||||
api.R(r, "/genre", model.Genre{}, false)
|
||||
api.R(r, "/player", model.Player{}, true)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user