diff --git a/internal/config/options.go b/internal/config/options.go index be8768a603e..690b390725e 100644 --- a/internal/config/options.go +++ b/internal/config/options.go @@ -7,6 +7,7 @@ import ( "fmt" "maps" "net/url" + "reflect" "slices" "strings" "time" @@ -20,8 +21,7 @@ type optionPair struct { type configValueType int const ( - stringType configValueType = iota - stringListType + stringListType configValueType = iota boolType intType int64Type @@ -30,13 +30,14 @@ const ( minuteType hourType dayType - secretFileType bytesType ) type configValue struct { + value any + str string + ParsedStringValue string - ParsedBoolValue bool ParsedIntValue int ParsedInt64Value int64 ParsedDuration time.Duration @@ -59,6 +60,25 @@ type configOptions struct { options map[string]*configValue } +func anyToStr(a any) string { + if a == nil { + return "" + } + if ret, ok := a.(string); ok { + return ret + } + panic(fmt.Sprintf("expected string, got %q", reflect.TypeOf(a))) +} +func anyToBool(a any) bool { + if a == nil { + return false + } + if ret, ok := a.(bool); ok { + return ret + } + panic(fmt.Sprintf("expected bool, got %q", reflect.TypeOf(a))) +} + // NewConfigOptions creates a new instance of ConfigOptions with default values. func NewConfigOptions() *configOptions { return &configOptions{ @@ -67,42 +87,28 @@ func NewConfigOptions() *configOptions { youTubeEmbedDomain: "www.youtube-nocookie.com", options: map[string]*configValue{ "ADMIN_PASSWORD": { - ParsedStringValue: "", - RawValue: "", - ValueType: stringType, - Secret: true, + value: "", + Secret: true, }, "ADMIN_PASSWORD_FILE": { - ParsedStringValue: "", - RawValue: "", - ValueType: secretFileType, - TargetKey: "ADMIN_PASSWORD", + value: "", + TargetKey: "ADMIN_PASSWORD", }, "ADMIN_USERNAME": { - ParsedStringValue: "", - RawValue: "", - ValueType: stringType, + value: "", }, "ADMIN_USERNAME_FILE": { - ParsedStringValue: "", - RawValue: "", - ValueType: secretFileType, - TargetKey: "ADMIN_USERNAME", + value: "", + TargetKey: "ADMIN_USERNAME", }, "AUTH_PROXY_HEADER": { - ParsedStringValue: "", - RawValue: "", - ValueType: stringType, + value: "", }, "AUTH_PROXY_USER_CREATION": { - ParsedBoolValue: false, - RawValue: "0", - ValueType: boolType, + value: false, }, "BASE_URL": { - ParsedStringValue: "http://localhost", - RawValue: "http://localhost", - ValueType: stringType, + value: "http://localhost", }, "BATCH_SIZE": { ParsedIntValue: 100, @@ -113,14 +119,10 @@ func NewConfigOptions() *configOptions { }, }, "CERT_DOMAIN": { - ParsedStringValue: "", - RawValue: "", - ValueType: stringType, + value: "", }, "CERT_FILE": { - ParsedStringValue: "", - RawValue: "", - ValueType: stringType, + value: "", }, "CLEANUP_ARCHIVE_BATCH_SIZE": { ParsedIntValue: 10000, @@ -154,9 +156,7 @@ func NewConfigOptions() *configOptions { ValueType: dayType, }, "CREATE_ADMIN": { - ParsedBoolValue: false, - RawValue: "0", - ValueType: boolType, + value: false, }, "DATABASE_CONNECTION_LIFETIME": { ParsedDuration: time.Minute * 5, @@ -183,56 +183,36 @@ func NewConfigOptions() *configOptions { }, }, "DATABASE_URL": { - ParsedStringValue: "user=postgres password=postgres dbname=miniflux2 sslmode=disable", - RawValue: "user=postgres password=postgres dbname=miniflux2 sslmode=disable", - ValueType: stringType, - Secret: true, + value: "user=postgres password=postgres dbname=miniflux2 sslmode=disable", + Secret: true, }, "DATABASE_URL_FILE": { - ParsedStringValue: "", - RawValue: "", - ValueType: secretFileType, - TargetKey: "DATABASE_URL", + value: "", + TargetKey: "DATABASE_URL", }, "DISABLE_HSTS": { - ParsedBoolValue: false, - RawValue: "0", - ValueType: boolType, + value: false, }, "DISABLE_HTTP_SERVICE": { - ParsedBoolValue: false, - RawValue: "0", - ValueType: boolType, + value: false, }, "DISABLE_LOCAL_AUTH": { - ParsedBoolValue: false, - RawValue: "0", - ValueType: boolType, + value: false, }, "DISABLE_SCHEDULER_SERVICE": { - ParsedBoolValue: false, - RawValue: "0", - ValueType: boolType, + value: false, }, "FETCH_BILIBILI_WATCH_TIME": { - ParsedBoolValue: false, - RawValue: "0", - ValueType: boolType, + value: false, }, "FETCH_NEBULA_WATCH_TIME": { - ParsedBoolValue: false, - RawValue: "0", - ValueType: boolType, + value: false, }, "FETCH_ODYSEE_WATCH_TIME": { - ParsedBoolValue: false, - RawValue: "0", - ValueType: boolType, + value: false, }, "FETCH_YOUTUBE_WATCH_TIME": { - ParsedBoolValue: false, - RawValue: "0", - ValueType: boolType, + value: false, }, "FILTER_ENTRY_MAX_AGE_DAYS": { ParsedIntValue: 0, @@ -279,9 +259,7 @@ func NewConfigOptions() *configOptions { }, }, "HTTP_CLIENT_USER_AGENT": { - ParsedStringValue: "", - RawValue: "", - ValueType: stringType, + value: "", }, "HTTP_SERVER_TIMEOUT": { ParsedDuration: 300 * time.Second, @@ -292,19 +270,13 @@ func NewConfigOptions() *configOptions { }, }, "HTTPS": { - ParsedBoolValue: false, - RawValue: "0", - ValueType: boolType, + value: false, }, "INVIDIOUS_INSTANCE": { - ParsedStringValue: "yewtu.be", - RawValue: "yewtu.be", - ValueType: stringType, + value: "yewtu.be", }, "KEY_FILE": { - ParsedStringValue: "", - RawValue: "", - ValueType: stringType, + value: "", }, "LISTEN_ADDR": { ParsedStringList: []string{"127.0.0.1:8080"}, @@ -312,40 +284,28 @@ func NewConfigOptions() *configOptions { ValueType: stringListType, }, "LOG_DATE_TIME": { - ParsedBoolValue: false, - RawValue: "0", - ValueType: boolType, + value: false, }, "LOG_FILE": { - ParsedStringValue: "stderr", - RawValue: "stderr", - ValueType: stringType, + value: "stderr", }, "LOG_FORMAT": { - ParsedStringValue: "text", - RawValue: "text", - ValueType: stringType, + value: "text", Validator: func(rawValue string) error { return validateChoices(rawValue, []string{"text", "json"}) }, }, "LOG_LEVEL": { - ParsedStringValue: "info", - RawValue: "info", - ValueType: stringType, + value: "info", Validator: func(rawValue string) error { return validateChoices(rawValue, []string{"debug", "info", "warning", "error"}) }, }, "MAINTENANCE_MESSAGE": { - ParsedStringValue: "Miniflux is currently under maintenance", - RawValue: "Miniflux is currently under maintenance", - ValueType: stringType, + value: "Miniflux is currently under maintenance", }, "MAINTENANCE_MODE": { - ParsedBoolValue: false, - RawValue: "0", - ValueType: boolType, + value: false, }, "MEDIA_PROXY_CUSTOM_URL": { RawValue: "", @@ -360,9 +320,7 @@ func NewConfigOptions() *configOptions { }, }, "MEDIA_PROXY_MODE": { - ParsedStringValue: "http-only", - RawValue: "http-only", - ValueType: stringType, + value: "http-only", Validator: func(rawValue string) error { return validateChoices(rawValue, []string{"none", "http-only", "all"}) }, @@ -385,21 +343,15 @@ func NewConfigOptions() *configOptions { ValueType: stringListType, }, "METRICS_COLLECTOR": { - ParsedBoolValue: false, - RawValue: "0", - ValueType: boolType, + value: false, }, "METRICS_PASSWORD": { - ParsedStringValue: "", - RawValue: "", - ValueType: stringType, - Secret: true, + value: "", + Secret: true, }, "METRICS_PASSWORD_FILE": { - ParsedStringValue: "", - RawValue: "", - ValueType: secretFileType, - TargetKey: "METRICS_PASSWORD", + value: "", + TargetKey: "METRICS_PASSWORD", }, "METRICS_REFRESH_INTERVAL": { ParsedDuration: 60 * time.Second, @@ -410,67 +362,45 @@ func NewConfigOptions() *configOptions { }, }, "METRICS_USERNAME": { - ParsedStringValue: "", - RawValue: "", - ValueType: stringType, + value: "", }, "METRICS_USERNAME_FILE": { - ParsedStringValue: "", - RawValue: "", - ValueType: secretFileType, - TargetKey: "METRICS_USERNAME", + value: "", + TargetKey: "METRICS_USERNAME", }, "OAUTH2_CLIENT_ID": { - ParsedStringValue: "", - RawValue: "", - ValueType: stringType, - Secret: true, + value: "", + Secret: true, }, "OAUTH2_CLIENT_ID_FILE": { - ParsedStringValue: "", - RawValue: "", - ValueType: secretFileType, - TargetKey: "OAUTH2_CLIENT_ID", + value: "", + TargetKey: "OAUTH2_CLIENT_ID", }, "OAUTH2_CLIENT_SECRET": { - ParsedStringValue: "", - RawValue: "", - ValueType: stringType, - Secret: true, + value: "", + Secret: true, }, "OAUTH2_CLIENT_SECRET_FILE": { - ParsedStringValue: "", - RawValue: "", - ValueType: secretFileType, - TargetKey: "OAUTH2_CLIENT_SECRET", + value: "", + TargetKey: "OAUTH2_CLIENT_SECRET", }, "OAUTH2_OIDC_DISCOVERY_ENDPOINT": { - ParsedStringValue: "", - RawValue: "", - ValueType: stringType, + value: "", }, "OAUTH2_OIDC_PROVIDER_NAME": { - ParsedStringValue: "OpenID Connect", - RawValue: "OpenID Connect", - ValueType: stringType, + value: "OpenID Connect", }, "OAUTH2_PROVIDER": { - ParsedStringValue: "", - RawValue: "", - ValueType: stringType, + value: "", Validator: func(rawValue string) error { return validateChoices(rawValue, []string{"oidc", "google"}) }, }, "OAUTH2_REDIRECT_URL": { - ParsedStringValue: "", - RawValue: "", - ValueType: stringType, + value: "", }, "OAUTH2_USER_CREATION": { - ParsedBoolValue: false, - RawValue: "0", - ValueType: boolType, + value: false, }, "POLLING_FREQUENCY": { ParsedDuration: 60 * time.Minute, @@ -497,25 +427,19 @@ func NewConfigOptions() *configOptions { }, }, "POLLING_SCHEDULER": { - ParsedStringValue: "round_robin", - RawValue: "round_robin", - ValueType: stringType, + value: "round_robin", Validator: func(rawValue string) error { return validateChoices(rawValue, []string{"round_robin", "entry_frequency"}) }, }, "PORT": { - ParsedStringValue: "", - RawValue: "", - ValueType: stringType, + value: "", Validator: func(rawValue string) error { return validateRange(rawValue, 1, 65535) }, }, "RUN_MIGRATIONS": { - ParsedBoolValue: false, - RawValue: "0", - ValueType: boolType, + value: false, }, "SCHEDULER_ENTRY_FREQUENCY_FACTOR": { ParsedIntValue: 1, @@ -555,14 +479,10 @@ func NewConfigOptions() *configOptions { }, }, "WATCHDOG": { - ParsedBoolValue: true, - RawValue: "1", - ValueType: boolType, + value: true, }, "WEBAUTHN": { - ParsedBoolValue: false, - RawValue: "0", - ValueType: boolType, + value: false, }, "WORKER_POOL_SIZE": { ParsedIntValue: 16, @@ -573,34 +493,30 @@ func NewConfigOptions() *configOptions { }, }, "YOUTUBE_API_KEY": { - ParsedStringValue: "", - RawValue: "", - ValueType: stringType, - Secret: true, + value: "", + Secret: true, }, "YOUTUBE_EMBED_URL_OVERRIDE": { - ParsedStringValue: "https://www.youtube-nocookie.com/embed/", - RawValue: "https://www.youtube-nocookie.com/embed/", - ValueType: stringType, + value: "https://www.youtube-nocookie.com/embed/", }, }, } } func (c *configOptions) AdminPassword() string { - return c.options["ADMIN_PASSWORD"].ParsedStringValue + return anyToStr(c.options["ADMIN_PASSWORD"].value) } func (c *configOptions) AdminUsername() string { - return c.options["ADMIN_USERNAME"].ParsedStringValue + return anyToStr(c.options["ADMIN_USERNAME"].value) } func (c *configOptions) AuthProxyHeader() string { - return c.options["AUTH_PROXY_HEADER"].ParsedStringValue + return anyToStr(c.options["AUTH_PROXY_HEADER"].value) } func (c *configOptions) AuthProxyUserCreation() bool { - return c.options["AUTH_PROXY_USER_CREATION"].ParsedBoolValue + return anyToBool(c.options["AUTH_PROXY_USER_CREATION"].value) } func (c *configOptions) BasePath() string { @@ -608,7 +524,7 @@ func (c *configOptions) BasePath() string { } func (c *configOptions) BaseURL() string { - return c.options["BASE_URL"].ParsedStringValue + return anyToStr(c.options["BASE_URL"].value) } func (c *configOptions) RootURL() string { @@ -620,11 +536,11 @@ func (c *configOptions) BatchSize() int { } func (c *configOptions) CertDomain() string { - return c.options["CERT_DOMAIN"].ParsedStringValue + return anyToStr(c.options["CERT_DOMAIN"].value) } func (c *configOptions) CertFile() string { - return c.options["CERT_FILE"].ParsedStringValue + return anyToStr(c.options["CERT_FILE"].value) } func (c *configOptions) CleanupArchiveBatchSize() int { @@ -648,7 +564,7 @@ func (c *configOptions) CleanupRemoveSessionsInterval() time.Duration { } func (c *configOptions) CreateAdmin() bool { - return c.options["CREATE_ADMIN"].ParsedBoolValue + return anyToBool(c.options["CREATE_ADMIN"].value) } func (c *configOptions) DatabaseConnectionLifetime() time.Duration { @@ -664,39 +580,39 @@ func (c *configOptions) DatabaseMinConns() int { } func (c *configOptions) DatabaseURL() string { - return c.options["DATABASE_URL"].ParsedStringValue + return anyToStr(c.options["DATABASE_URL"].value) } func (c *configOptions) DisableHSTS() bool { - return c.options["DISABLE_HSTS"].ParsedBoolValue + return anyToBool(c.options["DISABLE_HSTS"].value) } func (c *configOptions) DisableHTTPService() bool { - return c.options["DISABLE_HTTP_SERVICE"].ParsedBoolValue + return anyToBool(c.options["DISABLE_HTTP_SERVICE"].value) } func (c *configOptions) DisableLocalAuth() bool { - return c.options["DISABLE_LOCAL_AUTH"].ParsedBoolValue + return anyToBool(c.options["DISABLE_LOCAL_AUTH"].value) } func (c *configOptions) DisableSchedulerService() bool { - return c.options["DISABLE_SCHEDULER_SERVICE"].ParsedBoolValue + return anyToBool(c.options["DISABLE_SCHEDULER_SERVICE"].value) } func (c *configOptions) FetchBilibiliWatchTime() bool { - return c.options["FETCH_BILIBILI_WATCH_TIME"].ParsedBoolValue + return anyToBool(c.options["FETCH_BILIBILI_WATCH_TIME"].value) } func (c *configOptions) FetchNebulaWatchTime() bool { - return c.options["FETCH_NEBULA_WATCH_TIME"].ParsedBoolValue + return anyToBool(c.options["FETCH_NEBULA_WATCH_TIME"].value) } func (c *configOptions) FetchOdyseeWatchTime() bool { - return c.options["FETCH_ODYSEE_WATCH_TIME"].ParsedBoolValue + return anyToBool(c.options["FETCH_ODYSEE_WATCH_TIME"].value) } func (c *configOptions) FetchYouTubeWatchTime() bool { - return c.options["FETCH_YOUTUBE_WATCH_TIME"].ParsedBoolValue + return anyToBool(c.options["FETCH_YOUTUBE_WATCH_TIME"].value) } func (c *configOptions) FilterEntryMaxAgeDays() int { @@ -712,11 +628,11 @@ func (c *configOptions) HasHTTPClientProxiesConfigured() bool { } func (c *configOptions) HasHTTPService() bool { - return !c.options["DISABLE_HTTP_SERVICE"].ParsedBoolValue + return !anyToBool(c.options["DISABLE_HTTP_SERVICE"].value) } func (c *configOptions) HasHSTS() bool { - return !c.options["DISABLE_HSTS"].ParsedBoolValue + return !anyToBool(c.options["DISABLE_HSTS"].value) } func (c *configOptions) HasHTTPClientProxyURLConfigured() bool { @@ -724,19 +640,19 @@ func (c *configOptions) HasHTTPClientProxyURLConfigured() bool { } func (c *configOptions) HasMaintenanceMode() bool { - return c.options["MAINTENANCE_MODE"].ParsedBoolValue + return anyToBool(c.options["MAINTENANCE_MODE"].value) } func (c *configOptions) HasMetricsCollector() bool { - return c.options["METRICS_COLLECTOR"].ParsedBoolValue + return anyToBool(c.options["METRICS_COLLECTOR"].value) } func (c *configOptions) HasSchedulerService() bool { - return !c.options["DISABLE_SCHEDULER_SERVICE"].ParsedBoolValue + return !anyToBool(c.options["DISABLE_SCHEDULER_SERVICE"].value) } func (c *configOptions) HasWatchdog() bool { - return c.options["WATCHDOG"].ParsedBoolValue + return anyToBool(c.options["WATCHDOG"].value) } func (c *configOptions) HTTPClientMaxBodySize() int64 { @@ -756,8 +672,9 @@ func (c *configOptions) HTTPClientTimeout() time.Duration { } func (c *configOptions) HTTPClientUserAgent() string { - if c.options["HTTP_CLIENT_USER_AGENT"].ParsedStringValue != "" { - return c.options["HTTP_CLIENT_USER_AGENT"].ParsedStringValue + s := anyToStr(c.options["HTTP_CLIENT_USER_AGENT"].value) + if s != "" { + return s } return defaultHTTPClientUserAgent } @@ -767,27 +684,30 @@ func (c *configOptions) HTTPServerTimeout() time.Duration { } func (c *configOptions) HTTPS() bool { - return c.options["HTTPS"].ParsedBoolValue + return anyToBool(c.options["HTTPS"].value) } func (c *configOptions) InvidiousInstance() string { - return c.options["INVIDIOUS_INSTANCE"].ParsedStringValue + return anyToStr(c.options["INVIDIOUS_INSTANCE"].value) } func (c *configOptions) IsAuthProxyUserCreationAllowed() bool { - return c.options["AUTH_PROXY_USER_CREATION"].ParsedBoolValue + return anyToBool(c.options["AUTH_PROXY_USER_CREATION"].value) } func (c *configOptions) IsDefaultDatabaseURL() bool { - return c.options["DATABASE_URL"].RawValue == "user=postgres password=postgres dbname=miniflux2 sslmode=disable" + if c.options["DATABASE_URL"].str != "" { + return c.options["DATABASE_URL"].str == "user=postgres password=postgres dbname=miniflux2 sslmode=disable" + } + return anyToStr(c.options["DATABASE_URL"].value) == "user=postgres password=postgres dbname=miniflux2 sslmode=disable" } func (c *configOptions) IsOAuth2UserCreationAllowed() bool { - return c.options["OAUTH2_USER_CREATION"].ParsedBoolValue + return anyToBool(c.options["OAUTH2_USER_CREATION"].value) } func (c *configOptions) CertKeyFile() string { - return c.options["KEY_FILE"].ParsedStringValue + return anyToStr(c.options["KEY_FILE"].value) } func (c *configOptions) ListenAddr() []string { @@ -795,27 +715,27 @@ func (c *configOptions) ListenAddr() []string { } func (c *configOptions) LogFile() string { - return c.options["LOG_FILE"].ParsedStringValue + return anyToStr(c.options["LOG_FILE"].value) } func (c *configOptions) LogDateTime() bool { - return c.options["LOG_DATE_TIME"].ParsedBoolValue + return anyToBool(c.options["LOG_DATE_TIME"].value) } func (c *configOptions) LogFormat() string { - return c.options["LOG_FORMAT"].ParsedStringValue + return anyToStr(c.options["LOG_FORMAT"].value) } func (c *configOptions) LogLevel() string { - return c.options["LOG_LEVEL"].ParsedStringValue + return anyToStr(c.options["LOG_LEVEL"].value) } func (c *configOptions) MaintenanceMessage() string { - return c.options["MAINTENANCE_MESSAGE"].ParsedStringValue + return anyToStr(c.options["MAINTENANCE_MESSAGE"].value) } func (c *configOptions) MaintenanceMode() bool { - return c.options["MAINTENANCE_MODE"].ParsedBoolValue + return anyToBool(c.options["MAINTENANCE_MODE"].value) } func (c *configOptions) MediaCustomProxyURL() *url.URL { @@ -827,7 +747,7 @@ func (c *configOptions) MediaProxyHTTPClientTimeout() time.Duration { } func (c *configOptions) MediaProxyMode() string { - return c.options["MEDIA_PROXY_MODE"].ParsedStringValue + return anyToStr(c.options["MEDIA_PROXY_MODE"].value) } func (c *configOptions) MediaProxyPrivateKey() []byte { @@ -843,11 +763,11 @@ func (c *configOptions) MetricsAllowedNetworks() []string { } func (c *configOptions) MetricsCollector() bool { - return c.options["METRICS_COLLECTOR"].ParsedBoolValue + return anyToBool(c.options["METRICS_COLLECTOR"].value) } func (c *configOptions) MetricsPassword() string { - return c.options["METRICS_PASSWORD"].ParsedStringValue + return anyToStr(c.options["METRICS_PASSWORD"].value) } func (c *configOptions) MetricsRefreshInterval() time.Duration { @@ -855,35 +775,35 @@ func (c *configOptions) MetricsRefreshInterval() time.Duration { } func (c *configOptions) MetricsUsername() string { - return c.options["METRICS_USERNAME"].ParsedStringValue + return anyToStr(c.options["METRICS_USERNAME"].value) } func (c *configOptions) OAuth2ClientID() string { - return c.options["OAUTH2_CLIENT_ID"].ParsedStringValue + return anyToStr(c.options["OAUTH2_CLIENT_ID"].value) } func (c *configOptions) OAuth2ClientSecret() string { - return c.options["OAUTH2_CLIENT_SECRET"].ParsedStringValue + return anyToStr(c.options["OAUTH2_CLIENT_SECRET"].value) } func (c *configOptions) OAuth2OIDCDiscoveryEndpoint() string { - return c.options["OAUTH2_OIDC_DISCOVERY_ENDPOINT"].ParsedStringValue + return anyToStr(c.options["OAUTH2_OIDC_DISCOVERY_ENDPOINT"].value) } func (c *configOptions) OAuth2OIDCProviderName() string { - return c.options["OAUTH2_OIDC_PROVIDER_NAME"].ParsedStringValue + return anyToStr(c.options["OAUTH2_OIDC_PROVIDER_NAME"].value) } func (c *configOptions) OAuth2Provider() string { - return c.options["OAUTH2_PROVIDER"].ParsedStringValue + return anyToStr(c.options["OAUTH2_PROVIDER"].value) } func (c *configOptions) OAuth2RedirectURL() string { - return c.options["OAUTH2_REDIRECT_URL"].ParsedStringValue + return anyToStr(c.options["OAUTH2_REDIRECT_URL"].value) } func (c *configOptions) OAuth2UserCreation() bool { - return c.options["OAUTH2_USER_CREATION"].ParsedBoolValue + return anyToBool(c.options["OAUTH2_USER_CREATION"].value) } func (c *configOptions) PollingFrequency() time.Duration { @@ -899,29 +819,24 @@ func (c *configOptions) PollingParsingErrorLimit() int { } func (c *configOptions) PollingScheduler() string { - return c.options["POLLING_SCHEDULER"].ParsedStringValue + return anyToStr(c.options["POLLING_SCHEDULER"].value) } func (c *configOptions) Port() string { - return c.options["PORT"].ParsedStringValue + return anyToStr(c.options["PORT"].value) } func (c *configOptions) RunMigrations() bool { - return c.options["RUN_MIGRATIONS"].ParsedBoolValue + return anyToBool(c.options["RUN_MIGRATIONS"].value) } func (c *configOptions) SetLogLevel(level string) { - c.options["LOG_LEVEL"].ParsedStringValue = level - c.options["LOG_LEVEL"].RawValue = level + c.options["LOG_LEVEL"].value = level + c.options["LOG_LEVEL"].str = level } func (c *configOptions) SetHTTPSValue(value bool) { - c.options["HTTPS"].ParsedBoolValue = value - if value { - c.options["HTTPS"].RawValue = "1" - } else { - c.options["HTTPS"].RawValue = "0" - } + c.options["HTTPS"].value = value } func (c *configOptions) SchedulerEntryFrequencyFactor() int { @@ -945,11 +860,11 @@ func (c *configOptions) SchedulerRoundRobinMinInterval() time.Duration { } func (c *configOptions) Watchdog() bool { - return c.options["WATCHDOG"].ParsedBoolValue + return anyToBool(c.options["WATCHDOG"].value) } func (c *configOptions) WebAuthn() bool { - return c.options["WEBAUTHN"].ParsedBoolValue + return anyToBool(c.options["WEBAUTHN"].value) } func (c *configOptions) WorkerPoolSize() int { @@ -957,11 +872,11 @@ func (c *configOptions) WorkerPoolSize() int { } func (c *configOptions) YouTubeAPIKey() string { - return c.options["YOUTUBE_API_KEY"].ParsedStringValue + return anyToStr(c.options["YOUTUBE_API_KEY"].value) } func (c *configOptions) YouTubeEmbedUrlOverride() string { - return c.options["YOUTUBE_EMBED_URL_OVERRIDE"].ParsedStringValue + return anyToStr(c.options["YOUTUBE_EMBED_URL_OVERRIDE"].value) } func (c *configOptions) YouTubeEmbedDomain() string { @@ -973,7 +888,10 @@ func (c *configOptions) ConfigMap(redactSecret bool) []*optionPair { sortedOptions := make([]*optionPair, 0, len(sortedKeys)) for _, key := range sortedKeys { value := c.options[key] - displayValue := value.RawValue + displayValue := value.str + if displayValue == "" { + displayValue = value.RawValue + } if redactSecret && value.Secret && displayValue != "" { displayValue = "" } diff --git a/internal/config/options_parsing_test.go b/internal/config/options_parsing_test.go index cf965644f20..c465dcb33a6 100644 --- a/internal/config/options_parsing_test.go +++ b/internal/config/options_parsing_test.go @@ -1614,8 +1614,8 @@ func TestSetLogLevelFunction(t *testing.T) { if configParser.options.LogLevel() != "debug" { t.Fatalf("Expected LOG_LEVEL to be 'debug' after SetLogLevel('debug'), got '%s'", configParser.options.LogLevel()) } - if configParser.options.options["LOG_LEVEL"].RawValue != "debug" { - t.Fatalf("Expected LOG_LEVEL RawValue to be 'debug', got '%s'", configParser.options.options["LOG_LEVEL"].RawValue) + if configParser.options.options["LOG_LEVEL"].str != "debug" { + t.Fatalf("Expected LOG_LEVEL str to be 'debug', got '%s'", configParser.options.options["LOG_LEVEL"].str) } // Test setting log level to warning @@ -1623,8 +1623,8 @@ func TestSetLogLevelFunction(t *testing.T) { if configParser.options.LogLevel() != "warning" { t.Fatalf("Expected LOG_LEVEL to be 'warning' after SetLogLevel('warning'), got '%s'", configParser.options.LogLevel()) } - if configParser.options.options["LOG_LEVEL"].RawValue != "warning" { - t.Fatalf("Expected LOG_LEVEL RawValue to be 'warning', got '%s'", configParser.options.options["LOG_LEVEL"].RawValue) + if configParser.options.options["LOG_LEVEL"].str != "warning" { + t.Fatalf("Expected LOG_LEVEL RawValue to be 'warning', got '%s'", configParser.options.options["LOG_LEVEL"].str) } } diff --git a/internal/config/parser.go b/internal/config/parser.go index 686717f9a12..4732c8b8a50 100644 --- a/internal/config/parser.go +++ b/internal/config/parser.go @@ -51,7 +51,7 @@ func (cp *configParser) ParseFile(filename string) (*configOptions, error) { func (cp *configParser) postParsing() error { // Parse basePath and rootURL based on BASE_URL - baseURL := cp.options.options["BASE_URL"].ParsedStringValue + baseURL := anyToStr(cp.options.options["BASE_URL"].value) baseURL = strings.TrimSuffix(baseURL, "/") parsedURL, err := url.Parse(baseURL) @@ -64,14 +64,14 @@ func (cp *configParser) postParsing() error { return errors.New("BASE_URL scheme must be http or https") } - cp.options.options["BASE_URL"].ParsedStringValue = baseURL + cp.options.options["BASE_URL"].value = baseURL cp.options.basePath = parsedURL.Path parsedURL.Path = "" cp.options.rootURL = parsedURL.String() // Parse YouTube embed domain based on YOUTUBE_EMBED_URL_OVERRIDE - youTubeEmbedURLOverride := cp.options.options["YOUTUBE_EMBED_URL_OVERRIDE"].ParsedStringValue + youTubeEmbedURLOverride := anyToStr(cp.options.options["YOUTUBE_EMBED_URL_OVERRIDE"].value) if youTubeEmbedURLOverride != "" { parsedYouTubeEmbedURL, err := url.Parse(youTubeEmbedURLOverride) if err != nil { @@ -130,21 +130,47 @@ func (cp *configParser) parseLine(key, value string) error { } } + switch field.value.(type) { + case string: + if field.TargetKey != "" { + secretValue, err := readSecretFileValue(value) + if err != nil { + return fmt.Errorf("error reading secret file for key %s: %v", key, err) + } + if targetField, ok := cp.options.options[field.TargetKey]; ok { + targetField.value = secretValue + } + } + if value != "" { + field.value = value + } + field.str = anyToStr(field.value) + return nil + case bool: + switch strings.ToLower(value) { + case "": + if field.value == true { + field.str = "1" + } else { + field.str = "0" + } + case "1", "yes", "true", "on": + field.value = true + field.str = "0" + case "0", "no", "false", "off": + field.value = false + field.str = "1" + default: + return fmt.Errorf("invalid boolean value for key %s: %s", key, value) + } + return nil + } + // Convert the raw value based on its type switch field.ValueType { - case stringType: - field.ParsedStringValue = parseStringValue(value, field.ParsedStringValue) - field.RawValue = value case stringListType: field.ParsedStringList = parseStringListValue(value, field.ParsedStringList) field.RawValue = value - case boolType: - parsedValue, err := parseBoolValue(value, field.ParsedBoolValue) - if err != nil { - return fmt.Errorf("invalid boolean value for key %s: %v", key, err) - } - field.ParsedBoolValue = parsedValue - field.RawValue = value case intType: field.ParsedIntValue = parseIntValue(value, field.ParsedIntValue) field.RawValue = value @@ -170,18 +196,6 @@ func (cp *configParser) parseLine(key, value string) error { } field.ParsedURLValue = parsedURL field.RawValue = value - case secretFileType: - secretValue, err := readSecretFileValue(value) - if err != nil { - return fmt.Errorf("error reading secret file for key %s: %v", key, err) - } - if field.TargetKey != "" { - if targetField, ok := cp.options.options[field.TargetKey]; ok { - targetField.ParsedStringValue = secretValue - targetField.RawValue = secretValue - } - } - field.RawValue = value case bytesType: if value != "" { field.ParsedBytesValue = []byte(value)