mirror of
https://github.com/chuot/rdio-scanner.git
synced 2026-08-13 08:33:00 -06:00
308 lines
8.3 KiB
Go
308 lines
8.3 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 {
|
|
BaseDir string
|
|
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 NewConfig() *Config {
|
|
const (
|
|
defaultAdminUrl = "/admin"
|
|
defaultConfigFile = "rdio-scanner.ini"
|
|
defaultDbType = DbTypeSqlite
|
|
defaultDbFile = "rdio-scanner.db"
|
|
defaultDbHost = "localhost"
|
|
defaultDbPort = uint(3306)
|
|
defaultListen = ":3000"
|
|
)
|
|
|
|
var (
|
|
config = &Config{}
|
|
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")
|
|
)
|
|
|
|
if exe, err := os.Executable(); err == nil {
|
|
if !regexp.MustCompile(`go-build[0-9]+`).Match([]byte(exe)) {
|
|
config.BaseDir = filepath.Dir(exe)
|
|
if !config.isBaseDirWritable() {
|
|
if h, err := os.UserHomeDir(); err == nil {
|
|
config.BaseDir = filepath.Join(h, "Rdio Scanner")
|
|
if _, err := os.Stat(config.BaseDir); os.IsNotExist(err) {
|
|
os.MkdirAll(config.BaseDir, 0770)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
flag.StringVar(&config.BaseDir, "base_dir", config.BaseDir, "base directory where all data will be written")
|
|
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()
|
|
|
|
if !config.isBaseDirWritable() {
|
|
log.Fatalf("no write permissions in %s", config.BaseDir)
|
|
}
|
|
|
|
switch {
|
|
case *configSave:
|
|
if err := config.saveConfig(); err == nil {
|
|
fmt.Printf("%s file created\n", config.ConfigFile)
|
|
os.Exit(0)
|
|
} else {
|
|
fmt.Printf("error: %s\n", err.Error())
|
|
os.Exit(-1)
|
|
}
|
|
|
|
case *sslCreate:
|
|
fmt.Println("generating ssl certificate files")
|
|
|
|
if err := CreateSelfSignedCert(config); err == nil {
|
|
fmt.Println("ssl files created")
|
|
os.Exit(0)
|
|
} else {
|
|
fmt.Printf("error: %s", err.Error())
|
|
os.Exit(-1)
|
|
}
|
|
|
|
case *version:
|
|
fmt.Println(Version)
|
|
os.Exit(0)
|
|
|
|
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) {
|
|
fmt.Printf("unknown database type %s\n", config.DbType)
|
|
return nil
|
|
}
|
|
}
|
|
|
|
if *serviceAction != "" {
|
|
NewDaemon().Control(*serviceAction)
|
|
}
|
|
|
|
return config
|
|
}
|
|
|
|
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) {
|
|
return p
|
|
}
|
|
return path.Join(config.BaseDir, 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) isBaseDirWritable() bool {
|
|
if f, err := os.CreateTemp(config.BaseDir, ".tmp*"); err == nil {
|
|
f.Close()
|
|
os.Remove(f.Name())
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
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()
|
|
}
|