diff --git a/src/Core/AdminConsole/OrganizationFeatures/Policies/PolicyRequirements/AutomaticUserConfirmationPolicyRequirement.cs b/src/Core/AdminConsole/OrganizationFeatures/Policies/PolicyRequirements/AutomaticUserConfirmationPolicyRequirement.cs
index 3430f33a77..ea74a7ba74 100644
--- a/src/Core/AdminConsole/OrganizationFeatures/Policies/PolicyRequirements/AutomaticUserConfirmationPolicyRequirement.cs
+++ b/src/Core/AdminConsole/OrganizationFeatures/Policies/PolicyRequirements/AutomaticUserConfirmationPolicyRequirement.cs
@@ -19,7 +19,25 @@ namespace Bit.Core.AdminConsole.OrganizationFeatures.Policies.PolicyRequirements
/// Collection of policy details that apply to this user id
public class AutomaticUserConfirmationPolicyRequirement(IEnumerable policyDetails) : IPolicyRequirement
{
- public bool CannotBeGrantedEmergencyAccess() => policyDetails.Any();
+ ///
+ /// Returns true if the user cannot grant emergency access because they are in an
+ /// auto-confirm organization with status Accepted, Confirmed, or Revoked.
+ ///
+ public bool CannotGrantEmergencyAccess() => policyDetails.Any(p =>
+ p.OrganizationUserStatus is
+ OrganizationUserStatusType.Accepted or
+ OrganizationUserStatusType.Confirmed or
+ OrganizationUserStatusType.Revoked);
+
+ ///
+ /// Returns true if the user cannot be granted emergency access because they are in an
+ /// auto-confirm organization with status Accepted, Confirmed, or Revoked.
+ ///
+ public bool CannotBeGrantedEmergencyAccess() => policyDetails.Any(p =>
+ p.OrganizationUserStatus is
+ OrganizationUserStatusType.Accepted or
+ OrganizationUserStatusType.Confirmed or
+ OrganizationUserStatusType.Revoked);
public bool CannotJoinProvider() => policyDetails.Any();
diff --git a/src/Core/Auth/Services/EmergencyAccess/EmergencyAccessService.cs b/src/Core/Auth/Services/EmergencyAccess/EmergencyAccessService.cs
index 0072f85e61..ed7e9e09f8 100644
--- a/src/Core/Auth/Services/EmergencyAccess/EmergencyAccessService.cs
+++ b/src/Core/Auth/Services/EmergencyAccess/EmergencyAccessService.cs
@@ -3,6 +3,8 @@
using Bit.Core.AdminConsole.Entities;
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Interfaces;
+using Bit.Core.AdminConsole.OrganizationFeatures.Policies;
+using Bit.Core.AdminConsole.OrganizationFeatures.Policies.PolicyRequirements;
using Bit.Core.AdminConsole.Repositories;
using Bit.Core.Auth.Entities;
using Bit.Core.Auth.Enums;
@@ -34,6 +36,8 @@ public class EmergencyAccessService : IEmergencyAccessService
private readonly GlobalSettings _globalSettings;
private readonly IDataProtectorTokenFactory _dataProtectorTokenizer;
private readonly IRemoveOrganizationUserCommand _removeOrganizationUserCommand;
+ private readonly IFeatureService _featureService;
+ private readonly IPolicyRequirementQuery _policyRequirementQuery;
public EmergencyAccessService(
IEmergencyAccessRepository emergencyAccessRepository,
@@ -46,7 +50,9 @@ public class EmergencyAccessService : IEmergencyAccessService
IUserService userService,
GlobalSettings globalSettings,
IDataProtectorTokenFactory dataProtectorTokenizer,
- IRemoveOrganizationUserCommand removeOrganizationUserCommand)
+ IRemoveOrganizationUserCommand removeOrganizationUserCommand,
+ IFeatureService featureService,
+ IPolicyRequirementQuery policyRequirementQuery)
{
_emergencyAccessRepository = emergencyAccessRepository;
_organizationUserRepository = organizationUserRepository;
@@ -59,6 +65,8 @@ public class EmergencyAccessService : IEmergencyAccessService
_globalSettings = globalSettings;
_dataProtectorTokenizer = dataProtectorTokenizer;
_removeOrganizationUserCommand = removeOrganizationUserCommand;
+ _featureService = featureService;
+ _policyRequirementQuery = policyRequirementQuery;
}
public async Task InviteAsync(User grantorUser, string emergencyContactEmail, EmergencyAccessType accessType, int waitTime)
@@ -73,6 +81,17 @@ public class EmergencyAccessService : IEmergencyAccessService
throw new BadRequestException("You cannot use Emergency Access Takeover because you are using Key Connector.");
}
+ if (_featureService.IsEnabled(FeatureFlagKeys.AutomaticConfirmUsers))
+ {
+ var requirement = await _policyRequirementQuery
+ .GetAsync(grantorUser.Id);
+
+ if (requirement.CannotGrantEmergencyAccess())
+ {
+ throw new BadRequestException("You cannot invite emergency contacts because you are a member of an organization that uses Automatic User Confirmation.");
+ }
+ }
+
var emergencyAccess = new EmergencyAccess
{
GrantorId = grantorUser.Id,
@@ -131,6 +150,17 @@ public class EmergencyAccessService : IEmergencyAccessService
throw new BadRequestException("Invalid token.");
}
+ if (_featureService.IsEnabled(FeatureFlagKeys.AutomaticConfirmUsers))
+ {
+ var requirement = await _policyRequirementQuery
+ .GetAsync(granteeUser.Id);
+
+ if (requirement.CannotBeGrantedEmergencyAccess())
+ {
+ throw new BadRequestException("You cannot accept emergency access invitations because you are a member of an organization that uses Automatic User Confirmation.");
+ }
+ }
+
if (emergencyAccess.Status == EmergencyAccessStatusType.Accepted)
{
throw new BadRequestException("Invitation already accepted. You will receive an email when the grantor confirms you as an emergency access contact.");
diff --git a/test/Core.Test/AdminConsole/OrganizationFeatures/Policies/PolicyRequirements/AutomaticUserConfirmationPolicyRequirementTests.cs b/test/Core.Test/AdminConsole/OrganizationFeatures/Policies/PolicyRequirements/AutomaticUserConfirmationPolicyRequirementTests.cs
new file mode 100644
index 0000000000..8a5d1f6f6f
--- /dev/null
+++ b/test/Core.Test/AdminConsole/OrganizationFeatures/Policies/PolicyRequirements/AutomaticUserConfirmationPolicyRequirementTests.cs
@@ -0,0 +1,152 @@
+using Bit.Core.AdminConsole.Enums;
+using Bit.Core.AdminConsole.Models.Data.Organizations.Policies;
+using Bit.Core.AdminConsole.OrganizationFeatures.Policies.PolicyRequirements;
+using Bit.Core.Enums;
+using Xunit;
+
+namespace Bit.Core.Test.AdminConsole.OrganizationFeatures.Policies.PolicyRequirements;
+
+public class AutomaticUserConfirmationPolicyRequirementTests
+{
+ [Theory]
+ [InlineData(OrganizationUserStatusType.Accepted)]
+ [InlineData(OrganizationUserStatusType.Confirmed)]
+ [InlineData(OrganizationUserStatusType.Revoked)]
+ public void CannotGrantEmergencyAccess_WithActiveStatus_ReturnsTrue(OrganizationUserStatusType status)
+ {
+ var policyDetails = new[]
+ {
+ new PolicyDetails
+ {
+ OrganizationId = Guid.NewGuid(),
+ PolicyType = PolicyType.AutomaticUserConfirmation,
+ OrganizationUserStatus = status
+ }
+ };
+
+ var sut = new AutomaticUserConfirmationPolicyRequirement(policyDetails);
+
+ Assert.True(sut.CannotGrantEmergencyAccess());
+ }
+
+ [Fact]
+ public void CannotGrantEmergencyAccess_WithInvitedStatus_ReturnsFalse()
+ {
+ var policyDetails = new[]
+ {
+ new PolicyDetails
+ {
+ OrganizationId = Guid.NewGuid(),
+ PolicyType = PolicyType.AutomaticUserConfirmation,
+ OrganizationUserStatus = OrganizationUserStatusType.Invited
+ }
+ };
+
+ var sut = new AutomaticUserConfirmationPolicyRequirement(policyDetails);
+
+ Assert.False(sut.CannotGrantEmergencyAccess());
+ }
+
+ [Fact]
+ public void CannotGrantEmergencyAccess_WithNoPolicies_ReturnsFalse()
+ {
+ var sut = new AutomaticUserConfirmationPolicyRequirement([]);
+
+ Assert.False(sut.CannotGrantEmergencyAccess());
+ }
+
+ [Theory]
+ [InlineData(OrganizationUserStatusType.Accepted)]
+ [InlineData(OrganizationUserStatusType.Confirmed)]
+ [InlineData(OrganizationUserStatusType.Revoked)]
+ public void CannotBeGrantedEmergencyAccess_WithActiveStatus_ReturnsTrue(OrganizationUserStatusType status)
+ {
+ var policyDetails = new[]
+ {
+ new PolicyDetails
+ {
+ OrganizationId = Guid.NewGuid(),
+ PolicyType = PolicyType.AutomaticUserConfirmation,
+ OrganizationUserStatus = status
+ }
+ };
+
+ var sut = new AutomaticUserConfirmationPolicyRequirement(policyDetails);
+
+ Assert.True(sut.CannotBeGrantedEmergencyAccess());
+ }
+
+ [Fact]
+ public void CannotBeGrantedEmergencyAccess_WithInvitedStatus_ReturnsFalse()
+ {
+ var policyDetails = new[]
+ {
+ new PolicyDetails
+ {
+ OrganizationId = Guid.NewGuid(),
+ PolicyType = PolicyType.AutomaticUserConfirmation,
+ OrganizationUserStatus = OrganizationUserStatusType.Invited
+ }
+ };
+
+ var sut = new AutomaticUserConfirmationPolicyRequirement(policyDetails);
+
+ Assert.False(sut.CannotBeGrantedEmergencyAccess());
+ }
+
+ [Fact]
+ public void CannotBeGrantedEmergencyAccess_WithNoPolicies_ReturnsFalse()
+ {
+ var sut = new AutomaticUserConfirmationPolicyRequirement([]);
+
+ Assert.False(sut.CannotBeGrantedEmergencyAccess());
+ }
+
+ [Fact]
+ public void CannotGrantEmergencyAccess_WithMultiplePolicies_OneActive_ReturnsTrue()
+ {
+ var policyDetails = new[]
+ {
+ new PolicyDetails
+ {
+ OrganizationId = Guid.NewGuid(),
+ PolicyType = PolicyType.AutomaticUserConfirmation,
+ OrganizationUserStatus = OrganizationUserStatusType.Invited
+ },
+ new PolicyDetails
+ {
+ OrganizationId = Guid.NewGuid(),
+ PolicyType = PolicyType.AutomaticUserConfirmation,
+ OrganizationUserStatus = OrganizationUserStatusType.Confirmed
+ }
+ };
+
+ var sut = new AutomaticUserConfirmationPolicyRequirement(policyDetails);
+
+ Assert.True(sut.CannotGrantEmergencyAccess());
+ }
+
+ [Fact]
+ public void CannotBeGrantedEmergencyAccess_WithMultiplePolicies_OneActive_ReturnsTrue()
+ {
+ var policyDetails = new[]
+ {
+ new PolicyDetails
+ {
+ OrganizationId = Guid.NewGuid(),
+ PolicyType = PolicyType.AutomaticUserConfirmation,
+ OrganizationUserStatus = OrganizationUserStatusType.Invited
+ },
+ new PolicyDetails
+ {
+ OrganizationId = Guid.NewGuid(),
+ PolicyType = PolicyType.AutomaticUserConfirmation,
+ OrganizationUserStatus = OrganizationUserStatusType.Confirmed
+ }
+ };
+
+ var sut = new AutomaticUserConfirmationPolicyRequirement(policyDetails);
+
+ Assert.True(sut.CannotBeGrantedEmergencyAccess());
+ }
+}
diff --git a/test/Core.Test/Auth/Services/EmergencyAccessServiceTests.cs b/test/Core.Test/Auth/Services/EmergencyAccessServiceTests.cs
index 006515aafd..62b1e62893 100644
--- a/test/Core.Test/Auth/Services/EmergencyAccessServiceTests.cs
+++ b/test/Core.Test/Auth/Services/EmergencyAccessServiceTests.cs
@@ -1,4 +1,8 @@
-using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Interfaces;
+using Bit.Core.AdminConsole.Enums;
+using Bit.Core.AdminConsole.Models.Data.Organizations.Policies;
+using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Interfaces;
+using Bit.Core.AdminConsole.OrganizationFeatures.Policies;
+using Bit.Core.AdminConsole.OrganizationFeatures.Policies.PolicyRequirements;
using Bit.Core.AdminConsole.Repositories;
using Bit.Core.Auth.Entities;
using Bit.Core.Auth.Enums;
@@ -1512,4 +1516,317 @@ public class EmergencyAccessServiceTests
var exception = await Assert.ThrowsAsync(
() => sutProvider.Sut.GetAttachmentDownloadAsync(emergencyAccess.Id, default, default, granteeUser));
}
+
+ [Theory]
+ [BitAutoData(OrganizationUserStatusType.Accepted)]
+ [BitAutoData(OrganizationUserStatusType.Confirmed)]
+ [BitAutoData(OrganizationUserStatusType.Revoked)]
+ public async Task InviteAsync_FeatureFlagEnabled_UserInAutoConfirmOrg_ThrowsBadRequest(
+ OrganizationUserStatusType status,
+ SutProvider sutProvider,
+ User invitingUser,
+ string email,
+ int waitTime)
+ {
+ sutProvider.GetDependency().CanAccessPremium(invitingUser).Returns(true);
+ sutProvider.GetDependency()
+ .IsEnabled(FeatureFlagKeys.AutomaticConfirmUsers)
+ .Returns(true);
+
+ // Create a real requirement with an active status that blocks emergency access
+ var requirement = new AutomaticUserConfirmationPolicyRequirement(
+ [
+ new PolicyDetails
+ {
+ OrganizationId = Guid.NewGuid(),
+ PolicyType = PolicyType.AutomaticUserConfirmation,
+ OrganizationUserStatus = status
+ }
+ ]);
+
+ sutProvider.GetDependency()
+ .GetAsync(invitingUser.Id)
+ .Returns(requirement);
+
+ var exception = await Assert.ThrowsAsync(
+ () => sutProvider.Sut.InviteAsync(invitingUser, email, EmergencyAccessType.View, waitTime));
+
+ Assert.Contains("You cannot invite emergency contacts because you are a member of an organization that uses Automatic User Confirmation.", exception.Message);
+ await sutProvider.GetDependency()
+ .DidNotReceiveWithAnyArgs().CreateAsync(default);
+ }
+
+ [Theory, BitAutoData]
+ public async Task InviteAsync_FeatureFlagEnabled_UserNotInAutoConfirmOrg_Succeeds(
+ SutProvider sutProvider,
+ User invitingUser,
+ string email,
+ int waitTime)
+ {
+ sutProvider.GetDependency().CanAccessPremium(invitingUser).Returns(true);
+ sutProvider.GetDependency()
+ .IsEnabled(FeatureFlagKeys.AutomaticConfirmUsers)
+ .Returns(true);
+
+ // Create a real requirement with no policies (user is not in auto-confirm org)
+ var requirement = new AutomaticUserConfirmationPolicyRequirement([]);
+
+ sutProvider.GetDependency()
+ .GetAsync(invitingUser.Id)
+ .Returns(requirement);
+
+ var result = await sutProvider.Sut.InviteAsync(invitingUser, email, EmergencyAccessType.View, waitTime);
+
+ Assert.NotNull(result);
+ await sutProvider.GetDependency()
+ .Received(1).CreateAsync(Arg.Any());
+ }
+
+ [Theory, BitAutoData]
+ public async Task InviteAsync_FeatureFlagDisabled_UserInAutoConfirmOrg_Succeeds(
+ SutProvider sutProvider,
+ User invitingUser,
+ string email,
+ int waitTime)
+ {
+ sutProvider.GetDependency().CanAccessPremium(invitingUser).Returns(true);
+ sutProvider.GetDependency()
+ .IsEnabled(FeatureFlagKeys.AutomaticConfirmUsers)
+ .Returns(false);
+
+ var result = await sutProvider.Sut.InviteAsync(invitingUser, email, EmergencyAccessType.View, waitTime);
+
+ Assert.NotNull(result);
+ await sutProvider.GetDependency()
+ .Received(1).CreateAsync(Arg.Any());
+ await sutProvider.GetDependency()
+ .DidNotReceiveWithAnyArgs()
+ .GetAsync(default);
+ }
+
+ [Theory, BitAutoData]
+ public async Task InviteAsync_FeatureFlagEnabled_UserInvitedToAutoConfirmOrg_Succeeds(
+ SutProvider sutProvider,
+ User invitingUser,
+ string email,
+ int waitTime)
+ {
+ sutProvider.GetDependency().CanAccessPremium(invitingUser).Returns(true);
+ sutProvider.GetDependency()
+ .IsEnabled(FeatureFlagKeys.AutomaticConfirmUsers)
+ .Returns(true);
+
+ // Create a real requirement with Invited status (should not block emergency access)
+ var requirement = new AutomaticUserConfirmationPolicyRequirement(
+ [
+ new PolicyDetails
+ {
+ OrganizationId = Guid.NewGuid(),
+ PolicyType = PolicyType.AutomaticUserConfirmation,
+ OrganizationUserStatus = OrganizationUserStatusType.Invited
+ }
+ ]);
+
+ sutProvider.GetDependency()
+ .GetAsync(invitingUser.Id)
+ .Returns(requirement);
+
+ var result = await sutProvider.Sut.InviteAsync(invitingUser, email, EmergencyAccessType.View, waitTime);
+
+ Assert.NotNull(result);
+ await sutProvider.GetDependency()
+ .Received(1).CreateAsync(Arg.Any());
+ }
+
+ [Theory]
+ [BitAutoData(OrganizationUserStatusType.Accepted)]
+ [BitAutoData(OrganizationUserStatusType.Confirmed)]
+ [BitAutoData(OrganizationUserStatusType.Revoked)]
+ public async Task AcceptUserAsync_FeatureFlagEnabled_UserInAutoConfirmOrg_ThrowsBadRequest(
+ OrganizationUserStatusType status,
+ SutProvider sutProvider,
+ User acceptingUser,
+ EmergencyAccess emergencyAccess,
+ string token)
+ {
+ emergencyAccess.Status = EmergencyAccessStatusType.Invited;
+ emergencyAccess.Email = acceptingUser.Email;
+
+ sutProvider.GetDependency()
+ .GetByIdAsync(Arg.Any())
+ .Returns(emergencyAccess);
+
+ sutProvider.GetDependency>()
+ .TryUnprotect(token, out Arg.Any())
+ .Returns(callInfo =>
+ {
+ callInfo[1] = new EmergencyAccessInviteTokenable(emergencyAccess, 1);
+ return true;
+ });
+
+ sutProvider.GetDependency()
+ .IsEnabled(FeatureFlagKeys.AutomaticConfirmUsers)
+ .Returns(true);
+
+ // Create a real requirement with an active status that blocks emergency access
+ var requirement = new AutomaticUserConfirmationPolicyRequirement(
+ [
+ new PolicyDetails
+ {
+ OrganizationId = Guid.NewGuid(),
+ PolicyType = PolicyType.AutomaticUserConfirmation,
+ OrganizationUserStatus = status
+ }
+ ]);
+
+ sutProvider.GetDependency()
+ .GetAsync(acceptingUser.Id)
+ .Returns(requirement);
+
+ var exception = await Assert.ThrowsAsync(
+ () => sutProvider.Sut.AcceptUserAsync(emergencyAccess.Id, acceptingUser, token, sutProvider.GetDependency()));
+
+ Assert.Contains("You cannot accept emergency access invitations because you are a member of an organization that uses Automatic User Confirmation.", exception.Message);
+ await sutProvider.GetDependency()
+ .DidNotReceiveWithAnyArgs().ReplaceAsync(default);
+ }
+
+ [Theory, BitAutoData]
+ public async Task AcceptUserAsync_FeatureFlagEnabled_UserNotInAutoConfirmOrg_Succeeds(
+ SutProvider sutProvider,
+ User acceptingUser,
+ User invitingUser,
+ EmergencyAccess emergencyAccess,
+ string token)
+ {
+ emergencyAccess.Status = EmergencyAccessStatusType.Invited;
+ emergencyAccess.Email = acceptingUser.Email;
+
+ sutProvider.GetDependency()
+ .GetByIdAsync(Arg.Any())
+ .Returns(emergencyAccess);
+
+ sutProvider.GetDependency()
+ .GetUserByIdAsync(Arg.Any())
+ .Returns(invitingUser);
+
+ sutProvider.GetDependency>()
+ .TryUnprotect(token, out Arg.Any())
+ .Returns(callInfo =>
+ {
+ callInfo[1] = new EmergencyAccessInviteTokenable(emergencyAccess, 1);
+ return true;
+ });
+
+ sutProvider.GetDependency()
+ .IsEnabled(FeatureFlagKeys.AutomaticConfirmUsers)
+ .Returns(true);
+
+ // Create a real requirement with no policies (user is not in auto-confirm org)
+ var requirement = new AutomaticUserConfirmationPolicyRequirement([]);
+
+ sutProvider.GetDependency()
+ .GetAsync(acceptingUser.Id)
+ .Returns(requirement);
+
+ await sutProvider.Sut.AcceptUserAsync(emergencyAccess.Id, acceptingUser, token, sutProvider.GetDependency());
+
+ await sutProvider.GetDependency()
+ .Received(1)
+ .ReplaceAsync(Arg.Is(x => x.Status == EmergencyAccessStatusType.Accepted));
+ }
+
+ [Theory, BitAutoData]
+ public async Task AcceptUserAsync_FeatureFlagDisabled_UserInAutoConfirmOrg_Succeeds(
+ SutProvider sutProvider,
+ User acceptingUser,
+ User invitingUser,
+ EmergencyAccess emergencyAccess,
+ string token)
+ {
+ emergencyAccess.Status = EmergencyAccessStatusType.Invited;
+ emergencyAccess.Email = acceptingUser.Email;
+
+ sutProvider.GetDependency()
+ .GetByIdAsync(Arg.Any())
+ .Returns(emergencyAccess);
+
+ sutProvider.GetDependency()
+ .GetUserByIdAsync(Arg.Any())
+ .Returns(invitingUser);
+
+ sutProvider.GetDependency>()
+ .TryUnprotect(token, out Arg.Any())
+ .Returns(callInfo =>
+ {
+ callInfo[1] = new EmergencyAccessInviteTokenable(emergencyAccess, 1);
+ return true;
+ });
+
+ sutProvider.GetDependency()
+ .IsEnabled(FeatureFlagKeys.AutomaticConfirmUsers)
+ .Returns(false);
+
+ await sutProvider.Sut.AcceptUserAsync(emergencyAccess.Id, acceptingUser, token, sutProvider.GetDependency());
+
+ await sutProvider.GetDependency()
+ .Received(1)
+ .ReplaceAsync(Arg.Is(x => x.Status == EmergencyAccessStatusType.Accepted));
+ await sutProvider.GetDependency()
+ .DidNotReceiveWithAnyArgs()
+ .GetAsync(default);
+ }
+
+ [Theory, BitAutoData]
+ public async Task AcceptUserAsync_FeatureFlagEnabled_UserInvitedToAutoConfirmOrg_Succeeds(
+ SutProvider sutProvider,
+ User acceptingUser,
+ User invitingUser,
+ EmergencyAccess emergencyAccess,
+ string token)
+ {
+ emergencyAccess.Status = EmergencyAccessStatusType.Invited;
+ emergencyAccess.Email = acceptingUser.Email;
+
+ sutProvider.GetDependency()
+ .GetByIdAsync(Arg.Any())
+ .Returns(emergencyAccess);
+
+ sutProvider.GetDependency()
+ .GetUserByIdAsync(Arg.Any())
+ .Returns(invitingUser);
+
+ sutProvider.GetDependency>()
+ .TryUnprotect(token, out Arg.Any())
+ .Returns(callInfo =>
+ {
+ callInfo[1] = new EmergencyAccessInviteTokenable(emergencyAccess, 1);
+ return true;
+ });
+
+ sutProvider.GetDependency()
+ .IsEnabled(FeatureFlagKeys.AutomaticConfirmUsers)
+ .Returns(true);
+
+ // Create a real requirement with Invited status (should not block emergency access)
+ var requirement = new AutomaticUserConfirmationPolicyRequirement(
+ [
+ new PolicyDetails
+ {
+ OrganizationId = Guid.NewGuid(),
+ PolicyType = PolicyType.AutomaticUserConfirmation,
+ OrganizationUserStatus = OrganizationUserStatusType.Invited
+ }
+ ]);
+
+ sutProvider.GetDependency()
+ .GetAsync(acceptingUser.Id)
+ .Returns(requirement);
+
+ await sutProvider.Sut.AcceptUserAsync(emergencyAccess.Id, acceptingUser, token, sutProvider.GetDependency());
+
+ await sutProvider.GetDependency()
+ .Received(1)
+ .ReplaceAsync(Arg.Is(x => x.Status == EmergencyAccessStatusType.Accepted));
+ }
}