mirror of
https://github.com/navidrome/navidrome.git
synced 2025-08-10 00:52:20 +00:00
Merge branch 'os-lyrics' of github.com:kgarner7/navidrome into os-lyrics
This commit is contained in:
@@ -51,6 +51,7 @@ type configOptions struct {
|
||||
DefaultDownsamplingFormat string
|
||||
SearchFullString bool
|
||||
RecentlyAddedByModTime bool
|
||||
PreferSortTags bool
|
||||
IgnoredArticles string
|
||||
IndexGroups string
|
||||
SubsonicArtistParticipations bool
|
||||
@@ -296,6 +297,7 @@ func init() {
|
||||
viper.SetDefault("defaultdownsamplingformat", consts.DefaultDownsamplingFormat)
|
||||
viper.SetDefault("searchfullstring", false)
|
||||
viper.SetDefault("recentlyaddedbymodtime", false)
|
||||
viper.SetDefault("prefersorttags", false)
|
||||
viper.SetDefault("ignoredarticles", "The El La Los Las Le Les Os As O A")
|
||||
viper.SetDefault("indexgroups", "A B C D E F G H I J K L M N O P Q R S T U V W X-Z(XYZ) [Unknown]([)")
|
||||
viper.SetDefault("subsonicartistparticipations", false)
|
||||
@@ -335,8 +337,8 @@ func init() {
|
||||
viper.SetDefault("agents", "lastfm,spotify")
|
||||
viper.SetDefault("lastfm.enabled", true)
|
||||
viper.SetDefault("lastfm.language", "en")
|
||||
viper.SetDefault("lastfm.apikey", consts.LastFMAPIKey)
|
||||
viper.SetDefault("lastfm.secret", consts.LastFMAPISecret)
|
||||
viper.SetDefault("lastfm.apikey", "")
|
||||
viper.SetDefault("lastfm.secret", "")
|
||||
viper.SetDefault("spotify.id", "")
|
||||
viper.SetDefault("spotify.secret", "")
|
||||
viper.SetDefault("listenbrainz.enabled", true)
|
||||
|
||||
@@ -81,12 +81,6 @@ const (
|
||||
DefaultCacheCleanUpInterval = 10 * time.Minute
|
||||
)
|
||||
|
||||
// Shared secrets (only add here "secrets" that can be public)
|
||||
const (
|
||||
LastFMAPIKey = "9b94a5515ea66b2da3ec03c12300327e" // nolint:gosec
|
||||
LastFMAPISecret = "74cb6557cec7171d921af5d7d887c587" // nolint:gosec
|
||||
)
|
||||
|
||||
var (
|
||||
DefaultDownsamplingFormat = "opus"
|
||||
DefaultTranscodings = []map[string]interface{}{
|
||||
|
||||
@@ -311,12 +311,14 @@ func (l *lastfmAgent) IsAuthorized(ctx context.Context, userId string) bool {
|
||||
func init() {
|
||||
conf.AddHook(func() {
|
||||
if conf.Server.LastFM.Enabled {
|
||||
agents.Register(lastFMAgentName, func(ds model.DataStore) agents.Interface {
|
||||
return lastFMConstructor(ds)
|
||||
})
|
||||
scrobbler.Register(lastFMAgentName, func(ds model.DataStore) scrobbler.Scrobbler {
|
||||
return lastFMConstructor(ds)
|
||||
})
|
||||
if conf.Server.LastFM.ApiKey != "" && conf.Server.LastFM.Secret != "" {
|
||||
agents.Register(lastFMAgentName, func(ds model.DataStore) agents.Interface {
|
||||
return lastFMConstructor(ds)
|
||||
})
|
||||
scrobbler.Register(lastFMAgentName, func(ds model.DataStore) scrobbler.Scrobbler {
|
||||
return lastFMConstructor(ds)
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/go-chi/jwtauth/v5"
|
||||
"github.com/google/uuid"
|
||||
"github.com/lestrrat-go/jwx/v2/jwt"
|
||||
"github.com/navidrome/navidrome/conf"
|
||||
"github.com/navidrome/navidrome/consts"
|
||||
@@ -23,9 +24,10 @@ var (
|
||||
func Init(ds model.DataStore) {
|
||||
once.Do(func() {
|
||||
log.Info("Setting Session Timeout", "value", conf.Server.SessionTimeout)
|
||||
secret, err := ds.Property(context.TODO()).DefaultGet(consts.JWTSecretKey, "not so secret")
|
||||
if err != nil {
|
||||
secret, err := ds.Property(context.TODO()).Get(consts.JWTSecretKey)
|
||||
if err != nil || secret == "" {
|
||||
log.Error("No JWT secret found in DB. Setting a temp one, but please report this error", err)
|
||||
secret = uuid.NewString()
|
||||
}
|
||||
Secret = []byte(secret)
|
||||
TokenAuth = jwtauth.New("HS256", Secret, nil)
|
||||
|
||||
11
go.mod
11
go.mod
@@ -3,12 +3,11 @@ module github.com/navidrome/navidrome
|
||||
go 1.21
|
||||
|
||||
require (
|
||||
code.cloudfoundry.org/go-diodes v0.0.0-20231113191959-85adc333ee36
|
||||
github.com/DexterLB/mpvipc v0.0.0-20230829142118-145d6eabdc37
|
||||
github.com/Masterminds/squirrel v1.5.4
|
||||
github.com/ReneKroon/ttlcache/v2 v2.11.0
|
||||
github.com/bradleyjkemp/cupaloy/v2 v2.8.0
|
||||
github.com/deluan/rest v0.0.0-20211101235434-380523c4bb47
|
||||
github.com/deluan/rest v0.0.0-20211102003136-6260bc399cbf
|
||||
github.com/deluan/sanitize v0.0.0-20230310221930-6e18967d9fc1
|
||||
github.com/dhowden/tag v0.0.0-20230630033851-978a0926ee25
|
||||
github.com/disintegration/imaging v1.6.2
|
||||
@@ -21,16 +20,16 @@ require (
|
||||
github.com/fatih/structs v1.1.0
|
||||
github.com/go-chi/chi/v5 v5.0.10
|
||||
github.com/go-chi/cors v1.2.1
|
||||
github.com/go-chi/httprate v0.7.4
|
||||
github.com/go-chi/jwtauth/v5 v5.2.0
|
||||
github.com/google/uuid v1.4.0
|
||||
github.com/go-chi/httprate v0.8.0
|
||||
github.com/go-chi/jwtauth/v5 v5.3.0
|
||||
github.com/google/uuid v1.5.0
|
||||
github.com/google/wire v0.5.0
|
||||
github.com/hashicorp/go-multierror v1.1.1
|
||||
github.com/kr/pretty v0.3.1
|
||||
github.com/lestrrat-go/jwx/v2 v2.0.18
|
||||
github.com/matoous/go-nanoid/v2 v2.0.0
|
||||
github.com/mattn/go-sqlite3 v1.14.18
|
||||
github.com/mattn/go-zglob v0.0.3
|
||||
github.com/mattn/go-zglob v0.0.4
|
||||
github.com/microcosm-cc/bluemonday v1.0.26
|
||||
github.com/mileusna/useragent v1.3.4
|
||||
github.com/onsi/ginkgo/v2 v2.13.2
|
||||
|
||||
22
go.sum
22
go.sum
@@ -35,8 +35,6 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl
|
||||
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
||||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||
cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
|
||||
code.cloudfoundry.org/go-diodes v0.0.0-20231113191959-85adc333ee36 h1:rvJrEWqzJVIgzhVGzm3zRFWN46W+Rk6QkmfATsvv7MA=
|
||||
code.cloudfoundry.org/go-diodes v0.0.0-20231113191959-85adc333ee36/go.mod h1:+ARlrrIHjT9DE+ge1VugVtIs/DAOW8Cim8dKtspdkbc=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
@@ -72,8 +70,8 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
|
||||
github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
|
||||
github.com/deluan/rest v0.0.0-20211101235434-380523c4bb47 h1:IhGAYGDi212gspq0XkYAI+DN5e9lfAIm8Qgu1wj9yN4=
|
||||
github.com/deluan/rest v0.0.0-20211101235434-380523c4bb47/go.mod h1:tSgDythFsl0QgS/PFWfIZqcJKnkADWneY80jaVRlqK8=
|
||||
github.com/deluan/rest v0.0.0-20211102003136-6260bc399cbf h1:tb246l2Zmpt/GpF9EcHCKTtwzrd0HGfEmoODFA/qnk4=
|
||||
github.com/deluan/rest v0.0.0-20211102003136-6260bc399cbf/go.mod h1:tSgDythFsl0QgS/PFWfIZqcJKnkADWneY80jaVRlqK8=
|
||||
github.com/deluan/sanitize v0.0.0-20230310221930-6e18967d9fc1 h1:mGvOb3zxl4vCLv+dbf7JA6CAaM2UH/AGP1KX4DsJmTI=
|
||||
github.com/deluan/sanitize v0.0.0-20230310221930-6e18967d9fc1/go.mod h1:ZNCLJfehvEf34B7BbLKjgpsL9lyW7q938w/GY1XgV4E=
|
||||
github.com/dhowden/tag v0.0.0-20230630033851-978a0926ee25 h1:simG0vMYFvNriGhaaat7QVVkaVkXzvqcohaBoLZl9Hg=
|
||||
@@ -113,10 +111,10 @@ github.com/go-chi/chi/v5 v5.0.10 h1:rLz5avzKpjqxrYwXNfmjkrYYXOyLJd37pz53UFHC6vk=
|
||||
github.com/go-chi/chi/v5 v5.0.10/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||
github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4=
|
||||
github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
|
||||
github.com/go-chi/httprate v0.7.4 h1:a2GIjv8he9LRf3712zxxnRdckQCm7I8y8yQhkJ84V6M=
|
||||
github.com/go-chi/httprate v0.7.4/go.mod h1:6GOYBSwnpra4CQfAKXu8sQZg+nZ0M1g9QnyFvxrAB8A=
|
||||
github.com/go-chi/jwtauth/v5 v5.2.0 h1:rw2wRNY6QHxyjYhoZYrQ4IeXVpPeun9nCZ9DBItDFPc=
|
||||
github.com/go-chi/jwtauth/v5 v5.2.0/go.mod h1:2PoGm/KbnzRN9ILY6HFZAI6fTnb1gEZAKogAyqkd6fY=
|
||||
github.com/go-chi/httprate v0.8.0 h1:CyKng28yhGnlGXH9EDGC/Qizj29afJQSNW15W/yj34o=
|
||||
github.com/go-chi/httprate v0.8.0/go.mod h1:6GOYBSwnpra4CQfAKXu8sQZg+nZ0M1g9QnyFvxrAB8A=
|
||||
github.com/go-chi/jwtauth/v5 v5.3.0 h1:X7RKGks1lrVeIe2omGyz47pNaNjG2YmwlRN5UKhN8qg=
|
||||
github.com/go-chi/jwtauth/v5 v5.3.0/go.mod h1:2PoGm/KbnzRN9ILY6HFZAI6fTnb1gEZAKogAyqkd6fY=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
@@ -189,8 +187,8 @@ github.com/google/pprof v0.0.0-20230323073829-e72429f035bd/go.mod h1:79YE0hCXdHa
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
|
||||
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
|
||||
github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/wire v0.5.0 h1:I7ELFeVBr3yfPIcc8+MWvrjk+3VjbcSzoXm3JVa+jD8=
|
||||
github.com/google/wire v0.5.0/go.mod h1:ngWDr9Qvq3yZA10YrxfyGELY/AFWGVpy9c1LTRi1EoU=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
@@ -270,8 +268,8 @@ github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D
|
||||
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-sqlite3 v1.14.18 h1:JL0eqdCOq6DJVNPSvArO/bIV9/P7fbGrV00LZHc+5aI=
|
||||
github.com/mattn/go-sqlite3 v1.14.18/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||
github.com/mattn/go-zglob v0.0.3 h1:6Ry4EYsScDyt5di4OI6xw1bYhOqfE5S33Z1OPy+d+To=
|
||||
github.com/mattn/go-zglob v0.0.3/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo=
|
||||
github.com/mattn/go-zglob v0.0.4 h1:LQi2iOm0/fGgu80AioIJ/1j9w9Oh+9DZ39J4VAGzHQM=
|
||||
github.com/mattn/go-zglob v0.0.4/go.mod h1:MxxjyoXXnMxfIpxTK2GAkw1w8glPsQILx3N5wrKakiY=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
|
||||
github.com/mewkiz/flac v1.0.7 h1:uIXEjnuXqdRaZttmSFM5v5Ukp4U6orrZsnYGGR3yow8=
|
||||
|
||||
@@ -50,13 +50,6 @@ func NewAlbumRepository(ctx context.Context, db dbx.Builder) model.AlbumReposito
|
||||
r.ctx = ctx
|
||||
r.db = db
|
||||
r.tableName = "album"
|
||||
r.sortMappings = map[string]string{
|
||||
"name": "order_album_name asc, order_album_artist_name asc",
|
||||
"artist": "compilation asc, order_album_artist_name asc, order_album_name asc",
|
||||
"random": "RANDOM()",
|
||||
"max_year": "coalesce(nullif(original_date,''), cast(max_year as text)), release_date, name, order_album_name asc",
|
||||
"recently_added": recentlyAddedSort(),
|
||||
}
|
||||
r.filterMappings = map[string]filterFunc{
|
||||
"id": idFilter(r.tableName),
|
||||
"name": fullTextFilter,
|
||||
@@ -67,6 +60,24 @@ func NewAlbumRepository(ctx context.Context, db dbx.Builder) model.AlbumReposito
|
||||
"starred": booleanFilter,
|
||||
"has_rating": hasRatingFilter,
|
||||
}
|
||||
if conf.Server.PreferSortTags {
|
||||
r.sortMappings = map[string]string{
|
||||
"name": "COALESCE(NULLIF(sort_album_name,''),order_album_name)",
|
||||
"artist": "compilation asc, COALESCE(NULLIF(sort_album_artist_name,''),order_album_artist_name) asc, COALESCE(NULLIF(sort_album_name,''),order_album_name) asc",
|
||||
"albumArtist": "compilation asc, COALESCE(NULLIF(sort_album_artist_name,''),order_album_artist_name) asc, COALESCE(NULLIF(sort_album_name,''),order_album_name) asc",
|
||||
"max_year": "coalesce(nullif(original_date,''), cast(max_year as text)), release_date, name, COALESCE(NULLIF(sort_album_name,''),order_album_name) asc",
|
||||
"random": "RANDOM()",
|
||||
"recently_added": recentlyAddedSort(),
|
||||
}
|
||||
} else {
|
||||
r.sortMappings = map[string]string{
|
||||
"name": "order_album_name asc, order_album_artist_name asc",
|
||||
"artist": "compilation asc, order_album_artist_name asc, order_album_name asc",
|
||||
"max_year": "coalesce(nullif(original_date,''), cast(max_year as text)), release_date, name, order_album_name asc",
|
||||
"random": "RANDOM()",
|
||||
"recently_added": recentlyAddedSort(),
|
||||
}
|
||||
}
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
@@ -60,14 +60,20 @@ func NewArtistRepository(ctx context.Context, db dbx.Builder) model.ArtistReposi
|
||||
r.db = db
|
||||
r.indexGroups = utils.ParseIndexGroups(conf.Server.IndexGroups)
|
||||
r.tableName = "artist"
|
||||
r.sortMappings = map[string]string{
|
||||
"name": "order_artist_name",
|
||||
}
|
||||
r.filterMappings = map[string]filterFunc{
|
||||
"id": idFilter(r.tableName),
|
||||
"name": fullTextFilter,
|
||||
"starred": booleanFilter,
|
||||
}
|
||||
if conf.Server.PreferSortTags {
|
||||
r.sortMappings = map[string]string{
|
||||
"name": "COALESCE(NULLIF(sort_artist_name,''),order_artist_name)",
|
||||
}
|
||||
} else {
|
||||
r.sortMappings = map[string]string{
|
||||
"name": "order_artist_name",
|
||||
}
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
|
||||
. "github.com/Masterminds/squirrel"
|
||||
"github.com/deluan/rest"
|
||||
"github.com/navidrome/navidrome/conf"
|
||||
"github.com/navidrome/navidrome/log"
|
||||
"github.com/navidrome/navidrome/model"
|
||||
"github.com/pocketbase/dbx"
|
||||
@@ -25,16 +26,25 @@ func NewMediaFileRepository(ctx context.Context, db dbx.Builder) *mediaFileRepos
|
||||
r.ctx = ctx
|
||||
r.db = db
|
||||
r.tableName = "media_file"
|
||||
r.sortMappings = map[string]string{
|
||||
"artist": "order_artist_name asc, order_album_name asc, release_date asc, disc_number asc, track_number asc",
|
||||
"album": "order_album_name asc, release_date asc, disc_number asc, track_number asc, order_artist_name asc, title asc",
|
||||
"random": "RANDOM()",
|
||||
}
|
||||
r.filterMappings = map[string]filterFunc{
|
||||
"id": idFilter(r.tableName),
|
||||
"title": fullTextFilter,
|
||||
"starred": booleanFilter,
|
||||
}
|
||||
if conf.Server.PreferSortTags {
|
||||
r.sortMappings = map[string]string{
|
||||
"title": "COALESCE(NULLIF(sort_title,''),title)",
|
||||
"artist": "COALESCE(NULLIF(sort_artist_name,''),order_artist_name) asc, COALESCE(NULLIF(sort_album_name,''),order_album_name) asc, release_date asc, disc_number asc, track_number asc",
|
||||
"album": "COALESCE(NULLIF(sort_album_name,''),order_album_name) asc, release_date asc, disc_number asc, track_number asc, COALESCE(NULLIF(sort_artist_name,''),order_artist_name) asc, COALESCE(NULLIF(sort_title,''),title) asc",
|
||||
"random": "RANDOM()",
|
||||
}
|
||||
} else {
|
||||
r.sortMappings = map[string]string{
|
||||
"artist": "order_artist_name asc, order_album_name asc, release_date asc, disc_number asc, track_number asc",
|
||||
"album": "order_album_name asc, release_date asc, disc_number asc, track_number asc, order_artist_name asc, title asc",
|
||||
"random": "RANDOM()",
|
||||
}
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
|
||||
@@ -129,7 +129,7 @@ func (r sqlRepository) executeSQL(sq Sqlizer) (int64, error) {
|
||||
}
|
||||
start := time.Now()
|
||||
var c int64
|
||||
res, err := r.db.NewQuery(query).Bind(args).Execute()
|
||||
res, err := r.db.NewQuery(query).Bind(args).WithContext(r.ctx).Execute()
|
||||
if res != nil {
|
||||
c, _ = res.RowsAffected()
|
||||
}
|
||||
@@ -165,7 +165,7 @@ func (r sqlRepository) queryOne(sq Sqlizer, response interface{}) error {
|
||||
return err
|
||||
}
|
||||
start := time.Now()
|
||||
err = r.db.NewQuery(query).Bind(args).One(response)
|
||||
err = r.db.NewQuery(query).Bind(args).WithContext(r.ctx).One(response)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
r.logSQL(query, args, nil, 0, start)
|
||||
return model.ErrNotFound
|
||||
@@ -183,7 +183,7 @@ func (r sqlRepository) queryAll(sq SelectBuilder, response interface{}, options
|
||||
return err
|
||||
}
|
||||
start := time.Now()
|
||||
err = r.db.NewQuery(query).Bind(args).All(response)
|
||||
err = r.db.NewQuery(query).Bind(args).WithContext(r.ctx).All(response)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
r.logSQL(query, args, nil, -1, start)
|
||||
return model.ErrNotFound
|
||||
@@ -199,7 +199,7 @@ func (r sqlRepository) queryAllSlice(sq SelectBuilder, response interface{}) err
|
||||
return err
|
||||
}
|
||||
start := time.Now()
|
||||
err = r.db.NewQuery(query).Bind(args).Column(response)
|
||||
err = r.db.NewQuery(query).Bind(args).WithContext(r.ctx).Column(response)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
r.logSQL(query, args, nil, -1, start)
|
||||
return model.ErrNotFound
|
||||
|
||||
11
scanner/rescanall.go
Normal file
11
scanner/rescanall.go
Normal file
@@ -0,0 +1,11 @@
|
||||
//go:build go1.21
|
||||
|
||||
package scanner
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
func contextWithoutCancel(ctx context.Context) context.Context {
|
||||
return context.WithoutCancel(ctx)
|
||||
}
|
||||
12
scanner/rescanall_go1.20.go
Normal file
12
scanner/rescanall_go1.20.go
Normal file
@@ -0,0 +1,12 @@
|
||||
//go:build !go1.21
|
||||
|
||||
package scanner
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
// TODO Remove this file when we drop support for go 1.20
|
||||
func contextWithoutCancel(ctx context.Context) context.Context {
|
||||
return context.TODO()
|
||||
}
|
||||
@@ -139,27 +139,6 @@ func (s *scanner) startProgressTracker(mediaFolder string) (chan uint32, context
|
||||
return progress, cancel
|
||||
}
|
||||
|
||||
func (s *scanner) RescanAll(ctx context.Context, fullRescan bool) error {
|
||||
if !isScanning.TryLock() {
|
||||
log.Debug("Scanner already running, ignoring request for rescan.")
|
||||
return ErrAlreadyScanning
|
||||
}
|
||||
defer isScanning.Unlock()
|
||||
|
||||
var hasError bool
|
||||
for folder := range s.folders {
|
||||
err := s.rescan(ctx, folder, fullRescan)
|
||||
hasError = hasError || err != nil
|
||||
}
|
||||
if hasError {
|
||||
log.Error("Errors while scanning media. Please check the logs")
|
||||
core.WriteAfterScanMetrics(ctx, s.ds, false)
|
||||
return ErrScanError
|
||||
}
|
||||
core.WriteAfterScanMetrics(ctx, s.ds, true)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *scanner) getStatus(folder string) (scanStatus, bool) {
|
||||
s.lock.RLock()
|
||||
defer s.lock.RUnlock()
|
||||
@@ -198,6 +177,27 @@ func (s *scanner) setStatusEnd(folder string, lastUpdate time.Time) {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *scanner) RescanAll(ctx context.Context, fullRescan bool) error {
|
||||
ctx = contextWithoutCancel(ctx)
|
||||
if !isScanning.TryLock() {
|
||||
log.Debug(ctx, "Scanner already running, ignoring request for rescan.")
|
||||
return ErrAlreadyScanning
|
||||
}
|
||||
defer isScanning.Unlock()
|
||||
|
||||
var hasError bool
|
||||
for folder := range s.folders {
|
||||
err := s.rescan(ctx, folder, fullRescan)
|
||||
hasError = hasError || err != nil
|
||||
}
|
||||
if hasError {
|
||||
log.Error(ctx, "Errors while scanning media. Please check the logs")
|
||||
core.WriteAfterScanMetrics(ctx, s.ds, false)
|
||||
return ErrScanError
|
||||
}
|
||||
core.WriteAfterScanMetrics(ctx, s.ds, true)
|
||||
return nil
|
||||
}
|
||||
func (s *scanner) Status(mediaFolder string) (*StatusInfo, error) {
|
||||
status, ok := s.getStatus(mediaFolder)
|
||||
if !ok {
|
||||
|
||||
@@ -193,7 +193,7 @@ func UsernameFromToken(r *http.Request) string {
|
||||
}
|
||||
|
||||
func UsernameFromReverseProxyHeader(r *http.Request) string {
|
||||
if conf.Server.ReverseProxyWhitelist == "" {
|
||||
if conf.Server.ReverseProxyWhitelist == "" && !strings.HasPrefix(conf.Server.Address, "unix:") {
|
||||
return ""
|
||||
}
|
||||
if !validateIPAgainstList(r.RemoteAddr, conf.Server.ReverseProxyWhitelist) {
|
||||
@@ -316,6 +316,12 @@ func handleLoginFromHeaders(ds model.DataStore, r *http.Request) map[string]inte
|
||||
}
|
||||
|
||||
func validateIPAgainstList(ip string, comaSeparatedList string) bool {
|
||||
// Per https://github.com/golang/go/issues/49825, the remote address
|
||||
// on a unix socket is '@'
|
||||
if ip == "@" && strings.HasPrefix(conf.Server.Address, "unix:") {
|
||||
return true
|
||||
}
|
||||
|
||||
if comaSeparatedList == "" || ip == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -34,8 +34,8 @@ type Server struct {
|
||||
|
||||
func New(ds model.DataStore, broker events.Broker) *Server {
|
||||
s := &Server{ds: ds, broker: broker}
|
||||
auth.Init(s.ds)
|
||||
initialSetup(ds)
|
||||
auth.Init(s.ds)
|
||||
s.initRoutes()
|
||||
s.mountAuthenticationRoutes()
|
||||
s.mountRootRedirector()
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
package diodes
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"code.cloudfoundry.org/go-diodes"
|
||||
)
|
||||
|
||||
type Diode[T any] struct {
|
||||
d *diodes.Waiter
|
||||
}
|
||||
|
||||
type Alerter = diodes.Alerter
|
||||
|
||||
type AlertFunc = diodes.AlertFunc
|
||||
|
||||
func New[T any](ctx context.Context, size int, alerter Alerter) *Diode[T] {
|
||||
return &Diode[T]{
|
||||
d: diodes.NewWaiter(diodes.NewOneToOne(size, alerter), diodes.WithWaiterContext(ctx)),
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Diode[T]) Put(data T) {
|
||||
d.d.Set(diodes.GenericDataType(&data))
|
||||
}
|
||||
|
||||
func (d *Diode[T]) TryNext() (*T, bool) {
|
||||
data, ok := d.d.TryNext()
|
||||
if !ok {
|
||||
return nil, ok
|
||||
}
|
||||
return (*T)(data), true
|
||||
}
|
||||
|
||||
func (d *Diode[T]) Next() *T {
|
||||
data := d.d.Next()
|
||||
return (*T)(data)
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
package diodes_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/navidrome/navidrome/tests"
|
||||
. "github.com/navidrome/navidrome/utils/diodes"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
func TestDiodes(t *testing.T) {
|
||||
tests.Init(t, false)
|
||||
RegisterFailHandler(Fail)
|
||||
RunSpecs(t, "Diodes Suite")
|
||||
}
|
||||
|
||||
var _ = Describe("Diode", func() {
|
||||
type message struct {
|
||||
data string
|
||||
}
|
||||
var diode *Diode[message]
|
||||
var ctx context.Context
|
||||
var ctxCancel context.CancelFunc
|
||||
var missed int
|
||||
|
||||
BeforeEach(func() {
|
||||
missed = 0
|
||||
ctx, ctxCancel = context.WithCancel(context.Background())
|
||||
diode = New[message](ctx, 2, AlertFunc(func(m int) { missed = m }))
|
||||
})
|
||||
|
||||
It("enqueues the data correctly", func() {
|
||||
diode.Put(message{data: "1"})
|
||||
diode.Put(message{data: "2"})
|
||||
Expect(diode.Next()).To(Equal(&message{data: "1"}))
|
||||
Expect(diode.Next()).To(Equal(&message{data: "2"}))
|
||||
Expect(missed).To(BeZero())
|
||||
})
|
||||
|
||||
It("drops messages when Diode is full", func() {
|
||||
diode.Put(message{data: "1"})
|
||||
diode.Put(message{data: "2"})
|
||||
diode.Put(message{data: "3"})
|
||||
next, ok := diode.TryNext()
|
||||
Expect(ok).To(BeTrue())
|
||||
Expect(next).To(Equal(&message{data: "3"}))
|
||||
|
||||
_, ok = diode.TryNext()
|
||||
Expect(ok).To(BeFalse())
|
||||
|
||||
Expect(missed).To(Equal(2))
|
||||
})
|
||||
|
||||
It("returns nil when Diode is empty and the context is canceled", func() {
|
||||
diode.Put(message{data: "1"})
|
||||
ctxCancel()
|
||||
Expect(diode.Next()).To(Equal(&message{data: "1"}))
|
||||
Expect(diode.Next()).To(BeNil())
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user