config.go
1 package lib 2 3 import ( 4 "fmt" 5 "net" 6 "net/url" 7 "os" 8 "strings" 9 10 "github.com/spf13/viper" 11 ) 12 13 type Config struct { 14 Debug string 15 16 Admin struct { 17 Username string 18 Password string 19 } 20 21 Database struct { 22 Type string 23 Connection string 24 } 25 26 Server struct { 27 BindIP string 28 Port string 29 Endpoint struct { 30 Api string 31 Web string 32 } 33 } 34 35 Feeds struct { 36 AutoRefresh string 37 } 38 } 39 40 func Cfg() (Config, error) { 41 viper.SetDefault("Debug", "false") 42 43 viper.SetDefault("Admin.Username", "admin") 44 viper.SetDefault("Admin.Password", "admin") 45 46 viper.SetDefault("Database.Type", "sqlite3") 47 viper.SetDefault("Database.Connection", "file:ent?mode=memory&cache=shared&_fk=1") 48 49 viper.SetDefault("Server.BindIP", "127.0.0.1") 50 viper.SetDefault("Server.Port", "8000") 51 viper.SetDefault("Server.Endpoint.Api", "http://127.0.0.1:8000/api") 52 viper.SetDefault("Server.Endpoint.Web", "http://127.0.0.1:8000/web") 53 54 viper.SetDefault("Feeds.AutoRefresh", "900") 55 56 viper.SetConfigName("journalist.toml") 57 viper.SetConfigType("toml") 58 viper.AddConfigPath("/etc/") 59 viper.AddConfigPath("$XDG_CONFIG_HOME/") 60 viper.AddConfigPath("$HOME/.config/") 61 viper.AddConfigPath("$HOME/") 62 viper.AddConfigPath(".") 63 64 viper.SetEnvPrefix("journalist") 65 viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) 66 viper.AutomaticEnv() 67 68 if err := viper.ReadInConfig(); err != nil { 69 if _, ok := err.(viper.ConfigFileNotFoundError); !ok { 70 return Config{}, err 71 } 72 } 73 74 var config Config 75 if err := viper.Unmarshal(&config); err != nil { 76 return Config{}, err 77 } 78 79 config = *ParseDatabaseURL(&config) 80 81 return config, nil 82 } 83 84 func ParseDatabaseURL(config *Config) *Config { 85 databaseURL := os.Getenv("DATABASE_URL") 86 if databaseURL == "" { 87 return config 88 } 89 90 dbURL, err := url.Parse(databaseURL) 91 if err != nil { 92 return config 93 } 94 95 host, port, _ := net.SplitHostPort(dbURL.Host) 96 dbname := strings.TrimLeft(dbURL.Path, "/") 97 user := dbURL.User.Username() 98 password, _ := dbURL.User.Password() 99 100 switch dbURL.Scheme { 101 case "postgresql", "postgres": 102 if port == "" { 103 port = "5432" 104 } 105 config.Database.Type = "postgres" 106 config.Database.Connection = fmt.Sprintf( 107 "host=%s port=%s dbname=%s user=%s password=%s", 108 host, port, dbname, user, password, 109 ) 110 case "mysql": 111 if port == "" { 112 port = "3306" 113 } 114 config.Database.Type = "mysql" 115 config.Database.Connection = fmt.Sprintf( 116 "%s:%s@tcp(%s:%s)/%s?parseTime=True", 117 user, password, host, port, dbname, 118 ) 119 } 120 121 return config 122 }