From 3ec3e9672e5169875640ea9ae83457843e3c9011 Mon Sep 17 00:00:00 2001 From: Harvey Tindall Date: Thu, 22 Jun 2023 12:25:00 +0100 Subject: [PATCH] userpage: time-pad pwr request for ambiguity the user shouldn't know if the reset has actually been sent (i.e. if an account with the given contact address exists), so the backend response is always sent after 1 second. --- api-userpage.go | 27 +++++++++++++++++++++++---- ts/user.ts | 28 ++++++++++++++++------------ 2 files changed, 39 insertions(+), 16 deletions(-) diff --git a/api-userpage.go b/api-userpage.go index 189b8aa..3097b5e 100644 --- a/api-userpage.go +++ b/api-userpage.go @@ -487,9 +487,15 @@ func (app *appContext) UnlinkMyMatrix(gc *gin.Context) { // @Router /my/password/reset/{address} [post] // @tags Users func (app *appContext) ResetMyPassword(gc *gin.Context) { + // All requests should take 1 second, to make it harder to tell if a success occured or not. + timerWait := make(chan bool) + cancel := time.AfterFunc(1*time.Second, func() { + timerWait <- true + }) address := gc.Param("address") if address == "" { app.debug.Println("Ignoring empty request for PWR") + cancel.Stop() respondBool(400, false, gc) return } @@ -499,13 +505,20 @@ func (app *appContext) ResetMyPassword(gc *gin.Context) { jfID := app.reverseUserSearch(address) if jfID == "" { app.debug.Printf("Ignoring PWR request: User not found") - respondBool(204, true, gc) + + for range timerWait { + respondBool(204, true, gc) + return + } return } pwr, err = app.GenInternalReset(jfID) if err != nil { app.err.Printf("Failed to get user from Jellyfin: %v", err) - respondBool(500, false, gc) + for range timerWait { + respondBool(204, true, gc) + return + } return } if app.internalPWRs == nil { @@ -523,12 +536,18 @@ func (app *appContext) ResetMyPassword(gc *gin.Context) { ) if err != nil { app.err.Printf("Failed to construct password reset message for \"%s\": %v", pwr.Username, err) - respondBool(500, false, gc) + for range timerWait { + respondBool(204, true, gc) + return + } return } else if err := app.sendByID(msg, jfID); err != nil { app.err.Printf("Failed to send password reset message to \"%s\": %v", address, err) } else { app.info.Printf("Sent password reset message to \"%s\"", address) } - respondBool(204, true, gc) + for range timerWait { + respondBool(204, true, gc) + return + } } diff --git a/ts/user.ts b/ts/user.ts index 03e8f28..ac49b7e 100644 --- a/ts/user.ts +++ b/ts/user.ts @@ -63,18 +63,22 @@ window.notifications = new notificationBox(document.getElementById('notification if (window.pwrEnabled && window.linkResetEnabled) { const submitButton = document.getElementById("pwr-submit"); const input = document.getElementById("pwr-address") as HTMLInputElement; - submitButton.onclick = () => _post("/my/password/reset/" + input.value, null, (req: XMLHttpRequest) => { - if (req.readyState != 4) return; - if (req.status != 204) { - window.notifications.customError("unkownError", window.lang.notif("errorUnknown"));; - window.modals.pwr.close(); - return; - } - window.modals.pwr.modal.querySelector(".heading").textContent = window.lang.strings("resetSent"); - window.modals.pwr.modal.querySelector(".content").textContent = window.lang.strings("resetSentDescription"); - submitButton.classList.add("unfocused"); - input.classList.add("unfocused"); - }); + submitButton.onclick = () => { + toggleLoader(submitButton); + _post("/my/password/reset/" + input.value, null, (req: XMLHttpRequest) => { + if (req.readyState != 4) return; + toggleLoader(submitButton); + if (req.status != 204) { + window.notifications.customError("unkownError", window.lang.notif("errorUnknown"));; + window.modals.pwr.close(); + return; + } + window.modals.pwr.modal.querySelector(".heading").textContent = window.lang.strings("resetSent"); + window.modals.pwr.modal.querySelector(".content").textContent = window.lang.strings("resetSentDescription"); + submitButton.classList.add("unfocused"); + input.classList.add("unfocused"); + }); + }; } const grid = document.querySelector(".grid");