Require a verified email address before the app opens - #18
Merged
Merged
Conversation
MustVerifyEmail was commented out on the User model, so Laravel never
sent a verification mail and hasVerifiedEmail() was always true. That is
why the `verified` middleware was dead weight and got removed: the
contract behind it was never implemented.
Implementing it is the half that was missing. Everything else was
already here and already tested -- Fortify's three verification routes,
the verify-email page, VerifyEmailResponse, an unverified() factory
state, EmailVerificationTest and VerificationNotificationTest -- so this
turns the flow on rather than building it.
The middleware goes back on, and this time it bites. Registration signs
the account in, sends the mail and holds it at the prompt until the link
is clicked.
Accepting an invitation is gated too, which it was not before. An
invitation is addressed to an email; joining an organization on the
strength of one should require proving the address is yours, or anyone
could type a colleague's address at registration and walk in. The
profile page stays reachable without verification, so an address typed
wrong can still be corrected.
/dashboard is new, and is needed now. config('fortify.home') is the
fixed string '/dashboard', which Fortify redirects to on its own when an
already verified user opens the verification prompt or asks for another
mail. Every real dashboard lives under an organization, so that path was
a 404 waiting for the first person to click a stale link. It now
forwards to the current organization, or to onboarding.
.env.example pointed at MAIL_MAILER=log on port 2525. Nothing listens on
2525 here and mailpit is on 1025, so a fresh checkout would have buried
the verification link in a log file at the exact moment the link became
mandatory.
Verified end to end against Herd and mailpit: register, mail arrives over
SMTP, the link in it lands on onboarding.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
MustVerifyEmailwas commented out on theUsermodel, so Laravel never sent a verification mail andhasVerifiedEmail()was always true. That is why theverifiedmiddleware was dead weight and got removed — the contract behind it was never implemented.Implementing it is the half that was missing. Everything else was already here and already tested: Fortify's three verification routes, the
verify-emailpage,VerifyEmailResponse, anunverified()factory state,EmailVerificationTestandVerificationNotificationTest. This turns the flow on rather than building it.What changed
The middleware goes back on, and this time it bites. Registration signs the account in, sends the mail, and holds it at the prompt until the link is clicked.
Accepting an invitation is gated too, which it was not before. An invitation is addressed to an email; joining an organization on the strength of one should require proving the address is yours, or anyone could type a colleague's address at registration and walk in. The profile page stays reachable without verification, so an address typed wrong can still be corrected.
/dashboardis new, and is needed now.config('fortify.home')is the fixed string/dashboard, which Fortify redirects to on its own when an already verified user opens the verification prompt or asks for another mail. Every real dashboard lives under an organization, so that path was a 404 waiting for the first person to click a stale link. It now forwards to the current organization, or to onboarding..env.examplepointed atMAIL_MAILER=logon port 2525. Nothing listens on 2525 here and mailpit is on 1025, so a fresh checkout would have buried the verification link in a log file at the exact moment the link became mandatory.Verification
New
VerifiedAccessTestcovers each gated surface, the profile escape hatch, that registration sends the mail and leaves the account unverified, and both/dashboardoutcomes. Dropping the contract while keeping the middleware turns 8 of its 12 cases red, so the guard is real rather than a no-op.The browser tests now follow the actual signed link from the mail rather than writing
email_verified_atdirectly.Checked end to end against Herd and mailpit: register → prompt → mail arrives over SMTP → the link in it lands on onboarding. 330 tests, PHPStan, Pint,
tscandvp checkall green.🤖 Generated with Claude Code