Commit 126b8e6
authored
Email anonymous registrations a confirmation link that signs them in (#4018)
An anonymous register-flow registration can't create its bike —
`Ownership` needs a creator — so step 1 now emails the address a link.
Following it proves the address, creates a passwordless account, signs
them in, and creates the bike the registration was holding, dropping
them on whatever step they're on.
- **The link carries its own single-use token**, minted only in the send
path, bound to the address it was mailed to, and spent on use. The
registration's `id_token` is already in the registrant's URL before any
email goes out, so a click carrying it would prove nothing about who
received what. Binding matters because step 1 stays resubmittable:
without it, editing `owner_email` after the link went out would let that
link confirm — and sign you in as — an address you never received mail
at.
- **`BParam::TOKEN_EXPIRATION` (90 days) governs both** the link and how
long the register flow resumes by token, since a link outliving the
registration it resumes is a dead end. The confirm lookup applies no
window of its own, so an expired link can say so and send a new one
rather than dumping them into a fresh registration.
- **The landing page only renders a form that posts itself** via #4019's
`auto-submit` controller — a link scanner's GET can't spend the token.
Resends are rate limited off a stamp written by the sender, not by the
delivering job.
- **The account it makes is a `passwordless_user`**, so it gets #4019's
offer to set a password like every other emailed sign in; an address
that already has an unconfirmed account gets confirmed, as the magic
link does. Creating one moves out of `Users::ProcessOrganizationRoleJob`
into `UserServices::PasswordlessCreator`, and the non-redirecting half
of `Sessionable#sign_in_and_redirect` becomes `sign_in_user`, so this
lands in the same session state as every other sign in.
- **The email rides on `Email::PartialRegistrationJob`**, which now
takes the notification kind alongside the id — it and
`partial_registration` are the two a registration sends before it has a
bike, so they share the domain check and the notification. Both are
seeded now, since nothing else leaves a b_param mid-flow for the mailer
previews.
New accounts still land on the terms-of-service gate the first time they
visit their account — same as passwordless org accounts. If step 1's
submit should count as acceptance, that's a follow-up.1 parent 86ab5e7 commit 126b8e6
32 files changed
Lines changed: 712 additions & 69 deletions
File tree
- app
- components
- emails
- partial_register_confirmation
- partial_registration
- register
- confirm
- step1
- step2
- controllers
- concerns
- jobs
- email
- users
- mailers
- models
- services
- bike_services
- user_services
- config
- locales
- db/seeds
- spec
- integration/registration
- jobs/email
- mailers/previews
- models
- requests
- services
- bike_services
- user_services
Lines changed: 15 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
Lines changed: 11 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
Lines changed: 22 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
Lines changed: 1 addition & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
4 | | - | |
| 4 | + | |
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
18 | 18 | | |
19 | 19 | | |
20 | 20 | | |
21 | | - | |
22 | | - | |
23 | | - | |
24 | | - | |
25 | 21 | | |
26 | 22 | | |
27 | 23 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
67 | 67 | | |
68 | 68 | | |
69 | 69 | | |
70 | | - | |
| 70 | + | |
71 | 71 | | |
72 | 72 | | |
73 | 73 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
47 | 47 | | |
48 | 48 | | |
49 | 49 | | |
50 | | - | |
51 | | - | |
52 | | - | |
53 | | - | |
54 | | - | |
55 | 50 | | |
56 | 51 | | |
57 | 52 | | |
| |||
0 commit comments