mirror of
https://github.com/bitwarden/server.git
synced 2025-07-01 16:12:49 -05:00
PM-10564: Push notification updates to other clients
When a notification is updated, marked as read or deleted, a push notification is sent with updated push type event. The push notification includes the ReadDate and DeletedDate fields.
This commit is contained in:
@ -1,4 +1,5 @@
|
||||
using System.Text.Json;
|
||||
#nullable enable
|
||||
using System.Text.Json;
|
||||
using Azure.Storage.Queues;
|
||||
using Bit.Core.Auth.Entities;
|
||||
using Bit.Core.Context;
|
||||
@ -41,7 +42,7 @@ public class AzureQueuePushNotificationService : IPushNotificationService
|
||||
await PushCipherAsync(cipher, PushType.SyncLoginDelete, null);
|
||||
}
|
||||
|
||||
private async Task PushCipherAsync(Cipher cipher, PushType type, IEnumerable<Guid> collectionIds)
|
||||
private async Task PushCipherAsync(Cipher cipher, PushType type, IEnumerable<Guid>? collectionIds)
|
||||
{
|
||||
if (cipher.OrganizationId.HasValue)
|
||||
{
|
||||
@ -164,7 +165,7 @@ public class AzureQueuePushNotificationService : IPushNotificationService
|
||||
await PushSendAsync(send, PushType.SyncSendDelete);
|
||||
}
|
||||
|
||||
public async Task PushSyncNotificationAsync(Notification notification)
|
||||
public async Task PushSyncNotificationCreateAsync(Notification notification, NotificationStatus? notificationStatus)
|
||||
{
|
||||
var message = new SyncNotificationPushNotification
|
||||
{
|
||||
@ -172,10 +173,28 @@ public class AzureQueuePushNotificationService : IPushNotificationService
|
||||
UserId = notification.UserId,
|
||||
OrganizationId = notification.OrganizationId,
|
||||
ClientType = notification.ClientType,
|
||||
RevisionDate = notification.RevisionDate
|
||||
RevisionDate = notification.RevisionDate,
|
||||
ReadDate = notificationStatus?.ReadDate,
|
||||
DeletedDate = notificationStatus?.DeletedDate
|
||||
};
|
||||
|
||||
await SendMessageAsync(PushType.SyncNotification, message, true);
|
||||
await SendMessageAsync(PushType.SyncNotificationCreate, message, true);
|
||||
}
|
||||
|
||||
public async Task PushSyncNotificationUpdateAsync(Notification notification, NotificationStatus? notificationStatus)
|
||||
{
|
||||
var message = new SyncNotificationPushNotification
|
||||
{
|
||||
Id = notification.Id,
|
||||
UserId = notification.UserId,
|
||||
OrganizationId = notification.OrganizationId,
|
||||
ClientType = notification.ClientType,
|
||||
RevisionDate = notification.RevisionDate,
|
||||
ReadDate = notificationStatus?.ReadDate,
|
||||
DeletedDate = notificationStatus?.DeletedDate
|
||||
};
|
||||
|
||||
await SendMessageAsync(PushType.SyncNotificationUpdate, message, true);
|
||||
}
|
||||
|
||||
private async Task PushSendAsync(Send send, PushType type)
|
||||
@ -201,7 +220,7 @@ public class AzureQueuePushNotificationService : IPushNotificationService
|
||||
await _queueClient.SendMessageAsync(message);
|
||||
}
|
||||
|
||||
private string GetContextIdentifier(bool excludeCurrentContext)
|
||||
private string? GetContextIdentifier(bool excludeCurrentContext)
|
||||
{
|
||||
if (!excludeCurrentContext)
|
||||
{
|
||||
@ -214,14 +233,14 @@ public class AzureQueuePushNotificationService : IPushNotificationService
|
||||
}
|
||||
|
||||
public Task SendPayloadToUserAsync(string userId, PushType type, object payload, string identifier,
|
||||
string deviceId = null, ClientType? clientType = null)
|
||||
string? deviceId = null, ClientType? clientType = null)
|
||||
{
|
||||
// Noop
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task SendPayloadToOrganizationAsync(string orgId, PushType type, object payload, string identifier,
|
||||
string deviceId = null, ClientType? clientType = null)
|
||||
string? deviceId = null, ClientType? clientType = null)
|
||||
{
|
||||
// Noop
|
||||
return Task.FromResult(0);
|
||||
|
@ -1,4 +1,5 @@
|
||||
using Bit.Core.Auth.Entities;
|
||||
#nullable enable
|
||||
using Bit.Core.Auth.Entities;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.NotificationCenter.Entities;
|
||||
using Bit.Core.Settings;
|
||||
@ -11,7 +12,7 @@ namespace Bit.Core.Services;
|
||||
|
||||
public class MultiServicePushNotificationService : IPushNotificationService
|
||||
{
|
||||
private readonly IEnumerable<IPushNotificationService> _services;
|
||||
private readonly IEnumerable<IPushNotificationService>? _services;
|
||||
private readonly ILogger<MultiServicePushNotificationService> _logger;
|
||||
|
||||
public MultiServicePushNotificationService(
|
||||
@ -23,7 +24,7 @@ public class MultiServicePushNotificationService : IPushNotificationService
|
||||
|
||||
_logger = logger;
|
||||
_logger.LogInformation("Hub services: {Services}", _services.Count());
|
||||
globalSettings?.NotificationHubPool?.NotificationHubs?.ForEach(hub =>
|
||||
globalSettings.NotificationHubPool?.NotificationHubs?.ForEach(hub =>
|
||||
{
|
||||
_logger.LogInformation("HubName: {HubName}, EnableSendTracing: {EnableSendTracing}, RegistrationStartDate: {RegistrationStartDate}, RegistrationEndDate: {RegistrationEndDate}", hub.HubName, hub.EnableSendTracing, hub.RegistrationStartDate, hub.RegistrationEndDate);
|
||||
});
|
||||
@ -132,33 +133,43 @@ public class MultiServicePushNotificationService : IPushNotificationService
|
||||
}
|
||||
|
||||
public Task SendPayloadToUserAsync(string userId, PushType type, object payload, string identifier,
|
||||
string deviceId = null, ClientType? clientType = null)
|
||||
string? deviceId = null, ClientType? clientType = null)
|
||||
{
|
||||
PushToServices((s) => s.SendPayloadToUserAsync(userId, type, payload, identifier, deviceId, clientType));
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task SendPayloadToOrganizationAsync(string orgId, PushType type, object payload, string identifier,
|
||||
string deviceId = null, ClientType? clientType = null)
|
||||
string? deviceId = null, ClientType? clientType = null)
|
||||
{
|
||||
PushToServices((s) => s.SendPayloadToOrganizationAsync(orgId, type, payload, identifier, deviceId, clientType));
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task PushSyncNotificationAsync(Notification notification)
|
||||
public Task PushSyncNotificationCreateAsync(Notification notification, NotificationStatus? notificationStatus)
|
||||
{
|
||||
PushToServices((s) => s.PushSyncNotificationAsync(notification));
|
||||
PushToServices((s) => s.PushSyncNotificationCreateAsync(notification, notificationStatus));
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task PushSyncNotificationUpdateAsync(Notification notification, NotificationStatus? notificationStatus)
|
||||
{
|
||||
PushToServices((s) => s.PushSyncNotificationUpdateAsync(notification, notificationStatus));
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private void PushToServices(Func<IPushNotificationService, Task> pushFunc)
|
||||
{
|
||||
if (_services != null)
|
||||
if (_services == null)
|
||||
{
|
||||
foreach (var service in _services)
|
||||
{
|
||||
pushFunc(service);
|
||||
}
|
||||
_logger.LogWarning("No services found to push notification");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var service in _services)
|
||||
{
|
||||
_logger.LogDebug("Pushing notification to service {}", service.GetType().Name);
|
||||
pushFunc(service);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
using Bit.Core.Auth.Entities;
|
||||
#nullable enable
|
||||
using Bit.Core.Auth.Entities;
|
||||
using Bit.Core.Context;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Models;
|
||||
@ -13,7 +14,6 @@ namespace Bit.Core.Services;
|
||||
|
||||
public class NotificationsApiPushNotificationService : BaseIdentityClientService, IPushNotificationService
|
||||
{
|
||||
private readonly GlobalSettings _globalSettings;
|
||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||
|
||||
public NotificationsApiPushNotificationService(
|
||||
@ -30,7 +30,6 @@ public class NotificationsApiPushNotificationService : BaseIdentityClientService
|
||||
globalSettings.InternalIdentityKey,
|
||||
logger)
|
||||
{
|
||||
_globalSettings = globalSettings;
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
}
|
||||
|
||||
@ -49,7 +48,7 @@ public class NotificationsApiPushNotificationService : BaseIdentityClientService
|
||||
await PushCipherAsync(cipher, PushType.SyncLoginDelete, null);
|
||||
}
|
||||
|
||||
private async Task PushCipherAsync(Cipher cipher, PushType type, IEnumerable<Guid> collectionIds)
|
||||
private async Task PushCipherAsync(Cipher cipher, PushType type, IEnumerable<Guid>? collectionIds)
|
||||
{
|
||||
if (cipher.OrganizationId.HasValue)
|
||||
{
|
||||
@ -173,7 +172,7 @@ public class NotificationsApiPushNotificationService : BaseIdentityClientService
|
||||
await PushSendAsync(send, PushType.SyncSendDelete);
|
||||
}
|
||||
|
||||
public async Task PushSyncNotificationAsync(Notification notification)
|
||||
public async Task PushSyncNotificationCreateAsync(Notification notification, NotificationStatus? notificationStatus)
|
||||
{
|
||||
var message = new SyncNotificationPushNotification
|
||||
{
|
||||
@ -181,10 +180,28 @@ public class NotificationsApiPushNotificationService : BaseIdentityClientService
|
||||
UserId = notification.UserId,
|
||||
OrganizationId = notification.OrganizationId,
|
||||
ClientType = notification.ClientType,
|
||||
RevisionDate = notification.RevisionDate
|
||||
RevisionDate = notification.RevisionDate,
|
||||
ReadDate = notificationStatus?.ReadDate,
|
||||
DeletedDate = notificationStatus?.DeletedDate
|
||||
};
|
||||
|
||||
await SendMessageAsync(PushType.SyncNotification, message, true);
|
||||
await SendMessageAsync(PushType.SyncNotificationCreate, message, true);
|
||||
}
|
||||
|
||||
public async Task PushSyncNotificationUpdateAsync(Notification notification, NotificationStatus? notificationStatus)
|
||||
{
|
||||
var message = new SyncNotificationPushNotification
|
||||
{
|
||||
Id = notification.Id,
|
||||
UserId = notification.UserId,
|
||||
OrganizationId = notification.OrganizationId,
|
||||
ClientType = notification.ClientType,
|
||||
RevisionDate = notification.RevisionDate,
|
||||
ReadDate = notificationStatus?.ReadDate,
|
||||
DeletedDate = notificationStatus?.DeletedDate
|
||||
};
|
||||
|
||||
await SendMessageAsync(PushType.SyncNotificationUpdate, message, true);
|
||||
}
|
||||
|
||||
private async Task PushSendAsync(Send send, PushType type)
|
||||
@ -209,7 +226,7 @@ public class NotificationsApiPushNotificationService : BaseIdentityClientService
|
||||
await SendAsync(HttpMethod.Post, "send", request);
|
||||
}
|
||||
|
||||
private string GetContextIdentifier(bool excludeCurrentContext)
|
||||
private string? GetContextIdentifier(bool excludeCurrentContext)
|
||||
{
|
||||
if (!excludeCurrentContext)
|
||||
{
|
||||
@ -217,19 +234,19 @@ public class NotificationsApiPushNotificationService : BaseIdentityClientService
|
||||
}
|
||||
|
||||
var currentContext =
|
||||
_httpContextAccessor?.HttpContext?.RequestServices.GetService(typeof(ICurrentContext)) as ICurrentContext;
|
||||
_httpContextAccessor.HttpContext?.RequestServices.GetService(typeof(ICurrentContext)) as ICurrentContext;
|
||||
return currentContext?.DeviceIdentifier;
|
||||
}
|
||||
|
||||
public Task SendPayloadToUserAsync(string userId, PushType type, object payload, string identifier,
|
||||
string deviceId = null, ClientType? clientType = null)
|
||||
string? deviceId = null, ClientType? clientType = null)
|
||||
{
|
||||
// Noop
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task SendPayloadToOrganizationAsync(string orgId, PushType type, object payload, string identifier,
|
||||
string deviceId = null, ClientType? clientType = null)
|
||||
string? deviceId = null, ClientType? clientType = null)
|
||||
{
|
||||
// Noop
|
||||
return Task.FromResult(0);
|
||||
|
@ -1,4 +1,5 @@
|
||||
using Bit.Core.Auth.Entities;
|
||||
#nullable enable
|
||||
using Bit.Core.Auth.Entities;
|
||||
using Bit.Core.Context;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.IdentityServer;
|
||||
@ -53,7 +54,7 @@ public class RelayPushNotificationService : BaseIdentityClientService, IPushNoti
|
||||
await PushCipherAsync(cipher, PushType.SyncLoginDelete, null);
|
||||
}
|
||||
|
||||
private async Task PushCipherAsync(Cipher cipher, PushType type, IEnumerable<Guid> collectionIds)
|
||||
private async Task PushCipherAsync(Cipher cipher, PushType type, IEnumerable<Guid>? collectionIds)
|
||||
{
|
||||
if (cipher.OrganizationId.HasValue)
|
||||
{
|
||||
@ -189,7 +190,7 @@ public class RelayPushNotificationService : BaseIdentityClientService, IPushNoti
|
||||
await SendPayloadToUserAsync(authRequest.UserId, type, message, true);
|
||||
}
|
||||
|
||||
public async Task PushSyncNotificationAsync(Notification notification)
|
||||
public async Task PushSyncNotificationCreateAsync(Notification notification, NotificationStatus? notificationStatus)
|
||||
{
|
||||
var message = new SyncNotificationPushNotification
|
||||
{
|
||||
@ -197,17 +198,44 @@ public class RelayPushNotificationService : BaseIdentityClientService, IPushNoti
|
||||
UserId = notification.UserId,
|
||||
OrganizationId = notification.OrganizationId,
|
||||
ClientType = notification.ClientType,
|
||||
RevisionDate = notification.RevisionDate
|
||||
RevisionDate = notification.RevisionDate,
|
||||
ReadDate = notificationStatus?.ReadDate,
|
||||
DeletedDate = notificationStatus?.DeletedDate
|
||||
};
|
||||
|
||||
if (notification.UserId.HasValue)
|
||||
{
|
||||
await SendPayloadToUserAsync(notification.UserId.Value, PushType.SyncNotification, message, true,
|
||||
await SendPayloadToUserAsync(notification.UserId.Value, PushType.SyncNotificationCreate, message, true,
|
||||
notification.ClientType);
|
||||
}
|
||||
else if (notification.OrganizationId.HasValue)
|
||||
{
|
||||
await SendPayloadToOrganizationAsync(notification.OrganizationId.Value, PushType.SyncNotification, message,
|
||||
await SendPayloadToOrganizationAsync(notification.OrganizationId.Value, PushType.SyncNotificationCreate, message,
|
||||
true, notification.ClientType);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task PushSyncNotificationUpdateAsync(Notification notification, NotificationStatus? notificationStatus)
|
||||
{
|
||||
var message = new SyncNotificationPushNotification
|
||||
{
|
||||
Id = notification.Id,
|
||||
UserId = notification.UserId,
|
||||
OrganizationId = notification.OrganizationId,
|
||||
ClientType = notification.ClientType,
|
||||
RevisionDate = notification.RevisionDate,
|
||||
ReadDate = notificationStatus?.ReadDate,
|
||||
DeletedDate = notificationStatus?.DeletedDate
|
||||
};
|
||||
|
||||
if (notification.UserId.HasValue)
|
||||
{
|
||||
await SendPayloadToUserAsync(notification.UserId.Value, PushType.SyncNotificationUpdate, message, true,
|
||||
notification.ClientType);
|
||||
}
|
||||
else if (notification.OrganizationId.HasValue)
|
||||
{
|
||||
await SendPayloadToOrganizationAsync(notification.OrganizationId.Value, PushType.SyncNotificationUpdate, message,
|
||||
true, notification.ClientType);
|
||||
}
|
||||
}
|
||||
@ -245,7 +273,7 @@ public class RelayPushNotificationService : BaseIdentityClientService, IPushNoti
|
||||
private async Task AddCurrentContextAsync(PushSendRequestModel request, bool addIdentifier)
|
||||
{
|
||||
var currentContext =
|
||||
_httpContextAccessor?.HttpContext?.RequestServices.GetService(typeof(ICurrentContext)) as ICurrentContext;
|
||||
_httpContextAccessor.HttpContext?.RequestServices.GetService(typeof(ICurrentContext)) as ICurrentContext;
|
||||
if (!string.IsNullOrWhiteSpace(currentContext?.DeviceIdentifier))
|
||||
{
|
||||
var device = await _deviceRepository.GetByIdentifierAsync(currentContext.DeviceIdentifier);
|
||||
@ -262,13 +290,13 @@ public class RelayPushNotificationService : BaseIdentityClientService, IPushNoti
|
||||
}
|
||||
|
||||
public Task SendPayloadToUserAsync(string userId, PushType type, object payload, string identifier,
|
||||
string deviceId = null, ClientType? clientType = null)
|
||||
string? deviceId = null, ClientType? clientType = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task SendPayloadToOrganizationAsync(string orgId, PushType type, object payload, string identifier,
|
||||
string deviceId = null, ClientType? clientType = null)
|
||||
string? deviceId = null, ClientType? clientType = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
Reference in New Issue
Block a user