The reset email works — confirmed by a delivered message, after every attempt on record had failed at the lookup and the mail path had never once been exercised. What the delivered message showed was a different problem: it was in English, and its button pointed at `pb.petruzalekr.cz/_/#/auth/confirm-password-reset/…`, which is PocketBase's admin console. Every other surface of this app is Czech on purpose, because the people using it are the owner's parents and his children — and the one moment they are most likely to be stuck is the one moment it started speaking English and sent them to what reads like a developer tool. Found by looking at a delivered email rather than at the settings. The templates were simply PocketBase's defaults, and a default is invisible until somebody receives one. The reset link now lands on amber.petruzalekr.cz, which hosts the form: two fields, in Czech, on the domain people already know. A reset link wins over a stored session, because somebody arriving with one is trying to fix their account and dropping them into a signed-in page hides the thing they came to do. The token is stripped from the address bar once spent — a URL carrying a credential is one that ends up in a bookmark or a screenshot. A failed confirm names the likely cause. These links expire, and "something went wrong" gives somebody who opened yesterday's email no way to know that. Verification and email-change keep PocketBase's own confirm pages: nobody has used those, they are not part of the report, and pointing them at a page that does not exist would be worse than English. As a migration rather than a click in the admin UI, so restoring the backend from migrations does not quietly put English back.
83 lines
3.4 KiB
JavaScript
83 lines
3.4 KiB
JavaScript
/// <reference path="../pb_data/types.d.ts" />
|
|
|
|
// The account emails were in English, and pointed at PocketBase's admin console.
|
|
//
|
|
// **Why it matters here.** Every other surface of this app is Czech, on purpose:
|
|
// the people using it are the owner's parents and his children. The one moment
|
|
// they are most likely to be stuck — locked out, asking for a new password — was
|
|
// the one moment the product started speaking English and sent them to
|
|
// `pb.petruzalekr.cz/_/#/auth/confirm-password-reset/…`, which is the admin UI's
|
|
// own page and reads to anybody's parent like a developer tool opened by
|
|
// mistake.
|
|
//
|
|
// Found by looking at a delivered message rather than at the settings: the
|
|
// templates were simply PocketBase's defaults, and defaults are invisible until
|
|
// somebody receives one.
|
|
//
|
|
// The links now point at amber.petruzalekr.cz, which hosts the confirm form in
|
|
// Czech (see pb_public/index.html, `?reset=`). Verification and email-change
|
|
// keep PocketBase's own confirm pages: nobody has hit those yet, they are not
|
|
// part of the reported problem, and pointing them somewhere that does not exist
|
|
// would be worse than English.
|
|
const RESET_SUBJECT = "Nové heslo k Amberu";
|
|
const RESET_BODY = `<p>Ahoj,</p>
|
|
<p>Někdo (snad ty) požádal o nové heslo k Amberu. Nastavíš si ho tímhle odkazem:</p>
|
|
<p>
|
|
<a class="btn" href="https://amber.petruzalekr.cz/?reset={TOKEN}" target="_blank" rel="noopener">Nastavit nové heslo</a>
|
|
</p>
|
|
<p><i>Pokud jsi o nic nežádal, tenhle e-mail klidně smaž. Nic se nestalo a heslo
|
|
zůstává, jaké bylo.</i></p>
|
|
<p>Amber</p>`;
|
|
|
|
const VERIFY_SUBJECT = "Ověření e-mailu pro Amber";
|
|
const VERIFY_BODY = `<p>Ahoj,</p>
|
|
<p>Potvrď prosím tímhle odkazem, že tenhle e-mail patří tobě:</p>
|
|
<p>
|
|
<a class="btn" href="{APP_URL}/_/#/auth/confirm-verification/{TOKEN}" target="_blank" rel="noopener">Potvrdit e-mail</a>
|
|
</p>
|
|
<p>Amber</p>`;
|
|
|
|
const CHANGE_SUBJECT = "Změna e-mailu u Amberu";
|
|
const CHANGE_BODY = `<p>Ahoj,</p>
|
|
<p>Potvrď prosím změnu e-mailu u svého účtu:</p>
|
|
<p>
|
|
<a class="btn" href="{APP_URL}/_/#/auth/confirm-email-change/{TOKEN}" target="_blank" rel="noopener">Potvrdit změnu</a>
|
|
</p>
|
|
<p><i>Pokud jsi o změnu nežádal, ozvi se Richardovi — někdo se ti hrabe v účtu.</i></p>
|
|
<p>Amber</p>`;
|
|
|
|
// The defaults, so the down migration restores exactly what was there.
|
|
const EN = {
|
|
reset: {
|
|
subject: "Reset your {APP_NAME} password",
|
|
body: `<p>Hello,</p>
|
|
<p>Click on the button below to reset your password.</p>
|
|
<p>
|
|
<a class="btn" href="{APP_URL}/_/#/auth/confirm-password-reset/{TOKEN}" target="_blank" rel="noopener">Reset password</a>
|
|
</p>
|
|
<p><i>If you didn't ask to reset your password, please ignore this email.</i></p>
|
|
<p>
|
|
Thanks,<br/>
|
|
{APP_NAME} team
|
|
</p>`,
|
|
},
|
|
};
|
|
|
|
migrate(
|
|
(app) => {
|
|
const users = app.findCollectionByNameOrId("users");
|
|
users.resetPasswordTemplate.subject = RESET_SUBJECT;
|
|
users.resetPasswordTemplate.body = RESET_BODY;
|
|
users.verificationTemplate.subject = VERIFY_SUBJECT;
|
|
users.verificationTemplate.body = VERIFY_BODY;
|
|
users.confirmEmailChangeTemplate.subject = CHANGE_SUBJECT;
|
|
users.confirmEmailChangeTemplate.body = CHANGE_BODY;
|
|
app.save(users);
|
|
},
|
|
(app) => {
|
|
const users = app.findCollectionByNameOrId("users");
|
|
users.resetPasswordTemplate.subject = EN.reset.subject;
|
|
users.resetPasswordTemplate.body = EN.reset.body;
|
|
app.save(users);
|
|
},
|
|
);
|