mirror of
https://github.com/bitwarden/server.git
synced 2025-05-22 12:04:27 -05:00
Add tests for RegisterUserCommand to validate two-factor authentication policy handling during organization invites. Implement scenarios for both enabled and disabled policies, ensuring correct behavior based on feature flags and organization requirements.
This commit is contained in:
parent
03b0dc04c4
commit
5c6c3506b5
@ -1,6 +1,8 @@
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using Bit.Core.AdminConsole.Entities;
|
using Bit.Core.AdminConsole.Entities;
|
||||||
using Bit.Core.AdminConsole.Enums;
|
using Bit.Core.AdminConsole.Enums;
|
||||||
|
using Bit.Core.AdminConsole.OrganizationFeatures.Policies;
|
||||||
|
using Bit.Core.AdminConsole.OrganizationFeatures.Policies.PolicyRequirements;
|
||||||
using Bit.Core.AdminConsole.Repositories;
|
using Bit.Core.AdminConsole.Repositories;
|
||||||
using Bit.Core.Auth.Entities;
|
using Bit.Core.Auth.Entities;
|
||||||
using Bit.Core.Auth.Enums;
|
using Bit.Core.Auth.Enums;
|
||||||
@ -686,5 +688,339 @@ public class RegisterUserCommandTests
|
|||||||
Assert.Equal("Open registration has been disabled by the system administrator.", result.Message);
|
Assert.Equal("Open registration has been disabled by the system administrator.", result.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[BitAutoData]
|
||||||
|
public async Task RegisterUserViaOrgInvite_TwoFactorPolicyEnabled_EnablesTwoFactor(
|
||||||
|
SutProvider<RegisterUserCommand> sutProvider, User user, string masterPasswordHash,
|
||||||
|
OrganizationUser orgUser, string orgInviteToken, Guid orgUserId, Policy twoFactorPolicy)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
user.ReferenceData = null;
|
||||||
|
user.TwoFactorProviders = null;
|
||||||
|
orgUser.Email = user.Email;
|
||||||
|
orgUser.Id = orgUserId;
|
||||||
|
|
||||||
|
var orgInviteTokenable = new OrgUserInviteTokenable(orgUser);
|
||||||
|
|
||||||
|
sutProvider.GetDependency<IDataProtectorTokenFactory<OrgUserInviteTokenable>>()
|
||||||
|
.TryUnprotect(orgInviteToken, out Arg.Any<OrgUserInviteTokenable>())
|
||||||
|
.Returns(callInfo =>
|
||||||
|
{
|
||||||
|
callInfo[1] = orgInviteTokenable;
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Setup FeatureFlag to be disabled
|
||||||
|
sutProvider.GetDependency<IFeatureService>()
|
||||||
|
.IsEnabled(Bit.Core.FeatureFlagKeys.PolicyRequirements)
|
||||||
|
.Returns(false);
|
||||||
|
|
||||||
|
// Mock OrganizationUserRepository to return the orgUser
|
||||||
|
sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||||
|
.GetByIdAsync(orgUserId)
|
||||||
|
.Returns(orgUser);
|
||||||
|
|
||||||
|
// Mock Policy to be enabled
|
||||||
|
twoFactorPolicy.Enabled = true;
|
||||||
|
sutProvider.GetDependency<IPolicyRepository>()
|
||||||
|
.GetByOrganizationIdTypeAsync(orgUser.OrganizationId, PolicyType.TwoFactorAuthentication)
|
||||||
|
.Returns(twoFactorPolicy);
|
||||||
|
|
||||||
|
sutProvider.GetDependency<IUserService>()
|
||||||
|
.CreateUserAsync(user, masterPasswordHash)
|
||||||
|
.Returns(IdentityResult.Success);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = await sutProvider.Sut.RegisterUserViaOrganizationInviteToken(user, masterPasswordHash, orgInviteToken, orgUserId);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(result.Succeeded);
|
||||||
|
|
||||||
|
// Verify OrganizationUserRepository was called
|
||||||
|
await sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||||
|
.Received(1)
|
||||||
|
.GetByIdAsync(orgUserId);
|
||||||
|
|
||||||
|
// Verify FeatureService was called with the correct flag
|
||||||
|
sutProvider.GetDependency<IFeatureService>()
|
||||||
|
.Received(1)
|
||||||
|
.IsEnabled(Bit.Core.FeatureFlagKeys.PolicyRequirements);
|
||||||
|
|
||||||
|
// Verify that the legacy policy repository was called
|
||||||
|
await sutProvider.GetDependency<IPolicyRepository>()
|
||||||
|
.Received(1)
|
||||||
|
.GetByOrganizationIdTypeAsync(orgUser.OrganizationId, PolicyType.TwoFactorAuthentication);
|
||||||
|
|
||||||
|
// Verify that two-factor authentication was enabled for the user
|
||||||
|
sutProvider.GetDependency<IUserService>()
|
||||||
|
.Received(1)
|
||||||
|
.SetTwoFactorProvider(user, TwoFactorProviderType.Email);
|
||||||
|
|
||||||
|
// Verify the two-factor providers were set correctly
|
||||||
|
var twoFactorProviders = new Dictionary<TwoFactorProviderType, TwoFactorProvider>
|
||||||
|
{
|
||||||
|
[TwoFactorProviderType.Email] = new TwoFactorProvider
|
||||||
|
{
|
||||||
|
MetaData = new Dictionary<string, object> { ["Email"] = user.Email.ToLowerInvariant() },
|
||||||
|
Enabled = true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var serializedTwoFactorProviders =
|
||||||
|
JsonHelpers.LegacySerialize(twoFactorProviders, JsonHelpers.LegacyEnumKeyResolver);
|
||||||
|
|
||||||
|
Assert.Equal(user.TwoFactorProviders, serializedTwoFactorProviders);
|
||||||
|
|
||||||
|
// Verify that OrganizationPolicyRequirementQuery was NOT called
|
||||||
|
await sutProvider.GetDependency<IOrganizationPolicyRequirementQuery>()
|
||||||
|
.DidNotReceive()
|
||||||
|
.GetAsync<OrganizationTwoFactorPolicyRequirement>(Arg.Any<Guid>());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[BitAutoData]
|
||||||
|
public async Task RegisterUserViaOrgInvite_TwoFactorPolicyDisabled_DoesNotEnableTwoFactor(
|
||||||
|
SutProvider<RegisterUserCommand> sutProvider, User user, string masterPasswordHash,
|
||||||
|
OrganizationUser orgUser, string orgInviteToken, Guid orgUserId, Policy twoFactorPolicy)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
user.ReferenceData = null;
|
||||||
|
user.TwoFactorProviders = null;
|
||||||
|
orgUser.Email = user.Email;
|
||||||
|
orgUser.Id = orgUserId;
|
||||||
|
|
||||||
|
var orgInviteTokenable = new OrgUserInviteTokenable(orgUser);
|
||||||
|
|
||||||
|
sutProvider.GetDependency<IDataProtectorTokenFactory<OrgUserInviteTokenable>>()
|
||||||
|
.TryUnprotect(orgInviteToken, out Arg.Any<OrgUserInviteTokenable>())
|
||||||
|
.Returns(callInfo =>
|
||||||
|
{
|
||||||
|
callInfo[1] = orgInviteTokenable;
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Setup FeatureFlag to be disabled
|
||||||
|
sutProvider.GetDependency<IFeatureService>()
|
||||||
|
.IsEnabled(Bit.Core.FeatureFlagKeys.PolicyRequirements)
|
||||||
|
.Returns(false);
|
||||||
|
|
||||||
|
// Mock OrganizationUserRepository to return the orgUser
|
||||||
|
sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||||
|
.GetByIdAsync(orgUserId)
|
||||||
|
.Returns(orgUser);
|
||||||
|
|
||||||
|
// Mock Policy to be disabled
|
||||||
|
twoFactorPolicy.Enabled = false;
|
||||||
|
sutProvider.GetDependency<IPolicyRepository>()
|
||||||
|
.GetByOrganizationIdTypeAsync(orgUser.OrganizationId, PolicyType.TwoFactorAuthentication)
|
||||||
|
.Returns(twoFactorPolicy);
|
||||||
|
|
||||||
|
sutProvider.GetDependency<IUserService>()
|
||||||
|
.CreateUserAsync(user, masterPasswordHash)
|
||||||
|
.Returns(IdentityResult.Success);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = await sutProvider.Sut.RegisterUserViaOrganizationInviteToken(user, masterPasswordHash, orgInviteToken, orgUserId);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(result.Succeeded);
|
||||||
|
|
||||||
|
// Verify OrganizationUserRepository was called
|
||||||
|
await sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||||
|
.Received(1)
|
||||||
|
.GetByIdAsync(orgUserId);
|
||||||
|
|
||||||
|
// Verify FeatureService was called with the correct flag
|
||||||
|
sutProvider.GetDependency<IFeatureService>()
|
||||||
|
.Received(1)
|
||||||
|
.IsEnabled(Bit.Core.FeatureFlagKeys.PolicyRequirements);
|
||||||
|
|
||||||
|
// Verify that the legacy policy repository was called
|
||||||
|
await sutProvider.GetDependency<IPolicyRepository>()
|
||||||
|
.Received(1)
|
||||||
|
.GetByOrganizationIdTypeAsync(orgUser.OrganizationId, PolicyType.TwoFactorAuthentication);
|
||||||
|
|
||||||
|
// Verify that two-factor authentication was NOT enabled for the user
|
||||||
|
sutProvider.GetDependency<IUserService>()
|
||||||
|
.DidNotReceive()
|
||||||
|
.SetTwoFactorProvider(Arg.Any<User>(), Arg.Any<TwoFactorProviderType>());
|
||||||
|
|
||||||
|
// Verify the two-factor providers were not set
|
||||||
|
Assert.Null(user.TwoFactorProviders);
|
||||||
|
|
||||||
|
// Verify that OrganizationPolicyRequirementQuery was NOT called
|
||||||
|
await sutProvider.GetDependency<IOrganizationPolicyRequirementQuery>()
|
||||||
|
.DidNotReceive()
|
||||||
|
.GetAsync<OrganizationTwoFactorPolicyRequirement>(Arg.Any<Guid>());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[BitAutoData]
|
||||||
|
public async Task RegisterUserViaOrgInvite_WithPolicyRequirements_TwoFactorPolicyRequired_EnablesTwoFactor(
|
||||||
|
SutProvider<RegisterUserCommand> sutProvider, User user, string masterPasswordHash,
|
||||||
|
OrganizationUser orgUser, string orgInviteToken, Guid orgUserId)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
user.ReferenceData = null;
|
||||||
|
user.TwoFactorProviders = null;
|
||||||
|
orgUser.Email = user.Email;
|
||||||
|
orgUser.Id = orgUserId;
|
||||||
|
|
||||||
|
var orgInviteTokenable = new OrgUserInviteTokenable(orgUser);
|
||||||
|
|
||||||
|
sutProvider.GetDependency<IDataProtectorTokenFactory<OrgUserInviteTokenable>>()
|
||||||
|
.TryUnprotect(orgInviteToken, out Arg.Any<OrgUserInviteTokenable>())
|
||||||
|
.Returns(callInfo =>
|
||||||
|
{
|
||||||
|
callInfo[1] = orgInviteTokenable;
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Setup FeatureFlag and OrganizationPolicyRequirementQuery
|
||||||
|
sutProvider.GetDependency<IFeatureService>()
|
||||||
|
.IsEnabled(Bit.Core.FeatureFlagKeys.PolicyRequirements)
|
||||||
|
.Returns(true);
|
||||||
|
|
||||||
|
// Mock OrganizationUserRepository to return the orgUser
|
||||||
|
sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||||
|
.GetByIdAsync(orgUserId)
|
||||||
|
.Returns(orgUser);
|
||||||
|
|
||||||
|
// Mock OrganizationTwoFactorPolicyRequirement to return IsRequired = true
|
||||||
|
var twoFactorPolicy = new Policy { Type = PolicyType.TwoFactorAuthentication, Enabled = true };
|
||||||
|
var twoFactorPolicyRequirement = new OrganizationTwoFactorPolicyRequirement(twoFactorPolicy);
|
||||||
|
|
||||||
|
sutProvider.GetDependency<IOrganizationPolicyRequirementQuery>()
|
||||||
|
.GetAsync<OrganizationTwoFactorPolicyRequirement>(orgUser.OrganizationId)
|
||||||
|
.Returns(twoFactorPolicyRequirement);
|
||||||
|
|
||||||
|
sutProvider.GetDependency<IUserService>()
|
||||||
|
.CreateUserAsync(user, masterPasswordHash)
|
||||||
|
.Returns(IdentityResult.Success);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = await sutProvider.Sut.RegisterUserViaOrganizationInviteToken(user, masterPasswordHash, orgInviteToken, orgUserId);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(result.Succeeded);
|
||||||
|
|
||||||
|
// Verify OrganizationUserRepository was called
|
||||||
|
await sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||||
|
.Received(1)
|
||||||
|
.GetByIdAsync(orgUserId);
|
||||||
|
|
||||||
|
// Verify FeatureService was called with the correct flag
|
||||||
|
sutProvider.GetDependency<IFeatureService>()
|
||||||
|
.Received(1)
|
||||||
|
.IsEnabled(Bit.Core.FeatureFlagKeys.PolicyRequirements);
|
||||||
|
|
||||||
|
// Verify that OrganizationPolicyRequirementQuery was called with the correct organization ID
|
||||||
|
await sutProvider.GetDependency<IOrganizationPolicyRequirementQuery>()
|
||||||
|
.Received(1)
|
||||||
|
.GetAsync<OrganizationTwoFactorPolicyRequirement>(orgUser.OrganizationId);
|
||||||
|
|
||||||
|
// Verify that two-factor authentication was enabled for the user
|
||||||
|
sutProvider.GetDependency<IUserService>()
|
||||||
|
.Received(1)
|
||||||
|
.SetTwoFactorProvider(user, TwoFactorProviderType.Email);
|
||||||
|
|
||||||
|
// Verify the two-factor providers were set correctly
|
||||||
|
var twoFactorProviders = new Dictionary<TwoFactorProviderType, TwoFactorProvider>
|
||||||
|
{
|
||||||
|
[TwoFactorProviderType.Email] = new TwoFactorProvider
|
||||||
|
{
|
||||||
|
MetaData = new Dictionary<string, object> { ["Email"] = user.Email.ToLowerInvariant() },
|
||||||
|
Enabled = true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var serializedTwoFactorProviders =
|
||||||
|
JsonHelpers.LegacySerialize(twoFactorProviders, JsonHelpers.LegacyEnumKeyResolver);
|
||||||
|
|
||||||
|
Assert.Equal(user.TwoFactorProviders, serializedTwoFactorProviders);
|
||||||
|
|
||||||
|
// Verify that the legacy policy repository was not called
|
||||||
|
await sutProvider.GetDependency<IPolicyRepository>()
|
||||||
|
.DidNotReceive()
|
||||||
|
.GetByOrganizationIdTypeAsync(Arg.Any<Guid>(), Arg.Any<PolicyType>());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[BitAutoData]
|
||||||
|
public async Task RegisterUserViaOrgInvite_WithPolicyRequirements_TwoFactorPolicyNotRequired_DoesNotEnableTwoFactor(
|
||||||
|
SutProvider<RegisterUserCommand> sutProvider, User user, string masterPasswordHash,
|
||||||
|
OrganizationUser orgUser, string orgInviteToken, Guid orgUserId)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
user.ReferenceData = null;
|
||||||
|
user.TwoFactorProviders = null;
|
||||||
|
orgUser.Email = user.Email;
|
||||||
|
orgUser.Id = orgUserId;
|
||||||
|
|
||||||
|
var orgInviteTokenable = new OrgUserInviteTokenable(orgUser);
|
||||||
|
|
||||||
|
sutProvider.GetDependency<IDataProtectorTokenFactory<OrgUserInviteTokenable>>()
|
||||||
|
.TryUnprotect(orgInviteToken, out Arg.Any<OrgUserInviteTokenable>())
|
||||||
|
.Returns(callInfo =>
|
||||||
|
{
|
||||||
|
callInfo[1] = orgInviteTokenable;
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Setup FeatureFlag and OrganizationPolicyRequirementQuery
|
||||||
|
sutProvider.GetDependency<IFeatureService>()
|
||||||
|
.IsEnabled(Bit.Core.FeatureFlagKeys.PolicyRequirements)
|
||||||
|
.Returns(true);
|
||||||
|
|
||||||
|
// Mock OrganizationUserRepository to return the orgUser
|
||||||
|
sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||||
|
.GetByIdAsync(orgUserId)
|
||||||
|
.Returns(orgUser);
|
||||||
|
|
||||||
|
// Mock OrganizationTwoFactorPolicyRequirement to return IsRequired = false
|
||||||
|
var twoFactorPolicy = new Policy { Type = PolicyType.TwoFactorAuthentication, Enabled = false };
|
||||||
|
var twoFactorPolicyRequirement = new OrganizationTwoFactorPolicyRequirement(twoFactorPolicy);
|
||||||
|
|
||||||
|
sutProvider.GetDependency<IOrganizationPolicyRequirementQuery>()
|
||||||
|
.GetAsync<OrganizationTwoFactorPolicyRequirement>(orgUser.OrganizationId)
|
||||||
|
.Returns(twoFactorPolicyRequirement);
|
||||||
|
|
||||||
|
sutProvider.GetDependency<IUserService>()
|
||||||
|
.CreateUserAsync(user, masterPasswordHash)
|
||||||
|
.Returns(IdentityResult.Success);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = await sutProvider.Sut.RegisterUserViaOrganizationInviteToken(user, masterPasswordHash, orgInviteToken, orgUserId);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(result.Succeeded);
|
||||||
|
|
||||||
|
// Verify OrganizationUserRepository was called
|
||||||
|
await sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||||
|
.Received(1)
|
||||||
|
.GetByIdAsync(orgUserId);
|
||||||
|
|
||||||
|
// Verify FeatureService was called with the correct flag
|
||||||
|
sutProvider.GetDependency<IFeatureService>()
|
||||||
|
.Received(1)
|
||||||
|
.IsEnabled(Bit.Core.FeatureFlagKeys.PolicyRequirements);
|
||||||
|
|
||||||
|
// Verify that OrganizationPolicyRequirementQuery was called with the correct organization ID
|
||||||
|
await sutProvider.GetDependency<IOrganizationPolicyRequirementQuery>()
|
||||||
|
.Received(1)
|
||||||
|
.GetAsync<OrganizationTwoFactorPolicyRequirement>(orgUser.OrganizationId);
|
||||||
|
|
||||||
|
// Verify that two-factor authentication was NOT enabled for the user
|
||||||
|
sutProvider.GetDependency<IUserService>()
|
||||||
|
.DidNotReceive()
|
||||||
|
.SetTwoFactorProvider(Arg.Any<User>(), Arg.Any<TwoFactorProviderType>());
|
||||||
|
|
||||||
|
// Verify the two-factor providers were not set
|
||||||
|
Assert.Null(user.TwoFactorProviders);
|
||||||
|
|
||||||
|
// Verify that the legacy policy repository was not called
|
||||||
|
await sutProvider.GetDependency<IPolicyRepository>()
|
||||||
|
.DidNotReceive()
|
||||||
|
.GetByOrganizationIdTypeAsync(Arg.Any<Guid>(), Arg.Any<PolicyType>());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user