Fix setting pointers corrupting config in memory (#4868)

This commit is contained in:
WithoutPants 2024-05-23 10:56:18 +10:00 committed by GitHub
parent 77ef16570b
commit 4794a1d453
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 238 additions and 287 deletions

View file

@ -41,8 +41,8 @@ func (r *mutationResolver) DownloadFFMpeg(ctx context.Context) (string, error) {
OnComplete: func(ctx context.Context) {
// clear the ffmpeg and ffprobe paths
logger.Infof("Clearing ffmpeg and ffprobe config paths so they are resolved from the config directory")
mgr.Config.Set(config.FFMpegPath, "")
mgr.Config.Set(config.FFProbePath, "")
mgr.Config.SetString(config.FFMpegPath, "")
mgr.Config.SetString(config.FFProbePath, "")
mgr.RefreshFFMpeg(ctx)
mgr.RefreshStreamManager()
},
@ -53,6 +53,34 @@ func (r *mutationResolver) DownloadFFMpeg(ctx context.Context) (string, error) {
return strconv.Itoa(jobID), nil
}
func (r *mutationResolver) setConfigString(key string, value *string) {
c := config.GetInstance()
if value != nil {
c.SetString(key, *value)
}
}
func (r *mutationResolver) setConfigBool(key string, value *bool) {
c := config.GetInstance()
if value != nil {
c.SetBool(key, *value)
}
}
func (r *mutationResolver) setConfigInt(key string, value *int) {
c := config.GetInstance()
if value != nil {
c.SetInt(key, *value)
}
}
func (r *mutationResolver) setConfigFloat(key string, value *float64) {
c := config.GetInstance()
if value != nil {
c.SetFloat(key, *value)
}
}
func (r *mutationResolver) ConfigureGeneral(ctx context.Context, input ConfigGeneralInput) (*ConfigGeneralResult, error) {
c := config.GetInstance()
@ -74,7 +102,7 @@ func (r *mutationResolver) ConfigureGeneral(ctx context.Context, input ConfigGen
}
}
}
c.Set(config.Stash, input.Stashes)
c.SetInterface(config.Stash, input.Stashes)
}
checkConfigOverride := func(key string) error {
@ -109,7 +137,7 @@ func (r *mutationResolver) ConfigureGeneral(ctx context.Context, input ConfigGen
if ext != ".db" && ext != ".sqlite" && ext != ".sqlite3" {
return makeConfigGeneralResult(), fmt.Errorf("invalid database path, use extension db, sqlite, or sqlite3")
}
c.Set(config.Database, input.DatabasePath)
c.SetString(config.Database, *input.DatabasePath)
}
existingBackupDirectoryPath := c.GetBackupDirectoryPath()
@ -118,7 +146,7 @@ func (r *mutationResolver) ConfigureGeneral(ctx context.Context, input ConfigGen
return makeConfigGeneralResult(), err
}
c.Set(config.BackupDirectoryPath, input.BackupDirectoryPath)
c.SetString(config.BackupDirectoryPath, *input.BackupDirectoryPath)
}
existingGeneratedPath := c.GetGeneratedPath()
@ -127,7 +155,7 @@ func (r *mutationResolver) ConfigureGeneral(ctx context.Context, input ConfigGen
return makeConfigGeneralResult(), err
}
c.Set(config.Generated, input.GeneratedPath)
c.SetString(config.Generated, *input.GeneratedPath)
}
refreshScraperCache := false
@ -140,7 +168,7 @@ func (r *mutationResolver) ConfigureGeneral(ctx context.Context, input ConfigGen
refreshScraperCache = true
refreshScraperSource = true
c.Set(config.ScrapersPath, input.ScrapersPath)
c.SetString(config.ScrapersPath, *input.ScrapersPath)
}
refreshPluginCache := false
@ -153,7 +181,7 @@ func (r *mutationResolver) ConfigureGeneral(ctx context.Context, input ConfigGen
refreshPluginCache = true
refreshPluginSource = true
c.Set(config.PluginsPath, input.PluginsPath)
c.SetString(config.PluginsPath, *input.PluginsPath)
}
existingMetadataPath := c.GetMetadataPath()
@ -162,7 +190,7 @@ func (r *mutationResolver) ConfigureGeneral(ctx context.Context, input ConfigGen
return makeConfigGeneralResult(), err
}
c.Set(config.Metadata, input.MetadataPath)
c.SetString(config.Metadata, *input.MetadataPath)
}
refreshStreamManager := false
@ -172,7 +200,7 @@ func (r *mutationResolver) ConfigureGeneral(ctx context.Context, input ConfigGen
return makeConfigGeneralResult(), err
}
c.Set(config.Cache, input.CachePath)
c.SetString(config.Cache, *input.CachePath)
refreshStreamManager = true
}
@ -183,7 +211,7 @@ func (r *mutationResolver) ConfigureGeneral(ctx context.Context, input ConfigGen
return makeConfigGeneralResult(), err
}
c.Set(config.BlobsPath, input.BlobsPath)
c.SetString(config.BlobsPath, *input.BlobsPath)
refreshBlobStorage = true
}
@ -192,7 +220,7 @@ func (r *mutationResolver) ConfigureGeneral(ctx context.Context, input ConfigGen
return makeConfigGeneralResult(), fmt.Errorf("blobs path must be set when using filesystem storage")
}
c.Set(config.BlobsStorage, input.BlobsStorage)
c.SetInterface(config.BlobsStorage, *input.BlobsStorage)
refreshBlobStorage = true
}
@ -205,7 +233,7 @@ func (r *mutationResolver) ConfigureGeneral(ctx context.Context, input ConfigGen
}
}
c.Set(config.FFMpegPath, input.FfmpegPath)
c.SetString(config.FFMpegPath, *input.FfmpegPath)
refreshFfmpeg = true
}
@ -216,7 +244,7 @@ func (r *mutationResolver) ConfigureGeneral(ctx context.Context, input ConfigGen
}
}
c.Set(config.FFProbePath, input.FfprobePath)
c.SetString(config.FFProbePath, *input.FfprobePath)
refreshFfmpeg = true
}
@ -236,68 +264,42 @@ func (r *mutationResolver) ConfigureGeneral(ctx context.Context, input ConfigGen
return makeConfigGeneralResult(), err
}
c.Set(config.VideoFileNamingAlgorithm, *input.VideoFileNamingAlgorithm)
c.SetInterface(config.VideoFileNamingAlgorithm, *input.VideoFileNamingAlgorithm)
}
if input.CalculateMd5 != nil {
c.Set(config.CalculateMD5, *input.CalculateMd5)
}
if input.ParallelTasks != nil {
c.Set(config.ParallelTasks, *input.ParallelTasks)
}
if input.PreviewAudio != nil {
c.Set(config.PreviewAudio, *input.PreviewAudio)
}
if input.PreviewSegments != nil {
c.Set(config.PreviewSegments, *input.PreviewSegments)
}
if input.PreviewSegmentDuration != nil {
c.Set(config.PreviewSegmentDuration, *input.PreviewSegmentDuration)
}
if input.PreviewExcludeStart != nil {
c.Set(config.PreviewExcludeStart, *input.PreviewExcludeStart)
}
if input.PreviewExcludeEnd != nil {
c.Set(config.PreviewExcludeEnd, *input.PreviewExcludeEnd)
}
r.setConfigBool(config.CalculateMD5, input.CalculateMd5)
r.setConfigInt(config.ParallelTasks, input.ParallelTasks)
r.setConfigBool(config.PreviewAudio, input.PreviewAudio)
r.setConfigInt(config.PreviewSegments, input.PreviewSegments)
r.setConfigFloat(config.PreviewSegmentDuration, input.PreviewSegmentDuration)
r.setConfigString(config.PreviewExcludeStart, input.PreviewExcludeStart)
r.setConfigString(config.PreviewExcludeEnd, input.PreviewExcludeEnd)
if input.PreviewPreset != nil {
c.Set(config.PreviewPreset, input.PreviewPreset.String())
c.SetString(config.PreviewPreset, input.PreviewPreset.String())
}
if input.TranscodeHardwareAcceleration != nil {
c.Set(config.TranscodeHardwareAcceleration, *input.TranscodeHardwareAcceleration)
}
r.setConfigBool(config.TranscodeHardwareAcceleration, input.TranscodeHardwareAcceleration)
if input.MaxTranscodeSize != nil {
c.Set(config.MaxTranscodeSize, input.MaxTranscodeSize.String())
c.SetString(config.MaxTranscodeSize, input.MaxTranscodeSize.String())
}
if input.MaxStreamingTranscodeSize != nil {
c.Set(config.MaxStreamingTranscodeSize, input.MaxStreamingTranscodeSize.String())
}
if input.WriteImageThumbnails != nil {
c.Set(config.WriteImageThumbnails, *input.WriteImageThumbnails)
}
if input.CreateImageClipsFromVideos != nil {
c.Set(config.CreateImageClipsFromVideos, *input.CreateImageClipsFromVideos)
c.SetString(config.MaxStreamingTranscodeSize, input.MaxStreamingTranscodeSize.String())
}
r.setConfigBool(config.WriteImageThumbnails, input.WriteImageThumbnails)
r.setConfigBool(config.CreateImageClipsFromVideos, input.CreateImageClipsFromVideos)
if input.GalleryCoverRegex != nil {
_, err := regexp.Compile(*input.GalleryCoverRegex)
if err != nil {
return makeConfigGeneralResult(), fmt.Errorf("Gallery cover regex '%v' invalid, '%v'", *input.GalleryCoverRegex, err.Error())
}
c.Set(config.GalleryCoverRegex, *input.GalleryCoverRegex)
c.SetString(config.GalleryCoverRegex, *input.GalleryCoverRegex)
}
if input.Username != nil && *input.Username != c.GetUsername() {
c.Set(config.Username, input.Username)
c.SetString(config.Username, *input.Username)
if *input.Password == "" {
logger.Info("Username cleared")
} else {
@ -320,24 +322,13 @@ func (r *mutationResolver) ConfigureGeneral(ctx context.Context, input ConfigGen
}
}
if input.MaxSessionAge != nil {
c.Set(config.MaxSessionAge, *input.MaxSessionAge)
}
if input.LogFile != nil {
c.Set(config.LogFile, input.LogFile)
}
if input.LogOut != nil {
c.Set(config.LogOut, *input.LogOut)
}
if input.LogAccess != nil {
c.Set(config.LogAccess, *input.LogAccess)
}
r.setConfigInt(config.MaxSessionAge, input.MaxSessionAge)
r.setConfigString(config.LogFile, input.LogFile)
r.setConfigBool(config.LogOut, input.LogOut)
r.setConfigBool(config.LogAccess, input.LogAccess)
if input.LogLevel != nil && *input.LogLevel != c.GetLogLevel() {
c.Set(config.LogLevel, input.LogLevel)
c.SetString(config.LogLevel, *input.LogLevel)
logger := manager.GetInstance().Logger
logger.SetLogLevel(*input.LogLevel)
}
@ -349,7 +340,7 @@ func (r *mutationResolver) ConfigureGeneral(ctx context.Context, input ConfigGen
return makeConfigGeneralResult(), fmt.Errorf("video exclusion pattern '%v' invalid: %w", r, err)
}
}
c.Set(config.Exclude, input.Excludes)
c.SetInterface(config.Exclude, input.Excludes)
}
if input.ImageExcludes != nil {
@ -359,27 +350,25 @@ func (r *mutationResolver) ConfigureGeneral(ctx context.Context, input ConfigGen
return makeConfigGeneralResult(), fmt.Errorf("image/gallery exclusion pattern '%v' invalid: %w", r, err)
}
}
c.Set(config.ImageExclude, input.ImageExcludes)
c.SetInterface(config.ImageExclude, input.ImageExcludes)
}
if input.VideoExtensions != nil {
c.Set(config.VideoExtensions, input.VideoExtensions)
c.SetInterface(config.VideoExtensions, input.VideoExtensions)
}
if input.ImageExtensions != nil {
c.Set(config.ImageExtensions, input.ImageExtensions)
c.SetInterface(config.ImageExtensions, input.ImageExtensions)
}
if input.GalleryExtensions != nil {
c.Set(config.GalleryExtensions, input.GalleryExtensions)
c.SetInterface(config.GalleryExtensions, input.GalleryExtensions)
}
if input.CreateGalleriesFromFolders != nil {
c.Set(config.CreateGalleriesFromFolders, input.CreateGalleriesFromFolders)
}
r.setConfigBool(config.CreateGalleriesFromFolders, input.CreateGalleriesFromFolders)
if input.CustomPerformerImageLocation != nil {
c.Set(config.CustomPerformerImageLocation, *input.CustomPerformerImageLocation)
c.SetString(config.CustomPerformerImageLocation, *input.CustomPerformerImageLocation)
initCustomPerformerImages(*input.CustomPerformerImageLocation)
}
@ -387,37 +376,35 @@ func (r *mutationResolver) ConfigureGeneral(ctx context.Context, input ConfigGen
if err := c.ValidateStashBoxes(input.StashBoxes); err != nil {
return nil, err
}
c.Set(config.StashBoxes, input.StashBoxes)
c.SetInterface(config.StashBoxes, input.StashBoxes)
}
if input.PythonPath != nil {
c.Set(config.PythonPath, input.PythonPath)
r.setConfigString(config.PythonPath, input.PythonPath)
}
if input.TranscodeInputArgs != nil {
c.Set(config.TranscodeInputArgs, input.TranscodeInputArgs)
c.SetInterface(config.TranscodeInputArgs, input.TranscodeInputArgs)
}
if input.TranscodeOutputArgs != nil {
c.Set(config.TranscodeOutputArgs, input.TranscodeOutputArgs)
c.SetInterface(config.TranscodeOutputArgs, input.TranscodeOutputArgs)
}
if input.LiveTranscodeInputArgs != nil {
c.Set(config.LiveTranscodeInputArgs, input.LiveTranscodeInputArgs)
c.SetInterface(config.LiveTranscodeInputArgs, input.LiveTranscodeInputArgs)
}
if input.LiveTranscodeOutputArgs != nil {
c.Set(config.LiveTranscodeOutputArgs, input.LiveTranscodeOutputArgs)
c.SetInterface(config.LiveTranscodeOutputArgs, input.LiveTranscodeOutputArgs)
}
if input.DrawFunscriptHeatmapRange != nil {
c.Set(config.DrawFunscriptHeatmapRange, input.DrawFunscriptHeatmapRange)
}
r.setConfigBool(config.DrawFunscriptHeatmapRange, input.DrawFunscriptHeatmapRange)
if input.ScraperPackageSources != nil {
c.Set(config.ScraperPackageSources, input.ScraperPackageSources)
c.SetInterface(config.ScraperPackageSources, input.ScraperPackageSources)
refreshScraperSource = true
}
if input.PluginPackageSources != nil {
c.Set(config.PluginPackageSources, input.PluginPackageSources)
c.SetInterface(config.PluginPackageSources, input.PluginPackageSources)
refreshPluginSource = true
}
@ -457,102 +444,70 @@ func (r *mutationResolver) ConfigureGeneral(ctx context.Context, input ConfigGen
func (r *mutationResolver) ConfigureInterface(ctx context.Context, input ConfigInterfaceInput) (*ConfigInterfaceResult, error) {
c := config.GetInstance()
setBool := func(key string, v *bool) {
if v != nil {
c.Set(key, *v)
}
}
setString := func(key string, v *string) {
if v != nil {
c.Set(key, *v)
}
}
if input.MenuItems != nil {
c.Set(config.MenuItems, input.MenuItems)
c.SetInterface(config.MenuItems, input.MenuItems)
}
setBool(config.SoundOnPreview, input.SoundOnPreview)
setBool(config.WallShowTitle, input.WallShowTitle)
r.setConfigBool(config.SoundOnPreview, input.SoundOnPreview)
r.setConfigBool(config.WallShowTitle, input.WallShowTitle)
setBool(config.NoBrowser, input.NoBrowser)
r.setConfigBool(config.NoBrowser, input.NoBrowser)
setBool(config.NotificationsEnabled, input.NotificationsEnabled)
r.setConfigBool(config.NotificationsEnabled, input.NotificationsEnabled)
setBool(config.ShowScrubber, input.ShowScrubber)
r.setConfigBool(config.ShowScrubber, input.ShowScrubber)
if input.WallPlayback != nil {
c.Set(config.WallPlayback, *input.WallPlayback)
}
r.setConfigString(config.WallPlayback, input.WallPlayback)
r.setConfigInt(config.MaximumLoopDuration, input.MaximumLoopDuration)
r.setConfigBool(config.AutostartVideo, input.AutostartVideo)
r.setConfigBool(config.ShowStudioAsText, input.ShowStudioAsText)
r.setConfigBool(config.AutostartVideoOnPlaySelected, input.AutostartVideoOnPlaySelected)
r.setConfigBool(config.ContinuePlaylistDefault, input.ContinuePlaylistDefault)
if input.MaximumLoopDuration != nil {
c.Set(config.MaximumLoopDuration, *input.MaximumLoopDuration)
}
setBool(config.AutostartVideo, input.AutostartVideo)
setBool(config.ShowStudioAsText, input.ShowStudioAsText)
setBool(config.AutostartVideoOnPlaySelected, input.AutostartVideoOnPlaySelected)
setBool(config.ContinuePlaylistDefault, input.ContinuePlaylistDefault)
if input.Language != nil {
c.Set(config.Language, *input.Language)
}
r.setConfigString(config.Language, input.Language)
if input.ImageLightbox != nil {
options := input.ImageLightbox
if options.SlideshowDelay != nil {
c.Set(config.ImageLightboxSlideshowDelay, *options.SlideshowDelay)
}
r.setConfigInt(config.ImageLightboxSlideshowDelay, options.SlideshowDelay)
setString(config.ImageLightboxDisplayModeKey, (*string)(options.DisplayMode))
setBool(config.ImageLightboxScaleUp, options.ScaleUp)
setBool(config.ImageLightboxResetZoomOnNav, options.ResetZoomOnNav)
setString(config.ImageLightboxScrollModeKey, (*string)(options.ScrollMode))
r.setConfigString(config.ImageLightboxDisplayModeKey, (*string)(options.DisplayMode))
r.setConfigBool(config.ImageLightboxScaleUp, options.ScaleUp)
r.setConfigBool(config.ImageLightboxResetZoomOnNav, options.ResetZoomOnNav)
r.setConfigString(config.ImageLightboxScrollModeKey, (*string)(options.ScrollMode))
if options.ScrollAttemptsBeforeChange != nil {
c.Set(config.ImageLightboxScrollAttemptsBeforeChange, *options.ScrollAttemptsBeforeChange)
}
r.setConfigInt(config.ImageLightboxScrollAttemptsBeforeChange, options.ScrollAttemptsBeforeChange)
}
if input.CSS != nil {
c.SetCSS(*input.CSS)
}
setBool(config.CSSEnabled, input.CSSEnabled)
r.setConfigBool(config.CSSEnabled, input.CSSEnabled)
if input.Javascript != nil {
c.SetJavascript(*input.Javascript)
}
setBool(config.JavascriptEnabled, input.JavascriptEnabled)
r.setConfigBool(config.JavascriptEnabled, input.JavascriptEnabled)
if input.CustomLocales != nil {
c.SetCustomLocales(*input.CustomLocales)
}
setBool(config.CustomLocalesEnabled, input.CustomLocalesEnabled)
r.setConfigBool(config.CustomLocalesEnabled, input.CustomLocalesEnabled)
if input.DisableDropdownCreate != nil {
ddc := input.DisableDropdownCreate
setBool(config.DisableDropdownCreatePerformer, ddc.Performer)
setBool(config.DisableDropdownCreateStudio, ddc.Studio)
setBool(config.DisableDropdownCreateTag, ddc.Tag)
setBool(config.DisableDropdownCreateMovie, ddc.Movie)
r.setConfigBool(config.DisableDropdownCreatePerformer, ddc.Performer)
r.setConfigBool(config.DisableDropdownCreateStudio, ddc.Studio)
r.setConfigBool(config.DisableDropdownCreateTag, ddc.Tag)
r.setConfigBool(config.DisableDropdownCreateMovie, ddc.Movie)
}
if input.HandyKey != nil {
c.Set(config.HandyKey, *input.HandyKey)
}
if input.FunscriptOffset != nil {
c.Set(config.FunscriptOffset, *input.FunscriptOffset)
}
if input.UseStashHostedFunscript != nil {
c.Set(config.UseStashHostedFunscript, *input.UseStashHostedFunscript)
}
r.setConfigString(config.HandyKey, input.HandyKey)
r.setConfigInt(config.FunscriptOffset, input.FunscriptOffset)
r.setConfigBool(config.UseStashHostedFunscript, input.UseStashHostedFunscript)
if err := c.Write(); err != nil {
return makeConfigInterfaceResult(), err
@ -564,30 +519,23 @@ func (r *mutationResolver) ConfigureInterface(ctx context.Context, input ConfigI
func (r *mutationResolver) ConfigureDlna(ctx context.Context, input ConfigDLNAInput) (*ConfigDLNAResult, error) {
c := config.GetInstance()
if input.ServerName != nil {
c.Set(config.DLNAServerName, *input.ServerName)
}
r.setConfigString(config.DLNAServerName, input.ServerName)
if input.WhitelistedIPs != nil {
c.Set(config.DLNADefaultIPWhitelist, input.WhitelistedIPs)
c.SetInterface(config.DLNADefaultIPWhitelist, input.WhitelistedIPs)
}
if input.VideoSortOrder != nil {
c.Set(config.DLNAVideoSortOrder, input.VideoSortOrder)
}
if input.Port != nil {
c.Set(config.DLNAPort, *input.Port)
}
r.setConfigString(config.DLNAVideoSortOrder, input.VideoSortOrder)
r.setConfigInt(config.DLNAPort, input.Port)
refresh := false
if input.Enabled != nil {
c.Set(config.DLNADefaultEnabled, *input.Enabled)
c.SetBool(config.DLNADefaultEnabled, *input.Enabled)
refresh = true
}
if input.Interfaces != nil {
c.Set(config.DLNAInterfaces, input.Interfaces)
c.SetInterface(config.DLNAInterfaces, input.Interfaces)
}
if err := c.Write(); err != nil {
@ -606,12 +554,12 @@ func (r *mutationResolver) ConfigureScraping(ctx context.Context, input ConfigSc
refreshScraperCache := false
if input.ScraperUserAgent != nil {
c.Set(config.ScraperUserAgent, input.ScraperUserAgent)
c.SetString(config.ScraperUserAgent, *input.ScraperUserAgent)
refreshScraperCache = true
}
if input.ScraperCDPPath != nil {
c.Set(config.ScraperCDPPath, input.ScraperCDPPath)
c.SetString(config.ScraperCDPPath, *input.ScraperCDPPath)
refreshScraperCache = true
}
@ -622,12 +570,10 @@ func (r *mutationResolver) ConfigureScraping(ctx context.Context, input ConfigSc
return makeConfigScrapingResult(), fmt.Errorf("tag exclusion pattern '%v' invalid: %w", r, err)
}
}
c.Set(config.ScraperExcludeTagPatterns, input.ExcludeTagPatterns)
c.SetInterface(config.ScraperExcludeTagPatterns, input.ExcludeTagPatterns)
}
if input.ScraperCertCheck != nil {
c.Set(config.ScraperCertCheck, input.ScraperCertCheck)
}
r.setConfigBool(config.ScraperCertCheck, input.ScraperCertCheck)
if refreshScraperCache {
manager.GetInstance().RefreshScraperCache()
@ -643,30 +589,25 @@ func (r *mutationResolver) ConfigureDefaults(ctx context.Context, input ConfigDe
c := config.GetInstance()
if input.Identify != nil {
c.Set(config.DefaultIdentifySettings, input.Identify)
c.SetInterface(config.DefaultIdentifySettings, input.Identify)
}
if input.Scan != nil {
// if input.Scan is used then ScanMetadataOptions is included in the config file
// this causes the values to not be read correctly
c.Set(config.DefaultScanSettings, input.Scan.ScanMetadataOptions)
c.SetInterface(config.DefaultScanSettings, input.Scan.ScanMetadataOptions)
}
if input.AutoTag != nil {
c.Set(config.DefaultAutoTagSettings, input.AutoTag)
c.SetInterface(config.DefaultAutoTagSettings, input.AutoTag)
}
if input.Generate != nil {
c.Set(config.DefaultGenerateSettings, input.Generate)
c.SetInterface(config.DefaultGenerateSettings, input.Generate)
}
if input.DeleteFile != nil {
c.Set(config.DeleteFileDefault, *input.DeleteFile)
}
if input.DeleteGenerated != nil {
c.Set(config.DeleteGeneratedDefault, *input.DeleteGenerated)
}
r.setConfigBool(config.DeleteFileDefault, input.DeleteFile)
r.setConfigBool(config.DeleteGeneratedDefault, input.DeleteGenerated)
if err := c.Write(); err != nil {
return makeConfigDefaultsResult(), err
@ -690,7 +631,7 @@ func (r *mutationResolver) GenerateAPIKey(ctx context.Context, input GenerateAPI
}
}
c.Set(config.ApiKey, newAPIKey)
c.SetString(config.ApiKey, newAPIKey)
if err := c.Write(); err != nil {
return newAPIKey, err
}

View file

@ -103,7 +103,7 @@ func (r *mutationResolver) SetPluginsEnabled(ctx context.Context, enabledMap map
}
}
c.Set(config.DisabledPlugins, newDisabled)
c.SetInterface(config.DisabledPlugins, newDisabled)
if err := c.Write(); err != nil {
return false, err

View file

@ -21,7 +21,7 @@ func startSystray(exit chan int, faviconProvider FaviconProvider) {
c := config.GetInstance()
if c.GetShowOneTimeMovedNotification() {
SendNotification("Stash has moved!", "Stash now runs in your tray, instead of a terminal window.")
c.Set(config.ShowOneTimeMovedNotification, false)
c.SetBool(config.ShowOneTimeMovedNotification, false)
if err := c.Write(); err != nil {
logger.Errorf("Error while writing configuration file: %v", err)
}

View file

@ -381,10 +381,6 @@ func (i *Config) GetNotificationsEnabled() bool {
return i.getBool(NotificationsEnabled)
}
// func (i *Instance) GetConfigUpdatesChannel() chan int {
// return i.configUpdates
// }
// GetShowOneTimeMovedNotification shows whether a small notification to inform the user that Stash
// will no longer show a terminal window, and instead will be available in the tray, should be shown.
// It is true when an existing system is started after upgrading, and set to false forever after it is shown.
@ -392,10 +388,24 @@ func (i *Config) GetShowOneTimeMovedNotification() bool {
return i.getBool(ShowOneTimeMovedNotification)
}
func (i *Config) Set(key string, value interface{}) {
// if key == MenuItems {
// i.configUpdates <- 0
// }
// these methods are intended to ensure type safety (ie no primitive pointers)
func (i *Config) SetBool(key string, value bool) {
i.SetInterface(key, value)
}
func (i *Config) SetString(key string, value string) {
i.SetInterface(key, value)
}
func (i *Config) SetInt(key string, value int) {
i.SetInterface(key, value)
}
func (i *Config) SetFloat(key string, value float64) {
i.SetInterface(key, value)
}
func (i *Config) SetInterface(key string, value interface{}) {
i.Lock()
defer i.Unlock()
@ -438,9 +448,9 @@ func (i *Config) setDefault(key string, value interface{}) {
func (i *Config) SetPassword(value string) {
// if blank, don't bother hashing; we want it to be blank
if value == "" {
i.Set(Password, "")
i.SetString(Password, "")
} else {
i.Set(Password, hashPassword(value))
i.SetString(Password, hashPassword(value))
}
}
@ -1624,7 +1634,7 @@ func (i *Config) GetNoProxy() string {
// config field to the provided IP address to indicate that stash has been accessed
// from this public IP without authentication.
func (i *Config) ActivatePublicAccessTripwire(requestIP string) error {
i.Set(SecurityTripwireAccessedFromPublicInternet, requestIP)
i.SetString(SecurityTripwireAccessedFromPublicInternet, requestIP)
return i.Write()
}
@ -1807,7 +1817,7 @@ func (i *Config) SetInitialConfig() error {
if err != nil {
return fmt.Errorf("error generating JWTSignKey: %w", err)
}
i.Set(JWTSignKey, signKey)
i.SetString(JWTSignKey, signKey)
}
if string(i.GetSessionStoreKey()) == "" {
@ -1815,7 +1825,7 @@ func (i *Config) SetInitialConfig() error {
if err != nil {
return fmt.Errorf("error generating session store key: %w", err)
}
i.Set(SessionStoreKey, sessionStoreKey)
i.SetString(SessionStoreKey, sessionStoreKey)
}
i.setDefaultValues()

View file

@ -27,101 +27,101 @@ func TestConcurrentConfigAccess(t *testing.T) {
i.GetConfigFile()
i.GetConfigPath()
i.GetDefaultDatabaseFilePath()
i.Set(BackupDirectoryPath, i.GetBackupDirectoryPath())
i.SetInterface(BackupDirectoryPath, i.GetBackupDirectoryPath())
i.GetStashPaths()
_ = i.ValidateStashBoxes(nil)
_ = i.Validate()
_ = i.ActivatePublicAccessTripwire("")
i.Set(Cache, i.GetCachePath())
i.Set(Generated, i.GetGeneratedPath())
i.Set(Metadata, i.GetMetadataPath())
i.Set(Database, i.GetDatabasePath())
i.SetInterface(Cache, i.GetCachePath())
i.SetInterface(Generated, i.GetGeneratedPath())
i.SetInterface(Metadata, i.GetMetadataPath())
i.SetInterface(Database, i.GetDatabasePath())
// these must be set as strings since the original values are also strings
// setting them as []byte will cause the returned string to be corrupted
i.Set(JWTSignKey, string(i.GetJWTSignKey()))
i.Set(SessionStoreKey, string(i.GetSessionStoreKey()))
i.SetInterface(JWTSignKey, string(i.GetJWTSignKey()))
i.SetInterface(SessionStoreKey, string(i.GetSessionStoreKey()))
i.GetDefaultScrapersPath()
i.Set(Exclude, i.GetExcludes())
i.Set(ImageExclude, i.GetImageExcludes())
i.Set(VideoExtensions, i.GetVideoExtensions())
i.Set(ImageExtensions, i.GetImageExtensions())
i.Set(GalleryExtensions, i.GetGalleryExtensions())
i.Set(CreateGalleriesFromFolders, i.GetCreateGalleriesFromFolders())
i.Set(Language, i.GetLanguage())
i.Set(VideoFileNamingAlgorithm, i.GetVideoFileNamingAlgorithm())
i.Set(ScrapersPath, i.GetScrapersPath())
i.Set(ScraperUserAgent, i.GetScraperUserAgent())
i.Set(ScraperCDPPath, i.GetScraperCDPPath())
i.Set(ScraperCertCheck, i.GetScraperCertCheck())
i.Set(ScraperExcludeTagPatterns, i.GetScraperExcludeTagPatterns())
i.Set(StashBoxes, i.GetStashBoxes())
i.SetInterface(Exclude, i.GetExcludes())
i.SetInterface(ImageExclude, i.GetImageExcludes())
i.SetInterface(VideoExtensions, i.GetVideoExtensions())
i.SetInterface(ImageExtensions, i.GetImageExtensions())
i.SetInterface(GalleryExtensions, i.GetGalleryExtensions())
i.SetInterface(CreateGalleriesFromFolders, i.GetCreateGalleriesFromFolders())
i.SetInterface(Language, i.GetLanguage())
i.SetInterface(VideoFileNamingAlgorithm, i.GetVideoFileNamingAlgorithm())
i.SetInterface(ScrapersPath, i.GetScrapersPath())
i.SetInterface(ScraperUserAgent, i.GetScraperUserAgent())
i.SetInterface(ScraperCDPPath, i.GetScraperCDPPath())
i.SetInterface(ScraperCertCheck, i.GetScraperCertCheck())
i.SetInterface(ScraperExcludeTagPatterns, i.GetScraperExcludeTagPatterns())
i.SetInterface(StashBoxes, i.GetStashBoxes())
i.GetDefaultPluginsPath()
i.Set(PluginsPath, i.GetPluginsPath())
i.Set(Host, i.GetHost())
i.Set(Port, i.GetPort())
i.Set(ExternalHost, i.GetExternalHost())
i.Set(PreviewSegmentDuration, i.GetPreviewSegmentDuration())
i.Set(ParallelTasks, i.GetParallelTasks())
i.Set(ParallelTasks, i.GetParallelTasksWithAutoDetection())
i.Set(PreviewAudio, i.GetPreviewAudio())
i.Set(PreviewSegments, i.GetPreviewSegments())
i.Set(PreviewExcludeStart, i.GetPreviewExcludeStart())
i.Set(PreviewExcludeEnd, i.GetPreviewExcludeEnd())
i.Set(PreviewPreset, i.GetPreviewPreset())
i.Set(MaxTranscodeSize, i.GetMaxTranscodeSize())
i.Set(MaxStreamingTranscodeSize, i.GetMaxStreamingTranscodeSize())
i.Set(ApiKey, i.GetAPIKey())
i.Set(Username, i.GetUsername())
i.Set(Password, i.GetPasswordHash())
i.SetInterface(PluginsPath, i.GetPluginsPath())
i.SetInterface(Host, i.GetHost())
i.SetInterface(Port, i.GetPort())
i.SetInterface(ExternalHost, i.GetExternalHost())
i.SetInterface(PreviewSegmentDuration, i.GetPreviewSegmentDuration())
i.SetInterface(ParallelTasks, i.GetParallelTasks())
i.SetInterface(ParallelTasks, i.GetParallelTasksWithAutoDetection())
i.SetInterface(PreviewAudio, i.GetPreviewAudio())
i.SetInterface(PreviewSegments, i.GetPreviewSegments())
i.SetInterface(PreviewExcludeStart, i.GetPreviewExcludeStart())
i.SetInterface(PreviewExcludeEnd, i.GetPreviewExcludeEnd())
i.SetInterface(PreviewPreset, i.GetPreviewPreset())
i.SetInterface(MaxTranscodeSize, i.GetMaxTranscodeSize())
i.SetInterface(MaxStreamingTranscodeSize, i.GetMaxStreamingTranscodeSize())
i.SetInterface(ApiKey, i.GetAPIKey())
i.SetInterface(Username, i.GetUsername())
i.SetInterface(Password, i.GetPasswordHash())
i.GetCredentials()
i.Set(MaxSessionAge, i.GetMaxSessionAge())
i.Set(CustomServedFolders, i.GetCustomServedFolders())
i.Set(LegacyCustomUILocation, i.GetUILocation())
i.Set(MenuItems, i.GetMenuItems())
i.Set(SoundOnPreview, i.GetSoundOnPreview())
i.Set(WallShowTitle, i.GetWallShowTitle())
i.Set(CustomPerformerImageLocation, i.GetCustomPerformerImageLocation())
i.Set(WallPlayback, i.GetWallPlayback())
i.Set(MaximumLoopDuration, i.GetMaximumLoopDuration())
i.Set(AutostartVideo, i.GetAutostartVideo())
i.Set(ShowStudioAsText, i.GetShowStudioAsText())
i.Set(legacyImageLightboxSlideshowDelay, *i.GetImageLightboxOptions().SlideshowDelay)
i.Set(ImageLightboxSlideshowDelay, *i.GetImageLightboxOptions().SlideshowDelay)
i.SetInterface(MaxSessionAge, i.GetMaxSessionAge())
i.SetInterface(CustomServedFolders, i.GetCustomServedFolders())
i.SetInterface(LegacyCustomUILocation, i.GetUILocation())
i.SetInterface(MenuItems, i.GetMenuItems())
i.SetInterface(SoundOnPreview, i.GetSoundOnPreview())
i.SetInterface(WallShowTitle, i.GetWallShowTitle())
i.SetInterface(CustomPerformerImageLocation, i.GetCustomPerformerImageLocation())
i.SetInterface(WallPlayback, i.GetWallPlayback())
i.SetInterface(MaximumLoopDuration, i.GetMaximumLoopDuration())
i.SetInterface(AutostartVideo, i.GetAutostartVideo())
i.SetInterface(ShowStudioAsText, i.GetShowStudioAsText())
i.SetInterface(legacyImageLightboxSlideshowDelay, *i.GetImageLightboxOptions().SlideshowDelay)
i.SetInterface(ImageLightboxSlideshowDelay, *i.GetImageLightboxOptions().SlideshowDelay)
i.GetCSSPath()
i.GetCSS()
i.GetJavascriptPath()
i.GetJavascript()
i.GetCustomLocalesPath()
i.GetCustomLocales()
i.Set(CSSEnabled, i.GetCSSEnabled())
i.Set(CSSEnabled, i.GetCustomLocalesEnabled())
i.Set(HandyKey, i.GetHandyKey())
i.Set(UseStashHostedFunscript, i.GetUseStashHostedFunscript())
i.Set(DLNAServerName, i.GetDLNAServerName())
i.Set(DLNADefaultEnabled, i.GetDLNADefaultEnabled())
i.Set(DLNADefaultIPWhitelist, i.GetDLNADefaultIPWhitelist())
i.Set(DLNAInterfaces, i.GetDLNAInterfaces())
i.Set(DLNAPort, i.GetDLNAPort())
i.Set(LogFile, i.GetLogFile())
i.Set(LogOut, i.GetLogOut())
i.Set(LogLevel, i.GetLogLevel())
i.Set(LogAccess, i.GetLogAccess())
i.Set(MaxUploadSize, i.GetMaxUploadSize())
i.Set(FunscriptOffset, i.GetFunscriptOffset())
i.Set(DefaultIdentifySettings, i.GetDefaultIdentifySettings())
i.Set(DeleteGeneratedDefault, i.GetDeleteGeneratedDefault())
i.Set(DeleteFileDefault, i.GetDeleteFileDefault())
i.Set(dangerousAllowPublicWithoutAuth, i.GetDangerousAllowPublicWithoutAuth())
i.Set(SecurityTripwireAccessedFromPublicInternet, i.GetSecurityTripwireAccessedFromPublicInternet())
i.Set(DisableDropdownCreatePerformer, i.GetDisableDropdownCreate().Performer)
i.Set(DisableDropdownCreateStudio, i.GetDisableDropdownCreate().Studio)
i.Set(DisableDropdownCreateTag, i.GetDisableDropdownCreate().Tag)
i.Set(DisableDropdownCreateMovie, i.GetDisableDropdownCreate().Movie)
i.Set(AutostartVideoOnPlaySelected, i.GetAutostartVideoOnPlaySelected())
i.Set(ContinuePlaylistDefault, i.GetContinuePlaylistDefault())
i.Set(PythonPath, i.GetPythonPath())
i.SetInterface(CSSEnabled, i.GetCSSEnabled())
i.SetInterface(CSSEnabled, i.GetCustomLocalesEnabled())
i.SetInterface(HandyKey, i.GetHandyKey())
i.SetInterface(UseStashHostedFunscript, i.GetUseStashHostedFunscript())
i.SetInterface(DLNAServerName, i.GetDLNAServerName())
i.SetInterface(DLNADefaultEnabled, i.GetDLNADefaultEnabled())
i.SetInterface(DLNADefaultIPWhitelist, i.GetDLNADefaultIPWhitelist())
i.SetInterface(DLNAInterfaces, i.GetDLNAInterfaces())
i.SetInterface(DLNAPort, i.GetDLNAPort())
i.SetInterface(LogFile, i.GetLogFile())
i.SetInterface(LogOut, i.GetLogOut())
i.SetInterface(LogLevel, i.GetLogLevel())
i.SetInterface(LogAccess, i.GetLogAccess())
i.SetInterface(MaxUploadSize, i.GetMaxUploadSize())
i.SetInterface(FunscriptOffset, i.GetFunscriptOffset())
i.SetInterface(DefaultIdentifySettings, i.GetDefaultIdentifySettings())
i.SetInterface(DeleteGeneratedDefault, i.GetDeleteGeneratedDefault())
i.SetInterface(DeleteFileDefault, i.GetDeleteFileDefault())
i.SetInterface(dangerousAllowPublicWithoutAuth, i.GetDangerousAllowPublicWithoutAuth())
i.SetInterface(SecurityTripwireAccessedFromPublicInternet, i.GetSecurityTripwireAccessedFromPublicInternet())
i.SetInterface(DisableDropdownCreatePerformer, i.GetDisableDropdownCreate().Performer)
i.SetInterface(DisableDropdownCreateStudio, i.GetDisableDropdownCreate().Studio)
i.SetInterface(DisableDropdownCreateTag, i.GetDisableDropdownCreate().Tag)
i.SetInterface(DisableDropdownCreateMovie, i.GetDisableDropdownCreate().Movie)
i.SetInterface(AutostartVideoOnPlaySelected, i.GetAutostartVideoOnPlaySelected())
i.SetInterface(ContinuePlaylistDefault, i.GetContinuePlaylistDefault())
i.SetInterface(PythonPath, i.GetPythonPath())
t.Logf("Worker %v iteration %v took %v", wk, l, time.Since(start))
}
wg.Done()

View file

@ -245,7 +245,7 @@ func (s *Manager) Setup(ctx context.Context, input SetupInput) error {
}
}
s.Config.Set(config.Generated, input.GeneratedLocation)
s.Config.SetString(config.Generated, input.GeneratedLocation)
}
// create the cache directory if it does not exist
@ -256,11 +256,11 @@ func (s *Manager) Setup(ctx context.Context, input SetupInput) error {
}
}
cfg.Set(config.Cache, input.CacheLocation)
cfg.SetString(config.Cache, input.CacheLocation)
}
if input.StoreBlobsInDatabase {
cfg.Set(config.BlobsStorage, config.BlobStorageTypeDatabase)
cfg.SetInterface(config.BlobsStorage, config.BlobStorageTypeDatabase)
} else {
if !cfg.HasOverride(config.BlobsPath) {
if exists, _ := fsutil.DirExists(input.BlobsLocation); !exists {
@ -269,18 +269,18 @@ func (s *Manager) Setup(ctx context.Context, input SetupInput) error {
}
}
cfg.Set(config.BlobsPath, input.BlobsLocation)
cfg.SetString(config.BlobsPath, input.BlobsLocation)
}
cfg.Set(config.BlobsStorage, config.BlobStorageTypeFilesystem)
cfg.SetInterface(config.BlobsStorage, config.BlobStorageTypeFilesystem)
}
// set the configuration
if !cfg.HasOverride(config.Database) {
cfg.Set(config.Database, input.DatabaseFile)
cfg.SetString(config.Database, input.DatabaseFile)
}
cfg.Set(config.Stash, input.Stashes)
cfg.SetInterface(config.Stash, input.Stashes)
if err := cfg.Write(); err != nil {
return fmt.Errorf("error writing configuration file: %v", err)

View file

@ -273,7 +273,7 @@ func (m *schema45Migrator) migrateConfig(ctx context.Context) error {
}
logger.Infof("Setting blobs storage to %s", defaultStorage.String())
c.Set(config.BlobsStorage, defaultStorage)
c.SetInterface(config.BlobsStorage, defaultStorage)
if err := c.Write(); err != nil {
logger.Errorf("Error while writing configuration file: %s", err.Error())
}
@ -282,7 +282,7 @@ func (m *schema45Migrator) migrateConfig(ctx context.Context) error {
scanDefaults := c.GetDefaultScanSettings()
if scanDefaults != nil {
scanDefaults.ScanGenerateCovers = true
c.Set(config.DefaultScanSettings, scanDefaults)
c.SetInterface(config.DefaultScanSettings, scanDefaults)
if err := c.Write(); err != nil {
logger.Errorf("Error while writing configuration file: %s", err.Error())
}

View file

@ -130,7 +130,7 @@ func (m *schema58Migrator) migrateConfig() error {
newPlugins[key] = m.fromSnakeCaseMap(value)
}
c.Set(config.PluginsSetting, newPlugins)
c.SetInterface(config.PluginsSetting, newPlugins)
if err := c.Write(); err != nil {
return fmt.Errorf("failed to write config: %w", err)
}