go-jamming/common/config.go

146 lines
3.7 KiB
Go

package common
import (
"brainbaking.com/go-jamming/rest"
"encoding/json"
"errors"
"github.com/rs/zerolog/log"
"io/fs"
"io/ioutil"
"strings"
)
type Config struct {
// BaseURL should end with a / and is used to build URLs in notifications
BaseURL string `json:"baseURL"`
AdminEmail string `json:"adminEmail"`
Port int `json:"port"`
Token string `json:"token"`
AllowedWebmentionSources []string `json:"allowedWebmentionSources"`
Blacklist []string `json:"blacklist"`
Whitelist []string `json:"whitelist"`
}
func (c *Config) IsBlacklisted(url string) bool {
return isListedIn(url, c.Blacklist)
}
func (c *Config) IsWhitelisted(url string) bool {
return isListedIn(url, c.Whitelist)
}
func isListedIn(url string, list []string) bool {
if !strings.HasPrefix(url, "http") {
return false
}
domain := rest.Domain(url)
return Includes(list, domain)
}
func (c *Config) missingKeys() []string {
keys := []string{}
if c.Port == 0 {
keys = append(keys, "port")
}
if c.Token == "" {
keys = append(keys, "token")
}
if c.BaseURL == "" {
keys = append(keys, "baseURL")
}
if len(c.AllowedWebmentionSources) == 0 {
keys = append(keys, "allowedWebmentionSources")
}
return keys
}
func (c *Config) IsAnAllowedDomain(domain string) bool {
return Includes(c.AllowedWebmentionSources, domain)
}
func (c *Config) FetchDomain(url string) (string, error) {
for _, domain := range c.AllowedWebmentionSources {
if strings.Contains(url, domain) {
return domain, nil
}
}
return "", errors.New("no allowed domain found for url " + url)
}
func Configure() *Config {
c := config()
for _, domain := range c.AllowedWebmentionSources {
log.Info().Str("allowedDomain", domain).Msg("Configured")
}
return c
}
// AddToBlacklist adds the given domain to the blacklist slice and persists to disk.
func (c *Config) AddToBlacklist(domain string) {
c.Blacklist = addToList(domain, c.Blacklist)
c.Save()
}
// AddToWhitelist adds the given domain to the whitelist slice and persists to disk.
func (c *Config) AddToWhitelist(domain string) {
c.Whitelist = addToList(domain, c.Whitelist)
c.Save()
}
func addToList(key string, arr []string) []string {
for _, d := range arr {
if d == key {
return arr
}
}
return append(arr, key)
}
func (c *Config) String() string {
bytes, _ := json.MarshalIndent(c, "", " ")
return string(bytes)
}
func (c *Config) Save() {
err := ioutil.WriteFile("config.json", []byte(c.String()), fs.ModePerm)
if err != nil {
log.Err(err).Msg("Unable to save config.json to disk!")
}
}
func config() *Config {
confData, err := ioutil.ReadFile("config.json")
if err != nil {
log.Warn().Msg("No config.json file found, reverting to defaults...")
return defaultConfig()
}
conf := &Config{}
err = json.Unmarshal(confData, conf)
if err != nil {
log.Warn().Msg("config.json malformed JSON, reverting to defaults...")
return defaultConfig()
}
someMissingKeys := conf.missingKeys()
if len(someMissingKeys) > 0 {
log.Warn().Str("keys", strings.Join(someMissingKeys, ", ")).Msg("config.json is missing required keys, reverting to defaults...")
return defaultConfig()
}
return conf
}
func defaultConfig() *Config {
defaultConfig := &Config{
AdminEmail: "admin@mycooldomain.com",
BaseURL: "http://localhost:1337/",
Port: 1337,
Token: "miauwkes",
AllowedWebmentionSources: []string{"mycooldomain.com", "myotherdomain.com"},
Blacklist: []string{"youtube.com"},
Whitelist: []string{"mycooldomain.com"},
}
defaultConfig.Save()
return defaultConfig
}