mirror of
https://github.com/writefreely/writefreely
synced 2024-11-24 09:33:11 +00:00
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
This commit is contained in:
parent
3759f16ed3
commit
aa9efc7b37
3 changed files with 94 additions and 8 deletions
56
admin.go
56
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
|
||||
Config config.AppCfg
|
||||
Message string
|
||||
OwnUserPage bool
|
||||
|
||||
User *User
|
||||
Colls []inspectedCollection
|
||||
LastPost string
|
||||
|
||||
TotalPosts int64
|
||||
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
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
</style>
|
||||
<div class="snug content-container">
|
||||
{{template "admin-header" .}}
|
||||
|
||||
<h2 id="posts-header">{{.User.Username}}</h2>
|
||||
|
||||
{{if .NewPassword}}<p class="alert success">New password for user <strong>{{.User.Username}}</strong> is
|
||||
<input
|
||||
type="text"
|
||||
class="copy-text"
|
||||
value="{{.NewPassword}}"
|
||||
onfocus="if (this.select) this.select(); else this.setSelectionRange(0, this.value.length);"
|
||||
readonly />
|
||||
<br/><br/>
|
||||
You must share this new password with the user, this is the only time it will be displayed.
|
||||
</p>
|
||||
{{end}}
|
||||
<table class="classy export">
|
||||
<tr>
|
||||
<th>No.</th>
|
||||
|
@ -38,6 +58,21 @@ h3 {
|
|||
<th>Last Post</th>
|
||||
<td>{{if .LastPost}}{{.LastPost}}{{else}}Never{{end}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Password</th>
|
||||
<td>
|
||||
{{if not .OwnUserPage}}
|
||||
<form id="reset-form" action="/admin/user/{{.User.Username}}" method="post" autocomplete="false">
|
||||
<input type="hidden" name="user" value="{{.User.ID}}"/>
|
||||
<button
|
||||
class="danger"
|
||||
type="submit">Reset</button>
|
||||
</form>
|
||||
{{else}}
|
||||
<a href="/me/settings" title="Go to reset password page">Change your password</a>
|
||||
{{end}}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h2>Blogs</h2>
|
||||
|
@ -83,5 +118,13 @@ h3 {
|
|||
{{end}}
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
form = document.getElementById("reset-form");
|
||||
form.addEventListener('submit', function(e) {
|
||||
e.preventDefault();
|
||||
agreed = confirm("Really reset password for {{.User.Username}}?\nYou will have to record and share the new password with them.");
|
||||
if (agreed === true) { form.submit();}
|
||||
});
|
||||
</script>
|
||||
{{template "footer" .}}
|
||||
{{end}}
|
||||
|
|
Loading…
Reference in a new issue