Skip to content

[PM-34776/PM-37797] Add invite link email domain validation endpoint#7683

Open
r-tome wants to merge 9 commits into
mainfrom
ac/pm-37797/invite-link-email-domain-validation-endpoint
Open

[PM-34776/PM-37797] Add invite link email domain validation endpoint#7683
r-tome wants to merge 9 commits into
mainfrom
ac/pm-37797/invite-link-email-domain-validation-endpoint

Conversation

@r-tome
Copy link
Copy Markdown
Contributor

@r-tome r-tome commented May 20, 2026

🎟️ Tracking

https://bitwarden.atlassian.net/browse/PM-34776
https://bitwarden.atlassian.net/browse/PM-37797

📔 Objective

Add an anonymous POST /organizations/invite-link/validate-email-domain endpoint so clients can check whether an email belongs to an invite link's allowed domains before login/signup.

Introduces InviteLinkDomainValidator (will be reused by the accept command).

Clients PR

r-tome added 8 commits May 20, 2026 16:21
- Introduced IsEmailDomainAllowed method to check if an email's domain is permitted based on allowed domains.
- Added necessary using directives for MailAddress and domain sanitization utilities.
- Removed the IsEmailDomainAllowed method and associated using directives for MailAddress.
- Cleaned up the code by eliminating unused methods related to email domain validation.
- Introduced InviteLinkDomainValidator class with IsEmailDomainAllowed method to validate if an email's domain is in the list of allowed domains.
- Utilized MailAddress for email parsing and added domain sanitization logic.
- Implemented ValidateEmailDomain method in OrganizationInviteLinksController to check if an email's domain is allowed based on the invite link's permitted domains.
- Created OrganizationInviteLinkValidateEmailDomainRequestModel for request validation and OrganizationInviteLinkValidateEmailDomainResponseModel for response formatting.
- Integrated IOrganizationInviteLinkRepository to retrieve invite link details by code.
- Created InviteLinkDomainValidatorTests class to validate email domain functionality.
- Added tests for various scenarios including invalid emails, empty domain lists, and matching domains.
- Ensured comprehensive coverage of the IsEmailDomainAllowed method's behavior.
…eLinksController

- Implemented a test to validate that an allowed email domain returns the expected result when checked against an organization invite link.
- Ensured the test verifies the creation of an invite link and the subsequent validation of an email domain against the allowed domains list.
… domain

- Introduced ValidateOrganizationInviteLinkEmailDomainQuery class to validate if an email's domain is allowed based on the invite link's permitted domains.
- Created IValidateOrganizationInviteLinkEmailDomainQuery interface to define the validation method.
- Added unit tests for the validation query to ensure correct behavior for various scenarios, including link not found and domain matching.
…r email domain

- Updated ValidateEmailDomain method to utilize IValidateOrganizationInviteLinkEmailDomainQuery for domain validation instead of directly accessing the repository.
- Removed unnecessary repository dependency and streamlined the response handling for validation results.
- Registered the new validation query in OrganizationServiceCollectionExtensions for dependency injection.
@r-tome r-tome added the ai-review Request a Claude code review label May 20, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 20, 2026

🤖 Bitwarden Claude Code Review

Overall Assessment: APPROVE

Reviewed the new anonymous POST /organizations/invite-link/validate-email-domain endpoint, the IValidateOrganizationInviteLinkEmailDomainQuery and InviteLinkDomainValidator it delegates to, the DI registration, and the accompanying unit and integration tests. The implementation follows established server conventions (CommandResult error mapping, TryAddScoped DI, query/command separation) and reuses the shared EmailValidation.IsValidEmail/GetDomain helpers after the earlier reviewer feedback was addressed.

Code Review Details

No findings.

Notes considered and dropped:

  • Anonymous endpoint surface: the 404-vs-200 distinction is an existence oracle for invite-link codes, but codes are 128-bit Guid.NewGuid() values (intentionally non-Comb, per the entity remarks) and the endpoint is by design unauthenticated for pre-login domain checks. Default post:* IP rate limiting (60/min, 5/s) applies via CustomIpRateLimitMiddleware, so this is acceptable.
  • Parser mismatch between EmailValidation.IsValidEmail (MimeKit) and EmailValidation.GetDomain (System.Net.Mail.MailAddress): theoretically an email could pass the former and fail the latter, surfacing a BadRequestException instead of IsAllowed: false. The [EmailAddress] data annotation on the request model gates this further; impact is bounded to a 400 response, not a security issue. Pre-existing helper behaviour, not introduced by this PR.

@codecov
Copy link
Copy Markdown

codecov Bot commented May 20, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 60.23%. Comparing base (779320a) to head (24d121f).
⚠️ Report is 10 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #7683      +/-   ##
==========================================
+ Coverage   60.07%   60.23%   +0.15%     
==========================================
  Files        2132     2140       +8     
  Lines       93904    94424     +520     
  Branches     8341     8412      +71     
==========================================
+ Hits        56417    56872     +455     
- Misses      35503    35561      +58     
- Partials     1984     1991       +7     

☔ 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.

/// </summary>
public static bool IsEmailDomainAllowed(string? email, IEnumerable<string> allowedDomains)
{
if (!MailAddress.TryCreate(email, out var mailAddress))
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.

EmailValidation.IsValidEmail our preferred method of validating. I would validate that way then use the EmailValidation.GetDomain method (which does the same thing but is a shared method).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I did know that existed! Replaced

@r-tome r-tome requested a review from jrmccannon May 21, 2026 13:41
@sonarqubecloud
Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai-review Request a Claude code review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants