Let people ask for a new password on the website, and stop capitals breaking it
Two halves of the same report. A family member could not get in, four password resets produced nothing, and the site offered no way to ask for one anyway. **Capitals.** The web sign-in trimmed the address but did not lower-case it, and PocketBase looks accounts up case-sensitively — so `Vojta.Markup@seznam.cz` for an account stored in lowercase matched nothing and read as a wrong password. Phones capitalise the first letter of a text field by themselves, so this is the mistake people will actually make. The same fix went into the app. **The reset itself.** A link under the sign-in button, hidden until asked for: the overwhelmingly common visit is somebody who remembers their password, and a reset field on the way in invites people to reach for it first. The message it shows says what was *done*, never whether the address matched. The endpoint deliberately answers the same either way so that nobody can use it to discover which addresses are registered — and pretending otherwise is exactly what made this so hard to read from outside: four attempts, four "sent", nothing arriving, no way to tell that the lookup had simply found nothing. It also points at the one thing that always works when mail does not, which is asking for it to be set directly. Whether delivery itself works is still unverified: every reset attempt on record failed at the lookup, so the mail path has never once been exercised. A reset has been triggered against a real account to settle that.
This commit is contained in:
parent
5b69b9ec6a
commit
2b458fb9f6
1 changed files with 41 additions and 1 deletions
|
|
@ -118,6 +118,18 @@
|
|||
<input id="pass" type="password" autocomplete="current-password">
|
||||
<button id="loginBtn" class="btn primary">Přihlásit se</button>
|
||||
<div id="anonMsg" class="msg"></div>
|
||||
<p class="hint"><a href="#" id="forgotLink">Zapomenuté heslo?</a></p>
|
||||
|
||||
<!-- Hidden until asked for: the overwhelmingly common visit is somebody
|
||||
who remembers their password, and a reset field on the way in invites
|
||||
people to reach for it first. -->
|
||||
<div id="forgot" hidden>
|
||||
<label for="fEmail">E-mail účtu</label>
|
||||
<input id="fEmail" type="email" autocomplete="username" inputmode="email">
|
||||
<button id="forgotBtn" class="btn">Poslat odkaz na nové heslo</button>
|
||||
<div id="forgotMsg" class="msg"></div>
|
||||
</div>
|
||||
|
||||
<p class="hint">Účty zakládá Richard — registrace tu není. Když se nemůžeš
|
||||
dostat dovnitř, napiš mu.</p>
|
||||
</div>
|
||||
|
|
@ -505,7 +517,11 @@ async function restore(){
|
|||
}
|
||||
|
||||
$("loginBtn").onclick=async function(){
|
||||
var email=$("email").value.trim(), pass=$("pass").value;
|
||||
// Lower-cased, not just trimmed. PocketBase looks accounts up
|
||||
// case-sensitively, so an address typed with a capital — which phones do by
|
||||
// themselves — matches nothing and reads as a wrong password. It cost a
|
||||
// family member two days and four failed password resets.
|
||||
var email=$("email").value.trim().toLowerCase(), pass=$("pass").value;
|
||||
if(!email||!pass){ setMsg($("anonMsg"),"Vyplň e-mail i heslo.","err"); return; }
|
||||
setMsg($("anonMsg"),""); busy($("loginBtn"),true,"Přihlašuji…");
|
||||
var r=await api("POST","/api/collections/users/auth-with-password",
|
||||
|
|
@ -516,6 +532,30 @@ $("loginBtn").onclick=async function(){
|
|||
TOKEN=r.data.token; USER=r.data.record; PASSWORD=pass; saveSession();
|
||||
await enter();
|
||||
};
|
||||
$("forgotLink").onclick=function(e){
|
||||
e.preventDefault();
|
||||
var box=$("forgot");
|
||||
box.hidden=!box.hidden;
|
||||
if(!box.hidden){ $("fEmail").value=$("email").value; $("fEmail").focus(); }
|
||||
};
|
||||
|
||||
$("forgotBtn").onclick=async function(){
|
||||
var email=$("fEmail").value.trim().toLowerCase();
|
||||
if(!email){ setMsg($("forgotMsg"),"Vyplň e-mail.","err"); return; }
|
||||
setMsg($("forgotMsg"),""); busy($("forgotBtn"),true,"Odesílám…");
|
||||
var r=await api("POST","/api/collections/users/request-password-reset",
|
||||
{ email:email }, {anon:true});
|
||||
busy($("forgotBtn"),false);
|
||||
// The server answers the same whether or not the account exists — on purpose,
|
||||
// so nobody can use this to find out which addresses are registered. So the
|
||||
// message says what was DONE, never whether it matched: promising "sent" for
|
||||
// an address with no account is the lie that made the last outage so hard to
|
||||
// read from the outside.
|
||||
if(!r.ok){ setMsg($("forgotMsg"),"Nepovedlo se odeslat. Zkus to za chvíli.","err"); return; }
|
||||
setMsg($("forgotMsg"),"Pokud k té adrese účet existuje, přišel na ni odkaz. "+
|
||||
"Mrkni i do spamu. Když nic nedorazí, napiš Richardovi — heslo ti nastaví přímo.","ok");
|
||||
};
|
||||
|
||||
$("logoutBtn").onclick=signOut;
|
||||
|
||||
// ── shell ────────────────────────────────────────────────────────────────────
|
||||
|
|
|
|||
Loading…
Reference in a new issue