feat(album): add UpdateImage repository method for uploaded cover

This commit is contained in:
Deluan 2026-07-17 18:49:01 -04:00
parent 0d8ba90b13
commit 720993fe7c
4 changed files with 59 additions and 0 deletions

View File

@ -145,6 +145,7 @@ type AlbumRepository interface {
Exists(id string) (bool, error)
Put(*Album) error
UpdateExternalInfo(*Album) error
UpdateImage(id, filename string) error
Get(id string) (*Album, error)
GetAll(...QueryOptions) (Albums, error)
GetCursor(...QueryOptions) (AlbumCursor, error)

View File

@ -219,6 +219,22 @@ func (r *albumRepository) UpdateExternalInfo(al *model.Album) error {
return err
}
// UpdateImage is the sole writer of uploaded_image: it uses raw SQL because Put's
// structs.Map marshaling drops the structs:"-" tagged UploadedImage field.
func (r *albumRepository) UpdateImage(id, filename string) error {
c, err := r.executeSQL(Update(r.tableName).
Set("uploaded_image", filename).
Set("updated_at", time.Now()).
Where(Eq{"id": id}))
if err != nil {
return err
}
if c == 0 {
return model.ErrNotFound
}
return nil
}
func (r *albumRepository) selectAlbum(options ...model.QueryOptions) SelectBuilder {
sql := r.newSelect(options...).Columns("album.*", "library.path as library_path", "library.name as library_name").
LeftJoin("library on album.library_id = library.id")

View File

@ -41,6 +41,37 @@ var _ = Describe("AlbumRepository", func() {
})
})
Describe("UpdateImage", func() {
BeforeEach(func() {
Expect(albumRepo.Put(&model.Album{ID: "img-1", Name: "img", LibraryID: 1})).To(Succeed())
DeferCleanup(func() {
_, _ = albumRepo.executeSQL(squirrel.Delete("album").Where(squirrel.Eq{"id": "img-1"}))
})
})
It("sets and clears the uploaded image filename", func() {
Expect(albumRepo.UpdateImage("img-1", "img-1_cover.jpg")).To(Succeed())
got, err := albumRepo.Get("img-1")
Expect(err).ToNot(HaveOccurred())
Expect(got.UploadedImage).To(Equal("img-1_cover.jpg"))
Expect(albumRepo.UpdateImage("img-1", "")).To(Succeed())
got, err = albumRepo.Get("img-1")
Expect(err).ToNot(HaveOccurred())
Expect(got.UploadedImage).To(BeEmpty())
})
It("is preserved across a full-row Put (structs:\"-\" contract)", func() {
Expect(albumRepo.UpdateImage("img-1", "img-1_cover.jpg")).To(Succeed())
// A scan-style refresh re-Puts the album with a zero-valued UploadedImage.
Expect(albumRepo.Put(&model.Album{ID: "img-1", Name: "img changed", LibraryID: 1})).To(Succeed())
got, err := albumRepo.Get("img-1")
Expect(err).ToNot(HaveOccurred())
Expect(got.UploadedImage).To(Equal("img-1_cover.jpg"))
})
It("returns ErrNotFound for a missing album", func() {
Expect(albumRepo.UpdateImage("does-not-exist", "x.jpg")).To(MatchError(model.ErrNotFound))
})
})
Describe("CopyAttributes", func() {
var srcTime, dstTime time.Time
BeforeEach(func() {

View File

@ -134,6 +134,17 @@ func (m *MockAlbumRepo) UpdateExternalInfo(album *model.Album) error {
return nil
}
func (m *MockAlbumRepo) UpdateImage(id, filename string) error {
if m.Err {
return errors.New("unexpected error")
}
if al, ok := m.Data[id]; ok {
al.UploadedImage = filename
return nil
}
return model.ErrNotFound
}
func (m *MockAlbumRepo) Search(q string, options ...model.QueryOptions) (model.Albums, error) {
m.SearchQuery = q
if len(options) > 0 {