/
config.go
196 lines (149 loc) · 4.69 KB
/
config.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
package config
import (
"errors"
"fmt"
"os"
"os/user"
"path"
"github.com/BurntSushi/toml"
)
const (
// defaultWatchInterval defines the time in minutes between two FeedWatcher scans
defaultWatchInterval = 30
// defaultDBName is the default filename for the database
defaultDBName = "database.db"
// defaultHost sets up the webserver host default as a local host
defaultHost = "127.0.0.1"
// defaultPort sets up the webserver port to a non-standard one
defaultPort = 8000
// defaultAuthRealm is the default realm used for the web server digest authentication
defaultAuthRealm = "christopher.local"
// defaultLogLevel sets the minimum level for logging infos
defaultLogLevel = "info"
// defaultLogFormatter sets the log items formatter
defaultLogFormatter = "text"
)
// Feed is a Feed Representation
type feed struct {
Title string // Remote feed title
URL string // URL to the feed
Provider string // The feed provider
}
// FeedWatcherOptions defines some options for the FeedWatcher
type feedWatcherOptions struct {
WatchInterval int `toml:"watch_interval"` // In Minutes
Feeds []*feed
}
// DownloaderOptions defines options for the downloader
type DownloaderOptions struct {
Name string
AuthInfos map[string]interface{} `toml:"auth_infos"`
DownloadOptions map[string]interface{} `toml:"download_options"`
}
// DebriderOptions defines name and auth info for the debrider
type DebriderOptions struct {
Name string
AuthInfos map[string]string `toml:"auth_infos"`
}
// ProviderOptions specify options for a given provider
type ProviderOptions struct {
FavoriteHosts []string `toml:"favorite_hosts"`
}
type webUser struct {
Name string
Password string
}
// WebServerOptions defines some of the webserver options
type WebServerOptions struct {
Port int
Host string
// Secret is the secret for the CSRF token generation
Secret string
// SecureCookie constrains CSRF cookie to be HTTPS only if true
SecureCookie bool `toml:"secure_cookie"`
// AuthRealm is the realm for the HTTP digest auth
AuthRealm string `toml:"auth_realm"`
// Users are a list of allowed users.
// If no users are given, no Digest auth is setup.
Users []webUser
}
// TellerOptions defines logging options for the Teller
type TellerOptions struct {
// LogLevel is a level from when the Teller must log things
LogLevel string `toml:"log_level"`
// LogFormatter is the log items format
LogFormatter string `toml:"log_formatter"`
}
// Config defines the Christopher configuration
type Config struct {
configPath string `toml:"config_path"`
DBPath string `toml:"db_path"`
FeedWatcher feedWatcherOptions
Downloader DownloaderOptions
Debrider DebriderOptions
Providers map[string]ProviderOptions
WebServer WebServerOptions
Teller TellerOptions
}
// Load loads config from the default config path
func Load() (*Config, error) {
return LoadFromFile(DefaultConfigPath())
}
// LoadFromFile loads the configuration from a file
func LoadFromFile(configPath string) (*Config, error) {
// Initializing configuration
var config Config
// Setting defaults for required elements
config.setDefaults()
// Parsing config file, thus overriding defaults if needed
_, configError := toml.DecodeFile(configPath, &config)
if configError != nil {
if os.IsNotExist(configError) {
return nil, fmt.Errorf("Missing config file in %s", configPath)
}
return nil, fmt.Errorf("Invalid config file: %v", configError)
}
// Validating resulting configuration
validationError := config.validate()
if validationError != nil {
return nil, validationError
}
return &config, nil
}
// UserDir returns the user home directory
func UserDir() (string, error) {
user, userError := user.Current()
if userError != nil {
return "", userError
}
return user.HomeDir, nil
}
// DefaultConfigPath returns the default path to the config file
func DefaultConfigPath() string {
userDir, _ := UserDir()
return path.Join(userDir, ".config", "christopher", "config.toml")
}
func (c *Config) validate() error {
// Validating DBPath
if c.DBPath == "" {
return errors.New("DBPath can't be blank")
}
// Must have 32 bytes secret for CSRF protection
if c.WebServer.Secret == "" {
return errors.New("A 32 bytes secret token must be set")
}
return nil
}
func (c *Config) setDefaults() {
userDir, _ := UserDir()
// Setting default DBPath
c.DBPath = path.Join(userDir, ".config", "christopher", defaultDBName)
// Setting default WatchInterval
c.FeedWatcher.WatchInterval = defaultWatchInterval
// WebServer defaults
c.WebServer.Host = defaultHost
c.WebServer.Port = defaultPort
c.WebServer.AuthRealm = defaultAuthRealm
c.Teller.LogLevel = defaultLogLevel
c.Teller.LogFormatter = defaultLogFormatter
}