[PM-35830] Add ChangeEmailCommand#7650
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #7650 +/- ##
==========================================
- Coverage 64.86% 60.47% -4.39%
==========================================
Files 2140 2142 +2
Lines 94629 94709 +80
Branches 8445 8454 +9
==========================================
- Hits 61378 57275 -4103
- Misses 31155 35429 +4274
+ Partials 2096 2005 -91 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
| { | ||
| // Will throw if the new email violates a claiming organization's domain policy. | ||
| await EnsureNewEmailMatchesClaimedDomainAsync(user, newEmail); | ||
|
|
There was a problem hiding this comment.
As discussed in Slack, I think that the Admin Console layer can handle this.
Validation such as checking the admin role, making sure the user is claimed, and making sure the new email address is claimed, is all part of the admin/organization domain that we will handle.
The cross-team dependency on Auth is much narrower: we don't own the User domain and we don't know how to update a user's email (in the narrow sense). So that is the main thing we are looking for here.
I think if you remove the claimed domain check in this method, everything else LGTM. Thank you!
There was a problem hiding this comment.
Spoke with @jrmccannon yesterday and we found the correct approach. This is addressed in this commit: fd534bf
|
eliykat
left a comment
There was a problem hiding this comment.
Letting @jrmccannon handle this one as he's discussed the approach with you already.
|
@claude please review this PR. |
|
Claude finished @ike-kottlowski's task in 2m 56s —— View job Claude PR Review
Nice, well-tested command. The split between the cross-team 🔴 MasterPasswordSalt drifts from Email — likely auth regression for existing callers
The new command never touches Either:
Worth resolving before the follow-up migrates callers — silent salt drift is the kind of thing that surfaces as "cannot log in" much later. 🟡 Stripe-failure rollback path swallows context
The
If the rollback 🟡 Interface docstring contradicts the implementation
The interface tells callers they MUST perform organization-domain policy enforcement before invoking the command. The implementation then performs that exact check itself (
Right now the docstring and code disagree, which makes it ambiguous for the follow-up PR's caller migration. 🟢 Same-domain short-circuit comparison is case-sensitive
if (newDomain == CoreHelpers.GetEmailDomain(user.Email))
🟢 GatewayCustomerId null-check changes silent-skip behavior
🟢 Minor doc nit
The comment says the gate "mirrors the gate enforced by RegisterUserCommand." Nice things
• Branch: |



🎟️ Tracking
PM-35830
📔 Objective
Introduces a new
ChangeEmailCommandthat encapsulates the user email change flow.IChangeEmailCommand/ChangeEmailCommandunderBit.Core.Auth.UserFeatures.UserEmail, including claimed-domain enforcement, duplicate-email rejection, Stripe customer email sync with rollback on failure, and post-change push notifications (logout vs. settings sync depending on whether the user has a master password).ChangeEmailCommandTestscovering claimed-domain enforcement, disabled claiming orgs, duplicate email, same-user email, Stripe sync, Stripe rollback, and push branching.This PR introduces the command only; switching callers from
UserService.ChangeEmailAsyncto the new command will follow in a separate PR.Introduces a Admin Console Query to check if the email domain is allowed to be used.