mirror of
https://github.com/bitwarden/server
synced 2026-02-14 07:23:26 +00:00
[PM-26379] Implement auto confirm push notification (#6980)
* implement auto confirm push notification * fix test * fix test * simplify LINQ
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
#nullable disable
|
||||
|
||||
using Bit.Core.AdminConsole.Enums;
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Interfaces;
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.Policies;
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.Policies.Enforcement.AutoConfirm;
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.Policies.PolicyRequirements;
|
||||
@@ -36,6 +37,7 @@ public class AcceptOrgUserCommand : IAcceptOrgUserCommand
|
||||
private readonly IFeatureService _featureService;
|
||||
private readonly IPolicyRequirementQuery _policyRequirementQuery;
|
||||
private readonly IAutomaticUserConfirmationPolicyEnforcementValidator _automaticUserConfirmationPolicyEnforcementValidator;
|
||||
private readonly IPushAutoConfirmNotificationCommand _pushAutoConfirmNotificationCommand;
|
||||
|
||||
public AcceptOrgUserCommand(
|
||||
IDataProtectionProvider dataProtectionProvider,
|
||||
@@ -49,7 +51,8 @@ public class AcceptOrgUserCommand : IAcceptOrgUserCommand
|
||||
IDataProtectorTokenFactory<OrgUserInviteTokenable> orgUserInviteTokenDataFactory,
|
||||
IFeatureService featureService,
|
||||
IPolicyRequirementQuery policyRequirementQuery,
|
||||
IAutomaticUserConfirmationPolicyEnforcementValidator automaticUserConfirmationPolicyEnforcementValidator)
|
||||
IAutomaticUserConfirmationPolicyEnforcementValidator automaticUserConfirmationPolicyEnforcementValidator,
|
||||
IPushAutoConfirmNotificationCommand pushAutoConfirmNotificationCommand)
|
||||
{
|
||||
// TODO: remove data protector when old token validation removed
|
||||
_dataProtector = dataProtectionProvider.CreateProtector(OrgUserInviteTokenable.DataProtectorPurpose);
|
||||
@@ -64,6 +67,7 @@ public class AcceptOrgUserCommand : IAcceptOrgUserCommand
|
||||
_featureService = featureService;
|
||||
_policyRequirementQuery = policyRequirementQuery;
|
||||
_automaticUserConfirmationPolicyEnforcementValidator = automaticUserConfirmationPolicyEnforcementValidator;
|
||||
_pushAutoConfirmNotificationCommand = pushAutoConfirmNotificationCommand;
|
||||
}
|
||||
|
||||
public async Task<OrganizationUser> AcceptOrgUserByEmailTokenAsync(Guid organizationUserId, User user, string emailToken,
|
||||
@@ -233,6 +237,11 @@ public class AcceptOrgUserCommand : IAcceptOrgUserCommand
|
||||
await _mailService.SendOrganizationAcceptedEmailAsync(organization, user.Email, adminEmails);
|
||||
}
|
||||
|
||||
if (_featureService.IsEnabled(FeatureFlagKeys.AutomaticConfirmUsers))
|
||||
{
|
||||
await _pushAutoConfirmNotificationCommand.PushAsync(user.Id, orgUser.OrganizationId);
|
||||
}
|
||||
|
||||
return orgUser;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Interfaces;
|
||||
|
||||
public interface IPushAutoConfirmNotificationCommand
|
||||
{
|
||||
Task PushAsync(Guid userId, Guid organizationId);
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Interfaces;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Models;
|
||||
using Bit.Core.Platform.Push;
|
||||
using Bit.Core.Repositories;
|
||||
|
||||
namespace Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers;
|
||||
|
||||
public class PushAutoConfirmNotificationCommand : IPushAutoConfirmNotificationCommand
|
||||
{
|
||||
private readonly IOrganizationUserRepository _organizationUserRepository;
|
||||
private readonly IPushNotificationService _pushNotificationService;
|
||||
|
||||
public PushAutoConfirmNotificationCommand(
|
||||
IOrganizationUserRepository organizationUserRepository,
|
||||
IPushNotificationService pushNotificationService)
|
||||
{
|
||||
_organizationUserRepository = organizationUserRepository;
|
||||
_pushNotificationService = pushNotificationService;
|
||||
}
|
||||
|
||||
public async Task PushAsync(Guid userId, Guid organizationId)
|
||||
{
|
||||
var organizationUser = await _organizationUserRepository.GetByOrganizationAsync(organizationId, userId);
|
||||
if (organizationUser == null)
|
||||
{
|
||||
throw new Exception("Organization user not found");
|
||||
}
|
||||
|
||||
var admins = await _organizationUserRepository.GetManyByMinimumRoleAsync(
|
||||
organizationId,
|
||||
OrganizationUserType.Admin);
|
||||
|
||||
var customUsersWithManagePermission = (await _organizationUserRepository.GetManyDetailsByRoleAsync(
|
||||
organizationId,
|
||||
OrganizationUserType.Custom))
|
||||
.Where(c => c.GetPermissions()?.ManageUsers == true)
|
||||
.Select(c => c.UserId);
|
||||
|
||||
var userIds = admins
|
||||
.Select(a => a.UserId)
|
||||
.Concat(customUsersWithManagePermission)
|
||||
.Where(id => id.HasValue)
|
||||
.Select(id => id!.Value)
|
||||
.Distinct();
|
||||
|
||||
foreach (var adminUserId in userIds)
|
||||
{
|
||||
await _pushNotificationService.PushAsync(
|
||||
new PushNotification<AutoConfirmPushNotification>
|
||||
{
|
||||
Target = NotificationTarget.User,
|
||||
TargetId = adminUserId,
|
||||
Type = PushType.AutoConfirm,
|
||||
Payload = new AutoConfirmPushNotification
|
||||
{
|
||||
UserId = adminUserId,
|
||||
OrganizationId = organizationId,
|
||||
TargetUserId = organizationUser.Id
|
||||
},
|
||||
ExcludeCurrentContext = false,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -110,3 +110,21 @@ public class SyncPolicyPushNotification
|
||||
public Guid OrganizationId { get; set; }
|
||||
public required Policy Policy { get; set; }
|
||||
}
|
||||
|
||||
public class AutoConfirmPushNotification
|
||||
{
|
||||
/// <summary>
|
||||
/// The admin/owner receiving this notification
|
||||
/// </summary>
|
||||
public Guid UserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The organization the user accepted an invite to
|
||||
/// </summary>
|
||||
public Guid OrganizationId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The user who accepted the organization invite (will be auto-confirmed)
|
||||
/// </summary>
|
||||
public Guid TargetUserId { get; set; }
|
||||
}
|
||||
|
||||
@@ -197,6 +197,7 @@ public static class OrganizationServiceCollectionExtensions
|
||||
{
|
||||
services.AddScoped<ICountNewSmSeatsRequiredQuery, CountNewSmSeatsRequiredQuery>();
|
||||
services.AddScoped<IAcceptOrgUserCommand, AcceptOrgUserCommand>();
|
||||
services.AddScoped<IPushAutoConfirmNotificationCommand, PushAutoConfirmNotificationCommand>();
|
||||
services.AddScoped<IOrganizationUserUserDetailsQuery, OrganizationUserUserDetailsQuery>();
|
||||
services.AddScoped<IGetOrganizationUsersClaimedStatusQuery, GetOrganizationUsersClaimedStatusQuery>();
|
||||
|
||||
|
||||
@@ -99,4 +99,7 @@ public enum PushType : byte
|
||||
|
||||
[NotificationInfo("@bitwarden/team-admin-console-dev", typeof(Models.SyncPolicyPushNotification))]
|
||||
PolicyChanged = 25,
|
||||
|
||||
[NotificationInfo("@bitwarden/team-admin-console-dev", typeof(Models.AutoConfirmPushNotification))]
|
||||
AutoConfirm = 26,
|
||||
}
|
||||
|
||||
@@ -234,6 +234,18 @@ public class HubHelpers
|
||||
case PushType.PolicyChanged:
|
||||
await policyChangedNotificationHandler(notificationJson, cancellationToken);
|
||||
break;
|
||||
case PushType.AutoConfirm:
|
||||
var autoConfirmNotification =
|
||||
JsonSerializer.Deserialize<PushNotificationData<AutoConfirmPushNotification>>(
|
||||
notificationJson, _deserializerOptions);
|
||||
if (autoConfirmNotification is null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
await _hubContext.Clients.User(autoConfirmNotification.Payload.UserId.ToString())
|
||||
.SendAsync(_receiveMessageMethod, autoConfirmNotification, cancellationToken);
|
||||
break;
|
||||
default:
|
||||
_logger.LogWarning("Notification type '{NotificationType}' has not been registered in HubHelpers and will not be pushed as as result", notification.Type);
|
||||
break;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using Bit.Core.AdminConsole.Enums;
|
||||
using Bit.Core.AdminConsole.Models.Data.Organizations.Policies;
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.AutoConfirmUser;
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Interfaces;
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.Policies;
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.Policies.Enforcement.AutoConfirm;
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.Policies.PolicyRequirements;
|
||||
@@ -767,6 +768,50 @@ public class AcceptOrgUserCommandTests
|
||||
|
||||
}
|
||||
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task AcceptOrgUser_WithAutoConfirmFeatureFlagEnabled_SendsPushNotification(
|
||||
SutProvider<AcceptOrgUserCommand> sutProvider,
|
||||
User user, Organization org, OrganizationUser orgUser, OrganizationUserUserDetails adminUserDetails)
|
||||
{
|
||||
SetupCommonAcceptOrgUserMocks(sutProvider, user, org, orgUser, adminUserDetails);
|
||||
|
||||
sutProvider.GetDependency<IFeatureService>()
|
||||
.IsEnabled(FeatureFlagKeys.AutomaticConfirmUsers)
|
||||
.Returns(true);
|
||||
|
||||
sutProvider.GetDependency<IAutomaticUserConfirmationPolicyEnforcementValidator>()
|
||||
.IsCompliantAsync(Arg.Any<AutomaticUserConfirmationPolicyEnforcementRequest>())
|
||||
.Returns(Valid(new AutomaticUserConfirmationPolicyEnforcementRequest(org.Id, [orgUser], user)));
|
||||
|
||||
await sutProvider.Sut.AcceptOrgUserAsync(orgUser, user, _userService);
|
||||
|
||||
await sutProvider.GetDependency<IPushAutoConfirmNotificationCommand>()
|
||||
.Received(1)
|
||||
.PushAsync(user.Id, orgUser.OrganizationId);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task AcceptOrgUser_WithAutoConfirmFeatureFlagDisabled_DoesNotSendPushNotification(
|
||||
SutProvider<AcceptOrgUserCommand> sutProvider,
|
||||
User user, Organization org, OrganizationUser orgUser, OrganizationUserUserDetails adminUserDetails)
|
||||
{
|
||||
SetupCommonAcceptOrgUserMocks(sutProvider, user, org, orgUser, adminUserDetails);
|
||||
|
||||
sutProvider.GetDependency<IFeatureService>()
|
||||
.IsEnabled(FeatureFlagKeys.AutomaticConfirmUsers)
|
||||
.Returns(false);
|
||||
|
||||
await sutProvider.Sut.AcceptOrgUserAsync(orgUser, user, _userService);
|
||||
|
||||
await sutProvider.GetDependency<IPushAutoConfirmNotificationCommand>()
|
||||
.DidNotReceiveWithAnyArgs()
|
||||
.PushAsync(Arg.Any<Guid>(), Arg.Any<Guid>());
|
||||
}
|
||||
|
||||
|
||||
private void SetupCommonAcceptOrgUserByTokenMocks(SutProvider<AcceptOrgUserCommand> sutProvider, User user, OrganizationUser orgUser)
|
||||
{
|
||||
sutProvider.GetDependency<IGlobalSettings>().OrganizationInviteExpirationHours.Returns(24);
|
||||
|
||||
@@ -0,0 +1,286 @@
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers;
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Models;
|
||||
using Bit.Core.Models.Data.Organizations.OrganizationUsers;
|
||||
using Bit.Core.Platform.Push;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Test.Common.AutoFixture;
|
||||
using Bit.Test.Common.AutoFixture.Attributes;
|
||||
using NSubstitute;
|
||||
using Xunit;
|
||||
|
||||
namespace Bit.Core.Test.AdminConsole.OrganizationFeatures.OrganizationUsers;
|
||||
|
||||
[SutProviderCustomize]
|
||||
public class PushAutoConfirmNotificationCommandTests
|
||||
{
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task PushAsync_SendsNotificationToAdminsAndOwners(
|
||||
SutProvider<PushAutoConfirmNotificationCommand> sutProvider,
|
||||
Guid userId,
|
||||
Guid organizationId,
|
||||
OrganizationUser orgUser,
|
||||
List<OrganizationUserUserDetails> admins)
|
||||
{
|
||||
foreach (var admin in admins)
|
||||
{
|
||||
admin.UserId = Guid.NewGuid();
|
||||
}
|
||||
|
||||
orgUser.Id = Guid.NewGuid();
|
||||
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||
.GetByOrganizationAsync(organizationId, userId)
|
||||
.Returns(orgUser);
|
||||
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||
.GetManyByMinimumRoleAsync(organizationId, OrganizationUserType.Admin)
|
||||
.Returns(admins);
|
||||
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||
.GetManyDetailsByRoleAsync(organizationId, OrganizationUserType.Custom)
|
||||
.Returns(new List<OrganizationUserUserDetails>());
|
||||
|
||||
await sutProvider.Sut.PushAsync(userId, organizationId);
|
||||
|
||||
await sutProvider.GetDependency<IPushNotificationService>()
|
||||
.Received(admins.Count)
|
||||
.PushAsync(Arg.Is<PushNotification<AutoConfirmPushNotification>>(pn =>
|
||||
pn.Type == PushType.AutoConfirm &&
|
||||
pn.Target == NotificationTarget.User &&
|
||||
pn.Payload.OrganizationId == organizationId &&
|
||||
pn.Payload.TargetUserId == orgUser.Id &&
|
||||
pn.ExcludeCurrentContext == false));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task PushAsync_SendsNotificationToCustomUsersWithManageUsersPermission(
|
||||
SutProvider<PushAutoConfirmNotificationCommand> sutProvider,
|
||||
Guid userId,
|
||||
Guid organizationId,
|
||||
OrganizationUser orgUser,
|
||||
List<OrganizationUserUserDetails> customUsers)
|
||||
{
|
||||
foreach (var customUser in customUsers)
|
||||
{
|
||||
customUser.UserId = Guid.NewGuid();
|
||||
customUser.Permissions = "{\"manageUsers\":true}";
|
||||
}
|
||||
|
||||
orgUser.Id = Guid.NewGuid();
|
||||
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||
.GetByOrganizationAsync(organizationId, userId)
|
||||
.Returns(orgUser);
|
||||
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||
.GetManyByMinimumRoleAsync(organizationId, OrganizationUserType.Admin)
|
||||
.Returns(new List<OrganizationUserUserDetails>());
|
||||
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||
.GetManyDetailsByRoleAsync(organizationId, OrganizationUserType.Custom)
|
||||
.Returns(customUsers);
|
||||
|
||||
await sutProvider.Sut.PushAsync(userId, organizationId);
|
||||
|
||||
await sutProvider.GetDependency<IPushNotificationService>()
|
||||
.Received(customUsers.Count)
|
||||
.PushAsync(Arg.Is<PushNotification<AutoConfirmPushNotification>>(pn =>
|
||||
pn.Type == PushType.AutoConfirm &&
|
||||
pn.Target == NotificationTarget.User &&
|
||||
pn.Payload.OrganizationId == organizationId &&
|
||||
pn.Payload.TargetUserId == orgUser.Id &&
|
||||
pn.ExcludeCurrentContext == false));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task PushAsync_DoesNotSendToCustomUsersWithoutManageUsersPermission(
|
||||
SutProvider<PushAutoConfirmNotificationCommand> sutProvider,
|
||||
Guid userId,
|
||||
Guid organizationId,
|
||||
OrganizationUser orgUser,
|
||||
List<OrganizationUserUserDetails> customUsers)
|
||||
{
|
||||
foreach (var customUser in customUsers)
|
||||
{
|
||||
customUser.UserId = Guid.NewGuid();
|
||||
customUser.Permissions = "{\"manageUsers\":false}";
|
||||
}
|
||||
|
||||
orgUser.Id = Guid.NewGuid();
|
||||
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||
.GetByOrganizationAsync(organizationId, userId)
|
||||
.Returns(orgUser);
|
||||
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||
.GetManyByMinimumRoleAsync(organizationId, OrganizationUserType.Admin)
|
||||
.Returns(new List<OrganizationUserUserDetails>());
|
||||
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||
.GetManyDetailsByRoleAsync(organizationId, OrganizationUserType.Custom)
|
||||
.Returns(customUsers);
|
||||
|
||||
await sutProvider.Sut.PushAsync(userId, organizationId);
|
||||
|
||||
await sutProvider.GetDependency<IPushNotificationService>()
|
||||
.DidNotReceiveWithAnyArgs()
|
||||
.PushAsync(Arg.Any<PushNotification<AutoConfirmPushNotification>>());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task PushAsync_SendsToAdminsAndCustomUsersWithManageUsers(
|
||||
SutProvider<PushAutoConfirmNotificationCommand> sutProvider,
|
||||
Guid userId,
|
||||
Guid organizationId,
|
||||
OrganizationUser orgUser,
|
||||
List<OrganizationUserUserDetails> admins,
|
||||
List<OrganizationUserUserDetails> customUsersWithPermission,
|
||||
List<OrganizationUserUserDetails> customUsersWithoutPermission)
|
||||
{
|
||||
foreach (var admin in admins)
|
||||
{
|
||||
admin.UserId = Guid.NewGuid();
|
||||
}
|
||||
|
||||
foreach (var customUser in customUsersWithPermission)
|
||||
{
|
||||
customUser.UserId = Guid.NewGuid();
|
||||
customUser.Permissions = "{\"manageUsers\":true}";
|
||||
}
|
||||
|
||||
foreach (var customUser in customUsersWithoutPermission)
|
||||
{
|
||||
customUser.UserId = Guid.NewGuid();
|
||||
customUser.Permissions = "{\"manageUsers\":false}";
|
||||
}
|
||||
|
||||
orgUser.Id = Guid.NewGuid();
|
||||
|
||||
var allCustomUsers = customUsersWithPermission.Concat(customUsersWithoutPermission).ToList();
|
||||
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||
.GetByOrganizationAsync(organizationId, userId)
|
||||
.Returns(orgUser);
|
||||
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||
.GetManyByMinimumRoleAsync(organizationId, OrganizationUserType.Admin)
|
||||
.Returns(admins);
|
||||
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||
.GetManyDetailsByRoleAsync(organizationId, OrganizationUserType.Custom)
|
||||
.Returns(allCustomUsers);
|
||||
|
||||
await sutProvider.Sut.PushAsync(userId, organizationId);
|
||||
|
||||
var expectedNotificationCount = admins.Count + customUsersWithPermission.Count;
|
||||
await sutProvider.GetDependency<IPushNotificationService>()
|
||||
.Received(expectedNotificationCount)
|
||||
.PushAsync(Arg.Is<PushNotification<AutoConfirmPushNotification>>(pn =>
|
||||
pn.Type == PushType.AutoConfirm &&
|
||||
pn.Target == NotificationTarget.User &&
|
||||
pn.Payload.OrganizationId == organizationId &&
|
||||
pn.Payload.TargetUserId == orgUser.Id &&
|
||||
pn.ExcludeCurrentContext == false));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task PushAsync_SkipsUsersWithoutUserId(
|
||||
SutProvider<PushAutoConfirmNotificationCommand> sutProvider,
|
||||
Guid userId,
|
||||
Guid organizationId,
|
||||
OrganizationUser orgUser,
|
||||
List<OrganizationUserUserDetails> admins)
|
||||
{
|
||||
admins[0].UserId = Guid.NewGuid();
|
||||
admins[1].UserId = null;
|
||||
admins[2].UserId = Guid.NewGuid();
|
||||
|
||||
orgUser.Id = Guid.NewGuid();
|
||||
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||
.GetByOrganizationAsync(organizationId, userId)
|
||||
.Returns(orgUser);
|
||||
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||
.GetManyByMinimumRoleAsync(organizationId, OrganizationUserType.Admin)
|
||||
.Returns(admins);
|
||||
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||
.GetManyDetailsByRoleAsync(organizationId, OrganizationUserType.Custom)
|
||||
.Returns(new List<OrganizationUserUserDetails>());
|
||||
|
||||
await sutProvider.Sut.PushAsync(userId, organizationId);
|
||||
|
||||
await sutProvider.GetDependency<IPushNotificationService>()
|
||||
.Received(2)
|
||||
.PushAsync(Arg.Is<PushNotification<AutoConfirmPushNotification>>(pn =>
|
||||
pn.Type == PushType.AutoConfirm));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task PushAsync_DeduplicatesUserIds(
|
||||
SutProvider<PushAutoConfirmNotificationCommand> sutProvider,
|
||||
Guid userId,
|
||||
Guid organizationId,
|
||||
OrganizationUser orgUser,
|
||||
Guid duplicateUserId)
|
||||
{
|
||||
var admin1 = new OrganizationUserUserDetails { UserId = duplicateUserId };
|
||||
var admin2 = new OrganizationUserUserDetails { UserId = duplicateUserId };
|
||||
var customUser = new OrganizationUserUserDetails
|
||||
{
|
||||
UserId = duplicateUserId,
|
||||
Permissions = "{\"manageUsers\":true}"
|
||||
};
|
||||
|
||||
orgUser.Id = Guid.NewGuid();
|
||||
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||
.GetByOrganizationAsync(organizationId, userId)
|
||||
.Returns(orgUser);
|
||||
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||
.GetManyByMinimumRoleAsync(organizationId, OrganizationUserType.Admin)
|
||||
.Returns(new List<OrganizationUserUserDetails> { admin1, admin2 });
|
||||
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||
.GetManyDetailsByRoleAsync(organizationId, OrganizationUserType.Custom)
|
||||
.Returns(new List<OrganizationUserUserDetails> { customUser });
|
||||
|
||||
await sutProvider.Sut.PushAsync(userId, organizationId);
|
||||
|
||||
await sutProvider.GetDependency<IPushNotificationService>()
|
||||
.Received(1)
|
||||
.PushAsync(Arg.Is<PushNotification<AutoConfirmPushNotification>>(pn =>
|
||||
pn.TargetId == duplicateUserId));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task PushAsync_OrganizationUserNotFound_ThrowsException(
|
||||
SutProvider<PushAutoConfirmNotificationCommand> sutProvider,
|
||||
Guid userId,
|
||||
Guid organizationId)
|
||||
{
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||
.GetByOrganizationAsync(organizationId, userId)
|
||||
.Returns((OrganizationUser)null);
|
||||
|
||||
var exception = await Assert.ThrowsAsync<Exception>(() =>
|
||||
sutProvider.Sut.PushAsync(userId, organizationId));
|
||||
|
||||
Assert.Equal("Organization user not found", exception.Message);
|
||||
|
||||
await sutProvider.GetDependency<IPushNotificationService>()
|
||||
.DidNotReceiveWithAnyArgs()
|
||||
.PushAsync(Arg.Any<PushNotification<AutoConfirmPushNotification>>());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user