1
0
mirror of https://github.com/bitwarden/server.git synced 2025-07-01 08:02:49 -05:00

[PM-18238] Add RequireTwoFactorPolicyRequirement (#5840)

* Add RequireTwoFactorPolicyRequirement and its factory with unit tests

* Implemented RequireTwoFactorPolicyRequirement to enforce two-factor authentication policies.
* Created RequireTwoFactorPolicyRequirementFactory to generate policy requirements based on user status.
* Added unit tests for the factory to validate behavior with various user statuses and policy details.

* Enhance AcceptOrgUserCommand to use IPolicyRequirementQuery for two-factor authentication validation

* Update ConfirmOrganizationUserCommand to use RequireTwoFactorPolicyRequirement to check for 2FA requirement

* Implement CanAcceptInvitation and CanBeConfirmed methods in RequireTwoFactorPolicyRequirement; update tests to reflect new logic for two-factor authentication policy handling.

* Refactor AcceptOrgUserCommand to enforce two-factor authentication policy based on feature flag; update validation logic and tests accordingly.

* Enhance ConfirmOrganizationUserCommand to validate two-factor authentication policy based on feature flag; refactor validation logic and update related tests for improved policy handling.

* Remove unused method and its dependencies from OrganizationService.

* Implement CanBeRestored method in RequireTwoFactorPolicyRequirement to determine user restoration eligibility based on two-factor authentication status; add corresponding unit tests for various scenarios.

* Update RestoreOrganizationUserCommand to use IPolicyRequirementQuery for two-factor authentication policies checks

* Remove redundant vNext tests

* Add TwoFactorPoliciesForActiveMemberships property to RequireTwoFactorPolicyRequirement and corresponding unit tests for policy retrieval based on user status

* Refactor UserService to integrate IPolicyRequirementQuery for two-factor authentication policy checks

* Add XML documentation for TwoFactorPoliciesForActiveMemberships property in RequireTwoFactorPolicyRequirement to clarify its purpose and return value.

* Add exception documentation for ValidateTwoFactorAuthenticationPolicyAsync method in ConfirmOrganizationUserCommand to clarify error handling for users without two-step login enabled.

* Update comments in AcceptOrgUserCommand and ConfirmOrganizationUserCommand to clarify handling of two-step login and 2FA policy checks.

* Add RequireTwoFactorPolicyRequirementFactory to PolicyServiceCollectionExtensions

* Refactor two-factor authentication policy checks in AcceptOrgUserCommand and ConfirmOrganizationUserCommand to streamline validation logic and improve clarity. Update RequireTwoFactorPolicyRequirement to provide a method for checking if two-factor authentication is required for an organization. Adjust related unit tests accordingly.

* Add PolicyRequirements namespace

* Update comments in AcceptOrgUserCommand and ConfirmOrganizationUserCommand to clarify two-factor authentication policy requirements and exception handling.

* Refactor RequireTwoFactorPolicyRequirement to return tuples of (OrganizationId, OrganizationUserId) for active memberships requiring two-factor authentication. Update UserService and related tests to reflect this change.

* Refactor AcceptOrgUserCommand: delegate feature flag check to the ValidateTwoFactorAuthenticationPolicyAsync method

* Skip policy check if two-step login is enabled for the user

* Refactor ConfirmOrganizationUserCommand to streamline two-factor authentication policy validation logic

* Refactor AcceptOrgUserCommand to simplify two-factor authentication check by removing intermediate variable

* Update documentation in RequireTwoFactorPolicyRequirement to clarify the purpose of the IsTwoFactorRequiredForOrganization

* Refactor AcceptOrgUserCommandTests to remove redundant two-factor authentication checks and simplify test setup

* Refactor AcceptOrgUserCommand and ConfirmOrganizationUserCommand to streamline two-factor authentication checks by removing redundant conditions and simplifying logic flow.

* Rename removeOrgUserTasks variable in UserService

* Refactor RestoreOrganizationUserCommand to simplify two-factor authentication compliance checks by consolidating logic into a new method, IsTwoFactorRequiredForOrganizationAsync.

* Remove outdated two-factor authentication validation documentation from AcceptOrgUserCommand

* Invert two-factor compliance check in RestoreOrganizationUserCommand to ensure correct validation of organization user policies.

* Refactor UserService to enhance two-factor compliance checks by optimizing organization retrieval and logging when no organizations require two-factor authentication.
This commit is contained in:
Rui Tomé
2025-05-29 07:40:30 +01:00
committed by GitHub
parent c7b0c30370
commit 829ce86066
12 changed files with 852 additions and 188 deletions

View File

@ -0,0 +1,117 @@
using Bit.Core.AdminConsole.Enums;
using Bit.Core.AdminConsole.Models.Data.Organizations.Policies;
using Bit.Core.AdminConsole.OrganizationFeatures.Policies.PolicyRequirements;
using Bit.Core.Enums;
using Bit.Test.Common.AutoFixture;
using Bit.Test.Common.AutoFixture.Attributes;
using Xunit;
namespace Bit.Core.Test.AdminConsole.OrganizationFeatures.Policies.PolicyRequirements;
[SutProviderCustomize]
public class RequireTwoFactorPolicyRequirementFactoryTests
{
[Theory]
[BitAutoData]
public void IsTwoFactorRequiredForOrganization_WithNoPolicies_ReturnsFalse(
Guid organizationId,
SutProvider<RequireTwoFactorPolicyRequirementFactory> sutProvider)
{
var actual = sutProvider.Sut.Create([]);
Assert.False(actual.IsTwoFactorRequiredForOrganization(organizationId));
}
[Theory]
[BitAutoData]
public void IsTwoFactorRequiredForOrganization_WithOrganizationPolicy_ReturnsTrue(
Guid organizationId,
SutProvider<RequireTwoFactorPolicyRequirementFactory> sutProvider)
{
var actual = sutProvider.Sut.Create(
[
new PolicyDetails
{
OrganizationId = organizationId,
PolicyType = PolicyType.TwoFactorAuthentication,
}
]);
Assert.True(actual.IsTwoFactorRequiredForOrganization(organizationId));
}
[Theory]
[BitAutoData]
public void IsTwoFactorRequiredForOrganization_WithOtherOrganizationPolicy_ReturnsFalse(
Guid organizationId,
SutProvider<RequireTwoFactorPolicyRequirementFactory> sutProvider)
{
var actual = sutProvider.Sut.Create(
[
new PolicyDetails
{
OrganizationId = Guid.NewGuid(),
PolicyType = PolicyType.TwoFactorAuthentication,
},
]);
Assert.False(actual.IsTwoFactorRequiredForOrganization(organizationId));
}
[Theory, BitAutoData]
public void OrganizationsRequiringTwoFactor_WithNoPolicies_ReturnsEmptyCollection(
SutProvider<RequireTwoFactorPolicyRequirementFactory> sutProvider)
{
var actual = sutProvider.Sut.Create([]);
Assert.Empty(actual.OrganizationsRequiringTwoFactor);
}
[Theory, BitAutoData]
public void OrganizationsRequiringTwoFactor_WithMultiplePolicies_ReturnsActiveMemberships(
Guid orgId1, Guid orgUserId1, Guid orgId2, Guid orgUserId2,
Guid orgId3, Guid orgUserId3, Guid orgId4, Guid orgUserId4,
SutProvider<RequireTwoFactorPolicyRequirementFactory> sutProvider)
{
var policies = new[]
{
new PolicyDetails
{
OrganizationId = orgId1,
OrganizationUserId = orgUserId1,
PolicyType = PolicyType.TwoFactorAuthentication,
OrganizationUserStatus = OrganizationUserStatusType.Accepted
},
new PolicyDetails
{
OrganizationId = orgId2,
OrganizationUserId = orgUserId2,
PolicyType = PolicyType.TwoFactorAuthentication,
OrganizationUserStatus = OrganizationUserStatusType.Confirmed
},
new PolicyDetails
{
OrganizationId = orgId3,
OrganizationUserId = orgUserId3,
PolicyType = PolicyType.TwoFactorAuthentication,
OrganizationUserStatus = OrganizationUserStatusType.Invited
},
new PolicyDetails
{
OrganizationId = orgId4,
OrganizationUserId = orgUserId4,
PolicyType = PolicyType.TwoFactorAuthentication,
OrganizationUserStatus = OrganizationUserStatusType.Revoked
}
};
var actual = sutProvider.Sut.Create(policies);
var result = actual.OrganizationsRequiringTwoFactor.ToList();
Assert.Equal(2, result.Count);
Assert.Contains(result, p => p.OrganizationId == orgId1 && p.OrganizationUserId == orgUserId1);
Assert.Contains(result, p => p.OrganizationId == orgId2 && p.OrganizationUserId == orgUserId2);
Assert.DoesNotContain(result, p => p.OrganizationId == orgId3 && p.OrganizationUserId == orgUserId3);
Assert.DoesNotContain(result, p => p.OrganizationId == orgId4 && p.OrganizationUserId == orgUserId4);
}
}