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

Event Handler: Do not create external events for identity deletion if change was initiated by owner #638

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -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();
}
}