diff --git a/app.go b/app.go index f7c8d08..23286b0 100644 --- a/app.go +++ b/app.go @@ -235,15 +235,14 @@ func Serve() { if *configSections == "" { *configSections = "server db app" } - configSectionsArray := strings.Split(*configSections, " ") - // let's check there aren't any garbage in the list + configSectionsArray := strings.Split(*configSections, " ") for _, element := range configSectionsArray { if element != "server" && element != "db" && element != "app" { log.Error("Invalid argument to --sections. Valid arguments are only \"server\", \"db\" and \"app\"") } } - d, err := config.Configure(app.cfgFile, configSectionsArray) + d, err := config.Configure(app.cfgFile, *configSections) if err != nil { log.Error("Unable to configure: %v", err) os.Exit(1) diff --git a/config/setup.go b/config/setup.go index 5d806ea..7f5030b 100644 --- a/config/setup.go +++ b/config/setup.go @@ -17,6 +17,7 @@ import ( "github.com/mitchellh/go-wordwrap" "github.com/writeas/web-core/auth" "strconv" + "strings" ) type SetupData struct { @@ -24,7 +25,7 @@ type SetupData struct { Config *Config } -func Configure(fname string, configSections []string) (*SetupData, error) { +func Configure(fname string, configSections string) (*SetupData, error) { data := &SetupData{} var err error if fname == "" { @@ -52,9 +53,6 @@ func Configure(fname string, configSections []string) (*SetupData, error) { fmt.Println(wordwrap.WrapString(" This quick configuration process will "+action+" the application's config file, "+fname+".\n\n It validates your input along the way, so you can be sure any future errors aren't caused by a bad configuration. If you'd rather configure your server manually, instead run: writefreely --create-config and edit that file.", 75)) fmt.Println() - title(" Server setup ") - fmt.Println() - tmpls := &promptui.PromptTemplates{ Success: "{{ . | bold | faint }}: ", } @@ -78,284 +76,296 @@ func Configure(fname string, configSections []string) (*SetupData, error) { data.Config.Server.Dev = isDevEnv var prompt promptui.Prompt - if isDevEnv || !isStandalone { - // Running in dev environment or behind reverse proxy; ask for port - prompt = promptui.Prompt{ - Templates: tmpls, - Label: "Local port", - Validate: validatePort, - Default: fmt.Sprintf("%d", data.Config.Server.Port), + + if strings.Contains(configSections, "server"){ + + title(" Server setup ") + fmt.Println() + + if isDevEnv || !isStandalone { + // Running in dev environment or behind reverse proxy; ask for port + prompt = promptui.Prompt{ + Templates: tmpls, + Label: "Local port", + Validate: validatePort, + Default: fmt.Sprintf("%d", data.Config.Server.Port), + } + port, err := prompt.Run() + if err != nil { + return data, err + } + data.Config.Server.Port, _ = strconv.Atoi(port) // Ignore error, as we've already validated number } - port, err := prompt.Run() - if err != nil { - return data, err + + if isStandalone { + selPrompt = promptui.Select{ + Templates: selTmpls, + Label: "Web server mode", + Items: []string{"Insecure (port 80)", "Secure (port 443)"}, + } + sel, _, err := selPrompt.Run() + if err != nil { + return data, err + } + if sel == 0 { + data.Config.Server.Port = 80 + data.Config.Server.TLSCertPath = "" + data.Config.Server.TLSKeyPath = "" + } else if sel == 1 { + data.Config.Server.Port = 443 + + prompt = promptui.Prompt{ + Templates: tmpls, + Label: "Certificate path", + Validate: validateNonEmpty, + Default: data.Config.Server.TLSCertPath, + } + data.Config.Server.TLSCertPath, err = prompt.Run() + if err != nil { + return data, err + } + + prompt = promptui.Prompt{ + Templates: tmpls, + Label: "Key path", + Validate: validateNonEmpty, + Default: data.Config.Server.TLSKeyPath, + } + data.Config.Server.TLSKeyPath, err = prompt.Run() + if err != nil { + return data, err + } + } + } else { + data.Config.Server.TLSCertPath = "" + data.Config.Server.TLSKeyPath = "" } - data.Config.Server.Port, _ = strconv.Atoi(port) // Ignore error, as we've already validated number + + fmt.Println() } - - if isStandalone { + if strings.Contains(configSections, "db"){ + title(" Database setup ") + fmt.Println() + selPrompt = promptui.Select{ Templates: selTmpls, - Label: "Web server mode", - Items: []string{"Insecure (port 80)", "Secure (port 443)"}, + Label: "Database driver", + Items: []string{"MySQL", "SQLite"}, } sel, _, err := selPrompt.Run() if err != nil { return data, err } + if sel == 0 { - data.Config.Server.Port = 80 - data.Config.Server.TLSCertPath = "" - data.Config.Server.TLSKeyPath = "" - } else if sel == 1 { - data.Config.Server.Port = 443 - + // Configure for MySQL + data.Config.UseMySQL(isNewCfg) + prompt = promptui.Prompt{ Templates: tmpls, - Label: "Certificate path", + Label: "Username", Validate: validateNonEmpty, - Default: data.Config.Server.TLSCertPath, + Default: data.Config.Database.User, } - data.Config.Server.TLSCertPath, err = prompt.Run() + data.Config.Database.User, err = prompt.Run() if err != nil { return data, err } - + prompt = promptui.Prompt{ Templates: tmpls, - Label: "Key path", + Label: "Password", Validate: validateNonEmpty, - Default: data.Config.Server.TLSKeyPath, + Default: data.Config.Database.Password, + Mask: '*', } - data.Config.Server.TLSKeyPath, err = prompt.Run() + data.Config.Database.Password, err = prompt.Run() + if err != nil { + return data, err + } + + prompt = promptui.Prompt{ + Templates: tmpls, + Label: "Database name", + Validate: validateNonEmpty, + Default: data.Config.Database.Database, + } + data.Config.Database.Database, err = prompt.Run() + if err != nil { + return data, err + } + + prompt = promptui.Prompt{ + Templates: tmpls, + Label: "Host", + Validate: validateNonEmpty, + Default: data.Config.Database.Host, + } + data.Config.Database.Host, err = prompt.Run() + if err != nil { + return data, err + } + + prompt = promptui.Prompt{ + Templates: tmpls, + Label: "Port", + Validate: validatePort, + Default: fmt.Sprintf("%d", data.Config.Database.Port), + } + dbPort, err := prompt.Run() + if err != nil { + return data, err + } + data.Config.Database.Port, _ = strconv.Atoi(dbPort) // Ignore error, as we've already validated number + } else if sel == 1 { + // Configure for SQLite + data.Config.UseSQLite(isNewCfg) + + prompt = promptui.Prompt{ + Templates: tmpls, + Label: "Filename", + Validate: validateNonEmpty, + Default: data.Config.Database.FileName, + } + data.Config.Database.FileName, err = prompt.Run() if err != nil { return data, err } } - } else { - data.Config.Server.TLSCertPath = "" - data.Config.Server.TLSKeyPath = "" - } - - fmt.Println() - title(" Database setup ") - fmt.Println() - - selPrompt = promptui.Select{ - Templates: selTmpls, - Label: "Database driver", - Items: []string{"MySQL", "SQLite"}, - } - sel, _, err := selPrompt.Run() - if err != nil { - return data, err + + fmt.Println() } + if strings.Contains(configSections, "app"){ - if sel == 0 { - // Configure for MySQL - data.Config.UseMySQL(isNewCfg) - - prompt = promptui.Prompt{ - Templates: tmpls, - Label: "Username", - Validate: validateNonEmpty, - Default: data.Config.Database.User, - } - data.Config.Database.User, err = prompt.Run() - if err != nil { - return data, err - } - - prompt = promptui.Prompt{ - Templates: tmpls, - Label: "Password", - Validate: validateNonEmpty, - Default: data.Config.Database.Password, - Mask: '*', - } - data.Config.Database.Password, err = prompt.Run() - if err != nil { - return data, err - } - - prompt = promptui.Prompt{ - Templates: tmpls, - Label: "Database name", - Validate: validateNonEmpty, - Default: data.Config.Database.Database, - } - data.Config.Database.Database, err = prompt.Run() - if err != nil { - return data, err - } - - prompt = promptui.Prompt{ - Templates: tmpls, - Label: "Host", - Validate: validateNonEmpty, - Default: data.Config.Database.Host, - } - data.Config.Database.Host, err = prompt.Run() - if err != nil { - return data, err - } - - prompt = promptui.Prompt{ - Templates: tmpls, - Label: "Port", - Validate: validatePort, - Default: fmt.Sprintf("%d", data.Config.Database.Port), + title(" App setup ") + fmt.Println() + + selPrompt = promptui.Select{ + Templates: selTmpls, + Label: "Site type", + Items: []string{"Single user blog", "Multi-user instance"}, } - dbPort, err := prompt.Run() + _, usersType, err := selPrompt.Run() if err != nil { return data, err } - data.Config.Database.Port, _ = strconv.Atoi(dbPort) // Ignore error, as we've already validated number - } else if sel == 1 { - // Configure for SQLite - data.Config.UseSQLite(isNewCfg) - - prompt = promptui.Prompt{ - Templates: tmpls, - Label: "Filename", - Validate: validateNonEmpty, - Default: data.Config.Database.FileName, + data.Config.App.SingleUser = usersType == "Single user blog" + + if data.Config.App.SingleUser { + data.User = &UserCreation{} + + // prompt for username + prompt = promptui.Prompt{ + Templates: tmpls, + Label: "Admin username", + Validate: validateNonEmpty, + } + data.User.Username, err = prompt.Run() + if err != nil { + return data, err + } + + // prompt for password + prompt = promptui.Prompt{ + Templates: tmpls, + Label: "Admin password", + Validate: validateNonEmpty, + } + newUserPass, err := prompt.Run() + if err != nil { + return data, err + } + + data.User.HashedPass, err = auth.HashPass([]byte(newUserPass)) + if err != nil { + return data, err + } } - data.Config.Database.FileName, err = prompt.Run() - if err != nil { - return data, err + + siteNameLabel := "Instance name" + if data.Config.App.SingleUser { + siteNameLabel = "Blog name" } - } - - fmt.Println() - title(" App setup ") - fmt.Println() - - selPrompt = promptui.Select{ - Templates: selTmpls, - Label: "Site type", - Items: []string{"Single user blog", "Multi-user instance"}, - } - _, usersType, err := selPrompt.Run() - if err != nil { - return data, err - } - data.Config.App.SingleUser = usersType == "Single user blog" - - if data.Config.App.SingleUser { - data.User = &UserCreation{} - - // prompt for username prompt = promptui.Prompt{ Templates: tmpls, - Label: "Admin username", + Label: siteNameLabel, Validate: validateNonEmpty, + Default: data.Config.App.SiteName, } - data.User.Username, err = prompt.Run() + data.Config.App.SiteName, err = prompt.Run() if err != nil { return data, err } - - // prompt for password + prompt = promptui.Prompt{ Templates: tmpls, - Label: "Admin password", - Validate: validateNonEmpty, + Label: "Public URL", + Validate: validateDomain, + Default: data.Config.App.Host, } - newUserPass, err := prompt.Run() + data.Config.App.Host, err = prompt.Run() if err != nil { return data, err } - - data.User.HashedPass, err = auth.HashPass([]byte(newUserPass)) - if err != nil { - return data, err - } - } - - siteNameLabel := "Instance name" - if data.Config.App.SingleUser { - siteNameLabel = "Blog name" - } - prompt = promptui.Prompt{ - Templates: tmpls, - Label: siteNameLabel, - Validate: validateNonEmpty, - Default: data.Config.App.SiteName, - } - data.Config.App.SiteName, err = prompt.Run() - if err != nil { - return data, err - } - - prompt = promptui.Prompt{ - Templates: tmpls, - Label: "Public URL", - Validate: validateDomain, - Default: data.Config.App.Host, - } - data.Config.App.Host, err = prompt.Run() - if err != nil { - return data, err - } - - if !data.Config.App.SingleUser { - selPrompt = promptui.Select{ - Templates: selTmpls, - Label: "Registration", - Items: []string{"Open", "Closed"}, - } - _, regType, err := selPrompt.Run() - if err != nil { - return data, err - } - data.Config.App.OpenRegistration = regType == "Open" - - prompt = promptui.Prompt{ - Templates: tmpls, - Label: "Max blogs per user", - Default: fmt.Sprintf("%d", data.Config.App.MaxBlogs), - } - maxBlogs, err := prompt.Run() - if err != nil { - return data, err + + if !data.Config.App.SingleUser { + selPrompt = promptui.Select{ + Templates: selTmpls, + Label: "Registration", + Items: []string{"Open", "Closed"}, + } + _, regType, err := selPrompt.Run() + if err != nil { + return data, err + } + data.Config.App.OpenRegistration = regType == "Open" + + prompt = promptui.Prompt{ + Templates: tmpls, + Label: "Max blogs per user", + Default: fmt.Sprintf("%d", data.Config.App.MaxBlogs), + } + maxBlogs, err := prompt.Run() + if err != nil { + return data, err + } + data.Config.App.MaxBlogs, _ = strconv.Atoi(maxBlogs) // Ignore error, as we've already validated number } - data.Config.App.MaxBlogs, _ = strconv.Atoi(maxBlogs) // Ignore error, as we've already validated number - } - - selPrompt = promptui.Select{ - Templates: selTmpls, - Label: "Federation", - Items: []string{"Enabled", "Disabled"}, - } - _, fedType, err := selPrompt.Run() - if err != nil { - return data, err - } - data.Config.App.Federation = fedType == "Enabled" - - if data.Config.App.Federation { + selPrompt = promptui.Select{ Templates: selTmpls, - Label: "Federation usage stats", - Items: []string{"Public", "Private"}, + Label: "Federation", + Items: []string{"Enabled", "Disabled"}, } - _, fedStatsType, err := selPrompt.Run() + _, fedType, err := selPrompt.Run() if err != nil { return data, err } - data.Config.App.PublicStats = fedStatsType == "Public" - - selPrompt = promptui.Select{ - Templates: selTmpls, - Label: "Instance metadata privacy", - Items: []string{"Public", "Private"}, - } - _, fedStatsType, err = selPrompt.Run() - if err != nil { - return data, err + data.Config.App.Federation = fedType == "Enabled" + + if data.Config.App.Federation { + selPrompt = promptui.Select{ + Templates: selTmpls, + Label: "Federation usage stats", + Items: []string{"Public", "Private"}, + } + _, fedStatsType, err := selPrompt.Run() + if err != nil { + return data, err + } + data.Config.App.PublicStats = fedStatsType == "Public" + + selPrompt = promptui.Select{ + Templates: selTmpls, + Label: "Instance metadata privacy", + Items: []string{"Public", "Private"}, + } + _, fedStatsType, err = selPrompt.Run() + if err != nil { + return data, err + } + data.Config.App.Private = fedStatsType == "Private" } - data.Config.App.Private = fedStatsType == "Private" } return data, Save(data.Config, fname)