1
0
mirror of https://github.com/bitwarden/server synced 2025-12-18 01:03:17 +00:00

[PM-18555] Main part of notifications refactor (#5757)

* More tests

* More  tests

* Add non-guid tests

* Introduce slimmer services

* Implement IPushEngine on services

* Implement IPushEngine

* Fix tests

* Format

* Switch to `Guid` on `PushSendRequestModel`

* Remove TODOs
This commit is contained in:
Justin Baur
2025-06-17 13:30:56 -04:00
committed by GitHub
parent 6dc26f4be6
commit 6800bc57f3
23 changed files with 1271 additions and 2408 deletions

View File

@@ -1,8 +1,11 @@
using Bit.Core.Context;
using System.Diagnostics;
using System.Text.Json;
using Bit.Core.Context;
using Bit.Core.Exceptions;
using Bit.Core.Models.Api;
using Bit.Core.NotificationHub;
using Bit.Core.Platform.Push;
using Bit.Core.Platform.Push.Internal;
using Bit.Core.Settings;
using Bit.Core.Utilities;
using Microsoft.AspNetCore.Authorization;
@@ -20,14 +23,14 @@ namespace Bit.Api.Platform.Push;
public class PushController : Controller
{
private readonly IPushRegistrationService _pushRegistrationService;
private readonly IPushNotificationService _pushNotificationService;
private readonly IPushRelayer _pushRelayer;
private readonly IWebHostEnvironment _environment;
private readonly ICurrentContext _currentContext;
private readonly IGlobalSettings _globalSettings;
public PushController(
IPushRegistrationService pushRegistrationService,
IPushNotificationService pushNotificationService,
IPushRelayer pushRelayer,
IWebHostEnvironment environment,
ICurrentContext currentContext,
IGlobalSettings globalSettings)
@@ -35,7 +38,7 @@ public class PushController : Controller
_currentContext = currentContext;
_environment = environment;
_pushRegistrationService = pushRegistrationService;
_pushNotificationService = pushNotificationService;
_pushRelayer = pushRelayer;
_globalSettings = globalSettings;
}
@@ -74,31 +77,50 @@ public class PushController : Controller
}
[HttpPost("send")]
public async Task SendAsync([FromBody] PushSendRequestModel model)
public async Task SendAsync([FromBody] PushSendRequestModel<JsonElement> model)
{
CheckUsage();
if (!string.IsNullOrWhiteSpace(model.InstallationId))
NotificationTarget target;
Guid targetId;
if (model.InstallationId.HasValue)
{
if (_currentContext.InstallationId!.Value.ToString() != model.InstallationId!)
if (_currentContext.InstallationId!.Value != model.InstallationId.Value)
{
throw new BadRequestException("InstallationId does not match current context.");
}
await _pushNotificationService.SendPayloadToInstallationAsync(
_currentContext.InstallationId.Value.ToString(), model.Type, model.Payload, Prefix(model.Identifier),
Prefix(model.DeviceId), model.ClientType);
target = NotificationTarget.Installation;
targetId = _currentContext.InstallationId.Value;
}
else if (!string.IsNullOrWhiteSpace(model.UserId))
else if (model.UserId.HasValue)
{
await _pushNotificationService.SendPayloadToUserAsync(Prefix(model.UserId),
model.Type, model.Payload, Prefix(model.Identifier), Prefix(model.DeviceId), model.ClientType);
target = NotificationTarget.User;
targetId = model.UserId.Value;
}
else if (!string.IsNullOrWhiteSpace(model.OrganizationId))
else if (model.OrganizationId.HasValue)
{
await _pushNotificationService.SendPayloadToOrganizationAsync(Prefix(model.OrganizationId),
model.Type, model.Payload, Prefix(model.Identifier), Prefix(model.DeviceId), model.ClientType);
target = NotificationTarget.Organization;
targetId = model.OrganizationId.Value;
}
else
{
throw new UnreachableException("Model validation should have prevented getting here.");
}
var notification = new RelayedNotification
{
Type = model.Type,
Target = target,
TargetId = targetId,
Payload = model.Payload,
Identifier = model.Identifier,
DeviceId = model.DeviceId,
ClientType = model.ClientType,
};
await _pushRelayer.RelayAsync(_currentContext.InstallationId.Value, notification);
}
private string Prefix(string value)