mirror of
https://github.com/bitwarden/server
synced 2026-01-07 11:03:37 +00:00
Merge remote-tracking branch 'origin/main' into xunit-v3-full-upgrade
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
using System.Text.Json;
|
||||
using System.Reflection;
|
||||
using System.Text.Json;
|
||||
using AutoFixture;
|
||||
using AutoFixture.Kernel;
|
||||
using AutoFixture.Xunit2;
|
||||
using Bit.Core.AdminConsole.Entities;
|
||||
using Bit.Core.Auth.Enums;
|
||||
using Bit.Core.Auth.Models;
|
||||
@@ -20,6 +22,18 @@ public class OrganizationCustomization : ICustomization
|
||||
{
|
||||
public bool UseGroups { get; set; }
|
||||
public PlanType PlanType { get; set; }
|
||||
public bool UseAutomaticUserConfirmation { get; set; }
|
||||
|
||||
public OrganizationCustomization()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public OrganizationCustomization(bool useAutomaticUserConfirmation, PlanType planType)
|
||||
{
|
||||
UseAutomaticUserConfirmation = useAutomaticUserConfirmation;
|
||||
PlanType = planType;
|
||||
}
|
||||
|
||||
public void Customize(IFixture fixture)
|
||||
{
|
||||
@@ -37,7 +51,8 @@ public class OrganizationCustomization : ICustomization
|
||||
.With(o => o.UseGroups, UseGroups)
|
||||
.With(o => o.PlanType, PlanType)
|
||||
.With(o => o.Seats, seats)
|
||||
.With(o => o.SmSeats, smSeats));
|
||||
.With(o => o.SmSeats, smSeats)
|
||||
.With(o => o.UseAutomaticUserConfirmation, UseAutomaticUserConfirmation));
|
||||
|
||||
fixture.Customize<Collection>(composer =>
|
||||
composer
|
||||
@@ -277,3 +292,9 @@ internal class EphemeralDataProtectionAutoDataAttribute : CustomAutoDataAttribut
|
||||
public EphemeralDataProtectionAutoDataAttribute() : base(new SutProviderCustomization(), new EphemeralDataProtectionCustomization())
|
||||
{ }
|
||||
}
|
||||
|
||||
internal class OrganizationAttribute(bool useAutomaticUserConfirmation = false, PlanType planType = PlanType.Free) : CustomizeAttribute
|
||||
{
|
||||
public override ICustomization GetCustomization(ParameterInfo parameter) =>
|
||||
new OrganizationCustomization(useAutomaticUserConfirmation, planType);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,696 @@
|
||||
using Bit.Core.AdminConsole.Entities;
|
||||
using Bit.Core.AdminConsole.Enums;
|
||||
using Bit.Core.AdminConsole.Models.Data;
|
||||
using Bit.Core.AdminConsole.Models.Data.Organizations.Policies;
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.AutoConfirmUser;
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.DeleteClaimedAccount;
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.Policies;
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.Policies.PolicyRequirements;
|
||||
using Bit.Core.AdminConsole.Repositories;
|
||||
using Bit.Core.Auth.UserFeatures.TwoFactorAuth.Interfaces;
|
||||
using Bit.Core.Billing.Enums;
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.Test.AdminConsole.AutoFixture;
|
||||
using Bit.Core.Test.AutoFixture.OrganizationFixtures;
|
||||
using Bit.Core.Test.AutoFixture.OrganizationUserFixtures;
|
||||
using Bit.Test.Common.AutoFixture;
|
||||
using Bit.Test.Common.AutoFixture.Attributes;
|
||||
using NSubstitute;
|
||||
using Xunit;
|
||||
|
||||
namespace Bit.Core.Test.AdminConsole.OrganizationFeatures.OrganizationUsers.AutoConfirmUsers;
|
||||
|
||||
[SutProviderCustomize]
|
||||
public class AutomaticallyConfirmOrganizationUsersValidatorTests
|
||||
{
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task ValidateAsync_WithNullOrganizationUser_ReturnsUserNotFoundError(
|
||||
SutProvider<AutomaticallyConfirmOrganizationUsersValidator> sutProvider,
|
||||
Organization organization)
|
||||
{
|
||||
// Arrange
|
||||
var request = new AutomaticallyConfirmOrganizationUserValidationRequest
|
||||
{
|
||||
PerformedBy = Substitute.For<IActingUser>(),
|
||||
DefaultUserCollectionName = "test-collection",
|
||||
OrganizationUser = null,
|
||||
OrganizationUserId = Guid.NewGuid(),
|
||||
Organization = organization,
|
||||
OrganizationId = organization.Id,
|
||||
Key = "test-key"
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = await sutProvider.Sut.ValidateAsync(request);
|
||||
|
||||
// Assert
|
||||
Assert.True(result.IsError);
|
||||
Assert.IsType<UserNotFoundError>(result.AsError);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task ValidateAsync_WithNullUserId_ReturnsUserNotFoundError(
|
||||
SutProvider<AutomaticallyConfirmOrganizationUsersValidator> sutProvider,
|
||||
Organization organization,
|
||||
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser organizationUser)
|
||||
{
|
||||
// Arrange
|
||||
organizationUser.UserId = null;
|
||||
organizationUser.OrganizationId = organization.Id;
|
||||
|
||||
var request = new AutomaticallyConfirmOrganizationUserValidationRequest
|
||||
{
|
||||
PerformedBy = Substitute.For<IActingUser>(),
|
||||
DefaultUserCollectionName = "test-collection",
|
||||
OrganizationUser = organizationUser,
|
||||
OrganizationUserId = organizationUser.Id,
|
||||
Organization = organization,
|
||||
OrganizationId = organization.Id,
|
||||
Key = "test-key"
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = await sutProvider.Sut.ValidateAsync(request);
|
||||
|
||||
// Assert
|
||||
Assert.True(result.IsError);
|
||||
Assert.IsType<UserNotFoundError>(result.AsError);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task ValidateAsync_WithNullOrganization_ReturnsOrganizationNotFoundError(
|
||||
SutProvider<AutomaticallyConfirmOrganizationUsersValidator> sutProvider,
|
||||
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser organizationUser,
|
||||
Guid userId)
|
||||
{
|
||||
// Arrange
|
||||
organizationUser.UserId = userId;
|
||||
|
||||
var request = new AutomaticallyConfirmOrganizationUserValidationRequest
|
||||
{
|
||||
PerformedBy = Substitute.For<IActingUser>(),
|
||||
DefaultUserCollectionName = "test-collection",
|
||||
OrganizationUser = organizationUser,
|
||||
OrganizationUserId = organizationUser.Id,
|
||||
Organization = null,
|
||||
OrganizationId = organizationUser.OrganizationId,
|
||||
Key = "test-key"
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = await sutProvider.Sut.ValidateAsync(request);
|
||||
|
||||
// Assert
|
||||
Assert.True(result.IsError);
|
||||
Assert.IsType<OrganizationNotFound>(result.AsError);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task ValidateAsync_WithValidAcceptedUser_ReturnsValidResult(
|
||||
SutProvider<AutomaticallyConfirmOrganizationUsersValidator> sutProvider,
|
||||
[Organization(useAutomaticUserConfirmation: true, planType: PlanType.EnterpriseAnnually)] Organization organization,
|
||||
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser organizationUser,
|
||||
Guid userId,
|
||||
[Policy(PolicyType.AutomaticUserConfirmation)] Policy autoConfirmPolicy)
|
||||
{
|
||||
// Arrange
|
||||
organizationUser.UserId = userId;
|
||||
organizationUser.OrganizationId = organization.Id;
|
||||
|
||||
var request = new AutomaticallyConfirmOrganizationUserValidationRequest
|
||||
{
|
||||
PerformedBy = Substitute.For<IActingUser>(),
|
||||
DefaultUserCollectionName = "test-collection",
|
||||
OrganizationUser = organizationUser,
|
||||
OrganizationUserId = organizationUser.Id,
|
||||
Organization = organization,
|
||||
OrganizationId = organization.Id,
|
||||
Key = "test-key"
|
||||
};
|
||||
|
||||
sutProvider.GetDependency<IPolicyRepository>()
|
||||
.GetByOrganizationIdTypeAsync(organization.Id, PolicyType.AutomaticUserConfirmation)
|
||||
.Returns(autoConfirmPolicy);
|
||||
|
||||
sutProvider.GetDependency<ITwoFactorIsEnabledQuery>()
|
||||
.TwoFactorIsEnabledAsync(Arg.Any<IEnumerable<Guid>>())
|
||||
.Returns([(userId, true)]);
|
||||
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||
.GetManyByUserAsync(userId)
|
||||
.Returns([organizationUser]);
|
||||
|
||||
// Act
|
||||
var result = await sutProvider.Sut.ValidateAsync(request);
|
||||
|
||||
// Assert
|
||||
Assert.True(result.IsValid);
|
||||
Assert.Equal(request, result.Request);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task ValidateAsync_WithMismatchedOrganizationId_ReturnsOrganizationUserIdIsInvalidError(
|
||||
SutProvider<AutomaticallyConfirmOrganizationUsersValidator> sutProvider,
|
||||
Organization organization,
|
||||
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser organizationUser,
|
||||
Guid userId)
|
||||
{
|
||||
// Arrange
|
||||
organizationUser.UserId = userId;
|
||||
organizationUser.OrganizationId = Guid.NewGuid(); // Different from organization.Id
|
||||
|
||||
var request = new AutomaticallyConfirmOrganizationUserValidationRequest
|
||||
{
|
||||
PerformedBy = Substitute.For<IActingUser>(),
|
||||
DefaultUserCollectionName = "test-collection",
|
||||
OrganizationUser = organizationUser,
|
||||
OrganizationUserId = organizationUser.Id,
|
||||
Organization = organization,
|
||||
OrganizationId = organization.Id,
|
||||
Key = "test-key"
|
||||
};
|
||||
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||
.GetManyByUserAsync(userId)
|
||||
.Returns([organizationUser]);
|
||||
|
||||
// Act
|
||||
var result = await sutProvider.Sut.ValidateAsync(request);
|
||||
|
||||
// Assert
|
||||
Assert.True(result.IsError);
|
||||
Assert.IsType<OrganizationUserIdIsInvalid>(result.AsError);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData(OrganizationUserStatusType.Invited)]
|
||||
[BitAutoData(OrganizationUserStatusType.Revoked)]
|
||||
[BitAutoData(OrganizationUserStatusType.Confirmed)]
|
||||
public async Task ValidateAsync_WithNotAcceptedStatus_ReturnsUserIsNotAcceptedError(
|
||||
OrganizationUserStatusType statusType,
|
||||
SutProvider<AutomaticallyConfirmOrganizationUsersValidator> sutProvider,
|
||||
Organization organization,
|
||||
[OrganizationUser(OrganizationUserStatusType.Revoked)] OrganizationUser organizationUser,
|
||||
Guid userId)
|
||||
{
|
||||
// Arrange
|
||||
organizationUser.UserId = userId;
|
||||
organizationUser.OrganizationId = organization.Id;
|
||||
organizationUser.Status = statusType;
|
||||
|
||||
var request = new AutomaticallyConfirmOrganizationUserValidationRequest
|
||||
{
|
||||
PerformedBy = Substitute.For<IActingUser>(),
|
||||
DefaultUserCollectionName = "test-collection",
|
||||
OrganizationUser = organizationUser,
|
||||
OrganizationUserId = organizationUser.Id,
|
||||
Organization = organization,
|
||||
OrganizationId = organization.Id,
|
||||
Key = "test-key"
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = await sutProvider.Sut.ValidateAsync(request);
|
||||
|
||||
// Assert
|
||||
Assert.True(result.IsError);
|
||||
Assert.IsType<UserIsNotAccepted>(result.AsError);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData(OrganizationUserType.Owner)]
|
||||
[BitAutoData(OrganizationUserType.Custom)]
|
||||
[BitAutoData(OrganizationUserType.Admin)]
|
||||
public async Task ValidateAsync_WithNonUserType_ReturnsUserIsNotUserTypeError(
|
||||
OrganizationUserType userType,
|
||||
SutProvider<AutomaticallyConfirmOrganizationUsersValidator> sutProvider,
|
||||
Organization organization,
|
||||
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser organizationUser,
|
||||
Guid userId)
|
||||
{
|
||||
// Arrange
|
||||
organizationUser.UserId = userId;
|
||||
organizationUser.OrganizationId = organization.Id;
|
||||
organizationUser.Type = userType;
|
||||
|
||||
var request = new AutomaticallyConfirmOrganizationUserValidationRequest
|
||||
{
|
||||
PerformedBy = Substitute.For<IActingUser>(),
|
||||
DefaultUserCollectionName = "test-collection",
|
||||
OrganizationUser = organizationUser,
|
||||
OrganizationUserId = organizationUser.Id,
|
||||
Organization = organization,
|
||||
OrganizationId = organization.Id,
|
||||
Key = "test-key"
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = await sutProvider.Sut.ValidateAsync(request);
|
||||
|
||||
// Assert
|
||||
Assert.True(result.IsError);
|
||||
Assert.IsType<UserIsNotUserType>(result.AsError);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task ValidateAsync_UserWithout2FA_And2FARequired_ReturnsError(
|
||||
SutProvider<AutomaticallyConfirmOrganizationUsersValidator> sutProvider,
|
||||
[Organization(useAutomaticUserConfirmation: true)] Organization organization,
|
||||
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser organizationUser,
|
||||
Guid userId,
|
||||
[Policy(PolicyType.AutomaticUserConfirmation)] Policy autoConfirmPolicy)
|
||||
{
|
||||
// Arrange
|
||||
organizationUser.UserId = userId;
|
||||
organizationUser.OrganizationId = organization.Id;
|
||||
|
||||
var request = new AutomaticallyConfirmOrganizationUserValidationRequest
|
||||
{
|
||||
PerformedBy = Substitute.For<IActingUser>(),
|
||||
DefaultUserCollectionName = "test-collection",
|
||||
OrganizationUser = organizationUser,
|
||||
OrganizationUserId = organizationUser.Id,
|
||||
Organization = organization,
|
||||
OrganizationId = organization.Id,
|
||||
Key = "test-key"
|
||||
};
|
||||
|
||||
var twoFactorPolicyDetails = new PolicyDetails
|
||||
{
|
||||
OrganizationId = organization.Id,
|
||||
PolicyType = PolicyType.TwoFactorAuthentication
|
||||
};
|
||||
|
||||
sutProvider.GetDependency<IPolicyRepository>()
|
||||
.GetByOrganizationIdTypeAsync(organization.Id, PolicyType.AutomaticUserConfirmation)
|
||||
.Returns(autoConfirmPolicy);
|
||||
|
||||
sutProvider.GetDependency<ITwoFactorIsEnabledQuery>()
|
||||
.TwoFactorIsEnabledAsync(Arg.Any<IEnumerable<Guid>>())
|
||||
.Returns([(userId, false)]);
|
||||
|
||||
sutProvider.GetDependency<IPolicyRequirementQuery>()
|
||||
.GetAsync<RequireTwoFactorPolicyRequirement>(userId)
|
||||
.Returns(new RequireTwoFactorPolicyRequirement([twoFactorPolicyDetails]));
|
||||
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||
.GetManyByUserAsync(userId)
|
||||
.Returns([organizationUser]);
|
||||
|
||||
// Act
|
||||
var result = await sutProvider.Sut.ValidateAsync(request);
|
||||
|
||||
// Assert
|
||||
Assert.True(result.IsError);
|
||||
Assert.IsType<UserDoesNotHaveTwoFactorEnabled>(result.AsError);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task ValidateAsync_UserWith2FA_ReturnsValidResult(
|
||||
SutProvider<AutomaticallyConfirmOrganizationUsersValidator> sutProvider,
|
||||
[Organization(useAutomaticUserConfirmation: true)] Organization organization,
|
||||
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser organizationUser,
|
||||
Guid userId,
|
||||
[Policy(PolicyType.AutomaticUserConfirmation)] Policy autoConfirmPolicy)
|
||||
{
|
||||
// Arrange
|
||||
organizationUser.UserId = userId;
|
||||
organizationUser.OrganizationId = organization.Id;
|
||||
|
||||
var request = new AutomaticallyConfirmOrganizationUserValidationRequest
|
||||
{
|
||||
PerformedBy = Substitute.For<IActingUser>(),
|
||||
DefaultUserCollectionName = "test-collection",
|
||||
OrganizationUser = organizationUser,
|
||||
OrganizationUserId = organizationUser.Id,
|
||||
Organization = organization,
|
||||
OrganizationId = organization.Id,
|
||||
Key = "test-key"
|
||||
};
|
||||
|
||||
sutProvider.GetDependency<IPolicyRepository>()
|
||||
.GetByOrganizationIdTypeAsync(organization.Id, PolicyType.AutomaticUserConfirmation)
|
||||
.Returns(autoConfirmPolicy);
|
||||
|
||||
sutProvider.GetDependency<ITwoFactorIsEnabledQuery>()
|
||||
.TwoFactorIsEnabledAsync(Arg.Any<IEnumerable<Guid>>())
|
||||
.Returns([(userId, true)]);
|
||||
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||
.GetManyByUserAsync(userId)
|
||||
.Returns([organizationUser]);
|
||||
|
||||
// Act
|
||||
var result = await sutProvider.Sut.ValidateAsync(request);
|
||||
|
||||
// Assert
|
||||
Assert.True(result.IsValid);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task ValidateAsync_UserWithout2FA_And2FANotRequired_ReturnsValidResult(
|
||||
SutProvider<AutomaticallyConfirmOrganizationUsersValidator> sutProvider,
|
||||
[Organization(useAutomaticUserConfirmation: true)] Organization organization,
|
||||
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser organizationUser,
|
||||
Guid userId,
|
||||
[Policy(PolicyType.AutomaticUserConfirmation)] Policy autoConfirmPolicy)
|
||||
{
|
||||
// Arrange
|
||||
organizationUser.UserId = userId;
|
||||
organizationUser.OrganizationId = organization.Id;
|
||||
|
||||
var request = new AutomaticallyConfirmOrganizationUserValidationRequest
|
||||
{
|
||||
PerformedBy = Substitute.For<IActingUser>(),
|
||||
DefaultUserCollectionName = "test-collection",
|
||||
OrganizationUser = organizationUser,
|
||||
OrganizationUserId = organizationUser.Id,
|
||||
Organization = organization,
|
||||
OrganizationId = organization.Id,
|
||||
Key = "test-key"
|
||||
};
|
||||
|
||||
sutProvider.GetDependency<IPolicyRepository>()
|
||||
.GetByOrganizationIdTypeAsync(organization.Id, PolicyType.AutomaticUserConfirmation)
|
||||
.Returns(autoConfirmPolicy);
|
||||
|
||||
sutProvider.GetDependency<ITwoFactorIsEnabledQuery>()
|
||||
.TwoFactorIsEnabledAsync(Arg.Any<IEnumerable<Guid>>())
|
||||
.Returns([(userId, false)]);
|
||||
|
||||
sutProvider.GetDependency<IPolicyRequirementQuery>()
|
||||
.GetAsync<RequireTwoFactorPolicyRequirement>(userId)
|
||||
.Returns(new RequireTwoFactorPolicyRequirement([])); // No 2FA policy
|
||||
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||
.GetManyByUserAsync(userId)
|
||||
.Returns([organizationUser]);
|
||||
|
||||
// Act
|
||||
var result = await sutProvider.Sut.ValidateAsync(request);
|
||||
|
||||
// Assert
|
||||
Assert.True(result.IsValid);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task ValidateAsync_UserInMultipleOrgs_WithSingleOrgPolicyOnThisOrg_ReturnsError(
|
||||
SutProvider<AutomaticallyConfirmOrganizationUsersValidator> sutProvider,
|
||||
[Organization(useAutomaticUserConfirmation: true)] Organization organization,
|
||||
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser organizationUser,
|
||||
OrganizationUser otherOrgUser,
|
||||
Guid userId,
|
||||
[Policy(PolicyType.AutomaticUserConfirmation)] Policy autoConfirmPolicy)
|
||||
{
|
||||
// Arrange
|
||||
organizationUser.UserId = userId;
|
||||
organizationUser.OrganizationId = organization.Id;
|
||||
|
||||
var request = new AutomaticallyConfirmOrganizationUserValidationRequest
|
||||
{
|
||||
PerformedBy = Substitute.For<IActingUser>(),
|
||||
DefaultUserCollectionName = "test-collection",
|
||||
OrganizationUser = organizationUser,
|
||||
OrganizationUserId = organizationUser.Id,
|
||||
Organization = organization,
|
||||
OrganizationId = organization.Id,
|
||||
Key = "test-key"
|
||||
};
|
||||
|
||||
var singleOrgPolicyDetails = new PolicyDetails
|
||||
{
|
||||
OrganizationId = organization.Id,
|
||||
PolicyType = PolicyType.SingleOrg
|
||||
};
|
||||
|
||||
sutProvider.GetDependency<IPolicyRepository>()
|
||||
.GetByOrganizationIdTypeAsync(organization.Id, PolicyType.AutomaticUserConfirmation)
|
||||
.Returns(autoConfirmPolicy);
|
||||
|
||||
sutProvider.GetDependency<ITwoFactorIsEnabledQuery>()
|
||||
.TwoFactorIsEnabledAsync(Arg.Any<IEnumerable<Guid>>())
|
||||
.Returns([(userId, true)]);
|
||||
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||
.GetManyByUserAsync(userId)
|
||||
.Returns([organizationUser, otherOrgUser]);
|
||||
|
||||
sutProvider.GetDependency<IPolicyRequirementQuery>()
|
||||
.GetAsync<SingleOrganizationPolicyRequirement>(userId)
|
||||
.Returns(new SingleOrganizationPolicyRequirement([singleOrgPolicyDetails]));
|
||||
|
||||
// Act
|
||||
var result = await sutProvider.Sut.ValidateAsync(request);
|
||||
|
||||
// Assert
|
||||
Assert.True(result.IsError);
|
||||
Assert.IsType<OrganizationEnforcesSingleOrgPolicy>(result.AsError);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task ValidateAsync_UserInMultipleOrgs_WithSingleOrgPolicyOnOtherOrg_ReturnsError(
|
||||
SutProvider<AutomaticallyConfirmOrganizationUsersValidator> sutProvider,
|
||||
[Organization(useAutomaticUserConfirmation: true)] Organization organization,
|
||||
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser organizationUser,
|
||||
OrganizationUser otherOrgUser,
|
||||
Guid userId,
|
||||
[Policy(PolicyType.AutomaticUserConfirmation)] Policy autoConfirmPolicy)
|
||||
{
|
||||
// Arrange
|
||||
organizationUser.UserId = userId;
|
||||
organizationUser.OrganizationId = organization.Id;
|
||||
|
||||
var request = new AutomaticallyConfirmOrganizationUserValidationRequest
|
||||
{
|
||||
PerformedBy = Substitute.For<IActingUser>(),
|
||||
DefaultUserCollectionName = "test-collection",
|
||||
OrganizationUser = organizationUser,
|
||||
OrganizationUserId = organizationUser.Id,
|
||||
Organization = organization,
|
||||
OrganizationId = organization.Id,
|
||||
Key = "test-key"
|
||||
};
|
||||
|
||||
var otherOrgId = Guid.NewGuid(); // Different org
|
||||
var singleOrgPolicyDetails = new PolicyDetails
|
||||
{
|
||||
OrganizationId = otherOrgId,
|
||||
PolicyType = PolicyType.SingleOrg,
|
||||
};
|
||||
|
||||
sutProvider.GetDependency<IPolicyRepository>()
|
||||
.GetByOrganizationIdTypeAsync(organization.Id, PolicyType.AutomaticUserConfirmation)
|
||||
.Returns(autoConfirmPolicy);
|
||||
|
||||
sutProvider.GetDependency<ITwoFactorIsEnabledQuery>()
|
||||
.TwoFactorIsEnabledAsync(Arg.Any<IEnumerable<Guid>>())
|
||||
.Returns([(userId, true)]);
|
||||
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||
.GetManyByUserAsync(userId)
|
||||
.Returns([organizationUser, otherOrgUser]);
|
||||
|
||||
sutProvider.GetDependency<IPolicyRequirementQuery>()
|
||||
.GetAsync<SingleOrganizationPolicyRequirement>(userId)
|
||||
.Returns(new SingleOrganizationPolicyRequirement([singleOrgPolicyDetails]));
|
||||
|
||||
// Act
|
||||
var result = await sutProvider.Sut.ValidateAsync(request);
|
||||
|
||||
// Assert
|
||||
Assert.True(result.IsError);
|
||||
Assert.IsType<OtherOrganizationEnforcesSingleOrgPolicy>(result.AsError);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task ValidateAsync_UserInSingleOrg_ReturnsValidResult(
|
||||
SutProvider<AutomaticallyConfirmOrganizationUsersValidator> sutProvider,
|
||||
[Organization(useAutomaticUserConfirmation: true)] Organization organization,
|
||||
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser organizationUser,
|
||||
Guid userId,
|
||||
[Policy(PolicyType.AutomaticUserConfirmation)] Policy autoConfirmPolicy)
|
||||
{
|
||||
// Arrange
|
||||
organizationUser.UserId = userId;
|
||||
organizationUser.OrganizationId = organization.Id;
|
||||
|
||||
var request = new AutomaticallyConfirmOrganizationUserValidationRequest
|
||||
{
|
||||
PerformedBy = Substitute.For<IActingUser>(),
|
||||
DefaultUserCollectionName = "test-collection",
|
||||
OrganizationUser = organizationUser,
|
||||
OrganizationUserId = organizationUser.Id,
|
||||
Organization = organization,
|
||||
OrganizationId = organization.Id,
|
||||
Key = "test-key"
|
||||
};
|
||||
|
||||
sutProvider.GetDependency<IPolicyRepository>()
|
||||
.GetByOrganizationIdTypeAsync(organization.Id, PolicyType.AutomaticUserConfirmation)
|
||||
.Returns(autoConfirmPolicy);
|
||||
|
||||
sutProvider.GetDependency<ITwoFactorIsEnabledQuery>()
|
||||
.TwoFactorIsEnabledAsync(Arg.Any<IEnumerable<Guid>>())
|
||||
.Returns([(userId, true)]);
|
||||
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||
.GetManyByUserAsync(userId)
|
||||
.Returns([organizationUser]); // Single org
|
||||
|
||||
// Act
|
||||
var result = await sutProvider.Sut.ValidateAsync(request);
|
||||
|
||||
// Assert
|
||||
Assert.True(result.IsValid);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task ValidateAsync_UserInMultipleOrgs_WithNoSingleOrgPolicy_ReturnsValidResult(
|
||||
SutProvider<AutomaticallyConfirmOrganizationUsersValidator> sutProvider,
|
||||
[Organization(useAutomaticUserConfirmation: true)] Organization organization,
|
||||
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser organizationUser,
|
||||
OrganizationUser otherOrgUser,
|
||||
Guid userId,
|
||||
Policy autoConfirmPolicy)
|
||||
{
|
||||
// Arrange
|
||||
organizationUser.UserId = userId;
|
||||
organizationUser.OrganizationId = organization.Id;
|
||||
autoConfirmPolicy.Type = PolicyType.AutomaticUserConfirmation;
|
||||
autoConfirmPolicy.Enabled = true;
|
||||
|
||||
var request = new AutomaticallyConfirmOrganizationUserValidationRequest
|
||||
{
|
||||
PerformedBy = Substitute.For<IActingUser>(),
|
||||
DefaultUserCollectionName = "test-collection",
|
||||
OrganizationUser = organizationUser,
|
||||
OrganizationUserId = organizationUser.Id,
|
||||
Organization = organization,
|
||||
OrganizationId = organization.Id,
|
||||
Key = "test-key"
|
||||
};
|
||||
|
||||
sutProvider.GetDependency<IPolicyRepository>()
|
||||
.GetByOrganizationIdTypeAsync(organization.Id, PolicyType.AutomaticUserConfirmation)
|
||||
.Returns(autoConfirmPolicy);
|
||||
|
||||
sutProvider.GetDependency<ITwoFactorIsEnabledQuery>()
|
||||
.TwoFactorIsEnabledAsync(Arg.Any<IEnumerable<Guid>>())
|
||||
.Returns([(userId, true)]);
|
||||
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||
.GetManyByUserAsync(userId)
|
||||
.Returns([organizationUser, otherOrgUser]);
|
||||
|
||||
sutProvider.GetDependency<IPolicyRequirementQuery>()
|
||||
.GetAsync<SingleOrganizationPolicyRequirement>(userId)
|
||||
.Returns(new SingleOrganizationPolicyRequirement([]));
|
||||
|
||||
// Act
|
||||
var result = await sutProvider.Sut.ValidateAsync(request);
|
||||
|
||||
// Assert
|
||||
Assert.True(result.IsValid);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task ValidateAsync_WithAutoConfirmPolicyDisabled_ReturnsAutoConfirmPolicyNotEnabledError(
|
||||
SutProvider<AutomaticallyConfirmOrganizationUsersValidator> sutProvider,
|
||||
Organization organization,
|
||||
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser organizationUser,
|
||||
Guid userId)
|
||||
{
|
||||
// Arrange
|
||||
organizationUser.UserId = userId;
|
||||
organizationUser.OrganizationId = organization.Id;
|
||||
|
||||
var request = new AutomaticallyConfirmOrganizationUserValidationRequest
|
||||
{
|
||||
PerformedBy = Substitute.For<IActingUser>(),
|
||||
DefaultUserCollectionName = "test-collection",
|
||||
OrganizationUser = organizationUser,
|
||||
OrganizationUserId = organizationUser.Id,
|
||||
Organization = organization,
|
||||
OrganizationId = organization.Id,
|
||||
Key = "test-key"
|
||||
};
|
||||
|
||||
sutProvider.GetDependency<IPolicyRepository>()
|
||||
.GetByOrganizationIdTypeAsync(organization.Id, PolicyType.AutomaticUserConfirmation)
|
||||
.Returns((Policy)null);
|
||||
|
||||
sutProvider.GetDependency<ITwoFactorIsEnabledQuery>()
|
||||
.TwoFactorIsEnabledAsync(Arg.Any<IEnumerable<Guid>>())
|
||||
.Returns([(userId, true)]);
|
||||
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||
.GetManyByUserAsync(userId)
|
||||
.Returns([organizationUser]);
|
||||
|
||||
// Act
|
||||
var result = await sutProvider.Sut.ValidateAsync(request);
|
||||
|
||||
// Assert
|
||||
Assert.True(result.IsError);
|
||||
Assert.IsType<AutomaticallyConfirmUsersPolicyIsNotEnabled>(result.AsError);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task ValidateAsync_WithOrganizationUseAutomaticUserConfirmationDisabled_ReturnsAutoConfirmPolicyNotEnabledError(
|
||||
SutProvider<AutomaticallyConfirmOrganizationUsersValidator> sutProvider,
|
||||
[Organization(useAutomaticUserConfirmation: false)] Organization organization,
|
||||
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser organizationUser,
|
||||
Guid userId,
|
||||
[Policy(PolicyType.AutomaticUserConfirmation)] Policy autoConfirmPolicy)
|
||||
{
|
||||
// Arrange
|
||||
organizationUser.UserId = userId;
|
||||
organizationUser.OrganizationId = organization.Id;
|
||||
|
||||
var request = new AutomaticallyConfirmOrganizationUserValidationRequest
|
||||
{
|
||||
PerformedBy = Substitute.For<IActingUser>(),
|
||||
DefaultUserCollectionName = "test-collection",
|
||||
OrganizationUser = organizationUser,
|
||||
OrganizationUserId = organizationUser.Id,
|
||||
Organization = organization,
|
||||
OrganizationId = organization.Id,
|
||||
Key = "test-key"
|
||||
};
|
||||
|
||||
sutProvider.GetDependency<IPolicyRepository>()
|
||||
.GetByOrganizationIdTypeAsync(organization.Id, PolicyType.AutomaticUserConfirmation)
|
||||
.Returns(autoConfirmPolicy);
|
||||
|
||||
sutProvider.GetDependency<ITwoFactorIsEnabledQuery>()
|
||||
.TwoFactorIsEnabledAsync(Arg.Any<IEnumerable<Guid>>())
|
||||
.Returns([(userId, true)]);
|
||||
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||
.GetManyByUserAsync(userId)
|
||||
.Returns([organizationUser]);
|
||||
|
||||
// Act
|
||||
var result = await sutProvider.Sut.ValidateAsync(request);
|
||||
|
||||
// Assert
|
||||
Assert.True(result.IsError);
|
||||
Assert.IsType<AutomaticallyConfirmUsersPolicyIsNotEnabled>(result.AsError);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,730 @@
|
||||
using Bit.Core.AdminConsole.Entities;
|
||||
using Bit.Core.AdminConsole.Models.Data;
|
||||
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.AdminConsole.Utilities.v2;
|
||||
using Bit.Core.AdminConsole.Utilities.v2.Validation;
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Models.Data;
|
||||
using Bit.Core.Platform.Push;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Test.AutoFixture.OrganizationUserFixtures;
|
||||
using Bit.Test.Common.AutoFixture;
|
||||
using Bit.Test.Common.AutoFixture.Attributes;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using NSubstitute;
|
||||
using NSubstitute.ExceptionExtensions;
|
||||
using Xunit;
|
||||
|
||||
namespace Bit.Core.Test.AdminConsole.OrganizationFeatures.OrganizationUsers.AutoConfirmUsers;
|
||||
|
||||
[SutProviderCustomize]
|
||||
public class AutomaticallyConfirmUsersCommandTests
|
||||
{
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task AutomaticallyConfirmOrganizationUserAsync_WithValidRequest_ConfirmsUserSuccessfully(
|
||||
SutProvider<AutomaticallyConfirmOrganizationUserCommand> sutProvider,
|
||||
Organization organization,
|
||||
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser organizationUser,
|
||||
User user,
|
||||
Guid performingUserId,
|
||||
string key,
|
||||
string defaultCollectionName)
|
||||
{
|
||||
// Arrange
|
||||
organizationUser.UserId = user.Id;
|
||||
organizationUser.OrganizationId = organization.Id;
|
||||
|
||||
var request = new AutomaticallyConfirmOrganizationUserRequest
|
||||
{
|
||||
OrganizationUserId = organizationUser.Id,
|
||||
OrganizationId = organization.Id,
|
||||
Key = key,
|
||||
DefaultUserCollectionName = defaultCollectionName,
|
||||
PerformedBy = new StandardUser(performingUserId, true)
|
||||
};
|
||||
|
||||
SetupRepositoryMocks(sutProvider, organizationUser, organization, user);
|
||||
SetupValidatorMock(sutProvider, request, organizationUser, organization, true);
|
||||
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||
.ConfirmOrganizationUserAsync(Arg.Is<AcceptedOrganizationUserToConfirm>(o =>
|
||||
o.OrganizationUserId == organizationUser.Id && o.Key == request.Key))
|
||||
.Returns(true);
|
||||
|
||||
// Act
|
||||
var result = await sutProvider.Sut.AutomaticallyConfirmOrganizationUserAsync(request);
|
||||
|
||||
// Assert
|
||||
Assert.True(result.IsSuccess);
|
||||
|
||||
await sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||
.Received(1)
|
||||
.ConfirmOrganizationUserAsync(Arg.Is<AcceptedOrganizationUserToConfirm>(o =>
|
||||
o.OrganizationUserId == organizationUser.Id && o.Key == request.Key));
|
||||
|
||||
await AssertSuccessfulOperationsAsync(sutProvider, organizationUser, organization, user, key);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task AutomaticallyConfirmOrganizationUserAsync_WithInvalidUserOrgId_ReturnsOrganizationUserIdIsInvalidError(
|
||||
SutProvider<AutomaticallyConfirmOrganizationUserCommand> sutProvider,
|
||||
Organization organization,
|
||||
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser organizationUser,
|
||||
User user,
|
||||
Guid performingUserId,
|
||||
string key,
|
||||
string defaultCollectionName)
|
||||
{
|
||||
// Arrange
|
||||
organizationUser.UserId = user.Id;
|
||||
organizationUser.OrganizationId = Guid.NewGuid(); // User belongs to another organization
|
||||
var request = new AutomaticallyConfirmOrganizationUserRequest
|
||||
{
|
||||
OrganizationUserId = organizationUser.Id,
|
||||
OrganizationId = organization.Id,
|
||||
Key = key,
|
||||
DefaultUserCollectionName = defaultCollectionName,
|
||||
PerformedBy = new StandardUser(performingUserId, true)
|
||||
};
|
||||
|
||||
SetupRepositoryMocks(sutProvider, organizationUser, organization, user);
|
||||
SetupValidatorMock(sutProvider, request, organizationUser, organization, false, new OrganizationUserIdIsInvalid());
|
||||
|
||||
// Act
|
||||
var result = await sutProvider.Sut.AutomaticallyConfirmOrganizationUserAsync(request);
|
||||
|
||||
// Assert
|
||||
Assert.True(result.IsError);
|
||||
Assert.IsType<OrganizationUserIdIsInvalid>(result.AsError);
|
||||
|
||||
await sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||
.DidNotReceive()
|
||||
.ConfirmOrganizationUserAsync(Arg.Any<AcceptedOrganizationUserToConfirm>());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task AutomaticallyConfirmOrganizationUserAsync_WhenAlreadyConfirmed_ReturnsNoneSuccess(
|
||||
SutProvider<AutomaticallyConfirmOrganizationUserCommand> sutProvider,
|
||||
Organization organization,
|
||||
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser organizationUser,
|
||||
User user,
|
||||
Guid performingUserId,
|
||||
string key,
|
||||
string defaultCollectionName)
|
||||
{
|
||||
// Arrange
|
||||
organizationUser.UserId = user.Id;
|
||||
organizationUser.OrganizationId = organization.Id;
|
||||
var request = new AutomaticallyConfirmOrganizationUserRequest
|
||||
{
|
||||
OrganizationUserId = organizationUser.Id,
|
||||
OrganizationId = organization.Id,
|
||||
Key = key,
|
||||
DefaultUserCollectionName = defaultCollectionName,
|
||||
PerformedBy = new StandardUser(performingUserId, true)
|
||||
};
|
||||
|
||||
SetupRepositoryMocks(sutProvider, organizationUser, organization, user);
|
||||
SetupValidatorMock(sutProvider, request, organizationUser, organization, true);
|
||||
|
||||
// Return false to indicate the user is already confirmed
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||
.ConfirmOrganizationUserAsync(Arg.Is<AcceptedOrganizationUserToConfirm>(x =>
|
||||
x.OrganizationUserId == organizationUser.Id && x.Key == request.Key))
|
||||
.Returns(false);
|
||||
|
||||
// Act
|
||||
var result = await sutProvider.Sut.AutomaticallyConfirmOrganizationUserAsync(request);
|
||||
|
||||
// Assert
|
||||
Assert.True(result.IsSuccess);
|
||||
|
||||
await sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||
.Received(1)
|
||||
.ConfirmOrganizationUserAsync(Arg.Is<AcceptedOrganizationUserToConfirm>(x =>
|
||||
x.OrganizationUserId == organizationUser.Id && x.Key == request.Key));
|
||||
|
||||
// Verify no side effects occurred
|
||||
await sutProvider.GetDependency<IEventService>()
|
||||
.DidNotReceive()
|
||||
.LogOrganizationUserEventAsync(Arg.Any<OrganizationUser>(), Arg.Any<EventType>(), Arg.Any<DateTime?>());
|
||||
|
||||
await sutProvider.GetDependency<IPushNotificationService>()
|
||||
.DidNotReceive()
|
||||
.PushSyncOrgKeysAsync(Arg.Any<Guid>());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task AutomaticallyConfirmOrganizationUserAsync_WithDefaultCollectionEnabled_CreatesDefaultCollection(
|
||||
SutProvider<AutomaticallyConfirmOrganizationUserCommand> sutProvider,
|
||||
Organization organization,
|
||||
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser organizationUser,
|
||||
User user,
|
||||
Guid performingUserId,
|
||||
string key,
|
||||
string defaultCollectionName)
|
||||
{
|
||||
// Arrange
|
||||
organizationUser.UserId = user.Id;
|
||||
organizationUser.OrganizationId = organization.Id;
|
||||
var request = new AutomaticallyConfirmOrganizationUserRequest
|
||||
{
|
||||
OrganizationUserId = organizationUser.Id,
|
||||
OrganizationId = organization.Id,
|
||||
Key = key,
|
||||
DefaultUserCollectionName = defaultCollectionName, // Non-empty to trigger creation
|
||||
PerformedBy = new StandardUser(performingUserId, true)
|
||||
};
|
||||
|
||||
SetupRepositoryMocks(sutProvider, organizationUser, organization, user);
|
||||
SetupValidatorMock(sutProvider, request, organizationUser, organization, true);
|
||||
SetupPolicyRequirementMock(sutProvider, user.Id, organization.Id, true); // Policy requires collection
|
||||
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>().ConfirmOrganizationUserAsync(
|
||||
Arg.Is<AcceptedOrganizationUserToConfirm>(o =>
|
||||
o.OrganizationUserId == organizationUser.Id && o.Key == request.Key))
|
||||
.Returns(true);
|
||||
|
||||
// Act
|
||||
var result = await sutProvider.Sut.AutomaticallyConfirmOrganizationUserAsync(request);
|
||||
|
||||
// Assert
|
||||
Assert.True(result.IsSuccess);
|
||||
|
||||
await sutProvider.GetDependency<ICollectionRepository>()
|
||||
.Received(1)
|
||||
.CreateAsync(
|
||||
Arg.Is<Collection>(c =>
|
||||
c.OrganizationId == organization.Id &&
|
||||
c.Name == defaultCollectionName &&
|
||||
c.Type == CollectionType.DefaultUserCollection),
|
||||
Arg.Is<IEnumerable<CollectionAccessSelection>>(groups => groups == null),
|
||||
Arg.Is<IEnumerable<CollectionAccessSelection>>(access =>
|
||||
access.FirstOrDefault(x => x.Id == organizationUser.Id && x.Manage) != null));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task AutomaticallyConfirmOrganizationUserAsync_WithDefaultCollectionDisabled_DoesNotCreateCollection(
|
||||
SutProvider<AutomaticallyConfirmOrganizationUserCommand> sutProvider,
|
||||
Organization organization,
|
||||
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser organizationUser,
|
||||
User user,
|
||||
Guid performingUserId,
|
||||
string key)
|
||||
{
|
||||
// Arrange
|
||||
organizationUser.UserId = user.Id;
|
||||
organizationUser.OrganizationId = organization.Id;
|
||||
var request = new AutomaticallyConfirmOrganizationUserRequest
|
||||
{
|
||||
OrganizationUserId = organizationUser.Id,
|
||||
OrganizationId = organization.Id,
|
||||
Key = key,
|
||||
DefaultUserCollectionName = string.Empty, // Empty, so the collection won't be created
|
||||
PerformedBy = new StandardUser(performingUserId, true)
|
||||
};
|
||||
|
||||
SetupRepositoryMocks(sutProvider, organizationUser, organization, user);
|
||||
SetupValidatorMock(sutProvider, request, organizationUser, organization, true);
|
||||
SetupPolicyRequirementMock(sutProvider, user.Id, organization.Id, false); // Policy doesn't require
|
||||
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||
.ConfirmOrganizationUserAsync(Arg.Is<AcceptedOrganizationUserToConfirm>(o =>
|
||||
o.OrganizationUserId == organizationUser.Id && o.Key == request.Key))
|
||||
.Returns(true);
|
||||
|
||||
// Act
|
||||
var result = await sutProvider.Sut.AutomaticallyConfirmOrganizationUserAsync(request);
|
||||
|
||||
// Assert
|
||||
Assert.True(result.IsSuccess);
|
||||
|
||||
await sutProvider.GetDependency<ICollectionRepository>()
|
||||
.DidNotReceive()
|
||||
.CreateAsync(Arg.Any<Collection>(),
|
||||
Arg.Any<IEnumerable<CollectionAccessSelection>>(),
|
||||
Arg.Any<IEnumerable<CollectionAccessSelection>>());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task AutomaticallyConfirmOrganizationUserAsync_WhenCreateDefaultCollectionFails_LogsErrorButReturnsSuccess(
|
||||
SutProvider<AutomaticallyConfirmOrganizationUserCommand> sutProvider,
|
||||
Organization organization,
|
||||
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser organizationUser,
|
||||
User user,
|
||||
Guid performingUserId,
|
||||
string key,
|
||||
string defaultCollectionName)
|
||||
{
|
||||
// Arrange
|
||||
organizationUser.UserId = user.Id;
|
||||
organizationUser.OrganizationId = organization.Id;
|
||||
var request = new AutomaticallyConfirmOrganizationUserRequest
|
||||
{
|
||||
OrganizationUserId = organizationUser.Id,
|
||||
OrganizationId = organization.Id,
|
||||
Key = key,
|
||||
DefaultUserCollectionName = defaultCollectionName, // Non-empty to trigger creation
|
||||
PerformedBy = new StandardUser(performingUserId, true)
|
||||
};
|
||||
|
||||
SetupRepositoryMocks(sutProvider, organizationUser, organization, user);
|
||||
SetupValidatorMock(sutProvider, request, organizationUser, organization, true);
|
||||
SetupPolicyRequirementMock(sutProvider, user.Id, organization.Id, true);
|
||||
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||
.ConfirmOrganizationUserAsync(Arg.Is<AcceptedOrganizationUserToConfirm>(o =>
|
||||
o.OrganizationUserId == organizationUser.Id && o.Key == request.Key)).Returns(true);
|
||||
|
||||
var collectionException = new Exception("Collection creation failed");
|
||||
sutProvider.GetDependency<ICollectionRepository>()
|
||||
.CreateAsync(Arg.Any<Collection>(),
|
||||
Arg.Any<IEnumerable<CollectionAccessSelection>>(),
|
||||
Arg.Any<IEnumerable<CollectionAccessSelection>>())
|
||||
.ThrowsAsync(collectionException);
|
||||
|
||||
// Act
|
||||
var result = await sutProvider.Sut.AutomaticallyConfirmOrganizationUserAsync(request);
|
||||
|
||||
// Assert - side effects are fire-and-forget, so command returns success even if collection creation fails
|
||||
Assert.True(result.IsSuccess);
|
||||
|
||||
sutProvider.GetDependency<ILogger<AutomaticallyConfirmOrganizationUserCommand>>()
|
||||
.Received(1)
|
||||
.Log(
|
||||
LogLevel.Error,
|
||||
Arg.Any<EventId>(),
|
||||
Arg.Is<object>(o => o.ToString()!.Contains("Failed to create default collection for user")),
|
||||
collectionException,
|
||||
Arg.Any<Func<object, Exception?, string>>());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task AutomaticallyConfirmOrganizationUserAsync_WhenEventLogFails_LogsErrorButReturnsSuccess(
|
||||
SutProvider<AutomaticallyConfirmOrganizationUserCommand> sutProvider,
|
||||
Organization organization,
|
||||
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser organizationUser,
|
||||
User user,
|
||||
Guid performingUserId,
|
||||
string key,
|
||||
string defaultCollectionName)
|
||||
{
|
||||
// Arrange
|
||||
organizationUser.UserId = user.Id;
|
||||
organizationUser.OrganizationId = organization.Id;
|
||||
var request = new AutomaticallyConfirmOrganizationUserRequest
|
||||
{
|
||||
OrganizationUserId = organizationUser.Id,
|
||||
OrganizationId = organization.Id,
|
||||
Key = key,
|
||||
DefaultUserCollectionName = defaultCollectionName,
|
||||
PerformedBy = new StandardUser(performingUserId, true)
|
||||
};
|
||||
|
||||
SetupRepositoryMocks(sutProvider, organizationUser, organization, user);
|
||||
SetupValidatorMock(sutProvider, request, organizationUser, organization, true);
|
||||
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||
.ConfirmOrganizationUserAsync(Arg.Is<AcceptedOrganizationUserToConfirm>(o =>
|
||||
o.OrganizationUserId == organizationUser.Id && o.Key == request.Key))
|
||||
.Returns(true);
|
||||
|
||||
var eventException = new Exception("Event logging failed");
|
||||
sutProvider.GetDependency<IEventService>()
|
||||
.LogOrganizationUserEventAsync(Arg.Any<OrganizationUser>(),
|
||||
EventType.OrganizationUser_AutomaticallyConfirmed,
|
||||
Arg.Any<DateTime?>())
|
||||
.ThrowsAsync(eventException);
|
||||
|
||||
// Act
|
||||
var result = await sutProvider.Sut.AutomaticallyConfirmOrganizationUserAsync(request);
|
||||
|
||||
// Assert - side effects are fire-and-forget, so command returns success even if event log fails
|
||||
Assert.True(result.IsSuccess);
|
||||
|
||||
sutProvider.GetDependency<ILogger<AutomaticallyConfirmOrganizationUserCommand>>()
|
||||
.Received(1)
|
||||
.Log(
|
||||
LogLevel.Error,
|
||||
Arg.Any<EventId>(),
|
||||
Arg.Is<object>(o => o.ToString()!.Contains("Failed to log OrganizationUser_AutomaticallyConfirmed event")),
|
||||
eventException,
|
||||
Arg.Any<Func<object, Exception?, string>>());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task AutomaticallyConfirmOrganizationUserAsync_WhenSendEmailFails_LogsErrorButReturnsSuccess(
|
||||
SutProvider<AutomaticallyConfirmOrganizationUserCommand> sutProvider,
|
||||
Organization organization,
|
||||
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser organizationUser,
|
||||
User user,
|
||||
Guid performingUserId,
|
||||
string key,
|
||||
string defaultCollectionName)
|
||||
{
|
||||
// Arrange
|
||||
organizationUser.UserId = user.Id;
|
||||
organizationUser.OrganizationId = organization.Id;
|
||||
var request = new AutomaticallyConfirmOrganizationUserRequest
|
||||
{
|
||||
OrganizationUserId = organizationUser.Id,
|
||||
OrganizationId = organization.Id,
|
||||
Key = key,
|
||||
DefaultUserCollectionName = defaultCollectionName,
|
||||
PerformedBy = new StandardUser(performingUserId, true)
|
||||
};
|
||||
|
||||
SetupRepositoryMocks(sutProvider, organizationUser, organization, user);
|
||||
SetupValidatorMock(sutProvider, request, organizationUser, organization, true);
|
||||
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||
.ConfirmOrganizationUserAsync(Arg.Is<AcceptedOrganizationUserToConfirm>(o =>
|
||||
o.OrganizationUserId == organizationUser.Id && o.Key == request.Key))
|
||||
.Returns(true);
|
||||
|
||||
var emailException = new Exception("Email sending failed");
|
||||
sutProvider.GetDependency<IMailService>()
|
||||
.SendOrganizationConfirmedEmailAsync(organization.Name, user.Email, organizationUser.AccessSecretsManager)
|
||||
.ThrowsAsync(emailException);
|
||||
|
||||
// Act
|
||||
var result = await sutProvider.Sut.AutomaticallyConfirmOrganizationUserAsync(request);
|
||||
|
||||
// Assert - side effects are fire-and-forget, so command returns success even if email fails
|
||||
Assert.True(result.IsSuccess);
|
||||
|
||||
sutProvider.GetDependency<ILogger<AutomaticallyConfirmOrganizationUserCommand>>()
|
||||
.Received(1)
|
||||
.Log(
|
||||
LogLevel.Error,
|
||||
Arg.Any<EventId>(),
|
||||
Arg.Is<object>(o => o.ToString()!.Contains("Failed to send OrganizationUserConfirmed")),
|
||||
emailException,
|
||||
Arg.Any<Func<object, Exception?, string>>());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task AutomaticallyConfirmOrganizationUserAsync_WhenUserNotFoundForEmail_LogsErrorButReturnsSuccess(
|
||||
SutProvider<AutomaticallyConfirmOrganizationUserCommand> sutProvider,
|
||||
Organization organization,
|
||||
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser organizationUser,
|
||||
User user,
|
||||
Guid performingUserId,
|
||||
string key,
|
||||
string defaultCollectionName)
|
||||
{
|
||||
// Arrange
|
||||
organizationUser.UserId = user.Id;
|
||||
organizationUser.OrganizationId = organization.Id;
|
||||
var request = new AutomaticallyConfirmOrganizationUserRequest
|
||||
{
|
||||
OrganizationUserId = organizationUser.Id,
|
||||
OrganizationId = organization.Id,
|
||||
Key = key,
|
||||
DefaultUserCollectionName = defaultCollectionName,
|
||||
PerformedBy = new StandardUser(performingUserId, true)
|
||||
};
|
||||
|
||||
SetupRepositoryMocks(sutProvider, organizationUser, organization, user);
|
||||
SetupValidatorMock(sutProvider, request, organizationUser, organization, true);
|
||||
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||
.ConfirmOrganizationUserAsync(Arg.Is<AcceptedOrganizationUserToConfirm>(o =>
|
||||
o.OrganizationUserId == organizationUser.Id && o.Key == request.Key))
|
||||
.Returns(true);
|
||||
|
||||
// Return null when retrieving user for email
|
||||
sutProvider.GetDependency<IUserRepository>()
|
||||
.GetByIdAsync(user.Id)
|
||||
.Returns((User)null!);
|
||||
|
||||
// Act
|
||||
var result = await sutProvider.Sut.AutomaticallyConfirmOrganizationUserAsync(request);
|
||||
|
||||
// Assert - side effects are fire-and-forget, so command returns success even if user not found for email
|
||||
Assert.True(result.IsSuccess);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task AutomaticallyConfirmOrganizationUserAsync_WhenDeleteDeviceRegistrationFails_LogsErrorButReturnsSuccess(
|
||||
SutProvider<AutomaticallyConfirmOrganizationUserCommand> sutProvider,
|
||||
Organization organization,
|
||||
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser organizationUser,
|
||||
User user,
|
||||
Guid performingUserId,
|
||||
string key,
|
||||
string defaultCollectionName,
|
||||
Device device)
|
||||
{
|
||||
// Arrange
|
||||
organizationUser.UserId = user.Id;
|
||||
organizationUser.OrganizationId = organization.Id;
|
||||
device.UserId = user.Id;
|
||||
device.PushToken = "test-push-token";
|
||||
var request = new AutomaticallyConfirmOrganizationUserRequest
|
||||
{
|
||||
OrganizationUserId = organizationUser.Id,
|
||||
OrganizationId = organization.Id,
|
||||
Key = key,
|
||||
DefaultUserCollectionName = defaultCollectionName,
|
||||
PerformedBy = new StandardUser(performingUserId, true)
|
||||
};
|
||||
|
||||
SetupRepositoryMocks(sutProvider, organizationUser, organization, user);
|
||||
SetupValidatorMock(sutProvider, request, organizationUser, organization, true);
|
||||
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||
.ConfirmOrganizationUserAsync(Arg.Is<AcceptedOrganizationUserToConfirm>(o =>
|
||||
o.OrganizationUserId == organizationUser.Id && o.Key == request.Key))
|
||||
.Returns(true);
|
||||
|
||||
sutProvider.GetDependency<IDeviceRepository>()
|
||||
.GetManyByUserIdAsync(user.Id)
|
||||
.Returns(new List<Device> { device });
|
||||
|
||||
var deviceException = new Exception("Device registration deletion failed");
|
||||
sutProvider.GetDependency<IPushRegistrationService>()
|
||||
.DeleteUserRegistrationOrganizationAsync(Arg.Any<IEnumerable<string>>(), organization.Id.ToString())
|
||||
.ThrowsAsync(deviceException);
|
||||
|
||||
// Act
|
||||
var result = await sutProvider.Sut.AutomaticallyConfirmOrganizationUserAsync(request);
|
||||
|
||||
// Assert - side effects are fire-and-forget, so command returns success even if device registration deletion fails
|
||||
Assert.True(result.IsSuccess);
|
||||
|
||||
sutProvider.GetDependency<ILogger<AutomaticallyConfirmOrganizationUserCommand>>()
|
||||
.Received(1)
|
||||
.Log(
|
||||
LogLevel.Error,
|
||||
Arg.Any<EventId>(),
|
||||
Arg.Is<object>(o => o.ToString()!.Contains("Failed to delete device registration")),
|
||||
deviceException,
|
||||
Arg.Any<Func<object, Exception?, string>>());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task AutomaticallyConfirmOrganizationUserAsync_WhenPushSyncOrgKeysFails_LogsErrorButReturnsSuccess(
|
||||
SutProvider<AutomaticallyConfirmOrganizationUserCommand> sutProvider,
|
||||
Organization organization,
|
||||
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser organizationUser,
|
||||
User user,
|
||||
Guid performingUserId,
|
||||
string key,
|
||||
string defaultCollectionName)
|
||||
{
|
||||
// Arrange
|
||||
organizationUser.UserId = user.Id;
|
||||
organizationUser.OrganizationId = organization.Id;
|
||||
var request = new AutomaticallyConfirmOrganizationUserRequest
|
||||
{
|
||||
OrganizationUserId = organizationUser.Id,
|
||||
OrganizationId = organization.Id,
|
||||
Key = key,
|
||||
DefaultUserCollectionName = defaultCollectionName,
|
||||
PerformedBy = new StandardUser(performingUserId, true)
|
||||
};
|
||||
|
||||
SetupRepositoryMocks(sutProvider, organizationUser, organization, user);
|
||||
SetupValidatorMock(sutProvider, request, organizationUser, organization, true);
|
||||
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||
.ConfirmOrganizationUserAsync(Arg.Is<AcceptedOrganizationUserToConfirm>(o =>
|
||||
o.OrganizationUserId == organizationUser.Id && o.Key == request.Key))
|
||||
.Returns(true);
|
||||
|
||||
var pushException = new Exception("Push sync failed");
|
||||
sutProvider.GetDependency<IPushNotificationService>()
|
||||
.PushSyncOrgKeysAsync(user.Id)
|
||||
.ThrowsAsync(pushException);
|
||||
|
||||
// Act
|
||||
var result = await sutProvider.Sut.AutomaticallyConfirmOrganizationUserAsync(request);
|
||||
|
||||
// Assert - side effects are fire-and-forget, so command returns success even if push sync fails
|
||||
Assert.True(result.IsSuccess);
|
||||
|
||||
sutProvider.GetDependency<ILogger<AutomaticallyConfirmOrganizationUserCommand>>()
|
||||
.Received(1)
|
||||
.Log(
|
||||
LogLevel.Error,
|
||||
Arg.Any<EventId>(),
|
||||
Arg.Is<object>(o => o.ToString()!.Contains("Failed to push organization keys")),
|
||||
pushException,
|
||||
Arg.Any<Func<object, Exception?, string>>());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task AutomaticallyConfirmOrganizationUserAsync_WithDevicesWithoutPushToken_FiltersCorrectly(
|
||||
SutProvider<AutomaticallyConfirmOrganizationUserCommand> sutProvider,
|
||||
Organization organization,
|
||||
[OrganizationUser(OrganizationUserStatusType.Accepted)] OrganizationUser organizationUser,
|
||||
User user,
|
||||
Guid performingUserId,
|
||||
string key,
|
||||
string defaultCollectionName,
|
||||
Device deviceWithToken,
|
||||
Device deviceWithoutToken)
|
||||
{
|
||||
// Arrange
|
||||
organizationUser.UserId = user.Id;
|
||||
organizationUser.OrganizationId = organization.Id;
|
||||
deviceWithToken.UserId = user.Id;
|
||||
deviceWithToken.PushToken = "test-token";
|
||||
deviceWithoutToken.UserId = user.Id;
|
||||
deviceWithoutToken.PushToken = null;
|
||||
var request = new AutomaticallyConfirmOrganizationUserRequest
|
||||
{
|
||||
OrganizationUserId = organizationUser.Id,
|
||||
OrganizationId = organization.Id,
|
||||
Key = key,
|
||||
DefaultUserCollectionName = defaultCollectionName,
|
||||
PerformedBy = new StandardUser(performingUserId, true)
|
||||
};
|
||||
|
||||
SetupRepositoryMocks(sutProvider, organizationUser, organization, user);
|
||||
SetupValidatorMock(sutProvider, request, organizationUser, organization, true);
|
||||
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||
.ConfirmOrganizationUserAsync(Arg.Is<AcceptedOrganizationUserToConfirm>(o =>
|
||||
o.OrganizationUserId == organizationUser.Id && o.Key == request.Key))
|
||||
.Returns(true);
|
||||
|
||||
sutProvider.GetDependency<IDeviceRepository>()
|
||||
.GetManyByUserIdAsync(user.Id)
|
||||
.Returns(new List<Device> { deviceWithToken, deviceWithoutToken });
|
||||
|
||||
// Act
|
||||
var result = await sutProvider.Sut.AutomaticallyConfirmOrganizationUserAsync(request);
|
||||
|
||||
// Assert
|
||||
Assert.True(result.IsSuccess);
|
||||
|
||||
await sutProvider.GetDependency<IPushRegistrationService>()
|
||||
.Received(1)
|
||||
.DeleteUserRegistrationOrganizationAsync(
|
||||
Arg.Is<IEnumerable<string>>(devices =>
|
||||
devices.Count(d => deviceWithToken.Id.ToString() == d) == 1),
|
||||
organization.Id.ToString());
|
||||
}
|
||||
|
||||
private static void SetupRepositoryMocks(
|
||||
SutProvider<AutomaticallyConfirmOrganizationUserCommand> sutProvider,
|
||||
OrganizationUser organizationUser,
|
||||
Organization organization,
|
||||
User user)
|
||||
{
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||
.GetByIdAsync(organizationUser.Id)
|
||||
.Returns(organizationUser);
|
||||
|
||||
sutProvider.GetDependency<IOrganizationRepository>()
|
||||
.GetByIdAsync(organization.Id)
|
||||
.Returns(organization);
|
||||
|
||||
sutProvider.GetDependency<IUserRepository>()
|
||||
.GetByIdAsync(user.Id)
|
||||
.Returns(user);
|
||||
|
||||
sutProvider.GetDependency<IDeviceRepository>()
|
||||
.GetManyByUserIdAsync(user.Id)
|
||||
.Returns(new List<Device>());
|
||||
}
|
||||
|
||||
private static void SetupValidatorMock(
|
||||
SutProvider<AutomaticallyConfirmOrganizationUserCommand> sutProvider,
|
||||
AutomaticallyConfirmOrganizationUserRequest originalRequest,
|
||||
OrganizationUser organizationUser,
|
||||
Organization organization,
|
||||
bool isValid,
|
||||
Error? error = null)
|
||||
{
|
||||
var validationRequest = new AutomaticallyConfirmOrganizationUserValidationRequest
|
||||
{
|
||||
PerformedBy = originalRequest.PerformedBy,
|
||||
DefaultUserCollectionName = originalRequest.DefaultUserCollectionName,
|
||||
OrganizationUserId = originalRequest.OrganizationUserId,
|
||||
OrganizationUser = organizationUser,
|
||||
OrganizationId = originalRequest.OrganizationId,
|
||||
Organization = organization,
|
||||
Key = originalRequest.Key
|
||||
};
|
||||
|
||||
var validationResult = isValid
|
||||
? ValidationResultHelpers.Valid(validationRequest)
|
||||
: ValidationResultHelpers.Invalid(validationRequest, error ?? new UserIsNotAccepted());
|
||||
|
||||
sutProvider.GetDependency<IAutomaticallyConfirmOrganizationUsersValidator>()
|
||||
.ValidateAsync(Arg.Any<AutomaticallyConfirmOrganizationUserValidationRequest>())
|
||||
.Returns(validationResult);
|
||||
}
|
||||
|
||||
private static void SetupPolicyRequirementMock(
|
||||
SutProvider<AutomaticallyConfirmOrganizationUserCommand> sutProvider,
|
||||
Guid userId,
|
||||
Guid organizationId,
|
||||
bool requiresDefaultCollection)
|
||||
{
|
||||
var policyDetails = requiresDefaultCollection
|
||||
? new List<PolicyDetails> { new() { OrganizationId = organizationId } }
|
||||
: new List<PolicyDetails>();
|
||||
|
||||
var policyRequirement = new OrganizationDataOwnershipPolicyRequirement(
|
||||
requiresDefaultCollection ? OrganizationDataOwnershipState.Enabled : OrganizationDataOwnershipState.Disabled,
|
||||
policyDetails);
|
||||
|
||||
sutProvider.GetDependency<IPolicyRequirementQuery>()
|
||||
.GetAsync<OrganizationDataOwnershipPolicyRequirement>(userId)
|
||||
.Returns(policyRequirement);
|
||||
}
|
||||
|
||||
private static async Task AssertSuccessfulOperationsAsync(
|
||||
SutProvider<AutomaticallyConfirmOrganizationUserCommand> sutProvider,
|
||||
OrganizationUser organizationUser,
|
||||
Organization organization,
|
||||
User user,
|
||||
string key)
|
||||
{
|
||||
await sutProvider.GetDependency<IEventService>()
|
||||
.Received(1)
|
||||
.LogOrganizationUserEventAsync(
|
||||
Arg.Is<OrganizationUser>(x => x.Id == organizationUser.Id),
|
||||
EventType.OrganizationUser_AutomaticallyConfirmed,
|
||||
Arg.Any<DateTime?>());
|
||||
|
||||
await sutProvider.GetDependency<IMailService>()
|
||||
.Received(1)
|
||||
.SendOrganizationConfirmedEmailAsync(
|
||||
organization.Name,
|
||||
user.Email,
|
||||
organizationUser.AccessSecretsManager);
|
||||
|
||||
await sutProvider.GetDependency<IPushNotificationService>()
|
||||
.Received(1)
|
||||
.PushSyncOrgKeysAsync(user.Id);
|
||||
|
||||
await sutProvider.GetDependency<IPushRegistrationService>()
|
||||
.Received(1)
|
||||
.DeleteUserRegistrationOrganizationAsync(
|
||||
Arg.Any<IEnumerable<string>>(),
|
||||
organization.Id.ToString());
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.DeleteClaimedAccount;
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Interfaces;
|
||||
using Bit.Core.AdminConsole.Utilities.v2;
|
||||
using Bit.Core.AdminConsole.Utilities.v2.Validation;
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Exceptions;
|
||||
|
||||
Reference in New Issue
Block a user