mirror of
https://github.com/bitwarden/server.git
synced 2025-04-07 05:58:13 -05:00
Make common base for API based notifications
This commit is contained in:
parent
1d65e69200
commit
40c48510a3
@ -24,12 +24,14 @@ public class NotificationsApiPushNotificationService : BaseIdentityClientService
|
|||||||
{
|
{
|
||||||
private readonly IGlobalSettings _globalSettings;
|
private readonly IGlobalSettings _globalSettings;
|
||||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||||
|
private readonly TimeProvider _timeProvider;
|
||||||
|
|
||||||
public NotificationsApiPushNotificationService(
|
public NotificationsApiPushNotificationService(
|
||||||
IHttpClientFactory httpFactory,
|
IHttpClientFactory httpFactory,
|
||||||
GlobalSettings globalSettings,
|
GlobalSettings globalSettings,
|
||||||
IHttpContextAccessor httpContextAccessor,
|
IHttpContextAccessor httpContextAccessor,
|
||||||
ILogger<NotificationsApiPushNotificationService> logger)
|
ILogger<NotificationsApiPushNotificationService> logger,
|
||||||
|
TimeProvider timeProvider)
|
||||||
: base(
|
: base(
|
||||||
httpFactory,
|
httpFactory,
|
||||||
globalSettings.BaseServiceUri.InternalNotifications,
|
globalSettings.BaseServiceUri.InternalNotifications,
|
||||||
@ -41,6 +43,7 @@ public class NotificationsApiPushNotificationService : BaseIdentityClientService
|
|||||||
{
|
{
|
||||||
_globalSettings = globalSettings;
|
_globalSettings = globalSettings;
|
||||||
_httpContextAccessor = httpContextAccessor;
|
_httpContextAccessor = httpContextAccessor;
|
||||||
|
_timeProvider = timeProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task PushSyncCipherCreateAsync(Cipher cipher, IEnumerable<Guid> collectionIds)
|
public async Task PushSyncCipherCreateAsync(Cipher cipher, IEnumerable<Guid> collectionIds)
|
||||||
@ -148,7 +151,7 @@ public class NotificationsApiPushNotificationService : BaseIdentityClientService
|
|||||||
var message = new UserPushNotification
|
var message = new UserPushNotification
|
||||||
{
|
{
|
||||||
UserId = userId,
|
UserId = userId,
|
||||||
Date = DateTime.UtcNow
|
Date = _timeProvider.GetUtcNow().UtcDateTime,
|
||||||
};
|
};
|
||||||
|
|
||||||
await SendMessageAsync(type, message, excludeCurrentContext);
|
await SendMessageAsync(type, message, excludeCurrentContext);
|
||||||
|
@ -1,41 +1,383 @@
|
|||||||
using Bit.Core.Platform.Push;
|
using System.Text.Json.Nodes;
|
||||||
using Bit.Core.Settings;
|
using Bit.Core.AdminConsole.Entities;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Bit.Core.Auth.Entities;
|
||||||
using Microsoft.Extensions.Logging;
|
using Bit.Core.NotificationCenter.Entities;
|
||||||
using NSubstitute;
|
using Bit.Core.Platform.Push;
|
||||||
using Xunit;
|
using Bit.Core.Tools.Entities;
|
||||||
|
using Bit.Core.Vault.Entities;
|
||||||
|
using Microsoft.Extensions.Logging.Abstractions;
|
||||||
|
|
||||||
namespace Bit.Core.Test.Platform.Push.Services;
|
namespace Bit.Core.Test.Platform.Push.Services;
|
||||||
|
|
||||||
public class NotificationsApiPushNotificationServiceTests
|
public class NotificationsApiPushNotificationServiceTests : PushTestBase
|
||||||
{
|
{
|
||||||
private readonly NotificationsApiPushNotificationService _sut;
|
|
||||||
|
|
||||||
private readonly IHttpClientFactory _httpFactory;
|
|
||||||
private readonly GlobalSettings _globalSettings;
|
|
||||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
|
||||||
private readonly ILogger<NotificationsApiPushNotificationService> _logger;
|
|
||||||
|
|
||||||
public NotificationsApiPushNotificationServiceTests()
|
public NotificationsApiPushNotificationServiceTests()
|
||||||
{
|
{
|
||||||
_httpFactory = Substitute.For<IHttpClientFactory>();
|
GlobalSettings.BaseServiceUri.InternalNotifications = "https://localhost:7777";
|
||||||
_globalSettings = new GlobalSettings();
|
GlobalSettings.BaseServiceUri.InternalIdentity = "https://localhost:8888";
|
||||||
_httpContextAccessor = Substitute.For<IHttpContextAccessor>();
|
}
|
||||||
_logger = Substitute.For<ILogger<NotificationsApiPushNotificationService>>();
|
|
||||||
|
|
||||||
_sut = new NotificationsApiPushNotificationService(
|
protected override string ExpectedClientUrl() => "https://localhost:7777/send";
|
||||||
_httpFactory,
|
|
||||||
_globalSettings,
|
protected override IPushNotificationService CreateService()
|
||||||
_httpContextAccessor,
|
{
|
||||||
_logger
|
return new NotificationsApiPushNotificationService(
|
||||||
|
HttpClientFactory,
|
||||||
|
GlobalSettings,
|
||||||
|
HttpContextAccessor,
|
||||||
|
NullLogger<NotificationsApiPushNotificationService>.Instance,
|
||||||
|
FakeTimeProvider
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove this test when we add actual tests. It only proves that
|
protected override JsonNode GetPushSyncCipherCreatePayload(Cipher cipher, Guid collectionId)
|
||||||
// we've properly constructed the system under test.
|
|
||||||
[Fact(Skip = "Needs additional work")]
|
|
||||||
public void ServiceExists()
|
|
||||||
{
|
{
|
||||||
Assert.NotNull(_sut);
|
return new JsonObject
|
||||||
|
{
|
||||||
|
["Type"] = 1,
|
||||||
|
["Payload"] = new JsonObject
|
||||||
|
{
|
||||||
|
["Id"] = cipher.Id,
|
||||||
|
["UserId"] = cipher.UserId,
|
||||||
|
["OrganizationId"] = null,
|
||||||
|
["CollectionIds"] = new JsonArray(collectionId),
|
||||||
|
["RevisionDate"] = cipher.RevisionDate,
|
||||||
|
},
|
||||||
|
["ContextId"] = DeviceIdentifier,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
protected override JsonNode GetPushSyncCipherUpdatePayload(Cipher cipher, Guid collectionId)
|
||||||
|
{
|
||||||
|
return new JsonObject
|
||||||
|
{
|
||||||
|
["Type"] = 0,
|
||||||
|
["Payload"] = new JsonObject
|
||||||
|
{
|
||||||
|
["Id"] = cipher.Id,
|
||||||
|
["UserId"] = cipher.UserId,
|
||||||
|
["OrganizationId"] = null,
|
||||||
|
["CollectionIds"] = new JsonArray(collectionId),
|
||||||
|
["RevisionDate"] = cipher.RevisionDate,
|
||||||
|
},
|
||||||
|
["ContextId"] = DeviceIdentifier,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
protected override JsonNode GetPushSyncCipherDeletePayload(Cipher cipher)
|
||||||
|
{
|
||||||
|
return new JsonObject
|
||||||
|
{
|
||||||
|
["Type"] = 2,
|
||||||
|
["Payload"] = new JsonObject
|
||||||
|
{
|
||||||
|
["Id"] = cipher.Id,
|
||||||
|
["UserId"] = cipher.UserId,
|
||||||
|
["OrganizationId"] = null,
|
||||||
|
["CollectionIds"] = null,
|
||||||
|
["RevisionDate"] = cipher.RevisionDate,
|
||||||
|
},
|
||||||
|
["ContextId"] = DeviceIdentifier,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override JsonNode GetPushSyncFolderCreatePayload(Folder folder)
|
||||||
|
{
|
||||||
|
return new JsonObject
|
||||||
|
{
|
||||||
|
["Type"] = 7,
|
||||||
|
["Payload"] = new JsonObject
|
||||||
|
{
|
||||||
|
["Id"] = folder.Id,
|
||||||
|
["UserId"] = folder.UserId,
|
||||||
|
["RevisionDate"] = folder.RevisionDate,
|
||||||
|
},
|
||||||
|
["ContextId"] = DeviceIdentifier,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override JsonNode GetPushSyncFolderUpdatePayload(Folder folder)
|
||||||
|
{
|
||||||
|
return new JsonObject
|
||||||
|
{
|
||||||
|
["Type"] = 8,
|
||||||
|
["Payload"] = new JsonObject
|
||||||
|
{
|
||||||
|
["Id"] = folder.Id,
|
||||||
|
["UserId"] = folder.UserId,
|
||||||
|
["RevisionDate"] = folder.RevisionDate,
|
||||||
|
},
|
||||||
|
["ContextId"] = DeviceIdentifier,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override JsonNode GetPushSyncFolderDeletePayload(Folder folder)
|
||||||
|
{
|
||||||
|
return new JsonObject
|
||||||
|
{
|
||||||
|
["Type"] = 3,
|
||||||
|
["Payload"] = new JsonObject
|
||||||
|
{
|
||||||
|
["Id"] = folder.Id,
|
||||||
|
["UserId"] = folder.UserId,
|
||||||
|
["RevisionDate"] = folder.RevisionDate,
|
||||||
|
},
|
||||||
|
["ContextId"] = DeviceIdentifier,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override JsonNode GetPushSyncCiphersPayload(Guid userId)
|
||||||
|
{
|
||||||
|
return new JsonObject
|
||||||
|
{
|
||||||
|
["Type"] = 4,
|
||||||
|
["Payload"] = new JsonObject
|
||||||
|
{
|
||||||
|
["UserId"] = userId,
|
||||||
|
["Date"] = FakeTimeProvider.GetUtcNow().UtcDateTime,
|
||||||
|
},
|
||||||
|
["ContextId"] = null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override JsonNode GetPushSyncVaultPayload(Guid userId)
|
||||||
|
{
|
||||||
|
return new JsonObject
|
||||||
|
{
|
||||||
|
["Type"] = 5,
|
||||||
|
["Payload"] = new JsonObject
|
||||||
|
{
|
||||||
|
["UserId"] = userId,
|
||||||
|
["Date"] = FakeTimeProvider.GetUtcNow().UtcDateTime,
|
||||||
|
},
|
||||||
|
["ContextId"] = null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override JsonNode GetPushSyncOrganizationsPayload(Guid userId)
|
||||||
|
{
|
||||||
|
return new JsonObject
|
||||||
|
{
|
||||||
|
["Type"] = 17,
|
||||||
|
["Payload"] = new JsonObject
|
||||||
|
{
|
||||||
|
["UserId"] = userId,
|
||||||
|
["Date"] = FakeTimeProvider.GetUtcNow().UtcDateTime,
|
||||||
|
},
|
||||||
|
["ContextId"] = null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override JsonNode GetPushSyncOrgKeysPayload(Guid userId)
|
||||||
|
{
|
||||||
|
return new JsonObject
|
||||||
|
{
|
||||||
|
["Type"] = 6,
|
||||||
|
["Payload"] = new JsonObject
|
||||||
|
{
|
||||||
|
["UserId"] = userId,
|
||||||
|
["Date"] = FakeTimeProvider.GetUtcNow().UtcDateTime,
|
||||||
|
},
|
||||||
|
["ContextId"] = null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override JsonNode GetPushSyncSettingsPayload(Guid userId)
|
||||||
|
{
|
||||||
|
return new JsonObject
|
||||||
|
{
|
||||||
|
["Type"] = 10,
|
||||||
|
["Payload"] = new JsonObject
|
||||||
|
{
|
||||||
|
["UserId"] = userId,
|
||||||
|
["Date"] = FakeTimeProvider.GetUtcNow().UtcDateTime,
|
||||||
|
},
|
||||||
|
["ContextId"] = null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override JsonNode GetPushLogOutPayload(Guid userId, bool excludeCurrentContext)
|
||||||
|
{
|
||||||
|
JsonNode? contextId = excludeCurrentContext ? DeviceIdentifier : null;
|
||||||
|
|
||||||
|
return new JsonObject
|
||||||
|
{
|
||||||
|
["Type"] = 11,
|
||||||
|
["Payload"] = new JsonObject
|
||||||
|
{
|
||||||
|
["UserId"] = userId,
|
||||||
|
["Date"] = FakeTimeProvider.GetUtcNow().UtcDateTime,
|
||||||
|
},
|
||||||
|
["ContextId"] = contextId,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override JsonNode GetPushSendCreatePayload(Send send)
|
||||||
|
{
|
||||||
|
return new JsonObject
|
||||||
|
{
|
||||||
|
["Type"] = 12,
|
||||||
|
["Payload"] = new JsonObject
|
||||||
|
{
|
||||||
|
["Id"] = send.Id,
|
||||||
|
["UserId"] = send.UserId,
|
||||||
|
["RevisionDate"] = send.RevisionDate,
|
||||||
|
},
|
||||||
|
["ContextId"] = null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override JsonNode GetPushSendUpdatePayload(Send send)
|
||||||
|
{
|
||||||
|
return new JsonObject
|
||||||
|
{
|
||||||
|
["Type"] = 13,
|
||||||
|
["Payload"] = new JsonObject
|
||||||
|
{
|
||||||
|
["Id"] = send.Id,
|
||||||
|
["UserId"] = send.UserId,
|
||||||
|
["RevisionDate"] = send.RevisionDate,
|
||||||
|
},
|
||||||
|
["ContextId"] = null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override JsonNode GetPushSendDeletePayload(Send send)
|
||||||
|
{
|
||||||
|
return new JsonObject
|
||||||
|
{
|
||||||
|
["Type"] = 14,
|
||||||
|
["Payload"] = new JsonObject
|
||||||
|
{
|
||||||
|
["Id"] = send.Id,
|
||||||
|
["UserId"] = send.UserId,
|
||||||
|
["RevisionDate"] = send.RevisionDate,
|
||||||
|
},
|
||||||
|
["ContextId"] = null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override JsonNode GetPushAuthRequestPayload(AuthRequest authRequest)
|
||||||
|
{
|
||||||
|
return new JsonObject
|
||||||
|
{
|
||||||
|
["Type"] = 15,
|
||||||
|
["Payload"] = new JsonObject
|
||||||
|
{
|
||||||
|
["Id"] = authRequest.Id,
|
||||||
|
["UserId"] = authRequest.UserId,
|
||||||
|
},
|
||||||
|
["ContextId"] = DeviceIdentifier,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override JsonNode GetPushAuthRequestResponsePayload(AuthRequest authRequest)
|
||||||
|
{
|
||||||
|
return new JsonObject
|
||||||
|
{
|
||||||
|
["Type"] = 16,
|
||||||
|
["Payload"] = new JsonObject
|
||||||
|
{
|
||||||
|
["Id"] = authRequest.Id,
|
||||||
|
["UserId"] = authRequest.UserId,
|
||||||
|
},
|
||||||
|
["ContextId"] = DeviceIdentifier,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override JsonNode GetPushNotificationResponsePayload(Notification notification, Guid? userId, Guid? organizationId)
|
||||||
|
{
|
||||||
|
JsonNode? installationId = notification.Global ? GlobalSettings.Installation.Id : null;
|
||||||
|
|
||||||
|
return new JsonObject
|
||||||
|
{
|
||||||
|
["Type"] = 20,
|
||||||
|
["Payload"] = new JsonObject
|
||||||
|
{
|
||||||
|
["Id"] = notification.Id,
|
||||||
|
["Priority"] = 3,
|
||||||
|
["Global"] = notification.Global,
|
||||||
|
["ClientType"] = 0,
|
||||||
|
["UserId"] = notification.UserId,
|
||||||
|
["OrganizationId"] = notification.OrganizationId,
|
||||||
|
["InstallationId"] = installationId,
|
||||||
|
["Title"] = notification.Title,
|
||||||
|
["Body"] = notification.Body,
|
||||||
|
["CreationDate"] = notification.CreationDate,
|
||||||
|
["RevisionDate"] = notification.RevisionDate,
|
||||||
|
["ReadDate"] = null,
|
||||||
|
["DeletedDate"] = null,
|
||||||
|
},
|
||||||
|
["ContextId"] = DeviceIdentifier,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override JsonNode GetPushNotificationStatusResponsePayload(Notification notification, NotificationStatus notificationStatus, Guid? userId, Guid? organizationId)
|
||||||
|
{
|
||||||
|
JsonNode? installationId = notification.Global ? GlobalSettings.Installation.Id : null;
|
||||||
|
|
||||||
|
return new JsonObject
|
||||||
|
{
|
||||||
|
["Type"] = 21,
|
||||||
|
["Payload"] = new JsonObject
|
||||||
|
{
|
||||||
|
["Id"] = notification.Id,
|
||||||
|
["Priority"] = 3,
|
||||||
|
["Global"] = notification.Global,
|
||||||
|
["ClientType"] = 0,
|
||||||
|
["UserId"] = notification.UserId,
|
||||||
|
["OrganizationId"] = notification.OrganizationId,
|
||||||
|
["InstallationId"] = installationId,
|
||||||
|
["Title"] = notification.Title,
|
||||||
|
["Body"] = notification.Body,
|
||||||
|
["CreationDate"] = notification.CreationDate,
|
||||||
|
["RevisionDate"] = notification.RevisionDate,
|
||||||
|
["ReadDate"] = notificationStatus.ReadDate,
|
||||||
|
["DeletedDate"] = notificationStatus.DeletedDate,
|
||||||
|
},
|
||||||
|
["ContextId"] = DeviceIdentifier,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override JsonNode GetPushSyncOrganizationStatusResponsePayload(Organization organization)
|
||||||
|
{
|
||||||
|
return new JsonObject
|
||||||
|
{
|
||||||
|
["Type"] = 18,
|
||||||
|
["Payload"] = new JsonObject
|
||||||
|
{
|
||||||
|
["OrganizationId"] = organization.Id,
|
||||||
|
["Enabled"] = organization.Enabled,
|
||||||
|
},
|
||||||
|
["ContextId"] = null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override JsonNode GetPushSyncOrganizationCollectionManagementSettingsResponsePayload(Organization organization)
|
||||||
|
{
|
||||||
|
return new JsonObject
|
||||||
|
{
|
||||||
|
["Type"] = 19,
|
||||||
|
["Payload"] = new JsonObject
|
||||||
|
{
|
||||||
|
["OrganizationId"] = organization.Id,
|
||||||
|
["LimitCollectionCreation"] = organization.LimitCollectionCreation,
|
||||||
|
["LimitCollectionDeletion"] = organization.LimitCollectionDeletion,
|
||||||
|
["LimitItemDeletion"] = organization.LimitItemDeletion,
|
||||||
|
},
|
||||||
|
["ContextId"] = null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override JsonNode GetPushPendingSecurityTasksResponsePayload(Guid userId)
|
||||||
|
{
|
||||||
|
return new JsonObject
|
||||||
|
{
|
||||||
|
["Type"] = 22,
|
||||||
|
["Payload"] = new JsonObject
|
||||||
|
{
|
||||||
|
["UserId"] = userId,
|
||||||
|
["Date"] = FakeTimeProvider.GetUtcNow().UtcDateTime,
|
||||||
|
},
|
||||||
|
["ContextId"] = null,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
491
test/Core.Test/Platform/Push/Services/PushTestBase.cs
Normal file
491
test/Core.Test/Platform/Push/Services/PushTestBase.cs
Normal file
@ -0,0 +1,491 @@
|
|||||||
|
// TODO: Move to own file
|
||||||
|
using System.IdentityModel.Tokens.Jwt;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Http.Json;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Nodes;
|
||||||
|
using Bit.Core.AdminConsole.Entities;
|
||||||
|
using Bit.Core.Auth.Entities;
|
||||||
|
using Bit.Core.Context;
|
||||||
|
using Bit.Core.Enums;
|
||||||
|
using Bit.Core.NotificationCenter.Entities;
|
||||||
|
using Bit.Core.NotificationCenter.Enums;
|
||||||
|
using Bit.Core.Platform.Push;
|
||||||
|
using Bit.Core.Settings;
|
||||||
|
using Bit.Core.Tools.Entities;
|
||||||
|
using Bit.Core.Vault.Entities;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Time.Testing;
|
||||||
|
using NSubstitute;
|
||||||
|
using RichardSzalay.MockHttp;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
public abstract class PushTestBase
|
||||||
|
{
|
||||||
|
protected static readonly string DeviceIdentifier = "test_device_identifier";
|
||||||
|
|
||||||
|
protected readonly MockHttpMessageHandler MockClient = new();
|
||||||
|
protected readonly MockHttpMessageHandler MockIdentityClient = new();
|
||||||
|
|
||||||
|
protected readonly IHttpClientFactory HttpClientFactory;
|
||||||
|
protected readonly GlobalSettings GlobalSettings;
|
||||||
|
protected readonly IHttpContextAccessor HttpContextAccessor;
|
||||||
|
protected readonly FakeTimeProvider FakeTimeProvider;
|
||||||
|
|
||||||
|
public PushTestBase()
|
||||||
|
{
|
||||||
|
HttpClientFactory = Substitute.For<IHttpClientFactory>();
|
||||||
|
|
||||||
|
// Mock HttpClient
|
||||||
|
HttpClientFactory.CreateClient("client")
|
||||||
|
.Returns(new HttpClient(MockClient));
|
||||||
|
|
||||||
|
HttpClientFactory.CreateClient("identity")
|
||||||
|
.Returns(new HttpClient(MockIdentityClient));
|
||||||
|
|
||||||
|
GlobalSettings = new GlobalSettings();
|
||||||
|
HttpContextAccessor = Substitute.For<IHttpContextAccessor>();
|
||||||
|
|
||||||
|
FakeTimeProvider = new FakeTimeProvider();
|
||||||
|
|
||||||
|
FakeTimeProvider.SetUtcNow(DateTimeOffset.UtcNow);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract IPushNotificationService CreateService();
|
||||||
|
|
||||||
|
protected abstract string ExpectedClientUrl();
|
||||||
|
|
||||||
|
protected abstract JsonNode GetPushSyncCipherCreatePayload(Cipher cipher, Guid collectionId);
|
||||||
|
protected abstract JsonNode GetPushSyncCipherUpdatePayload(Cipher cipher, Guid collectionId);
|
||||||
|
protected abstract JsonNode GetPushSyncCipherDeletePayload(Cipher cipher);
|
||||||
|
protected abstract JsonNode GetPushSyncFolderCreatePayload(Folder folder);
|
||||||
|
protected abstract JsonNode GetPushSyncFolderUpdatePayload(Folder folder);
|
||||||
|
protected abstract JsonNode GetPushSyncFolderDeletePayload(Folder folder);
|
||||||
|
protected abstract JsonNode GetPushSyncCiphersPayload(Guid userId);
|
||||||
|
protected abstract JsonNode GetPushSyncVaultPayload(Guid userId);
|
||||||
|
protected abstract JsonNode GetPushSyncOrganizationsPayload(Guid userId);
|
||||||
|
protected abstract JsonNode GetPushSyncOrgKeysPayload(Guid userId);
|
||||||
|
protected abstract JsonNode GetPushSyncSettingsPayload(Guid userId);
|
||||||
|
protected abstract JsonNode GetPushLogOutPayload(Guid userId, bool excludeCurrentContext);
|
||||||
|
protected abstract JsonNode GetPushSendCreatePayload(Send send);
|
||||||
|
protected abstract JsonNode GetPushSendUpdatePayload(Send send);
|
||||||
|
protected abstract JsonNode GetPushSendDeletePayload(Send send);
|
||||||
|
protected abstract JsonNode GetPushAuthRequestPayload(AuthRequest authRequest);
|
||||||
|
protected abstract JsonNode GetPushAuthRequestResponsePayload(AuthRequest authRequest);
|
||||||
|
protected abstract JsonNode GetPushNotificationResponsePayload(Notification notification, Guid? userId, Guid? organizationId);
|
||||||
|
protected abstract JsonNode GetPushNotificationStatusResponsePayload(Notification notification, NotificationStatus notificationStatus, Guid? userId, Guid? organizationId);
|
||||||
|
protected abstract JsonNode GetPushSyncOrganizationStatusResponsePayload(Organization organization);
|
||||||
|
protected abstract JsonNode GetPushSyncOrganizationCollectionManagementSettingsResponsePayload(Organization organization);
|
||||||
|
protected abstract JsonNode GetPushPendingSecurityTasksResponsePayload(Guid userId);
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task PushSyncCipherCreateAsync_SendsExpectedResponse()
|
||||||
|
{
|
||||||
|
var collectionId = Guid.NewGuid();
|
||||||
|
|
||||||
|
var cipher = new Cipher
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(),
|
||||||
|
UserId = Guid.NewGuid(),
|
||||||
|
OrganizationId = null,
|
||||||
|
RevisionDate = DateTime.UtcNow,
|
||||||
|
};
|
||||||
|
|
||||||
|
await VerifyNotificationAsync(
|
||||||
|
async sut => await sut.PushSyncCipherCreateAsync(cipher, [collectionId]),
|
||||||
|
GetPushSyncCipherCreatePayload(cipher, collectionId)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task PushSyncCipherUpdateAsync_SendsExpectedResponse()
|
||||||
|
{
|
||||||
|
var collectionId = Guid.NewGuid();
|
||||||
|
|
||||||
|
var cipher = new Cipher
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(),
|
||||||
|
UserId = Guid.NewGuid(),
|
||||||
|
OrganizationId = null,
|
||||||
|
RevisionDate = DateTime.UtcNow,
|
||||||
|
};
|
||||||
|
|
||||||
|
await VerifyNotificationAsync(
|
||||||
|
async sut => await sut.PushSyncCipherUpdateAsync(cipher, [collectionId]),
|
||||||
|
GetPushSyncCipherUpdatePayload(cipher, collectionId)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task PushSyncCipherDeleteAsync_SendsExpectedResponse()
|
||||||
|
{
|
||||||
|
var collectionId = Guid.NewGuid();
|
||||||
|
|
||||||
|
var cipher = new Cipher
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(),
|
||||||
|
UserId = Guid.NewGuid(),
|
||||||
|
OrganizationId = null,
|
||||||
|
RevisionDate = DateTime.UtcNow,
|
||||||
|
};
|
||||||
|
|
||||||
|
await VerifyNotificationAsync(
|
||||||
|
async sut => await sut.PushSyncCipherDeleteAsync(cipher),
|
||||||
|
GetPushSyncCipherDeletePayload(cipher)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task PushSyncFolderCreateAsync_SendsExpectedResponse()
|
||||||
|
{
|
||||||
|
var folder = new Folder
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(),
|
||||||
|
UserId = Guid.NewGuid(),
|
||||||
|
RevisionDate = DateTime.UtcNow,
|
||||||
|
};
|
||||||
|
|
||||||
|
await VerifyNotificationAsync(
|
||||||
|
async sut => await sut.PushSyncFolderCreateAsync(folder),
|
||||||
|
GetPushSyncFolderCreatePayload(folder)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task PushSyncFolderUpdateAsync_SendsExpectedResponse()
|
||||||
|
{
|
||||||
|
var collectionId = Guid.NewGuid();
|
||||||
|
|
||||||
|
var folder = new Folder
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(),
|
||||||
|
UserId = Guid.NewGuid(),
|
||||||
|
RevisionDate = DateTime.UtcNow,
|
||||||
|
};
|
||||||
|
|
||||||
|
await VerifyNotificationAsync(
|
||||||
|
async sut => await sut.PushSyncFolderUpdateAsync(folder),
|
||||||
|
GetPushSyncFolderUpdatePayload(folder)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task PushSyncFolderDeleteAsync_SendsExpectedResponse()
|
||||||
|
{
|
||||||
|
var collectionId = Guid.NewGuid();
|
||||||
|
|
||||||
|
var folder = new Folder
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(),
|
||||||
|
UserId = Guid.NewGuid(),
|
||||||
|
RevisionDate = DateTime.UtcNow,
|
||||||
|
};
|
||||||
|
|
||||||
|
await VerifyNotificationAsync(
|
||||||
|
async sut => await sut.PushSyncFolderDeleteAsync(folder),
|
||||||
|
GetPushSyncFolderDeletePayload(folder)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task PushSyncCiphersAsync_SendsExpectedResponse()
|
||||||
|
{
|
||||||
|
var userId = Guid.NewGuid();
|
||||||
|
|
||||||
|
await VerifyNotificationAsync(
|
||||||
|
async sut => await sut.PushSyncCiphersAsync(userId),
|
||||||
|
GetPushSyncCiphersPayload(userId)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task PushSyncVaultAsync_SendsExpectedResponse()
|
||||||
|
{
|
||||||
|
var userId = Guid.NewGuid();
|
||||||
|
|
||||||
|
await VerifyNotificationAsync(
|
||||||
|
async sut => await sut.PushSyncVaultAsync(userId),
|
||||||
|
GetPushSyncVaultPayload(userId)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task PushSyncOrganizationsAsync_SendsExpectedResponse()
|
||||||
|
{
|
||||||
|
var userId = Guid.NewGuid();
|
||||||
|
|
||||||
|
await VerifyNotificationAsync(
|
||||||
|
async sut => await sut.PushSyncOrganizationsAsync(userId),
|
||||||
|
GetPushSyncOrganizationsPayload(userId)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task PushSyncOrgKeysAsync_SendsExpectedResponse()
|
||||||
|
{
|
||||||
|
var userId = Guid.NewGuid();
|
||||||
|
|
||||||
|
await VerifyNotificationAsync(
|
||||||
|
async sut => await sut.PushSyncOrgKeysAsync(userId),
|
||||||
|
GetPushSyncOrgKeysPayload(userId)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task PushSyncSettingsAsync_SendsExpectedResponse()
|
||||||
|
{
|
||||||
|
var userId = Guid.NewGuid();
|
||||||
|
|
||||||
|
await VerifyNotificationAsync(
|
||||||
|
async sut => await sut.PushSyncSettingsAsync(userId),
|
||||||
|
GetPushSyncSettingsPayload(userId)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(true)]
|
||||||
|
[InlineData(false)]
|
||||||
|
public async Task PushLogOutAsync_SendsExpectedResponse(bool excludeCurrentContext)
|
||||||
|
{
|
||||||
|
var userId = Guid.NewGuid();
|
||||||
|
|
||||||
|
await VerifyNotificationAsync(
|
||||||
|
async sut => await sut.PushLogOutAsync(userId, excludeCurrentContext),
|
||||||
|
GetPushLogOutPayload(userId, excludeCurrentContext)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task PushSyncSendCreateAsync_SendsExpectedResponse()
|
||||||
|
{
|
||||||
|
var send = new Send
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(),
|
||||||
|
UserId = Guid.NewGuid(),
|
||||||
|
RevisionDate = DateTime.UtcNow,
|
||||||
|
};
|
||||||
|
|
||||||
|
await VerifyNotificationAsync(
|
||||||
|
async sut => await sut.PushSyncSendCreateAsync(send),
|
||||||
|
GetPushSendCreatePayload(send)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task PushSyncSendUpdateAsync_SendsExpectedResponse()
|
||||||
|
{
|
||||||
|
var send = new Send
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(),
|
||||||
|
UserId = Guid.NewGuid(),
|
||||||
|
RevisionDate = DateTime.UtcNow,
|
||||||
|
};
|
||||||
|
|
||||||
|
await VerifyNotificationAsync(
|
||||||
|
async sut => await sut.PushSyncSendUpdateAsync(send),
|
||||||
|
GetPushSendUpdatePayload(send)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task PushSyncSendDeleteAsync_SendsExpectedResponse()
|
||||||
|
{
|
||||||
|
var send = new Send
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(),
|
||||||
|
UserId = Guid.NewGuid(),
|
||||||
|
RevisionDate = DateTime.UtcNow,
|
||||||
|
};
|
||||||
|
|
||||||
|
await VerifyNotificationAsync(
|
||||||
|
async sut => await sut.PushSyncSendDeleteAsync(send),
|
||||||
|
GetPushSendDeletePayload(send)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task PushAuthRequestAsync_SendsExpectedResponse()
|
||||||
|
{
|
||||||
|
var authRequest = new AuthRequest
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(),
|
||||||
|
UserId = Guid.NewGuid(),
|
||||||
|
};
|
||||||
|
|
||||||
|
await VerifyNotificationAsync(
|
||||||
|
async sut => await sut.PushAuthRequestAsync(authRequest),
|
||||||
|
GetPushAuthRequestPayload(authRequest)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task PushAuthRequestResponseAsync_SendsExpectedResponse()
|
||||||
|
{
|
||||||
|
var authRequest = new AuthRequest
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(),
|
||||||
|
UserId = Guid.NewGuid(),
|
||||||
|
};
|
||||||
|
|
||||||
|
await VerifyNotificationAsync(
|
||||||
|
async sut => await sut.PushAuthRequestResponseAsync(authRequest),
|
||||||
|
GetPushAuthRequestResponsePayload(authRequest)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(true, null, null)]
|
||||||
|
[InlineData(false, "e8e08ce8-8a26-4a65-913a-ba1d8c478b2f", null)]
|
||||||
|
[InlineData(false, null, "2f53ee32-edf9-4169-b276-760fe92e03bf")]
|
||||||
|
public async Task PushNotificationAsync_SendsExpectedResponse(bool global, string? userId, string? organizationId)
|
||||||
|
{
|
||||||
|
var notification = new Notification
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(),
|
||||||
|
Priority = Priority.High,
|
||||||
|
Global = global,
|
||||||
|
ClientType = ClientType.All,
|
||||||
|
UserId = userId != null ? Guid.Parse(userId) : null,
|
||||||
|
OrganizationId = organizationId != null ? Guid.Parse(organizationId) : null,
|
||||||
|
Title = "My Title",
|
||||||
|
Body = "My Body",
|
||||||
|
CreationDate = DateTime.UtcNow.AddDays(-1),
|
||||||
|
RevisionDate = DateTime.UtcNow,
|
||||||
|
};
|
||||||
|
|
||||||
|
await VerifyNotificationAsync(
|
||||||
|
async sut => await sut.PushNotificationAsync(notification),
|
||||||
|
GetPushNotificationResponsePayload(notification, notification.UserId, notification.OrganizationId)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(true, null, null)]
|
||||||
|
[InlineData(false, "e8e08ce8-8a26-4a65-913a-ba1d8c478b2f", null)]
|
||||||
|
[InlineData(false, null, "2f53ee32-edf9-4169-b276-760fe92e03bf")]
|
||||||
|
public async Task PushNotificationStatusAsync_SendsExpectedResponse(bool global, string? userId, string? organizationId)
|
||||||
|
{
|
||||||
|
var notification = new Notification
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(),
|
||||||
|
Priority = Priority.High,
|
||||||
|
Global = global,
|
||||||
|
ClientType = ClientType.All,
|
||||||
|
UserId = userId != null ? Guid.Parse(userId) : null,
|
||||||
|
OrganizationId = organizationId != null ? Guid.Parse(organizationId) : null,
|
||||||
|
Title = "My Title",
|
||||||
|
Body = "My Body",
|
||||||
|
CreationDate = DateTime.UtcNow.AddDays(-1),
|
||||||
|
RevisionDate = DateTime.UtcNow,
|
||||||
|
};
|
||||||
|
|
||||||
|
var notificationStatus = new NotificationStatus
|
||||||
|
{
|
||||||
|
ReadDate = DateTime.UtcNow,
|
||||||
|
DeletedDate = DateTime.UtcNow,
|
||||||
|
};
|
||||||
|
|
||||||
|
await VerifyNotificationAsync(
|
||||||
|
async sut => await sut.PushNotificationStatusAsync(notification, notificationStatus),
|
||||||
|
GetPushNotificationStatusResponsePayload(notification, notificationStatus, notification.UserId, notification.OrganizationId)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task PushSyncOrganizationStatusAsync_SendsExpectedResponse()
|
||||||
|
{
|
||||||
|
var organization = new Organization
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(),
|
||||||
|
Enabled = true,
|
||||||
|
};
|
||||||
|
|
||||||
|
await VerifyNotificationAsync(
|
||||||
|
async sut => await sut.PushSyncOrganizationStatusAsync(organization),
|
||||||
|
GetPushSyncOrganizationStatusResponsePayload(organization)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task PushSyncOrganizationCollectionManagementSettingsAsync_SendsExpectedResponse()
|
||||||
|
{
|
||||||
|
var organization = new Organization
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(),
|
||||||
|
Enabled = true,
|
||||||
|
LimitCollectionCreation = true,
|
||||||
|
LimitCollectionDeletion = true,
|
||||||
|
LimitItemDeletion = true,
|
||||||
|
};
|
||||||
|
|
||||||
|
await VerifyNotificationAsync(
|
||||||
|
async sut => await sut.PushSyncOrganizationCollectionManagementSettingsAsync(organization),
|
||||||
|
GetPushSyncOrganizationCollectionManagementSettingsResponsePayload(organization)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task PushPendingSecurityTasksAsync_SendsExpectedResponse()
|
||||||
|
{
|
||||||
|
var userId = Guid.NewGuid();
|
||||||
|
|
||||||
|
await VerifyNotificationAsync(
|
||||||
|
async sut => await sut.PushPendingSecurityTasksAsync(userId),
|
||||||
|
GetPushPendingSecurityTasksResponsePayload(userId)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task VerifyNotificationAsync(
|
||||||
|
Func<IPushNotificationService, Task> test,
|
||||||
|
JsonNode expectedRequestBody
|
||||||
|
)
|
||||||
|
{
|
||||||
|
var httpContext = new DefaultHttpContext();
|
||||||
|
|
||||||
|
var serviceCollection = new ServiceCollection();
|
||||||
|
var currentContext = Substitute.For<ICurrentContext>();
|
||||||
|
currentContext.DeviceIdentifier = DeviceIdentifier;
|
||||||
|
serviceCollection.AddSingleton(currentContext);
|
||||||
|
|
||||||
|
httpContext.RequestServices = serviceCollection.BuildServiceProvider();
|
||||||
|
|
||||||
|
HttpContextAccessor.HttpContext
|
||||||
|
.Returns(httpContext);
|
||||||
|
|
||||||
|
var connectTokenRequest = MockIdentityClient
|
||||||
|
.Expect(HttpMethod.Post, "https://localhost:8888/connect/token")
|
||||||
|
.Respond(HttpStatusCode.OK, JsonContent.Create(new
|
||||||
|
{
|
||||||
|
access_token = CreateAccessToken(DateTime.UtcNow.AddDays(1)),
|
||||||
|
}));
|
||||||
|
|
||||||
|
var clientRequest = MockClient
|
||||||
|
.Expect(HttpMethod.Post, ExpectedClientUrl())
|
||||||
|
.With(request =>
|
||||||
|
{
|
||||||
|
if (request.Content is not JsonContent jsonContent)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: What options?
|
||||||
|
var actualString = JsonSerializer.Serialize(jsonContent.Value);
|
||||||
|
var actualNode = JsonNode.Parse(actualString);
|
||||||
|
|
||||||
|
return JsonNode.DeepEquals(actualNode, expectedRequestBody);
|
||||||
|
})
|
||||||
|
.Respond(HttpStatusCode.OK);
|
||||||
|
|
||||||
|
await test(CreateService());
|
||||||
|
|
||||||
|
Assert.Equal(1, MockClient.GetMatchCount(clientRequest));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static string CreateAccessToken(DateTime expirationTime)
|
||||||
|
{
|
||||||
|
var tokenHandler = new JwtSecurityTokenHandler();
|
||||||
|
var token = new JwtSecurityToken(expires: expirationTime);
|
||||||
|
return tokenHandler.WriteToken(token);
|
||||||
|
}
|
||||||
|
}
|
@ -1,102 +1,92 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
|
|
||||||
using System.IdentityModel.Tokens.Jwt;
|
|
||||||
using System.Net;
|
|
||||||
using System.Net.Http.Json;
|
|
||||||
using System.Text.Json;
|
|
||||||
using System.Text.Json.Nodes;
|
using System.Text.Json.Nodes;
|
||||||
using Bit.Core.AdminConsole.Entities;
|
using Bit.Core.AdminConsole.Entities;
|
||||||
using Bit.Core.Auth.Entities;
|
using Bit.Core.Auth.Entities;
|
||||||
using Bit.Core.Context;
|
|
||||||
using Bit.Core.Entities;
|
using Bit.Core.Entities;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
using Bit.Core.NotificationCenter.Entities;
|
using Bit.Core.NotificationCenter.Entities;
|
||||||
using Bit.Core.NotificationCenter.Enums;
|
|
||||||
using Bit.Core.Platform.Push.Internal;
|
using Bit.Core.Platform.Push.Internal;
|
||||||
using Bit.Core.Repositories;
|
using Bit.Core.Repositories;
|
||||||
using Bit.Core.Settings;
|
using Bit.Core.Settings;
|
||||||
using Bit.Core.Tools.Entities;
|
using Bit.Core.Tools.Entities;
|
||||||
using Bit.Core.Vault.Entities;
|
using Bit.Core.Vault.Entities;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.Extensions.Logging.Abstractions;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using Microsoft.Extensions.Time.Testing;
|
using Microsoft.Extensions.Time.Testing;
|
||||||
using NSubstitute;
|
using NSubstitute;
|
||||||
using RichardSzalay.MockHttp;
|
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Bit.Core.Test.Platform.Push.Services;
|
namespace Bit.Core.Test.Platform.Push.Services;
|
||||||
|
|
||||||
public class RelayPushNotificationServiceTests
|
public class RelayPushNotificationServiceTests : PushTestBase
|
||||||
{
|
{
|
||||||
private static readonly Guid _deviceId = Guid.Parse("c4730f80-caaa-4772-97bd-5c0d23a2baa3");
|
private static readonly Guid _deviceId = Guid.Parse("c4730f80-caaa-4772-97bd-5c0d23a2baa3");
|
||||||
private static readonly string _deviceIdentifier = "test_device_identifier";
|
|
||||||
|
|
||||||
private readonly RelayPushNotificationService _sut;
|
|
||||||
|
|
||||||
private readonly MockHttpMessageHandler _mockPushClient = new();
|
|
||||||
private readonly MockHttpMessageHandler _mockIdentityClient = new();
|
|
||||||
|
|
||||||
private readonly IHttpClientFactory _httpFactory;
|
|
||||||
private readonly IDeviceRepository _deviceRepository;
|
private readonly IDeviceRepository _deviceRepository;
|
||||||
private readonly GlobalSettings _globalSettings;
|
|
||||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
|
||||||
private readonly ILogger<RelayPushNotificationService> _logger;
|
|
||||||
private readonly FakeTimeProvider _fakeTimeProvider;
|
|
||||||
|
|
||||||
public RelayPushNotificationServiceTests()
|
public RelayPushNotificationServiceTests()
|
||||||
{
|
{
|
||||||
_httpFactory = Substitute.For<IHttpClientFactory>();
|
|
||||||
|
|
||||||
// Mock HttpClient
|
|
||||||
_httpFactory.CreateClient("client")
|
|
||||||
.Returns(new HttpClient(_mockPushClient));
|
|
||||||
|
|
||||||
_httpFactory.CreateClient("identity")
|
|
||||||
.Returns(new HttpClient(_mockIdentityClient));
|
|
||||||
|
|
||||||
_deviceRepository = Substitute.For<IDeviceRepository>();
|
_deviceRepository = Substitute.For<IDeviceRepository>();
|
||||||
_globalSettings = new GlobalSettings();
|
|
||||||
_httpContextAccessor = Substitute.For<IHttpContextAccessor>();
|
|
||||||
_logger = Substitute.For<ILogger<RelayPushNotificationService>>();
|
|
||||||
|
|
||||||
_globalSettings.PushRelayBaseUri = "https://localhost:7777";
|
_deviceRepository.GetByIdentifierAsync(DeviceIdentifier)
|
||||||
_globalSettings.Installation.Id = Guid.Parse("478c608a-99fd-452a-94f0-af271654e6ee");
|
.Returns(new Device
|
||||||
_globalSettings.Installation.IdentityUri = "https://localhost:8888";
|
{
|
||||||
|
Id = _deviceId,
|
||||||
|
});
|
||||||
|
|
||||||
_fakeTimeProvider = new FakeTimeProvider();
|
GlobalSettings.PushRelayBaseUri = "https://localhost:7777";
|
||||||
|
GlobalSettings.Installation.Id = Guid.Parse("478c608a-99fd-452a-94f0-af271654e6ee");
|
||||||
|
GlobalSettings.Installation.IdentityUri = "https://localhost:8888";
|
||||||
|
}
|
||||||
|
|
||||||
_fakeTimeProvider.SetUtcNow(DateTimeOffset.UtcNow);
|
protected override RelayPushNotificationService CreateService()
|
||||||
|
{
|
||||||
_sut = new RelayPushNotificationService(
|
return new RelayPushNotificationService(
|
||||||
_httpFactory,
|
HttpClientFactory,
|
||||||
_deviceRepository,
|
_deviceRepository,
|
||||||
_globalSettings,
|
GlobalSettings,
|
||||||
_httpContextAccessor,
|
HttpContextAccessor,
|
||||||
_logger,
|
NullLogger<RelayPushNotificationService>.Instance,
|
||||||
_fakeTimeProvider
|
FakeTimeProvider
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string ExpectedClientUrl() => "https://localhost:7777/push/send";
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task SendPayloadToInstallationAsync_ThrowsNotImplementedException()
|
||||||
|
{
|
||||||
|
var sut = CreateService();
|
||||||
|
await Assert.ThrowsAsync<NotImplementedException>(
|
||||||
|
async () => await sut.SendPayloadToInstallationAsync("installation_id", PushType.AuthRequest, new {}, null)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task PushSyncCipherCreateAsync_SendsExpectedResponse()
|
public async Task SendPayloadToUserAsync_ThrowsNotImplementedException()
|
||||||
{
|
{
|
||||||
var collectionId = Guid.NewGuid();
|
var sut = CreateService();
|
||||||
|
await Assert.ThrowsAsync<NotImplementedException>(
|
||||||
|
async () => await sut.SendPayloadToUserAsync("user_id", PushType.AuthRequest, new {}, null)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
var cipher = new Cipher
|
[Fact]
|
||||||
|
public async Task SendPayloadToOrganizationAsync_ThrowsNotImplementedException()
|
||||||
{
|
{
|
||||||
Id = Guid.NewGuid(),
|
var sut = CreateService();
|
||||||
UserId = Guid.NewGuid(),
|
await Assert.ThrowsAsync<NotImplementedException>(
|
||||||
OrganizationId = null,
|
async () => await sut.SendPayloadToOrganizationAsync("organization_id", PushType.AuthRequest, new {}, null)
|
||||||
RevisionDate = DateTime.UtcNow,
|
);
|
||||||
};
|
}
|
||||||
|
|
||||||
var expectedPayload = new JsonObject
|
protected override JsonNode GetPushSyncCipherCreatePayload(Cipher cipher, Guid collectionIds)
|
||||||
|
{
|
||||||
|
return new JsonObject
|
||||||
{
|
{
|
||||||
["UserId"] = cipher.UserId,
|
["UserId"] = cipher.UserId,
|
||||||
["OrganizationId"] = null,
|
["OrganizationId"] = null,
|
||||||
["DeviceId"] = _deviceId,
|
["DeviceId"] = _deviceId,
|
||||||
["Identifier"] = _deviceIdentifier,
|
["Identifier"] = DeviceIdentifier,
|
||||||
["Type"] = 1,
|
["Type"] = 1,
|
||||||
["Payload"] = new JsonObject
|
["Payload"] = new JsonObject
|
||||||
{
|
{
|
||||||
@ -111,32 +101,16 @@ public class RelayPushNotificationServiceTests
|
|||||||
["ClientType"] = null,
|
["ClientType"] = null,
|
||||||
["InstallationId"] = null,
|
["InstallationId"] = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
await VerifyNotificationAsync(
|
|
||||||
async sut => await sut.PushSyncCipherCreateAsync(cipher, [collectionId]),
|
|
||||||
expectedPayload
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
protected override JsonNode GetPushSyncCipherUpdatePayload(Cipher cipher, Guid collectionIds)
|
||||||
public async Task PushSyncCipherUpdateAsync_SendsExpectedResponse()
|
|
||||||
{
|
{
|
||||||
var collectionId = Guid.NewGuid();
|
return new JsonObject
|
||||||
|
|
||||||
var cipher = new Cipher
|
|
||||||
{
|
|
||||||
Id = Guid.NewGuid(),
|
|
||||||
UserId = Guid.NewGuid(),
|
|
||||||
OrganizationId = null,
|
|
||||||
RevisionDate = DateTime.UtcNow,
|
|
||||||
};
|
|
||||||
|
|
||||||
var expectedPayload = new JsonObject
|
|
||||||
{
|
{
|
||||||
["UserId"] = cipher.UserId,
|
["UserId"] = cipher.UserId,
|
||||||
["OrganizationId"] = null,
|
["OrganizationId"] = null,
|
||||||
["DeviceId"] = _deviceId,
|
["DeviceId"] = _deviceId,
|
||||||
["Identifier"] = _deviceIdentifier,
|
["Identifier"] = DeviceIdentifier,
|
||||||
["Type"] = 0,
|
["Type"] = 0,
|
||||||
["Payload"] = new JsonObject
|
["Payload"] = new JsonObject
|
||||||
{
|
{
|
||||||
@ -151,32 +125,16 @@ public class RelayPushNotificationServiceTests
|
|||||||
["ClientType"] = null,
|
["ClientType"] = null,
|
||||||
["InstallationId"] = null,
|
["InstallationId"] = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
await VerifyNotificationAsync(
|
|
||||||
async sut => await sut.PushSyncCipherUpdateAsync(cipher, [collectionId]),
|
|
||||||
expectedPayload
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
protected override JsonNode GetPushSyncCipherDeletePayload(Cipher cipher)
|
||||||
public async Task PushSyncCipherDeleteAsync_SendsExpectedResponse()
|
|
||||||
{
|
{
|
||||||
var collectionId = Guid.NewGuid();
|
return new JsonObject
|
||||||
|
|
||||||
var cipher = new Cipher
|
|
||||||
{
|
|
||||||
Id = Guid.NewGuid(),
|
|
||||||
UserId = Guid.NewGuid(),
|
|
||||||
OrganizationId = null,
|
|
||||||
RevisionDate = DateTime.UtcNow,
|
|
||||||
};
|
|
||||||
|
|
||||||
var expectedPayload = new JsonObject
|
|
||||||
{
|
{
|
||||||
["UserId"] = cipher.UserId,
|
["UserId"] = cipher.UserId,
|
||||||
["OrganizationId"] = null,
|
["OrganizationId"] = null,
|
||||||
["DeviceId"] = _deviceId,
|
["DeviceId"] = _deviceId,
|
||||||
["Identifier"] = _deviceIdentifier,
|
["Identifier"] = DeviceIdentifier,
|
||||||
["Type"] = 2,
|
["Type"] = 2,
|
||||||
["Payload"] = new JsonObject
|
["Payload"] = new JsonObject
|
||||||
{
|
{
|
||||||
@ -189,31 +147,16 @@ public class RelayPushNotificationServiceTests
|
|||||||
["ClientType"] = null,
|
["ClientType"] = null,
|
||||||
["InstallationId"] = null,
|
["InstallationId"] = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
await VerifyNotificationAsync(
|
|
||||||
async sut => await sut.PushSyncCipherDeleteAsync(cipher),
|
|
||||||
expectedPayload
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
protected override JsonNode GetPushSyncFolderCreatePayload(Folder folder)
|
||||||
public async Task PushSyncFolderCreateAsync_SendsExpectedResponse()
|
|
||||||
{
|
{
|
||||||
var collectionId = Guid.NewGuid();
|
return new JsonObject
|
||||||
|
|
||||||
var folder = new Folder
|
|
||||||
{
|
|
||||||
Id = Guid.NewGuid(),
|
|
||||||
UserId = Guid.NewGuid(),
|
|
||||||
RevisionDate = DateTime.UtcNow,
|
|
||||||
};
|
|
||||||
|
|
||||||
var expectedPayload = new JsonObject
|
|
||||||
{
|
{
|
||||||
["UserId"] = folder.UserId,
|
["UserId"] = folder.UserId,
|
||||||
["OrganizationId"] = null,
|
["OrganizationId"] = null,
|
||||||
["DeviceId"] = _deviceId,
|
["DeviceId"] = _deviceId,
|
||||||
["Identifier"] = _deviceIdentifier,
|
["Identifier"] = DeviceIdentifier,
|
||||||
["Type"] = 7,
|
["Type"] = 7,
|
||||||
["Payload"] = new JsonObject
|
["Payload"] = new JsonObject
|
||||||
{
|
{
|
||||||
@ -224,31 +167,16 @@ public class RelayPushNotificationServiceTests
|
|||||||
["ClientType"] = null,
|
["ClientType"] = null,
|
||||||
["InstallationId"] = null,
|
["InstallationId"] = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
await VerifyNotificationAsync(
|
|
||||||
async sut => await sut.PushSyncFolderCreateAsync(folder),
|
|
||||||
expectedPayload
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
protected override JsonNode GetPushSyncFolderUpdatePayload(Folder folder)
|
||||||
public async Task PushSyncFolderUpdateAsync_SendsExpectedResponse()
|
|
||||||
{
|
{
|
||||||
var collectionId = Guid.NewGuid();
|
return new JsonObject
|
||||||
|
|
||||||
var folder = new Folder
|
|
||||||
{
|
|
||||||
Id = Guid.NewGuid(),
|
|
||||||
UserId = Guid.NewGuid(),
|
|
||||||
RevisionDate = DateTime.UtcNow,
|
|
||||||
};
|
|
||||||
|
|
||||||
var expectedPayload = new JsonObject
|
|
||||||
{
|
{
|
||||||
["UserId"] = folder.UserId,
|
["UserId"] = folder.UserId,
|
||||||
["OrganizationId"] = null,
|
["OrganizationId"] = null,
|
||||||
["DeviceId"] = _deviceId,
|
["DeviceId"] = _deviceId,
|
||||||
["Identifier"] = _deviceIdentifier,
|
["Identifier"] = DeviceIdentifier,
|
||||||
["Type"] = 8,
|
["Type"] = 8,
|
||||||
["Payload"] = new JsonObject
|
["Payload"] = new JsonObject
|
||||||
{
|
{
|
||||||
@ -259,31 +187,16 @@ public class RelayPushNotificationServiceTests
|
|||||||
["ClientType"] = null,
|
["ClientType"] = null,
|
||||||
["InstallationId"] = null,
|
["InstallationId"] = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
await VerifyNotificationAsync(
|
|
||||||
async sut => await sut.PushSyncFolderUpdateAsync(folder),
|
|
||||||
expectedPayload
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
protected override JsonNode GetPushSyncFolderDeletePayload(Folder folder)
|
||||||
public async Task PushSyncFolderDeleteAsync_SendsExpectedResponse()
|
|
||||||
{
|
{
|
||||||
var collectionId = Guid.NewGuid();
|
return new JsonObject
|
||||||
|
|
||||||
var folder = new Folder
|
|
||||||
{
|
|
||||||
Id = Guid.NewGuid(),
|
|
||||||
UserId = Guid.NewGuid(),
|
|
||||||
RevisionDate = DateTime.UtcNow,
|
|
||||||
};
|
|
||||||
|
|
||||||
var expectedPayload = new JsonObject
|
|
||||||
{
|
{
|
||||||
["UserId"] = folder.UserId,
|
["UserId"] = folder.UserId,
|
||||||
["OrganizationId"] = null,
|
["OrganizationId"] = null,
|
||||||
["DeviceId"] = _deviceId,
|
["DeviceId"] = _deviceId,
|
||||||
["Identifier"] = _deviceIdentifier,
|
["Identifier"] = DeviceIdentifier,
|
||||||
["Type"] = 3,
|
["Type"] = 3,
|
||||||
["Payload"] = new JsonObject
|
["Payload"] = new JsonObject
|
||||||
{
|
{
|
||||||
@ -294,19 +207,11 @@ public class RelayPushNotificationServiceTests
|
|||||||
["ClientType"] = null,
|
["ClientType"] = null,
|
||||||
["InstallationId"] = null,
|
["InstallationId"] = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
await VerifyNotificationAsync(
|
|
||||||
async sut => await sut.PushSyncFolderDeleteAsync(folder),
|
|
||||||
expectedPayload
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
protected override JsonNode GetPushSyncCiphersPayload(Guid userId)
|
||||||
public async Task PushSyncCiphersAsync_SendsExpectedResponse()
|
|
||||||
{
|
{
|
||||||
var userId = Guid.NewGuid();
|
return new JsonObject
|
||||||
|
|
||||||
var expectedPayload = new JsonObject
|
|
||||||
{
|
{
|
||||||
["UserId"] = userId,
|
["UserId"] = userId,
|
||||||
["OrganizationId"] = null,
|
["OrganizationId"] = null,
|
||||||
@ -316,24 +221,16 @@ public class RelayPushNotificationServiceTests
|
|||||||
["Payload"] = new JsonObject
|
["Payload"] = new JsonObject
|
||||||
{
|
{
|
||||||
["UserId"] = userId,
|
["UserId"] = userId,
|
||||||
["Date"] = _fakeTimeProvider.GetUtcNow().UtcDateTime,
|
["Date"] = FakeTimeProvider.GetUtcNow().UtcDateTime,
|
||||||
},
|
},
|
||||||
["ClientType"] = null,
|
["ClientType"] = null,
|
||||||
["InstallationId"] = null,
|
["InstallationId"] = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
await VerifyNotificationAsync(
|
|
||||||
async sut => await sut.PushSyncCiphersAsync(userId),
|
|
||||||
expectedPayload
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
protected override JsonNode GetPushSyncVaultPayload(Guid userId)
|
||||||
public async Task PushSyncVaultAsync_SendsExpectedResponse()
|
|
||||||
{
|
{
|
||||||
var userId = Guid.NewGuid();
|
return new JsonObject
|
||||||
|
|
||||||
var expectedPayload = new JsonObject
|
|
||||||
{
|
{
|
||||||
["UserId"] = userId,
|
["UserId"] = userId,
|
||||||
["OrganizationId"] = null,
|
["OrganizationId"] = null,
|
||||||
@ -343,24 +240,16 @@ public class RelayPushNotificationServiceTests
|
|||||||
["Payload"] = new JsonObject
|
["Payload"] = new JsonObject
|
||||||
{
|
{
|
||||||
["UserId"] = userId,
|
["UserId"] = userId,
|
||||||
["Date"] = _fakeTimeProvider.GetUtcNow().UtcDateTime,
|
["Date"] = FakeTimeProvider.GetUtcNow().UtcDateTime,
|
||||||
},
|
},
|
||||||
["ClientType"] = null,
|
["ClientType"] = null,
|
||||||
["InstallationId"] = null,
|
["InstallationId"] = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
await VerifyNotificationAsync(
|
|
||||||
async sut => await sut.PushSyncVaultAsync(userId),
|
|
||||||
expectedPayload
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
protected override JsonNode GetPushSyncOrganizationsPayload(Guid userId)
|
||||||
public async Task PushSyncOrganizationsAsync_SendsExpectedResponse()
|
|
||||||
{
|
{
|
||||||
var userId = Guid.NewGuid();
|
return new JsonObject
|
||||||
|
|
||||||
var expectedPayload = new JsonObject
|
|
||||||
{
|
{
|
||||||
["UserId"] = userId,
|
["UserId"] = userId,
|
||||||
["OrganizationId"] = null,
|
["OrganizationId"] = null,
|
||||||
@ -370,24 +259,16 @@ public class RelayPushNotificationServiceTests
|
|||||||
["Payload"] = new JsonObject
|
["Payload"] = new JsonObject
|
||||||
{
|
{
|
||||||
["UserId"] = userId,
|
["UserId"] = userId,
|
||||||
["Date"] = _fakeTimeProvider.GetUtcNow().UtcDateTime,
|
["Date"] = FakeTimeProvider.GetUtcNow().UtcDateTime,
|
||||||
},
|
},
|
||||||
["ClientType"] = null,
|
["ClientType"] = null,
|
||||||
["InstallationId"] = null,
|
["InstallationId"] = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
await VerifyNotificationAsync(
|
|
||||||
async sut => await sut.PushSyncOrganizationsAsync(userId),
|
|
||||||
expectedPayload
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
protected override JsonNode GetPushSyncOrgKeysPayload(Guid userId)
|
||||||
public async Task PushSyncOrgKeysAsync_SendsExpectedResponse()
|
|
||||||
{
|
{
|
||||||
var userId = Guid.NewGuid();
|
return new JsonObject
|
||||||
|
|
||||||
var expectedPayload = new JsonObject
|
|
||||||
{
|
{
|
||||||
["UserId"] = userId,
|
["UserId"] = userId,
|
||||||
["OrganizationId"] = null,
|
["OrganizationId"] = null,
|
||||||
@ -397,24 +278,16 @@ public class RelayPushNotificationServiceTests
|
|||||||
["Payload"] = new JsonObject
|
["Payload"] = new JsonObject
|
||||||
{
|
{
|
||||||
["UserId"] = userId,
|
["UserId"] = userId,
|
||||||
["Date"] = _fakeTimeProvider.GetUtcNow().UtcDateTime,
|
["Date"] = FakeTimeProvider.GetUtcNow().UtcDateTime,
|
||||||
},
|
},
|
||||||
["ClientType"] = null,
|
["ClientType"] = null,
|
||||||
["InstallationId"] = null,
|
["InstallationId"] = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
await VerifyNotificationAsync(
|
|
||||||
async sut => await sut.PushSyncOrgKeysAsync(userId),
|
|
||||||
expectedPayload
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
protected override JsonNode GetPushSyncSettingsPayload(Guid userId)
|
||||||
public async Task PushSyncSettingsAsync_SendsExpectedResponse()
|
|
||||||
{
|
{
|
||||||
var userId = Guid.NewGuid();
|
return new JsonObject
|
||||||
|
|
||||||
var expectedPayload = new JsonObject
|
|
||||||
{
|
{
|
||||||
["UserId"] = userId,
|
["UserId"] = userId,
|
||||||
["OrganizationId"] = null,
|
["OrganizationId"] = null,
|
||||||
@ -424,28 +297,18 @@ public class RelayPushNotificationServiceTests
|
|||||||
["Payload"] = new JsonObject
|
["Payload"] = new JsonObject
|
||||||
{
|
{
|
||||||
["UserId"] = userId,
|
["UserId"] = userId,
|
||||||
["Date"] = _fakeTimeProvider.GetUtcNow().UtcDateTime,
|
["Date"] = FakeTimeProvider.GetUtcNow().UtcDateTime,
|
||||||
},
|
},
|
||||||
["ClientType"] = null,
|
["ClientType"] = null,
|
||||||
["InstallationId"] = null,
|
["InstallationId"] = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
await VerifyNotificationAsync(
|
|
||||||
async sut => await sut.PushSyncSettingsAsync(userId),
|
|
||||||
expectedPayload
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
protected override JsonNode GetPushLogOutPayload(Guid userId, bool excludeCurrentContext)
|
||||||
[InlineData(true)]
|
|
||||||
[InlineData(false)]
|
|
||||||
public async Task PushLogOutAsync_SendsExpectedResponse(bool excludeCurrentContext)
|
|
||||||
{
|
{
|
||||||
var userId = Guid.NewGuid();
|
JsonNode? identifier = excludeCurrentContext ? DeviceIdentifier : null;
|
||||||
|
|
||||||
JsonNode? identifier = excludeCurrentContext ? _deviceIdentifier : null;
|
return new JsonObject
|
||||||
|
|
||||||
var expectedPayload = new JsonObject
|
|
||||||
{
|
{
|
||||||
["UserId"] = userId,
|
["UserId"] = userId,
|
||||||
["OrganizationId"] = null,
|
["OrganizationId"] = null,
|
||||||
@ -455,34 +318,20 @@ public class RelayPushNotificationServiceTests
|
|||||||
["Payload"] = new JsonObject
|
["Payload"] = new JsonObject
|
||||||
{
|
{
|
||||||
["UserId"] = userId,
|
["UserId"] = userId,
|
||||||
["Date"] = _fakeTimeProvider.GetUtcNow().UtcDateTime,
|
["Date"] = FakeTimeProvider.GetUtcNow().UtcDateTime,
|
||||||
},
|
},
|
||||||
["ClientType"] = null,
|
["ClientType"] = null,
|
||||||
["InstallationId"] = null,
|
["InstallationId"] = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
await VerifyNotificationAsync(
|
|
||||||
async sut => await sut.PushLogOutAsync(userId, excludeCurrentContext),
|
|
||||||
expectedPayload
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
protected override JsonNode GetPushSendCreatePayload(Send send)
|
||||||
[Fact]
|
|
||||||
public async Task PushSyncSendCreateAsync_SendsExpectedResponse()
|
|
||||||
{
|
{
|
||||||
var send = new Send
|
return new JsonObject
|
||||||
{
|
|
||||||
Id = Guid.NewGuid(),
|
|
||||||
UserId = Guid.NewGuid(),
|
|
||||||
RevisionDate = DateTime.UtcNow,
|
|
||||||
};
|
|
||||||
|
|
||||||
var expectedPayload = new JsonObject
|
|
||||||
{
|
{
|
||||||
["UserId"] = send.UserId,
|
["UserId"] = send.UserId,
|
||||||
["OrganizationId"] = null,
|
["OrganizationId"] = null,
|
||||||
["DeviceId"] = _deviceId,
|
["DeviceId"] = _deviceId,
|
||||||
["Identifier"] = _deviceIdentifier,
|
["Identifier"] = DeviceIdentifier,
|
||||||
["Type"] = 12,
|
["Type"] = 12,
|
||||||
["Payload"] = new JsonObject
|
["Payload"] = new JsonObject
|
||||||
{
|
{
|
||||||
@ -493,29 +342,15 @@ public class RelayPushNotificationServiceTests
|
|||||||
["ClientType"] = null,
|
["ClientType"] = null,
|
||||||
["InstallationId"] = null,
|
["InstallationId"] = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
await VerifyNotificationAsync(
|
|
||||||
async sut => await sut.PushSyncSendCreateAsync(send),
|
|
||||||
expectedPayload
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
protected override JsonNode GetPushSendUpdatePayload(Send send)
|
||||||
[Fact]
|
|
||||||
public async Task PushSyncSendUpdateAsync_SendsExpectedResponse()
|
|
||||||
{
|
{
|
||||||
var send = new Send
|
return new JsonObject
|
||||||
{
|
|
||||||
Id = Guid.NewGuid(),
|
|
||||||
UserId = Guid.NewGuid(),
|
|
||||||
RevisionDate = DateTime.UtcNow,
|
|
||||||
};
|
|
||||||
|
|
||||||
var expectedPayload = new JsonObject
|
|
||||||
{
|
{
|
||||||
["UserId"] = send.UserId,
|
["UserId"] = send.UserId,
|
||||||
["OrganizationId"] = null,
|
["OrganizationId"] = null,
|
||||||
["DeviceId"] = _deviceId,
|
["DeviceId"] = _deviceId,
|
||||||
["Identifier"] = _deviceIdentifier,
|
["Identifier"] = DeviceIdentifier,
|
||||||
["Type"] = 13,
|
["Type"] = 13,
|
||||||
["Payload"] = new JsonObject
|
["Payload"] = new JsonObject
|
||||||
{
|
{
|
||||||
@ -526,29 +361,15 @@ public class RelayPushNotificationServiceTests
|
|||||||
["ClientType"] = null,
|
["ClientType"] = null,
|
||||||
["InstallationId"] = null,
|
["InstallationId"] = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
await VerifyNotificationAsync(
|
|
||||||
async sut => await sut.PushSyncSendUpdateAsync(send),
|
|
||||||
expectedPayload
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
protected override JsonNode GetPushSendDeletePayload(Send send)
|
||||||
[Fact]
|
|
||||||
public async Task PushSyncSendDeleteAsync_SendsExpectedResponse()
|
|
||||||
{
|
{
|
||||||
var send = new Send
|
return new JsonObject
|
||||||
{
|
|
||||||
Id = Guid.NewGuid(),
|
|
||||||
UserId = Guid.NewGuid(),
|
|
||||||
RevisionDate = DateTime.UtcNow,
|
|
||||||
};
|
|
||||||
|
|
||||||
var expectedPayload = new JsonObject
|
|
||||||
{
|
{
|
||||||
["UserId"] = send.UserId,
|
["UserId"] = send.UserId,
|
||||||
["OrganizationId"] = null,
|
["OrganizationId"] = null,
|
||||||
["DeviceId"] = _deviceId,
|
["DeviceId"] = _deviceId,
|
||||||
["Identifier"] = _deviceIdentifier,
|
["Identifier"] = DeviceIdentifier,
|
||||||
["Type"] = 14,
|
["Type"] = 14,
|
||||||
["Payload"] = new JsonObject
|
["Payload"] = new JsonObject
|
||||||
{
|
{
|
||||||
@ -559,28 +380,15 @@ public class RelayPushNotificationServiceTests
|
|||||||
["ClientType"] = null,
|
["ClientType"] = null,
|
||||||
["InstallationId"] = null,
|
["InstallationId"] = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
await VerifyNotificationAsync(
|
|
||||||
async sut => await sut.PushSyncSendDeleteAsync(send),
|
|
||||||
expectedPayload
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
protected override JsonNode GetPushAuthRequestPayload(AuthRequest authRequest)
|
||||||
[Fact]
|
|
||||||
public async Task PushAuthRequestAsync_SendsExpectedResponse()
|
|
||||||
{
|
{
|
||||||
var authRequest = new AuthRequest
|
return new JsonObject
|
||||||
{
|
|
||||||
Id = Guid.NewGuid(),
|
|
||||||
UserId = Guid.NewGuid(),
|
|
||||||
};
|
|
||||||
|
|
||||||
var expectedPayload = new JsonObject
|
|
||||||
{
|
{
|
||||||
["UserId"] = authRequest.UserId,
|
["UserId"] = authRequest.UserId,
|
||||||
["OrganizationId"] = null,
|
["OrganizationId"] = null,
|
||||||
["DeviceId"] = _deviceId,
|
["DeviceId"] = _deviceId,
|
||||||
["Identifier"] = _deviceIdentifier,
|
["Identifier"] = DeviceIdentifier,
|
||||||
["Type"] = 15,
|
["Type"] = 15,
|
||||||
["Payload"] = new JsonObject
|
["Payload"] = new JsonObject
|
||||||
{
|
{
|
||||||
@ -590,28 +398,15 @@ public class RelayPushNotificationServiceTests
|
|||||||
["ClientType"] = null,
|
["ClientType"] = null,
|
||||||
["InstallationId"] = null,
|
["InstallationId"] = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
await VerifyNotificationAsync(
|
|
||||||
async sut => await sut.PushAuthRequestAsync(authRequest),
|
|
||||||
expectedPayload
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
protected override JsonNode GetPushAuthRequestResponsePayload(AuthRequest authRequest)
|
||||||
[Fact]
|
|
||||||
public async Task PushAuthRequestResponseAsync_SendsExpectedResponse()
|
|
||||||
{
|
{
|
||||||
var authRequest = new AuthRequest
|
return new JsonObject
|
||||||
{
|
|
||||||
Id = Guid.NewGuid(),
|
|
||||||
UserId = Guid.NewGuid(),
|
|
||||||
};
|
|
||||||
|
|
||||||
var expectedPayload = new JsonObject
|
|
||||||
{
|
{
|
||||||
["UserId"] = authRequest.UserId,
|
["UserId"] = authRequest.UserId,
|
||||||
["OrganizationId"] = null,
|
["OrganizationId"] = null,
|
||||||
["DeviceId"] = _deviceId,
|
["DeviceId"] = _deviceId,
|
||||||
["Identifier"] = _deviceIdentifier,
|
["Identifier"] = DeviceIdentifier,
|
||||||
["Type"] = 16,
|
["Type"] = 16,
|
||||||
["Payload"] = new JsonObject
|
["Payload"] = new JsonObject
|
||||||
{
|
{
|
||||||
@ -621,47 +416,23 @@ public class RelayPushNotificationServiceTests
|
|||||||
["ClientType"] = null,
|
["ClientType"] = null,
|
||||||
["InstallationId"] = null,
|
["InstallationId"] = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
await VerifyNotificationAsync(
|
|
||||||
async sut => await sut.PushAuthRequestResponseAsync(authRequest),
|
|
||||||
expectedPayload
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
protected override JsonNode GetPushNotificationResponsePayload(Notification notification, Guid? userId, Guid? organizationId)
|
||||||
[Theory]
|
|
||||||
[InlineData(true, null, null)]
|
|
||||||
[InlineData(false, "e8e08ce8-8a26-4a65-913a-ba1d8c478b2f", null)]
|
|
||||||
[InlineData(false, null, "2f53ee32-edf9-4169-b276-760fe92e03bf")]
|
|
||||||
public async Task PushNotificationAsync_SendsExpectedResponse(bool global, string? userId, string? organizationId)
|
|
||||||
{
|
{
|
||||||
var notification = new Notification
|
JsonNode? installationId = notification.Global ? GlobalSettings.Installation.Id : null;
|
||||||
{
|
|
||||||
Id = Guid.NewGuid(),
|
|
||||||
Priority = Priority.High,
|
|
||||||
Global = global,
|
|
||||||
ClientType = ClientType.All,
|
|
||||||
UserId = userId != null ? Guid.Parse(userId) : null,
|
|
||||||
OrganizationId = organizationId != null ? Guid.Parse(organizationId) : null,
|
|
||||||
Title = "My Title",
|
|
||||||
Body = "My Body",
|
|
||||||
CreationDate = DateTime.UtcNow.AddDays(-1),
|
|
||||||
RevisionDate = DateTime.UtcNow,
|
|
||||||
};
|
|
||||||
|
|
||||||
JsonNode? installationId = global ? _globalSettings.Installation.Id : null;
|
return new JsonObject
|
||||||
|
|
||||||
var expectedPayload = new JsonObject
|
|
||||||
{
|
{
|
||||||
["UserId"] = notification.UserId,
|
["UserId"] = notification.UserId,
|
||||||
["OrganizationId"] = notification.OrganizationId,
|
["OrganizationId"] = notification.OrganizationId,
|
||||||
["DeviceId"] = _deviceId,
|
["DeviceId"] = _deviceId,
|
||||||
["Identifier"] = _deviceIdentifier,
|
["Identifier"] = DeviceIdentifier,
|
||||||
["Type"] = 20,
|
["Type"] = 20,
|
||||||
["Payload"] = new JsonObject
|
["Payload"] = new JsonObject
|
||||||
{
|
{
|
||||||
["Id"] = notification.Id,
|
["Id"] = notification.Id,
|
||||||
["Priority"] = 3,
|
["Priority"] = 3,
|
||||||
["Global"] = global,
|
["Global"] = notification.Global,
|
||||||
["ClientType"] = 0,
|
["ClientType"] = 0,
|
||||||
["UserId"] = notification.UserId,
|
["UserId"] = notification.UserId,
|
||||||
["OrganizationId"] = notification.OrganizationId,
|
["OrganizationId"] = notification.OrganizationId,
|
||||||
@ -676,53 +447,23 @@ public class RelayPushNotificationServiceTests
|
|||||||
["ClientType"] = 0,
|
["ClientType"] = 0,
|
||||||
["InstallationId"] = installationId?.DeepClone(),
|
["InstallationId"] = installationId?.DeepClone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
await VerifyNotificationAsync(
|
|
||||||
async sut => await sut.PushNotificationAsync(notification),
|
|
||||||
expectedPayload
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
protected override JsonNode GetPushNotificationStatusResponsePayload(Notification notification, NotificationStatus notificationStatus, Guid? userId, Guid? organizationId)
|
||||||
[Theory]
|
|
||||||
[InlineData(true, null, null)]
|
|
||||||
[InlineData(false, "e8e08ce8-8a26-4a65-913a-ba1d8c478b2f", null)]
|
|
||||||
[InlineData(false, null, "2f53ee32-edf9-4169-b276-760fe92e03bf")]
|
|
||||||
public async Task PushNotificationStatusAsync_SendsExpectedResponse(bool global, string? userId, string? organizationId)
|
|
||||||
{
|
{
|
||||||
var notification = new Notification
|
JsonNode? installationId = notification.Global ? GlobalSettings.Installation.Id : null;
|
||||||
{
|
|
||||||
Id = Guid.NewGuid(),
|
|
||||||
Priority = Priority.High,
|
|
||||||
Global = global,
|
|
||||||
ClientType = ClientType.All,
|
|
||||||
UserId = userId != null ? Guid.Parse(userId) : null,
|
|
||||||
OrganizationId = organizationId != null ? Guid.Parse(organizationId) : null,
|
|
||||||
Title = "My Title",
|
|
||||||
Body = "My Body",
|
|
||||||
CreationDate = DateTime.UtcNow.AddDays(-1),
|
|
||||||
RevisionDate = DateTime.UtcNow,
|
|
||||||
};
|
|
||||||
|
|
||||||
var notificationStatus = new NotificationStatus
|
return new JsonObject
|
||||||
{
|
|
||||||
ReadDate = DateTime.UtcNow,
|
|
||||||
DeletedDate = DateTime.UtcNow,
|
|
||||||
};
|
|
||||||
|
|
||||||
JsonNode? installationId = global ? _globalSettings.Installation.Id : null;
|
|
||||||
|
|
||||||
var expectedPayload = new JsonObject
|
|
||||||
{
|
{
|
||||||
["UserId"] = notification.UserId,
|
["UserId"] = notification.UserId,
|
||||||
["OrganizationId"] = notification.OrganizationId,
|
["OrganizationId"] = notification.OrganizationId,
|
||||||
["DeviceId"] = _deviceId,
|
["DeviceId"] = _deviceId,
|
||||||
["Identifier"] = _deviceIdentifier,
|
["Identifier"] = DeviceIdentifier,
|
||||||
["Type"] = 21,
|
["Type"] = 21,
|
||||||
["Payload"] = new JsonObject
|
["Payload"] = new JsonObject
|
||||||
{
|
{
|
||||||
["Id"] = notification.Id,
|
["Id"] = notification.Id,
|
||||||
["Priority"] = 3,
|
["Priority"] = 3,
|
||||||
["Global"] = global,
|
["Global"] = notification.Global,
|
||||||
["ClientType"] = 0,
|
["ClientType"] = 0,
|
||||||
["UserId"] = notification.UserId,
|
["UserId"] = notification.UserId,
|
||||||
["OrganizationId"] = notification.OrganizationId,
|
["OrganizationId"] = notification.OrganizationId,
|
||||||
@ -737,23 +478,10 @@ public class RelayPushNotificationServiceTests
|
|||||||
["ClientType"] = 0,
|
["ClientType"] = 0,
|
||||||
["InstallationId"] = installationId?.DeepClone(),
|
["InstallationId"] = installationId?.DeepClone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
await VerifyNotificationAsync(
|
|
||||||
async sut => await sut.PushNotificationStatusAsync(notification, notificationStatus),
|
|
||||||
expectedPayload
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
protected override JsonNode GetPushSyncOrganizationStatusResponsePayload(Organization organization)
|
||||||
[Fact]
|
|
||||||
public async Task PushSyncOrganizationStatusAsync_SendsExpectedResponse()
|
|
||||||
{
|
{
|
||||||
var organization = new Organization
|
return new JsonObject
|
||||||
{
|
|
||||||
Id = Guid.NewGuid(),
|
|
||||||
Enabled = true,
|
|
||||||
};
|
|
||||||
|
|
||||||
var expectedPayload = new JsonObject
|
|
||||||
{
|
{
|
||||||
["UserId"] = null,
|
["UserId"] = null,
|
||||||
["OrganizationId"] = organization.Id,
|
["OrganizationId"] = organization.Id,
|
||||||
@ -768,26 +496,10 @@ public class RelayPushNotificationServiceTests
|
|||||||
["ClientType"] = null,
|
["ClientType"] = null,
|
||||||
["InstallationId"] = null,
|
["InstallationId"] = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
await VerifyNotificationAsync(
|
|
||||||
async sut => await sut.PushSyncOrganizationStatusAsync(organization),
|
|
||||||
expectedPayload
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
protected override JsonNode GetPushSyncOrganizationCollectionManagementSettingsResponsePayload(Organization organization)
|
||||||
[Fact]
|
|
||||||
public async Task PushSyncOrganizationCollectionManagementSettingsAsync_SendsExpectedResponse()
|
|
||||||
{
|
{
|
||||||
var organization = new Organization
|
return new JsonObject
|
||||||
{
|
|
||||||
Id = Guid.NewGuid(),
|
|
||||||
Enabled = true,
|
|
||||||
LimitCollectionCreation = true,
|
|
||||||
LimitCollectionDeletion = true,
|
|
||||||
LimitItemDeletion = true,
|
|
||||||
};
|
|
||||||
|
|
||||||
var expectedPayload = new JsonObject
|
|
||||||
{
|
{
|
||||||
["UserId"] = null,
|
["UserId"] = null,
|
||||||
["OrganizationId"] = organization.Id,
|
["OrganizationId"] = organization.Id,
|
||||||
@ -804,19 +516,11 @@ public class RelayPushNotificationServiceTests
|
|||||||
["ClientType"] = null,
|
["ClientType"] = null,
|
||||||
["InstallationId"] = null,
|
["InstallationId"] = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
await VerifyNotificationAsync(
|
|
||||||
async sut => await sut.PushSyncOrganizationCollectionManagementSettingsAsync(organization),
|
|
||||||
expectedPayload
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
protected override JsonNode GetPushPendingSecurityTasksResponsePayload(Guid userId)
|
||||||
public async Task PushPendingSecurityTasksAsync_SendsExpectedResponse()
|
|
||||||
{
|
{
|
||||||
var userId = Guid.NewGuid();
|
return new JsonObject
|
||||||
|
|
||||||
var expectedPayload = new JsonObject
|
|
||||||
{
|
{
|
||||||
["UserId"] = userId,
|
["UserId"] = userId,
|
||||||
["OrganizationId"] = null,
|
["OrganizationId"] = null,
|
||||||
@ -826,95 +530,10 @@ public class RelayPushNotificationServiceTests
|
|||||||
["Payload"] = new JsonObject
|
["Payload"] = new JsonObject
|
||||||
{
|
{
|
||||||
["UserId"] = userId,
|
["UserId"] = userId,
|
||||||
["Date"] = _fakeTimeProvider.GetUtcNow().UtcDateTime,
|
["Date"] = FakeTimeProvider.GetUtcNow().UtcDateTime,
|
||||||
},
|
},
|
||||||
["ClientType"] = null,
|
["ClientType"] = null,
|
||||||
["InstallationId"] = null,
|
["InstallationId"] = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
await VerifyNotificationAsync(
|
|
||||||
async sut => await sut.PushPendingSecurityTasksAsync(userId),
|
|
||||||
expectedPayload
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task SendPayloadToInstallationAsync_ThrowsNotImplementedException()
|
|
||||||
{
|
|
||||||
await Assert.ThrowsAsync<NotImplementedException>(
|
|
||||||
async () => await _sut.SendPayloadToInstallationAsync("installation_id", PushType.AuthRequest, new {}, null)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task SendPayloadToUserAsync_ThrowsNotImplementedException()
|
|
||||||
{
|
|
||||||
await Assert.ThrowsAsync<NotImplementedException>(
|
|
||||||
async () => await _sut.SendPayloadToUserAsync("user_id", PushType.AuthRequest, new {}, null)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task SendPayloadToOrganizationAsync_ThrowsNotImplementedException()
|
|
||||||
{
|
|
||||||
await Assert.ThrowsAsync<NotImplementedException>(
|
|
||||||
async () => await _sut.SendPayloadToOrganizationAsync("organization_id", PushType.AuthRequest, new {}, null)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task VerifyNotificationAsync(Func<RelayPushNotificationService, Task> test, JsonNode expectedRequestBody)
|
|
||||||
{
|
|
||||||
var httpContext = new DefaultHttpContext();
|
|
||||||
|
|
||||||
var serviceCollection = new ServiceCollection();
|
|
||||||
var currentContext = Substitute.For<ICurrentContext>();
|
|
||||||
currentContext.DeviceIdentifier = _deviceIdentifier;
|
|
||||||
serviceCollection.AddSingleton(currentContext);
|
|
||||||
|
|
||||||
httpContext.RequestServices = serviceCollection.BuildServiceProvider();
|
|
||||||
|
|
||||||
_httpContextAccessor.HttpContext
|
|
||||||
.Returns(httpContext);
|
|
||||||
|
|
||||||
_deviceRepository.GetByIdentifierAsync(_deviceIdentifier)
|
|
||||||
.Returns(new Device
|
|
||||||
{
|
|
||||||
Id = _deviceId,
|
|
||||||
});
|
|
||||||
|
|
||||||
var connectTokenRequest = _mockIdentityClient
|
|
||||||
.Expect(HttpMethod.Post, "https://localhost:8888/connect/token")
|
|
||||||
.Respond(HttpStatusCode.OK, JsonContent.Create(new
|
|
||||||
{
|
|
||||||
access_token = CreateAccessToken(DateTime.UtcNow.AddDays(1)),
|
|
||||||
}));
|
|
||||||
|
|
||||||
var pushSendRequest = _mockPushClient
|
|
||||||
.Expect(HttpMethod.Post, "https://localhost:7777/push/send")
|
|
||||||
.With(request =>
|
|
||||||
{
|
|
||||||
if (request.Content is not JsonContent jsonContent)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: What options?
|
|
||||||
var actualString = JsonSerializer.Serialize(jsonContent.Value);
|
|
||||||
var actualNode = JsonNode.Parse(actualString);
|
|
||||||
|
|
||||||
return JsonNode.DeepEquals(actualNode, expectedRequestBody);
|
|
||||||
})
|
|
||||||
.Respond(HttpStatusCode.OK);
|
|
||||||
|
|
||||||
await test(_sut);
|
|
||||||
|
|
||||||
Assert.Equal(1, _mockPushClient.GetMatchCount(pushSendRequest));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string CreateAccessToken(DateTime expirationTime)
|
|
||||||
{
|
|
||||||
var tokenHandler = new JwtSecurityTokenHandler();
|
|
||||||
var token = new JwtSecurityToken(expires: expirationTime);
|
|
||||||
return tokenHandler.WriteToken(token);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user