From 41166e5c356df10d36237e9296979cae65652504 Mon Sep 17 00:00:00 2001 From: Rob Loranger Date: Tue, 5 Nov 2019 09:14:20 -0800 Subject: [PATCH] CLI delete account by username and delete posts this changed the CLI flag to use the username instead of the userID leaving the underlying database function as is. also now posts are all deleted with no option to skip as this is likely never needed. --- account.go | 4 ++-- app.go | 25 ++++++++++++---------- cmd/writefreely/main.go | 7 +++--- database.go | 47 ++++++++++++++++++----------------------- 4 files changed, 39 insertions(+), 44 deletions(-) diff --git a/account.go b/account.go index c8e946a..5e5f03e 100644 --- a/account.go +++ b/account.go @@ -1069,6 +1069,6 @@ func getTempInfo(app *App, key string, r *http.Request, w http.ResponseWriter) s return s } -func deleteAccount(app *App, userID int64, posts bool) error { - return app.db.DeleteAccount(userID, posts) +func deleteAccount(app *App, userID int64) error { + return app.db.DeleteAccount(userID) } diff --git a/app.go b/app.go index 8e8471f..e793902 100644 --- a/app.go +++ b/app.go @@ -682,21 +682,24 @@ func ResetPassword(apper Apper, username string) error { } // DoDeleteAccount runs the confirmation and account delete process. -func DoDeleteAccount(apper Apper, userID int64, posts bool) error { +func DoDeleteAccount(apper Apper, username string) error { // Connect to the database apper.LoadConfig() connectToDatabase(apper.App()) defer shutdown(apper.App()) - // do not delete the root admin account - // TODO: check for other admins and skip? - if userID == 1 { - log.Error("Can not delete admin account") + // check user exists + u, err := apper.App().db.GetUserForAuth(username) + if err != nil { + log.Error("%s", err) os.Exit(1) } - // check user exists - if _, err := apper.App().db.GetUserByID(userID); err != nil { - log.Error("%s", err) + userID := u.ID + + // do not delete the admin account + // TODO: check for other admins and skip? + if u.IsAdmin() { + log.Error("Can not delete admin account") os.Exit(1) } @@ -705,17 +708,17 @@ func DoDeleteAccount(apper Apper, userID int64, posts bool) error { Templates: &promptui.PromptTemplates{ Success: "{{ . | bold | faint }}: ", }, - Label: fmt.Sprintf("Delete user with ID: %d", userID), + Label: fmt.Sprintf("Really delete user : %s", username), IsConfirm: true, } - _, err := prompt.Run() + _, err = prompt.Run() if err != nil { log.Info("Aborted...") os.Exit(0) } log.Info("Deleting...") - err = deleteAccount(apper.App(), userID, posts) + err = deleteAccount(apper.App(), userID) if err != nil { log.Error("%s", err) os.Exit(1) diff --git a/cmd/writefreely/main.go b/cmd/writefreely/main.go index 10d8141..7fc2342 100644 --- a/cmd/writefreely/main.go +++ b/cmd/writefreely/main.go @@ -39,8 +39,7 @@ func main() { // Admin actions createAdmin := flag.String("create-admin", "", "Create an admin with the given username:password") createUser := flag.String("create-user", "", "Create a regular user with the given username:password") - deleteUserID := flag.Int64("delete-user", 0, "Delete a user with the given id, does not delete posts. Use `--delete-user id --posts`") - deletePosts := flag.Bool("posts", false, "Optionally delete the user's posts during account deletion") + deleteUsername := flag.String("delete-user", "", "Delete a user with the given username") resetPassUser := flag.String("reset-pass", "", "Reset the given user's password") outputVersion := flag.Bool("v", false, "Output the current version") flag.Parse() @@ -105,8 +104,8 @@ func main() { os.Exit(1) } os.Exit(0) - } else if *deleteUserID != 0 { - err := writefreely.DoDeleteAccount(app, *deleteUserID, *deletePosts) + } else if *deleteUsername != "" { + err := writefreely.DoDeleteAccount(app, *deleteUsername) if err != nil { log.Error(err.Error()) os.Exit(1) diff --git a/database.go b/database.go index cecd169..f2888ec 100644 --- a/database.go +++ b/database.go @@ -61,7 +61,7 @@ type writestore interface { GetAccessToken(userID int64) (string, error) GetTemporaryAccessToken(userID int64, validSecs int) (string, error) GetTemporaryOneTimeAccessToken(userID int64, validSecs int, oneTime bool) (string, error) - DeleteAccount(userID int64, posts bool) error + DeleteAccount(userID int64) error ChangeSettings(app *App, u *User, s *userSettings) error ChangePassphrase(userID int64, sudo bool, curPass string, hashedPass []byte) error @@ -2079,9 +2079,8 @@ func (db *datastore) CollectionHasAttribute(id int64, attr string) bool { return true } -// DeleteAccount will delete the entire account for userID, and if posts -// is true, also all posts associated with the userID -func (db *datastore) DeleteAccount(userID int64, posts bool) error { +// DeleteAccount will delete the entire account for userID +func (db *datastore) DeleteAccount(userID int64) error { // Get all collections rows, err := db.Query("SELECT id, alias FROM collections WHERE owner_id = ?", userID) if err != nil { @@ -2110,7 +2109,6 @@ func (db *datastore) DeleteAccount(userID int64, posts bool) error { // Clean up all collection related information var res sql.Result for _, c := range colls { - // TODO: user deleteCollection() func // Delete tokens res, err = t.Exec("DELETE FROM collectionattributes WHERE collection_id = ?", c.ID) if err != nil { @@ -2151,18 +2149,15 @@ func (db *datastore) DeleteAccount(userID int64, posts bool) error { rs, _ = res.RowsAffected() log.Info("Deleted %d for %s from collectionkeys", rs, c.Alias) - // only remove collection in posts if not deleting the user posts - if !posts { - // Float all collection's posts - res, err = t.Exec("UPDATE posts SET collection_id = NULL WHERE collection_id = ? AND owner_id = ?", c.ID, userID) - if err != nil { - t.Rollback() - log.Error("Unable to update collection %s for posts: %v", err) - return err - } - rs, _ = res.RowsAffected() - log.Info("Removed %d posts from collection %s", rs, c.Alias) + // Float all collection's posts + res, err = t.Exec("UPDATE posts SET collection_id = NULL WHERE collection_id = ? AND owner_id = ?", c.ID, userID) + if err != nil { + t.Rollback() + log.Error("Unable to update collection %s for posts: %v", c.Alias, err) + return err } + rs, _ = res.RowsAffected() + log.Info("Removed %d posts from collection %s", rs, c.Alias) // TODO: federate delete collection @@ -2198,18 +2193,16 @@ func (db *datastore) DeleteAccount(userID int64, posts bool) error { log.Info("Deleted %d from accesstokens", rs) // Delete posts - if posts { - // TODO: should maybe get each row so we can federate a delete - // if so needs to be outside of transaction like collections - res, err = t.Exec("DELETE FROM posts WHERE owner_id = ?", userID) - if err != nil { - t.Rollback() - log.Error("Unable to delete posts: %v", err) - return err - } - rs, _ = res.RowsAffected() - log.Info("Deleted %d from posts", rs) + // TODO: should maybe get each row so we can federate a delete + // if so needs to be outside of transaction like collections + res, err = t.Exec("DELETE FROM posts WHERE owner_id = ?", userID) + if err != nil { + t.Rollback() + log.Error("Unable to delete posts: %v", err) + return err } + rs, _ = res.RowsAffected() + log.Info("Deleted %d from posts", rs) // Delete user attributes res, err = t.Exec("DELETE FROM userattributes WHERE user_id = ?", userID)