1
0
mirror of https://github.com/bitwarden/server.git synced 2025-06-13 06:20:48 -05:00

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

This commit is contained in:
Rui Tome 2025-05-23 14:19:11 +01:00
parent 705bccae10
commit 2e3056fc2a
No known key found for this signature in database
GPG Key ID: 526239D96A8EC066
3 changed files with 25 additions and 18 deletions

View File

@ -28,13 +28,15 @@ public class RequireTwoFactorPolicyRequirement : IPolicyRequirement
_policyDetails.Any(p => p.OrganizationId == organizationId); _policyDetails.Any(p => p.OrganizationId == organizationId);
/// <summary> /// <summary>
/// Gets the active two-factor authentication policies for active memberships. /// Returns tuples of (OrganizationId, OrganizationUserId) for active memberships where two-factor authentication is required.
/// Users should be revoked from these organizations if they disable all 2FA methods.
/// </summary> /// </summary>
/// <returns>The active two-factor authentication policies for active memberships.</returns> public IEnumerable<(Guid OrganizationId, Guid OrganizationUserId)> OrganizationsRequiringTwoFactor =>
public IEnumerable<PolicyDetails> TwoFactorPoliciesForActiveMemberships => _policyDetails
_policyDetails.Where(p => p.OrganizationUserStatus is .Where(p => p.OrganizationUserStatus is
OrganizationUserStatusType.Accepted or OrganizationUserStatusType.Accepted or
OrganizationUserStatusType.Confirmed); OrganizationUserStatusType.Confirmed)
.Select(p => (p.OrganizationId, p.OrganizationUserId));
} }
public class RequireTwoFactorPolicyRequirementFactory : BasePolicyRequirementFactory<RequireTwoFactorPolicyRequirement> public class RequireTwoFactorPolicyRequirementFactory : BasePolicyRequirementFactory<RequireTwoFactorPolicyRequirement>

View File

