feat(auth): one mail, one click — the approval mail carries the confirmation link (E9.5 S6)
The funnel's common ordering made a person open TWO messages: one saying their access was approved, another asking them to confirm their address. The approval mail now branches on what they actually still have to do — carry the confirmation link, point at sign-in, or say a confirmation mail follows once they register — so the usual case is one mail and one click. A mail that guesses wrong is worse than a plain one: telling someone to sign in while their address is unconfirmed contradicts the screen that will refuse them. That embedded link lives 7 days rather than the usual 24 hours. Nobody sits waiting for an approval — it can easily be read on Monday after a weekend, and an expired link spends the one-mail promise and puts them back on two. The risk is small: the token only ever confirms an address; it signs nobody in and sets no password. The most likely root cause of the 2026-09-03 report that a confirmation mail "never arrived" is here too, and it was never a delivery failure: re-registering an address that already had an unconfirmed account returned in SILENCE — same cheerful "check your inbox", no mail sent at all. It now re-sends the link. Nothing new leaks: the response and its timing are unchanged, and the public verify/resend already does exactly this for the same input. Whitelisting stays silent, and that is a decision, not an omission. The operator opens a door as a possibility — usually already agreed with the person — and a row can sit approved for weeks with nobody registering; a mail fired automatically there would be nudging someone who never asked. Telling them is its own act on its own button, `invited_at` records it so a second click is a decision rather than an accident, and the button only appears where nobody is behind the address yet: "the door is open, come in" is meaningless to someone already inside. Two things UAT caught that no test would have. Every fresh registration appeared in BOTH admin lists at once, because the stuck-sign-ups filter keyed on "unconfirmed" — the rule is now "the address may sign in, and this account still can't", which leaves an undecided request with the queue that owns it. And the invitation button was offered on every approved row, half of which are existing users. Also: the confirmation mail finally says what its link's rules are (once, 24 hours) — the reset mail always has, while this one left the reader to discover both by meeting a dead link. The card's "didn't get the email?" moves up under the form, and the three waiting messages name the spam folder, which is where a first message to a fresh recipient sometimes lands. Registration now records the language the sign-up page was in. Nothing reads it yet — the bilingual templates are S7 — but it is the only moment that choice exists anywhere the server can see, and a preference nobody recorded cannot be backfilled later. UAT on localdev: re-registering re-sent the link (one token became two, one account); approval issued a 7-day token and moved the account into the stuck list with only a re-send; whitelisting mailed nobody; the invitation recorded itself and the row then warned that sending again would write twice. Test data removed.
This commit is contained in:
@@ -22,5 +22,6 @@
|
||||
"audit_clear": "Audit log cleared",
|
||||
"download_credential_set": "Download cookies set",
|
||||
"download_credential_delete": "Download cookies removed",
|
||||
"invite_delete": "Whitelist entry deleted"
|
||||
"invite_delete": "Whitelist entry deleted",
|
||||
"invite_send": "Invitation sent"
|
||||
}
|
||||
|
||||
@@ -157,6 +157,12 @@
|
||||
"approveFailed": "Approve failed",
|
||||
"denyFailed": "Deny failed",
|
||||
"addedToWhitelist": "{{email}} added to the whitelist",
|
||||
"inviteHint": "Send them an invitation. Adding an address never mails anyone — this does.",
|
||||
"invitedAt": "Invited {{time}}. Sending again will mail them a second time.",
|
||||
"inviteLabel": "Send an invitation to {{email}}",
|
||||
"invited": "Invitation sent to {{email}}.",
|
||||
"inviteFailed": "Couldn't send that invitation.",
|
||||
"inviteEmailOff": "No mail was sent: this instance has no working SMTP setup. Check Configuration → Email.",
|
||||
"addFailed": "Couldn't add that email",
|
||||
"requested": "requested {{time}}",
|
||||
"approveHint": "Approve — whitelist this email and email them they're in.",
|
||||
|
||||
@@ -82,8 +82,8 @@
|
||||
"demoEmail": "Demo email",
|
||||
"demoEnter": "Enter",
|
||||
"demoDenied": "That email isn't enabled for the demo. Ask the admin to add it.",
|
||||
"registerDone": "Almost there — check your email for a verification link. After you confirm it, an admin approves your account before you can sign in.",
|
||||
"forgotDone": "If that email has an account, we've sent a reset link. Check your inbox.",
|
||||
"registerDone": "Almost there — check your email for a confirmation link, and your spam folder if it isn't there in a minute. After you confirm it, an admin approves your account before you can sign in.",
|
||||
"forgotDone": "If that email has an account, we've sent a reset link. Check your inbox, and your spam folder if it hasn't arrived in a minute.",
|
||||
"resetDone": "Your password has been set — you can sign in now.",
|
||||
"deadLink": {
|
||||
"title": "This link is no longer valid",
|
||||
@@ -96,7 +96,7 @@
|
||||
"verifyOkResetCta": "Set a new password",
|
||||
"verifyInvalid": "That verification link is invalid or has expired.",
|
||||
"resendCta": "Send a new link",
|
||||
"resendDone": "If that email has an unverified account, we've sent a new verification link. Check your inbox.",
|
||||
"resendDone": "If that email has an unconfirmed account, we've sent a new confirmation link. Check your inbox, and your spam folder if it hasn't arrived in a minute.",
|
||||
"oauthCancelled": "Google sign-in was cancelled. You can try again or use email and password.",
|
||||
"accessRequested": "Thanks — we recorded your request. An admin will review it.",
|
||||
"accessRequestedFor": "We've recorded your access request for:",
|
||||
|
||||
@@ -22,5 +22,6 @@
|
||||
"audit_clear": "Napló ürítve",
|
||||
"download_credential_set": "Letöltési cookie-k beállítva",
|
||||
"download_credential_delete": "Letöltési cookie-k eltávolítva",
|
||||
"invite_delete": "Whitelista-bejegyzés törölve"
|
||||
"invite_delete": "Whitelista-bejegyzés törölve",
|
||||
"invite_send": "Meghívó elküldve"
|
||||
}
|
||||
|
||||
@@ -157,6 +157,12 @@
|
||||
"approveFailed": "A jóváhagyás sikertelen",
|
||||
"denyFailed": "Az elutasítás sikertelen",
|
||||
"addedToWhitelist": "{{email}} hozzáadva a fehérlistához",
|
||||
"inviteHint": "Küldj neki meghívót. A cím hozzáadása soha nem küld levelet — ez igen.",
|
||||
"invitedAt": "Meghívva: {{time}}. Az újraküldés másodszor is levelet küld neki.",
|
||||
"inviteLabel": "Meghívó küldése ide: {{email}}",
|
||||
"invited": "Meghívó elküldve ide: {{email}}.",
|
||||
"inviteFailed": "Nem sikerült elküldeni a meghívót.",
|
||||
"inviteEmailOff": "Nem ment ki levél: ezen a példányon nincs működő SMTP. Nézd meg a Beállítások → E-mail részt.",
|
||||
"addFailed": "Nem sikerült hozzáadni ezt az e-mailt",
|
||||
"requested": "kérve: {{time}}",
|
||||
"approveHint": "Jóváhagyás — fehérlistára teszi ezt az e-mailt és e-mailben értesíti őket, hogy bekerültek.",
|
||||
|
||||
@@ -82,8 +82,8 @@
|
||||
"demoEmail": "Demó e-mail",
|
||||
"demoEnter": "Belépés",
|
||||
"demoDenied": "Ez az e-mail nincs engedélyezve a demóhoz. Kérd az admint, hogy adja hozzá.",
|
||||
"registerDone": "Majdnem kész — nézd meg a postafiókod a megerősítő linkért. Miután megerősítetted, egy admin jóváhagyja a fiókodat, mielőtt beléphetnél.",
|
||||
"forgotDone": "Ha ehhez az e-mailhez tartozik fiók, elküldtük a visszaállító linket. Nézd meg a postafiókod.",
|
||||
"registerDone": "Majdnem kész — nézd meg a postafiókod a megerősítő linkért, és a Spam mappát is, ha egy percen belül nem jön meg. Miután megerősítetted, egy admin jóváhagyja a fiókodat, mielőtt beléphetnél.",
|
||||
"forgotDone": "Ha ehhez az e-mailhez tartozik fiók, elküldtük a visszaállító linket. Nézd meg a postafiókod, és a Spam mappát is, ha egy percen belül nem érkezik meg.",
|
||||
"resetDone": "A jelszavad be van állítva — most már beléphetsz.",
|
||||
"deadLink": {
|
||||
"title": "Ez a link már nem érvényes",
|
||||
@@ -96,7 +96,7 @@
|
||||
"verifyOkResetCta": "Új jelszó beállítása",
|
||||
"verifyInvalid": "Ez a megerősítő link érvénytelen vagy lejárt.",
|
||||
"resendCta": "Új link küldése",
|
||||
"resendDone": "Ha ehhez az e-mailhez tartozik megerősítetlen fiók, elküldtünk egy új megerősítő linket. Nézd meg a postafiókod.",
|
||||
"resendDone": "Ha ehhez az e-mailhez tartozik megerősítetlen fiók, elküldtünk egy új megerősítő linket. Nézd meg a postafiókod, és a Spam mappát is, ha egy percen belül nem érkezik meg.",
|
||||
"oauthCancelled": "A Google-belépés megszakadt. Próbáld újra, vagy lépj be e-maillel és jelszóval.",
|
||||
"accessRequested": "Köszönjük — rögzítettük a kérésed. Egy admin felülvizsgálja.",
|
||||
"accessRequestedFor": "Rögzítettük a hozzáférési kérelmedet erre a címre:",
|
||||
|
||||
Reference in New Issue
Block a user