package main import ( "github.com/fsnotify/fsnotify" log "github.com/sirupsen/logrus" "github.com/spf13/viper" "random.chars.jp/git/image-board/store" "strconv" ) var instance *store.Store func configSetup() { // Configure configuration file parameters viper.SetConfigName("server") viper.SetConfigType("toml") viper.SetConfigPermissions(0600) viper.AddConfigPath(".") viper.AddConfigPath("/etc/imageboard/") viper.AddConfigPath("$HOME/.config/imageboard/") // Configure default values viper.SetDefault("system", map[string]interface{}{ "loglevel": "info", "store": "./db", "single-user": true, "private": false, }) viper.SetDefault("server", map[string]interface{}{ "host": "127.0.0.1", "port": int64(7777), "unix": false, "proxy": true, }) // Load configuration log.Info("Loading configuration file.") err := viper.ReadInConfig() if err != nil { if _, ok := err.(viper.ConfigFileNotFoundError); ok { err = viper.WriteConfigAs("server.toml") if err != nil { log.Fatalf("Error generating default configuration, %s", err) } log.Warn("Generated default server.toml in current directory.") } else { log.Fatalf("Error loading configuration, %s", err) } } if viper.ConfigFileUsed() != "" { log.Infof("Successfully loaded configuration %s, enabling watch.", viper.ConfigFileUsed()) } viper.WatchConfig() viper.OnConfigChange(func(event fsnotify.Event) { if d { return } log.Infof("Configuration file %s updated.", event.Name) if viper.GetStringMap("server")["unix"] != serverConfig["unix"] || viper.GetStringMap("server")["host"] != serverConfig["host"] || viper.GetStringMap("server")["port"] != serverConfig["port"] || viper.GetStringMap("system")["single-user"] != systemConfig["single-user"] || viper.GetStringMap("system")["private"] != systemConfig["private"] { log.Warn("Configuration change requires restart.") cleanup(true) return } // Update configuration setLevel() serverConfig = viper.GetStringMap("server") systemConfig = viper.GetStringMap("system") }) // Read initial config serverConfig = viper.GetStringMap("server") systemConfig = viper.GetStringMap("system") } func openStore() { path := systemConfig["store"].(string) single := parseBool(systemConfig["single-user"]) private := parseBool(systemConfig["private"]) instance = store.New(path, single, private) if instance == nil { log.Fatalf("Error initializing store.") } log.Infof("Store opened on %s revision %v compat %v.", path, instance.Revision, instance.Compat) info := instance.User(instance.InitialUser) if info.Snowflake == instance.InitialUser { log.Infof("Initial user ID %s secret %s.", info.Snowflake, info.Secret) if instance.UserPasswordValidate(info.Snowflake, "initial") { log.Warnf("Initial user still has the initial password.") } } else { if single { log.Fatal("Instance has no initial user, single user mode unavailable.") } } if single { log.Info("Server running in single user mode, all operations are performed as the initial user.") } else if private { log.Info("Server running in private mode, all operations will require authentication.") } } func parseBool(v interface{}) bool { if s, ok := v.(bool); !ok { var sS string if sS, ok = v.(string); !ok { return false } else { if b, err := strconv.ParseBool(sS); err != nil { log.Warnf("Error parsing boolean value, %s", err) return false } else { return b } } } else { return s } }