mirror of
https://github.com/bitwarden/server
synced 2026-02-27 18:03:17 +00:00
PM-31847 Wire up UseMyItems organization ability (#7039)
Skip My Items creation if organization.UseMyItems is disabled
This commit is contained in:
@@ -0,0 +1,217 @@
|
||||
using Bit.Core.AdminConsole.Entities;
|
||||
using Bit.Core.AdminConsole.Enums;
|
||||
using Bit.Core.AdminConsole.Models.Data.Organizations.Policies;
|
||||
using Bit.Core.AdminConsole.Models.Data.OrganizationUsers;
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.AutoConfirmUser;
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.Policies;
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.Policies.PolicyRequirements;
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.Test.AutoFixture.OrganizationUserFixtures;
|
||||
using Bit.Test.Common.AutoFixture;
|
||||
using Bit.Test.Common.AutoFixture.Attributes;
|
||||
using NSubstitute;
|
||||
using Xunit;
|
||||
using static Bit.Core.AdminConsole.Utilities.v2.Validation.ValidationResultHelpers;
|
||||
|
||||
namespace Bit.Core.Test.AdminConsole.OrganizationFeatures.OrganizationUsers.AutoConfirmUser;
|
||||
|
||||
[SutProviderCustomize]
|
||||
public class AutomaticallyConfirmOrganizationUserCommandTests
|
||||
{
|
||||
[Theory, BitAutoData]
|
||||
public async Task AutomaticallyConfirmOrganizationUserAsync_UseMyItemsDisabled_DoesNotCreateCollection(
|
||||
Organization organization,
|
||||
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser orgUser,
|
||||
string key,
|
||||
string collectionName,
|
||||
SutProvider<AutomaticallyConfirmOrganizationUserCommand> sutProvider)
|
||||
{
|
||||
// Arrange
|
||||
organization.UseMyItems = false;
|
||||
orgUser.OrganizationId = organization.Id;
|
||||
|
||||
SetupRepositoryMocks(sutProvider, organization, orgUser);
|
||||
|
||||
// Mock positive validation result
|
||||
var validationRequest = new AutomaticallyConfirmOrganizationUserValidationRequest
|
||||
{
|
||||
OrganizationUserId = orgUser.Id,
|
||||
OrganizationId = organization.Id,
|
||||
Key = key,
|
||||
DefaultUserCollectionName = collectionName,
|
||||
PerformedBy = null,
|
||||
OrganizationUser = orgUser,
|
||||
Organization = organization
|
||||
};
|
||||
sutProvider.GetDependency<IAutomaticallyConfirmOrganizationUsersValidator>()
|
||||
.ValidateAsync(Arg.Any<AutomaticallyConfirmOrganizationUserValidationRequest>())
|
||||
.Returns(Valid(validationRequest));
|
||||
|
||||
// Mock enabled policy requirement
|
||||
var policyDetails = new PolicyDetails
|
||||
{
|
||||
OrganizationId = organization.Id,
|
||||
OrganizationUserId = orgUser.Id,
|
||||
IsProvider = false,
|
||||
OrganizationUserStatus = orgUser.Status,
|
||||
OrganizationUserType = orgUser.Type,
|
||||
PolicyType = PolicyType.OrganizationDataOwnership
|
||||
};
|
||||
sutProvider.GetDependency<IPolicyRequirementQuery>()
|
||||
.GetAsync<OrganizationDataOwnershipPolicyRequirement>(orgUser.UserId!.Value)
|
||||
.Returns(new OrganizationDataOwnershipPolicyRequirement(OrganizationDataOwnershipState.Enabled, [policyDetails]));
|
||||
|
||||
var request = new AutomaticallyConfirmOrganizationUserRequest
|
||||
{
|
||||
OrganizationUserId = orgUser.Id,
|
||||
OrganizationId = organization.Id,
|
||||
Key = key,
|
||||
DefaultUserCollectionName = collectionName,
|
||||
PerformedBy = null
|
||||
};
|
||||
|
||||
// Act
|
||||
await sutProvider.Sut.AutomaticallyConfirmOrganizationUserAsync(request);
|
||||
|
||||
// Assert - Collection repository should NOT be called
|
||||
await sutProvider.GetDependency<ICollectionRepository>()
|
||||
.DidNotReceive()
|
||||
.CreateDefaultCollectionsAsync(Arg.Any<Guid>(), Arg.Any<IEnumerable<Guid>>(), Arg.Any<string>());
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task AutomaticallyConfirmOrganizationUserAsync_UseMyItemsEnabled_CreatesCollection(
|
||||
Organization organization,
|
||||
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser orgUser,
|
||||
string key,
|
||||
string collectionName,
|
||||
SutProvider<AutomaticallyConfirmOrganizationUserCommand> sutProvider)
|
||||
{
|
||||
// Arrange
|
||||
organization.UseMyItems = true;
|
||||
orgUser.OrganizationId = organization.Id;
|
||||
|
||||
SetupRepositoryMocks(sutProvider, organization, orgUser);
|
||||
|
||||
// Mock positive validation result
|
||||
var validationRequest = new AutomaticallyConfirmOrganizationUserValidationRequest
|
||||
{
|
||||
OrganizationUserId = orgUser.Id,
|
||||
OrganizationId = organization.Id,
|
||||
Key = key,
|
||||
DefaultUserCollectionName = collectionName,
|
||||
PerformedBy = null,
|
||||
OrganizationUser = orgUser,
|
||||
Organization = organization
|
||||
};
|
||||
sutProvider.GetDependency<IAutomaticallyConfirmOrganizationUsersValidator>()
|
||||
.ValidateAsync(Arg.Any<AutomaticallyConfirmOrganizationUserValidationRequest>())
|
||||
.Returns(Valid(validationRequest));
|
||||
|
||||
// Mock enabled policy requirement
|
||||
var policyDetails = new PolicyDetails
|
||||
{
|
||||
OrganizationId = organization.Id,
|
||||
OrganizationUserId = orgUser.Id,
|
||||
IsProvider = false,
|
||||
OrganizationUserStatus = orgUser.Status,
|
||||
OrganizationUserType = orgUser.Type,
|
||||
PolicyType = PolicyType.OrganizationDataOwnership
|
||||
};
|
||||
sutProvider.GetDependency<IPolicyRequirementQuery>()
|
||||
.GetAsync<OrganizationDataOwnershipPolicyRequirement>(orgUser.UserId!.Value)
|
||||
.Returns(new OrganizationDataOwnershipPolicyRequirement(OrganizationDataOwnershipState.Enabled, [policyDetails]));
|
||||
|
||||
var request = new AutomaticallyConfirmOrganizationUserRequest
|
||||
{
|
||||
OrganizationUserId = orgUser.Id,
|
||||
OrganizationId = organization.Id,
|
||||
Key = key,
|
||||
DefaultUserCollectionName = collectionName,
|
||||
PerformedBy = null
|
||||
};
|
||||
|
||||
// Act
|
||||
await sutProvider.Sut.AutomaticallyConfirmOrganizationUserAsync(request);
|
||||
|
||||
// Assert - Collection repository should be called
|
||||
await sutProvider.GetDependency<ICollectionRepository>()
|
||||
.Received(1)
|
||||
.CreateDefaultCollectionsAsync(
|
||||
organization.Id,
|
||||
Arg.Is<IEnumerable<Guid>>(ids => ids.Single() == orgUser.Id),
|
||||
collectionName);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task AutomaticallyConfirmOrganizationUserAsync_UseMyItemsEnabled_PolicyDisabled_DoesNotCreateCollection(
|
||||
Organization organization,
|
||||
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser orgUser,
|
||||
string key,
|
||||
string collectionName,
|
||||
SutProvider<AutomaticallyConfirmOrganizationUserCommand> sutProvider)
|
||||
{
|
||||
// Arrange
|
||||
organization.UseMyItems = true;
|
||||
orgUser.OrganizationId = organization.Id;
|
||||
|
||||
SetupRepositoryMocks(sutProvider, organization, orgUser);
|
||||
|
||||
// Mock positive validation result
|
||||
var validationRequest = new AutomaticallyConfirmOrganizationUserValidationRequest
|
||||
{
|
||||
OrganizationUserId = orgUser.Id,
|
||||
OrganizationId = organization.Id,
|
||||
Key = key,
|
||||
DefaultUserCollectionName = collectionName,
|
||||
PerformedBy = null,
|
||||
OrganizationUser = orgUser,
|
||||
Organization = organization
|
||||
};
|
||||
sutProvider.GetDependency<IAutomaticallyConfirmOrganizationUsersValidator>()
|
||||
.ValidateAsync(Arg.Any<AutomaticallyConfirmOrganizationUserValidationRequest>())
|
||||
.Returns(Valid(validationRequest));
|
||||
|
||||
// Mock disabled policy requirement
|
||||
sutProvider.GetDependency<IPolicyRequirementQuery>()
|
||||
.GetAsync<OrganizationDataOwnershipPolicyRequirement>(orgUser.UserId!.Value)
|
||||
.Returns(new OrganizationDataOwnershipPolicyRequirement(OrganizationDataOwnershipState.Disabled, []));
|
||||
|
||||
var request = new AutomaticallyConfirmOrganizationUserRequest
|
||||
{
|
||||
OrganizationUserId = orgUser.Id,
|
||||
OrganizationId = organization.Id,
|
||||
Key = key,
|
||||
DefaultUserCollectionName = collectionName,
|
||||
PerformedBy = null
|
||||
};
|
||||
|
||||
// Act
|
||||
await sutProvider.Sut.AutomaticallyConfirmOrganizationUserAsync(request);
|
||||
|
||||
// Assert - Collection repository should NOT be called when policy is disabled
|
||||
await sutProvider.GetDependency<ICollectionRepository>()
|
||||
.DidNotReceive()
|
||||
.CreateDefaultCollectionsAsync(Arg.Any<Guid>(), Arg.Any<IEnumerable<Guid>>(), Arg.Any<string>());
|
||||
}
|
||||
|
||||
private static void SetupRepositoryMocks(
|
||||
SutProvider<AutomaticallyConfirmOrganizationUserCommand> sutProvider,
|
||||
Organization organization,
|
||||
OrganizationUser organizationUser)
|
||||
{
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||
.GetByIdAsync(organizationUser.Id)
|
||||
.Returns(organizationUser);
|
||||
|
||||
sutProvider.GetDependency<IOrganizationRepository>()
|
||||
.GetByIdAsync(organization.Id)
|
||||
.Returns(organization);
|
||||
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||
.ConfirmOrganizationUserAsync(Arg.Any<AcceptedOrganizationUserToConfirm>())
|
||||
.Returns(true);
|
||||
}
|
||||
}
|
||||
@@ -843,4 +843,164 @@ public class ConfirmOrganizationUserCommandTests
|
||||
.DidNotReceive()
|
||||
.SendConfirmationAsync(Arg.Any<Organization>(), Arg.Any<string>(), Arg.Any<bool>());
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task ConfirmUserAsync_UseMyItemsDisabled_DoesNotCreateDefaultCollection(
|
||||
Organization organization, OrganizationUser confirmingUser,
|
||||
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser orgUser, User user,
|
||||
string key, string collectionName, SutProvider<ConfirmOrganizationUserCommand> sutProvider)
|
||||
{
|
||||
// Arrange
|
||||
organization.PlanType = PlanType.EnterpriseAnnually;
|
||||
organization.UseMyItems = false;
|
||||
orgUser.OrganizationId = confirmingUser.OrganizationId = organization.Id;
|
||||
orgUser.UserId = user.Id;
|
||||
|
||||
sutProvider.GetDependency<IOrganizationRepository>().GetByIdAsync(organization.Id).Returns(organization);
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>().GetManyAsync(default).ReturnsForAnyArgs(new[] { orgUser });
|
||||
sutProvider.GetDependency<IUserRepository>().GetManyAsync(default).ReturnsForAnyArgs(new[] { user });
|
||||
|
||||
var policyDetails = new PolicyDetails
|
||||
{
|
||||
OrganizationId = organization.Id,
|
||||
OrganizationUserId = orgUser.Id,
|
||||
IsProvider = false,
|
||||
OrganizationUserStatus = orgUser.Status,
|
||||
OrganizationUserType = orgUser.Type,
|
||||
PolicyType = PolicyType.OrganizationDataOwnership
|
||||
};
|
||||
sutProvider.GetDependency<IPolicyRequirementQuery>()
|
||||
.GetAsync<OrganizationDataOwnershipPolicyRequirement>(orgUser.UserId!.Value)
|
||||
.Returns(new OrganizationDataOwnershipPolicyRequirement(OrganizationDataOwnershipState.Enabled, [policyDetails]));
|
||||
|
||||
// Act
|
||||
await sutProvider.Sut.ConfirmUserAsync(orgUser.OrganizationId, orgUser.Id, key, confirmingUser.Id, collectionName);
|
||||
|
||||
// Assert - Collection repository should NOT be called
|
||||
await sutProvider.GetDependency<ICollectionRepository>()
|
||||
.DidNotReceive()
|
||||
.CreateDefaultCollectionsAsync(Arg.Any<Guid>(), Arg.Any<IEnumerable<Guid>>(), Arg.Any<string>());
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task ConfirmUserAsync_UseMyItemsEnabled_CreatesDefaultCollection(
|
||||
Organization organization, OrganizationUser confirmingUser,
|
||||
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser orgUser, User user,
|
||||
string key, string collectionName, SutProvider<ConfirmOrganizationUserCommand> sutProvider)
|
||||
{
|
||||
// Arrange
|
||||
organization.PlanType = PlanType.EnterpriseAnnually;
|
||||
organization.UseMyItems = true;
|
||||
orgUser.OrganizationId = confirmingUser.OrganizationId = organization.Id;
|
||||
orgUser.UserId = user.Id;
|
||||
|
||||
sutProvider.GetDependency<IOrganizationRepository>().GetByIdAsync(organization.Id).Returns(organization);
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>().GetManyAsync(default).ReturnsForAnyArgs(new[] { orgUser });
|
||||
sutProvider.GetDependency<IUserRepository>().GetManyAsync(default).ReturnsForAnyArgs(new[] { user });
|
||||
|
||||
var policyDetails = new PolicyDetails
|
||||
{
|
||||
OrganizationId = organization.Id,
|
||||
OrganizationUserId = orgUser.Id,
|
||||
IsProvider = false,
|
||||
OrganizationUserStatus = orgUser.Status,
|
||||
OrganizationUserType = orgUser.Type,
|
||||
PolicyType = PolicyType.OrganizationDataOwnership
|
||||
};
|
||||
sutProvider.GetDependency<IPolicyRequirementQuery>()
|
||||
.GetAsync<OrganizationDataOwnershipPolicyRequirement>(orgUser.UserId!.Value)
|
||||
.Returns(new OrganizationDataOwnershipPolicyRequirement(OrganizationDataOwnershipState.Enabled, [policyDetails]));
|
||||
|
||||
// Act
|
||||
await sutProvider.Sut.ConfirmUserAsync(orgUser.OrganizationId, orgUser.Id, key, confirmingUser.Id, collectionName);
|
||||
|
||||
// Assert - Collection repository should be called
|
||||
await sutProvider.GetDependency<ICollectionRepository>()
|
||||
.Received(1)
|
||||
.CreateDefaultCollectionsAsync(
|
||||
organization.Id,
|
||||
Arg.Is<IEnumerable<Guid>>(ids => ids.Single() == orgUser.Id),
|
||||
collectionName);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task ConfirmUsersAsync_UseMyItemsDisabled_DoesNotCreateDefaultCollections(
|
||||
Organization organization, OrganizationUser confirmingUser,
|
||||
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser orgUser1,
|
||||
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser orgUser2,
|
||||
User user1, User user2, string key1, string key2, string collectionName,
|
||||
SutProvider<ConfirmOrganizationUserCommand> sutProvider)
|
||||
{
|
||||
// Arrange
|
||||
organization.PlanType = PlanType.EnterpriseAnnually;
|
||||
organization.UseMyItems = false;
|
||||
orgUser1.OrganizationId = confirmingUser.OrganizationId = organization.Id;
|
||||
orgUser2.OrganizationId = organization.Id;
|
||||
orgUser1.UserId = user1.Id;
|
||||
orgUser2.UserId = user2.Id;
|
||||
|
||||
var keys = new Dictionary<Guid, string>
|
||||
{
|
||||
{ orgUser1.Id, key1 },
|
||||
{ orgUser2.Id, key2 }
|
||||
};
|
||||
|
||||
sutProvider.GetDependency<IOrganizationRepository>().GetByIdAsync(organization.Id).Returns(organization);
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>().GetManyAsync(default).ReturnsForAnyArgs(new[] { orgUser1, orgUser2 });
|
||||
sutProvider.GetDependency<IUserRepository>().GetManyAsync(default).ReturnsForAnyArgs(new[] { user1, user2 });
|
||||
|
||||
sutProvider.GetDependency<IPolicyRequirementQuery>()
|
||||
.GetManyByOrganizationIdAsync<OrganizationDataOwnershipPolicyRequirement>(organization.Id)
|
||||
.Returns([orgUser1.Id, orgUser2.Id]);
|
||||
|
||||
// Act
|
||||
await sutProvider.Sut.ConfirmUsersAsync(organization.Id, keys, confirmingUser.Id, collectionName);
|
||||
|
||||
// Assert - Collection repository should NOT be called
|
||||
await sutProvider.GetDependency<ICollectionRepository>()
|
||||
.DidNotReceive()
|
||||
.CreateDefaultCollectionsAsync(Arg.Any<Guid>(), Arg.Any<IEnumerable<Guid>>(), Arg.Any<string>());
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task ConfirmUsersAsync_UseMyItemsEnabled_CreatesDefaultCollections(
|
||||
Organization organization, OrganizationUser confirmingUser,
|
||||
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser orgUser1,
|
||||
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser orgUser2,
|
||||
User user1, User user2, string key1, string key2, string collectionName,
|
||||
SutProvider<ConfirmOrganizationUserCommand> sutProvider)
|
||||
{
|
||||
// Arrange
|
||||
organization.PlanType = PlanType.EnterpriseAnnually;
|
||||
organization.UseMyItems = true;
|
||||
orgUser1.OrganizationId = confirmingUser.OrganizationId = organization.Id;
|
||||
orgUser2.OrganizationId = organization.Id;
|
||||
orgUser1.UserId = user1.Id;
|
||||
orgUser2.UserId = user2.Id;
|
||||
|
||||
var keys = new Dictionary<Guid, string>
|
||||
{
|
||||
{ orgUser1.Id, key1 },
|
||||
{ orgUser2.Id, key2 }
|
||||
};
|
||||
|
||||
sutProvider.GetDependency<IOrganizationRepository>().GetByIdAsync(organization.Id).Returns(organization);
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>().GetManyAsync(default).ReturnsForAnyArgs(new[] { orgUser1, orgUser2 });
|
||||
sutProvider.GetDependency<IUserRepository>().GetManyAsync(default).ReturnsForAnyArgs(new[] { user1, user2 });
|
||||
|
||||
sutProvider.GetDependency<IPolicyRequirementQuery>()
|
||||
.GetManyByOrganizationIdAsync<OrganizationDataOwnershipPolicyRequirement>(organization.Id)
|
||||
.Returns([orgUser1.Id, orgUser2.Id]);
|
||||
|
||||
// Act
|
||||
await sutProvider.Sut.ConfirmUsersAsync(organization.Id, keys, confirmingUser.Id, collectionName);
|
||||
|
||||
// Assert - Collection repository should be called with correct parameters
|
||||
await sutProvider.GetDependency<ICollectionRepository>()
|
||||
.Received(1)
|
||||
.CreateDefaultCollectionsAsync(
|
||||
organization.Id,
|
||||
Arg.Is<IEnumerable<Guid>>(ids => ids.Count() == 2 && ids.Contains(orgUser1.Id) && ids.Contains(orgUser2.Id)),
|
||||
collectionName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1542,4 +1542,194 @@ public class RestoreOrganizationUserCommandTests
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region UseMyItems Tests
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task RestoreUserAsync_UseMyItemsDisabled_DoesNotCreateCollection(
|
||||
Organization organization,
|
||||
[OrganizationUser(type: OrganizationUserType.Owner)] OrganizationUser owner,
|
||||
[OrganizationUser(status: OrganizationUserStatusType.Revoked)] OrganizationUser orgUser,
|
||||
string collectionName,
|
||||
SutProvider<RestoreOrganizationUserCommand> sutProvider)
|
||||
{
|
||||
// Arrange
|
||||
RestoreUser_Setup(organization, owner, orgUser, sutProvider);
|
||||
organization.UseMyItems = false;
|
||||
|
||||
sutProvider.GetDependency<IFeatureService>()
|
||||
.IsEnabled(FeatureFlagKeys.DefaultUserCollectionRestore)
|
||||
.Returns(true);
|
||||
|
||||
// User will restore to Confirmed
|
||||
orgUser.Email = null;
|
||||
orgUser.OrganizationId = organization.Id;
|
||||
|
||||
sutProvider.GetDependency<IPolicyRequirementQuery>()
|
||||
.GetAsync<OrganizationDataOwnershipPolicyRequirement>(orgUser.UserId!.Value)
|
||||
.Returns(new OrganizationDataOwnershipPolicyRequirement(OrganizationDataOwnershipState.Enabled, []));
|
||||
|
||||
// Act
|
||||
await sutProvider.Sut.RestoreUserAsync(orgUser, owner.Id, collectionName);
|
||||
|
||||
// Assert - No collection should be created
|
||||
await sutProvider.GetDependency<ICollectionRepository>()
|
||||
.DidNotReceive()
|
||||
.CreateDefaultCollectionsAsync(Arg.Any<Guid>(), Arg.Any<IEnumerable<Guid>>(), Arg.Any<string>());
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task RestoreUserAsync_UseMyItemsEnabled_CreatesCollection(
|
||||
Organization organization,
|
||||
[OrganizationUser(type: OrganizationUserType.Owner)] OrganizationUser owner,
|
||||
[OrganizationUser(status: OrganizationUserStatusType.Revoked)] OrganizationUser orgUser,
|
||||
string collectionName,
|
||||
SutProvider<RestoreOrganizationUserCommand> sutProvider)
|
||||
{
|
||||
// Arrange
|
||||
RestoreUser_Setup(organization, owner, orgUser, sutProvider);
|
||||
organization.UseMyItems = true;
|
||||
|
||||
sutProvider.GetDependency<IFeatureService>()
|
||||
.IsEnabled(FeatureFlagKeys.DefaultUserCollectionRestore)
|
||||
.Returns(true);
|
||||
|
||||
// User will restore to Confirmed
|
||||
orgUser.Email = null;
|
||||
orgUser.OrganizationId = organization.Id;
|
||||
|
||||
sutProvider.GetDependency<IPolicyRequirementQuery>()
|
||||
.GetAsync<OrganizationDataOwnershipPolicyRequirement>(orgUser.UserId!.Value)
|
||||
.Returns(new OrganizationDataOwnershipPolicyRequirement(OrganizationDataOwnershipState.Enabled, []));
|
||||
|
||||
// Act
|
||||
await sutProvider.Sut.RestoreUserAsync(orgUser, owner.Id, collectionName);
|
||||
|
||||
// Assert - Collection should be created
|
||||
await sutProvider.GetDependency<ICollectionRepository>()
|
||||
.Received(1)
|
||||
.CreateDefaultCollectionsAsync(
|
||||
organization.Id,
|
||||
Arg.Is<IEnumerable<Guid>>(ids => ids.Single() == orgUser.Id),
|
||||
collectionName);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task RestoreUsersAsync_UseMyItemsDisabled_DoesNotCreateCollections(
|
||||
Organization organization,
|
||||
[OrganizationUser(type: OrganizationUserType.Owner)] OrganizationUser owner,
|
||||
[OrganizationUser(status: OrganizationUserStatusType.Revoked)] OrganizationUser orgUser1,
|
||||
[OrganizationUser(status: OrganizationUserStatusType.Revoked)] OrganizationUser orgUser2,
|
||||
string collectionName,
|
||||
SutProvider<RestoreOrganizationUserCommand> sutProvider)
|
||||
{
|
||||
// Arrange
|
||||
RestoreUser_Setup(organization, owner, orgUser1, sutProvider);
|
||||
organization.UseMyItems = false;
|
||||
|
||||
var organizationUserRepository = sutProvider.GetDependency<IOrganizationUserRepository>();
|
||||
var userService = Substitute.For<IUserService>();
|
||||
|
||||
sutProvider.GetDependency<IFeatureService>()
|
||||
.IsEnabled(FeatureFlagKeys.DefaultUserCollectionRestore)
|
||||
.Returns(true);
|
||||
|
||||
// Both users will restore to Confirmed
|
||||
orgUser1.Email = null;
|
||||
orgUser1.OrganizationId = organization.Id;
|
||||
orgUser2.Email = null;
|
||||
orgUser2.OrganizationId = organization.Id;
|
||||
|
||||
organizationUserRepository
|
||||
.GetManyAsync(Arg.Is<IEnumerable<Guid>>(ids => ids.Contains(orgUser1.Id) && ids.Contains(orgUser2.Id)))
|
||||
.Returns([orgUser1, orgUser2]);
|
||||
|
||||
// Setup bulk policy query - both users have policy enabled
|
||||
sutProvider.GetDependency<IPolicyRequirementQuery>()
|
||||
.GetManyByOrganizationIdAsync<OrganizationDataOwnershipPolicyRequirement>(organization.Id)
|
||||
.Returns([orgUser1.Id, orgUser2.Id]);
|
||||
|
||||
sutProvider.GetDependency<ITwoFactorIsEnabledQuery>()
|
||||
.TwoFactorIsEnabledAsync(Arg.Any<IEnumerable<Guid>>())
|
||||
.Returns(new List<(Guid userId, bool twoFactorIsEnabled)>
|
||||
{
|
||||
(orgUser1.UserId!.Value, true),
|
||||
(orgUser2.UserId!.Value, true)
|
||||
});
|
||||
|
||||
// Act
|
||||
var result = await sutProvider.Sut.RestoreUsersAsync(
|
||||
organization.Id,
|
||||
[orgUser1.Id, orgUser2.Id],
|
||||
owner.Id,
|
||||
userService,
|
||||
collectionName);
|
||||
|
||||
// Assert - No collections should be created
|
||||
await sutProvider.GetDependency<ICollectionRepository>()
|
||||
.DidNotReceive()
|
||||
.CreateDefaultCollectionsAsync(Arg.Any<Guid>(), Arg.Any<IEnumerable<Guid>>(), Arg.Any<string>());
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task RestoreUsersAsync_UseMyItemsEnabled_CreatesCollections(
|
||||
Organization organization,
|
||||
[OrganizationUser(type: OrganizationUserType.Owner)] OrganizationUser owner,
|
||||
[OrganizationUser(status: OrganizationUserStatusType.Revoked)] OrganizationUser orgUser1,
|
||||
[OrganizationUser(status: OrganizationUserStatusType.Revoked)] OrganizationUser orgUser2,
|
||||
string collectionName,
|
||||
SutProvider<RestoreOrganizationUserCommand> sutProvider)
|
||||
{
|
||||
// Arrange
|
||||
RestoreUser_Setup(organization, owner, orgUser1, sutProvider);
|
||||
organization.UseMyItems = true;
|
||||
|
||||
var organizationUserRepository = sutProvider.GetDependency<IOrganizationUserRepository>();
|
||||
var userService = Substitute.For<IUserService>();
|
||||
|
||||
sutProvider.GetDependency<IFeatureService>()
|
||||
.IsEnabled(FeatureFlagKeys.DefaultUserCollectionRestore)
|
||||
.Returns(true);
|
||||
|
||||
// Both users will restore to Confirmed
|
||||
orgUser1.Email = null;
|
||||
orgUser1.OrganizationId = organization.Id;
|
||||
orgUser2.Email = null;
|
||||
orgUser2.OrganizationId = organization.Id;
|
||||
|
||||
organizationUserRepository
|
||||
.GetManyAsync(Arg.Is<IEnumerable<Guid>>(ids => ids.Contains(orgUser1.Id) && ids.Contains(orgUser2.Id)))
|
||||
.Returns([orgUser1, orgUser2]);
|
||||
|
||||
// Setup bulk policy query - both users have policy enabled
|
||||
sutProvider.GetDependency<IPolicyRequirementQuery>()
|
||||
.GetManyByOrganizationIdAsync<OrganizationDataOwnershipPolicyRequirement>(organization.Id)
|
||||
.Returns([orgUser1.Id, orgUser2.Id]);
|
||||
|
||||
sutProvider.GetDependency<ITwoFactorIsEnabledQuery>()
|
||||
.TwoFactorIsEnabledAsync(Arg.Any<IEnumerable<Guid>>())
|
||||
.Returns(new List<(Guid userId, bool twoFactorIsEnabled)>
|
||||
{
|
||||
(orgUser1.UserId!.Value, true),
|
||||
(orgUser2.UserId!.Value, true)
|
||||
});
|
||||
|
||||
// Act
|
||||
var result = await sutProvider.Sut.RestoreUsersAsync(
|
||||
organization.Id,
|
||||
[orgUser1.Id, orgUser2.Id],
|
||||
owner.Id,
|
||||
userService,
|
||||
collectionName);
|
||||
|
||||
// Assert - Collections should be created for both confirmed users
|
||||
await sutProvider.GetDependency<ICollectionRepository>()
|
||||
.Received(1)
|
||||
.CreateDefaultCollectionsAsync(
|
||||
organization.Id,
|
||||
Arg.Is<IEnumerable<Guid>>(ids => ids.Count() == 2 && ids.Contains(orgUser1.Id) && ids.Contains(orgUser2.Id)),
|
||||
collectionName);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -24,11 +24,17 @@ public class OrganizationDataOwnershipPolicyValidatorTests
|
||||
[PolicyUpdate(PolicyType.OrganizationDataOwnership, true)] PolicyUpdate policyUpdate,
|
||||
[Policy(PolicyType.OrganizationDataOwnership, true)] Policy postUpdatedPolicy,
|
||||
[Policy(PolicyType.OrganizationDataOwnership, true)] Policy previousPolicyState,
|
||||
Organization organization,
|
||||
SutProvider<OrganizationDataOwnershipPolicyValidator> sutProvider)
|
||||
{
|
||||
// Arrange
|
||||
postUpdatedPolicy.OrganizationId = policyUpdate.OrganizationId;
|
||||
previousPolicyState.OrganizationId = policyUpdate.OrganizationId;
|
||||
organization.Id = policyUpdate.OrganizationId;
|
||||
|
||||
sutProvider.GetDependency<IOrganizationRepository>()
|
||||
.GetByIdAsync(policyUpdate.OrganizationId)
|
||||
.Returns(organization);
|
||||
|
||||
var policyRequest = new SavePolicyModel(policyUpdate, new OrganizationModelOwnershipPolicyModel(_defaultUserCollectionName));
|
||||
|
||||
@@ -46,11 +52,17 @@ public class OrganizationDataOwnershipPolicyValidatorTests
|
||||
[PolicyUpdate(PolicyType.OrganizationDataOwnership, false)] PolicyUpdate policyUpdate,
|
||||
[Policy(PolicyType.OrganizationDataOwnership, false)] Policy postUpdatedPolicy,
|
||||
[Policy(PolicyType.OrganizationDataOwnership)] Policy previousPolicyState,
|
||||
Organization organization,
|
||||
SutProvider<OrganizationDataOwnershipPolicyValidator> sutProvider)
|
||||
{
|
||||
// Arrange
|
||||
previousPolicyState.OrganizationId = policyUpdate.OrganizationId;
|
||||
postUpdatedPolicy.OrganizationId = policyUpdate.OrganizationId;
|
||||
organization.Id = policyUpdate.OrganizationId;
|
||||
|
||||
sutProvider.GetDependency<IOrganizationRepository>()
|
||||
.GetByIdAsync(policyUpdate.OrganizationId)
|
||||
.Returns(organization);
|
||||
|
||||
var policyRequest = new SavePolicyModel(policyUpdate, new OrganizationModelOwnershipPolicyModel(_defaultUserCollectionName));
|
||||
|
||||
@@ -195,12 +207,18 @@ public class OrganizationDataOwnershipPolicyValidatorTests
|
||||
[PolicyUpdate(PolicyType.OrganizationDataOwnership)] PolicyUpdate policyUpdate,
|
||||
[Policy(PolicyType.OrganizationDataOwnership, true)] Policy postUpdatedPolicy,
|
||||
[Policy(PolicyType.OrganizationDataOwnership, false)] Policy previousPolicyState,
|
||||
Organization organization,
|
||||
SutProvider<OrganizationDataOwnershipPolicyValidator> sutProvider)
|
||||
{
|
||||
// Arrange
|
||||
postUpdatedPolicy.OrganizationId = policyUpdate.OrganizationId;
|
||||
previousPolicyState.OrganizationId = policyUpdate.OrganizationId;
|
||||
policyUpdate.Enabled = true;
|
||||
organization.Id = policyUpdate.OrganizationId;
|
||||
|
||||
sutProvider.GetDependency<IOrganizationRepository>()
|
||||
.GetByIdAsync(policyUpdate.OrganizationId)
|
||||
.Returns(organization);
|
||||
|
||||
var policyRequest = new SavePolicyModel(policyUpdate, metadata);
|
||||
|
||||
@@ -226,9 +244,18 @@ public class OrganizationDataOwnershipPolicyValidatorTests
|
||||
private static OrganizationDataOwnershipPolicyValidator ArrangeSut(
|
||||
OrganizationDataOwnershipPolicyRequirementFactory factory,
|
||||
IPolicyRepository policyRepository,
|
||||
ICollectionRepository collectionRepository)
|
||||
ICollectionRepository collectionRepository,
|
||||
bool useMyItems = true)
|
||||
{
|
||||
var sut = new OrganizationDataOwnershipPolicyValidator(policyRepository, collectionRepository, [factory]);
|
||||
var organizationRepository = Substitute.For<IOrganizationRepository>();
|
||||
// Default to UseMyItems = true for existing tests
|
||||
organizationRepository.GetByIdAsync(Arg.Any<Guid>())
|
||||
.Returns(callInfo => new Organization
|
||||
{
|
||||
Id = callInfo.Arg<Guid>(),
|
||||
UseMyItems = useMyItems
|
||||
});
|
||||
var sut = new OrganizationDataOwnershipPolicyValidator(policyRepository, collectionRepository, organizationRepository, [factory]);
|
||||
return sut;
|
||||
}
|
||||
|
||||
@@ -237,11 +264,17 @@ public class OrganizationDataOwnershipPolicyValidatorTests
|
||||
[PolicyUpdate(PolicyType.OrganizationDataOwnership, true)] PolicyUpdate policyUpdate,
|
||||
[Policy(PolicyType.OrganizationDataOwnership, true)] Policy postUpdatedPolicy,
|
||||
[Policy(PolicyType.OrganizationDataOwnership, true)] Policy previousPolicyState,
|
||||
Organization organization,
|
||||
SutProvider<OrganizationDataOwnershipPolicyValidator> sutProvider)
|
||||
{
|
||||
// Arrange
|
||||
postUpdatedPolicy.OrganizationId = policyUpdate.OrganizationId;
|
||||
previousPolicyState.OrganizationId = policyUpdate.OrganizationId;
|
||||
organization.Id = policyUpdate.OrganizationId;
|
||||
|
||||
sutProvider.GetDependency<IOrganizationRepository>()
|
||||
.GetByIdAsync(policyUpdate.OrganizationId)
|
||||
.Returns(organization);
|
||||
|
||||
var policyRequest = new SavePolicyModel(policyUpdate, new OrganizationModelOwnershipPolicyModel(_defaultUserCollectionName));
|
||||
|
||||
@@ -259,11 +292,17 @@ public class OrganizationDataOwnershipPolicyValidatorTests
|
||||
[PolicyUpdate(PolicyType.OrganizationDataOwnership, false)] PolicyUpdate policyUpdate,
|
||||
[Policy(PolicyType.OrganizationDataOwnership, false)] Policy postUpdatedPolicy,
|
||||
[Policy(PolicyType.OrganizationDataOwnership)] Policy previousPolicyState,
|
||||
Organization organization,
|
||||
SutProvider<OrganizationDataOwnershipPolicyValidator> sutProvider)
|
||||
{
|
||||
// Arrange
|
||||
previousPolicyState.OrganizationId = policyUpdate.OrganizationId;
|
||||
postUpdatedPolicy.OrganizationId = policyUpdate.OrganizationId;
|
||||
organization.Id = policyUpdate.OrganizationId;
|
||||
|
||||
sutProvider.GetDependency<IOrganizationRepository>()
|
||||
.GetByIdAsync(policyUpdate.OrganizationId)
|
||||
.Returns(organization);
|
||||
|
||||
var policyRequest = new SavePolicyModel(policyUpdate, new OrganizationModelOwnershipPolicyModel(_defaultUserCollectionName));
|
||||
|
||||
@@ -352,12 +391,18 @@ public class OrganizationDataOwnershipPolicyValidatorTests
|
||||
[PolicyUpdate(PolicyType.OrganizationDataOwnership)] PolicyUpdate policyUpdate,
|
||||
[Policy(PolicyType.OrganizationDataOwnership, true)] Policy postUpdatedPolicy,
|
||||
[Policy(PolicyType.OrganizationDataOwnership, false)] Policy previousPolicyState,
|
||||
Organization organization,
|
||||
SutProvider<OrganizationDataOwnershipPolicyValidator> sutProvider)
|
||||
{
|
||||
// Arrange
|
||||
postUpdatedPolicy.OrganizationId = policyUpdate.OrganizationId;
|
||||
previousPolicyState.OrganizationId = policyUpdate.OrganizationId;
|
||||
policyUpdate.Enabled = true;
|
||||
organization.Id = policyUpdate.OrganizationId;
|
||||
|
||||
sutProvider.GetDependency<IOrganizationRepository>()
|
||||
.GetByIdAsync(policyUpdate.OrganizationId)
|
||||
.Returns(organization);
|
||||
|
||||
var policyRequest = new SavePolicyModel(policyUpdate, metadata);
|
||||
|
||||
@@ -369,4 +414,69 @@ public class OrganizationDataOwnershipPolicyValidatorTests
|
||||
.DidNotReceiveWithAnyArgs()
|
||||
.CreateDefaultCollectionsBulkAsync(default, default, default);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitMemberAutoData(nameof(ShouldUpsertDefaultCollectionsTestCases))]
|
||||
public async Task ExecuteSideEffectsAsync_OrganizationNotFound_ThrowsInvalidOperationException(
|
||||
Policy postUpdatedPolicy,
|
||||
Policy? previousPolicyState,
|
||||
[PolicyUpdate(PolicyType.OrganizationDataOwnership)] PolicyUpdate policyUpdate,
|
||||
[OrganizationPolicyDetails(PolicyType.OrganizationDataOwnership)] IEnumerable<OrganizationPolicyDetails> orgPolicyDetails,
|
||||
OrganizationDataOwnershipPolicyRequirementFactory factory)
|
||||
{
|
||||
// Arrange
|
||||
var orgPolicyDetailsList = orgPolicyDetails.ToList();
|
||||
foreach (var policyDetail in orgPolicyDetailsList)
|
||||
{
|
||||
policyDetail.OrganizationId = policyUpdate.OrganizationId;
|
||||
}
|
||||
|
||||
var policyRepository = ArrangePolicyRepository(orgPolicyDetailsList);
|
||||
var collectionRepository = Substitute.For<ICollectionRepository>();
|
||||
var organizationRepository = Substitute.For<IOrganizationRepository>();
|
||||
|
||||
// Return null to simulate organization not found
|
||||
organizationRepository.GetByIdAsync(Arg.Any<Guid>()).Returns((Organization?)null);
|
||||
|
||||
var sut = new OrganizationDataOwnershipPolicyValidator(policyRepository, collectionRepository, organizationRepository, [factory]);
|
||||
var policyRequest = new SavePolicyModel(policyUpdate, new OrganizationModelOwnershipPolicyModel(_defaultUserCollectionName));
|
||||
|
||||
// Act & Assert
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() =>
|
||||
sut.ExecuteSideEffectsAsync(policyRequest, postUpdatedPolicy, previousPolicyState));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitMemberAutoData(nameof(ShouldUpsertDefaultCollectionsTestCases))]
|
||||
public async Task ExecuteSideEffectsAsync_UseMyItemsDisabled_DoesNotCreateCollections(
|
||||
Policy postUpdatedPolicy,
|
||||
Policy? previousPolicyState,
|
||||
[PolicyUpdate(PolicyType.OrganizationDataOwnership)] PolicyUpdate policyUpdate,
|
||||
[OrganizationPolicyDetails(PolicyType.OrganizationDataOwnership)] IEnumerable<OrganizationPolicyDetails> orgPolicyDetails,
|
||||
OrganizationDataOwnershipPolicyRequirementFactory factory)
|
||||
{
|
||||
// Arrange
|
||||
var orgPolicyDetailsList = orgPolicyDetails.ToList();
|
||||
foreach (var policyDetail in orgPolicyDetailsList)
|
||||
{
|
||||
policyDetail.OrganizationId = policyUpdate.OrganizationId;
|
||||
}
|
||||
|
||||
var policyRepository = ArrangePolicyRepository(orgPolicyDetailsList);
|
||||
var collectionRepository = Substitute.For<ICollectionRepository>();
|
||||
|
||||
var sut = ArrangeSut(factory, policyRepository, collectionRepository, useMyItems: false);
|
||||
var policyRequest = new SavePolicyModel(policyUpdate, new OrganizationModelOwnershipPolicyModel(_defaultUserCollectionName));
|
||||
|
||||
// Act
|
||||
await sut.ExecuteSideEffectsAsync(policyRequest, postUpdatedPolicy, previousPolicyState);
|
||||
|
||||
// Assert - Should NOT create collections when UseMyItems is disabled
|
||||
await collectionRepository
|
||||
.DidNotReceive()
|
||||
.CreateDefaultCollectionsBulkAsync(
|
||||
Arg.Any<Guid>(),
|
||||
Arg.Any<IEnumerable<Guid>>(),
|
||||
Arg.Any<string>());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user