From aa9efc7b37219066ac767049b1c77e2d52fbc634 Mon Sep 17 00:00:00 2001 From: Rob Loranger Date: Thu, 3 Oct 2019 13:41:50 -0700 Subject: [PATCH 1/9] allow admin to reset user passwords this adds a new button when viewing a user as an admin, that will generate and store a new password for the user --- admin.go | 58 +++++++++++++++++++++++++---- routes.go | 1 + templates/user/admin/view-user.tmpl | 45 +++++++++++++++++++++- 3 files changed, 95 insertions(+), 9 deletions(-) diff --git a/admin.go b/admin.go index fdbb82f..5b3acab 100644 --- a/admin.go +++ b/admin.go @@ -16,12 +16,14 @@ import ( "net/http" "runtime" "strconv" + "strings" "time" "github.com/gorilla/mux" "github.com/writeas/impart" "github.com/writeas/web-core/auth" "github.com/writeas/web-core/log" + "github.com/writeas/web-core/passgen" "github.com/writeas/writefreely/appstats" "github.com/writeas/writefreely/config" ) @@ -167,25 +169,34 @@ func handleViewAdminUser(app *App, u *User, w http.ResponseWriter, r *http.Reque p := struct { *UserPage - Config config.AppCfg - Message string - - User *User - Colls []inspectedCollection - LastPost string - - TotalPosts int64 + Config config.AppCfg + Message string + OwnUserPage bool + + User *User + Colls []inspectedCollection + LastPost string + NewPassword string + TotalPosts int64 }{ Config: app.cfg.App, Message: r.FormValue("m"), Colls: []inspectedCollection{}, } + flashes, _ := getSessionFlashes(app, w, r, nil) + for _, flash := range flashes { + if strings.HasPrefix(flash, "SUCCESS: ") { + p.NewPassword = strings.TrimPrefix(flash, "SUCCESS: ") + } + } + var err error p.User, err = app.db.GetUserForAuth(username) if err != nil { return impart.HTTPError{http.StatusInternalServerError, fmt.Sprintf("Could not get user: %v", err)} } + p.OwnUserPage = u.ID == p.User.ID p.UserPage = NewUserPage(app, r, u, p.User.Username, nil) p.TotalPosts = app.db.GetUserPostsCount(p.User.ID) lp, err := app.db.GetUserLastPostTime(p.User.ID) @@ -230,6 +241,37 @@ func handleViewAdminUser(app *App, u *User, w http.ResponseWriter, r *http.Reque return nil } +func handleAdminResetUserPass(app *App, u *User, w http.ResponseWriter, r *http.Request) error { + vars := mux.Vars(r) + username := vars["username"] + if username == "" { + return impart.HTTPError{http.StatusFound, "/admin/users"} + } + // Generate new random password since none supplied + pass := passgen.New() + hashedPass, err := auth.HashPass([]byte(pass)) + if err != nil { + return impart.HTTPError{http.StatusInternalServerError, fmt.Sprintf("Could not create password hash: %v", err)} + } + + userIDVal := r.FormValue("user") + log.Info("ADMIN: Changing user %s password", userIDVal) + id, err := strconv.Atoi(userIDVal) + if err != nil { + return impart.HTTPError{http.StatusBadRequest, fmt.Sprintf("Invalid user ID: %v", err)} + } + + err = app.db.ChangePassphrase(int64(id), true, "", hashedPass) + if err != nil { + return impart.HTTPError{http.StatusInternalServerError, fmt.Sprintf("Could not update passphrase: %v", err)} + } + log.Info("ADMIN: Successfully changed.") + + addSessionFlash(app, w, r, fmt.Sprintf("SUCCESS: %s", pass), nil) + + return impart.HTTPError{http.StatusFound, fmt.Sprintf("/admin/user/%s", username)} +} + func handleViewAdminPages(app *App, u *User, w http.ResponseWriter, r *http.Request) error { p := struct { *UserPage diff --git a/routes.go b/routes.go index 0113e93..003b7d1 100644 --- a/routes.go +++ b/routes.go @@ -144,6 +144,7 @@ func InitRoutes(apper Apper, r *mux.Router) *mux.Router { write.HandleFunc("/admin", handler.Admin(handleViewAdminDash)).Methods("GET") write.HandleFunc("/admin/users", handler.Admin(handleViewAdminUsers)).Methods("GET") write.HandleFunc("/admin/user/{username}", handler.Admin(handleViewAdminUser)).Methods("GET") + write.HandleFunc("/admin/user/{username}", handler.Admin(handleAdminResetUserPass)).Methods("POST") write.HandleFunc("/admin/pages", handler.Admin(handleViewAdminPages)).Methods("GET") write.HandleFunc("/admin/page/{slug}", handler.Admin(handleViewAdminPage)).Methods("GET") write.HandleFunc("/admin/update/config", handler.AdminApper(handleAdminUpdateConfig)).Methods("POST") diff --git a/templates/user/admin/view-user.tmpl b/templates/user/admin/view-user.tmpl index 2a74e5b..211297d 100644 --- a/templates/user/admin/view-user.tmpl +++ b/templates/user/admin/view-user.tmpl @@ -7,12 +7,32 @@ table.classy th { h3 { font-weight: normal; } +input.copy-text { + text-align: center; + font-size: 1.2em; + color: #555; + margin-left: 1rem; +} +button[type="submit"].danger { + padding-left: 2rem; + padding-right: 2rem; +}
{{template "admin-header" .}}

{{.User.Username}}

- + {{if .NewPassword}}

New password for user {{.User.Username}} is + +

+ You must share this new password with the user, this is the only time it will be displayed. +

+ {{end}} @@ -38,6 +58,21 @@ h3 { + + + +
No.Last Post {{if .LastPost}}{{.LastPost}}{{else}}Never{{end}}
Password + {{if not .OwnUserPage}} +
+ + +
+ {{else}} + Change your password + {{end}} +

Blogs

@@ -83,5 +118,13 @@ h3 { {{end}}
+ {{template "footer" .}} {{end}} From 6e09fcb9e2a3088c9c5ad1cbbbb5cc5947d2122a Mon Sep 17 00:00:00 2001 From: Matt Baer Date: Mon, 11 Nov 2019 16:02:22 +0900 Subject: [PATCH 2/9] Change password reset endpoint to /admin/user/{Username}/passphrase Ref T695 --- routes.go | 2 +- templates/user/admin/view-user.tmpl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/routes.go b/routes.go index 003b7d1..de19ff2 100644 --- a/routes.go +++ b/routes.go @@ -144,7 +144,7 @@ func InitRoutes(apper Apper, r *mux.Router) *mux.Router { write.HandleFunc("/admin", handler.Admin(handleViewAdminDash)).Methods("GET") write.HandleFunc("/admin/users", handler.Admin(handleViewAdminUsers)).Methods("GET") write.HandleFunc("/admin/user/{username}", handler.Admin(handleViewAdminUser)).Methods("GET") - write.HandleFunc("/admin/user/{username}", handler.Admin(handleAdminResetUserPass)).Methods("POST") + write.HandleFunc("/admin/user/{username}/passphrase", handler.Admin(handleAdminResetUserPass)).Methods("POST") write.HandleFunc("/admin/pages", handler.Admin(handleViewAdminPages)).Methods("GET") write.HandleFunc("/admin/page/{slug}", handler.Admin(handleViewAdminPage)).Methods("GET") write.HandleFunc("/admin/update/config", handler.AdminApper(handleAdminUpdateConfig)).Methods("POST") diff --git a/templates/user/admin/view-user.tmpl b/templates/user/admin/view-user.tmpl index 211297d..91fdaf1 100644 --- a/templates/user/admin/view-user.tmpl +++ b/templates/user/admin/view-user.tmpl @@ -62,7 +62,7 @@ button[type="submit"].danger { Password {{if not .OwnUserPage}} -
+