* refactor: enhance null safety in InviteOrganization and related models
- Updated InviteOrganization properties to be nullable for improved null safety.
- Refactored InviteOrganizationUsersRequest to use primary constructor syntax.
- Added null checks for Plan in validation logic to prevent errors when the organization plan is unavailable.
- Adjusted PasswordManagerSubscriptionUpdate to handle nullable PasswordManagerPlan.
- Ensured consistent handling of nullable properties across various validation classes.
* refactor: update organization handling in SCIM user models and commands
- Replaced references to InviteOrganization with Organization in SCIM user request models and related commands for consistency.
- Enhanced null safety by ensuring proper handling of organization properties across various components.
- Updated tests to reflect changes in organization handling and ensure functionality remains intact.
* test: add unit tests for SCIM organization user invitation scenarios
- Implemented tests for inviting SCIM organization users under different conditions: when self-hosted with a null plan and when not self-hosted with a null plan.
- Ensured proper validation and response handling for both success and failure cases.
- Updated dependencies and mock setups to reflect the new test scenarios.
feat: Add WebAuthn Cache
- Add IWebAuthnChallengeCacheProvider with distributed cache implementation for storing WebAuthn Challenges
- Inject the cache provider into AssertWebAuthnLoginCredentialCommand and WebAuthnGrantValidator so challenges can be stored
- Use a static token lifetime for WebAuthnLoginAssertionOptionsTokenable and enable nullable reference types on the tokenable
- Add unit tests for the cache provider, the assertion command, and the WebAuthn controller; add Identity integration and unit tests for WebAuthnGrantValidator with a FakeWebAuthnAuthenticator helper
* Add UseInviteLinks to Organization SQL schema and views
* Add Migrator scripts for UseInviteLinks column and data migration
* Add EF migrations for UseInviteLinks on Organization
* Wire UseInviteLinks through organization domain and repositories
* Add HasInviteLinks plan support and UseInviteLinks license handling
* Expose UseInviteLinks and HasInviteLinks on organization and plan API models
* Update tests for UseInviteLinks and invite-links plan feature
* Update migration script with missing update to Organization_ReadManyByIds
* Move UseInviteLinks column after ExemptFromBillingAutomation
* Bump date on migration scripts
* Add optional RevisionDate param to group sprocs
When provided, bump Group.RevisionDate on affected groups during
membership and collection-access changes. Defaults to NULL for
backward compatibility.
* Add migration for group RevisionDate bump
* Add revisionDate param to group repository methods
Update IGroupRepository and IOrganizationUserRepository interfaces
and their Dapper and Entity Framework implementations.
* Pass revisionDate through business logic to repos
Inject TimeProvider into commands, services, and controllers to
supply the timestamp when modifying group membership.
* Update unit tests for group revisionDate param
* Update and add integration tests for group revision
* Enhance IGroupRepository and IOrganizationUserRepository with detailed XML documentation
* Bump date on migration script
* Bump date on migration script
* [PM-34813] fix system coupons regression
refactor customer setup class to split system coupons from discount coupons so that they can be applied systematically
* [PM-34213] Log event when attachment is created via delayed upload
* [PM-34213] Add tests for attachment created event logging
* [PM-34213] Move Cipher_AttachmentCreated event log to authenticated attachment creation callers
* Add changes for unpaid subscriptions
* Remove the unpaid status and update the test
* Add changes for premium user
* Fix the lint error
* remove subscriptionInfo and use subscription
* Fix file encoding issue
* SubscriptionLicenseValidator.cs is deleted
* Fix the lint error
Deprecating V1 User Asymmetric Key information in favor of new V2 User Asymmetric Account Keys structure.
This PR adds support for the new AccountKeys structure while maintaining support for the legacy UserAsymmetricKey-based flow. Validation is updated to check either AccountKeys or UserAsymmetricKeys are updated. Tests include modeling for both scenarios.
- Standardize validation on `RegisterFinishRequestModel` so Auth and Unlock data are both required and consistently validated
- Add salt validation to both unlock and authentication data
- Enforce that Auth and Unlock data contain matching values
- Keep validation backwards compatible with older clients
- Add and update unit tests covering the new validation rules and error messages
Co-authored-by: Ike Kottlowski <ikottlowski@bitwarden.com>
* PM-4517 - Add LastActivityDate to Device entity, interfaces, DTOs, and response models
Adds the LastActivityDate nullable DateTime property to the Device entity,
IDeviceRepository interface (BumpLastActivityDateByIdAsync and
BumpLastActivityDateByIdentifierAsync), DeviceAuthDetails DTO,
DeviceResponseModel, DeviceAuthRequestResponseModel, and the
DevicesLastActivityDate feature flag key in Constants.
* PM-4517 - Add BumpDeviceLastActivityDateCommand with distributed cache guard
Adds IBumpDeviceLastActivityDateCommand and IDeviceLastActivityCacheService
interfaces with their implementations. The cache service uses the persistent
keyed IDistributedCache (Cosmos DB in cloud, SQL Server in self-hosted) with
a 48h TTL to guard against redundant DB writes within the same calendar day.
Moves device DI registration into a consolidated AddDeviceServices() extension.
* PM-4517 - Add LastActivityDate SQL schema, stored procedures, and MSSQL migration
Adds LastActivityDate DATETIME2 column to the Device table. Updates Device_Create
and Device_Update stored procedures. Adds Device_BumpLastActivityDateById and
Device_BumpLastActivityDateByIdentifier stored procedures with a CAST AS DATE
guard as a fallback against redundant writes when the application-layer cache
is unavailable.
* PM-4517 - Implement LastActivityDate repository methods and EF migrations
Implements BumpLastActivityDateByIdAsync and BumpLastActivityDateByIdentifierAsync
in both Dapper (via stored procedures) and EF (via ExecuteUpdateAsync with a
date-level guard). Adds EF migrations for Postgres, SQLite, and MySQL.
* PM-4517 - Bump device LastActivityDate on login and refresh token
Wires IBumpDeviceLastActivityDateCommand into BaseRequestValidator (login path,
keyed on device.Id) and CustomTokenRequestValidator (refresh token path, keyed
on device identifier from subject claims). Both call sites are feature-flagged
behind DevicesLastActivityDate.
* PM-4517 - Move AddDeviceServices() to AddBaseServices alongside IDeviceService
Device services are not user features — co-locating them with IDeviceService
in AddBaseServices is more cohesive than nesting them inside AddUserServices.
* PM-4517 - Swallow transient LastActivityDate bump failures to prevent auth disruption
* PM-4517 - Fix DeviceAuthDetails Dapper constructor parameter order to match LastActivityDate column position
* PM-4517 - Add edge case tests for BumpDeviceLastActivityForRefreshAsync guard conditions
* PM-4517 - Add tests for BumpLastActivityDate flag-disabled, null-device, and happy-path cases
* PM-4517 - Add PM-34091 cleanup TODOs to all DevicesLastActivityDate feature flag sites
* PM-4517 - Refine PM-34091 cleanup TODOs and add missing feature flag disabled test for refresh path
* PM-4517 - Remove redundant LastActivityDate shadow property from DeviceAuthDetails
* PM-4517 - Use CultureInfo.InvariantCulture in date string formatting for CA1305
* PM-4517 - Make _bumpDeviceLastActivityDateCommand protected in base to remove duplicate field in derived class
* PM-4517 - Scope device last activity cache key by userId to prevent cross-user collisions
The Device table's unique constraint is (UserId, Identifier), not Identifier alone,
so two users can share the same device identifier (e.g. account switching in a browser).
Scoping the cache key to device:last-activity:{userId}:{identifier} ensures that a cache
hit for one user never suppresses a DB write for another.
Also adds userId to BumpByIdAsync signature and reorders params to be consistent with
BumpByIdentifierAsync(string identifier, Guid userId).
* PM-4517 - Widen try-catch in TryBumpDeviceLastActivityForRefreshAsync and add happy-path test
Renames BumpDeviceLastActivityForRefreshAsync to TryBumpDeviceLastActivityForRefreshAsync
to signal the swallow-on-error intent. Moves the try-catch to wrap the entire method body,
including GetSubjectId() which can throw InvalidOperationException, so no exception can
escape and disrupt token refresh. Also moves the XML doc comment to RecordActivityForInstallation
where it belongs, and adds a happy-path test verifying BumpByIdentifierAsync is called
with the correct identifier and userId.
* PM-4517 - Capture DateTime.UtcNow once in EF bump methods to ensure consistent timestamp
Avoids a minor inconsistency where the WHERE filter and SET clause could evaluate
DateTime.UtcNow at slightly different moments, aligning behavior with the SQL stored
procedures which use a single @RevisionDate parameter.
* PM-4517 - Preserve LastActivityDate on Device_Update when null to prevent regressions
Device_Update previously overwrote LastActivityDate unconditionally, meaning any unrelated
device update (push token rotation, trust changes, deactivation) could silently regress a
recently-bumped value. COALESCE preserves the existing DB value when NULL is passed, while
still allowing callers to set it in the same write by passing a non-NULL value. The EF
ReplaceAsync override applies the same semantics via IsModified = false. Integration test
added to cover the preserve-on-null behaviour across all DB providers.
* PM-4517 - Add docs
* PM-4517 - Adjust docs
* PM-4517 - Add test coverage for BumpLastActivityDateByIdentifierAsync
* PM-4517 - Per PR feedback, add docs on IDeviceLastActivityCacheService
* PM-4517 - Per PR feedback, adjust IBumpDeviceLastActivityDateCommand.BumpById to be bump by device instead b/c it has all what we need.
* PM-4517 - Per PR feedback, add tech debt ticket.
* PM-4517 - Rename BumpByIdentifierAsync to BumpByIdentifierAndUserIdAsync across the board.
* PM-4517 - Per PR feedback, adjust stored proc names to meet SQL style requirements
* PM-4517 - Replace COALESCE with CASE in Device_Update to prevent stale non-null LastActivityDate overwrites
* PM-4517 - Add EF repository feature parity for replace logic + test to ensure we don't run into this again.
* PM-4517 - Fix DB migration order after main merge.
* PM-4517 - Regenerate EF DB migrations
* PM-4517 - actually regenerate EF DB migrations
* PM-4517 - Add LastActivityDate to Device_ReadActiveWithPendingAuthRequestsByUserId and integration tests
* Initial pass of revocation reason
* 2'nd pass, with tests, of revocation reason
* separate migration concerns, begin using new bulk sprocs
* remove old RevokeManyByIdAsync in favor of RevokeManyAsync
* fix migrations order
* Adjust other missing sprocs
* begrudgingly formats file
* No longer drop now-deprecated sprocs
* Add more views to refresh
* re-adds stored procs
* formatting from restoration
* Fix naming
* Modify sproc file name to match name
* Added extended cache implementation for org ability.
* fixed up events
* Moved utilities to service class. Moved tests to integration tests - with specific endpoints tested. moved registration to ext method
* Remove pm-26462-milestone-3 flag from PricingClient
Simplify FamiliesAnnually2025 lookup to always return "families-2025".
Remove PreProcessFamiliesPreMigrationPlan deployment safeguard method
and its call sites. Remove unused IFeatureService constructor dependency.
* Remove pm-26462-milestone-3 flag from UpcomingInvoiceHandler.HandleForOrganizationAsync
Remove milestone3 variable and parameter from
AlignOrganizationSubscriptionConcernsAsync. Simplify guard clause
to only check plan type.
* Update PricingClientTests after pm-26462-milestone-3 removal
Remove IFeatureService from test setup. Delete tests for flag-disabled
safeguard behavior. Clean up remaining test names.
* Update UpcomingInvoiceHandlerTests after pm-26462-milestone-3 removal
Remove all feature flag mock setup lines for PM26462_Milestone_3.
Delete test methods that verified flag-disabled behavior.
* Merge GetPlan lookup key test regions into one
* secure SSRP protection for internal requests
* remove nullable enable
* explicitly handle redirect requests for SSRF
* track current uri in SsrfProtectionHandler. add followRedirects option in AddSsrfProtection
* preserve request method for 301 and 302 requests
* Migrate admin HttpClient usages to IHttpClientFactory
* add missing dep
* [PM-34866] Fix EnableAutomaticTaxAsync to update schedule phases
* Use test clock frozen time for phase filtering
* Expand test_clock on customer subscription fetches
* [PM-26043] refactored AddSecretsManagerSubscriptionCommand
move to billing, fix bug unable to add secrets manager to legacy plan by moving all validation into command and skipping the disabled check
* forgot BillingCommandResult is being deprecated
* cleanup
* add unit test coverage
* one more test
* pr feedback
* forgot to fix in actual code file
* Fix UpdateCollectionCommand to set RevisionDate using TimeProvider and update corresponding tests. Adjust tests to verify correct RevisionDate assignment during collection updates.
* Enhance BulkAddCollectionAccessCommand to include revision date in access updates. Update ICollectionRepository and its implementations to accept revision date parameter. Modify stored procedure to update collection revision dates accordingly. Add tests to verify correct behavior of access creation and revision date updates.
* Update GroupRepository and stored procedures to bump RevisionDate for affected collections during group creation and updates. Enhance integration tests to verify that collection revision dates are correctly updated when groups are created or modified.
* Implement revision date updates for affected collections in OrganizationUserRepository and related stored procedures. Add integration tests to ensure revision dates are correctly bumped during organization user creation and updates.
* Update database migration script
* Update migration script summary
* Refactor OrganizationUserReplaceTests to create collection first
* Refactor stored procedures to use Common Table Expressions (CTEs) for updating RevisionDate of affected collections. This change improves readability and maintainability by consolidating the logic for identifying affected collections in Group_UpdateWithCollections and OrganizationUser_UpdateWithCollections procedures.
* Enhance OrganizationUser_CreateManyWithCollectionsAndGroups stored procedure to accept RevisionDate parameter for updating affected collections. Update OrganizationUserRepository to utilize the provided RevisionDate when available, ensuring accurate revision date management during organization user operations.
* Refactor OrganizationUser_CreateManyWithCollectionsGroups and migration script to utilize temporary table for CollectionUser data insertion. This change improves performance and maintains consistency in updating RevisionDate for affected collections.
* Refactor OrganizationUserRepository to consistently use RevisionDate from created OrganizationUsers when updating affected collections. This change enhances the accuracy of revision date management across the repository.
* Refactor tests to ensure consistent handling of RevisionDate across Group and Collection repositories. Update assertions to compare RevisionDate directly, improving accuracy in revision date management during tests.
* Restore BOM in Group_UpdateWithCollections and OrganizationUser_UpdateWithCollections
* Refactor GroupRepository and OrganizationUserRepository to improve handling of RevisionDate. Updated collection filtering logic to use HashSet for efficiency and ensured that affected collections are filtered by OrganizationId, enhancing accuracy in revision date management.
* Bump migration script date
* Remove internal set from RevisionDate on Group and OrganizationUser
The Dapper repositories use a System.Text.Json serialize/deserialize
round-trip to build *WithCollections objects. System.Text.Json silently
skips properties with non-public setters, so RevisionDate was reverting
to DateTime.UtcNow instead of preserving the value set in C#.
* Refactor OrganizationUser_CreateManyWithCollectionsGroups and migration script to improve the logic for updating RevisionDate. The update now uses INNER JOINs to ensure accurate filtering of collections based on OrganizationId and CollectionUser data, enhancing the precision of revision date management.
* Fix sprocs styling
* Added early return to OrganizationUserRepository.CreateManyAsync if the supplied parameter is empty
* Refactor organization user confirmation logic by removing direct feature flag checks. Updated related commands and tests to utilize policy requirements instead of feature service checks for automatic user confirmation. Cleaned up organization form view by simplifying checkbox rendering for automatic user confirmation.
* Refactor ProviderService to remove feature service dependency for automatic user confirmation. Updated logic to streamline policy requirement checks and cleaned up related tests by removing unnecessary feature flag assertions.
* Enhance tests for automatic user confirmation policy requirements. Updated multiple test classes to include checks for `AutomaticUserConfirmationPolicyRequirement`, ensuring no auto-confirm restrictions are applied by default. Refactored related assertions in `AcceptOrgUserCommandTests`, `ConfirmOrganizationUserCommandTests`, `RestoreOrganizationUserCommandTests`, and others to streamline compliance validation logic.
* Enhance tests for automatic user confirmation policy across multiple test classes. Added checks for `AutomaticUserConfirmationPolicyRequirement` in `ConfirmOrganizationUserCommandTests`, `RestoreOrganizationUserCommandTests`, and `SelfHostedOrganizationSignUpCommandTests`, ensuring compliance validation logic is streamlined and consistent. Updated assertions to reflect new policy requirements.
* Implement mock for AutomaticUserConfirmationPolicyRequirement in ProviderServiceTests to enhance test coverage for user confirmation policies.
* Update ProviderServiceTests to include mocks for AutomaticUserConfirmationPolicyRequirement, enhancing test coverage for user acceptance scenarios.
* Refactor test method names in EmergencyAccessServiceTests for clarity by removing feature flag references, improving readability and maintainability of the test suite.
* fix(refactor): [PM-34246] Rename Set Password to Finalize Onboarding - Initial set of renames take two.
* fix(refactor): [PM-34246] Rename Set Password to Finalize Onboarding - Updated function name.
* fix(refactor): [PM-34246] Rename Set Password to Finalize Onboarding - Fixed test.
* fix(refactor): [PM-34246] Rename Set Password to Finalize Onboarding - Unborked tests.
* fix(refactor): [PM-34246] Rename Set Password to Finalize Onboarding - Changed test names.
* Remove deprecated ISavePolicyCommand interface and SavePolicyCommand implementation along with associated tests
* Refactor policy validation: remove IPolicyValidator interface and related implementations. Update PolicyServiceCollectionExtensions to eliminate deprecated methods. Adjust policy validator classes to remove IPolicyValidator dependency and streamline validation methods.
* Remove IPostSavePolicySideEffect interface and its implementation from the policy validation framework.
* Rename VNextSavePolicyCommand to SavePolicyCommand
* Continue renaming VNextSavePolicyCommand
* Refactor policy validation tests to use SavePolicyModel in ValidateAsync and side effect methods
* Refactor policy validators to directly use PolicyUpdate from SavePolicyModel in validation and side effect methods, improving code clarity and reducing method complexity.
* Rename test methods in PoliciesControllerTests and VerifyOrganizationDomainCommandTests to better reflect their functionality, enhancing clarity and consistency across the test suite.
* Refactor OrganizationUserNotificationPolicyValidator by removing unused methods and simplifying the implementation. Update corresponding tests to reflect these changes.
* Remove unnecessary nullable enable directives from policy validator files and update using statements for consistency.
* Rename policy validators to handlers
* dotnet format
When a subscription has an active schedule during the ~15-day window before
renewal, the invoice preview for tax estimation was built with the new price
but without the Phase 2 discount coupon. This caused the estimated tax on the
subscription page to be higher than what Stripe would actually charge.
Pass the coupon ID from the schedule's Phase 2 discount through to
EstimatePremiumTaxAsync so it is included in the InvoiceCreatePreviewOptions.