mirror of
https://github.com/osmarks/mycorrhiza.git
synced 2024-10-29 19:26:16 +00:00
implement user facing password change page
similar to the admin password change, but with a few changes: - require current password verification the following still included: - empty password check - confirm password check
This commit is contained in:
parent
4629f39e99
commit
5f592acc55
62
settings/settings.go
Normal file
62
settings/settings.go
Normal file
@ -0,0 +1,62 @@
|
||||
package settings
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"mime"
|
||||
"net/http"
|
||||
"reflect"
|
||||
|
||||
"github.com/bouncepaw/mycorrhiza/viewutil"
|
||||
|
||||
"github.com/bouncepaw/mycorrhiza/user"
|
||||
"github.com/bouncepaw/mycorrhiza/util"
|
||||
)
|
||||
|
||||
func handlerUserChangePassword(w http.ResponseWriter, rq *http.Request) {
|
||||
u := user.FromRequest(rq)
|
||||
// TODO: is there a better way?
|
||||
if reflect.DeepEqual(u, user.EmptyUser()) || u == nil {
|
||||
util.HTTP404Page(w, "404 page not found")
|
||||
return
|
||||
}
|
||||
|
||||
f := util.FormDataFromRequest(rq, []string{"current_password", "password", "password_confirm"})
|
||||
currentPassword := f.Get("current_password")
|
||||
|
||||
if user.CredentialsOK(u.Name, currentPassword) {
|
||||
password := f.Get("password")
|
||||
passwordConfirm := f.Get("password_confirm")
|
||||
// server side validation
|
||||
if password == "" {
|
||||
err := fmt.Errorf("passwords should not be empty")
|
||||
f = f.WithError(err)
|
||||
}
|
||||
if password == passwordConfirm {
|
||||
previousPassword := u.Password // for rollback
|
||||
if err := u.ChangePassword(password); err != nil {
|
||||
f = f.WithError(err)
|
||||
} else {
|
||||
if err := user.SaveUserDatabase(); err != nil {
|
||||
u.Password = previousPassword
|
||||
f = f.WithError(err)
|
||||
} else {
|
||||
http.Redirect(w, rq, "/", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
}
|
||||
} else {
|
||||
err := fmt.Errorf("passwords do not match")
|
||||
f = f.WithError(err)
|
||||
}
|
||||
} else {
|
||||
err := fmt.Errorf("incorrect password")
|
||||
f = f.WithError(err)
|
||||
}
|
||||
|
||||
if f.HasError() {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
}
|
||||
w.Header().Set("Content-Type", mime.TypeByExtension(".html"))
|
||||
|
||||
changePasswordPage(viewutil.MetaFrom(w, rq), f, u)
|
||||
}
|
47
settings/view.go
Normal file
47
settings/view.go
Normal file
@ -0,0 +1,47 @@
|
||||
package settings
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"github.com/bouncepaw/mycorrhiza/util"
|
||||
"github.com/bouncepaw/mycorrhiza/viewutil"
|
||||
"github.com/gorilla/mux"
|
||||
"net/http"
|
||||
|
||||
"github.com/bouncepaw/mycorrhiza/user"
|
||||
)
|
||||
|
||||
// TODO: translate untranslated strings
|
||||
const settingsTranslationRu = `
|
||||
{{define "change password"}}Change password{{end}}
|
||||
{{define "confirm password"}}Confirm password{{end}}
|
||||
{{define "current password"}}Current password{{end}}
|
||||
{{define "non local password change"}}Non-local accounts cannot have their passwords changed.{{end}}
|
||||
{{define "password"}}Password{{end}}
|
||||
{{define "submit"}}Submit{{end}}
|
||||
`
|
||||
|
||||
var (
|
||||
//go:embed *.html
|
||||
fs embed.FS
|
||||
changePassowrdChain viewutil.Chain
|
||||
)
|
||||
|
||||
func Init(rtr *mux.Router) {
|
||||
rtr.HandleFunc("/change-password", handlerUserChangePassword).Methods(http.MethodGet, http.MethodPost)
|
||||
|
||||
changePassowrdChain = viewutil.CopyEnRuWith(fs, "view_change_password.html", settingsTranslationRu)
|
||||
}
|
||||
|
||||
func changePasswordPage(meta viewutil.Meta, form util.FormData, u *user.User) {
|
||||
viewutil.ExecutePage(meta, changePassowrdChain, changePasswordData{
|
||||
BaseData: &viewutil.BaseData{},
|
||||
Form: form,
|
||||
U: u,
|
||||
})
|
||||
}
|
||||
|
||||
type changePasswordData struct {
|
||||
*viewutil.BaseData
|
||||
Form util.FormData
|
||||
U *user.User
|
||||
}
|
37
settings/view_change_password.html
Normal file
37
settings/view_change_password.html
Normal file
@ -0,0 +1,37 @@
|
||||
{{/* TODO: translate title? */}}
|
||||
{{define "title"}}Change password{{end}}
|
||||
{{define "body"}}
|
||||
<main class="main-width form-wrap">
|
||||
{{if .Form.HasError}}
|
||||
<div class="notice notice--error">
|
||||
<strong>{{template "error"}}:</strong>
|
||||
{{.Form.Error}}
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
<h2>{{block "change password" .}}Change password{{end}}</h2>
|
||||
|
||||
{{if eq .U.Source "local"}}
|
||||
<form action="/settings/change-password" method="post">
|
||||
<div class="form-field">
|
||||
<label for="current_pass">{{block "current password" .}}Current password{{end}}</label>
|
||||
<input required type="password" autocomplete="current-password" id="current_pass" name="current_password">
|
||||
<br>
|
||||
<br>
|
||||
<label for="pass">{{block "password" .}}Password{{end}}</label>
|
||||
<input required type="password" autocomplete="new-password" id="pass" name="password">
|
||||
<br>
|
||||
<br>
|
||||
<label for="pass_confirm">{{block "confirm password" .}}Confirm password{{end}}</label>
|
||||
<input required type="password" autocomplete="new-password" id="pass_confirm" name="password_confirm">
|
||||
</div>
|
||||
|
||||
<div class="form-field">
|
||||
<input class="btn" type="submit" value='{{block "submit" .}}Submit{{end}}'>
|
||||
</div>
|
||||
</form>
|
||||
{{else}}
|
||||
<p>{{block "non local password change" .}}Non-local accounts cannot have their passwords changed.{{end}}</p>
|
||||
{{end}}
|
||||
</main>
|
||||
{{end}}
|
@ -7,6 +7,7 @@ import (
|
||||
"net/url"
|
||||
|
||||
"github.com/bouncepaw/mycorrhiza/admin"
|
||||
"github.com/bouncepaw/mycorrhiza/settings"
|
||||
"github.com/bouncepaw/mycorrhiza/auth"
|
||||
"github.com/bouncepaw/mycorrhiza/backlinks"
|
||||
"github.com/bouncepaw/mycorrhiza/categories"
|
||||
@ -67,6 +68,11 @@ func Handler() http.Handler {
|
||||
adminRouter := wikiRouter.PathPrefix("/admin").Subrouter()
|
||||
adminRouter.Use(groupMiddleware("admin"))
|
||||
admin.Init(adminRouter)
|
||||
|
||||
settingsRouter := wikiRouter.PathPrefix("/settings").Subrouter()
|
||||
// TODO: check if necessary?
|
||||
//settingsRouter.Use(groupMiddleware("settings"))
|
||||
settings.Init(settingsRouter)
|
||||
}
|
||||
|
||||
// Index page
|
||||
|
Loading…
Reference in New Issue
Block a user