Added page to change own password

This commit is contained in:
Andreas Schneider 2020-11-01 12:10:20 +01:00
parent 652e3086d5
commit f5869bfc3b
3 changed files with 109 additions and 26 deletions

View File

@ -77,7 +77,6 @@
.dialog label {
display: flex;
margin-bottom: 1em;
align-items: center;
}
@ -112,6 +111,7 @@
{{ end }}
<hr/>
<span><a href="my-shares">My Shares</a></span>
<span><a href="change-password">Change Password</a></span>
<hr/>
<span><a href="logout">Logout</a></span>
{{ end }}

View File

@ -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 }}

View File

@ -36,25 +36,27 @@ import (
"time"
"github.com/go-chi/chi"
passwordvalidator "github.com/lane-c-wagner/go-password-validator"
uuid "github.com/satori/go.uuid"
"github.com/tidwall/buntdb"
"golang.org/x/crypto/bcrypt"
)
type webAdminHandler struct {
router chi.Router
shareStore ShareStore
tplError *template.Template
tplConfirm *template.Template
tplLogin *template.Template
tplIndex *template.Template
tplUsers *template.Template
tplShares *template.Template
tplMyShares *template.Template
tplShareAddUser *template.Template
tplShareAddLogin *template.Template
tplCreateShare *template.Template
tplCreateUser *template.Template
router chi.Router
shareStore ShareStore
tplError *template.Template
tplConfirm *template.Template
tplLogin *template.Template
tplIndex *template.Template
tplUsers *template.Template
tplShares *template.Template
tplMyShares *template.Template
tplShareAddUser *template.Template
tplShareAddLogin *template.Template
tplCreateShare *template.Template
tplCreateUser *template.Template
tplChangePassword *template.Template
}
type sessionContext struct {
@ -72,6 +74,8 @@ const confirmRequested = 0
const confirmAccepted = 1
const confirmDenied = 2
const minPasswordEntropy = 60
func newWebAdminHandler(app *app) *webAdminHandler {
sessionStore, err := buntdb.Open(":memory:")
if err != nil {
@ -97,18 +101,19 @@ func newWebAdminHandler(app *app) *webAdminHandler {
}
h := &webAdminHandler{
shareStore: app.shareStore,
tplError: loadTemplate("error"),
tplConfirm: loadTemplate("confirm"),
tplLogin: loadSingleTemplate("login"),
tplIndex: loadTemplate("index"),
tplUsers: loadTemplate("users"),
tplShares: loadTemplate("shares"),
tplMyShares: loadTemplate("my-shares"),
tplShareAddUser: loadTemplate("share-add-user"),
tplShareAddLogin: loadTemplate("share-add-login"),
tplCreateShare: loadTemplate("create-share"),
tplCreateUser: loadTemplate("create-user"),
shareStore: app.shareStore,
tplError: loadTemplate("error"),
tplConfirm: loadTemplate("confirm"),
tplLogin: loadSingleTemplate("login"),
tplIndex: loadTemplate("index"),
tplUsers: loadTemplate("users"),
tplShares: loadTemplate("shares"),
tplMyShares: loadTemplate("my-shares"),
tplShareAddUser: loadTemplate("share-add-user"),
tplShareAddLogin: loadTemplate("share-add-login"),
tplCreateShare: loadTemplate("create-share"),
tplCreateUser: loadTemplate("create-user"),
tplChangePassword: loadTemplate("change-password"),
}
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) {
sessionContext := h.buildSessionContext(w, r)
// TODO invalidate sessions
if sessionContext.user.Role != GlobalRoleAdmin {
sessionContext.Unauthorized()
return
@ -600,6 +607,50 @@ Are you sure you want to continue?`, user.Username, user.Role)
}
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
return h