linstrom/config/config.go
2024-08-22 19:57:53 +02:00

135 lines
4.1 KiB
Go

package config
import (
"errors"
"fmt"
"os"
"github.com/BurntSushi/toml"
)
type ConfigSSL struct {
HandleSSL bool `toml:"handle_ssl"` // Whether Linstrom should handle SSL encryption itself
// If Linstrom is to handle SSL, whether it should use LetsEncrypt for certificates
UseLetsEncrypt *bool `toml:"use_lets_encrypt"`
// Path to the certificate if Linstrom is to handle SSL while not using LetsEncrypt
CertificateFile *string `toml:"certificate_file"`
// Mail adress to use in case of using LetsEncrypt
AdminMail *string `toml:"admin_mail"`
}
type ConfigGeneral struct {
Domain string `toml:"domain"` // The domain this server operates under
FullDomain string `toml:"full_domain"` // The full url the server operates under (without port), eg "http://localhost", the public port will be appended as needed
PublicPort int `toml:"public_port"` // The public facing port, usually either 80 or 443
PrivatePort int `toml:"private_port"` // The port the server should launch at
// Explanation:
// The public port is the port to connect to from outside the server to access it.
// The private port is where the server will open for itself on launch
// Important for reverse proxies like nginx or traeffik
// Where you the public port would be either 80 (http) or 443 (https), but the private one could be 3000 for example
}
type ConfigAdmin struct {
Username string `toml:"username"`
PasswordHash string `toml:"password_hash"`
}
type ConfigStorage struct {
IsPostgres bool `toml:"is_postgres"`
Uri string `toml:"uri"`
}
type ConfigMail struct {
Host string `toml:"host"`
Port int `toml:"port"`
Username string `toml:"username"`
Password string `toml:"password"`
EncryptionOverwrite *string `toml:"encryption_overwrite,omitempty"`
KeepAliveOverwrite *bool `toml:"keep_alive_overwrite,omitempty"`
ConnectTimeoutSecondsOverwrite *int `toml:"connect_timeout_seconds_overwrite,omitempty"`
SendTimeoutSecondsOverwrite *int `toml:"send_timeout_seconds_overwrite,omitempty"`
TemplateOverwriteDirectory *string `toml:"template_overwrite_directory,omitempty"`
}
type Config struct {
General ConfigGeneral `toml:"general"`
SSL ConfigSSL `toml:"ssl"`
Admin ConfigAdmin `toml:"admin"`
Storage ConfigStorage `toml:"storage"`
Mail ConfigMail `toml:"mail"`
}
const DEFAULT_CONFIG_FILE_PATH = "config.toml"
// "Global" variable for accessing the config
// If nil, no config has been loaded yet
var Global *Config
var ErrGlobalConfigNotSet = errors.New("global config not set")
// The default config is for a local debug environment
var defaultConfig = Config{
General: ConfigGeneral{
Domain: "localhost",
PublicPort: 8080,
PrivatePort: 8080,
},
SSL: ConfigSSL{
HandleSSL: false,
UseLetsEncrypt: nil,
CertificateFile: nil,
AdminMail: nil,
},
Admin: ConfigAdmin{
Username: "admin",
PasswordHash: "", // No password
},
Storage: ConfigStorage{
IsPostgres: false,
Uri: "db.sqlite",
},
}
func LoadConfigFromFile(file string, tryDefaultPath, saveIntoGlobal bool) (*Config, error) {
conf := &Config{}
data, err := os.ReadFile(file)
if err != nil && !tryDefaultPath {
return nil, fmt.Errorf("failed to read config %s: %w", file, err)
}
if err != nil && tryDefaultPath {
conf, err = loadFromDefaultPath()
if err != nil {
return nil, fmt.Errorf("failed to read custom and default config: %w", err)
}
}
err = toml.Unmarshal(data, &conf)
if err != nil {
return nil, fmt.Errorf("failed to convert from toml: %w", err)
}
if saveIntoGlobal {
Global = conf
}
return conf, nil
}
func loadFromDefaultPath() (*Config, error) {
data, err := os.ReadFile(DEFAULT_CONFIG_FILE_PATH)
if err != nil {
return nil, fmt.Errorf(
"failed to load default config path %s: %w",
DEFAULT_CONFIG_FILE_PATH,
err,
)
}
conf := Config{}
err = toml.Unmarshal(data, &conf)
if err != nil {
return nil, fmt.Errorf(
"failed to parse file content of %s as toml: %w",
DEFAULT_CONFIG_FILE_PATH,
err,
)
}
return &conf, nil
}