rdio-scanner/server/config.go
2021-12-01 09:22:49 -05:00

283 lines
7.6 KiB
Go

// Copyright (C) 2019-2021 Chrystian Huot <chrystian.huot@saubeo.solutions>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>
package main
import (
"flag"
"fmt"
"log"
"os"
"path"
"path/filepath"
"regexp"
"strconv"
"gopkg.in/ini.v1"
)
const (
DbTypeMariadb string = "mariadb"
DbTypeMysql string = "mysql"
DbTypeSqlite string = "sqlite"
)
type Config struct {
ConfigFile string
DbType string
DbFile string
DbHost string
DbPort uint
DbName string
DbUsername string
DbPassword string
Listen string
SslAutoCert string
SslCaCertFile string
SslCaKeyFile string
SslCertFile string
SslKeyFile string
SslListen string
newAdminPassword string
}
func (config *Config) GetConfigFilePath() string {
return config.GetPath(config.ConfigFile)
}
func (config *Config) GetDbFilePath() string {
return config.GetPath(config.DbFile)
}
func (config *Config) GetPath(p string) string {
if !path.IsAbs(p) {
if exe, err := os.Executable(); err == nil {
if !regexp.MustCompile(`go-build[0-9]+`).Match([]byte(exe)) {
return path.Join(filepath.Dir(exe), p)
}
}
}
return p
}
func (config *Config) GetSslCaCertFilePath() string {
return config.GetPath(config.SslCaCertFile)
}
func (config *Config) GetSslCaKeyFilePath() string {
return config.GetPath(config.SslCaKeyFile)
}
func (config *Config) GetSslCertFilePath() string {
return config.GetPath(config.SslCertFile)
}
func (config *Config) GetSslKeyFilePath() string {
return config.GetPath(config.SslKeyFile)
}
func (config *Config) Init() (ok bool, error error) {
const (
defaultAdminUrl = "/admin"
defaultConfigFile = "rdio-scanner.ini"
defaultDbType = DbTypeSqlite
defaultDbFile = "rdio-scanner.db"
defaultDbHost = "localhost"
defaultDbPort = uint(3306)
defaultListen = ":3000"
)
var (
configSave = flag.Bool("config_save", false, fmt.Sprintf("save configuration to %s", defaultConfigFile))
serviceAction = flag.String("service", "", "service command, one of start, stop, restart, install, uninstall")
sslCreate = flag.Bool("ssl_create", false, "create self-signed certificates")
version = flag.Bool("version", false, "show application version")
)
flag.StringVar(&config.DbFile, "db_file", defaultDbFile, "sqlite database file")
flag.StringVar(&config.DbHost, "db_host", defaultDbHost, "database host ip or hostname")
flag.StringVar(&config.DbName, "db_name", "", "database name")
flag.StringVar(&config.DbPassword, "db_pass", "", "database password")
flag.UintVar(&config.DbPort, "db_port", defaultDbPort, "database host port")
flag.StringVar(&config.DbType, "db_type", defaultDbType, fmt.Sprintf("database type, one of %s, %s, %s", DbTypeSqlite, DbTypeMariadb, DbTypeMysql))
flag.StringVar(&config.DbUsername, "db_user", "", "database user name")
flag.StringVar(&config.ConfigFile, "config", defaultConfigFile, "Server config file")
flag.StringVar(&config.Listen, "listen", defaultListen, "listening address")
flag.StringVar(&config.SslAutoCert, "ssl_auto_cert", "", "Domain name for Let's Encrypt automatic certificate")
flag.StringVar(&config.SslCertFile, "ssl_cert_file", "", "ssl PEM formated certificate")
flag.StringVar(&config.SslKeyFile, "ssl_key_file", "", "ssl PEM formated key")
flag.StringVar(&config.SslListen, "ssl_listen", "", "listening address for ssl")
flag.StringVar(&config.newAdminPassword, "admin_password", "", "change admin password")
flag.Parse()
switch {
case *configSave:
if err := config.saveConfig(); err == nil {
log.Printf("%s file created", config.ConfigFile)
return false, nil
} else {
return false, err
}
case *sslCreate:
log.Print("generating ssl certificate files")
if err := CreateSelfSignedCert(config); err == nil {
log.Print("ssl files created")
return false, nil
} else {
return false, err
}
case *version:
fmt.Println(Version)
return false, nil
default:
if cfg, err := ini.Load(config.GetConfigFilePath()); err == nil {
if v := cfg.Section("").Key("db_file").String(); len(v) > 0 {
config.DbFile = v
}
if v := cfg.Section("").Key("db_host").String(); len(v) > 0 {
config.DbHost = v
}
if v := cfg.Section("").Key("db_name").String(); len(v) > 0 {
config.DbName = v
}
if v := cfg.Section("").Key("db_pass").String(); len(v) > 0 {
config.DbPassword = v
}
if config.DbPort, err = cfg.Section("").Key("db_port").Uint(); err != nil {
config.DbPort = defaultDbPort
}
if v := cfg.Section("").Key("db_type").String(); len(v) > 0 {
config.DbType = v
}
if v := cfg.Section("").Key("db_user").String(); len(v) > 0 {
config.DbUsername = v
}
if v := cfg.Section("").Key("listen").String(); len(v) > 0 {
config.Listen = v
}
if v := cfg.Section("").Key("ssl_auto_cert").String(); len(v) > 0 {
config.SslAutoCert = v
}
if v := cfg.Section("").Key("ssl_cert_file").String(); len(v) > 0 {
config.SslCertFile = v
}
if v := cfg.Section("").Key("ssl_key_file").String(); len(v) > 0 {
config.SslKeyFile = v
}
if v := cfg.Section("").Key("ssl_listen").String(); len(v) > 0 {
config.SslListen = v
}
}
if !(config.DbType == DbTypeMariadb || config.DbType == DbTypeMysql || config.DbType == DbTypeSqlite) {
return false, fmt.Errorf("unknown database type %s", config.DbType)
}
}
if *serviceAction != "" {
return NewDaemon().Control(*serviceAction)
}
return true, nil
}
func (config *Config) saveConfig() error {
ini := []string{}
if config.DbType == DbTypeSqlite {
if config.DbFile != "" {
ini = append(ini, fmt.Sprintf("db_file = %s", config.DbFile))
}
} else {
if config.DbHost != "" {
ini = append(ini, fmt.Sprintf("db_host = %s", config.DbHost))
}
if config.DbName != "" {
ini = append(ini, fmt.Sprintf("db_name = %s", config.DbName))
}
if config.DbPassword != "" {
ini = append(ini, fmt.Sprintf("db_pass = %s", config.DbPassword))
}
if config.DbPort > 0 {
ini = append(ini, fmt.Sprintf("db_port = %s", strconv.Itoa(int(config.DbPort))))
}
}
if config.DbType != "" {
ini = append(ini, fmt.Sprintf("db_type = %s", config.DbType))
}
if config.DbUsername != "" && config.DbType != DbTypeSqlite {
ini = append(ini, fmt.Sprintf("db_user = %s", config.DbUsername))
}
if config.Listen != "" {
ini = append(ini, fmt.Sprintf("listen = %s", config.Listen))
}
if config.SslAutoCert != "" {
ini = append(ini, fmt.Sprintf("ssl_auto_cert = %s", config.SslAutoCert))
}
if config.SslCertFile != "" {
ini = append(ini, fmt.Sprintf("ssl_cert_file = %s", config.SslCertFile))
}
if config.SslKeyFile != "" {
ini = append(ini, fmt.Sprintf("ssl_key_file = %s", config.SslKeyFile))
}
if config.SslListen != "" {
ini = append(ini, fmt.Sprintf("ssl_listen = %s", config.SslListen))
}
file, err := os.Create(config.GetConfigFilePath())
if err != nil {
return err
}
for _, line := range ini {
_, err := file.WriteString(line + "\n")
if err != nil {
return err
}
}
return file.Close()
}