From 1d5c396327c036b2448628d806f351ea516191ce Mon Sep 17 00:00:00 2001 From: Michael Demetriou Date: Thu, 20 Jun 2019 23:14:36 +0300 Subject: [PATCH 1/6] Add --sections flag to app.go and pass it to setup.go Add --sections flag to app.go according to T657, parse them into a string array (check for invalid arguments and abort) and pass them to Configure(). For now Configure() doesn't do anything with them yet. --- app.go | 16 +++++++++++++++- config/setup.go | 2 +- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/app.go b/app.go index 540b496..f7c8d08 100644 --- a/app.go +++ b/app.go @@ -198,6 +198,9 @@ func Serve() { // Setup actions createConfig := flag.Bool("create-config", false, "Creates a basic configuration and exits") doConfig := flag.Bool("config", false, "Run the configuration process") + configSections := flag.String("sections", "server db app", "Which sections of the configuration to go through (requires --config), " + + "valid values are any combination of 'server', 'db' and 'app' " + + "example: writefreely --config --sections \"db app\"") genKeys := flag.Bool("gen-keys", false, "Generate encryption and authentication keys") createSchema := flag.Bool("init-db", false, "Initialize app database") migrate := flag.Bool("migrate", false, "Migrate the database") @@ -229,7 +232,18 @@ func Serve() { } os.Exit(0) } else if *doConfig { - d, err := config.Configure(app.cfgFile) + if *configSections == "" { + *configSections = "server db app" + } + configSectionsArray := strings.Split(*configSections, " ") + + // let's check there aren't any garbage in the list + 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) if err != nil { log.Error("Unable to configure: %v", err) os.Exit(1) diff --git a/config/setup.go b/config/setup.go index 4950bc3..5d806ea 100644 --- a/config/setup.go +++ b/config/setup.go @@ -24,7 +24,7 @@ type SetupData struct { Config *Config } -func Configure(fname string) (*SetupData, error) { +func Configure(fname string, configSections []string) (*SetupData, error) { data := &SetupData{} var err error if fname == "" { From 07fe366c15836cd24d688848ecb501556716acce Mon Sep 17 00:00:00 2001 From: Michael Demetriou Date: Thu, 20 Jun 2019 23:41:03 +0300 Subject: [PATCH 2/6] Fix T657: add --sections argument to allow partial configuration. Use the split argument list (slice) just for validation purposes as it's substantially easier to do `.contains` in a string instead of a slice. As such, pass the `configSections` arguments to `Configure()` and check the existence of each one before showing the options to the user. An empty argument list is replaced by "server db app" so everything is there negating the need to check anything else in `Configure()`. In the same vein the default is "server db app". The parsing is done in `app.go` alongside the other flags instead of `main.go` as described in T657. --- app.go | 5 +- config/setup.go | 464 +++++++++++++++++++++++++----------------------- 2 files changed, 239 insertions(+), 230 deletions(-) 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) From efbef83362036fd0b7571365ca5739b7265fde87 Mon Sep 17 00:00:00 2001 From: Michael Demetriou Date: Fri, 21 Jun 2019 10:40:40 +0300 Subject: [PATCH 3/6] make sure app exits after error in --sections argument --- app.go | 1 + 1 file changed, 1 insertion(+) diff --git a/app.go b/app.go index 23286b0..4cb7dab 100644 --- a/app.go +++ b/app.go @@ -240,6 +240,7 @@ func Serve() { 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\"") + os.Exit(1) } } d, err := config.Configure(app.cfgFile, *configSections) From aeab30db8a53defa6c1d7fa228323abf806d335a Mon Sep 17 00:00:00 2001 From: Michael Demetriou Date: Mon, 10 Jun 2019 00:43:19 +0300 Subject: [PATCH 4/6] Fix #96 This solves the error 500 on the /api/me endpoint. Replace token search query `=` with `LIKE` to fix sqlite complaining about no valid tokens. Also checked with MySQL and it still works after the change. --- database.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/database.go b/database.go index b52f27b..3af659d 100644 --- a/database.go +++ b/database.go @@ -388,7 +388,7 @@ func (db *datastore) GetUserNameFromToken(accessToken string) (string, error) { var oneTime bool var username string - err := db.QueryRow("SELECT username, one_time FROM accesstokens LEFT JOIN users ON user_id = id WHERE token = ? AND (expires IS NULL OR expires > NOW())", t).Scan(&username, &oneTime) + err := db.QueryRow("SELECT username, one_time FROM accesstokens LEFT JOIN users ON user_id = id WHERE token LIKE ? AND (expires IS NULL OR expires > "+db.now()+")", t).Scan(&username, &oneTime) switch { case err == sql.ErrNoRows: return "", ErrBadAccessToken @@ -413,7 +413,7 @@ func (db *datastore) GetUserDataFromToken(accessToken string) (int64, string, er var userID int64 var oneTime bool var username string - err := db.QueryRow("SELECT user_id, username, one_time FROM accesstokens LEFT JOIN users ON user_id = id WHERE token = ? AND (expires IS NULL OR expires > NOW())", t).Scan(&userID, &username, &oneTime) + err := db.QueryRow("SELECT user_id, username, one_time FROM accesstokens LEFT JOIN users ON user_id = id WHERE token LIKE ? AND (expires IS NULL OR expires > "+db.now()+")", t).Scan(&userID, &username, &oneTime) switch { case err == sql.ErrNoRows: return 0, "", ErrBadAccessToken @@ -452,7 +452,7 @@ func (db *datastore) GetUserIDPrivilege(accessToken string) (userID int64, sudo } var oneTime bool - err := db.QueryRow("SELECT user_id, sudo, one_time FROM accesstokens WHERE token = ? AND (expires IS NULL OR expires > NOW())", t).Scan(&userID, &sudo, &oneTime) + err := db.QueryRow("SELECT user_id, sudo, one_time FROM accesstokens WHERE token LIKE ? AND (expires IS NULL OR expires > "+db.now()+")", t).Scan(&userID, &sudo, &oneTime) switch { case err == sql.ErrNoRows: return -1, false @@ -469,7 +469,7 @@ func (db *datastore) GetUserIDPrivilege(accessToken string) (userID int64, sudo } func (db *datastore) DeleteToken(accessToken []byte) error { - res, err := db.Exec("DELETE FROM accesstokens WHERE token = ?", accessToken) + res, err := db.Exec("DELETE FROM accesstokens WHERE token LIKE ?", accessToken) if err != nil { return err } @@ -484,7 +484,7 @@ func (db *datastore) DeleteToken(accessToken []byte) error { // userID. func (db *datastore) FetchLastAccessToken(userID int64) string { var t []byte - err := db.QueryRow("SELECT token FROM accesstokens WHERE user_id = ? AND (expires IS NULL OR expires > NOW()) ORDER BY created DESC LIMIT 1", userID).Scan(&t) + err := db.QueryRow("SELECT token FROM accesstokens WHERE user_id = ? AND (expires IS NULL OR expires > "+db.now()+") ORDER BY created DESC LIMIT 1", userID).Scan(&t) switch { case err == sql.ErrNoRows: return "" @@ -529,7 +529,7 @@ func (db *datastore) GetTemporaryOneTimeAccessToken(userID int64, validSecs int, expirationVal := "NULL" if validSecs > 0 { - expirationVal = fmt.Sprintf("DATE_ADD(NOW(), INTERVAL %d SECOND)", validSecs) + expirationVal = fmt.Sprintf("DATE_ADD("+db.now()+", INTERVAL %d SECOND)", validSecs) } _, err = db.Exec("INSERT INTO accesstokens (token, user_id, one_time, expires) VALUES (?, ?, ?, "+expirationVal+")", string(binTok), userID, oneTime) From a740c67495a902fac8ab7ced9e452abe1cd909c6 Mon Sep 17 00:00:00 2001 From: Matt Baer Date: Mon, 1 Jul 2019 13:21:41 -0400 Subject: [PATCH 5/6] Fix whitespace This runs `go fmt` on changed files and moves around some blank lines. --- cmd/writefreely/main.go | 6 ++--- config/setup.go | 60 ++++++++++++++++++++--------------------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/cmd/writefreely/main.go b/cmd/writefreely/main.go index 98a984e..10cd7d6 100644 --- a/cmd/writefreely/main.go +++ b/cmd/writefreely/main.go @@ -28,9 +28,9 @@ func main() { // Setup actions createConfig := flag.Bool("create-config", false, "Creates a basic configuration and exits") doConfig := flag.Bool("config", false, "Run the configuration process") - configSections := flag.String("sections", "server db app", "Which sections of the configuration to go through (requires --config), " + - "valid values are any combination of 'server', 'db' and 'app' " + - "example: writefreely --config --sections \"db app\"") + configSections := flag.String("sections", "server db app", "Which sections of the configuration to go through (requires --config), "+ + "valid values are any combination of 'server', 'db' and 'app' "+ + "example: writefreely --config --sections \"db app\"") genKeys := flag.Bool("gen-keys", false, "Generate encryption and authentication keys") createSchema := flag.Bool("init-db", false, "Initialize app database") migrate := flag.Bool("migrate", false, "Migrate the database") diff --git a/config/setup.go b/config/setup.go index 7f5030b..ec4c368 100644 --- a/config/setup.go +++ b/config/setup.go @@ -76,12 +76,11 @@ func Configure(fname string, configSections string) (*SetupData, error) { data.Config.Server.Dev = isDevEnv var prompt promptui.Prompt - - if strings.Contains(configSections, "server"){ + 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{ @@ -96,7 +95,7 @@ func Configure(fname string, configSections string) (*SetupData, error) { } data.Config.Server.Port, _ = strconv.Atoi(port) // Ignore error, as we've already validated number } - + if isStandalone { selPrompt = promptui.Select{ Templates: selTmpls, @@ -113,7 +112,7 @@ func Configure(fname string, configSections string) (*SetupData, error) { data.Config.Server.TLSKeyPath = "" } else if sel == 1 { data.Config.Server.Port = 443 - + prompt = promptui.Prompt{ Templates: tmpls, Label: "Certificate path", @@ -124,7 +123,7 @@ func Configure(fname string, configSections string) (*SetupData, error) { if err != nil { return data, err } - + prompt = promptui.Prompt{ Templates: tmpls, Label: "Key path", @@ -140,13 +139,14 @@ func Configure(fname string, configSections string) (*SetupData, error) { data.Config.Server.TLSCertPath = "" data.Config.Server.TLSKeyPath = "" } - + fmt.Println() } - if strings.Contains(configSections, "db"){ + + if strings.Contains(configSections, "db") { title(" Database setup ") fmt.Println() - + selPrompt = promptui.Select{ Templates: selTmpls, Label: "Database driver", @@ -156,11 +156,11 @@ func Configure(fname string, configSections string) (*SetupData, error) { if err != nil { return data, err } - + if sel == 0 { // Configure for MySQL data.Config.UseMySQL(isNewCfg) - + prompt = promptui.Prompt{ Templates: tmpls, Label: "Username", @@ -171,7 +171,7 @@ func Configure(fname string, configSections string) (*SetupData, error) { if err != nil { return data, err } - + prompt = promptui.Prompt{ Templates: tmpls, Label: "Password", @@ -183,7 +183,7 @@ func Configure(fname string, configSections string) (*SetupData, error) { if err != nil { return data, err } - + prompt = promptui.Prompt{ Templates: tmpls, Label: "Database name", @@ -194,7 +194,7 @@ func Configure(fname string, configSections string) (*SetupData, error) { if err != nil { return data, err } - + prompt = promptui.Prompt{ Templates: tmpls, Label: "Host", @@ -205,7 +205,7 @@ func Configure(fname string, configSections string) (*SetupData, error) { if err != nil { return data, err } - + prompt = promptui.Prompt{ Templates: tmpls, Label: "Port", @@ -220,7 +220,7 @@ func Configure(fname string, configSections string) (*SetupData, error) { } else if sel == 1 { // Configure for SQLite data.Config.UseSQLite(isNewCfg) - + prompt = promptui.Prompt{ Templates: tmpls, Label: "Filename", @@ -232,14 +232,14 @@ func Configure(fname string, configSections string) (*SetupData, error) { return data, err } } - + fmt.Println() } - if strings.Contains(configSections, "app"){ + if strings.Contains(configSections, "app") { title(" App setup ") fmt.Println() - + selPrompt = promptui.Select{ Templates: selTmpls, Label: "Site type", @@ -250,10 +250,10 @@ func Configure(fname string, configSections string) (*SetupData, error) { 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, @@ -264,7 +264,7 @@ func Configure(fname string, configSections string) (*SetupData, error) { if err != nil { return data, err } - + // prompt for password prompt = promptui.Prompt{ Templates: tmpls, @@ -275,13 +275,13 @@ func Configure(fname string, configSections string) (*SetupData, error) { 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" @@ -296,7 +296,7 @@ func Configure(fname string, configSections string) (*SetupData, error) { if err != nil { return data, err } - + prompt = promptui.Prompt{ Templates: tmpls, Label: "Public URL", @@ -307,7 +307,7 @@ func Configure(fname string, configSections string) (*SetupData, error) { if err != nil { return data, err } - + if !data.Config.App.SingleUser { selPrompt = promptui.Select{ Templates: selTmpls, @@ -319,7 +319,7 @@ func Configure(fname string, configSections string) (*SetupData, error) { return data, err } data.Config.App.OpenRegistration = regType == "Open" - + prompt = promptui.Prompt{ Templates: tmpls, Label: "Max blogs per user", @@ -331,7 +331,7 @@ func Configure(fname string, configSections string) (*SetupData, error) { } data.Config.App.MaxBlogs, _ = strconv.Atoi(maxBlogs) // Ignore error, as we've already validated number } - + selPrompt = promptui.Select{ Templates: selTmpls, Label: "Federation", @@ -342,7 +342,7 @@ func Configure(fname string, configSections string) (*SetupData, error) { return data, err } data.Config.App.Federation = fedType == "Enabled" - + if data.Config.App.Federation { selPrompt = promptui.Select{ Templates: selTmpls, @@ -354,7 +354,7 @@ func Configure(fname string, configSections string) (*SetupData, error) { return data, err } data.Config.App.PublicStats = fedStatsType == "Public" - + selPrompt = promptui.Select{ Templates: selTmpls, Label: "Instance metadata privacy", From b8b15c85500688d41eaae6d28d80e02d1bddc657 Mon Sep 17 00:00:00 2001 From: Matt Baer Date: Mon, 1 Jul 2019 14:00:56 -0400 Subject: [PATCH 6/6] Move Environment prompt back under Server section --- config/setup.go | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/config/setup.go b/config/setup.go index ec4c368..b1c0c37 100644 --- a/config/setup.go +++ b/config/setup.go @@ -60,27 +60,28 @@ func Configure(fname string, configSections string) (*SetupData, error) { Selected: fmt.Sprintf(`{{.Label}} {{ . | faint }}`), } - // Environment selection - selPrompt := promptui.Select{ - Templates: selTmpls, - Label: "Environment", - Items: []string{"Development", "Production, standalone", "Production, behind reverse proxy"}, - } - _, envType, err := selPrompt.Run() - if err != nil { - return data, err - } - isDevEnv := envType == "Development" - isStandalone := envType == "Production, standalone" - - data.Config.Server.Dev = isDevEnv - + var selPrompt promptui.Select var prompt promptui.Prompt if strings.Contains(configSections, "server") { title(" Server setup ") fmt.Println() + // Environment selection + selPrompt = promptui.Select{ + Templates: selTmpls, + Label: "Environment", + Items: []string{"Development", "Production, standalone", "Production, behind reverse proxy"}, + } + _, envType, err := selPrompt.Run() + if err != nil { + return data, err + } + isDevEnv := envType == "Development" + isStandalone := envType == "Production, standalone" + + data.Config.Server.Dev = isDevEnv + if isDevEnv || !isStandalone { // Running in dev environment or behind reverse proxy; ask for port prompt = promptui.Prompt{