package config import ( "net/netip" "slices" "strconv" "github.com/rs/zerolog" "github.com/spf13/viper" ) type Config struct { DatabaseDSN string // panic = 5, // fatal = 4, // error = 3, // warn = 2, // info = 1, // debug = 0, // trace = -1 LogLevel int HostIP netip.Addr HostPort int HostURL string ProxyHeader string AccessLog bool } func NewConfig(configPath string) *Config { logger := NewLogger(zerolog.InfoLevel) loadConfigFile(configPath, logger) cfg := new(Config) exit := false // handle Database DSN if viper.GetString("database.url") != "" { cfg.DatabaseDSN = viper.GetString("database.url") } else { dsn := "postgres://" if viper.GetString("database.username") == "" { exit = true logger.Error().Msg("If database.url is not set, database.username must not be empty!") } else { dsn = dsn + viper.GetString("database.username") } if viper.GetString("database.password") == "" { exit = true logger.Error().Msg("If database.url is not set, database.password must not be empty!") } else { dsn = dsn + ":" + viper.GetString("database.password") } if viper.GetString("database.address") == "" { exit = true logger.Error().Msg("If database.url is not set, database.address must not be empty!") } else { dsn = dsn + "@" + viper.GetString("database.address") } if viper.GetString("database.port") != "" { dsn = dsn + ":" + strconv.Itoa(viper.GetInt("database.port")) } if viper.GetString("database.database") == "" { exit = true logger.Error().Msg("If database.url is not set, database.database must not be empty!") } else { dsn = dsn + "/" + viper.GetString("database.database") } if slices.Contains([]string{"disable", "require", "verify-full", ""}, viper.GetString("database.ssl-mode")) { if viper.GetString("database.ssl-mode") == "" { cfg.DatabaseDSN = dsn + "?sslmode=disable" } else { cfg.DatabaseDSN = dsn + "?sslmode=" + viper.GetString("database.ssl-mode") } } else { logger.Error().Msg(`If database.url is not set, database.ssl-mode must be either "disable", "require", "verify-full" or empty!`) } } // Handle Logging switch logLevel := viper.GetString("logging.level"); logLevel { case "panic": cfg.LogLevel = 5 case "fatal": cfg.LogLevel = 4 case "error": cfg.LogLevel = 3 case "warn": cfg.LogLevel = 2 case "info": cfg.LogLevel = 1 case "debug": cfg.LogLevel = 0 case "trace": cfg.LogLevel = -1 default: exit = true logger.Error().Str("value", logLevel).Msg(`Value of logging.level is invalid!`) } cfg.HostURL = viper.GetString("application.base-url") if viper.GetString("application.listen") != "" { ip, err := netip.ParseAddr(viper.GetString("application.listen")) if err != nil { exit = true logger.Error().Str("value", viper.GetString("application.listen")).Msg(`Value of application.listen is not a valid IP address!`) } else { cfg.HostIP = ip } } else { cfg.HostIP = netip.MustParseAddr("127.0.0.1") } if viper.GetInt("application.port") != 0 { // if port is a valid port number if viper.GetInt("application.port") <= 65535 && viper.GetInt("application.port") > 0 { cfg.HostPort = viper.GetInt("application.port") } else { logger.Error().Str("value", viper.GetString("application.port")).Msg(`Value of application.port is not a valid port number!`) } } else { cfg.HostPort = 3000 } if viper.GetString("application.proxy-header") == "" { cfg.ProxyHeader = "X-Forwarded-For" } else { cfg.ProxyHeader = viper.GetString("application.proxy-header") } if exit { logger.Fatal().Msg("There were errors reading the config file. See errors above!") } return cfg }