authentricity/internal/webui/act_chpw.go

72 lines
1.7 KiB
Go

package webui
import (
"net/http"
"github.com/GehirnInc/crypt/sha512_crypt"
"go.e43.eu/authentricity/internal/models"
"go.e43.eu/authentricity/internal/store"
"go.uber.org/zap"
)
func (s *Service) actionChangePassword(
w http.ResponseWriter,
r *http.Request,
ent models.Entity,
md store.EntryMetadata,
) {
user, ok := ent.(*models.UserRecord)
if !ok {
s.renderBadRequest(w, r)
return
}
if !s.canEditEntity(r.Context(), user.UUID) {
s.renderForbidden(w, r)
return
}
tok := getUserToken(r.Context())
isYou := user.UUID.String() == tok.Subject()
priv := user.EnsurePrivileged()
oldPW := r.PostForm.Get("old_password")
newPW := r.PostForm.Get("new_password")
confirmPW := r.PostForm.Get("confirm_password")
switch {
case newPW == "":
w.WriteHeader(http.StatusBadRequest)
s.renderEntity(w, r, ent, "New password must not be blank")
return
case newPW != confirmPW:
w.WriteHeader(http.StatusBadRequest)
s.renderEntity(w, r, ent, "Passwords do not match")
return
// Admins skip old password check, except for when changing their own password
case isYou && !priv.CheckPassword(oldPW):
w.WriteHeader(http.StatusBadRequest)
s.renderEntity(w, r, ent, "Old password incorrect")
return
}
// TODO: This should probably be customizable!
c := sha512_crypt.New()
hash, err := c.Generate([]byte(newPW), nil)
if err != nil {
zap.L().Error("Error computing password hash", zap.Error(err))
s.renderError(w)
return
}
priv.HashedPassword = []string{hash}
if err := s.store.UpdateEntitySimple(r.Context(), user, md); err != nil {
zap.L().Error("Error updating user", zap.Error(err))
s.renderError(w)
} else {
s.renderEntity(w, r, ent, "Password changed")
}
}