package onboarding import ( "testing" "github.com/google/uuid" ) func TestSMSLoginSelectsRegistrationOrExistingAccountTemplate(t *testing.T) { for _, registered := range []bool{false, true} { name := "register" if registered { name = "login" } t.Run(name, func(t *testing.T) { f := newLoginFixture(t) if registered { _, err := f.s.pool.Exec(f.ctx, `INSERT INTO customer_phone_credential(phone_digest,phone_masked,issuer,subject) VALUES($1,$2,$3,$4)`, domainMAC(f.s.crypt.hashKey, "PHONE1\n"+f.phone), "+86138****0000", f.user.Issuer, f.user.Subject) must(t, err) } f.send() want := SMSPurposeRegister if registered { want = SMSPurposeLogin } if f.sender.purpose != want { t.Fatalf("expected %s, got %s", want, f.sender.purpose) } }) } } func TestSMSPasswordPurposeAndIdempotencyAreBoundTogether(t *testing.T) { f := newLoginFixture(t) in := f.smsInput() in.Purpose = SMSPurposeChangePassword id := uuid.NewString() w, first := f.request("POST", "/api/v1/web/login/sms/send", in, f.cookie, f.csrf, id) if w.Code != 200 || f.sender.purpose != SMSPurposeChangePassword { t.Fatal("wrong password template", w.Body.String()) } w, again := f.request("POST", "/api/v1/web/login/sms/send", in, f.cookie, f.csrf, id) if w.Code != 200 || first["sms_challenge_id"] != again["sms_challenge_id"] || f.sender.calls != 1 { t.Fatal("replay sent a second message", w.Body.String()) } in.Purpose = SMSPurposeLogin w, _ = f.request("POST", "/api/v1/web/login/sms/send", in, f.cookie, f.csrf, id) if w.Code != 409 || f.sender.calls != 1 { t.Fatal("request ID reused across purposes", w.Body.String()) } } func TestSMSLoginRejectsPhoneChangePurpose(t *testing.T) { f := newLoginFixture(t) in := f.smsInput() in.Purpose = SMSPurposeChangePhone w, _ := f.request("POST", "/api/v1/web/login/sms/send", in, f.cookie, f.csrf, "") if w.Code != 400 || f.sender.calls != 0 { t.Fatal("phone change accepted by login", w.Body.String()) } } func TestSMSOperatorAlwaysUsesLoginTemplate(t *testing.T) { f := newOperatorLoginFixture(t) f.send() if f.sender.purpose != SMSPurposeLogin { t.Fatal("unprovisioned operator received a registration message") } }