✨ Added page to change own password
This commit is contained in:
parent
652e3086d5
commit
f5869bfc3b
|
@ -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 }}
|
||||
|
|
|
@ -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 }}
|
101
webadmin.go
101
webadmin.go
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue