hub 0.164.0 (unreleased): bind mail true when no box exists (W3), tries left on a wrong try (W4), use the newer mail hint (W5)
gates / gates (push) Failing after 14m55s
gates / gates (push) Failing after 14m55s
This commit is contained in:
@@ -7,6 +7,15 @@
|
||||
from the host's newest swap event (`store.LatestHostSwapEvent`, by `details.host_id`), so repeats and a hub restart
|
||||
stay quiet. An older agent (no numbers) is not evaluated. Both in `notify.operatorOnlyEvents`. Tests
|
||||
`TestR1192_HostSwapShortIsRaisedOnceAndClearedOnce`, `TestR1192_HostSwapEventsAreOperatorOnly`.
|
||||
- **The rehearsal's first-hour words (W3, W4, W5).** W3 — the bind mail no longer says „Elkészült a Felhom dobozod…"
|
||||
when no box exists (it is also sent when the operator deletes a dead box): „Ezzel a hivatkozással kötheted össze a
|
||||
Felhom dobozodat a fiókoddal, amikor a telepítés után a doboz képernyőjén megjelenik a párosító kód. Nincs szükség
|
||||
bejelentkezésre:" (EN „With this link you can link your Felhom box to your account once the box shows its pairing
|
||||
code on its screen after the installation. No sign-in needed:"); mail goldens regenerated on purpose. W4 — a wrong
|
||||
try says „Még N próbálkozásod van, utána a hivatkozás zárolódik." (EN „Tries left before the link locks: N."); the
|
||||
same for a wrong code and a wrong passphrase (no oracle). W5 — a used or expired link says „Ha van újabb leveled a
|
||||
Felhomtól, abban lévő linket használd." (EN „If you have a newer mail from Felhom, use the link in that one.") above
|
||||
„Új linket kérek". Tests `TestW4_*`, `TestW5_*` (W4 red-proved).
|
||||
|
||||
## v0.163.0 — a rebuilt box gets the household's sealed key package back (R-1176); one run per daily job on clock-change days (R-1183); abandoning one set-aside copy keeps the other copies' packages (R-1182); the „new link" page tells a household its old box is still linked (R-1203) (2026-10-21)
|
||||
|
||||
|
||||
@@ -57,13 +57,15 @@
|
||||
"mail.claim.claim.subject": "[Felhom] Your Felhom server is up — setup code",
|
||||
"mail.claim.claim.body": "Dear Customer,\n\nYour Felhom server is up. To use the dashboard for the first time, enter the\nsetup code below, then choose your own password:\n\nSetup code: %s\n\nThe code is valid for 72 hours and can be used once. You can reach the\ndashboard here:\n\n%s\n\nIf it did not reach you in time, the dashboard's \"Request a new code\" button\ngets you a fresh one — it always arrives at this e-mail address.\n\nBest regards,\nFelhom.eu",
|
||||
"mail.selfbind.subject": "[Felhom] Link your Felhom box to your account",
|
||||
"mail.selfbind.body": "Dear Customer,\n\nYour Felhom box is ready and waiting to be linked. You can link it to your\naccount yourself using the link below — no sign-in needed:\n\n%s\n\nAfter you open the link you will need to enter two things:\n\n 1. The pairing code, shown on the box's own screen (the monitor).\n 2. Your owner passphrase (the 5-word phrase) that you received from your\n Felhom operator — in person or by telephone, never by e-mail. It proves\n the account is yours.\n\nThe link is valid for 7 days. For safety it locks after 5 failed attempts —\nif that happens, contact support.\n\nIf you did not ask for this, ignore this e-mail.\n\nBest regards,\nFelhom.eu",
|
||||
"mail.selfbind.body": "Dear Customer,\n\nWith this link you can link your Felhom box to your account once the box shows\nits pairing code on its screen after the installation. No sign-in needed:\n\n%s\n\nAfter you open the link you will need to enter two things:\n\n 1. The pairing code, shown on the box's own screen (the monitor).\n 2. Your owner passphrase (the 5-word phrase) that you received from your\n Felhom operator — in person or by telephone, never by e-mail. It proves\n the account is yours.\n\nThe link is valid for 7 days. For safety it locks after 5 failed attempts —\nif that happens, contact support.\n\nIf you did not ask for this, ignore this e-mail.\n\nBest regards,\nFelhom.eu",
|
||||
"mail.kernel.subject": "[Felhom] Your Felhom box restarts tonight",
|
||||
"mail.kernel.body": "Hi,\n\nTonight your Felhom box restarts for a security update. Your apps will be away for a few\nminutes, then come back by themselves. You do not need to do anything.\n\nIf the box is not back by morning: unplug its power cable, wait 10 seconds, and plug it back\nin. The box then starts its earlier, proven system by itself.\n\nIf that does not help, reply to this e-mail and we will help.\n\nBest,\nFelhom.eu",
|
||||
"bind.title": "Felhom — Link your box",
|
||||
"bind.heading": "Link your Felhom <span>box</span>",
|
||||
"bind.lead": "Link the Felhom box you have just installed to your account. Enter the pairing code shown on the box's screen, and your owner passphrase.",
|
||||
"bind.failed": "Those details are not right. Check the pairing code and the owner passphrase, then try again.",
|
||||
"bind.attempts_left.pre": "Tries left before the link locks:",
|
||||
"bind.attempts_left.post": ".",
|
||||
"bind.label.pairing": "Pairing code",
|
||||
"bind.placeholder.pairing": "ABC-234",
|
||||
"bind.hint.pairing": "It appears on the box's monitor, after the install.",
|
||||
@@ -89,6 +91,7 @@
|
||||
"mail.event.app_stopped_unhealthy": "%s: the app was stopped because it kept crashing",
|
||||
"bind.resend.hint": "If this was your link and your box is not linked yet, we send a fresh link to the e-mail address you gave Felhom.",
|
||||
"bind.resend.button": "Send me a new link",
|
||||
"bind.resend.newer": "If you have a newer mail from Felhom, use the link in that one.",
|
||||
"bind.resent.lead": "Done.",
|
||||
"bind.resent.body": "If this was a real link and your box is not linked yet, a new e-mail reaches your registered address within a few minutes. If it does not, contact support.",
|
||||
"bind.oldbox.lead": "Your old box is still linked to your account.",
|
||||
|
||||
@@ -57,13 +57,15 @@
|
||||
"mail.claim.claim.subject": "[Felhom] Elindult a Felhom szervered — beállító kód",
|
||||
"mail.claim.claim.body": "Kedves Ügyfél!\n\nElindult a Felhom szervered. A vezérlőpult első használatához add meg az\nalábbi beállító kódot, majd válassz saját jelszót:\n\nBeállító kód: %s\n\nA kód 72 óráig érvényes, és egyszer használható fel. A vezérlőpultot itt éred el:\n\n%s\n\nHa nem kaptad volna meg időben, a vezérlőpult \"Új kód kérése\" gombjával\nkérhetsz frisset — az mindig erre az e-mail címre érkezik.\n\nÜdvözlettel,\nFelhom.eu",
|
||||
"mail.selfbind.subject": "[Felhom] Kösd össze a Felhom dobozodat",
|
||||
"mail.selfbind.body": "Kedves Ügyfél!\n\nElkészült a Felhom dobozod, és készen áll az összekötésre. Az alábbi hivatkozáson\ntudod te magad összekötni a fiókoddal — nincs szükség bejelentkezésre:\n\n%s\n\nA hivatkozás megnyitása után két adatot kell megadnod:\n\n 1. A párosító kódot, amely a doboz képernyőjén (a monitoron) látható.\n 2. A tulajdonosi jelmondatodat (az 5 szóból álló kifejezést), amelyet a\n Felhom üzemeltetőjétől kaptál — személyesen vagy telefonon, e-mailben\n soha. Ez igazolja, hogy a fiók a tiéd.\n\nA hivatkozás 7 napig érvényes. Biztonsági okból 5 sikertelen próbálkozás után\nzárolódik — ilyenkor vedd fel a kapcsolatot az ügyfélszolgálattal.\n\nHa nem te kérted ezt, hagyd figyelmen kívül ezt az e-mailt.\n\nÜdvözlettel,\nFelhom.eu",
|
||||
"mail.selfbind.body": "Kedves Ügyfél!\n\nEzzel a hivatkozással kötheted össze a Felhom dobozodat a fiókoddal, amikor a\ntelepítés után a doboz képernyőjén megjelenik a párosító kód. Nincs szükség\nbejelentkezésre:\n\n%s\n\nA hivatkozás megnyitása után két adatot kell megadnod:\n\n 1. A párosító kódot, amely a doboz képernyőjén (a monitoron) látható.\n 2. A tulajdonosi jelmondatodat (az 5 szóból álló kifejezést), amelyet a\n Felhom üzemeltetőjétől kaptál — személyesen vagy telefonon, e-mailben\n soha. Ez igazolja, hogy a fiók a tiéd.\n\nA hivatkozás 7 napig érvényes. Biztonsági okból 5 sikertelen próbálkozás után\nzárolódik — ilyenkor vedd fel a kapcsolatot az ügyfélszolgálattal.\n\nHa nem te kérted ezt, hagyd figyelmen kívül ezt az e-mailt.\n\nÜdvözlettel,\nFelhom.eu",
|
||||
"mail.kernel.subject": "[Felhom] Ma éjjel újraindul a Felhom dobozod",
|
||||
"mail.kernel.body": "Szia!\n\nMa éjjel a Felhom dobozod egy biztonsági frissítés miatt újraindul. Ilyenkor az alkalmazásaid\nnéhány percig nem érhetők el, utána maguktól visszajönnek. Neked nem kell semmit tenned.\n\nHa reggelre a doboz mégsem érhető el: húzd ki a tápkábelét, várj 10 másodpercet, és dugd\nvissza. A doboz ilyenkor magától a korábbi, bevált rendszerrel indul el.\n\nHa ez sem segít, válaszolj erre a levélre, és segítünk.\n\nÜdv,\nFelhom.eu",
|
||||
"bind.title": "Felhom — Doboz összekötése",
|
||||
"bind.heading": "Felhom <span>doboz</span> összekötése",
|
||||
"bind.lead": "Kösd össze a most telepített Felhom dobozodat a fiókoddal. Add meg a doboz képernyőjén látható párosító kódot és a tulajdonosi jelmondatodat.",
|
||||
"bind.failed": "A megadott adatok nem megfelelőek. Ellenőrizd a párosító kódot és a tulajdonosi jelmondatot, majd próbáld újra.",
|
||||
"bind.attempts_left.pre": "Még",
|
||||
"bind.attempts_left.post": " próbálkozásod van, utána a hivatkozás zárolódik.",
|
||||
"bind.label.pairing": "Párosító kód",
|
||||
"bind.placeholder.pairing": "ABC-234",
|
||||
"bind.hint.pairing": "A doboz monitorán jelenik meg, a telepítés után.",
|
||||
@@ -89,6 +91,7 @@
|
||||
"mail.event.app_stopped_unhealthy": "%s: az alkalmazást leállítottuk, mert újra és újra összeomlott",
|
||||
"bind.resend.hint": "Ha ez a te linked volt, és a dobozod még nincs összekötve, új linket küldünk arra az e-mail címre, amelyet a Felhomnál megadtál.",
|
||||
"bind.resend.button": "Új linket kérek",
|
||||
"bind.resend.newer": "Ha van újabb leveled a Felhomtól, abban lévő linket használd.",
|
||||
"bind.resent.lead": "Kész.",
|
||||
"bind.resent.body": "Ha ez egy valódi hivatkozás volt, és a dobozod még nincs összekötve, néhány percen belül új e-mailt kapsz a regisztrált címedre. Ha nem jön, szólj az ügyfélszolgálatnak.",
|
||||
"bind.oldbox.lead": "A régi dobozod még össze van kötve a fiókoddal.",
|
||||
|
||||
@@ -2,8 +2,8 @@ SUBJECT: [Felhom] Link your Felhom box to your account
|
||||
---
|
||||
Dear Customer,
|
||||
|
||||
Your Felhom box is ready and waiting to be linked. You can link it to your
|
||||
account yourself using the link below — no sign-in needed:
|
||||
With this link you can link your Felhom box to your account once the box shows
|
||||
its pairing code on its screen after the installation. No sign-in needed:
|
||||
|
||||
https://hub.felhom.eu/bind/FIXTURETOKEN
|
||||
|
||||
|
||||
@@ -2,8 +2,9 @@ SUBJECT: [Felhom] Kösd össze a Felhom dobozodat
|
||||
---
|
||||
Kedves Ügyfél!
|
||||
|
||||
Elkészült a Felhom dobozod, és készen áll az összekötésre. Az alábbi hivatkozáson
|
||||
tudod te magad összekötni a fiókoddal — nincs szükség bejelentkezésre:
|
||||
Ezzel a hivatkozással kötheted össze a Felhom dobozodat a fiókoddal, amikor a
|
||||
telepítés után a doboz képernyőjén megjelenik a párosító kód. Nincs szükség
|
||||
bejelentkezésre:
|
||||
|
||||
https://hub.felhom.eu/bind/FIXTURETOKEN
|
||||
|
||||
|
||||
@@ -102,6 +102,9 @@ type bindPageData struct {
|
||||
State string // "form" | "success" | "expired" | "consumed" | "locked" | "resent" | "oldbox" (R-1203)
|
||||
Token string // echoed into the form action (the capability itself; already in the URL)
|
||||
Failed bool // generic factor-check failure (form state only)
|
||||
// AttemptsLeft (W4, night 2026-10-21) is how many tries the link has before it locks — said beside the failure,
|
||||
// so the household is not surprised by the lock (which only support can open). 0 = not shown.
|
||||
AttemptsLeft int
|
||||
// Lang is the language to render in. It is the CUSTOMER'S CREATION-TIME language and nothing
|
||||
// else: no box has reported yet at bind time, and this page deliberately offers no switch —
|
||||
// the person opening it is a stranger holding a capability URL, exactly like the guest share
|
||||
@@ -249,7 +252,11 @@ func (s *Server) handleBind(w http.ResponseWriter, r *http.Request) {
|
||||
s.renderBind(w, http.StatusOK, bindPageData{State: "locked", Lang: lang})
|
||||
return
|
||||
}
|
||||
s.renderBind(w, http.StatusOK, bindPageData{State: "form", Token: token, Failed: true, Lang: lang})
|
||||
left := store.SelfBindMaxAttempts - attempts
|
||||
if left < 0 {
|
||||
left = 0
|
||||
}
|
||||
s.renderBind(w, http.StatusOK, bindPageData{State: "form", Token: token, Failed: true, AttemptsLeft: left, Lang: lang})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -318,7 +325,7 @@ const bindPageHTML = `<!DOCTYPE html>
|
||||
<h1>{{T "bind.heading"}}</h1>
|
||||
{{if eq .State "form"}}
|
||||
<p class="lead">{{T "bind.lead"}}</p>
|
||||
{{if .Failed}}<div class="banner">{{T "bind.failed"}}</div>{{end}}
|
||||
{{if .Failed}}<div class="banner">{{T "bind.failed"}}{{if .AttemptsLeft}} {{T "bind.attempts_left.pre"}} {{.AttemptsLeft}}{{T "bind.attempts_left.post"}}{{end}}</div>{{end}}
|
||||
<form method="POST" action="/bind/{{.Token}}">
|
||||
<label for="pairing_code">{{T "bind.label.pairing"}}</label>
|
||||
<input class="code" type="text" id="pairing_code" name="pairing_code" autocomplete="off" autocapitalize="characters" spellcheck="false" required autofocus placeholder="{{T "bind.placeholder.pairing"}}">
|
||||
@@ -335,6 +342,7 @@ const bindPageHTML = `<!DOCTYPE html>
|
||||
{{else if eq .State "consumed"}}
|
||||
<p class="lead">{{T "bind.consumed.lead"}}</p>
|
||||
<p>{{T "bind.consumed.body"}}</p>
|
||||
<p class="hint">{{T "bind.resend.newer"}}</p>
|
||||
<form method="POST" action="/bind/{{.Token}}/resend"><p class="hint">{{T "bind.resend.hint"}}</p><button type="submit">{{T "bind.resend.button"}}</button></form>
|
||||
{{else if eq .State "oldbox"}}
|
||||
<p class="lead">{{T "bind.oldbox.lead"}}</p>
|
||||
@@ -348,6 +356,7 @@ const bindPageHTML = `<!DOCTYPE html>
|
||||
{{else}}
|
||||
<p class="lead">{{T "bind.invalid.lead"}}</p>
|
||||
{{if .Token}}<p>{{T "bind.invalid.body_resend"}}</p>
|
||||
<p class="hint">{{T "bind.resend.newer"}}</p>
|
||||
<form method="POST" action="/bind/{{.Token}}/resend"><p class="hint">{{T "bind.resend.hint"}}</p><button type="submit">{{T "bind.resend.button"}}</button></form>
|
||||
{{else}}<p>{{T "bind.invalid.body"}}</p>{{end}}
|
||||
{{end}}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package web
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"gitea.dooplex.hu/admin/felhom-hub/internal/store"
|
||||
)
|
||||
|
||||
// W4 (rehearsal word table, night 2026-10-21): a wrong try says how many tries are left before the link locks — the
|
||||
// fifth locks it and only support can open it. The count is the same for a wrong code and a wrong passphrase, so the
|
||||
// no-oracle rule (TestSelfBind_B_NoOracle) holds.
|
||||
// RED-PROOF: with AttemptsLeft not set on the failure render the „Még N" sentence is missing → fails at attempt 1.
|
||||
func TestW4_AWrongTrySaysHowManyTriesAreLeft(t *testing.T) {
|
||||
s, st := newTestServer(t)
|
||||
selfBindSetup(t, st, "acme", testCode)
|
||||
token := mintLink(t, st, "acme", selfBindTTL)
|
||||
for i := 1; i < store.SelfBindMaxAttempts; i++ {
|
||||
body := bindPOST(t, s, token, "ZZZ999", "definitely wrong words indeed").Body.String()
|
||||
want := fmt.Sprintf("Még %d próbálkozásod van", store.SelfBindMaxAttempts-i)
|
||||
if !strings.Contains(body, want) {
|
||||
t.Fatalf("attempt %d: the page must say %q", i, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// W5: on a used or expired link the page says to use the newer mail before „Új linket kérek" (a new link kills the
|
||||
// one the household may be about to use — TestSelfBind_C4_SingleActive).
|
||||
func TestW5_AnOldLinkPointsToTheNewerMail(t *testing.T) {
|
||||
s, st := newTestServer(t)
|
||||
selfBindSetup(t, st, "acme", testCode)
|
||||
token := mintLink(t, st, "acme", -1) // already expired
|
||||
body := bindGET(t, s, token).Body.String()
|
||||
if !strings.Contains(body, "újabb leveled") || !strings.Contains(body, "Új linket kérek") {
|
||||
t.Fatalf("an expired link must point to the newer mail above the button: %q", body)
|
||||
}
|
||||
if strings.Index(body, "újabb leveled") > strings.Index(body, "Új linket kérek") {
|
||||
t.Fatal("the newer-mail hint must come BEFORE the button")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user