Skip to content

[PM-35830] Add ChangeEmailCommand#7650

Merged
ike-kottlowski merged 24 commits into
mainfrom
auth/pm-35830/change-email-command
May 27, 2026
Merged

[PM-35830] Add ChangeEmailCommand#7650
ike-kottlowski merged 24 commits into
mainfrom
auth/pm-35830/change-email-command

Conversation

@ike-kottlowski
Copy link
Copy Markdown
Contributor

@ike-kottlowski ike-kottlowski commented May 15, 2026

🎟️ Tracking

PM-35830

📔 Objective

Introduces a new ChangeEmailCommand that encapsulates the user email change flow.

  • Adds IChangeEmailCommand / ChangeEmailCommand under Bit.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).
  • Adds ChangeEmailCommandTests covering 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.ChangeEmailAsync to 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.

@ike-kottlowski ike-kottlowski requested a review from enmande May 15, 2026 22:31
@codecov
Copy link
Copy Markdown

codecov Bot commented May 15, 2026

Codecov Report

❌ Patch coverage is 98.07692% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 60.59%. Comparing base (8bd4af7) to head (e453bf2).
⚠️ Report is 14 commits behind head on main.

Files with missing lines Patch % Lines
.../Auth/UserFeatures/UserEmail/ChangeEmailCommand.cs 97.43% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #7650      +/-   ##
==========================================
- Coverage   64.90%   60.59%   -4.32%     
==========================================
  Files        2141     2145       +4     
  Lines       94654    94957     +303     
  Branches     8456     8498      +42     
==========================================
- Hits        61435    57537    -3898     
- Misses      31118    35401    +4283     
+ Partials     2101     2019      -82     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@ike-kottlowski ike-kottlowski requested a review from eliykat May 16, 2026 02:11
@ike-kottlowski ike-kottlowski marked this pull request as ready for review May 16, 2026 02:16
@ike-kottlowski ike-kottlowski requested a review from a team as a code owner May 16, 2026 02:16
Comment thread src/Core/Auth/UserFeatures/UserEmail/ChangeEmailCommand.cs
@ike-kottlowski ike-kottlowski requested review from JaredSnider-Bitwarden and removed request for enmande May 20, 2026 15:24
@ike-kottlowski ike-kottlowski marked this pull request as draft May 20, 2026 16:50
@eliykat eliykat requested a review from jrmccannon May 21, 2026 05:25
Copy link
Copy Markdown
Member

@eliykat eliykat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Letting @jrmccannon handle this one as he's discussed the approach with you already.

@ike-kottlowski ike-kottlowski changed the title [PM-35830] Add ChangeEmailCommand with DI [PM-35830] Add ChangeEmailCommand May 21, 2026
@ike-kottlowski ike-kottlowski marked this pull request as ready for review May 21, 2026 22:21
@ike-kottlowski ike-kottlowski requested a review from a team as a code owner May 21, 2026 22:21
@ike-kottlowski
Copy link
Copy Markdown
Contributor Author

@claude please review this PR.

@claude

This comment was marked as resolved.

Comment thread src/Core/Auth/UserFeatures/UserEmail/ChangeEmailCommand.cs Outdated
Comment thread src/Core/Auth/UserFeatures/UserEmail/ChangeEmailCommand.cs Outdated
@ike-kottlowski ike-kottlowski requested review from eliykat and jrmccannon and removed request for eliykat May 22, 2026 21:35
@eliykat eliykat removed their request for review May 22, 2026 21:55
jrmccannon
jrmccannon previously approved these changes May 26, 2026
Copy link
Copy Markdown
Contributor

@jrmccannon jrmccannon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for adding the additional domain checks!

Copy link
Copy Markdown
Contributor

@JaredSnider-Bitwarden JaredSnider-Bitwarden left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking really good so far. Just some clarity work to be done:

Comment thread src/Core/Auth/UserFeatures/UserEmail/IChangeEmailCommand.cs Outdated
Comment thread src/Core/Auth/UserFeatures/UserEmail/ChangeEmailCommand.cs Outdated
Comment thread src/Core/Auth/UserFeatures/UserEmail/ChangeEmailCommand.cs Outdated
…in query

Replace IsAllowedAsync's bool return with the
OrganizationDomainAllowEmailChangeDenialReason enum so call sites can
branch on the specific reason a domain change was denied. ChangeEmailCommand
now surfaces a tailored BadRequestException message per denial reason.
Replace the if + switch with a switch expression whose discard arm
throws InvalidOperationException, so any future
OrganizationDomainAllowEmailChangeDenialReason value fails closed instead
of letting the email change proceed. Add a unit test covering the
UserIsClaimedAndDomainNotVerified branch, which previously had no
assertion on its tailored error message.
@ike-kottlowski
Copy link
Copy Markdown
Contributor Author

@claude please review my current changes. Please consider @JaredSnider-Bitwarden comments when responding.

@claude

This comment was marked as resolved.

@ike-kottlowski
Copy link
Copy Markdown
Contributor Author

ike-kottlowski commented May 27, 2026

@claude Please review again. for gap 1 the user.BillingEmailAddress != null check is required to satisfy the nullable constraint for C# otherwise there is an error. It's defensive but fine. There is an additional test for the domain case matching, gap 4. We've also removed the throw when a gateway has a value but the customerId is null.

@claude

This comment was marked as resolved.

@sonarqubecloud
Copy link
Copy Markdown

Copy link
Copy Markdown
Contributor

@JaredSnider-Bitwarden JaredSnider-Bitwarden left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Excellent work! LGTM! Please see my one comment below about QA note implications 👇


await _userRepository.ReplaceAsync(user);

if (user.Gateway == GatewayType.Stripe)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🏅 The stripe logic change to allow free users with a gateway but no customer id to change their email appears to be a good one, but please be sure we note it as a QA test case if it can be tested since it is a behavior change.

Copy link
Copy Markdown
Contributor Author

@ike-kottlowski ike-kottlowski May 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll add it to the self-service ticket. These changes won't be able to be tested until AC has their email change flow implemented. These changes are foundational and not functional at this point in time.

@ike-kottlowski ike-kottlowski merged commit fa85039 into main May 27, 2026
55 checks passed
@ike-kottlowski ike-kottlowski deleted the auth/pm-35830/change-email-command branch May 27, 2026 21:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants