package config import ( "encoding/json" "fmt" "html/template" "io/ioutil" "log" ) type Config struct { Server struct { ListenAddress string ListenPort int Protocol string Domain string } Date struct { MinuteGranularity int } Request struct { SecretLength int } Mailer struct { Type string FromAddress string FromName template.HTML SmtpHost string SmtpPort int SmtpUseAuth bool SmtpIdentity string SmtpPassword string } SQL struct { Type string SQLiteFile string MysqlUser string MysqlPassword string MysqlHost string MysqlPort int MysqlDatabase string } Tutor struct { MailSuffix string } } // ReadConfigFile takes a file path as an argument and attempts to // unmarshal the content of the file into a struct containing a // configuration. func ReadConfigFile(filename string, conf *Config) error { configData, err := ioutil.ReadFile(filename) if err != nil { err = fmt.Errorf("Error reading config file: %w", err) log.Println(err.Error()) return err } err = json.Unmarshal(configData, conf) if err != nil { err = fmt.Errorf("Error parsing config file as json: %w", err) log.Println(err.Error()) return err } return validateConfig(conf) } // Checks config for sane values (e.g. correct port range or database type). func validateConfig(conf *Config) error { var err error if !(conf.Server.ListenPort >= 1 && conf.Server.ListenPort <= 65535) { err = fmt.Errorf("Validating config: Server port must be between 1 and 65535, but is %d.", conf.Server.ListenPort) log.Println(err.Error()) } if !(conf.Server.Protocol == "http" || conf.Server.Protocol == "https") { err = fmt.Errorf("Validating config: Server protocol must be 'http' or 'https', but is '%s'.", conf.Server.Protocol) log.Println(err.Error()) } if !(conf.Date.MinuteGranularity >= 1 && conf.Date.MinuteGranularity <= 60) { err = fmt.Errorf("Validating config: Minute granularity must be between 1 and 60, but is %d.", conf.Date.MinuteGranularity) log.Println(err.Error()) } if !(conf.Request.SecretLength >= 5 && conf.Request.SecretLength <= 50) { err = fmt.Errorf("Validating config: Requests' secret length must be between 5 and 50, but is %d.", conf.Request.SecretLength) log.Println(err.Error()) } if !(conf.Mailer.Type == "Stdout" || conf.Mailer.Type == "Smtp") { err = fmt.Errorf("Validating config: Mailer type must be 'Stdout' or 'Smtp', but is '%s'.", conf.Mailer.Type) log.Println(err.Error()) } if !(conf.SQL.Type == "SQLite" || conf.SQL.Type == "Mysql") { err = fmt.Errorf("Validating config: SQL type must be 'SQLite' or 'Mysql', but is '%s'.", conf.SQL.Type) log.Println(err.Error()) } return err }