package internal import ( "errors" "fmt" "io/ioutil" "math/rand" "net/url" "os" "strings" "time" "github.com/gabstv/merger" "github.com/goccy/go-yaml" log "github.com/sirupsen/logrus" ) var ( ErrConfigPathMissing = errors.New("error: config file missing") ) // Settings contains Pod Settings that can be customised via the Web UI type Settings struct { Name string `yaml:"pod_name"` Description string `yaml:"pod_description"` } // Config contains the server configuration parameters type Config struct { Debug bool Data string Name string Description string Store string Theme string BaseURL string AdminUser string AdminPass string AdminName string AdminEmail string SearchPrompts []string ResultsPerPage int APISessionTime time.Duration SessionExpiry time.Duration SessionCacheTTL time.Duration APISigningKey string CookieSecret string MagicLinkSecret string SMTPHost string SMTPPort int SMTPUser string SMTPPass string SMTPFrom string baseURL *url.URL } func (c *Config) IsLocalURL(url string) bool { if NormalizeURL(url) == "" { return false } return strings.HasPrefix(NormalizeURL(url), NormalizeURL(c.BaseURL)) } func (c *Config) LocalURL() *url.URL { return c.baseURL } // Settings returns a `Settings` struct containing pod settings that can // then be persisted to disk to override some configuration options. func (c *Config) Settings() *Settings { settings := &Settings{} if err := merger.MergeOverwrite(settings, c); err != nil { log.WithError(err).Warn("error creating pod settings") } return settings } // RandomSearchPrompt returns a random Search Prompt for display by the UI func (c *Config) RandomSearchPrompt() string { n := rand.Int() % len(c.SearchPrompts) return c.SearchPrompts[n] } // Validate validates the configuration is valid which for the most part // just ensures that default secrets are actually configured correctly func (c *Config) Validate() error { if c.Debug { return nil } if c.CookieSecret == InvalidConfigValue { return fmt.Errorf("error: COOKIE_SECRET is not configured!") } if c.MagicLinkSecret == InvalidConfigValue { return fmt.Errorf("error: MAGICLINK_SECRET is not configured!") } if c.APISigningKey == InvalidConfigValue { return fmt.Errorf("error: API_SIGNING_KEY is not configured!") } return nil } // LoadSettings loads pod settings from the given path func LoadSettings(path string) (*Settings, error) { var settings Settings data, err := ioutil.ReadFile(path) if err != nil { return nil, err } if err := yaml.Unmarshal(data, &settings); err != nil { return nil, err } return &settings, nil } // Save saves the pod settings to the given path func (s *Settings) Save(path string) error { f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0600) if err != nil { return err } data, err := yaml.MarshalWithOptions(s, yaml.Indent(4)) if err != nil { return err } if _, err = f.Write(data); err != nil { return err } if err = f.Sync(); err != nil { return err } return f.Close() }