@ -1403,13 +1403,13 @@ public class UserService : UserManager<User>, IUserService, IDisposable
{ {
var requirement = await _policyRequirementQuery.GetAsync<RequireTwoFactorPolicyRequirement>(user.Id); var requirement = await _policyRequirementQuery.GetAsync<RequireTwoFactorPolicyRequirement>(user.Id);
var removeOrgUserTasks = requirement.TwoFactorPoliciesForActiveMemberships.Select(async p => var removeOrgUserTasks = requirement.OrganizationsRequiringTwoFactor.Select(async o =>
{ {
var organization = await _organizationRepository.GetByIdAsync(p.OrganizationId); var organization = await _organizationRepository.GetByIdAsync(o.OrganizationId);
await _revokeNonCompliantOrganizationUserCommand.RevokeNonCompliantOrganizationUsersAsync( await _revokeNonCompliantOrganizationUserCommand.RevokeNonCompliantOrganizationUsersAsync(
new RevokeOrganizationUsersRequest( new RevokeOrganizationUsersRequest(
p.OrganizationId, o.OrganizationId,
[new OrganizationUserUserDetails { Id = p.OrganizationUserId, OrganizationId = p.OrganizationId }], [new OrganizationUserUserDetails { Id = o.OrganizationUserId, OrganizationId = o.OrganizationId }],
new SystemUser(EventSystemUser.TwoFactorDisabled))); new SystemUser(EventSystemUser.TwoFactorDisabled)));
await _mailService.SendOrganizationUserRevokedForTwoFactorPolicyEmailAsync(organization.DisplayName(), user.Email); await _mailService.SendOrganizationUserRevokedForTwoFactorPolicyEmailAsync(organization.DisplayName(), user.Email);
}).ToArray(); }).ToArray();

View File

@ -59,17 +59,18 @@ public class RequireTwoFactorPolicyRequirementFactoryTests
} }
[Theory, BitAutoData] [Theory, BitAutoData]
public void TwoFactorPoliciesForActiveMemberships_WithNoPolicies_ReturnsEmptyCollection( public void OrganizationsRequiringTwoFactor_WithNoPolicies_ReturnsEmptyCollection(
SutProvider<RequireTwoFactorPolicyRequirementFactory> sutProvider) SutProvider<RequireTwoFactorPolicyRequirementFactory> sutProvider)
{ {
var actual = sutProvider.Sut.Create([]); var actual = sutProvider.Sut.Create([]);
Assert.Empty(actual.TwoFactorPoliciesForActiveMemberships); Assert.Empty(actual.OrganizationsRequiringTwoFactor);
} }
[Theory, BitAutoData] [Theory, BitAutoData]
public void TwoFactorPoliciesForActiveMemberships_WithMultiplePolicies_ReturnsActiveMemberships( public void OrganizationsRequiringTwoFactor_WithMultiplePolicies_ReturnsActiveMemberships(
Guid orgId1, Guid orgId2, Guid orgId3, Guid orgId4, Guid orgId1, Guid orgUserId1, Guid orgId2, Guid orgUserId2,
Guid orgId3, Guid orgUserId3, Guid orgId4, Guid orgUserId4,
SutProvider<RequireTwoFactorPolicyRequirementFactory> sutProvider) SutProvider<RequireTwoFactorPolicyRequirementFactory> sutProvider)
{ {
var policies = new[] var policies = new[]
@ -77,24 +78,28 @@ public class RequireTwoFactorPolicyRequirementFactoryTests
new PolicyDetails new PolicyDetails
{ {
OrganizationId = orgId1, OrganizationId = orgId1,
OrganizationUserId = orgUserId1,
PolicyType = PolicyType.TwoFactorAuthentication, PolicyType = PolicyType.TwoFactorAuthentication,
OrganizationUserStatus = OrganizationUserStatusType.Accepted OrganizationUserStatus = OrganizationUserStatusType.Accepted
}, },
new PolicyDetails new PolicyDetails
{ {
OrganizationId = orgId2, OrganizationId = orgId2,
OrganizationUserId = orgUserId2,
PolicyType = PolicyType.TwoFactorAuthentication, PolicyType = PolicyType.TwoFactorAuthentication,
OrganizationUserStatus = OrganizationUserStatusType.Confirmed OrganizationUserStatus = OrganizationUserStatusType.Confirmed
}, },
new PolicyDetails new PolicyDetails
{ {
OrganizationId = orgId3, OrganizationId = orgId3,
OrganizationUserId = orgUserId3,
PolicyType = PolicyType.TwoFactorAuthentication, PolicyType = PolicyType.TwoFactorAuthentication,
OrganizationUserStatus = OrganizationUserStatusType.Invited OrganizationUserStatus = OrganizationUserStatusType.Invited
}, },
new PolicyDetails new PolicyDetails
{ {
OrganizationId = orgId4, OrganizationId = orgId4,
OrganizationUserId = orgUserId4,
PolicyType = PolicyType.TwoFactorAuthentication, PolicyType = PolicyType.TwoFactorAuthentication,
OrganizationUserStatus = OrganizationUserStatusType.Revoked OrganizationUserStatus = OrganizationUserStatusType.Revoked
} }
@ -102,11 +107,11 @@ public class RequireTwoFactorPolicyRequirementFactoryTests
var actual = sutProvider.Sut.Create(policies); var actual = sutProvider.Sut.Create(policies);
var result = actual.TwoFactorPoliciesForActiveMemberships.ToList(); var result = actual.OrganizationsRequiringTwoFactor.ToList();
Assert.Equal(2, result.Count); Assert.Equal(2, result.Count);
Assert.Contains(result, p => p.OrganizationId == orgId1); Assert.Contains(result, p => p.OrganizationId == orgId1 && p.OrganizationUserId == orgUserId1);
Assert.Contains(result, p => p.OrganizationId == orgId2); Assert.Contains(result, p => p.OrganizationId == orgId2 && p.OrganizationUserId == orgUserId2);
Assert.DoesNotContain(result, p => p.OrganizationId == orgId3); Assert.DoesNotContain(result, p => p.OrganizationId == orgId3 && p.OrganizationUserId == orgUserId3);
Assert.DoesNotContain(result, p => p.OrganizationId == orgId4); Assert.DoesNotContain(result, p => p.OrganizationId == orgId4 && p.OrganizationUserId == orgUserId4);
} }
} }