Files
spyda/internal/config.go
2021-01-30 15:06:58 +10:00

149 lines
3.0 KiB
Go

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()
}