Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow sending push notifications to multiple identities and with dynamic text #939

Merged
merged 19 commits into from
Nov 15, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ private async Task ExecuteDeletion(IdentityAddress identityAddress, Cancellation

private async Task NotifyIdentityAboutStartingDeletion(IdentityAddress identityAddress, CancellationToken cancellationToken)
{
await _pushNotificationSender.SendNotification(identityAddress, new DeletionStartsPushNotification(), cancellationToken);
await _pushNotificationSender.SendNotification(new DeletionStartsPushNotification(), new SendPushNotificationFilter { IncludedIdentities = [identityAddress] }, cancellationToken);
}

private async Task Delete(IdentityAddress identityAddress)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Backbone.DevelopmentKit.Identity.ValueObjects;
using Backbone.Job.IdentityDeletion.Workers;
using Backbone.Modules.Devices.Application.Identities.Commands.TriggerRipeDeletionProcesses;
using Backbone.Modules.Devices.Application.Infrastructure.PushNotifications.DeletionProcess;
using Backbone.Modules.Relationships.Application.Relationships.Queries.FindRelationshipsOfIdentity;
using CSharpFunctionalExtensions;
using FakeItEasy;
Expand Down Expand Up @@ -74,7 +75,11 @@ public async Task Sends_push_notification_to_each_deleted_identity()
// Assert
foreach (var identityAddress in new[] { identityAddress1, identityAddress2, identityAddress3 })
{
A.CallTo(() => mockPushNotificationSender.SendNotification(identityAddress, A<IPushNotification>._, A<CancellationToken>._)).MustHaveHappenedOnceExactly();
A.CallTo(() => mockPushNotificationSender.SendNotification(
A<DeletionStartsPushNotification>._,
A<SendPushNotificationFilter>.That.Matches(f => f.IncludedIdentities.Contains(identityAddress)),
A<CancellationToken>._)
).MustHaveHappenedOnceExactly();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
using System.Text.RegularExpressions;
using Backbone.BuildingBlocks.API.Extensions;
using Backbone.BuildingBlocks.Application.Abstractions.Exceptions;
using Backbone.BuildingBlocks.Domain;
using Backbone.BuildingBlocks.Domain.Errors;
using Backbone.BuildingBlocks.Domain.Exceptions;
using Backbone.BuildingBlocks.Infrastructure.Exceptions;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,19 @@ namespace Backbone.BuildingBlocks.Application.PushNotifications;

public interface IPushNotificationSender
{
Task SendNotification(IdentityAddress recipient, IPushNotification notification, CancellationToken cancellationToken);
Task SendFilteredNotification(IdentityAddress recipient, IPushNotification notification, IEnumerable<string> excludedDevices, CancellationToken cancellationToken);
// Task SendNotification(IPushNotificationWithConstantTextWithDynamicText notification, CancellationToken cancellationToken);
// Task SendNotification(IdentityAddress recipient, IPushNotificationWithConstantText notificationWithConstantText, CancellationToken cancellationToken);
// Task SendFilteredNotification(IdentityAddress recipient, IPushNotificationWithConstantText notificationWithConstantText, IEnumerable<string> excludedDevices, CancellationToken cancellationToken);
Task SendNotification(IPushNotificationWithConstantText notification, SendPushNotificationFilter filter, CancellationToken cancellationToken);

Task SendNotification(IPushNotificationWithDynamicText notification, SendPushNotificationFilter filter, Dictionary<string, NotificationText> notificationTexts,
CancellationToken cancellationToken);
}

public record SendPushNotificationFilter
{
public List<DeviceId> ExcludedDevices { get; set; } = [];
public List<IdentityAddress> IncludedIdentities { get; set; } = [];
}

public record NotificationText(string Title, string Body);
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
namespace Backbone.BuildingBlocks.Application.PushNotifications;

public interface IPushNotificationWithConstantText : IPushNotification;
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
namespace Backbone.BuildingBlocks.Application.PushNotifications;

public interface IPushNotificationWithDynamicText : IPushNotification;
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using Backbone.BuildingBlocks.Domain.Errors;

namespace Backbone.BuildingBlocks.Domain;
namespace Backbone.BuildingBlocks.Domain.Exceptions;

public class DomainException : Exception
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Backbone.BuildingBlocks.Domain;
using Backbone.BuildingBlocks.Domain.Exceptions;
using FluentAssertions;
using FluentAssertions.Specialized;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using Backbone.BuildingBlocks.Application.Abstractions.Infrastructure.UserContext;
using Backbone.BuildingBlocks.Domain;
using Backbone.BuildingBlocks.Domain.Exceptions;
using Backbone.DevelopmentKit.Identity.ValueObjects;
using Backbone.Modules.Devices.Application.Infrastructure.Persistence.Repository;
using Backbone.Modules.Devices.Domain.Entities.Identities;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Backbone.BuildingBlocks.Application.Abstractions.Infrastructure.EventBus;
using Backbone.BuildingBlocks.Application.PushNotifications;
using Backbone.DevelopmentKit.Identity.ValueObjects;
using Backbone.Modules.Devices.Application.Infrastructure.PushNotifications.Datawallet;
using Backbone.Modules.Devices.Domain.DomainEvents.Incoming.DatawalletModificationCreated;

Expand All @@ -17,6 +18,11 @@ public DatawalletModifiedDomainEventHandler(IPushNotificationSender pushSenderSe
public async Task Handle(DatawalletModifiedDomainEvent domainEvent)
{
var notification = new DatawalletModificationsCreatedPushNotification(domainEvent.ModifiedByDevice);
await _pushSenderService.SendFilteredNotification(domainEvent.Identity, notification, [domainEvent.ModifiedByDevice], CancellationToken.None);
await _pushSenderService.SendNotification(notification,
new SendPushNotificationFilter
{
ExcludedDevices = [DeviceId.Parse(domainEvent.ModifiedByDevice)],
IncludedIdentities = [domainEvent.Identity]
}, CancellationToken.None);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ public async Task Handle(ExternalEventCreatedDomainEvent @event)
var identity = await _identitiesRepository.FindByAddress(@event.Owner, CancellationToken.None) ?? throw new NotFoundException(nameof(Identity));

if (identity.Status != IdentityStatus.ToBeDeleted)
await _pushSenderService.SendNotification(@event.Owner, new ExternalEventCreatedPushNotification(), CancellationToken.None);
await _pushSenderService.SendNotification(
new ExternalEventCreatedPushNotification(),
new SendPushNotificationFilter { IncludedIdentities = [@event.Owner] },
CancellationToken.None
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ public IdentityDeletionProcessStartedDomainEventHandler(IPushNotificationSender

public async Task Handle(IdentityDeletionProcessStartedDomainEvent @event)
{
await _pushNotificationSender.SendNotification(@event.Address, new DeletionProcessStartedPushNotification(), CancellationToken.None);
await _pushNotificationSender.SendNotification(new DeletionProcessStartedPushNotification(), new SendPushNotificationFilter { IncludedIdentities = [@event.Address] }, CancellationToken.None);
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using Backbone.BuildingBlocks.Application.Abstractions.Exceptions;
using Backbone.BuildingBlocks.Application.Abstractions.Infrastructure.UserContext;
using Backbone.BuildingBlocks.Application.PushNotifications;
using Backbone.BuildingBlocks.Domain;
using Backbone.BuildingBlocks.Domain.Exceptions;
using Backbone.Modules.Devices.Application.Infrastructure.Persistence.Repository;
using Backbone.Modules.Devices.Application.Infrastructure.PushNotifications.DeletionProcess;
using Backbone.Modules.Devices.Domain.Entities.Identities;
Expand Down Expand Up @@ -43,7 +43,12 @@ public async Task<ApproveDeletionProcessResponse> Handle(ApproveDeletionProcessC

var daysUntilDeletion = deletionProcess.GracePeriodEndsAt.Value.DaysUntilDate();

await _notificationSender.SendNotification(identity.Address, new DeletionProcessApprovedNotification(daysUntilDeletion), cancellationToken);

await _notificationSender.SendNotification(
new DeletionProcessApprovedNotification(daysUntilDeletion),
new SendPushNotificationFilter { IncludedIdentities = [identity.Address] },
cancellationToken
);

return new ApproveDeletionProcessResponse(deletionProcess);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using Backbone.BuildingBlocks.Application.Abstractions.Exceptions;
using Backbone.BuildingBlocks.Application.Abstractions.Infrastructure.UserContext;
using Backbone.BuildingBlocks.Application.PushNotifications;
using Backbone.BuildingBlocks.Domain;
using Backbone.BuildingBlocks.Domain.Exceptions;
using Backbone.Modules.Devices.Application.Infrastructure.Persistence.Repository;
using Backbone.Modules.Devices.Application.Infrastructure.PushNotifications.DeletionProcess;
using Backbone.Modules.Devices.Domain.Entities.Identities;
Expand Down Expand Up @@ -38,7 +38,11 @@ public async Task<CancelDeletionProcessAsOwnerResponse> Handle(CancelDeletionPro

await _identitiesRepository.Update(identity, cancellationToken);

await _notificationSender.SendNotification(identity.Address, new DeletionProcessCancelledByOwnerNotification(), cancellationToken);
await _notificationSender.SendNotification(
new DeletionProcessCancelledByOwnerNotification(),
new SendPushNotificationFilter { IncludedIdentities = [identity.Address] },
cancellationToken
);

return new CancelDeletionProcessAsOwnerResponse(deletionProcess);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,11 @@ public async Task<CancelDeletionAsSupportResponse> Handle(CancelDeletionAsSuppor

await _identitiesRepository.Update(identity, cancellationToken);

await _notificationSender.SendNotification(identity.Address, new DeletionProcessCancelledBySupportNotification(), cancellationToken);
await _notificationSender.SendNotification(
new DeletionProcessCancelledBySupportNotification(),
new SendPushNotificationFilter { IncludedIdentities = [identity.Address] },
cancellationToken
);

return new CancelDeletionAsSupportResponse(deletionProcess);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
using Backbone.BuildingBlocks.Application.Abstractions.Exceptions;
using Backbone.BuildingBlocks.Application.Abstractions.Infrastructure.UserContext;
using Backbone.BuildingBlocks.Domain;
using Backbone.BuildingBlocks.Domain.Exceptions;
using Backbone.Modules.Devices.Application.Infrastructure.Persistence.Repository;
using Backbone.Modules.Devices.Domain.Entities.Identities;
using MediatR;

namespace Backbone.Modules.Devices.Application.Identities.Commands.RejectDeletionProcess;

public class Handler : IRequestHandler<RejectDeletionProcessCommand, RejectDeletionProcessResponse>
{
private readonly IIdentitiesRepository _identitiesRepository;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,26 +61,35 @@ public async Task Handle(SendDeletionProcessApprovalRemindersCommand request, Ca

private async Task SendReminder3(Identity identity, double daysUntilApprovalPeriodEnds, IdentityDeletionProcessId deletionProcessId, CancellationToken cancellationToken)
{
await _pushNotificationSender.SendNotification(identity.Address, new DeletionProcessWaitingForApprovalReminderPushNotification((int)Math.Ceiling(daysUntilApprovalPeriodEnds)),
cancellationToken);
await _pushNotificationSender.SendNotification(
new DeletionProcessWaitingForApprovalReminderPushNotification((int)Math.Ceiling(daysUntilApprovalPeriodEnds)),
new SendPushNotificationFilter { IncludedIdentities = [identity.Address] },
cancellationToken
);
identity.DeletionProcessApprovalReminder3Sent();
await _identitiesRepository.Update(identity, cancellationToken);
_logger.ApprovalReminder3Sent(deletionProcessId);
}

private async Task SendReminder2(Identity identity, double daysUntilApprovalPeriodEnds, IdentityDeletionProcessId deletionProcessId, CancellationToken cancellationToken)
{
await _pushNotificationSender.SendNotification(identity.Address, new DeletionProcessWaitingForApprovalReminderPushNotification((int)Math.Ceiling(daysUntilApprovalPeriodEnds)),
cancellationToken);
await _pushNotificationSender.SendNotification(
new DeletionProcessWaitingForApprovalReminderPushNotification((int)Math.Ceiling(daysUntilApprovalPeriodEnds)),
new SendPushNotificationFilter { IncludedIdentities = [identity.Address] },
cancellationToken
);
identity.DeletionProcessApprovalReminder2Sent();
await _identitiesRepository.Update(identity, cancellationToken);
_logger.ApprovalReminder2Sent(deletionProcessId);
}

private async Task SendReminder1(Identity identity, double daysUntilApprovalPeriodEnds, IdentityDeletionProcessId deletionProcessId, CancellationToken cancellationToken)
{
await _pushNotificationSender.SendNotification(identity.Address, new DeletionProcessWaitingForApprovalReminderPushNotification((int)Math.Ceiling(daysUntilApprovalPeriodEnds)),
cancellationToken);
await _pushNotificationSender.SendNotification(
new DeletionProcessWaitingForApprovalReminderPushNotification((int)Math.Ceiling(daysUntilApprovalPeriodEnds)),
new SendPushNotificationFilter { IncludedIdentities = [identity.Address] },
cancellationToken
);
identity.DeletionProcessApprovalReminder1Sent();
await _identitiesRepository.Update(identity, cancellationToken);
_logger.ApprovalReminder1Sent(deletionProcessId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,23 +66,35 @@ public async Task Handle(SendDeletionProcessGracePeriodRemindersCommand request,

private async Task SendReminder3(Identity identity, double daysUntilGracePeriodEnds, IdentityDeletionProcessId deletionProcessId, CancellationToken cancellationToken)
{
await _pushSender.SendNotification(identity.Address, new DeletionProcessGracePeriodReminderPushNotification((int)Math.Ceiling(daysUntilGracePeriodEnds)), cancellationToken);
await _pushSender.SendNotification(
new DeletionProcessGracePeriodReminderPushNotification((int)Math.Ceiling(daysUntilGracePeriodEnds)),
new SendPushNotificationFilter { IncludedIdentities = [identity.Address] },
cancellationToken
);
identity.DeletionGracePeriodReminder3Sent();
await _identitiesRepository.Update(identity, cancellationToken);
_logger.Reminder3Sent(deletionProcessId);
}

private async Task SendReminder2(Identity identity, double daysUntilGracePeriodEnds, IdentityDeletionProcessId deletionProcessId, CancellationToken cancellationToken)
{
await _pushSender.SendNotification(identity.Address, new DeletionProcessGracePeriodReminderPushNotification((int)Math.Ceiling(daysUntilGracePeriodEnds)), cancellationToken);
await _pushSender.SendNotification(
new DeletionProcessGracePeriodReminderPushNotification((int)Math.Ceiling(daysUntilGracePeriodEnds)),
new SendPushNotificationFilter { IncludedIdentities = [identity.Address] },
cancellationToken
);
identity.DeletionGracePeriodReminder2Sent();
await _identitiesRepository.Update(identity, cancellationToken);
_logger.Reminder2Sent(deletionProcessId);
}

private async Task SendReminder1(Identity identity, double daysUntilGracePeriodEnds, IdentityDeletionProcessId deletionProcessId, CancellationToken cancellationToken)
{
await _pushSender.SendNotification(identity.Address, new DeletionProcessGracePeriodReminderPushNotification((int)Math.Ceiling(daysUntilGracePeriodEnds)), cancellationToken);
await _pushSender.SendNotification(
new DeletionProcessGracePeriodReminderPushNotification((int)Math.Ceiling(daysUntilGracePeriodEnds)),
new SendPushNotificationFilter { IncludedIdentities = [identity.Address] },
cancellationToken
);
identity.DeletionGracePeriodReminder1Sent();
await _identitiesRepository.Update(identity, cancellationToken);
_logger.Reminder1Sent(deletionProcessId);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using Backbone.BuildingBlocks.Application.Abstractions.Exceptions;
using Backbone.BuildingBlocks.Application.Abstractions.Infrastructure.UserContext;
using Backbone.BuildingBlocks.Application.PushNotifications;
using Backbone.BuildingBlocks.Domain;
using Backbone.BuildingBlocks.Domain.Exceptions;
using Backbone.Modules.Devices.Application.Infrastructure.Persistence.Repository;
using Backbone.Modules.Devices.Application.Infrastructure.PushNotifications.DeletionProcess;
using Backbone.Modules.Devices.Domain;
Expand Down Expand Up @@ -38,7 +38,11 @@ public async Task<StartDeletionProcessAsOwnerResponse> Handle(StartDeletionProce
throw new DomainException(DomainErrors.OnlyOneActiveDeletionProcessAllowed());
}

await _notificationSender.SendNotification(identity.Address, new DeletionProcessStartedPushNotification(), cancellationToken);
await _notificationSender.SendNotification(
new DeletionProcessStartedPushNotification(),
new SendPushNotificationFilter { IncludedIdentities = [identity.Address] },
cancellationToken
);

return new StartDeletionProcessAsOwnerResponse(deletionProcess);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
using Backbone.BuildingBlocks.Domain;
using Backbone.BuildingBlocks.Domain.Exceptions;
using Backbone.Modules.Devices.Application.Infrastructure.Persistence.Repository;
using Backbone.Modules.Devices.Domain.Entities.Identities;
using MediatR;

namespace Backbone.Modules.Devices.Application.Identities.Commands.TriggerRipeDeletionProcesses;

public class Handler : IRequestHandler<TriggerRipeDeletionProcessesCommand, TriggerRipeDeletionProcessesResponse>
{
private readonly IIdentitiesRepository _identitiesRepository;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ public interface IIdentitiesRepository
Task<DbPaginationResult<Device>> FindAllDevicesOfIdentity(IdentityAddress identity, IEnumerable<DeviceId> ids, PaginationFilter paginationFilter, CancellationToken cancellationToken);
Task<Device?> GetDeviceById(DeviceId deviceId, CancellationToken cancellationToken, bool track = false);
Task Update(Device device, CancellationToken cancellationToken);
Task<IEnumerable<Device>> FindDevices(Expression<Func<Device, bool>> filter, CancellationToken cancellationToken, bool track = false);
Task<List<T>> FindDevices<T>(Expression<Func<Device, bool>> filter, Expression<Func<Device, T>> selector, CancellationToken cancellationToken, bool track = false);

#endregion

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ public interface IPnsRegistrationsRepository
Task<PnsRegistration?> FindByDeviceId(DeviceId deviceId, CancellationToken cancellationToken, bool track = false);
Task Delete(List<DeviceId> deviceIds, CancellationToken cancellationToken);
Task Delete(Expression<Func<PnsRegistration, bool>> filter, CancellationToken cancellationToken);
Task<IEnumerable<PnsRegistration>> Find(Expression<Func<PnsRegistration, bool>> filter, CancellationToken cancellationToken);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

namespace Backbone.Modules.Devices.Application.Infrastructure.PushNotifications.Datawallet;

public record DatawalletModificationsCreatedPushNotification(string CreatedByDevice) : IPushNotification;
public record DatawalletModificationsCreatedPushNotification(string CreatedByDevice) : IPushNotificationWithConstantText;
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

namespace Backbone.Modules.Devices.Application.Infrastructure.PushNotifications.DeletionProcess;

public record DeletionProcessApprovedNotification(int DaysUntilDeletion) : IPushNotification;
public record DeletionProcessApprovedNotification(int DaysUntilDeletion) : IPushNotificationWithConstantText;
Loading
Loading