mirror of
https://github.com/bitwarden/server.git
synced 2025-07-02 00:22:50 -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:
@ -26,5 +26,6 @@ public enum PushType : byte
|
||||
|
||||
SyncOrganizations = 17,
|
||||
|
||||
SyncNotification = 18,
|
||||
SyncNotificationCreate = 18,
|
||||
SyncNotificationUpdate = 19
|
||||
}
|
||||
|
@ -1,10 +1,11 @@
|
||||
using Bit.Core.Enums;
|
||||
#nullable enable
|
||||
using Bit.Core.Enums;
|
||||
|
||||
namespace Bit.Core.Models;
|
||||
|
||||
public class PushNotificationData<T>
|
||||
{
|
||||
public PushNotificationData(PushType type, T payload, string contextId)
|
||||
public PushNotificationData(PushType type, T payload, string? contextId)
|
||||
{
|
||||
Type = type;
|
||||
Payload = payload;
|
||||
@ -13,7 +14,7 @@ public class PushNotificationData<T>
|
||||
|
||||
public PushType Type { get; set; }
|
||||
public T Payload { get; set; }
|
||||
public string ContextId { get; set; }
|
||||
public string? ContextId { get; set; }
|
||||
}
|
||||
|
||||
public class SyncCipherPushNotification
|
||||
@ -21,7 +22,7 @@ public class SyncCipherPushNotification
|
||||
public Guid Id { get; set; }
|
||||
public Guid? UserId { get; set; }
|
||||
public Guid? OrganizationId { get; set; }
|
||||
public IEnumerable<Guid> CollectionIds { get; set; }
|
||||
public IEnumerable<Guid>? CollectionIds { get; set; }
|
||||
public DateTime RevisionDate { get; set; }
|
||||
}
|
||||
|
||||
@ -52,6 +53,8 @@ public class SyncNotificationPushNotification
|
||||
public Guid? OrganizationId { get; set; }
|
||||
public ClientType ClientType { get; set; }
|
||||
public DateTime RevisionDate { get; set; }
|
||||
public DateTime? ReadDate { get; set; }
|
||||
public DateTime? DeletedDate { get; set; }
|
||||
}
|
||||
|
||||
public class AuthRequestPushNotification
|
||||
|
@ -37,7 +37,7 @@ public class CreateNotificationCommand : ICreateNotificationCommand
|
||||
|
||||
var newNotification = await _notificationRepository.CreateAsync(notification);
|
||||
|
||||
await _pushNotificationService.PushSyncNotificationAsync(newNotification);
|
||||
await _pushNotificationService.PushSyncNotificationCreateAsync(newNotification, null);
|
||||
|
||||
return newNotification;
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ using Bit.Core.NotificationCenter.Authorization;
|
||||
using Bit.Core.NotificationCenter.Commands.Interfaces;
|
||||
using Bit.Core.NotificationCenter.Entities;
|
||||
using Bit.Core.NotificationCenter.Repositories;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Utilities;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
|
||||
@ -16,16 +17,19 @@ public class CreateNotificationStatusCommand : ICreateNotificationStatusCommand
|
||||
private readonly IAuthorizationService _authorizationService;
|
||||
private readonly INotificationRepository _notificationRepository;
|
||||
private readonly INotificationStatusRepository _notificationStatusRepository;
|
||||
private readonly IPushNotificationService _pushNotificationService;
|
||||
|
||||
public CreateNotificationStatusCommand(ICurrentContext currentContext,
|
||||
IAuthorizationService authorizationService,
|
||||
INotificationRepository notificationRepository,
|
||||
INotificationStatusRepository notificationStatusRepository)
|
||||
INotificationStatusRepository notificationStatusRepository,
|
||||
IPushNotificationService pushNotificationService)
|
||||
{
|
||||
_currentContext = currentContext;
|
||||
_authorizationService = authorizationService;
|
||||
_notificationRepository = notificationRepository;
|
||||
_notificationStatusRepository = notificationStatusRepository;
|
||||
_pushNotificationService = pushNotificationService;
|
||||
}
|
||||
|
||||
public async Task<NotificationStatus> CreateAsync(NotificationStatus notificationStatus)
|
||||
@ -42,6 +46,10 @@ public class CreateNotificationStatusCommand : ICreateNotificationStatusCommand
|
||||
await _authorizationService.AuthorizeOrThrowAsync(_currentContext.HttpContext.User, notificationStatus,
|
||||
NotificationStatusOperations.Create);
|
||||
|
||||
return await _notificationStatusRepository.CreateAsync(notificationStatus);
|
||||
var newNotificationStatus = await _notificationStatusRepository.CreateAsync(notificationStatus);
|
||||
|
||||
await _pushNotificationService.PushSyncNotificationCreateAsync(notification, newNotificationStatus);
|
||||
|
||||
return newNotificationStatus;
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ using Bit.Core.NotificationCenter.Authorization;
|
||||
using Bit.Core.NotificationCenter.Commands.Interfaces;
|
||||
using Bit.Core.NotificationCenter.Entities;
|
||||
using Bit.Core.NotificationCenter.Repositories;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Utilities;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
|
||||
@ -16,16 +17,19 @@ public class MarkNotificationDeletedCommand : IMarkNotificationDeletedCommand
|
||||
private readonly IAuthorizationService _authorizationService;
|
||||
private readonly INotificationRepository _notificationRepository;
|
||||
private readonly INotificationStatusRepository _notificationStatusRepository;
|
||||
private readonly IPushNotificationService _pushNotificationService;
|
||||
|
||||
public MarkNotificationDeletedCommand(ICurrentContext currentContext,
|
||||
IAuthorizationService authorizationService,
|
||||
INotificationRepository notificationRepository,
|
||||
INotificationStatusRepository notificationStatusRepository)
|
||||
INotificationStatusRepository notificationStatusRepository,
|
||||
IPushNotificationService pushNotificationService)
|
||||
{
|
||||
_currentContext = currentContext;
|
||||
_authorizationService = authorizationService;
|
||||
_notificationRepository = notificationRepository;
|
||||
_notificationStatusRepository = notificationStatusRepository;
|
||||
_pushNotificationService = pushNotificationService;
|
||||
}
|
||||
|
||||
public async Task MarkDeletedAsync(Guid notificationId)
|
||||
@ -59,7 +63,9 @@ public class MarkNotificationDeletedCommand : IMarkNotificationDeletedCommand
|
||||
await _authorizationService.AuthorizeOrThrowAsync(_currentContext.HttpContext.User, notificationStatus,
|
||||
NotificationStatusOperations.Create);
|
||||
|
||||
await _notificationStatusRepository.CreateAsync(notificationStatus);
|
||||
var newNotificationStatus = await _notificationStatusRepository.CreateAsync(notificationStatus);
|
||||
|
||||
await _pushNotificationService.PushSyncNotificationCreateAsync(notification, newNotificationStatus);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -69,6 +75,8 @@ public class MarkNotificationDeletedCommand : IMarkNotificationDeletedCommand
|
||||
notificationStatus.DeletedDate = DateTime.UtcNow;
|
||||
|
||||
await _notificationStatusRepository.UpdateAsync(notificationStatus);
|
||||
|
||||
await _pushNotificationService.PushSyncNotificationCreateAsync(notification, notificationStatus);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ using Bit.Core.NotificationCenter.Authorization;
|
||||
using Bit.Core.NotificationCenter.Commands.Interfaces;
|
||||
using Bit.Core.NotificationCenter.Entities;
|
||||
using Bit.Core.NotificationCenter.Repositories;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Utilities;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
|
||||
@ -16,16 +17,19 @@ public class MarkNotificationReadCommand : IMarkNotificationReadCommand
|
||||
private readonly IAuthorizationService _authorizationService;
|
||||
private readonly INotificationRepository _notificationRepository;
|
||||
private readonly INotificationStatusRepository _notificationStatusRepository;
|
||||
private readonly IPushNotificationService _pushNotificationService;
|
||||
|
||||
public MarkNotificationReadCommand(ICurrentContext currentContext,
|
||||
IAuthorizationService authorizationService,
|
||||
INotificationRepository notificationRepository,
|
||||
INotificationStatusRepository notificationStatusRepository)
|
||||
INotificationStatusRepository notificationStatusRepository,
|
||||
IPushNotificationService pushNotificationService)
|
||||
{
|
||||
_currentContext = currentContext;
|
||||
_authorizationService = authorizationService;
|
||||
_notificationRepository = notificationRepository;
|
||||
_notificationStatusRepository = notificationStatusRepository;
|
||||
_pushNotificationService = pushNotificationService;
|
||||
}
|
||||
|
||||
public async Task MarkReadAsync(Guid notificationId)
|
||||
@ -59,7 +63,9 @@ public class MarkNotificationReadCommand : IMarkNotificationReadCommand
|
||||
await _authorizationService.AuthorizeOrThrowAsync(_currentContext.HttpContext.User, notificationStatus,
|
||||
NotificationStatusOperations.Create);
|
||||
|
||||
await _notificationStatusRepository.CreateAsync(notificationStatus);
|
||||
var newNotificationStatus = await _notificationStatusRepository.CreateAsync(notificationStatus);
|
||||
|
||||
await _pushNotificationService.PushSyncNotificationCreateAsync(notification, newNotificationStatus);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -69,6 +75,8 @@ public class MarkNotificationReadCommand : IMarkNotificationReadCommand
|
||||
notificationStatus.ReadDate = DateTime.UtcNow;
|
||||
|
||||
await _notificationStatusRepository.UpdateAsync(notificationStatus);
|
||||
|
||||
await _pushNotificationService.PushSyncNotificationCreateAsync(notification, notificationStatus);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ using Bit.Core.NotificationCenter.Authorization;
|
||||
using Bit.Core.NotificationCenter.Commands.Interfaces;
|
||||
using Bit.Core.NotificationCenter.Entities;
|
||||
using Bit.Core.NotificationCenter.Repositories;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Utilities;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
|
||||
@ -15,14 +16,17 @@ public class UpdateNotificationCommand : IUpdateNotificationCommand
|
||||
private readonly ICurrentContext _currentContext;
|
||||
private readonly IAuthorizationService _authorizationService;
|
||||
private readonly INotificationRepository _notificationRepository;
|
||||
private readonly IPushNotificationService _pushNotificationService;
|
||||
|
||||
public UpdateNotificationCommand(ICurrentContext currentContext,
|
||||
IAuthorizationService authorizationService,
|
||||
INotificationRepository notificationRepository)
|
||||
INotificationRepository notificationRepository,
|
||||
IPushNotificationService pushNotificationService)
|
||||
{
|
||||
_currentContext = currentContext;
|
||||
_authorizationService = authorizationService;
|
||||
_notificationRepository = notificationRepository;
|
||||
_pushNotificationService = pushNotificationService;
|
||||
}
|
||||
|
||||
public async Task UpdateAsync(Notification notificationToUpdate)
|
||||
@ -43,5 +47,7 @@ public class UpdateNotificationCommand : IUpdateNotificationCommand
|
||||
notification.RevisionDate = DateTime.UtcNow;
|
||||
|
||||
await _notificationRepository.ReplaceAsync(notification);
|
||||
|
||||
await _pushNotificationService.PushSyncNotificationCreateAsync(notification, null);
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,12 @@
|
||||
using System.Text.Json;
|
||||
#nullable enable
|
||||
using System.Text.Json;
|
||||
using System.Text.RegularExpressions;
|
||||
using Bit.Core.Auth.Entities;
|
||||
using Bit.Core.Context;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Models;
|
||||
using Bit.Core.Models.Data;
|
||||
using Bit.Core.NotificationCenter.Entities;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Tools.Entities;
|
||||
@ -50,7 +52,7 @@ public class NotificationHubPushNotificationService : 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)
|
||||
{
|
||||
@ -180,7 +182,7 @@ public class NotificationHubPushNotificationService : IPushNotificationService
|
||||
await PushAuthRequestAsync(authRequest, PushType.AuthRequestResponse);
|
||||
}
|
||||
|
||||
public async Task PushSyncNotificationAsync(Notification notification)
|
||||
public async Task PushSyncNotificationCreateAsync(Notification notification, NotificationStatus? notificationStatus)
|
||||
{
|
||||
var message = new SyncNotificationPushNotification
|
||||
{
|
||||
@ -188,17 +190,44 @@ public class NotificationHubPushNotificationService : IPushNotificationService
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -224,8 +253,8 @@ public class NotificationHubPushNotificationService : IPushNotificationService
|
||||
GetContextIdentifier(excludeCurrentContext), clientType: clientType);
|
||||
}
|
||||
|
||||
public async Task SendPayloadToUserAsync(string userId, PushType type, object payload, string identifier,
|
||||
string deviceId = null, ClientType? clientType = null)
|
||||
public async Task SendPayloadToUserAsync(string userId, PushType type, object payload, string? identifier,
|
||||
string? deviceId = null, ClientType? clientType = null)
|
||||
{
|
||||
var tag = BuildTag($"template:payload_userId:{SanitizeTagInput(userId)}", identifier, clientType);
|
||||
await SendPayloadAsync(tag, type, payload);
|
||||
@ -235,8 +264,8 @@ public class NotificationHubPushNotificationService : IPushNotificationService
|
||||
}
|
||||
}
|
||||
|
||||
public async Task SendPayloadToOrganizationAsync(string orgId, PushType type, object payload, string identifier,
|
||||
string deviceId = null, ClientType? clientType = null)
|
||||
public async Task SendPayloadToOrganizationAsync(string orgId, PushType type, object payload, string? identifier,
|
||||
string? deviceId = null, ClientType? clientType = null)
|
||||
{
|
||||
var tag = BuildTag($"template:payload && organizationId:{SanitizeTagInput(orgId)}", identifier, clientType);
|
||||
await SendPayloadAsync(tag, type, payload);
|
||||
@ -246,7 +275,7 @@ public class NotificationHubPushNotificationService : IPushNotificationService
|
||||
}
|
||||
}
|
||||
|
||||
private string GetContextIdentifier(bool excludeCurrentContext)
|
||||
private string? GetContextIdentifier(bool excludeCurrentContext)
|
||||
{
|
||||
if (!excludeCurrentContext)
|
||||
{
|
||||
@ -254,11 +283,11 @@ public class NotificationHubPushNotificationService : IPushNotificationService
|
||||
}
|
||||
|
||||
var currentContext =
|
||||
_httpContextAccessor?.HttpContext?.RequestServices.GetService(typeof(ICurrentContext)) as ICurrentContext;
|
||||
_httpContextAccessor.HttpContext?.RequestServices.GetService(typeof(ICurrentContext)) as ICurrentContext;
|
||||
return currentContext?.DeviceIdentifier;
|
||||
}
|
||||
|
||||
private string BuildTag(string tag, string identifier, ClientType? clientType)
|
||||
private string BuildTag(string tag, string? identifier, ClientType? clientType)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(identifier))
|
||||
{
|
||||
|
@ -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.Tools.Entities;
|
||||
@ -23,13 +24,14 @@ public interface IPushNotificationService
|
||||
Task PushSyncSendCreateAsync(Send send);
|
||||
Task PushSyncSendUpdateAsync(Send send);
|
||||
Task PushSyncSendDeleteAsync(Send send);
|
||||
Task PushSyncNotificationAsync(Notification notification);
|
||||
Task PushSyncNotificationCreateAsync(Notification notification, NotificationStatus? notificationStatus);
|
||||
Task PushSyncNotificationUpdateAsync(Notification notification, NotificationStatus? notificationStatus);
|
||||
Task PushAuthRequestAsync(AuthRequest authRequest);
|
||||
Task PushAuthRequestResponseAsync(AuthRequest authRequest);
|
||||
|
||||
Task SendPayloadToUserAsync(string userId, PushType type, object payload, string identifier,
|
||||
string deviceId = null, ClientType? clientType = null);
|
||||
string? deviceId = null, ClientType? clientType = null);
|
||||
|
||||
Task SendPayloadToOrganizationAsync(string orgId, PushType type, object payload, string identifier,
|
||||
string deviceId = null, ClientType? clientType = null);
|
||||
string? deviceId = null, ClientType? clientType = null);
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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.Tools.Entities;
|
||||
@ -84,7 +85,7 @@ public class NoopPushNotificationService : IPushNotificationService
|
||||
}
|
||||
|
||||
public Task SendPayloadToOrganizationAsync(string orgId, PushType type, object payload, string identifier,
|
||||
string deviceId = null, ClientType? clientType = null)
|
||||
string? deviceId = null, ClientType? clientType = null)
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
@ -100,10 +101,12 @@ public class NoopPushNotificationService : IPushNotificationService
|
||||
}
|
||||
|
||||
public Task SendPayloadToUserAsync(string userId, PushType type, object payload, string identifier,
|
||||
string deviceId = null, ClientType? clientType = null)
|
||||
string? deviceId = null, ClientType? clientType = null)
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task PushSyncNotificationAsync(Notification notification) => Task.CompletedTask;
|
||||
public Task PushSyncNotificationCreateAsync(Notification notification, NotificationStatus? notificationStatus) => Task.CompletedTask;
|
||||
|
||||
public Task PushSyncNotificationUpdateAsync(Notification notification, NotificationStatus? notificationStatus) => Task.CompletedTask;
|
||||
}
|
||||
|
@ -89,7 +89,8 @@ public static class HubHelpers
|
||||
await hubContext.Clients.User(authRequestNotification.Payload.UserId.ToString())
|
||||
.SendAsync(_receiveMessageMethod, authRequestNotification, cancellationToken);
|
||||
break;
|
||||
case PushType.SyncNotification:
|
||||
case PushType.SyncNotificationCreate:
|
||||
case PushType.SyncNotificationUpdate:
|
||||
var syncNotification =
|
||||
JsonSerializer.Deserialize<PushNotificationData<SyncNotificationPushNotification>>(
|
||||
notificationJson, _deserializerOptions);
|
||||
|
Reference in New Issue
Block a user