mirror of
https://github.com/navidrome/navidrome.git
synced 2026-10-08 02:17:25 +02:00
feat: validate all configuration durations (#6002)
* chore: ensure that all durations are nonnegative * make sure you actually include the test file * test(conf): use non-zero durations in the valid_duration fixture Zero is the boundary between the accepted and rejected ranges, so it passes even if the guard is off by one. 1s exercises an ordinary value. --------- Co-authored-by: Deluan <deluan@navidrome.org>
This commit is contained in:
parent
47bc3c00f3
commit
bd46284087
5 changed files with 99 additions and 3 deletions
|
|
@ -351,6 +351,13 @@ func LoadFromFile(confFile string) {
|
|||
Load(true)
|
||||
}
|
||||
|
||||
func durationNonNegativeOrDefault(val *time.Duration, original time.Duration) {
|
||||
if val.Nanoseconds() < 0 {
|
||||
log.Warn("Duration is a negative value. Using default value", "value", *val, "default", original)
|
||||
*val = original
|
||||
}
|
||||
}
|
||||
|
||||
func Load(noConfigDump bool) {
|
||||
parseIniFileConfiguration()
|
||||
remapEnvVarKeysFromConfig()
|
||||
|
|
@ -418,6 +425,20 @@ func Load(noConfigDump bool) {
|
|||
log.SetLogSourceLine(Server.DevLogSourceLine)
|
||||
log.SetRedacting(Server.EnableLogRedacting)
|
||||
|
||||
durationNonNegativeOrDefault(&Server.SessionTimeout, consts.DefaultSessionTimeout)
|
||||
durationNonNegativeOrDefault(&Server.SmartPlaylistRefreshDelay, consts.DefaultSmartRefresh)
|
||||
durationNonNegativeOrDefault(&Server.DefaultShareExpiration, consts.DefaultShareExpiration)
|
||||
durationNonNegativeOrDefault(&Server.UIPlaybackReportInterval, consts.DefaultUIPlaybackReportInterval)
|
||||
durationNonNegativeOrDefault(&Server.AuthWindowLength, consts.DefaultAuthWindowLength)
|
||||
durationNonNegativeOrDefault(&Server.Scanner.WatcherWait, consts.DefaultWatcherWait)
|
||||
|
||||
durationNonNegativeOrDefault(&Server.DevActivityPanelUpdateRate, consts.DefaultActivityPanelUpdateRate)
|
||||
durationNonNegativeOrDefault(&Server.DevArtworkThrottleBacklogTimeout, consts.RequestThrottleBacklogTimeout)
|
||||
durationNonNegativeOrDefault(&Server.DevArtistInfoTimeToLive, consts.ArtistInfoTimeToLive)
|
||||
durationNonNegativeOrDefault(&Server.DevAlbumInfoTimeToLive, consts.AlbumInfoTimeToLive)
|
||||
durationNonNegativeOrDefault(&Server.DevInsightsInitialDelay, consts.InsightsInitialDelay)
|
||||
durationNonNegativeOrDefault(&Server.DevPluginCompilationTimeout, consts.DefaultPluginCompilationTimeout)
|
||||
|
||||
// Log deprecated, removed and unknown options
|
||||
for _, o := range deprecatedOptions {
|
||||
logDeprecatedOptions(o.name, o.replacement)
|
||||
|
|
@ -967,7 +988,7 @@ func setViperDefaults() {
|
|||
viper.SetDefault("autoimportplaylists", true)
|
||||
viper.SetDefault("defaultplaylistpublicvisibility", false)
|
||||
viper.SetDefault("playlistspath", "")
|
||||
viper.SetDefault("smartPlaylistRefreshDelay", 5*time.Second)
|
||||
viper.SetDefault("smartPlaylistRefreshDelay", consts.DefaultSmartRefresh)
|
||||
viper.SetDefault("enabledownloads", true)
|
||||
viper.SetDefault("enableexternalservices", true)
|
||||
viper.SetDefault("enablem3uexternalalbumart", false)
|
||||
|
|
@ -1011,14 +1032,14 @@ func setViperDefaults() {
|
|||
viper.SetDefault("maximagesize", consts.DefaultMaxImageSize)
|
||||
viper.SetDefault("enablesharing", true)
|
||||
viper.SetDefault("shareurl", "")
|
||||
viper.SetDefault("defaultshareexpiration", 8760*time.Hour)
|
||||
viper.SetDefault("defaultshareexpiration", consts.DefaultShareExpiration)
|
||||
viper.SetDefault("defaultdownloadableshare", false)
|
||||
viper.SetDefault("gatrackingid", "")
|
||||
viper.SetDefault("enableinsightscollector", true)
|
||||
viper.SetDefault("enablescheduleddbanalyze", true)
|
||||
viper.SetDefault("enablelogredacting", true)
|
||||
viper.SetDefault("authrequestlimit", 5)
|
||||
viper.SetDefault("authwindowlength", 20*time.Second)
|
||||
viper.SetDefault("authwindowlength", consts.DefaultAuthWindowLength)
|
||||
viper.SetDefault("passwordencryptionkey", "")
|
||||
viper.SetDefault("extauth.userheader", "Remote-User")
|
||||
viper.SetDefault("extauth.trustedsources", "")
|
||||
|
|
|
|||
|
|
@ -6,9 +6,11 @@ import (
|
|||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/navidrome/navidrome/conf"
|
||||
"github.com/navidrome/navidrome/conf/configtest"
|
||||
"github.com/navidrome/navidrome/consts"
|
||||
"github.com/navidrome/navidrome/log"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
|
|
@ -453,6 +455,49 @@ var _ = Describe("Configuration", func() {
|
|||
Entry("INI format", "ini"),
|
||||
Entry("JSON format", "json"),
|
||||
)
|
||||
|
||||
It("should use default values for negative duration fields", func() {
|
||||
filename := filepath.Join("testdata", "invalid_duration.toml")
|
||||
conf.InitConfig(filename, false)
|
||||
conf.Load(true)
|
||||
|
||||
server := conf.Server
|
||||
Expect(server.SessionTimeout).To(Equal(consts.DefaultSessionTimeout))
|
||||
Expect(server.SmartPlaylistRefreshDelay).To(Equal(consts.DefaultSmartRefresh))
|
||||
Expect(server.DefaultShareExpiration).To(Equal(consts.DefaultShareExpiration))
|
||||
Expect(server.UIPlaybackReportInterval).To(Equal(consts.DefaultUIPlaybackReportInterval))
|
||||
Expect(server.AuthWindowLength).To(Equal(consts.DefaultAuthWindowLength))
|
||||
Expect(server.Scanner.WatcherWait).To(Equal(consts.DefaultWatcherWait))
|
||||
|
||||
Expect(server.DevActivityPanelUpdateRate).To(Equal(consts.DefaultActivityPanelUpdateRate))
|
||||
Expect(server.DevArtworkThrottleBacklogTimeout).To(Equal(consts.RequestThrottleBacklogTimeout))
|
||||
Expect(server.DevArtistInfoTimeToLive).To(Equal(consts.ArtistInfoTimeToLive))
|
||||
Expect(server.DevAlbumInfoTimeToLive).To(Equal(consts.AlbumInfoTimeToLive))
|
||||
Expect(server.DevInsightsInitialDelay).To(Equal(consts.InsightsInitialDelay))
|
||||
Expect(server.DevPluginCompilationTimeout).To(Equal(consts.DefaultPluginCompilationTimeout))
|
||||
})
|
||||
|
||||
It("should use parsed values for duration fields", func() {
|
||||
conf.InitConfig(filepath.Join("testdata", "valid_duration.toml"), false)
|
||||
conf.Load(true)
|
||||
|
||||
configured := 1 * time.Second
|
||||
|
||||
server := conf.Server
|
||||
Expect(server.SessionTimeout).To(Equal(configured))
|
||||
Expect(server.SmartPlaylistRefreshDelay).To(Equal(configured))
|
||||
Expect(server.DefaultShareExpiration).To(Equal(configured))
|
||||
Expect(server.UIPlaybackReportInterval).To(Equal(configured))
|
||||
Expect(server.AuthWindowLength).To(Equal(configured))
|
||||
Expect(server.Scanner.WatcherWait).To(Equal(configured))
|
||||
|
||||
Expect(server.DevActivityPanelUpdateRate).To(Equal(configured))
|
||||
Expect(server.DevArtworkThrottleBacklogTimeout).To(Equal(configured))
|
||||
Expect(server.DevArtistInfoTimeToLive).To(Equal(configured))
|
||||
Expect(server.DevAlbumInfoTimeToLive).To(Equal(configured))
|
||||
Expect(server.DevInsightsInitialDelay).To(Equal(configured))
|
||||
Expect(server.DevPluginCompilationTimeout).To(Equal(configured))
|
||||
})
|
||||
})
|
||||
|
||||
var _ = Describe("TLSEnabled", func() {
|
||||
|
|
|
|||
12
conf/testdata/invalid_duration.toml
vendored
Normal file
12
conf/testdata/invalid_duration.toml
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
SessionTimeout = "-10s"
|
||||
SmartPlaylistRefreshDelay = "-10s"
|
||||
UIPlaybackReportInterval = "-10s"
|
||||
AuthWindowLength = "-10s"
|
||||
DefaultShareExpiration = "-10s"
|
||||
Scanner.WatcherWait = "-10s"
|
||||
DevActivityPanelUpdateRate = "-10s"
|
||||
DevArtworkThrottleBacklogTimeout = "-10s"
|
||||
DevArtistInfoTimeToLive = "-10s"
|
||||
DevAlbumInfoTimeToLive = "-10s"
|
||||
DevInsightsInitialDelay = "-10s"
|
||||
DevPluginCompilationTimeout = "-10s"
|
||||
12
conf/testdata/valid_duration.toml
vendored
Normal file
12
conf/testdata/valid_duration.toml
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
SessionTimeout = "1s"
|
||||
SmartPlaylistRefreshDelay = "1s"
|
||||
UIPlaybackReportInterval = "1s"
|
||||
AuthWindowLength = "1s"
|
||||
DefaultShareExpiration = "1s"
|
||||
Scanner.WatcherWait = "1s"
|
||||
DevActivityPanelUpdateRate = "1s"
|
||||
DevArtworkThrottleBacklogTimeout = "1s"
|
||||
DevArtistInfoTimeToLive = "1s"
|
||||
DevAlbumInfoTimeToLive = "1s"
|
||||
DevInsightsInitialDelay = "1s"
|
||||
DevPluginCompilationTimeout = "1s"
|
||||
|
|
@ -34,6 +34,8 @@ const (
|
|||
JWTPublicSecretKey = "JWTPublicSecret"
|
||||
JWTIssuer = "ND"
|
||||
DefaultSessionTimeout = 48 * time.Hour
|
||||
DefaultSmartRefresh = 5 * time.Second
|
||||
DefaultShareExpiration = 8760 * time.Hour
|
||||
CookieExpiry = 365 * 24 * 3600 // One year
|
||||
|
||||
DBAnalyzeCheckSchedule = "@every 30m"
|
||||
|
|
@ -71,6 +73,7 @@ const (
|
|||
DefaultUILoginBackgroundURLOffline = "data:image/png;base64," + DefaultUILoginBackgroundOffline
|
||||
DefaultMaxSidebarPlaylists = 100
|
||||
|
||||
DefaultAuthWindowLength = 20 * time.Second
|
||||
RequestThrottleBacklogLimit = 100
|
||||
RequestThrottleBacklogTimeout = time.Minute
|
||||
|
||||
|
|
@ -106,6 +109,9 @@ const (
|
|||
DefaultScannerExtractor = "taglib"
|
||||
DefaultWatcherWait = 5 * time.Second
|
||||
Zwsp = string('\u200b')
|
||||
|
||||
DefaultActivityPanelUpdateRate = 300 * time.Millisecond
|
||||
DefaultPluginCompilationTimeout = time.Minute
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue