✨ Added page to change own password
This commit is contained in:
parent
652e3086d5
commit
f5869bfc3b
|
@ -77,7 +77,6 @@
|
||||||
|
|
||||||
.dialog label {
|
.dialog label {
|
||||||
display: flex;
|
display: flex;
|
||||||
margin-bottom: 1em;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,6 +111,7 @@
|
||||||
{{ end }}
|
{{ end }}
|
||||||
<hr/>
|
<hr/>
|
||||||
<span><a href="my-shares">My Shares</a></span>
|
<span><a href="my-shares">My Shares</a></span>
|
||||||
|
<span><a href="change-password">Change Password</a></span>
|
||||||
<hr/>
|
<hr/>
|
||||||
<span><a href="logout">Logout</a></span>
|
<span><a href="logout">Logout</a></span>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
{{ define "page-styles"}}
|
||||||
|
<style>
|
||||||
|
.form-content {
|
||||||
|
display: grid;
|
||||||
|
grid-gap: .5em;
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-content input {
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ define "page-content" }}
|
||||||
|
<form method="post" class="dialog">
|
||||||
|
<div class="form-content">
|
||||||
|
<label for="password">Current Password</label>
|
||||||
|
<input type="password" name="password" id="password" placeholder="Password" size="32"/>
|
||||||
|
|
||||||
|
<label for="password-new">New Password</label>
|
||||||
|
<input type="password" name="password-new" id="password-new" placeholder="New Password" size="32"/>
|
||||||
|
|
||||||
|
<label for="password-repeat">Repeat Password</label>
|
||||||
|
<input type="password" name="password-repeat" id="password-repeat" placeholder="Repeat New Password" size="32"/>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="form-controls">
|
||||||
|
<input type="submit" value="Change Password"/>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
{{ end }}
|
51
webadmin.go
51
webadmin.go
|
@ -36,6 +36,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-chi/chi"
|
"github.com/go-chi/chi"
|
||||||
|
passwordvalidator "github.com/lane-c-wagner/go-password-validator"
|
||||||
uuid "github.com/satori/go.uuid"
|
uuid "github.com/satori/go.uuid"
|
||||||
"github.com/tidwall/buntdb"
|
"github.com/tidwall/buntdb"
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
|
@ -55,6 +56,7 @@ type webAdminHandler struct {
|
||||||
tplShareAddLogin *template.Template
|
tplShareAddLogin *template.Template
|
||||||
tplCreateShare *template.Template
|
tplCreateShare *template.Template
|
||||||
tplCreateUser *template.Template
|
tplCreateUser *template.Template
|
||||||
|
tplChangePassword *template.Template
|
||||||
}
|
}
|
||||||
|
|
||||||
type sessionContext struct {
|
type sessionContext struct {
|
||||||
|
@ -72,6 +74,8 @@ const confirmRequested = 0
|
||||||
const confirmAccepted = 1
|
const confirmAccepted = 1
|
||||||
const confirmDenied = 2
|
const confirmDenied = 2
|
||||||
|
|
||||||
|
const minPasswordEntropy = 60
|
||||||
|
|
||||||
func newWebAdminHandler(app *app) *webAdminHandler {
|
func newWebAdminHandler(app *app) *webAdminHandler {
|
||||||
sessionStore, err := buntdb.Open(":memory:")
|
sessionStore, err := buntdb.Open(":memory:")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -109,6 +113,7 @@ func newWebAdminHandler(app *app) *webAdminHandler {
|
||||||
tplShareAddLogin: loadTemplate("share-add-login"),
|
tplShareAddLogin: loadTemplate("share-add-login"),
|
||||||
tplCreateShare: loadTemplate("create-share"),
|
tplCreateShare: loadTemplate("create-share"),
|
||||||
tplCreateUser: loadTemplate("create-user"),
|
tplCreateUser: loadTemplate("create-user"),
|
||||||
|
tplChangePassword: loadTemplate("change-password"),
|
||||||
}
|
}
|
||||||
|
|
||||||
r := chi.NewRouter()
|
r := chi.NewRouter()
|
||||||
|
@ -574,6 +579,8 @@ Are you sure you want to continue?`, share.UUID, share.Name)
|
||||||
ar.Post("/delete-user", func(w http.ResponseWriter, r *http.Request) {
|
ar.Post("/delete-user", func(w http.ResponseWriter, r *http.Request) {
|
||||||
sessionContext := h.buildSessionContext(w, r)
|
sessionContext := h.buildSessionContext(w, r)
|
||||||
|
|
||||||
|
// TODO invalidate sessions
|
||||||
|
|
||||||
if sessionContext.user.Role != GlobalRoleAdmin {
|
if sessionContext.user.Role != GlobalRoleAdmin {
|
||||||
sessionContext.Unauthorized()
|
sessionContext.Unauthorized()
|
||||||
return
|
return
|
||||||
|
@ -600,6 +607,50 @@ Are you sure you want to continue?`, user.Username, user.Role)
|
||||||
}
|
}
|
||||||
sessionContext.Redirect("users")
|
sessionContext.Redirect("users")
|
||||||
})
|
})
|
||||||
|
ar.Route("/change-password", func(r chi.Router) {
|
||||||
|
r.Get("/", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
sessionContext := h.buildSessionContext(w, r)
|
||||||
|
sessionContext.RenderPage(h.tplChangePassword, nil)
|
||||||
|
})
|
||||||
|
r.Post("/", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
sessionContext := h.buildSessionContext(w, r)
|
||||||
|
|
||||||
|
currentPassword := r.FormValue("password")
|
||||||
|
newPassword := r.FormValue("password-new")
|
||||||
|
repeatPassword := r.FormValue("password-repeat")
|
||||||
|
|
||||||
|
if err := bcrypt.CompareHashAndPassword([]byte(sessionContext.user.Password), []byte(currentPassword)); err != nil {
|
||||||
|
sessionContext.RenderError(template.HTML("The current password is wrong. Please check."), "")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if newPassword != repeatPassword {
|
||||||
|
sessionContext.RenderError(template.HTML("The new password doesn't match the repeated password."), "")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := passwordvalidator.Validate(newPassword, minPasswordEntropy); err != nil {
|
||||||
|
sessionContext.RenderError(template.HTML("The new password is not strong enough."), "")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
pwHash, err := bcrypt.GenerateFromPassword([]byte(newPassword), bcrypt.DefaultCost)
|
||||||
|
if err != nil {
|
||||||
|
sessionContext.RenderError(template.HTML("Internal error: "+err.Error()), "")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := app.userStore.UpdateUser(User{
|
||||||
|
Username: sessionContext.user.Username,
|
||||||
|
Password: string(pwHash),
|
||||||
|
}); err != nil {
|
||||||
|
sessionContext.RenderError(template.HTML("Internal error: "+err.Error()), "")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
sessionContext.Redirect("./")
|
||||||
|
})
|
||||||
|
})
|
||||||
h.router = r
|
h.router = r
|
||||||
|
|
||||||
return h
|
return h
|
||||||
|
|
Loading…
Reference in New Issue