Fix password reset and rework checkout-driven account creation#371
Merged
Fix password reset and rework checkout-driven account creation#371
Conversation
…count creation Password reset emails (and other transactional mail) were being silently dropped for users with email_verified_at = null or receives_notification_emails = false, because SuppressMailNotificationListener only carved out VerifyEmail. Customers who purchased Ultra via the pricing flow were created with a random password and never sent a verification email (no Registered event fired), so they had no way into their account: the post-purchase license email was suppressed, and password reset was suppressed too. Changes: - Introduce App\Contracts\TransactionalNotification marker so transactional mail (account recovery, entitlements, receipts) bypasses the listener. - Tag LicenseKeyGenerated, BundleGranted, PluginGranted, ProductGranted. - Carve out framework ResetPassword + VerifyEmail explicitly in the listener. - Add ClaimAccount notification (uses the password broker token + existing reset-password UI) so checkout-created users get one email that verifies email and lets them set a password. - Dispatch ClaimAccount from MobilePricing and Api\LicenseController when wasRecentlyCreated. Fire Registered from ClaimDonationLicense (user already chose their own password there). - On password reset, set email_verified_at = now() when null so the same flow serves both real resets and account claims. - Rework OrderSuccess: drop license-key copy entirely. For Ultra, show "Go to Dashboard" for verified users, or a "check your inbox / contact support@nativephp.com" message for newly-created users. Co-Authored-By: Claude Opus 4.7 (1M context) <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.
Summary
Fixes a class of bug where users created via the Ultra checkout flow (e.g.
alex.ganderton@arrangemy.com) end up stranded — no verification email, no license email, and password reset silently fails — becauseSuppressMailNotificationListenerwas dropping any mail to users who were unverified or opted-out of notification emails, with onlyVerifyEmailcarved out.What changed
Listener / transactional notifications
App\Contracts\TransactionalNotificationmarker interfaceSuppressMailNotificationListenernow bypasses anything implementing the marker, plus frameworkVerifyEmailandResetPasswordLicenseKeyGenerated,BundleGranted,PluginGranted,ProductGrantedas transactionalAccount claim flow
ClaimAccountnotification — uses the password broker token so it routes through the existing reset-password UI; one email verifies their address and sets a passwordCustomerAuthController::resetPasswordnow setsemail_verified_at = now()when null on a successful reset, so the same flow serves both real password resets and first-time account claimsMobilePricing::findOrCreateUserandApi\LicenseController::storedispatchClaimAccountwhen the user is newly createdClaimDonationLicense::claimnow firesRegistered(user already chose their own password there, so just needs verification)Order success page
licenseKeytosubscriptionTest plan
php artisan test --compact tests/Feature/SuppressMailNotificationListenerTest.php tests/Feature/CustomerAuthenticationTest.php tests/Feature/MobilePricingTest.php tests/Feature/Livewire/OrderSuccessTest.php tests/Feature/ClaimDonationLicenseTest.php— 67 passingvendor/bin/pint --dirty --format agent— cleanemail_verified_at = null, and "Go to Dashboard" for a verified userClaimAccountto the population of stranded users created viaMobilePricingwho never received any email🤖 Generated with Claude Code