mirror of
https://github.com/navidrome/navidrome.git
synced 2026-10-08 10:27:08 +02:00
* fix(nativeapi): stop partial PUTs from clearing untouched columns The REST layer parses the request body's top-level JSON keys and passes them to Repository.Update as colsToUpdate. The radio and library repositories discarded that list and issued a full-row UPDATE, so any field absent from the body was written as its zero value. For radio this wiped uploaded_image, deleting the station's cover on every partial update (the Web UI is unaffected because its form submits the whole record). For library it silently cleared remote_path and default_new_users. Thread the column list through to Put in both repositories, and extract the column-selection half of filterUpdateValues into selectUpdateColumns so library, which hand-builds its update map, shares the same rule instead of copying it. Fixes #6057 * refactor(persistence): drop pluginRepository's dead rest.Persistable methods Save and Update had no callers: PUT /api/plugin/{id} is served by the hand-written updatePlugin handler over a typed request struct, and the route only wires rest.GetAll and rest.Get. Both methods delegated to Put, which upserts all twelve columns, so wiring rest.Put to this repository would have reintroduced the partial-update clobbering fixed in the previous commit. Removing them, along with the rest.Persistable assertion, makes that a compile error instead of a silent data loss. Put itself is unchanged and still backs plugin discovery.
61 lines
2.2 KiB
Go
61 lines
2.2 KiB
Go
package model
|
|
|
|
import (
|
|
"time"
|
|
|
|
"github.com/navidrome/navidrome/utils/slice"
|
|
)
|
|
|
|
type Library struct {
|
|
ID int `json:"id" db:"id"`
|
|
Name string `json:"name" db:"name"`
|
|
Path string `json:"path" db:"path"`
|
|
RemotePath string `json:"remotePath" db:"remote_path"`
|
|
LastScanAt time.Time `json:"lastScanAt" db:"last_scan_at"`
|
|
LastScanStartedAt time.Time `json:"lastScanStartedAt" db:"last_scan_started_at"`
|
|
FullScanInProgress bool `json:"fullScanInProgress" db:"full_scan_in_progress"`
|
|
UpdatedAt time.Time `json:"updatedAt" db:"updated_at"`
|
|
CreatedAt time.Time `json:"createdAt" db:"created_at"`
|
|
TotalSongs int `json:"totalSongs" db:"total_songs"`
|
|
TotalAlbums int `json:"totalAlbums" db:"total_albums"`
|
|
TotalArtists int `json:"totalArtists" db:"total_artists"`
|
|
TotalFolders int `json:"totalFolders" db:"total_folders"`
|
|
TotalFiles int `json:"totalFiles" db:"total_files"`
|
|
TotalMissingFiles int `json:"totalMissingFiles" db:"total_missing_files"`
|
|
TotalSize int64 `json:"totalSize" db:"total_size"`
|
|
TotalDuration float64 `json:"totalDuration" db:"total_duration"`
|
|
DefaultNewUsers bool `json:"defaultNewUsers" db:"default_new_users"`
|
|
}
|
|
|
|
const (
|
|
DefaultLibraryID = 1
|
|
DefaultLibraryName = "Music Library"
|
|
)
|
|
|
|
type Libraries []Library
|
|
|
|
func (l Libraries) IDs() []int {
|
|
return slice.Map(l, func(lib Library) int { return lib.ID })
|
|
}
|
|
|
|
type LibraryRepository interface {
|
|
Get(id int) (*Library, error)
|
|
// GetPath returns the path of the library with the given ID.
|
|
// Its implementation must be optimized to avoid unnecessary queries.
|
|
GetPath(id int) (string, error)
|
|
GetAll(...QueryOptions) (Libraries, error)
|
|
CountAll(...QueryOptions) (int64, error)
|
|
Put(l *Library, colsToUpdate ...string) error
|
|
Delete(id int) error
|
|
StoreMusicFolder() error
|
|
AddArtist(id int, artistID string) error
|
|
|
|
// User-library association methods
|
|
GetUsersWithLibraryAccess(libraryID int) (Users, error)
|
|
|
|
// TODO These methods should be moved to a core service
|
|
ScanBegin(id int, fullScan bool) error
|
|
ScanEnd(id int) error
|
|
ScanInProgress() (bool, error)
|
|
RefreshStats(id int) error
|
|
}
|