mirror of
https://github.com/bitwarden/server.git
synced 2025-07-01 16:12:49 -05:00
PM-15084: Push notifications to installation id.
This enables the Notification Center created global notifications to be sent to affected devices of the same server installation. All clients connected to any of the server instance of that installation id would receive it. This is useful for notifying all clients of an installation about upcoming maintenance. This works both for Self-Hosted, but also for Cloud, assuming an installation id is set.
This commit is contained in:
@ -5,11 +5,11 @@ using Bit.Core.Enums;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.Models.Api;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Settings;
|
||||
using Bit.Test.Common.AutoFixture;
|
||||
using Bit.Test.Common.AutoFixture.Attributes;
|
||||
using NSubstitute;
|
||||
using Xunit;
|
||||
using GlobalSettings = Bit.Core.Settings.GlobalSettings;
|
||||
|
||||
namespace Bit.Api.Test.Controllers;
|
||||
|
||||
@ -24,18 +24,19 @@ public class PushControllerTests
|
||||
public async Task SendAsync_InstallationIdNotSetOrSelfHosted_BadRequest(bool haveInstallationId, bool selfHosted,
|
||||
SutProvider<PushController> sutProvider, Guid installationId, Guid userId, Guid organizationId)
|
||||
{
|
||||
sutProvider.GetDependency<GlobalSettings>().SelfHosted = selfHosted;
|
||||
sutProvider.GetDependency<IGlobalSettings>().SelfHosted = selfHosted;
|
||||
if (haveInstallationId)
|
||||
{
|
||||
sutProvider.GetDependency<ICurrentContext>().InstallationId.Returns(installationId);
|
||||
}
|
||||
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(() =>
|
||||
sutProvider.Sut.PostSend(new PushSendRequestModel
|
||||
sutProvider.Sut.SendAsync(new PushSendRequestModel
|
||||
{
|
||||
Type = PushType.SyncNotificationCreate,
|
||||
UserId = userId.ToString(),
|
||||
OrganizationId = organizationId.ToString(),
|
||||
InstallationId = installationId.ToString(),
|
||||
Payload = "test-payload"
|
||||
}));
|
||||
|
||||
@ -47,21 +48,25 @@ public class PushControllerTests
|
||||
await sutProvider.GetDependency<IPushNotificationService>().Received(0)
|
||||
.SendPayloadToOrganizationAsync(Arg.Any<string>(), Arg.Any<PushType>(), Arg.Any<object>(),
|
||||
Arg.Any<string>(), Arg.Any<string?>(), Arg.Any<ClientType?>());
|
||||
await sutProvider.GetDependency<IPushNotificationService>().Received(0)
|
||||
.SendPayloadToInstallationAsync(Arg.Any<string>(), Arg.Any<PushType>(), Arg.Any<object>(),
|
||||
Arg.Any<string>(), Arg.Any<string?>(), Arg.Any<ClientType?>());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task SendAsync_UserIdAndOrganizationIdEmpty_NoPushNotificationSent(
|
||||
public async Task SendAsync_UserIdAndOrganizationIdAndInstallationIdEmpty_NoPushNotificationSent(
|
||||
SutProvider<PushController> sutProvider, Guid installationId)
|
||||
{
|
||||
sutProvider.GetDependency<GlobalSettings>().SelfHosted = false;
|
||||
sutProvider.GetDependency<IGlobalSettings>().SelfHosted = false;
|
||||
sutProvider.GetDependency<ICurrentContext>().InstallationId.Returns(installationId);
|
||||
|
||||
await sutProvider.Sut.PostSend(new PushSendRequestModel
|
||||
await sutProvider.Sut.SendAsync(new PushSendRequestModel
|
||||
{
|
||||
Type = PushType.SyncNotificationCreate,
|
||||
UserId = null,
|
||||
OrganizationId = null,
|
||||
InstallationId = null,
|
||||
Payload = "test-payload"
|
||||
});
|
||||
|
||||
@ -71,33 +76,30 @@ public class PushControllerTests
|
||||
await sutProvider.GetDependency<IPushNotificationService>().Received(0)
|
||||
.SendPayloadToOrganizationAsync(Arg.Any<string>(), Arg.Any<PushType>(), Arg.Any<object>(),
|
||||
Arg.Any<string>(), Arg.Any<string?>(), Arg.Any<ClientType?>());
|
||||
await sutProvider.GetDependency<IPushNotificationService>().Received(0)
|
||||
.SendPayloadToInstallationAsync(Arg.Any<string>(), Arg.Any<PushType>(), Arg.Any<object>(),
|
||||
Arg.Any<string>(), Arg.Any<string?>(), Arg.Any<ClientType?>());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData(true, true, false)]
|
||||
[BitAutoData(true, true, true)]
|
||||
[BitAutoData(true, false, true)]
|
||||
[BitAutoData(true, false, false)]
|
||||
[BitAutoData(false, true, true)]
|
||||
[BitAutoData(false, true, false)]
|
||||
[BitAutoData(false, false, true)]
|
||||
[BitAutoData(false, false, false)]
|
||||
[RepeatingPatternBitAutoData([false, true], [false, true], [false, true])]
|
||||
public async Task SendAsync_UserIdSet_SendPayloadToUserAsync(bool haveIdentifier, bool haveDeviceId,
|
||||
bool haveOrganizationId, SutProvider<PushController> sutProvider, Guid installationId, Guid userId,
|
||||
Guid identifier, Guid deviceId)
|
||||
{
|
||||
sutProvider.GetDependency<GlobalSettings>().SelfHosted = false;
|
||||
sutProvider.GetDependency<IGlobalSettings>().SelfHosted = false;
|
||||
sutProvider.GetDependency<ICurrentContext>().InstallationId.Returns(installationId);
|
||||
|
||||
var expectedUserId = $"{installationId}_{userId}";
|
||||
var expectedIdentifier = haveIdentifier ? $"{installationId}_{identifier}" : null;
|
||||
var expectedDeviceId = haveDeviceId ? $"{installationId}_{deviceId}" : null;
|
||||
|
||||
await sutProvider.Sut.PostSend(new PushSendRequestModel
|
||||
await sutProvider.Sut.SendAsync(new PushSendRequestModel
|
||||
{
|
||||
Type = PushType.SyncNotificationCreate,
|
||||
UserId = userId.ToString(),
|
||||
OrganizationId = haveOrganizationId ? Guid.NewGuid().ToString() : null,
|
||||
InstallationId = null,
|
||||
Payload = "test-payload",
|
||||
DeviceId = haveDeviceId ? deviceId.ToString() : null,
|
||||
Identifier = haveIdentifier ? identifier.ToString() : null,
|
||||
@ -110,29 +112,30 @@ public class PushControllerTests
|
||||
await sutProvider.GetDependency<IPushNotificationService>().Received(0)
|
||||
.SendPayloadToOrganizationAsync(Arg.Any<string>(), Arg.Any<PushType>(), Arg.Any<object>(),
|
||||
Arg.Any<string>(), Arg.Any<string?>(), Arg.Any<ClientType?>());
|
||||
await sutProvider.GetDependency<IPushNotificationService>().Received(0)
|
||||
.SendPayloadToInstallationAsync(Arg.Any<string>(), Arg.Any<PushType>(), Arg.Any<object>(),
|
||||
Arg.Any<string>(), Arg.Any<string?>(), Arg.Any<ClientType?>());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData(true, true)]
|
||||
[BitAutoData(true, false)]
|
||||
[BitAutoData(false, true)]
|
||||
[BitAutoData(false, false)]
|
||||
[RepeatingPatternBitAutoData([false, true], [false, true])]
|
||||
public async Task SendAsync_OrganizationIdSet_SendPayloadToOrganizationAsync(bool haveIdentifier, bool haveDeviceId,
|
||||
SutProvider<PushController> sutProvider, Guid installationId, Guid organizationId, Guid identifier,
|
||||
Guid deviceId)
|
||||
{
|
||||
sutProvider.GetDependency<GlobalSettings>().SelfHosted = false;
|
||||
sutProvider.GetDependency<IGlobalSettings>().SelfHosted = false;
|
||||
sutProvider.GetDependency<ICurrentContext>().InstallationId.Returns(installationId);
|
||||
|
||||
var expectedOrganizationId = $"{installationId}_{organizationId}";
|
||||
var expectedIdentifier = haveIdentifier ? $"{installationId}_{identifier}" : null;
|
||||
var expectedDeviceId = haveDeviceId ? $"{installationId}_{deviceId}" : null;
|
||||
|
||||
await sutProvider.Sut.PostSend(new PushSendRequestModel
|
||||
await sutProvider.Sut.SendAsync(new PushSendRequestModel
|
||||
{
|
||||
Type = PushType.SyncNotificationCreate,
|
||||
UserId = null,
|
||||
OrganizationId = organizationId.ToString(),
|
||||
InstallationId = null,
|
||||
Payload = "test-payload",
|
||||
DeviceId = haveDeviceId ? deviceId.ToString() : null,
|
||||
Identifier = haveIdentifier ? identifier.ToString() : null,
|
||||
@ -145,5 +148,141 @@ public class PushControllerTests
|
||||
await sutProvider.GetDependency<IPushNotificationService>().Received(0)
|
||||
.SendPayloadToUserAsync(Arg.Any<string>(), Arg.Any<PushType>(), Arg.Any<object>(), Arg.Any<string>(),
|
||||
Arg.Any<string?>(), Arg.Any<ClientType?>());
|
||||
await sutProvider.GetDependency<IPushNotificationService>().Received(0)
|
||||
.SendPayloadToInstallationAsync(Arg.Any<string>(), Arg.Any<PushType>(), Arg.Any<object>(),
|
||||
Arg.Any<string>(), Arg.Any<string?>(), Arg.Any<ClientType?>());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[RepeatingPatternBitAutoData([false, true], [false, true])]
|
||||
public async Task SendAsync_InstallationIdSet_SendPayloadToInstallationAsync(bool haveIdentifier, bool haveDeviceId,
|
||||
SutProvider<PushController> sutProvider, Guid installationId, Guid identifier, Guid deviceId)
|
||||
{
|
||||
sutProvider.GetDependency<IGlobalSettings>().SelfHosted = false;
|
||||
sutProvider.GetDependency<ICurrentContext>().InstallationId.Returns(installationId);
|
||||
|
||||
var expectedIdentifier = haveIdentifier ? $"{installationId}_{identifier}" : null;
|
||||
var expectedDeviceId = haveDeviceId ? $"{installationId}_{deviceId}" : null;
|
||||
|
||||
await sutProvider.Sut.SendAsync(new PushSendRequestModel
|
||||
{
|
||||
Type = PushType.SyncNotificationCreate,
|
||||
UserId = null,
|
||||
OrganizationId = null,
|
||||
InstallationId = installationId.ToString(),
|
||||
Payload = "test-payload",
|
||||
DeviceId = haveDeviceId ? deviceId.ToString() : null,
|
||||
Identifier = haveIdentifier ? identifier.ToString() : null,
|
||||
ClientType = ClientType.All,
|
||||
});
|
||||
|
||||
await sutProvider.GetDependency<IPushNotificationService>().Received(1)
|
||||
.SendPayloadToInstallationAsync(installationId.ToString(), PushType.SyncNotificationCreate, "test-payload",
|
||||
expectedIdentifier, expectedDeviceId, ClientType.All);
|
||||
await sutProvider.GetDependency<IPushNotificationService>().Received(0)
|
||||
.SendPayloadToOrganizationAsync(Arg.Any<string>(), Arg.Any<PushType>(), Arg.Any<object>(),
|
||||
Arg.Any<string>(), Arg.Any<string?>(), Arg.Any<ClientType?>());
|
||||
await sutProvider.GetDependency<IPushNotificationService>().Received(0)
|
||||
.SendPayloadToUserAsync(Arg.Any<string>(), Arg.Any<PushType>(), Arg.Any<object>(), Arg.Any<string>(),
|
||||
Arg.Any<string?>(), Arg.Any<ClientType?>());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task SendAsync_InstallationIdNotMatching_BadRequest(SutProvider<PushController> sutProvider,
|
||||
Guid installationId)
|
||||
{
|
||||
sutProvider.GetDependency<IGlobalSettings>().SelfHosted = false;
|
||||
sutProvider.GetDependency<ICurrentContext>().InstallationId.Returns(installationId);
|
||||
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(() =>
|
||||
sutProvider.Sut.SendAsync(new PushSendRequestModel
|
||||
{
|
||||
Type = PushType.SyncNotificationCreate,
|
||||
UserId = null,
|
||||
OrganizationId = null,
|
||||
InstallationId = Guid.NewGuid().ToString(),
|
||||
Payload = "test-payload",
|
||||
DeviceId = null,
|
||||
Identifier = null,
|
||||
ClientType = ClientType.All,
|
||||
}));
|
||||
|
||||
Assert.Equal("InstallationId does not match current context.", exception.Message);
|
||||
|
||||
await sutProvider.GetDependency<IPushNotificationService>().Received(0)
|
||||
.SendPayloadToInstallationAsync(Arg.Any<string>(), Arg.Any<PushType>(), Arg.Any<object>(),
|
||||
Arg.Any<string>(), Arg.Any<string?>(), Arg.Any<ClientType?>());
|
||||
await sutProvider.GetDependency<IPushNotificationService>().Received(0)
|
||||
.SendPayloadToOrganizationAsync(Arg.Any<string>(), Arg.Any<PushType>(), Arg.Any<object>(),
|
||||
Arg.Any<string>(), Arg.Any<string?>(), Arg.Any<ClientType?>());
|
||||
await sutProvider.GetDependency<IPushNotificationService>().Received(0)
|
||||
.SendPayloadToUserAsync(Arg.Any<string>(), Arg.Any<PushType>(), Arg.Any<object>(), Arg.Any<string>(),
|
||||
Arg.Any<string?>(), Arg.Any<ClientType?>());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData(false, true)]
|
||||
[BitAutoData(false, false)]
|
||||
[BitAutoData(true, true)]
|
||||
public async Task RegisterAsync_InstallationIdNotSetOrSelfHosted_BadRequest(bool haveInstallationId,
|
||||
bool selfHosted,
|
||||
SutProvider<PushController> sutProvider, Guid installationId, Guid userId, Guid identifier, Guid deviceId)
|
||||
{
|
||||
sutProvider.GetDependency<IGlobalSettings>().SelfHosted = selfHosted;
|
||||
if (haveInstallationId)
|
||||
{
|
||||
sutProvider.GetDependency<ICurrentContext>().InstallationId.Returns(installationId);
|
||||
}
|
||||
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(() =>
|
||||
sutProvider.Sut.RegisterAsync(new PushRegistrationRequestModel
|
||||
{
|
||||
DeviceId = deviceId.ToString(),
|
||||
PushToken = "test-push-token",
|
||||
UserId = userId.ToString(),
|
||||
Type = DeviceType.Android,
|
||||
Identifier = identifier.ToString()
|
||||
}));
|
||||
|
||||
Assert.Equal("Not correctly configured for push relays.", exception.Message);
|
||||
|
||||
await sutProvider.GetDependency<IPushRegistrationService>().Received(0)
|
||||
.CreateOrUpdateRegistrationAsync(Arg.Any<string>(), Arg.Any<string>(), Arg.Any<string>(), Arg.Any<string>(),
|
||||
Arg.Any<DeviceType>(), Arg.Any<IEnumerable<string>>(), Arg.Any<string>());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task? RegisterAsync_ValidModel_CreatedOrUpdatedRegistration(SutProvider<PushController> sutProvider,
|
||||
Guid installationId, Guid userId, Guid identifier, Guid deviceId, Guid organizationId)
|
||||
{
|
||||
sutProvider.GetDependency<IGlobalSettings>().SelfHosted = false;
|
||||
sutProvider.GetDependency<ICurrentContext>().InstallationId.Returns(installationId);
|
||||
|
||||
var expectedUserId = $"{installationId}_{userId}";
|
||||
var expectedIdentifier = $"{installationId}_{identifier}";
|
||||
var expectedDeviceId = $"{installationId}_{deviceId}";
|
||||
var expectedOrganizationId = $"{installationId}_{organizationId}";
|
||||
|
||||
await sutProvider.Sut.RegisterAsync(new PushRegistrationRequestModel
|
||||
{
|
||||
DeviceId = deviceId.ToString(),
|
||||
PushToken = "test-push-token",
|
||||
UserId = userId.ToString(),
|
||||
Type = DeviceType.Android,
|
||||
Identifier = identifier.ToString(),
|
||||
OrganizationIds = [organizationId.ToString()],
|
||||
InstallationId = installationId.ToString()
|
||||
});
|
||||
|
||||
await sutProvider.GetDependency<IPushRegistrationService>().Received(1)
|
||||
.CreateOrUpdateRegistrationAsync("test-push-token", expectedDeviceId, expectedUserId,
|
||||
expectedIdentifier, DeviceType.Android, Arg.Do<IEnumerable<string>>(organizationIds =>
|
||||
{
|
||||
var organizationIdsList = organizationIds.ToList();
|
||||
Assert.Contains(expectedOrganizationId, organizationIdsList);
|
||||
Assert.Single(organizationIdsList);
|
||||
}), installationId.ToString());
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,62 @@
|
||||
using System.Reflection;
|
||||
|
||||
namespace Bit.Test.Common.AutoFixture.Attributes;
|
||||
|
||||
public class RepeatingPatternBitAutoDataAttribute : BitAutoDataAttribute
|
||||
{
|
||||
private readonly List<object[]> _repeatingDataList;
|
||||
|
||||
public RepeatingPatternBitAutoDataAttribute(object[] first)
|
||||
{
|
||||
_repeatingDataList = AllValues([first]);
|
||||
}
|
||||
|
||||
public RepeatingPatternBitAutoDataAttribute(object[] first, object[] second)
|
||||
{
|
||||
_repeatingDataList = AllValues([first, second]);
|
||||
}
|
||||
|
||||
public RepeatingPatternBitAutoDataAttribute(object[] first, object[] second, object[] third)
|
||||
{
|
||||
_repeatingDataList = AllValues([first, second, third]);
|
||||
}
|
||||
|
||||
public override IEnumerable<object[]> GetData(MethodInfo testMethod)
|
||||
{
|
||||
foreach (var repeatingData in _repeatingDataList)
|
||||
{
|
||||
var bitData = base.GetData(testMethod).First();
|
||||
for (var i = 0; i < repeatingData.Length; i++)
|
||||
{
|
||||
bitData[i] = repeatingData[i];
|
||||
}
|
||||
|
||||
yield return bitData;
|
||||
}
|
||||
}
|
||||
|
||||
private static List<object[]> AllValues(object[][] parameterToPatternValues)
|
||||
{
|
||||
var result = new List<object[]>();
|
||||
GenerateCombinations(parameterToPatternValues, new object[parameterToPatternValues.Length], 0, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void GenerateCombinations(object[][] parameterToPatternValues, object[] current, int index,
|
||||
List<object[]> result)
|
||||
{
|
||||
if (index == current.Length)
|
||||
{
|
||||
result.Add((object[])current.Clone());
|
||||
return;
|
||||
}
|
||||
|
||||
var patternValues = parameterToPatternValues[index];
|
||||
|
||||
foreach (var value in patternValues)
|
||||
{
|
||||
current[index] = value;
|
||||
GenerateCombinations(parameterToPatternValues, current, index + 1, result);
|
||||
}
|
||||
}
|
||||
}
|
@ -12,19 +12,15 @@ namespace Bit.Core.Test.Models.Api.Request;
|
||||
public class PushSendRequestModelTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(null, null)]
|
||||
[InlineData(null, "")]
|
||||
[InlineData(null, " ")]
|
||||
[InlineData("", null)]
|
||||
[InlineData(" ", null)]
|
||||
[InlineData("", "")]
|
||||
[InlineData(" ", " ")]
|
||||
public void Validate_UserIdOrganizationIdNullOrEmpty_Invalid(string? userId, string? organizationId)
|
||||
[RepeatingPatternBitAutoData([null, "", " "], [null, "", " "], [null, "", " "])]
|
||||
public void Validate_UserIdOrganizationIdInstallationIdNullOrEmpty_Invalid(string? userId, string? organizationId,
|
||||
string? installationId)
|
||||
{
|
||||
var model = new PushSendRequestModel
|
||||
{
|
||||
UserId = userId,
|
||||
OrganizationId = organizationId,
|
||||
InstallationId = installationId,
|
||||
Type = PushType.SyncCiphers,
|
||||
Payload = "test"
|
||||
};
|
||||
@ -32,7 +28,65 @@ public class PushSendRequestModelTests
|
||||
var results = Validate(model);
|
||||
|
||||
Assert.Single(results);
|
||||
Assert.Contains(results, result => result.ErrorMessage == "UserId or OrganizationId is required.");
|
||||
Assert.Contains(results,
|
||||
result => result.ErrorMessage == "UserId or OrganizationId or InstallationId is required.");
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[RepeatingPatternBitAutoData([null, "", " "], [null, "", " "])]
|
||||
public void Validate_UserIdProvidedOrganizationIdInstallationIdNullOrEmpty_Valid(string? organizationId,
|
||||
string? installationId)
|
||||
{
|
||||
var model = new PushSendRequestModel
|
||||
{
|
||||
UserId = Guid.NewGuid().ToString(),
|
||||
OrganizationId = organizationId,
|
||||
InstallationId = installationId,
|
||||
Type = PushType.SyncCiphers,
|
||||
Payload = "test"
|
||||
};
|
||||
|
||||
var results = Validate(model);
|
||||
|
||||
Assert.Empty(results);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[RepeatingPatternBitAutoData([null, "", " "], [null, "", " "])]
|
||||
public void Validate_OrganizationIdProvidedUserIdInstallationIdNullOrEmpty_Valid(string? userId,
|
||||
string? installationId)
|
||||
{
|
||||
var model = new PushSendRequestModel
|
||||
{
|
||||
UserId = userId,
|
||||
OrganizationId = Guid.NewGuid().ToString(),
|
||||
InstallationId = installationId,
|
||||
Type = PushType.SyncCiphers,
|
||||
Payload = "test"
|
||||
};
|
||||
|
||||
var results = Validate(model);
|
||||
|
||||
Assert.Empty(results);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[RepeatingPatternBitAutoData([null, "", " "], [null, "", " "])]
|
||||
public void Validate_InstallationIdProvidedUserIdOrganizationIdNullOrEmpty_Valid(string? userId,
|
||||
string? organizationId)
|
||||
{
|
||||
var model = new PushSendRequestModel
|
||||
{
|
||||
UserId = userId,
|
||||
OrganizationId = organizationId,
|
||||
InstallationId = Guid.NewGuid().ToString(),
|
||||
Type = PushType.SyncCiphers,
|
||||
Payload = "test"
|
||||
};
|
||||
|
||||
var results = Validate(model);
|
||||
|
||||
Assert.Empty(results);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
@ -6,6 +6,7 @@ using Bit.Core.Models.Data;
|
||||
using Bit.Core.NotificationCenter.Entities;
|
||||
using Bit.Core.NotificationHub;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.Settings;
|
||||
using Bit.Core.Test.NotificationCenter.AutoFixture;
|
||||
using Bit.Test.Common.AutoFixture;
|
||||
using Bit.Test.Common.AutoFixture.Attributes;
|
||||
@ -21,9 +22,11 @@ public class NotificationHubPushNotificationServiceTests
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
[NotificationCustomize]
|
||||
public async Task PushSyncNotificationCreateAsync_Global_NotSent(
|
||||
public async Task PushSyncNotificationCreateAsync_GlobalInstallationIdDefault_NotSent(
|
||||
SutProvider<NotificationHubPushNotificationService> sutProvider, Notification notification)
|
||||
{
|
||||
sutProvider.GetDependency<IGlobalSettings>().Installation.Id = default;
|
||||
|
||||
await sutProvider.Sut.PushSyncNotificationCreateAsync(notification);
|
||||
|
||||
await sutProvider.GetDependency<INotificationHubPool>()
|
||||
@ -36,6 +39,53 @@ public class NotificationHubPushNotificationServiceTests
|
||||
.UpsertAsync(Arg.Any<InstallationDeviceEntity>());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
[NotificationCustomize]
|
||||
public async Task PushSyncNotificationCreateAsync_GlobalInstallationIdSetClientTypeAll_SentToInstallationId(
|
||||
SutProvider<NotificationHubPushNotificationService> sutProvider, Notification notification, Guid installationId)
|
||||
{
|
||||
sutProvider.GetDependency<IGlobalSettings>().Installation.Id = installationId;
|
||||
notification.ClientType = ClientType.All;
|
||||
var expectedSyncNotification = ToSyncNotificationPushNotification(notification, null);
|
||||
expectedSyncNotification.InstallationId = installationId;
|
||||
|
||||
await sutProvider.Sut.PushSyncNotificationCreateAsync(notification);
|
||||
|
||||
await AssertSendTemplateNotificationAsync(sutProvider, PushType.SyncNotificationCreate,
|
||||
expectedSyncNotification,
|
||||
$"(template:payload && installationId:{installationId})");
|
||||
await sutProvider.GetDependency<IInstallationDeviceRepository>()
|
||||
.Received(0)
|
||||
.UpsertAsync(Arg.Any<InstallationDeviceEntity>());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData(ClientType.Browser)]
|
||||
[BitAutoData(ClientType.Desktop)]
|
||||
[BitAutoData(ClientType.Web)]
|
||||
[BitAutoData(ClientType.Mobile)]
|
||||
[NotificationCustomize]
|
||||
public async Task
|
||||
PushSyncNotificationCreateAsync_GlobalInstallationIdSetClientTypeNotAll_SentToInstallationIdAndClientType(
|
||||
ClientType clientType, SutProvider<NotificationHubPushNotificationService> sutProvider,
|
||||
Notification notification, Guid installationId)
|
||||
{
|
||||
sutProvider.GetDependency<IGlobalSettings>().Installation.Id = installationId;
|
||||
notification.ClientType = clientType;
|
||||
var expectedSyncNotification = ToSyncNotificationPushNotification(notification, null);
|
||||
expectedSyncNotification.InstallationId = installationId;
|
||||
|
||||
await sutProvider.Sut.PushSyncNotificationCreateAsync(notification);
|
||||
|
||||
await AssertSendTemplateNotificationAsync(sutProvider, PushType.SyncNotificationCreate,
|
||||
expectedSyncNotification,
|
||||
$"(template:payload && installationId:{installationId} && clientType:{clientType})");
|
||||
await sutProvider.GetDependency<IInstallationDeviceRepository>()
|
||||
.Received(0)
|
||||
.UpsertAsync(Arg.Any<InstallationDeviceEntity>());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData(false)]
|
||||
[BitAutoData(true)]
|
||||
@ -158,10 +208,12 @@ public class NotificationHubPushNotificationServiceTests
|
||||
[BitAutoData(false)]
|
||||
[BitAutoData(true)]
|
||||
[NotificationCustomize]
|
||||
public async Task PushSyncNotificationUpdateAsync_Global_NotSent(bool notificationStatusNull,
|
||||
public async Task PushSyncNotificationUpdateAsync_GlobalInstallationIdDefault_NotSent(bool notificationStatusNull,
|
||||
SutProvider<NotificationHubPushNotificationService> sutProvider, Notification notification,
|
||||
NotificationStatus notificationStatus)
|
||||
{
|
||||
sutProvider.GetDependency<IGlobalSettings>().Installation.Id = default;
|
||||
|
||||
await sutProvider.Sut.PushSyncNotificationUpdateAsync(notification,
|
||||
notificationStatusNull ? null : notificationStatus);
|
||||
|
||||
@ -176,10 +228,59 @@ public class NotificationHubPushNotificationServiceTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData(false, false)]
|
||||
[BitAutoData(false, true)]
|
||||
[BitAutoData(true, false)]
|
||||
[BitAutoData(true, true)]
|
||||
[BitAutoData(false)]
|
||||
[BitAutoData(true)]
|
||||
[NotificationCustomize]
|
||||
public async Task PushSyncNotificationUpdateAsync_GlobalInstallationIdSetClientTypeAll_SentToInstallationId(
|
||||
bool notificationStatusNull, SutProvider<NotificationHubPushNotificationService> sutProvider,
|
||||
Notification notification, NotificationStatus notificationStatus, Guid installationId)
|
||||
{
|
||||
sutProvider.GetDependency<IGlobalSettings>().Installation.Id = installationId;
|
||||
notification.ClientType = ClientType.All;
|
||||
|
||||
var expectedNotificationStatus = notificationStatusNull ? null : notificationStatus;
|
||||
var expectedSyncNotification = ToSyncNotificationPushNotification(notification, expectedNotificationStatus);
|
||||
expectedSyncNotification.InstallationId = installationId;
|
||||
|
||||
await sutProvider.Sut.PushSyncNotificationUpdateAsync(notification, expectedNotificationStatus);
|
||||
|
||||
await AssertSendTemplateNotificationAsync(sutProvider, PushType.SyncNotificationUpdate,
|
||||
expectedSyncNotification,
|
||||
$"(template:payload && installationId:{installationId})");
|
||||
await sutProvider.GetDependency<IInstallationDeviceRepository>()
|
||||
.Received(0)
|
||||
.UpsertAsync(Arg.Any<InstallationDeviceEntity>());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[RepeatingPatternBitAutoData([false, true],
|
||||
[ClientType.Browser, ClientType.Desktop, ClientType.Web, ClientType.Mobile])]
|
||||
[NotificationCustomize]
|
||||
public async Task
|
||||
PushSyncNotificationUpdateAsync_GlobalInstallationIdSetClientTypeNotAll_SentToInstallationIdAndClientType(
|
||||
bool notificationStatusNull, ClientType clientType,
|
||||
SutProvider<NotificationHubPushNotificationService> sutProvider,
|
||||
Notification notification, NotificationStatus notificationStatus, Guid installationId)
|
||||
{
|
||||
sutProvider.GetDependency<IGlobalSettings>().Installation.Id = installationId;
|
||||
notification.ClientType = clientType;
|
||||
|
||||
var expectedNotificationStatus = notificationStatusNull ? null : notificationStatus;
|
||||
var expectedSyncNotification = ToSyncNotificationPushNotification(notification, expectedNotificationStatus);
|
||||
expectedSyncNotification.InstallationId = installationId;
|
||||
|
||||
await sutProvider.Sut.PushSyncNotificationUpdateAsync(notification, expectedNotificationStatus);
|
||||
|
||||
await AssertSendTemplateNotificationAsync(sutProvider, PushType.SyncNotificationUpdate,
|
||||
expectedSyncNotification,
|
||||
$"(template:payload && installationId:{installationId} && clientType:{clientType})");
|
||||
await sutProvider.GetDependency<IInstallationDeviceRepository>()
|
||||
.Received(0)
|
||||
.UpsertAsync(Arg.Any<InstallationDeviceEntity>());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[RepeatingPatternBitAutoData([false, true], [false, true])]
|
||||
[NotificationCustomize(false)]
|
||||
public async Task PushSyncNotificationUpdateAsync_UserIdProvidedClientTypeAll_SentToUser(
|
||||
bool organizationIdNull, bool notificationStatusNull,
|
||||
@ -206,14 +307,8 @@ public class NotificationHubPushNotificationServiceTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData(false, ClientType.Browser)]
|
||||
[BitAutoData(false, ClientType.Desktop)]
|
||||
[BitAutoData(false, ClientType.Web)]
|
||||
[BitAutoData(false, ClientType.Mobile)]
|
||||
[BitAutoData(true, ClientType.Browser)]
|
||||
[BitAutoData(true, ClientType.Desktop)]
|
||||
[BitAutoData(true, ClientType.Web)]
|
||||
[BitAutoData(true, ClientType.Mobile)]
|
||||
[RepeatingPatternBitAutoData([false, true],
|
||||
[ClientType.Browser, ClientType.Desktop, ClientType.Web, ClientType.Mobile])]
|
||||
[NotificationCustomize(false)]
|
||||
public async Task PushSyncNotificationUpdateAsync_UserIdProvidedOrganizationIdNullClientTypeNotAll_SentToUser(
|
||||
bool notificationStatusNull, ClientType clientType,
|
||||
@ -236,14 +331,8 @@ public class NotificationHubPushNotificationServiceTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData(false, ClientType.Browser)]
|
||||
[BitAutoData(false, ClientType.Desktop)]
|
||||
[BitAutoData(false, ClientType.Web)]
|
||||
[BitAutoData(false, ClientType.Mobile)]
|
||||
[BitAutoData(true, ClientType.Browser)]
|
||||
[BitAutoData(true, ClientType.Desktop)]
|
||||
[BitAutoData(true, ClientType.Web)]
|
||||
[BitAutoData(true, ClientType.Mobile)]
|
||||
[RepeatingPatternBitAutoData([false, true],
|
||||
[ClientType.Browser, ClientType.Desktop, ClientType.Web, ClientType.Mobile])]
|
||||
[NotificationCustomize(false)]
|
||||
public async Task PushSyncNotificationUpdateAsync_UserIdProvidedOrganizationIdProvidedClientTypeNotAll_SentToUser(
|
||||
bool notificationStatusNull, ClientType clientType,
|
||||
@ -288,14 +377,8 @@ public class NotificationHubPushNotificationServiceTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData(false, ClientType.Browser)]
|
||||
[BitAutoData(false, ClientType.Desktop)]
|
||||
[BitAutoData(false, ClientType.Web)]
|
||||
[BitAutoData(false, ClientType.Mobile)]
|
||||
[BitAutoData(true, ClientType.Browser)]
|
||||
[BitAutoData(true, ClientType.Desktop)]
|
||||
[BitAutoData(true, ClientType.Web)]
|
||||
[BitAutoData(true, ClientType.Mobile)]
|
||||
[RepeatingPatternBitAutoData([false, true],
|
||||
[ClientType.Browser, ClientType.Desktop, ClientType.Web, ClientType.Mobile])]
|
||||
[NotificationCustomize(false)]
|
||||
public async Task
|
||||
PushSyncNotificationUpdateAsync_UserIdNullOrganizationIdProvidedClientTypeNotAll_SentToOrganization(
|
||||
@ -390,6 +473,42 @@ public class NotificationHubPushNotificationServiceTests
|
||||
.UpsertAsync(Arg.Any<InstallationDeviceEntity>());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData([null])]
|
||||
[BitAutoData(ClientType.All)]
|
||||
public async Task SendPayloadToInstallationAsync_ClientTypeNullOrAll_SentToInstallation(ClientType? clientType,
|
||||
SutProvider<NotificationHubPushNotificationService> sutProvider, Guid installationId, PushType pushType,
|
||||
string payload, string identifier)
|
||||
{
|
||||
await sutProvider.Sut.SendPayloadToInstallationAsync(installationId.ToString(), pushType, payload, identifier,
|
||||
null, clientType);
|
||||
|
||||
await AssertSendTemplateNotificationAsync(sutProvider, pushType, payload,
|
||||
$"(template:payload && installationId:{installationId} && !deviceIdentifier:{identifier})");
|
||||
await sutProvider.GetDependency<IInstallationDeviceRepository>()
|
||||
.Received(0)
|
||||
.UpsertAsync(Arg.Any<InstallationDeviceEntity>());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData(ClientType.Browser)]
|
||||
[BitAutoData(ClientType.Desktop)]
|
||||
[BitAutoData(ClientType.Mobile)]
|
||||
[BitAutoData(ClientType.Web)]
|
||||
public async Task SendPayloadToInstallationAsync_ClientTypeExplicit_SentToInstallationAndClientType(
|
||||
ClientType clientType, SutProvider<NotificationHubPushNotificationService> sutProvider, Guid installationId,
|
||||
PushType pushType, string payload, string identifier)
|
||||
{
|
||||
await sutProvider.Sut.SendPayloadToInstallationAsync(installationId.ToString(), pushType, payload, identifier,
|
||||
null, clientType);
|
||||
|
||||
await AssertSendTemplateNotificationAsync(sutProvider, pushType, payload,
|
||||
$"(template:payload && installationId:{installationId} && !deviceIdentifier:{identifier} && clientType:{clientType})");
|
||||
await sutProvider.GetDependency<IInstallationDeviceRepository>()
|
||||
.Received(0)
|
||||
.UpsertAsync(Arg.Any<InstallationDeviceEntity>());
|
||||
}
|
||||
|
||||
private static SyncNotificationPushNotification ToSyncNotificationPushNotification(Notification notification,
|
||||
NotificationStatus? notificationStatus) =>
|
||||
new()
|
||||
|
@ -14,15 +14,13 @@ namespace Bit.Core.Test.NotificationHub;
|
||||
public class NotificationHubPushRegistrationServiceTests
|
||||
{
|
||||
[Theory]
|
||||
[BitAutoData([null])]
|
||||
[BitAutoData("")]
|
||||
[BitAutoData(" ")]
|
||||
[RepeatingPatternBitAutoData([null, "", " "])]
|
||||
public async Task CreateOrUpdateRegistrationAsync_PushTokenNullOrEmpty_InstallationNotCreated(string? pushToken,
|
||||
SutProvider<NotificationHubPushRegistrationService> sutProvider, Guid deviceId, Guid userId, Guid identifier,
|
||||
Guid organizationId)
|
||||
Guid organizationId, Guid installationId)
|
||||
{
|
||||
await sutProvider.Sut.CreateOrUpdateRegistrationAsync(pushToken, deviceId.ToString(), userId.ToString(),
|
||||
identifier.ToString(), DeviceType.Android, [organizationId.ToString()]);
|
||||
identifier.ToString(), DeviceType.Android, [organizationId.ToString()], installationId.ToString());
|
||||
|
||||
sutProvider.GetDependency<INotificationHubPool>()
|
||||
.Received(0)
|
||||
@ -30,13 +28,11 @@ public class NotificationHubPushRegistrationServiceTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData(false, false)]
|
||||
[BitAutoData(false, true)]
|
||||
[BitAutoData(true, false)]
|
||||
[BitAutoData(true, true)]
|
||||
[RepeatingPatternBitAutoData([false, true], [false, true], [false, true])]
|
||||
public async Task CreateOrUpdateRegistrationAsync_DeviceTypeAndroid_InstallationCreated(bool identifierNull,
|
||||
bool partOfOrganizationId, SutProvider<NotificationHubPushRegistrationService> sutProvider, Guid deviceId,
|
||||
Guid userId, Guid? identifier, Guid organizationId)
|
||||
bool partOfOrganizationId, bool installationIdNull,
|
||||
SutProvider<NotificationHubPushRegistrationService> sutProvider, Guid deviceId, Guid userId, Guid? identifier,
|
||||
Guid organizationId, Guid installationId)
|
||||
{
|
||||
var notificationHubClient = Substitute.For<INotificationHubClient>();
|
||||
sutProvider.GetDependency<INotificationHubPool>().ClientFor(Arg.Any<Guid>()).Returns(notificationHubClient);
|
||||
@ -45,7 +41,8 @@ public class NotificationHubPushRegistrationServiceTests
|
||||
|
||||
await sutProvider.Sut.CreateOrUpdateRegistrationAsync(pushToken, deviceId.ToString(), userId.ToString(),
|
||||
identifierNull ? null : identifier.ToString(), DeviceType.Android,
|
||||
partOfOrganizationId ? [organizationId.ToString()] : []);
|
||||
partOfOrganizationId ? [organizationId.ToString()] : [],
|
||||
installationIdNull ? null : installationId.ToString());
|
||||
|
||||
sutProvider.GetDependency<INotificationHubPool>()
|
||||
.Received(1)
|
||||
@ -60,6 +57,7 @@ public class NotificationHubPushRegistrationServiceTests
|
||||
installation.Tags.Contains("clientType:Mobile") &&
|
||||
(identifierNull || installation.Tags.Contains($"deviceIdentifier:{identifier}")) &&
|
||||
(!partOfOrganizationId || installation.Tags.Contains($"organizationId:{organizationId}")) &&
|
||||
(installationIdNull || installation.Tags.Contains($"installationId:{installationId}")) &&
|
||||
installation.Templates.Count == 3));
|
||||
await notificationHubClient
|
||||
.Received(1)
|
||||
@ -73,6 +71,7 @@ public class NotificationHubPushRegistrationServiceTests
|
||||
"clientType:Mobile",
|
||||
identifierNull ? null : $"template:payload_deviceIdentifier:{identifier}",
|
||||
partOfOrganizationId ? $"organizationId:{organizationId}" : null,
|
||||
installationIdNull ? null : $"installationId:{installationId}",
|
||||
})));
|
||||
await notificationHubClient
|
||||
.Received(1)
|
||||
@ -86,6 +85,7 @@ public class NotificationHubPushRegistrationServiceTests
|
||||
"clientType:Mobile",
|
||||
identifierNull ? null : $"template:message_deviceIdentifier:{identifier}",
|
||||
partOfOrganizationId ? $"organizationId:{organizationId}" : null,
|
||||
installationIdNull ? null : $"installationId:{installationId}",
|
||||
})));
|
||||
await notificationHubClient
|
||||
.Received(1)
|
||||
@ -99,17 +99,16 @@ public class NotificationHubPushRegistrationServiceTests
|
||||
"clientType:Mobile",
|
||||
identifierNull ? null : $"template:badgeMessage_deviceIdentifier:{identifier}",
|
||||
partOfOrganizationId ? $"organizationId:{organizationId}" : null,
|
||||
installationIdNull ? null : $"installationId:{installationId}",
|
||||
})));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData(false, false)]
|
||||
[BitAutoData(false, true)]
|
||||
[BitAutoData(true, false)]
|
||||
[BitAutoData(true, true)]
|
||||
[RepeatingPatternBitAutoData([false, true], [false, true], [false, true])]
|
||||
public async Task CreateOrUpdateRegistrationAsync_DeviceTypeIOS_InstallationCreated(bool identifierNull,
|
||||
bool partOfOrganizationId, SutProvider<NotificationHubPushRegistrationService> sutProvider, Guid deviceId,
|
||||
Guid userId, Guid identifier, Guid organizationId)
|
||||
bool partOfOrganizationId, bool installationIdNull,
|
||||
SutProvider<NotificationHubPushRegistrationService> sutProvider, Guid deviceId, Guid userId, Guid identifier,
|
||||
Guid organizationId, Guid installationId)
|
||||
{
|
||||
var notificationHubClient = Substitute.For<INotificationHubClient>();
|
||||
sutProvider.GetDependency<INotificationHubPool>().ClientFor(Arg.Any<Guid>()).Returns(notificationHubClient);
|
||||
@ -118,7 +117,8 @@ public class NotificationHubPushRegistrationServiceTests
|
||||
|
||||
await sutProvider.Sut.CreateOrUpdateRegistrationAsync(pushToken, deviceId.ToString(), userId.ToString(),
|
||||
identifierNull ? null : identifier.ToString(), DeviceType.iOS,
|
||||
partOfOrganizationId ? [organizationId.ToString()] : []);
|
||||
partOfOrganizationId ? [organizationId.ToString()] : [],
|
||||
installationIdNull ? null : installationId.ToString());
|
||||
|
||||
sutProvider.GetDependency<INotificationHubPool>()
|
||||
.Received(1)
|
||||
@ -133,6 +133,7 @@ public class NotificationHubPushRegistrationServiceTests
|
||||
installation.Tags.Contains("clientType:Mobile") &&
|
||||
(identifierNull || installation.Tags.Contains($"deviceIdentifier:{identifier}")) &&
|
||||
(!partOfOrganizationId || installation.Tags.Contains($"organizationId:{organizationId}")) &&
|
||||
(installationIdNull || installation.Tags.Contains($"installationId:{installationId}")) &&
|
||||
installation.Templates.Count == 3));
|
||||
await notificationHubClient
|
||||
.Received(1)
|
||||
@ -146,6 +147,7 @@ public class NotificationHubPushRegistrationServiceTests
|
||||
"clientType:Mobile",
|
||||
identifierNull ? null : $"template:payload_deviceIdentifier:{identifier}",
|
||||
partOfOrganizationId ? $"organizationId:{organizationId}" : null,
|
||||
installationIdNull ? null : $"installationId:{installationId}",
|
||||
})));
|
||||
await notificationHubClient
|
||||
.Received(1)
|
||||
@ -159,6 +161,7 @@ public class NotificationHubPushRegistrationServiceTests
|
||||
"clientType:Mobile",
|
||||
identifierNull ? null : $"template:message_deviceIdentifier:{identifier}",
|
||||
partOfOrganizationId ? $"organizationId:{organizationId}" : null,
|
||||
installationIdNull ? null : $"installationId:{installationId}",
|
||||
})));
|
||||
await notificationHubClient
|
||||
.Received(1)
|
||||
@ -172,17 +175,16 @@ public class NotificationHubPushRegistrationServiceTests
|
||||
"clientType:Mobile",
|
||||
identifierNull ? null : $"template:badgeMessage_deviceIdentifier:{identifier}",
|
||||
partOfOrganizationId ? $"organizationId:{organizationId}" : null,
|
||||
installationIdNull ? null : $"installationId:{installationId}",
|
||||
})));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData(false, false)]
|
||||
[BitAutoData(false, true)]
|
||||
[BitAutoData(true, false)]
|
||||
[BitAutoData(true, true)]
|
||||
[RepeatingPatternBitAutoData([false, true], [false, true], [false, true])]
|
||||
public async Task CreateOrUpdateRegistrationAsync_DeviceTypeAndroidAmazon_InstallationCreated(bool identifierNull,
|
||||
bool partOfOrganizationId, SutProvider<NotificationHubPushRegistrationService> sutProvider, Guid deviceId,
|
||||
Guid userId, Guid identifier, Guid organizationId)
|
||||
bool partOfOrganizationId, bool installationIdNull,
|
||||
SutProvider<NotificationHubPushRegistrationService> sutProvider, Guid deviceId,
|
||||
Guid userId, Guid identifier, Guid organizationId, Guid installationId)
|
||||
{
|
||||
var notificationHubClient = Substitute.For<INotificationHubClient>();
|
||||
sutProvider.GetDependency<INotificationHubPool>().ClientFor(Arg.Any<Guid>()).Returns(notificationHubClient);
|
||||
@ -191,7 +193,8 @@ public class NotificationHubPushRegistrationServiceTests
|
||||
|
||||
await sutProvider.Sut.CreateOrUpdateRegistrationAsync(pushToken, deviceId.ToString(), userId.ToString(),
|
||||
identifierNull ? null : identifier.ToString(), DeviceType.AndroidAmazon,
|
||||
partOfOrganizationId ? [organizationId.ToString()] : []);
|
||||
partOfOrganizationId ? [organizationId.ToString()] : [],
|
||||
installationIdNull ? null : installationId.ToString());
|
||||
|
||||
sutProvider.GetDependency<INotificationHubPool>()
|
||||
.Received(1)
|
||||
@ -206,6 +209,7 @@ public class NotificationHubPushRegistrationServiceTests
|
||||
installation.Tags.Contains("clientType:Mobile") &&
|
||||
(identifierNull || installation.Tags.Contains($"deviceIdentifier:{identifier}")) &&
|
||||
(!partOfOrganizationId || installation.Tags.Contains($"organizationId:{organizationId}")) &&
|
||||
(installationIdNull || installation.Tags.Contains($"installationId:{installationId}")) &&
|
||||
installation.Templates.Count == 3));
|
||||
await notificationHubClient
|
||||
.Received(1)
|
||||
@ -219,6 +223,7 @@ public class NotificationHubPushRegistrationServiceTests
|
||||
"clientType:Mobile",
|
||||
identifierNull ? null : $"template:payload_deviceIdentifier:{identifier}",
|
||||
partOfOrganizationId ? $"organizationId:{organizationId}" : null,
|
||||
installationIdNull ? null : $"installationId:{installationId}",
|
||||
})));
|
||||
await notificationHubClient
|
||||
.Received(1)
|
||||
@ -232,6 +237,7 @@ public class NotificationHubPushRegistrationServiceTests
|
||||
"clientType:Mobile",
|
||||
identifierNull ? null : $"template:message_deviceIdentifier:{identifier}",
|
||||
partOfOrganizationId ? $"organizationId:{organizationId}" : null,
|
||||
installationIdNull ? null : $"installationId:{installationId}",
|
||||
})));
|
||||
await notificationHubClient
|
||||
.Received(1)
|
||||
@ -245,6 +251,7 @@ public class NotificationHubPushRegistrationServiceTests
|
||||
"clientType:Mobile",
|
||||
identifierNull ? null : $"template:badgeMessage_deviceIdentifier:{identifier}",
|
||||
partOfOrganizationId ? $"organizationId:{organizationId}" : null,
|
||||
installationIdNull ? null : $"installationId:{installationId}",
|
||||
})));
|
||||
}
|
||||
|
||||
@ -254,7 +261,7 @@ public class NotificationHubPushRegistrationServiceTests
|
||||
[BitAutoData(DeviceType.MacOsDesktop)]
|
||||
public async Task CreateOrUpdateRegistrationAsync_DeviceTypeNotMobile_InstallationCreated(DeviceType deviceType,
|
||||
SutProvider<NotificationHubPushRegistrationService> sutProvider, Guid deviceId, Guid userId, Guid identifier,
|
||||
Guid organizationId)
|
||||
Guid organizationId, Guid installationId)
|
||||
{
|
||||
var notificationHubClient = Substitute.For<INotificationHubClient>();
|
||||
sutProvider.GetDependency<INotificationHubPool>().ClientFor(Arg.Any<Guid>()).Returns(notificationHubClient);
|
||||
@ -262,7 +269,7 @@ public class NotificationHubPushRegistrationServiceTests
|
||||
var pushToken = "test push token";
|
||||
|
||||
await sutProvider.Sut.CreateOrUpdateRegistrationAsync(pushToken, deviceId.ToString(), userId.ToString(),
|
||||
identifier.ToString(), deviceType, [organizationId.ToString()]);
|
||||
identifier.ToString(), deviceType, [organizationId.ToString()], installationId.ToString());
|
||||
|
||||
sutProvider.GetDependency<INotificationHubPool>()
|
||||
.Received(1)
|
||||
@ -276,6 +283,7 @@ public class NotificationHubPushRegistrationServiceTests
|
||||
installation.Tags.Contains($"clientType:{DeviceTypes.ToClientType(deviceType)}") &&
|
||||
installation.Tags.Contains($"deviceIdentifier:{identifier}") &&
|
||||
installation.Tags.Contains($"organizationId:{organizationId}") &&
|
||||
installation.Tags.Contains($"installationId:{installationId}") &&
|
||||
installation.Templates.Count == 0));
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@ using Bit.Core.Enums;
|
||||
using Bit.Core.Models;
|
||||
using Bit.Core.NotificationCenter.Entities;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Settings;
|
||||
using Bit.Core.Test.AutoFixture;
|
||||
using Bit.Core.Test.AutoFixture.CurrentContextFixtures;
|
||||
using Bit.Core.Test.NotificationCenter.AutoFixture;
|
||||
@ -25,19 +26,43 @@ public class AzureQueuePushNotificationServiceTests
|
||||
[BitAutoData]
|
||||
[NotificationCustomize]
|
||||
[CurrentContextCustomize]
|
||||
public async Task PushSyncNotificationCreateAsync_Notification_Sent(
|
||||
public async Task PushSyncNotificationCreateAsync_NotificationGlobal_Sent(
|
||||
SutProvider<AzureQueuePushNotificationService> sutProvider, Notification notification, Guid deviceIdentifier,
|
||||
ICurrentContext currentContext)
|
||||
ICurrentContext currentContext, Guid installationId)
|
||||
{
|
||||
currentContext.DeviceIdentifier.Returns(deviceIdentifier.ToString());
|
||||
sutProvider.GetDependency<IHttpContextAccessor>().HttpContext!.RequestServices
|
||||
.GetService(Arg.Any<Type>()).Returns(currentContext);
|
||||
sutProvider.GetDependency<IGlobalSettings>().Installation.Id = installationId;
|
||||
|
||||
await sutProvider.Sut.PushSyncNotificationCreateAsync(notification);
|
||||
|
||||
await sutProvider.GetDependency<QueueClient>().Received(1)
|
||||
.SendMessageAsync(Arg.Is<string>(message =>
|
||||
MatchMessage(PushType.SyncNotificationCreate, message, new SyncNotificationEquals(notification, null),
|
||||
MatchMessage(PushType.SyncNotificationCreate, message,
|
||||
new SyncNotificationEquals(notification, null, installationId),
|
||||
deviceIdentifier.ToString())));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
[NotificationCustomize(false)]
|
||||
[CurrentContextCustomize]
|
||||
public async Task PushSyncNotificationCreateAsync_NotificationNotGlobal_Sent(
|
||||
SutProvider<AzureQueuePushNotificationService> sutProvider, Notification notification, Guid deviceIdentifier,
|
||||
ICurrentContext currentContext, Guid installationId)
|
||||
{
|
||||
currentContext.DeviceIdentifier.Returns(deviceIdentifier.ToString());
|
||||
sutProvider.GetDependency<IHttpContextAccessor>().HttpContext!.RequestServices
|
||||
.GetService(Arg.Any<Type>()).Returns(currentContext);
|
||||
sutProvider.GetDependency<IGlobalSettings>().Installation.Id = installationId;
|
||||
|
||||
await sutProvider.Sut.PushSyncNotificationCreateAsync(notification);
|
||||
|
||||
await sutProvider.GetDependency<QueueClient>().Received(1)
|
||||
.SendMessageAsync(Arg.Is<string>(message =>
|
||||
MatchMessage(PushType.SyncNotificationCreate, message,
|
||||
new SyncNotificationEquals(notification, null, null),
|
||||
deviceIdentifier.ToString())));
|
||||
}
|
||||
|
||||
@ -47,21 +72,47 @@ public class AzureQueuePushNotificationServiceTests
|
||||
[NotificationCustomize]
|
||||
[NotificationStatusCustomize]
|
||||
[CurrentContextCustomize]
|
||||
public async Task PushSyncNotificationUpdateAsync_Notification_Sent(bool notificationStatusNull,
|
||||
public async Task PushSyncNotificationUpdateAsync_NotificationGlobal_Sent(bool notificationStatusNull,
|
||||
SutProvider<AzureQueuePushNotificationService> sutProvider, Notification notification, Guid deviceIdentifier,
|
||||
ICurrentContext currentContext, NotificationStatus notificationStatus)
|
||||
ICurrentContext currentContext, NotificationStatus notificationStatus, Guid installationId)
|
||||
{
|
||||
var expectedNotificationStatus = notificationStatusNull ? null : notificationStatus;
|
||||
currentContext.DeviceIdentifier.Returns(deviceIdentifier.ToString());
|
||||
sutProvider.GetDependency<IHttpContextAccessor>().HttpContext!.RequestServices
|
||||
.GetService(Arg.Any<Type>()).Returns(currentContext);
|
||||
sutProvider.GetDependency<IGlobalSettings>().Installation.Id = installationId;
|
||||
|
||||
await sutProvider.Sut.PushSyncNotificationUpdateAsync(notification, expectedNotificationStatus);
|
||||
|
||||
await sutProvider.GetDependency<QueueClient>().Received(1)
|
||||
.SendMessageAsync(Arg.Is<string>(message =>
|
||||
MatchMessage(PushType.SyncNotificationUpdate, message,
|
||||
new SyncNotificationEquals(notification, expectedNotificationStatus),
|
||||
new SyncNotificationEquals(notification, expectedNotificationStatus, installationId),
|
||||
deviceIdentifier.ToString())));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData(false)]
|
||||
[BitAutoData(true)]
|
||||
[NotificationCustomize(false)]
|
||||
[NotificationStatusCustomize]
|
||||
[CurrentContextCustomize]
|
||||
public async Task PushSyncNotificationUpdateAsync_NotificationNotGlobal_Sent(bool notificationStatusNull,
|
||||
SutProvider<AzureQueuePushNotificationService> sutProvider, Notification notification, Guid deviceIdentifier,
|
||||
ICurrentContext currentContext, NotificationStatus notificationStatus, Guid installationId)
|
||||
{
|
||||
var expectedNotificationStatus = notificationStatusNull ? null : notificationStatus;
|
||||
currentContext.DeviceIdentifier.Returns(deviceIdentifier.ToString());
|
||||
sutProvider.GetDependency<IHttpContextAccessor>().HttpContext!.RequestServices
|
||||
.GetService(Arg.Any<Type>()).Returns(currentContext);
|
||||
sutProvider.GetDependency<IGlobalSettings>().Installation.Id = installationId;
|
||||
|
||||
await sutProvider.Sut.PushSyncNotificationUpdateAsync(notification, expectedNotificationStatus);
|
||||
|
||||
await sutProvider.GetDependency<QueueClient>().Received(1)
|
||||
.SendMessageAsync(Arg.Is<string>(message =>
|
||||
MatchMessage(PushType.SyncNotificationUpdate, message,
|
||||
new SyncNotificationEquals(notification, expectedNotificationStatus, null),
|
||||
deviceIdentifier.ToString())));
|
||||
}
|
||||
|
||||
@ -76,7 +127,10 @@ public class AzureQueuePushNotificationServiceTests
|
||||
pushNotificationData.ContextId == contextId;
|
||||
}
|
||||
|
||||
private class SyncNotificationEquals(Notification notification, NotificationStatus? notificationStatus)
|
||||
private class SyncNotificationEquals(
|
||||
Notification notification,
|
||||
NotificationStatus? notificationStatus,
|
||||
Guid? installationId)
|
||||
: IEquatable<SyncNotificationPushNotification>
|
||||
{
|
||||
public bool Equals(SyncNotificationPushNotification? other)
|
||||
@ -85,6 +139,7 @@ public class AzureQueuePushNotificationServiceTests
|
||||
other.Id == notification.Id &&
|
||||
other.UserId == notification.UserId &&
|
||||
other.OrganizationId == notification.OrganizationId &&
|
||||
other.InstallationId == installationId &&
|
||||
other.ClientType == notification.ClientType &&
|
||||
other.RevisionDate == notification.RevisionDate &&
|
||||
other.ReadDate == notificationStatus?.ReadDate &&
|
||||
|
@ -6,6 +6,7 @@ using Bit.Core.Exceptions;
|
||||
using Bit.Core.Models.Data.Organizations.OrganizationUsers;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Settings;
|
||||
using Bit.Test.Common.AutoFixture;
|
||||
using Bit.Test.Common.AutoFixture.Attributes;
|
||||
using NSubstitute;
|
||||
@ -19,7 +20,7 @@ public class DeviceServiceTests
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task SaveAsync_IdProvided_UpdatedRevisionDateAndPushRegistration(Guid id, Guid userId,
|
||||
Guid organizationId1, Guid organizationId2,
|
||||
Guid organizationId1, Guid organizationId2, Guid installationId,
|
||||
OrganizationUserOrganizationDetails organizationUserOrganizationDetails1,
|
||||
OrganizationUserOrganizationDetails organizationUserOrganizationDetails2)
|
||||
{
|
||||
@ -31,7 +32,9 @@ public class DeviceServiceTests
|
||||
var organizationUserRepository = Substitute.For<IOrganizationUserRepository>();
|
||||
organizationUserRepository.GetManyDetailsByUserAsync(Arg.Any<Guid>(), Arg.Any<OrganizationUserStatusType?>())
|
||||
.Returns([organizationUserOrganizationDetails1, organizationUserOrganizationDetails2]);
|
||||
var deviceService = new DeviceService(deviceRepo, pushRepo, organizationUserRepository);
|
||||
var globalSettings = Substitute.For<IGlobalSettings>();
|
||||
globalSettings.Installation.Id.Returns(installationId);
|
||||
var deviceService = new DeviceService(deviceRepo, pushRepo, organizationUserRepository, globalSettings);
|
||||
|
||||
var device = new Device
|
||||
{
|
||||
@ -53,13 +56,13 @@ public class DeviceServiceTests
|
||||
Assert.Equal(2, organizationIdsList.Count);
|
||||
Assert.Contains(organizationId1.ToString(), organizationIdsList);
|
||||
Assert.Contains(organizationId2.ToString(), organizationIdsList);
|
||||
}));
|
||||
}), installationId.ToString());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task SaveAsync_IdNotProvided_CreatedAndPushRegistration(Guid userId, Guid organizationId1,
|
||||
Guid organizationId2,
|
||||
Guid organizationId2, Guid installationId,
|
||||
OrganizationUserOrganizationDetails organizationUserOrganizationDetails1,
|
||||
OrganizationUserOrganizationDetails organizationUserOrganizationDetails2)
|
||||
{
|
||||
@ -71,7 +74,9 @@ public class DeviceServiceTests
|
||||
var organizationUserRepository = Substitute.For<IOrganizationUserRepository>();
|
||||
organizationUserRepository.GetManyDetailsByUserAsync(Arg.Any<Guid>(), Arg.Any<OrganizationUserStatusType?>())
|
||||
.Returns([organizationUserOrganizationDetails1, organizationUserOrganizationDetails2]);
|
||||
var deviceService = new DeviceService(deviceRepo, pushRepo, organizationUserRepository);
|
||||
var globalSettings = Substitute.For<IGlobalSettings>();
|
||||
globalSettings.Installation.Id.Returns(installationId);
|
||||
var deviceService = new DeviceService(deviceRepo, pushRepo, organizationUserRepository, globalSettings);
|
||||
|
||||
var device = new Device
|
||||
{
|
||||
@ -91,7 +96,7 @@ public class DeviceServiceTests
|
||||
Assert.Equal(2, organizationIdsList.Count);
|
||||
Assert.Contains(organizationId1.ToString(), organizationIdsList);
|
||||
Assert.Contains(organizationId2.ToString(), organizationIdsList);
|
||||
}));
|
||||
}), installationId.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -79,4 +79,22 @@ public class MultiServicePushNotificationServiceTests
|
||||
.Received(1)
|
||||
.SendPayloadToOrganizationAsync(organizationId, type, payload, identifier, deviceId, clientType);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData([null, null])]
|
||||
[BitAutoData(ClientType.All, null)]
|
||||
[BitAutoData([null, "test device id"])]
|
||||
[BitAutoData(ClientType.All, "test device id")]
|
||||
public async Task SendPayloadToInstallationAsync_Message_Sent(ClientType? clientType, string? deviceId,
|
||||
string installationId, PushType type, object payload, string identifier,
|
||||
SutProvider<MultiServicePushNotificationService> sutProvider)
|
||||
{
|
||||
await sutProvider.Sut.SendPayloadToInstallationAsync(installationId, type, payload, identifier, deviceId,
|
||||
clientType);
|
||||
|
||||
await sutProvider.GetDependency<IEnumerable<IPushNotificationService>>()
|
||||
.First()
|
||||
.Received(1)
|
||||
.SendPayloadToInstallationAsync(installationId, type, payload, identifier, deviceId, clientType);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user