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") } }