From 08667d8978eb3dddbd473fcdd0ff4147bf515e6a Mon Sep 17 00:00:00 2001 From: Matt Baer Date: Sat, 26 Jan 2019 10:52:11 -0500 Subject: [PATCH 1/6] Return error from adminInitDatabase() ...instead of doing os.Exit(). This allows the func to be used in many places (as it is) and handle success results in different ways. Previously, this caused the single-user configuration process to exit prematurely. This fixes that and closes #71. --- app.go | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/app.go b/app.go index e942f7b..b60bc6e 100644 --- a/app.go +++ b/app.go @@ -234,7 +234,11 @@ func Serve() { defer shutdown(app) if !app.db.DatabaseInitialized() { - adminInitDatabase(app) + err = adminInitDatabase(app) + if err != nil { + log.Error(err.Error()) + os.Exit(1) + } } u := &User{ @@ -289,7 +293,12 @@ func Serve() { loadConfig(app) connectToDatabase(app) defer shutdown(app) - adminInitDatabase(app) + err := adminInitDatabase(app) + if err != nil { + log.Error(err.Error()) + os.Exit(1) + } + os.Exit(0) } else if *createAdmin != "" { adminCreateUser(app, *createAdmin, true) } else if *createUser != "" { @@ -581,7 +590,7 @@ func adminCreateUser(app *app, credStr string, isAdmin bool) { os.Exit(0) } -func adminInitDatabase(app *app) { +func adminInitDatabase(app *app) error { schemaFileName := "schema.sql" if app.cfg.Database.Type == driverSQLite { schemaFileName = "sqlite.sql" @@ -589,8 +598,7 @@ func adminInitDatabase(app *app) { schema, err := Asset(schemaFileName) if err != nil { - log.Error("Unable to load schema file: %v", err) - os.Exit(1) + return fmt.Errorf("Unable to load schema file: %v", err) } tblReg := regexp.MustCompile("CREATE TABLE (IF NOT EXISTS )?`([a-z_]+)`") @@ -618,10 +626,9 @@ func adminInitDatabase(app *app) { log.Info("Updating appmigrations table...") err = migrations.SetInitialMigrations(migrations.NewDatastore(app.db.DB, app.db.driverName)) if err != nil { - log.Error("Unable to set initial migrations: %v", err) - os.Exit(1) + return fmt.Errorf("Unable to set initial migrations: %v", err) } - log.Info("Done.") - os.Exit(0) + log.Info("Done.") + return nil } From c11ede53d9f849f0a43d798635dacd4657f5db50 Mon Sep 17 00:00:00 2001 From: Matt Baer Date: Sat, 26 Jan 2019 11:06:58 -0500 Subject: [PATCH 2/6] Return error from adminCreateUser() ...instead of using os.Exit(). This makes it more apparent what's going on, less error-prone, and more consistent with other command logic paths. --- app.go | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/app.go b/app.go index b60bc6e..f39c21a 100644 --- a/app.go +++ b/app.go @@ -300,9 +300,19 @@ func Serve() { } os.Exit(0) } else if *createAdmin != "" { - adminCreateUser(app, *createAdmin, true) + err := adminCreateUser(app, *createAdmin, true) + if err != nil { + log.Error(err.Error()) + os.Exit(1) + } + os.Exit(0) } else if *createUser != "" { - adminCreateUser(app, *createUser, false) + err := adminCreateUser(app, *createUser, false) + if err != nil { + log.Error(err.Error()) + os.Exit(1) + } + os.Exit(0) } else if *resetPassUser != "" { // Connect to the database loadConfig(app) @@ -517,12 +527,11 @@ func shutdown(app *app) { app.db.Close() } -func adminCreateUser(app *app, credStr string, isAdmin bool) { +func adminCreateUser(app *app, credStr string, isAdmin bool) error { // Create an admin user with --create-admin creds := strings.Split(credStr, ":") if len(creds) != 2 { - log.Error("usage: writefreely --create-admin username:password") - os.Exit(1) + return fmt.Errorf("usage: writefreely --create-admin username:password") } loadConfig(app) @@ -534,14 +543,12 @@ func adminCreateUser(app *app, credStr string, isAdmin bool) { if isAdmin { // Abort if trying to create admin user, but one already exists if firstUser != nil { - log.Error("Admin user already exists (%s). Create a regular user with: writefreely --create-user", firstUser.Username) - os.Exit(1) + return fmt.Errorf("Admin user already exists (%s). Create a regular user with: writefreely --create-user", firstUser.Username) } } else { // Abort if trying to create regular user, but no admin exists yet if firstUser == nil { - log.Error("No admin user exists yet. Create an admin first with: writefreely --create-admin") - os.Exit(1) + return fmt.Errorf("No admin user exists yet. Create an admin first with: writefreely --create-admin") } } @@ -559,15 +566,13 @@ func adminCreateUser(app *app, credStr string, isAdmin bool) { } if !author.IsValidUsername(app.cfg, username) { - log.Error("Username %s is invalid, reserved, or shorter than configured minimum length (%d characters).", usernameDesc, app.cfg.App.MinUsernameLen) - os.Exit(1) + return fmt.Errorf("Username %s is invalid, reserved, or shorter than configured minimum length (%d characters).", usernameDesc, app.cfg.App.MinUsernameLen) } // Hash the password hashedPass, err := auth.HashPass([]byte(password)) if err != nil { - log.Error("Unable to hash password: %v", err) - os.Exit(1) + return fmt.Errorf("Unable to hash password: %v", err) } u := &User{ @@ -583,11 +588,10 @@ func adminCreateUser(app *app, credStr string, isAdmin bool) { log.Info("Creating %s %s...", userType, usernameDesc) err = app.db.CreateUser(u, desiredUsername) if err != nil { - log.Error("Unable to create user: %s", err) - os.Exit(1) + return fmt.Errorf("Unable to create user: %s", err) } log.Info("Done!") - os.Exit(0) + return nil } func adminInitDatabase(app *app) error { From cd752858b7ce7dead753d312c069e6019e96d195 Mon Sep 17 00:00:00 2001 From: Matt Baer Date: Sat, 26 Jan 2019 11:11:17 -0500 Subject: [PATCH 3/6] Fix --create-user usage error message --- app.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app.go b/app.go index f39c21a..0c2a1f5 100644 --- a/app.go +++ b/app.go @@ -531,7 +531,11 @@ func adminCreateUser(app *app, credStr string, isAdmin bool) error { // Create an admin user with --create-admin creds := strings.Split(credStr, ":") if len(creds) != 2 { - return fmt.Errorf("usage: writefreely --create-admin username:password") + c := "user" + if isAdmin { + c = "admin" + } + return fmt.Errorf("usage: writefreely --create-%s username:password", c) } loadConfig(app) From e1cd11df20dd07d529c75d19787b0b6975c3cbd7 Mon Sep 17 00:00:00 2001 From: Matt Baer Date: Sat, 26 Jan 2019 11:13:36 -0500 Subject: [PATCH 4/6] Update `go get` instructions Including the `-d` flag ensures the package doesn't build. We need this because it will immediately fail, since the static assets haven't been compiled yet. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bde2d7d..52a1e88 100644 --- a/README.md +++ b/README.md @@ -102,7 +102,7 @@ Ready to hack on your site? Here's a quick overview. ### Setting up ```bash -go get github.com/writeas/writefreely/cmd/writefreely +go get -d github.com/writeas/writefreely/cmd/writefreely ``` Configure your site, create your database, and import the schema [as shown above](#quick-start). Then generate the remaining files you'll need: From ef40c50920015782f593f8ea10527b7f3a173caa Mon Sep 17 00:00:00 2001 From: Matt Baer Date: Sat, 26 Jan 2019 11:59:02 -0500 Subject: [PATCH 5/6] Link to tutorials on some features Also, add static pages --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 52a1e88..c61f5dc 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,9 @@ It's designed to be flexible and share your writing widely, so it's built around * Start a blog for yourself, or host a community of writers * Form larger federated networks, and interact over modern protocols like ActivityPub * Write on a fast, dead-simple, and distraction-free editor -* Format text with Markdown, and organize posts with hashtags +* [Format text](https://howto.write.as/getting-started) with Markdown +* [Organize posts](https://howto.write.as/organization) with hashtags +* Create [static pages](https://howto.write.as/creating-a-static-page) * Publish drafts and let others proofread them by sharing a private link * Create multiple lightweight blogs under a single account * Export all data in plain text files From 02054aae18f75e4b64852c91f3ef42ec7c7a6597 Mon Sep 17 00:00:00 2001 From: Matt Baer Date: Sat, 26 Jan 2019 21:25:38 -0500 Subject: [PATCH 6/6] Link to documentation repo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c61f5dc..ec8ec17 100644 --- a/README.md +++ b/README.md @@ -150,7 +150,7 @@ working on it, though! ## Contributing -We gladly welcome contributions to WriteFreely, whether in the form of [code](https://github.com/writeas/writefreely/blob/master/CONTRIBUTING.md#contributing-to-writefreely), [bug reports](https://github.com/writeas/writefreely/issues/new?template=bug_report.md), [feature requests](https://discuss.write.as/c/feedback/feature-requests), [translations](https://poeditor.com/join/project/TIZ6HFRFdE), or documentation improvements. +We gladly welcome contributions to WriteFreely, whether in the form of [code](https://github.com/writeas/writefreely/blob/master/CONTRIBUTING.md#contributing-to-writefreely), [bug reports](https://github.com/writeas/writefreely/issues/new?template=bug_report.md), [feature requests](https://discuss.write.as/c/feedback/feature-requests), [translations](https://poeditor.com/join/project/TIZ6HFRFdE), or [documentation](https://github.com/writefreely/documentation) improvements. Before contributing anything, please read our [Contributing Guide](https://github.com/writeas/writefreely/blob/master/CONTRIBUTING.md#contributing-to-writefreely). It describes the correct channels for submitting contributions and any potential requirements.