5eae8cc102
Add SettingsService.ResolveString/Bool/Int resolving runtime config as app_settings (UI) > environment variable > default. Env seeds bootstrap; any value set in the UI persists to app_settings and wins. Foundation for OIDC and TLS UI configuration. Unit-tested for the precedence order. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
64 lines
1.9 KiB
Go
64 lines
1.9 KiB
Go
// Package services - settings precedence resolution.
|
|
//
|
|
// Runtime configuration resolves with a fixed precedence:
|
|
//
|
|
// app_settings (set via the UI/API) > environment variable > built-in default
|
|
//
|
|
// This lets environment variables seed a working configuration for bootstrap
|
|
// (containers, first run, the MSI), while any value an administrator sets in the
|
|
// UI is persisted to app_settings and wins from then on. Bootstrap-only settings
|
|
// that must be known before the database opens (data path, secret key, listen
|
|
// address/port) are NOT resolved here — they stay in package config.
|
|
package services
|
|
|
|
import (
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// ResolveString returns the effective string value for key: the app_settings
|
|
// value if one is set (non-empty), else the environment variable envVar if set,
|
|
// else def. A blank envVar skips the environment lookup.
|
|
func (s *SettingsService) ResolveString(key, envVar, def string) string {
|
|
if setting, err := s.Get(key); err == nil && setting != nil && setting.Value != "" {
|
|
return setting.Value
|
|
}
|
|
if envVar != "" {
|
|
if v := os.Getenv(envVar); v != "" {
|
|
return v
|
|
}
|
|
}
|
|
return def
|
|
}
|
|
|
|
// ResolveBool resolves a boolean setting with the same precedence. Recognized
|
|
// true values (case-insensitive): 1, t, true, yes, on.
|
|
func (s *SettingsService) ResolveBool(key, envVar string, def bool) bool {
|
|
raw := s.ResolveString(key, envVar, "")
|
|
if raw == "" {
|
|
return def
|
|
}
|
|
switch strings.ToLower(strings.TrimSpace(raw)) {
|
|
case "1", "t", "true", "yes", "on":
|
|
return true
|
|
case "0", "f", "false", "no", "off":
|
|
return false
|
|
default:
|
|
return def
|
|
}
|
|
}
|
|
|
|
// ResolveInt resolves an integer setting with the same precedence, falling back
|
|
// to def when unset or unparseable.
|
|
func (s *SettingsService) ResolveInt(key, envVar string, def int) int {
|
|
raw := s.ResolveString(key, envVar, "")
|
|
if raw == "" {
|
|
return def
|
|
}
|
|
if i, err := strconv.Atoi(strings.TrimSpace(raw)); err == nil {
|
|
return i
|
|
}
|
|
return def
|
|
}
|