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 sutProvider, Guid userId, Guid organizationId, OrganizationUser orgUser, List admins) { foreach (var admin in admins) { admin.UserId = Guid.NewGuid(); } orgUser.Id = Guid.NewGuid(); sutProvider.GetDependency() .GetByOrganizationAsync(organizationId, userId) .Returns(orgUser); sutProvider.GetDependency() .GetManyByMinimumRoleAsync(organizationId, OrganizationUserType.Admin) .Returns(admins); sutProvider.GetDependency() .GetManyDetailsByRoleAsync(organizationId, OrganizationUserType.Custom) .Returns(new List()); await sutProvider.Sut.PushAsync(userId, organizationId); await sutProvider.GetDependency() .Received(admins.Count) .PushAsync(Arg.Is>(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 sutProvider, Guid userId, Guid organizationId, OrganizationUser orgUser, List customUsers) { foreach (var customUser in customUsers) { customUser.UserId = Guid.NewGuid(); customUser.Permissions = "{\"manageUsers\":true}"; } orgUser.Id = Guid.NewGuid(); sutProvider.GetDependency() .GetByOrganizationAsync(organizationId, userId) .Returns(orgUser); sutProvider.GetDependency() .GetManyByMinimumRoleAsync(organizationId, OrganizationUserType.Admin) .Returns(new List()); sutProvider.GetDependency() .GetManyDetailsByRoleAsync(organizationId, OrganizationUserType.Custom) .Returns(customUsers); await sutProvider.Sut.PushAsync(userId, organizationId); await sutProvider.GetDependency() .Received(customUsers.Count) .PushAsync(Arg.Is>(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 sutProvider, Guid userId, Guid organizationId, OrganizationUser orgUser, List customUsers) { foreach (var customUser in customUsers) { customUser.UserId = Guid.NewGuid(); customUser.Permissions = "{\"manageUsers\":false}"; } orgUser.Id = Guid.NewGuid(); sutProvider.GetDependency() .GetByOrganizationAsync(organizationId, userId) .Returns(orgUser); sutProvider.GetDependency() .GetManyByMinimumRoleAsync(organizationId, OrganizationUserType.Admin) .Returns(new List()); sutProvider.GetDependency() .GetManyDetailsByRoleAsync(organizationId, OrganizationUserType.Custom) .Returns(customUsers); await sutProvider.Sut.PushAsync(userId, organizationId); await sutProvider.GetDependency() .DidNotReceiveWithAnyArgs() .PushAsync(Arg.Any>()); } [Theory] [BitAutoData] public async Task PushAsync_SendsToAdminsAndCustomUsersWithManageUsers( SutProvider sutProvider, Guid userId, Guid organizationId, OrganizationUser orgUser, List admins, List customUsersWithPermission, List 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() .GetByOrganizationAsync(organizationId, userId) .Returns(orgUser); sutProvider.GetDependency() .GetManyByMinimumRoleAsync(organizationId, OrganizationUserType.Admin) .Returns(admins); sutProvider.GetDependency() .GetManyDetailsByRoleAsync(organizationId, OrganizationUserType.Custom) .Returns(allCustomUsers); await sutProvider.Sut.PushAsync(userId, organizationId); var expectedNotificationCount = admins.Count + customUsersWithPermission.Count; await sutProvider.GetDependency() .Received(expectedNotificationCount) .PushAsync(Arg.Is>(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 sutProvider, Guid userId, Guid organizationId, OrganizationUser orgUser, List admins) { admins[0].UserId = Guid.NewGuid(); admins[1].UserId = null; admins[2].UserId = Guid.NewGuid(); orgUser.Id = Guid.NewGuid(); sutProvider.GetDependency() .GetByOrganizationAsync(organizationId, userId) .Returns(orgUser); sutProvider.GetDependency() .GetManyByMinimumRoleAsync(organizationId, OrganizationUserType.Admin) .Returns(admins); sutProvider.GetDependency() .GetManyDetailsByRoleAsync(organizationId, OrganizationUserType.Custom) .Returns(new List()); await sutProvider.Sut.PushAsync(userId, organizationId); await sutProvider.GetDependency() .Received(2) .PushAsync(Arg.Is>(pn => pn.Type == PushType.AutoConfirm)); } [Theory] [BitAutoData] public async Task PushAsync_DeduplicatesUserIds( SutProvider 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() .GetByOrganizationAsync(organizationId, userId) .Returns(orgUser); sutProvider.GetDependency() .GetManyByMinimumRoleAsync(organizationId, OrganizationUserType.Admin) .Returns(new List { admin1, admin2 }); sutProvider.GetDependency() .GetManyDetailsByRoleAsync(organizationId, OrganizationUserType.Custom) .Returns(new List { customUser }); await sutProvider.Sut.PushAsync(userId, organizationId); await sutProvider.GetDependency() .Received(1) .PushAsync(Arg.Is>(pn => pn.TargetId == duplicateUserId)); } [Theory] [BitAutoData] public async Task PushAsync_OrganizationUserNotFound_ThrowsException( SutProvider sutProvider, Guid userId, Guid organizationId) { sutProvider.GetDependency() .GetByOrganizationAsync(organizationId, userId) .Returns((OrganizationUser)null); var exception = await Assert.ThrowsAsync(() => sutProvider.Sut.PushAsync(userId, organizationId)); Assert.Equal("Organization user not found", exception.Message); await sutProvider.GetDependency() .DidNotReceiveWithAnyArgs() .PushAsync(Arg.Any>()); } }