Skip to content

[PM-21179] Add interface to check if user is enrolled in account recovery#6993

Merged
r-tome merged 15 commits intomainfrom
ac/pm-21179/interface-to-check-enrolled-in-account-recovery
Feb 24, 2026
Merged

[PM-21179] Add interface to check if user is enrolled in account recovery#6993
r-tome merged 15 commits intomainfrom
ac/pm-21179/interface-to-check-enrolled-in-account-recovery

Conversation

@r-tome
Copy link
Copy Markdown
Contributor

@r-tome r-tome commented Feb 12, 2026

🎟️ Tracking

https://bitwarden.atlassian.net/browse/PM-21179

📔 Objective

Centralizes the logic for determining whether an organization user is enrolled in account recovery by introducing two methods on OrganizationUser:

  • Static IsValidResetPasswordKey(string?)
  • Instance IsEnrolledInAccountRecovery()

This removes scattered string.IsNullOrEmpty / string.IsNullOrWhiteSpace checks across the codebase and replaces them with a single consistent implementation.
It also fixes an inconsistency where some call sites treated whitespace-only keys as valid (IsNullOrEmpty) while others did not (IsNullOrWhiteSpace).

… and add unit test for empty or whitespace reset password key handling
…keys and add unit tests for filtering out invalid keys
…ment and adjust tests for whitespace reset password keys
…keys, including filtering out whitespace-only keys, and add corresponding unit tests for validation logic.
…whitespace-only test cases for account recovery key validation.
…hod for ResetPasswordEnrolled status and update corresponding unit test for clarity.
…rganizationUser's validation method for ResetPasswordKey, ensuring consistent validation across the application. Add unit tests for OrganizationUser to verify key validation logic.
@r-tome r-tome added the ai-review Request a Claude code review label Feb 12, 2026
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Feb 12, 2026

Claude finished @r-tome's task in 3m 19s —— View job


Pull Request Review: PM-21179 Add interface to check if user is enrolled in account recovery

Summary

This PR centralizes the validation of reset password keys into the OrganizationUser entity, replacing scattered string.IsNullOrEmpty and string.IsNullOrWhiteSpace calls across the codebase with two new methods:

  • OrganizationUser.IsValidResetPasswordKey(string?) -- static method for validating reset password keys from any source
  • OrganizationUser.IsEnrolledInAccountRecovery() -- instance method for checking enrollment status on an OrganizationUser entity

Assessment

Area Status
Security No concerns -- this is a security improvement; whitespace-only keys are now consistently rejected
Correctness No issues found
Breaking Changes None
Performance No impact
Test Coverage Thorough -- all modified components have corresponding test additions

Key Observations

Behavioral consistency fix: Several call sites previously used string.IsNullOrEmpty (which accepts whitespace-only strings as valid), while others used string.IsNullOrWhiteSpace. The centralized method standardizes on IsNullOrWhiteSpace, which is the correct behavior -- a whitespace-only string should never be considered a valid reset password key. The affected call sites are in OrganizationUserResponseModel, AdminRecoverAccountCommand, OrganizationUserUserDetailsQuery, UserService, and UserDecryptionOptionsBuilder.

Complete migration verified: No remaining instances of the old string.IsNullOrEmpty(*.ResetPasswordKey) or string.IsNullOrWhiteSpace(*.ResetPasswordKey) patterns exist in the source code. All validation checks have been migrated to use the new centralized methods.

Client compatibility properly handled: The OrganizationUserRotationValidator correctly maintains backward compatibility with a known client-side bug (PM-31001) where clients send "" as a reset password key during rotation. The validation only checks for null (not empty/whitespace) on incoming rotation keys, with a clear TODO comment documenting the intended migration path once PM-31001 is resolved on the client side. This addresses the feedback from the existing review thread.

Clean design: The static method appropriately handles validation for DTOs and request models that carry a ResetPasswordKey property but are not OrganizationUser entities, while the instance method provides a domain-expressive way to check enrollment status on actual entity instances.

Incremental Changes Review (post-initial feedback)

The following commits were added after the initial review:

  • 716b78f1 -- Addressed @quexten's feedback about the client-side bug (PM-31001). Changed OrganizationUserRotationValidator to check only for null on incoming rotation keys instead of using IsValidResetPasswordKey(), preserving backward compatibility. Added well-documented TODO comments and updated tests accordingly. This change is correct.
  • beb9eafd -- Trivial BOM character removal from test file header.
  • Two merge commits from main (no conflicts in PR-relevant code).

Verdict

Approve -- This is a well-structured refactoring that improves consistency, fixes a subtle validation gap (whitespace-only keys), and provides comprehensive test coverage. The incremental changes properly address the client compatibility concern raised during review. No issues found.

@codecov
Copy link
Copy Markdown

codecov Bot commented Feb 12, 2026

Codecov Report

❌ Patch coverage is 76.47059% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 60.75%. Comparing base (9eccb00) to head (8dfe4af).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
...Console/Controllers/OrganizationUsersController.cs 50.00% 0 Missing and 1 partial ⚠️
...nse/Organizations/OrganizationUserResponseModel.cs 50.00% 1 Missing ⚠️
...anizationUsers/OrganizationUserUserDetailsQuery.cs 50.00% 0 Missing and 1 partial ⚠️
.../Reports/ReportFeatures/MemberAccessReportQuery.cs 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #6993      +/-   ##
==========================================
+ Coverage   60.72%   60.75%   +0.03%     
==========================================
  Files        2013     2013              
  Lines       88125    88129       +4     
  Branches     7848     7848              
==========================================
+ Hits        53512    53545      +33     
+ Misses      32712    32679      -33     
- Partials     1901     1905       +4     

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

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Feb 12, 2026

Logo
Checkmarx One – Scan Summary & Details8644088c-3e7e-43ff-89d1-3c2b21f4edc3

Great job! No new security vulnerabilities introduced in this pull request

@r-tome r-tome marked this pull request as ready for review February 12, 2026 11:45
@r-tome r-tome requested review from a team as code owners February 12, 2026 11:45
Copy link
Copy Markdown
Contributor

@quexten quexten left a comment

Choose a reason for hiding this comment

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

Looks like this may re-introduce a regression to key-rotation, since clients are still sending empty strings. Your approach is the correct one, but is blocked by this client mis-behavior.

Comment thread src/Api/KeyManagement/Validators/OrganizationUserRotationValidator.cs Outdated
…d keys and adjust tests for client-side bug. Add comments for future migration after resolving PM-31001.
@r-tome r-tome requested a review from quexten February 13, 2026 15:32
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.

👍 Auth changes are minimal

…ccount-recovery

# Conflicts:
#	test/Core.Test/Services/UserServiceTests.cs
@r-tome r-tome removed the ai-review Request a Claude code review label Feb 16, 2026
@r-tome r-tome removed the needs-qa label Feb 24, 2026
@sonarqubecloud
Copy link
Copy Markdown

@r-tome r-tome merged commit ef4f4e3 into main Feb 24, 2026
45 of 46 checks passed
@r-tome r-tome deleted the ac/pm-21179/interface-to-check-enrolled-in-account-recovery branch February 24, 2026 14:16
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.

5 participants