Skip to content

Commit

Permalink
Event Handler: Do not create external events for identity deletion if…
Browse files Browse the repository at this point in the history
… change was initiated by owner (#638)

* feat: don't create an external event in case the deletion process was started by the identity

* feat: don't create an external event in case the deletion process status was changed by the owner of the identity

---------

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
  • Loading branch information
tnotheis and mergify[bot] authored May 6, 2024
1 parent 9ab2466 commit fd576e4
Show file tree
Hide file tree
Showing 13 changed files with 100 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public async Task<CancelDeletionProcessAsOwnerResponse> Handle(CancelDeletionPro
var newTierId = identity.TierId;

_eventBus.Publish(new TierOfIdentityChangedDomainEvent(identity, oldTierId, newTierId));
_eventBus.Publish(new IdentityDeletionProcessStatusChangedDomainEvent(identity.Address, deletionProcess.Id));
_eventBus.Publish(new IdentityDeletionProcessStatusChangedDomainEvent(identity.Address, deletionProcess.Id, _userContext.GetAddress()));

return new CancelDeletionProcessAsOwnerResponse(deletionProcess);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public async Task<CancelDeletionAsSupportResponse> Handle(CancelDeletionAsSuppor
var newTierId = identity.TierId;

_eventBus.Publish(new TierOfIdentityChangedDomainEvent(identity, oldTierId, newTierId));
_eventBus.Publish(new IdentityDeletionProcessStatusChangedDomainEvent(identity.Address, deletionProcess.Id));
_eventBus.Publish(new IdentityDeletionProcessStatusChangedDomainEvent(identity.Address, deletionProcess.Id, null));

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

await _identityRepository.Update(identity, cancellationToken);

_eventBus.Publish(new IdentityDeletionProcessStatusChangedDomainEvent(identity.Address, deletionProcess.Value.Id));
_eventBus.Publish(new IdentityDeletionProcessStatusChangedDomainEvent(identity.Address, deletionProcess.Value.Id, null));
}

return new CancelStaleIdentityDeletionProcessesResponse(idsOfCancelledDeletionProcesses);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public async Task<StartDeletionProcessAsSupportResponse> Handle(StartDeletionPro

await _identitiesRepository.Update(identity, cancellationToken);

_eventBus.Publish(new IdentityDeletionProcessStartedDomainEvent(identity.Address, deletionProcess.Id));
_eventBus.Publish(new IdentityDeletionProcessStartedDomainEvent(identity.Address, deletionProcess.Id, null));

return new StartDeletionProcessAsSupportResponse(deletionProcess);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ namespace Backbone.Modules.Devices.Domain.DomainEvents.Outgoing;

public class IdentityDeletionProcessStartedDomainEvent : DomainEvent
{
public IdentityDeletionProcessStartedDomainEvent(string identityAddress, string deletionProcessId) : base($"{identityAddress}/DeletionProcessStarted/{deletionProcessId}")
public IdentityDeletionProcessStartedDomainEvent(string identityAddress, string deletionProcessId, string? initiator) : base($"{identityAddress}/DeletionProcessStarted/{deletionProcessId}")
{
DeletionProcessId = deletionProcessId;
Address = identityAddress;
Initiator = initiator;
}

public string Address { get; private set; }
public string DeletionProcessId { get; private set; }
public string? Initiator { get; set; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ namespace Backbone.Modules.Devices.Domain.DomainEvents.Outgoing;

public class IdentityDeletionProcessStatusChangedDomainEvent : DomainEvent
{
public IdentityDeletionProcessStatusChangedDomainEvent(string identityAddress, string deletionProcessId)
public IdentityDeletionProcessStatusChangedDomainEvent(string identityAddress, string deletionProcessId, string? initiator)
: base($"{identityAddress}/IdentityDeletionProcessStatusChanged/{deletionProcessId}")
{
Address = identityAddress;
DeletionProcessId = deletionProcessId;
Initiator = initiator;
}

public string Address { get; }
public string DeletionProcessId { get; }
public string? Initiator { get; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public async Task Sends_push_notification()
var mockPushNotificationSender = A.Fake<IPushNotificationSender>();
var handler = new IdentityDeletionProcessStartedDomainEventHandler(mockPushNotificationSender);
var identity = TestDataGenerator.CreateIdentity();
var identityDeletionProcessStartedDomainEvent = new IdentityDeletionProcessStartedDomainEvent(identity.Address, IdentityDeletionProcess.StartAsSupport(identity.Address).Id);
var identityDeletionProcessStartedDomainEvent = new IdentityDeletionProcessStartedDomainEvent(identity.Address, IdentityDeletionProcess.StartAsSupport(identity.Address).Id, null);

// Act
await handler.Handle(identityDeletionProcessStartedDomainEvent);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ public IdentityDeletionProcessStartedDomainEventHandler(ISynchronizationDbContex

public async Task Handle(IdentityDeletionProcessStartedDomainEvent domainEvent)
{
// No need to create an external event if the deletion process was started by the identity itself (in that case it's not "external").
if (domainEvent.Initiator == domainEvent.Address)
return;

#pragma warning disable IDE0037
var payload = new { DeletionProcessId = domainEvent.DeletionProcessId };
#pragma warning restore IDE0037
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ public IdentityDeletionProcessStatusChangedDomainEventHandler(ISynchronizationDb

public async Task Handle(IdentityDeletionProcessStatusChangedDomainEvent @event)
{
// No need to create an external event if the action that triggered the event was initiated by the owner of the deletion process (in that case it's not "external").
if (@event.Initiator == @event.Address)
return;

#pragma warning disable IDE0037
var payload = new { DeletionProcessId = @event.DeletionProcessId };
#pragma warning restore IDE0037
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ namespace Backbone.Modules.Synchronization.Domain.DomainEvents.Incoming.Identity

public class IdentityDeletionProcessStartedDomainEvent : DomainEvent
{
public IdentityDeletionProcessStartedDomainEvent(string identityAddress, string deletionProcessId) : base($"{identityAddress}/DeletionProcessStarted/{deletionProcessId}")
public IdentityDeletionProcessStartedDomainEvent(string identityAddress, string deletionProcessId, string? initiator)
{
DeletionProcessId = deletionProcessId;
Address = identityAddress;
Initiator = initiator;
}

public string Address { get; private set; }
public string DeletionProcessId { get; private set; }
public string? Initiator { get; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ namespace Backbone.Modules.Synchronization.Domain.DomainEvents.Incoming.Identity

public class IdentityDeletionProcessStatusChangedDomainEvent : DomainEvent
{
public IdentityDeletionProcessStatusChangedDomainEvent(string address, string deletionProcessId)
public IdentityDeletionProcessStatusChangedDomainEvent(string address, string deletionProcessId, string? initiator)
{
Address = address;
DeletionProcessId = deletionProcessId;
Initiator = initiator;
}

public string Address { get; }
public string DeletionProcessId { get; }
public string? Initiator { get; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ namespace Backbone.Modules.Synchronization.Application.Tests.Tests.DomainEvents;
public class IdentityDeletionProcessStartedDomainEventHandlerTests
{
[Fact]
public async Task Creates_an_external_event()
public async Task Creates_an_external_event_if_initiator_is_someone_else()
{
// Arrange
var identityAddress = TestDataGenerator.CreateRandomIdentityAddress();
var identityDeletionProcessStartedDomainEvent = new IdentityDeletionProcessStartedDomainEvent(identityAddress, "some-deletion-process-id");
var identityDeletionProcessStartedDomainEvent = new IdentityDeletionProcessStartedDomainEvent(identityAddress, "some-deletion-process-id", null);

var fakeDbContext = A.Fake<ISynchronizationDbContext>();
var mockEventBus = A.Fake<IEventBus>();
Expand All @@ -37,9 +37,37 @@ public async Task Creates_an_external_event()
// Act
await handler.Handle(identityDeletionProcessStartedDomainEvent);

// Handle
// Assert
A.CallTo(() => mockEventBus.Publish(
A<ExternalEventCreatedDomainEvent>.That.Matches(e => e.Owner == externalEvent.Owner && e.EventId == externalEvent.Id))
).MustHaveHappenedOnceExactly();
}

[Fact]
public async Task Does_nothing_if_initiator_is_deletion_process_owner()
{
// Arrange
var deletionProcessOwner = TestDataGenerator.CreateRandomIdentityAddress();
var identityDeletionProcessStartedDomainEvent = new IdentityDeletionProcessStartedDomainEvent(deletionProcessOwner, "some-deletion-process-id", deletionProcessOwner);

var fakeDbContext = A.Fake<ISynchronizationDbContext>();
var mockEventBus = A.Fake<IEventBus>();

var externalEvent = new ExternalEvent(ExternalEventType.IdentityDeletionProcessStarted, IdentityAddress.Parse(deletionProcessOwner), 1,
new { identityDeletionProcessStartedDomainEvent.DeletionProcessId });

A.CallTo(() => fakeDbContext.CreateExternalEvent(
A<IdentityAddress>.That.Matches(i => i.Value == deletionProcessOwner),
ExternalEventType.IdentityDeletionProcessStarted,
A<object>._)
).Returns(externalEvent);

var handler = new IdentityDeletionProcessStartedDomainEventHandler(fakeDbContext, mockEventBus, A.Fake<ILogger<IdentityDeletionProcessStartedDomainEventHandler>>());

// Act
await handler.Handle(identityDeletionProcessStartedDomainEvent);

// Assert
A.CallTo(() => mockEventBus.Publish(A<ExternalEventCreatedDomainEvent>._)).MustNotHaveHappened();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,19 @@ namespace Backbone.Modules.Synchronization.Application.Tests.Tests.DomainEvents;
public class IdentityDeletionProcessStatusChangedDomainEventHandlerTests
{
[Fact]
public async Task Creates_an_external_event()
public async Task Creates_an_external_event_if_initiator_is_someone_else()
{
// Arrange
var identityAddress = TestDataGenerator.CreateRandomIdentityAddress();
var identityDeletionProcessStatusChangedDomainEvent = new IdentityDeletionProcessStatusChangedDomainEvent(identityAddress, "someDeletionProcessId");
var deletionProcessOwner = TestDataGenerator.CreateRandomIdentityAddress();
var identityDeletionProcessStatusChangedDomainEvent = new IdentityDeletionProcessStatusChangedDomainEvent(deletionProcessOwner, "someDeletionProcessId", null);

var mockDbContext = A.Fake<ISynchronizationDbContext>();

var externalEvent = new ExternalEvent(ExternalEventType.IdentityDeletionProcessStatusChanged, IdentityAddress.Parse(identityAddress), 1,
var externalEvent = new ExternalEvent(ExternalEventType.IdentityDeletionProcessStatusChanged, IdentityAddress.Parse(deletionProcessOwner), 1,
new { identityDeletionProcessStatusChangedDomainEvent.DeletionProcessId });

A.CallTo(() => mockDbContext.CreateExternalEvent(
identityAddress,
deletionProcessOwner,
ExternalEventType.IdentityDeletionProcessStatusChanged,
A<object>._)
).Returns(externalEvent);
Expand All @@ -38,26 +38,26 @@ public async Task Creates_an_external_event()
// Act
await handler.Handle(identityDeletionProcessStatusChangedDomainEvent);

// Handle
A.CallTo(() => mockDbContext.CreateExternalEvent(identityAddress, ExternalEventType.IdentityDeletionProcessStatusChanged, A<object>._))
// Assert
A.CallTo(() => mockDbContext.CreateExternalEvent(deletionProcessOwner, ExternalEventType.IdentityDeletionProcessStatusChanged, A<object>._))
.MustHaveHappenedOnceExactly();
}

[Fact]
public async Task Publishes_an_external_event()
public async Task Publishes_a_domain_event_after_creating_an_external_event()
{
// Arrange
var identityAddress = TestDataGenerator.CreateRandomIdentityAddress();
var identityDeletionProcessStatusChangedDomainEvent = new IdentityDeletionProcessStatusChangedDomainEvent(identityAddress, "someDeletionProcessId");
var deletionProcessOwner = TestDataGenerator.CreateRandomIdentityAddress();
var identityDeletionProcessStatusChangedDomainEvent = new IdentityDeletionProcessStatusChangedDomainEvent(deletionProcessOwner, "someDeletionProcessId", null);

var fakeDbContext = A.Fake<ISynchronizationDbContext>();
var mockEventBus = A.Fake<IEventBus>();

var externalEvent = new ExternalEvent(ExternalEventType.IdentityDeletionProcessStatusChanged, IdentityAddress.Parse(identityAddress), 1,
var externalEvent = new ExternalEvent(ExternalEventType.IdentityDeletionProcessStatusChanged, IdentityAddress.Parse(deletionProcessOwner), 1,
new { identityDeletionProcessStatusChangedDomainEvent.DeletionProcessId });

A.CallTo(() => fakeDbContext.CreateExternalEvent(
identityAddress,
deletionProcessOwner,
ExternalEventType.IdentityDeletionProcessStatusChanged,
A<object>._)
).Returns(externalEvent);
Expand All @@ -69,9 +69,40 @@ public async Task Publishes_an_external_event()
// Act
await handler.Handle(identityDeletionProcessStatusChangedDomainEvent);

// Handle
// Assert
A.CallTo(() => mockEventBus.Publish(
A<ExternalEventCreatedDomainEvent>.That.Matches(e => e.Owner == externalEvent.Owner && e.EventId == externalEvent.Id))
).MustHaveHappenedOnceExactly();
}

[Fact]
public async Task Does_nothing_if_initiator_is_deletion_process_owner()
{
// Arrange
var deletionProcessOwner = TestDataGenerator.CreateRandomIdentityAddress();
var identityDeletionProcessStatusChangedDomainEvent = new IdentityDeletionProcessStatusChangedDomainEvent(deletionProcessOwner, "someDeletionProcessId", deletionProcessOwner);

var mockDbContext = A.Fake<ISynchronizationDbContext>();
var mockEventBus = A.Fake<IEventBus>();

var externalEvent = new ExternalEvent(ExternalEventType.IdentityDeletionProcessStatusChanged, IdentityAddress.Parse(deletionProcessOwner), 1,
new { identityDeletionProcessStatusChangedDomainEvent.DeletionProcessId });

A.CallTo(() => mockDbContext.CreateExternalEvent(
deletionProcessOwner,
ExternalEventType.IdentityDeletionProcessStatusChanged,
A<object>._)
).Returns(externalEvent);

var handler = new IdentityDeletionProcessStatusChangedDomainEventHandler(mockDbContext,
mockEventBus,
A.Fake<ILogger<IdentityDeletionProcessStatusChangedDomainEventHandler>>());

// Act
await handler.Handle(identityDeletionProcessStatusChangedDomainEvent);

// Assert
A.CallTo(() => mockDbContext.CreateExternalEvent(A<IdentityAddress>._, A<ExternalEventType>._, A<object>._)).MustNotHaveHappened();
A.CallTo(() => mockEventBus.Publish(A<IdentityDeletionProcessStatusChangedDomainEvent>._)).MustNotHaveHappened();
}
}

0 comments on commit fd576e4

Please sign in to comment.