1
0
mirror of https://github.com/bitwarden/server synced 2025-12-15 07:43:54 +00:00
Files
server/test/Core.Test/AdminConsole/OrganizationFeatures/OrganizationUsers/ConfirmOrganizationUserCommandTests.cs

818 lines
48 KiB
C#

using Bit.Core.AdminConsole.Entities;
using Bit.Core.AdminConsole.Enums;
using Bit.Core.AdminConsole.Models.Data.Organizations.Policies;
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers;
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.AutoConfirmUser;
using Bit.Core.AdminConsole.OrganizationFeatures.Policies;
using Bit.Core.AdminConsole.OrganizationFeatures.Policies.Enforcement.AutoConfirm;
using Bit.Core.AdminConsole.OrganizationFeatures.Policies.PolicyRequirements;
using Bit.Core.AdminConsole.Services;
using Bit.Core.Auth.UserFeatures.TwoFactorAuth.Interfaces;
using Bit.Core.Billing.Enums;
using Bit.Core.Entities;
using Bit.Core.Enums;
using Bit.Core.Exceptions;
using Bit.Core.Models.Data;
using Bit.Core.Models.Data.Organizations.OrganizationUsers;
using Bit.Core.Platform.Push;
using Bit.Core.Repositories;
using Bit.Core.Services;
using Bit.Core.Test.AdminConsole.AutoFixture;
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;
[SutProviderCustomize]
public class ConfirmOrganizationUserCommandTests
{
[Theory, BitAutoData]
public async Task ConfirmUserAsync_WithInvalidStatus_ThrowsBadRequestException(OrganizationUser confirmingUser,
[OrganizationUser(OrganizationUserStatusType.Invited)] OrganizationUser orgUser, string key,
SutProvider<ConfirmOrganizationUserCommand> sutProvider)
{
var organizationUserRepository = sutProvider.GetDependency<IOrganizationUserRepository>();
organizationUserRepository.GetByIdAsync(orgUser.Id).Returns(orgUser);
var exception = await Assert.ThrowsAsync<BadRequestException>(
() => sutProvider.Sut.ConfirmUserAsync(orgUser.OrganizationId, orgUser.Id, key, confirmingUser.Id));
Assert.Contains("User not valid.", exception.Message);
}
[Theory, BitAutoData]
public async Task ConfirmUserAsync_WithWrongOrganization_ThrowsBadRequestException(OrganizationUser confirmingUser,
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser orgUser, string key,
SutProvider<ConfirmOrganizationUserCommand> sutProvider)
{
var organizationUserRepository = sutProvider.GetDependency<IOrganizationUserRepository>();
organizationUserRepository.GetByIdAsync(orgUser.Id).Returns(orgUser);
var exception = await Assert.ThrowsAsync<BadRequestException>(
() => sutProvider.Sut.ConfirmUserAsync(confirmingUser.OrganizationId, orgUser.Id, key, confirmingUser.Id));
Assert.Contains("User not valid.", exception.Message);
}
[Theory]
[BitAutoData(OrganizationUserType.Admin)]
[BitAutoData(OrganizationUserType.Owner)]
public async Task ConfirmUserAsync_ToFree_WithExistingAdminOrOwner_ThrowsBadRequestException(OrganizationUserType userType, Organization org, OrganizationUser confirmingUser,
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser orgUser, User user,
string key, SutProvider<ConfirmOrganizationUserCommand> sutProvider)
{
var organizationUserRepository = sutProvider.GetDependency<IOrganizationUserRepository>();
var organizationRepository = sutProvider.GetDependency<IOrganizationRepository>();
var userRepository = sutProvider.GetDependency<IUserRepository>();
org.PlanType = PlanType.Free;
orgUser.OrganizationId = confirmingUser.OrganizationId = org.Id;
orgUser.UserId = user.Id;
orgUser.Type = userType;
organizationUserRepository.GetManyAsync(default).ReturnsForAnyArgs(new[] { orgUser });
organizationUserRepository.GetCountByFreeOrganizationAdminUserAsync(orgUser.UserId.Value).Returns(1);
organizationRepository.GetByIdAsync(org.Id).Returns(org);
userRepository.GetManyAsync(default).ReturnsForAnyArgs(new[] { user });
var exception = await Assert.ThrowsAsync<BadRequestException>(
() => sutProvider.Sut.ConfirmUserAsync(orgUser.OrganizationId, orgUser.Id, key, confirmingUser.Id));
Assert.Contains("User can only be an admin of one free organization.", exception.Message);
}
[Theory]
[BitAutoData(PlanType.Custom, OrganizationUserType.Admin)]
[BitAutoData(PlanType.Custom, OrganizationUserType.Owner)]
[BitAutoData(PlanType.EnterpriseAnnually, OrganizationUserType.Admin)]
[BitAutoData(PlanType.EnterpriseAnnually, OrganizationUserType.Owner)]
[BitAutoData(PlanType.EnterpriseAnnually2020, OrganizationUserType.Admin)]
[BitAutoData(PlanType.EnterpriseAnnually2020, OrganizationUserType.Owner)]
[BitAutoData(PlanType.EnterpriseAnnually2019, OrganizationUserType.Admin)]
[BitAutoData(PlanType.EnterpriseAnnually2019, OrganizationUserType.Owner)]
[BitAutoData(PlanType.EnterpriseMonthly, OrganizationUserType.Admin)]
[BitAutoData(PlanType.EnterpriseMonthly, OrganizationUserType.Owner)]
[BitAutoData(PlanType.EnterpriseMonthly2020, OrganizationUserType.Admin)]
[BitAutoData(PlanType.EnterpriseMonthly2020, OrganizationUserType.Owner)]
[BitAutoData(PlanType.EnterpriseMonthly2019, OrganizationUserType.Admin)]
[BitAutoData(PlanType.EnterpriseMonthly2019, OrganizationUserType.Owner)]
[BitAutoData(PlanType.FamiliesAnnually, OrganizationUserType.Admin)]
[BitAutoData(PlanType.FamiliesAnnually, OrganizationUserType.Owner)]
[BitAutoData(PlanType.FamiliesAnnually2025, OrganizationUserType.Admin)]
[BitAutoData(PlanType.FamiliesAnnually2025, OrganizationUserType.Owner)]
[BitAutoData(PlanType.FamiliesAnnually2019, OrganizationUserType.Admin)]
[BitAutoData(PlanType.FamiliesAnnually2019, OrganizationUserType.Owner)]
[BitAutoData(PlanType.TeamsAnnually, OrganizationUserType.Admin)]
[BitAutoData(PlanType.TeamsAnnually, OrganizationUserType.Owner)]
[BitAutoData(PlanType.TeamsAnnually2020, OrganizationUserType.Admin)]
[BitAutoData(PlanType.TeamsAnnually2020, OrganizationUserType.Owner)]
[BitAutoData(PlanType.TeamsAnnually2019, OrganizationUserType.Admin)]
[BitAutoData(PlanType.TeamsAnnually2019, OrganizationUserType.Owner)]
[BitAutoData(PlanType.TeamsMonthly, OrganizationUserType.Admin)]
[BitAutoData(PlanType.TeamsMonthly, OrganizationUserType.Owner)]
[BitAutoData(PlanType.TeamsMonthly2020, OrganizationUserType.Admin)]
[BitAutoData(PlanType.TeamsMonthly2020, OrganizationUserType.Owner)]
[BitAutoData(PlanType.TeamsMonthly2019, OrganizationUserType.Admin)]
[BitAutoData(PlanType.TeamsMonthly2019, OrganizationUserType.Owner)]
public async Task ConfirmUserAsync_ToNonFree_WithExistingFreeAdminOrOwner_Succeeds(PlanType planType, OrganizationUserType orgUserType, Organization org, OrganizationUser confirmingUser,
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser orgUser, User user,
string key, SutProvider<ConfirmOrganizationUserCommand> sutProvider)
{
var organizationUserRepository = sutProvider.GetDependency<IOrganizationUserRepository>();
var organizationRepository = sutProvider.GetDependency<IOrganizationRepository>();
var userRepository = sutProvider.GetDependency<IUserRepository>();
var device = new Device() { Id = Guid.NewGuid(), UserId = user.Id, PushToken = "pushToken", Identifier = "identifier" };
sutProvider.GetDependency<IDeviceRepository>()
.GetManyByUserIdAsync(user.Id)
.Returns([device]);
org.PlanType = planType;
orgUser.OrganizationId = confirmingUser.OrganizationId = org.Id;
orgUser.UserId = user.Id;
orgUser.Type = orgUserType;
orgUser.AccessSecretsManager = false;
organizationUserRepository.GetManyAsync(default).ReturnsForAnyArgs(new[] { orgUser });
organizationUserRepository.GetCountByFreeOrganizationAdminUserAsync(orgUser.UserId.Value).Returns(1);
organizationRepository.GetByIdAsync(org.Id).Returns(org);
userRepository.GetManyAsync(default).ReturnsForAnyArgs(new[] { user });
await sutProvider.Sut.ConfirmUserAsync(orgUser.OrganizationId, orgUser.Id, key, confirmingUser.Id);
await sutProvider.GetDependency<IEventService>().Received(1).LogOrganizationUserEventAsync(orgUser, EventType.OrganizationUser_Confirmed);
await sutProvider.GetDependency<IMailService>().Received(1).SendOrganizationConfirmedEmailAsync(org.DisplayName(), user.Email);
await organizationUserRepository.Received(1).ReplaceManyAsync(Arg.Is<List<OrganizationUser>>(users => users.Contains(orgUser) && users.Count == 1));
await sutProvider.GetDependency<IPushRegistrationService>()
.Received(1)
.DeleteUserRegistrationOrganizationAsync(
Arg.Is<IEnumerable<string>>(ids => ids.Contains(device.Id.ToString()) && ids.Count() == 1),
org.Id.ToString());
await sutProvider.GetDependency<IPushNotificationService>().Received(1).PushSyncOrgKeysAsync(user.Id);
}
[Theory, BitAutoData]
public async Task ConfirmUserAsync_AsUser_WithSingleOrgPolicyAppliedFromConfirmingOrg_ThrowsBadRequestException(Organization org, OrganizationUser confirmingUser,
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser orgUser, User user,
OrganizationUser orgUserAnotherOrg, [OrganizationUserPolicyDetails(PolicyType.SingleOrg)] OrganizationUserPolicyDetails singleOrgPolicy,
string key, SutProvider<ConfirmOrganizationUserCommand> sutProvider)
{
var organizationUserRepository = sutProvider.GetDependency<IOrganizationUserRepository>();
var organizationRepository = sutProvider.GetDependency<IOrganizationRepository>();
var userRepository = sutProvider.GetDependency<IUserRepository>();
var policyService = sutProvider.GetDependency<IPolicyService>();
org.PlanType = PlanType.EnterpriseAnnually;
orgUser.Status = OrganizationUserStatusType.Accepted;
orgUser.OrganizationId = confirmingUser.OrganizationId = org.Id;
orgUser.UserId = orgUserAnotherOrg.UserId = user.Id;
organizationUserRepository.GetManyAsync(default).ReturnsForAnyArgs(new[] { orgUser });
organizationUserRepository.GetManyByManyUsersAsync(default).ReturnsForAnyArgs(new[] { orgUserAnotherOrg });
organizationRepository.GetByIdAsync(org.Id).Returns(org);
userRepository.GetManyAsync(default).ReturnsForAnyArgs(new[] { user });
singleOrgPolicy.OrganizationId = org.Id;
policyService.GetPoliciesApplicableToUserAsync(user.Id, PolicyType.SingleOrg).Returns(new[] { singleOrgPolicy });
var exception = await Assert.ThrowsAsync<BadRequestException>(
() => sutProvider.Sut.ConfirmUserAsync(orgUser.OrganizationId, orgUser.Id, key, confirmingUser.Id));
Assert.Contains("Cannot confirm this member to the organization until they leave or remove all other organizations.", exception.Message);
}
[Theory, BitAutoData]
public async Task ConfirmUserAsync_AsUser_WithSingleOrgPolicyAppliedFromOtherOrg_ThrowsBadRequestException(Organization org, OrganizationUser confirmingUser,
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser orgUser, User user,
OrganizationUser orgUserAnotherOrg, [OrganizationUserPolicyDetails(PolicyType.SingleOrg)] OrganizationUserPolicyDetails singleOrgPolicy,
string key, SutProvider<ConfirmOrganizationUserCommand> sutProvider)
{
var organizationUserRepository = sutProvider.GetDependency<IOrganizationUserRepository>();
var organizationRepository = sutProvider.GetDependency<IOrganizationRepository>();
var userRepository = sutProvider.GetDependency<IUserRepository>();
var policyService = sutProvider.GetDependency<IPolicyService>();
org.PlanType = PlanType.EnterpriseAnnually;
orgUser.Status = OrganizationUserStatusType.Accepted;
orgUser.OrganizationId = confirmingUser.OrganizationId = org.Id;
orgUser.UserId = orgUserAnotherOrg.UserId = user.Id;
organizationUserRepository.GetManyAsync(default).ReturnsForAnyArgs(new[] { orgUser });
organizationUserRepository.GetManyByManyUsersAsync(default).ReturnsForAnyArgs(new[] { orgUserAnotherOrg });
organizationRepository.GetByIdAsync(org.Id).Returns(org);
userRepository.GetManyAsync(default).ReturnsForAnyArgs(new[] { user });
singleOrgPolicy.OrganizationId = orgUserAnotherOrg.Id;
policyService.GetPoliciesApplicableToUserAsync(user.Id, PolicyType.SingleOrg).Returns(new[] { singleOrgPolicy });
var exception = await Assert.ThrowsAsync<BadRequestException>(
() => sutProvider.Sut.ConfirmUserAsync(orgUser.OrganizationId, orgUser.Id, key, confirmingUser.Id));
Assert.Contains("Cannot confirm this member to the organization because they are in another organization which forbids it.", exception.Message);
}
[Theory]
[BitAutoData(OrganizationUserType.Admin)]
[BitAutoData(OrganizationUserType.Owner)]
public async Task ConfirmUserAsync_AsOwnerOrAdmin_WithSingleOrgPolicy_ExcludedViaUserType_Success(
OrganizationUserType userType, Organization org, OrganizationUser confirmingUser,
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser orgUser, User user,
OrganizationUser orgUserAnotherOrg,
string key, SutProvider<ConfirmOrganizationUserCommand> sutProvider)
{
var organizationUserRepository = sutProvider.GetDependency<IOrganizationUserRepository>();
var organizationRepository = sutProvider.GetDependency<IOrganizationRepository>();
var userRepository = sutProvider.GetDependency<IUserRepository>();
org.PlanType = PlanType.EnterpriseAnnually;
orgUser.Type = userType;
orgUser.Status = OrganizationUserStatusType.Accepted;
orgUser.OrganizationId = confirmingUser.OrganizationId = org.Id;
orgUser.UserId = orgUserAnotherOrg.UserId = user.Id;
orgUser.AccessSecretsManager = true;
organizationUserRepository.GetManyAsync(default).ReturnsForAnyArgs(new[] { orgUser });
organizationUserRepository.GetManyByManyUsersAsync(default).ReturnsForAnyArgs(new[] { orgUserAnotherOrg });
organizationRepository.GetByIdAsync(org.Id).Returns(org);
userRepository.GetManyAsync(default).ReturnsForAnyArgs(new[] { user });
await sutProvider.Sut.ConfirmUserAsync(orgUser.OrganizationId, orgUser.Id, key, confirmingUser.Id);
await sutProvider.GetDependency<IEventService>().Received(1).LogOrganizationUserEventAsync(orgUser, EventType.OrganizationUser_Confirmed);
await sutProvider.GetDependency<IMailService>().Received(1).SendOrganizationConfirmedEmailAsync(org.DisplayName(), user.Email, true);
await organizationUserRepository.Received(1).ReplaceManyAsync(Arg.Is<List<OrganizationUser>>(users => users.Contains(orgUser) && users.Count == 1));
}
[Theory, BitAutoData]
public async Task ConfirmUserAsync_WithTwoFactorPolicyAndTwoFactorDisabled_ThrowsBadRequestException(Organization org, OrganizationUser confirmingUser,
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser orgUser, User user,
OrganizationUser orgUserAnotherOrg,
[OrganizationUserPolicyDetails(PolicyType.TwoFactorAuthentication)] OrganizationUserPolicyDetails twoFactorPolicy,
string key, SutProvider<ConfirmOrganizationUserCommand> sutProvider)
{
var organizationUserRepository = sutProvider.GetDependency<IOrganizationUserRepository>();
var organizationRepository = sutProvider.GetDependency<IOrganizationRepository>();
var userRepository = sutProvider.GetDependency<IUserRepository>();
var policyService = sutProvider.GetDependency<IPolicyService>();
var twoFactorIsEnabledQuery = sutProvider.GetDependency<ITwoFactorIsEnabledQuery>();
org.PlanType = PlanType.EnterpriseAnnually;
orgUser.OrganizationId = confirmingUser.OrganizationId = org.Id;
orgUser.UserId = orgUserAnotherOrg.UserId = user.Id;
organizationUserRepository.GetManyAsync(default).ReturnsForAnyArgs(new[] { orgUser });
organizationUserRepository.GetManyByManyUsersAsync(default).ReturnsForAnyArgs(new[] { orgUserAnotherOrg });
organizationRepository.GetByIdAsync(org.Id).Returns(org);
userRepository.GetManyAsync(default).ReturnsForAnyArgs(new[] { user });
twoFactorPolicy.OrganizationId = org.Id;
policyService.GetPoliciesApplicableToUserAsync(user.Id, PolicyType.TwoFactorAuthentication).Returns(new[] { twoFactorPolicy });
twoFactorIsEnabledQuery.TwoFactorIsEnabledAsync(Arg.Is<IEnumerable<Guid>>(ids => ids.Contains(user.Id)))
.Returns(new List<(Guid userId, bool twoFactorIsEnabled)>() { (user.Id, false) });
var exception = await Assert.ThrowsAsync<BadRequestException>(
() => sutProvider.Sut.ConfirmUserAsync(orgUser.OrganizationId, orgUser.Id, key, confirmingUser.Id));
Assert.Contains("User does not have two-step login enabled.", exception.Message);
}
[Theory, BitAutoData]
public async Task ConfirmUserAsync_WithTwoFactorPolicyAndTwoFactorEnabled_Succeeds(Organization org, OrganizationUser confirmingUser,
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser orgUser, User user,
[OrganizationUserPolicyDetails(PolicyType.TwoFactorAuthentication)] OrganizationUserPolicyDetails twoFactorPolicy,
string key, SutProvider<ConfirmOrganizationUserCommand> sutProvider)
{
var organizationUserRepository = sutProvider.GetDependency<IOrganizationUserRepository>();
var organizationRepository = sutProvider.GetDependency<IOrganizationRepository>();
var userRepository = sutProvider.GetDependency<IUserRepository>();
var policyService = sutProvider.GetDependency<IPolicyService>();
var twoFactorIsEnabledQuery = sutProvider.GetDependency<ITwoFactorIsEnabledQuery>();
org.PlanType = PlanType.EnterpriseAnnually;
orgUser.OrganizationId = confirmingUser.OrganizationId = org.Id;
orgUser.UserId = user.Id;
organizationUserRepository.GetManyAsync(default).ReturnsForAnyArgs(new[] { orgUser });
organizationRepository.GetByIdAsync(org.Id).Returns(org);
userRepository.GetManyAsync(default).ReturnsForAnyArgs(new[] { user });
twoFactorPolicy.OrganizationId = org.Id;
policyService.GetPoliciesApplicableToUserAsync(user.Id, PolicyType.TwoFactorAuthentication).Returns(new[] { twoFactorPolicy });
twoFactorIsEnabledQuery.TwoFactorIsEnabledAsync(Arg.Is<IEnumerable<Guid>>(ids => ids.Contains(user.Id)))
.Returns(new List<(Guid userId, bool twoFactorIsEnabled)>() { (user.Id, true) });
await sutProvider.Sut.ConfirmUserAsync(orgUser.OrganizationId, orgUser.Id, key, confirmingUser.Id);
}
[Theory, BitAutoData]
public async Task ConfirmUsersAsync_WithMultipleUsers_ReturnsExpectedMixedResults(Organization org,
OrganizationUser confirmingUser,
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser orgUser1,
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser orgUser2,
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser orgUser3,
OrganizationUser anotherOrgUser, User user1, User user2, User user3,
[OrganizationUserPolicyDetails(PolicyType.TwoFactorAuthentication)] OrganizationUserPolicyDetails twoFactorPolicy,
[OrganizationUserPolicyDetails(PolicyType.SingleOrg)] OrganizationUserPolicyDetails singleOrgPolicy,
string key, SutProvider<ConfirmOrganizationUserCommand> sutProvider)
{
var organizationUserRepository = sutProvider.GetDependency<IOrganizationUserRepository>();
var organizationRepository = sutProvider.GetDependency<IOrganizationRepository>();
var userRepository = sutProvider.GetDependency<IUserRepository>();
var policyService = sutProvider.GetDependency<IPolicyService>();
var twoFactorIsEnabledQuery = sutProvider.GetDependency<ITwoFactorIsEnabledQuery>();
org.PlanType = PlanType.EnterpriseAnnually;
orgUser1.OrganizationId = orgUser2.OrganizationId = orgUser3.OrganizationId = confirmingUser.OrganizationId = org.Id;
orgUser1.UserId = user1.Id;
orgUser2.UserId = user2.Id;
orgUser3.UserId = user3.Id;
anotherOrgUser.UserId = user3.Id;
var orgUsers = new[] { orgUser1, orgUser2, orgUser3 };
organizationUserRepository.GetManyAsync(default).ReturnsForAnyArgs(orgUsers);
organizationRepository.GetByIdAsync(org.Id).Returns(org);
userRepository.GetManyAsync(default).ReturnsForAnyArgs(new[] { user1, user2, user3 });
twoFactorPolicy.OrganizationId = org.Id;
policyService.GetPoliciesApplicableToUserAsync(Arg.Any<Guid>(), PolicyType.TwoFactorAuthentication).Returns(new[] { twoFactorPolicy });
twoFactorIsEnabledQuery.TwoFactorIsEnabledAsync(Arg.Is<IEnumerable<Guid>>(ids => ids.Contains(user1.Id) && ids.Contains(user2.Id) && ids.Contains(user3.Id)))
.Returns(new List<(Guid userId, bool twoFactorIsEnabled)>()
{
(user1.Id, true),
(user2.Id, false),
(user3.Id, true)
});
singleOrgPolicy.OrganizationId = org.Id;
policyService.GetPoliciesApplicableToUserAsync(user3.Id, PolicyType.SingleOrg)
.Returns(new[] { singleOrgPolicy });
organizationUserRepository.GetManyByManyUsersAsync(default)
.ReturnsForAnyArgs(new[] { orgUser1, orgUser2, orgUser3, anotherOrgUser });
var keys = orgUsers.ToDictionary(ou => ou.Id, _ => key);
var result = await sutProvider.Sut.ConfirmUsersAsync(confirmingUser.OrganizationId, keys, confirmingUser.Id);
Assert.Contains("", result[0].Item2);
Assert.Contains("User does not have two-step login enabled.", result[1].Item2);
Assert.Contains("Cannot confirm this member to the organization until they leave or remove all other organizations.", result[2].Item2);
}
[Theory, BitAutoData]
public async Task ConfirmUserAsync_WithPolicyRequirementsEnabled_AndTwoFactorRequired_ThrowsBadRequestException(
Organization org, OrganizationUser confirmingUser,
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser orgUser, User user,
SutProvider<ConfirmOrganizationUserCommand> sutProvider)
{
var organizationUserRepository = sutProvider.GetDependency<IOrganizationUserRepository>();
var organizationRepository = sutProvider.GetDependency<IOrganizationRepository>();
var userRepository = sutProvider.GetDependency<IUserRepository>();
var featureService = sutProvider.GetDependency<IFeatureService>();
var policyRequirementQuery = sutProvider.GetDependency<IPolicyRequirementQuery>();
var twoFactorIsEnabledQuery = sutProvider.GetDependency<ITwoFactorIsEnabledQuery>();
org.PlanType = PlanType.EnterpriseAnnually;
orgUser.OrganizationId = confirmingUser.OrganizationId = org.Id;
orgUser.UserId = user.Id;
organizationUserRepository.GetManyAsync(default).ReturnsForAnyArgs(new[] { orgUser });
organizationRepository.GetByIdAsync(org.Id).Returns(org);
userRepository.GetManyAsync(default).ReturnsForAnyArgs(new[] { user });
featureService.IsEnabled(FeatureFlagKeys.PolicyRequirements).Returns(true);
policyRequirementQuery.GetAsync<RequireTwoFactorPolicyRequirement>(user.Id)
.Returns(new RequireTwoFactorPolicyRequirement(
[
new PolicyDetails
{
OrganizationId = org.Id,
OrganizationUserStatus = OrganizationUserStatusType.Accepted,
PolicyType = PolicyType.TwoFactorAuthentication
}
]));
twoFactorIsEnabledQuery.TwoFactorIsEnabledAsync(Arg.Is<IEnumerable<Guid>>(ids => ids.Contains(user.Id)))
.Returns(new List<(Guid userId, bool twoFactorIsEnabled)>() { (user.Id, false) });
var exception = await Assert.ThrowsAsync<BadRequestException>(
() => sutProvider.Sut.ConfirmUserAsync(orgUser.OrganizationId, orgUser.Id, "key", confirmingUser.Id));
Assert.Contains("User does not have two-step login enabled.", exception.Message);
}
[Theory, BitAutoData]
public async Task ConfirmUserAsync_WithPolicyRequirementsEnabled_AndTwoFactorNotRequired_Succeeds(
Organization org, OrganizationUser confirmingUser,
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser orgUser, User user,
SutProvider<ConfirmOrganizationUserCommand> sutProvider)
{
var organizationUserRepository = sutProvider.GetDependency<IOrganizationUserRepository>();
var organizationRepository = sutProvider.GetDependency<IOrganizationRepository>();
var userRepository = sutProvider.GetDependency<IUserRepository>();
var featureService = sutProvider.GetDependency<IFeatureService>();
var policyRequirementQuery = sutProvider.GetDependency<IPolicyRequirementQuery>();
var twoFactorIsEnabledQuery = sutProvider.GetDependency<ITwoFactorIsEnabledQuery>();
org.PlanType = PlanType.EnterpriseAnnually;
orgUser.OrganizationId = confirmingUser.OrganizationId = org.Id;
orgUser.UserId = user.Id;
organizationUserRepository.GetManyAsync(default).ReturnsForAnyArgs(new[] { orgUser });
organizationRepository.GetByIdAsync(org.Id).Returns(org);
userRepository.GetManyAsync(default).ReturnsForAnyArgs(new[] { user });
featureService.IsEnabled(FeatureFlagKeys.PolicyRequirements).Returns(true);
policyRequirementQuery.GetAsync<RequireTwoFactorPolicyRequirement>(user.Id)
.Returns(new RequireTwoFactorPolicyRequirement(
[
new PolicyDetails
{
OrganizationId = Guid.NewGuid(),
OrganizationUserStatus = OrganizationUserStatusType.Invited,
PolicyType = PolicyType.TwoFactorAuthentication,
}
]));
twoFactorIsEnabledQuery.TwoFactorIsEnabledAsync(Arg.Is<IEnumerable<Guid>>(ids => ids.Contains(user.Id)))
.Returns(new List<(Guid userId, bool twoFactorIsEnabled)>() { (user.Id, false) });
await sutProvider.Sut.ConfirmUserAsync(orgUser.OrganizationId, orgUser.Id, "key", confirmingUser.Id);
await sutProvider.GetDependency<IEventService>().Received(1).LogOrganizationUserEventAsync(orgUser, EventType.OrganizationUser_Confirmed);
await sutProvider.GetDependency<IMailService>().Received(1).SendOrganizationConfirmedEmailAsync(org.DisplayName(), user.Email, orgUser.AccessSecretsManager);
await organizationUserRepository.Received(1).ReplaceManyAsync(Arg.Is<List<OrganizationUser>>(users => users.Contains(orgUser) && users.Count == 1));
}
[Theory, BitAutoData]
public async Task ConfirmUserAsync_WithPolicyRequirementsEnabled_AndTwoFactorEnabled_Succeeds(
Organization org, OrganizationUser confirmingUser,
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser orgUser, User user,
SutProvider<ConfirmOrganizationUserCommand> sutProvider)
{
var organizationUserRepository = sutProvider.GetDependency<IOrganizationUserRepository>();
var organizationRepository = sutProvider.GetDependency<IOrganizationRepository>();
var userRepository = sutProvider.GetDependency<IUserRepository>();
var featureService = sutProvider.GetDependency<IFeatureService>();
var policyRequirementQuery = sutProvider.GetDependency<IPolicyRequirementQuery>();
var twoFactorIsEnabledQuery = sutProvider.GetDependency<ITwoFactorIsEnabledQuery>();
org.PlanType = PlanType.EnterpriseAnnually;
orgUser.OrganizationId = confirmingUser.OrganizationId = org.Id;
orgUser.UserId = user.Id;
organizationUserRepository.GetManyAsync(default).ReturnsForAnyArgs(new[] { orgUser });
organizationRepository.GetByIdAsync(org.Id).Returns(org);
userRepository.GetManyAsync(default).ReturnsForAnyArgs(new[] { user });
featureService.IsEnabled(FeatureFlagKeys.PolicyRequirements).Returns(true);
policyRequirementQuery.GetAsync<RequireTwoFactorPolicyRequirement>(user.Id)
.Returns(new RequireTwoFactorPolicyRequirement(
[
new PolicyDetails
{
OrganizationId = org.Id,
OrganizationUserStatus = OrganizationUserStatusType.Accepted,
PolicyType = PolicyType.TwoFactorAuthentication
}
]));
twoFactorIsEnabledQuery.TwoFactorIsEnabledAsync(Arg.Is<IEnumerable<Guid>>(ids => ids.Contains(user.Id)))
.Returns(new List<(Guid userId, bool twoFactorIsEnabled)>() { (user.Id, true) });
await sutProvider.Sut.ConfirmUserAsync(orgUser.OrganizationId, orgUser.Id, "key", confirmingUser.Id);
await sutProvider.GetDependency<IEventService>().Received(1).LogOrganizationUserEventAsync(orgUser, EventType.OrganizationUser_Confirmed);
await sutProvider.GetDependency<IMailService>().Received(1).SendOrganizationConfirmedEmailAsync(org.DisplayName(), user.Email, orgUser.AccessSecretsManager);
await organizationUserRepository.Received(1).ReplaceManyAsync(Arg.Is<List<OrganizationUser>>(users => users.Contains(orgUser) && users.Count == 1));
}
[Theory, BitAutoData]
public async Task ConfirmUserAsync_WithCreateDefaultLocationEnabled_WithOrganizationDataOwnershipPolicyApplicable_WithValidCollectionName_CreatesDefaultCollection(
Organization organization, OrganizationUser confirmingUser,
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser orgUser, User user,
string key, string collectionName, SutProvider<ConfirmOrganizationUserCommand> sutProvider)
{
organization.PlanType = PlanType.EnterpriseAnnually;
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 });
sutProvider.GetDependency<IFeatureService>().IsEnabled(FeatureFlagKeys.CreateDefaultLocation).Returns(true);
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]));
await sutProvider.Sut.ConfirmUserAsync(orgUser.OrganizationId, orgUser.Id, key, confirmingUser.Id, collectionName);
await sutProvider.GetDependency<ICollectionRepository>()
.Received(1)
.CreateAsync(
Arg.Is<Collection>(c =>
c.Name == collectionName &&
c.OrganizationId == organization.Id &&
c.Type == CollectionType.DefaultUserCollection),
Arg.Any<IEnumerable<CollectionAccessSelection>>(),
Arg.Is<IEnumerable<CollectionAccessSelection>>(cu =>
cu.Single().Id == orgUser.Id &&
cu.Single().Manage));
}
[Theory, BitAutoData]
public async Task ConfirmUserAsync_WithCreateDefaultLocationEnabled_WithOrganizationDataOwnershipPolicyApplicable_WithInvalidCollectionName_DoesNotCreateDefaultCollection(
Organization org, OrganizationUser confirmingUser,
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser orgUser, User user,
string key, SutProvider<ConfirmOrganizationUserCommand> sutProvider)
{
org.PlanType = PlanType.EnterpriseAnnually;
orgUser.OrganizationId = confirmingUser.OrganizationId = org.Id;
orgUser.UserId = user.Id;
sutProvider.GetDependency<IOrganizationUserRepository>().GetManyAsync(default).ReturnsForAnyArgs(new[] { orgUser });
sutProvider.GetDependency<IOrganizationRepository>().GetByIdAsync(org.Id).Returns(org);
sutProvider.GetDependency<IUserRepository>().GetManyAsync(default).ReturnsForAnyArgs(new[] { user });
sutProvider.GetDependency<IFeatureService>().IsEnabled(FeatureFlagKeys.CreateDefaultLocation).Returns(true);
await sutProvider.Sut.ConfirmUserAsync(orgUser.OrganizationId, orgUser.Id, key, confirmingUser.Id, "");
await sutProvider.GetDependency<ICollectionRepository>()
.DidNotReceive()
.UpsertDefaultCollectionsAsync(Arg.Any<Guid>(), Arg.Any<IEnumerable<Guid>>(), Arg.Any<string>());
}
[Theory, BitAutoData]
public async Task ConfirmUserAsync_WithCreateDefaultLocationEnabled_WithOrganizationDataOwnershipPolicyNotApplicable_DoesNotCreateDefaultCollection(
Organization org, OrganizationUser confirmingUser,
[OrganizationUser(OrganizationUserStatusType.Accepted, OrganizationUserType.Owner)] OrganizationUser orgUser, User user,
string key, string collectionName, SutProvider<ConfirmOrganizationUserCommand> sutProvider)
{
org.PlanType = PlanType.EnterpriseAnnually;
orgUser.OrganizationId = confirmingUser.OrganizationId = org.Id;
orgUser.UserId = user.Id;
sutProvider.GetDependency<IOrganizationRepository>().GetByIdAsync(org.Id).Returns(org);
sutProvider.GetDependency<IOrganizationUserRepository>().GetManyAsync(default).ReturnsForAnyArgs(new[] { orgUser });
sutProvider.GetDependency<IUserRepository>().GetManyAsync(default).ReturnsForAnyArgs(new[] { user });
sutProvider.GetDependency<IFeatureService>().IsEnabled(FeatureFlagKeys.CreateDefaultLocation).Returns(true);
var policyDetails = new PolicyDetails
{
OrganizationId = org.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.Disabled, [policyDetails]));
await sutProvider.Sut.ConfirmUserAsync(orgUser.OrganizationId, orgUser.Id, key, confirmingUser.Id, collectionName);
await sutProvider.GetDependency<ICollectionRepository>()
.DidNotReceive()
.UpsertDefaultCollectionsAsync(Arg.Any<Guid>(), Arg.Any<IEnumerable<Guid>>(), Arg.Any<string>());
}
[Theory, BitAutoData]
public async Task ConfirmUserAsync_WithAutoConfirmEnabledAndUserBelongsToAnotherOrg_ThrowsBadRequest(
Organization org, OrganizationUser confirmingUser,
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser orgUser, User user,
OrganizationUser otherOrgUser, string key, SutProvider<ConfirmOrganizationUserCommand> sutProvider)
{
org.PlanType = PlanType.EnterpriseAnnually;
orgUser.OrganizationId = confirmingUser.OrganizationId = org.Id;
orgUser.UserId = user.Id;
otherOrgUser.UserId = user.Id;
otherOrgUser.OrganizationId = Guid.NewGuid(); // Different org
sutProvider.GetDependency<IOrganizationUserRepository>()
.GetManyAsync([]).ReturnsForAnyArgs([orgUser]);
sutProvider.GetDependency<IOrganizationUserRepository>()
.GetManyByManyUsersAsync([])
.ReturnsForAnyArgs([orgUser, otherOrgUser]);
sutProvider.GetDependency<IOrganizationRepository>().GetByIdAsync(org.Id).Returns(org);
sutProvider.GetDependency<IUserRepository>().GetManyAsync([]).ReturnsForAnyArgs([user]);
sutProvider.GetDependency<IFeatureService>()
.IsEnabled(FeatureFlagKeys.AutomaticConfirmUsers)
.Returns(true);
sutProvider.GetDependency<IAutomaticUserConfirmationPolicyEnforcementValidator>()
.IsCompliantAsync(Arg.Any<AutomaticUserConfirmationPolicyEnforcementRequest>())
.Returns(Invalid(
new AutomaticUserConfirmationPolicyEnforcementRequest(orgUser.Id, [orgUser, otherOrgUser], user),
new OrganizationEnforcesSingleOrgPolicy()));
var exception = await Assert.ThrowsAsync<BadRequestException>(
() => sutProvider.Sut.ConfirmUserAsync(orgUser.OrganizationId, orgUser.Id, key, confirmingUser.Id));
Assert.Equal(new OrganizationEnforcesSingleOrgPolicy().Message, exception.Message);
}
[Theory, BitAutoData]
public async Task ConfirmUserAsync_WithAutoConfirmEnabledForOtherOrg_ThrowsBadRequest(
Organization org, OrganizationUser confirmingUser,
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser orgUser, User user,
OrganizationUser otherOrgUser, string key, SutProvider<ConfirmOrganizationUserCommand> sutProvider)
{
// Arrange
org.PlanType = PlanType.EnterpriseAnnually;
orgUser.OrganizationId = confirmingUser.OrganizationId = org.Id;
orgUser.UserId = user.Id;
otherOrgUser.UserId = user.Id;
otherOrgUser.OrganizationId = Guid.NewGuid();
sutProvider.GetDependency<IOrganizationUserRepository>()
.GetManyAsync([]).ReturnsForAnyArgs([orgUser]);
sutProvider.GetDependency<IOrganizationUserRepository>()
.GetManyByManyUsersAsync([])
.ReturnsForAnyArgs([orgUser, otherOrgUser]);
sutProvider.GetDependency<IOrganizationRepository>().GetByIdAsync(org.Id).Returns(org);
sutProvider.GetDependency<IUserRepository>().GetManyAsync([]).ReturnsForAnyArgs([user]);
sutProvider.GetDependency<IFeatureService>()
.IsEnabled(FeatureFlagKeys.AutomaticConfirmUsers)
.Returns(true);
sutProvider.GetDependency<IAutomaticUserConfirmationPolicyEnforcementValidator>()
.IsCompliantAsync(Arg.Any<AutomaticUserConfirmationPolicyEnforcementRequest>())
.Returns(Invalid(
new AutomaticUserConfirmationPolicyEnforcementRequest(org.Id, [orgUser, otherOrgUser], user),
new OtherOrganizationDoesNotAllowOtherMembership()));
// Act & Assert
var exception = await Assert.ThrowsAsync<BadRequestException>(
() => sutProvider.Sut.ConfirmUserAsync(orgUser.OrganizationId, orgUser.Id, key, confirmingUser.Id));
Assert.Equal(new OtherOrganizationDoesNotAllowOtherMembership().Message, exception.Message);
}
[Theory, BitAutoData]
public async Task ConfirmUserAsync_WithAutoConfirmEnabledAndUserIsProvider_ThrowsBadRequest(
Organization org, OrganizationUser confirmingUser,
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser orgUser, User user,
string key, SutProvider<ConfirmOrganizationUserCommand> sutProvider)
{
// Arrange
org.PlanType = PlanType.EnterpriseAnnually;
orgUser.OrganizationId = confirmingUser.OrganizationId = org.Id;
orgUser.UserId = user.Id;
sutProvider.GetDependency<IOrganizationUserRepository>()
.GetManyAsync([]).ReturnsForAnyArgs([orgUser]);
sutProvider.GetDependency<IOrganizationUserRepository>()
.GetManyByManyUsersAsync([])
.ReturnsForAnyArgs([orgUser]);
sutProvider.GetDependency<IOrganizationRepository>().GetByIdAsync(org.Id).Returns(org);
sutProvider.GetDependency<IUserRepository>().GetManyAsync([]).ReturnsForAnyArgs([user]);
sutProvider.GetDependency<IFeatureService>()
.IsEnabled(FeatureFlagKeys.AutomaticConfirmUsers)
.Returns(true);
sutProvider.GetDependency<IAutomaticUserConfirmationPolicyEnforcementValidator>()
.IsCompliantAsync(Arg.Any<AutomaticUserConfirmationPolicyEnforcementRequest>())
.Returns(Invalid(
new AutomaticUserConfirmationPolicyEnforcementRequest(org.Id, [orgUser], user),
new ProviderUsersCannotJoin()));
// Act & Assert
var exception = await Assert.ThrowsAsync<BadRequestException>(
() => sutProvider.Sut.ConfirmUserAsync(orgUser.OrganizationId, orgUser.Id, key, confirmingUser.Id));
Assert.Equal(new ProviderUsersCannotJoin().Message, exception.Message);
}
[Theory, BitAutoData]
public async Task ConfirmUserAsync_WithAutoConfirmNotApplicable_Succeeds(
Organization org, OrganizationUser confirmingUser,
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser orgUser, User user,
string key, SutProvider<ConfirmOrganizationUserCommand> sutProvider)
{
// Arrange
org.PlanType = PlanType.EnterpriseAnnually;
orgUser.OrganizationId = confirmingUser.OrganizationId = org.Id;
orgUser.UserId = user.Id;
sutProvider.GetDependency<IOrganizationUserRepository>()
.GetManyAsync([]).ReturnsForAnyArgs([orgUser]);
sutProvider.GetDependency<IOrganizationUserRepository>()
.GetManyByManyUsersAsync([])
.ReturnsForAnyArgs([orgUser]);
sutProvider.GetDependency<IOrganizationRepository>().GetByIdAsync(org.Id).Returns(org);
sutProvider.GetDependency<IUserRepository>().GetManyAsync([]).ReturnsForAnyArgs([user]);
sutProvider.GetDependency<IFeatureService>()
.IsEnabled(FeatureFlagKeys.AutomaticConfirmUsers)
.Returns(true);
sutProvider.GetDependency<IAutomaticUserConfirmationPolicyEnforcementValidator>()
.IsCompliantAsync(Arg.Any<AutomaticUserConfirmationPolicyEnforcementRequest>())
.Returns(Valid(new AutomaticUserConfirmationPolicyEnforcementRequest(org.Id, [orgUser], user)));
// Act
await sutProvider.Sut.ConfirmUserAsync(orgUser.OrganizationId, orgUser.Id, key, confirmingUser.Id);
// Assert
await sutProvider.GetDependency<IEventService>()
.Received(1).LogOrganizationUserEventAsync(orgUser, EventType.OrganizationUser_Confirmed);
await sutProvider.GetDependency<IMailService>()
.Received(1).SendOrganizationConfirmedEmailAsync(org.DisplayName(), user.Email, orgUser.AccessSecretsManager);
}
[Theory, BitAutoData]
public async Task ConfirmUserAsync_WithAutoConfirmValidationBeforeSingleOrgPolicy_ChecksAutoConfirmFirst(
Organization org, OrganizationUser confirmingUser,
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser orgUser, User user,
OrganizationUser otherOrgUser,
[OrganizationUserPolicyDetails(PolicyType.SingleOrg)] OrganizationUserPolicyDetails singleOrgPolicy,
string key, SutProvider<ConfirmOrganizationUserCommand> sutProvider)
{
// Arrange - Setup conditions that would fail BOTH auto-confirm AND single org policy
org.PlanType = PlanType.EnterpriseAnnually;
orgUser.OrganizationId = confirmingUser.OrganizationId = org.Id;
orgUser.UserId = user.Id;
otherOrgUser.UserId = user.Id;
otherOrgUser.OrganizationId = Guid.NewGuid();
sutProvider.GetDependency<IOrganizationUserRepository>()
.GetManyAsync([]).ReturnsForAnyArgs([orgUser]);
sutProvider.GetDependency<IOrganizationUserRepository>()
.GetManyByManyUsersAsync([])
.ReturnsForAnyArgs([orgUser, otherOrgUser]);
sutProvider.GetDependency<IOrganizationRepository>().GetByIdAsync(org.Id).Returns(org);
sutProvider.GetDependency<IUserRepository>().GetManyAsync([]).ReturnsForAnyArgs([user]);
sutProvider.GetDependency<IFeatureService>()
.IsEnabled(FeatureFlagKeys.AutomaticConfirmUsers)
.Returns(true);
singleOrgPolicy.OrganizationId = org.Id;
sutProvider.GetDependency<IPolicyService>()
.GetPoliciesApplicableToUserAsync(user.Id, PolicyType.SingleOrg)
.Returns([singleOrgPolicy]);
sutProvider.GetDependency<IAutomaticUserConfirmationPolicyEnforcementValidator>()
.IsCompliantAsync(Arg.Any<AutomaticUserConfirmationPolicyEnforcementRequest>())
.Returns(Invalid(
new AutomaticUserConfirmationPolicyEnforcementRequest(org.Id, [orgUser, otherOrgUser], user),
new OrganizationEnforcesSingleOrgPolicy()));
// Act & Assert
var exception = await Assert.ThrowsAsync<BadRequestException>(
() => sutProvider.Sut.ConfirmUserAsync(orgUser.OrganizationId, orgUser.Id, key, confirmingUser.Id));
Assert.Equal(new OrganizationEnforcesSingleOrgPolicy().Message, exception.Message);
Assert.NotEqual("Cannot confirm this member to the organization until they leave or remove all other organizations.",
exception.Message);
}
[Theory, BitAutoData]
public async Task ConfirmUsersAsync_WithAutoConfirmEnabled_MixedResults(
Organization org, OrganizationUser confirmingUser,
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser orgUser1,
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser orgUser2,
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser orgUser3,
OrganizationUser otherOrgUser, User user1, User user2, User user3,
string key, SutProvider<ConfirmOrganizationUserCommand> sutProvider)
{
// Arrange
org.PlanType = PlanType.EnterpriseAnnually;
orgUser1.OrganizationId = orgUser2.OrganizationId = orgUser3.OrganizationId = confirmingUser.OrganizationId = org.Id;
orgUser1.UserId = user1.Id;
orgUser2.UserId = user2.Id;
orgUser3.UserId = user3.Id;
otherOrgUser.UserId = user3.Id;
otherOrgUser.OrganizationId = Guid.NewGuid();
var orgUsers = new[] { orgUser1, orgUser2, orgUser3 };
sutProvider.GetDependency<IOrganizationUserRepository>()
.GetManyAsync([]).ReturnsForAnyArgs(orgUsers);
sutProvider.GetDependency<IOrganizationRepository>().GetByIdAsync(org.Id).Returns(org);
sutProvider.GetDependency<IUserRepository>()
.GetManyAsync([]).ReturnsForAnyArgs([user1, user2, user3]);
sutProvider.GetDependency<IOrganizationUserRepository>()
.GetManyByManyUsersAsync([])
.ReturnsForAnyArgs([orgUser1, orgUser2, orgUser3, otherOrgUser]);
sutProvider.GetDependency<IFeatureService>()
.IsEnabled(FeatureFlagKeys.AutomaticConfirmUsers)
.Returns(true);
sutProvider.GetDependency<IAutomaticUserConfirmationPolicyEnforcementValidator>()
.IsCompliantAsync(Arg.Is<AutomaticUserConfirmationPolicyEnforcementRequest>(r => r.User.Id == user1.Id))
.Returns(Valid(new AutomaticUserConfirmationPolicyEnforcementRequest(org.Id, [orgUser1], user1)));
sutProvider.GetDependency<IAutomaticUserConfirmationPolicyEnforcementValidator>()
.IsCompliantAsync(Arg.Is<AutomaticUserConfirmationPolicyEnforcementRequest>(r => r.User.Id == user2.Id))
.Returns(Valid(new AutomaticUserConfirmationPolicyEnforcementRequest(org.Id, [orgUser2], user2)));
sutProvider.GetDependency<IAutomaticUserConfirmationPolicyEnforcementValidator>()
.IsCompliantAsync(Arg.Is<AutomaticUserConfirmationPolicyEnforcementRequest>(r => r.User.Id == user3.Id))
.Returns(Invalid(
new AutomaticUserConfirmationPolicyEnforcementRequest(org.Id, [orgUser3, otherOrgUser], user3),
new OtherOrganizationDoesNotAllowOtherMembership()));
var keys = orgUsers.ToDictionary(ou => ou.Id, _ => key);
// Act
var result = await sutProvider.Sut.ConfirmUsersAsync(confirmingUser.OrganizationId, keys, confirmingUser.Id);
// Assert
Assert.Equal(3, result.Count);
Assert.Empty(result[0].Item2);
Assert.Empty(result[1].Item2);
Assert.Equal(new OtherOrganizationDoesNotAllowOtherMembership().Message, result[2].Item2);
}
}