diff --git a/Applications/ConsumerApi/test/ConsumerApi.Tests.Integration/Features/Messages/POST.feature b/Applications/ConsumerApi/test/ConsumerApi.Tests.Integration/Features/Messages/POST.feature index 4695759f93..82c04534be 100644 --- a/Applications/ConsumerApi/test/ConsumerApi.Tests.Integration/Features/Messages/POST.feature +++ b/Applications/ConsumerApi/test/ConsumerApi.Tests.Integration/Features/Messages/POST.feature @@ -15,9 +15,8 @@ Identity sends a Message And an active Relationship r12 between i1 and i2 And i2 is in status "ToBeDeleted" When i1 sends a POST request to the /Messages endpoint with i2 as recipient - Then the response status code is 400 (Bad Request) - And the response content contains an error with the error code "error.platform.validation.message.recipientToBeDeleted" - And the error contains a list of Identities to be deleted that includes i2 + Then the response status code is 201 (Created) + And the response contains a SendMessageResponse Scenario: Sending a Message to a terminated Relationship Given Identities i1 and i2 diff --git a/Applications/ConsumerApi/test/ConsumerApi.Tests.Integration/Features/Relationships/{id}/Accept/PUT.feature b/Applications/ConsumerApi/test/ConsumerApi.Tests.Integration/Features/Relationships/{id}/Accept/PUT.feature index 4d4a198dae..6ad26bb04b 100644 --- a/Applications/ConsumerApi/test/ConsumerApi.Tests.Integration/Features/Relationships/{id}/Accept/PUT.feature +++ b/Applications/ConsumerApi/test/ConsumerApi.Tests.Integration/Features/Relationships/{id}/Accept/PUT.feature @@ -15,5 +15,5 @@ User accepts a Relationship And a pending Relationship r between i1 and i2 created by i2 And i2 is in status "ToBeDeleted" When i1 sends a PUT request to the /Relationships/{r.Id}/Accept endpoint - Then the response status code is 400 (Bad Request) - And the response content contains an error with the error code "error.platform.validation.relationship.peerIsToBeDeleted" + Then the response status code is 200 (OK) + And the response contains a RelationshipMetadata diff --git a/Applications/ConsumerApi/test/ConsumerApi.Tests.Integration/Features/Relationships/{id}/Reject/PUT.feature b/Applications/ConsumerApi/test/ConsumerApi.Tests.Integration/Features/Relationships/{id}/Reject/PUT.feature index e507afe429..ed5055ab99 100644 --- a/Applications/ConsumerApi/test/ConsumerApi.Tests.Integration/Features/Relationships/{id}/Reject/PUT.feature +++ b/Applications/ConsumerApi/test/ConsumerApi.Tests.Integration/Features/Relationships/{id}/Reject/PUT.feature @@ -15,5 +15,5 @@ User rejects a Relationship And a pending Relationship r between i1 and i2 created by i2 And i2 is in status "ToBeDeleted" When i1 sends a PUT request to the /Relationships/{r.Id}/Reject endpoint - Then the response status code is 400 (Bad Request) - And the response content contains an error with the error code "error.platform.validation.relationship.peerIsToBeDeleted" + Then the response status code is 200 (OK) + And the response contains a RelationshipMetadata diff --git a/Applications/ConsumerApi/test/ConsumerApi.Tests.Integration/Features/Relationships/{id}/Revoke/PUT.feature b/Applications/ConsumerApi/test/ConsumerApi.Tests.Integration/Features/Relationships/{id}/Revoke/PUT.feature index 805b05d68f..7e48bf039e 100644 --- a/Applications/ConsumerApi/test/ConsumerApi.Tests.Integration/Features/Relationships/{id}/Revoke/PUT.feature +++ b/Applications/ConsumerApi/test/ConsumerApi.Tests.Integration/Features/Relationships/{id}/Revoke/PUT.feature @@ -12,8 +12,8 @@ User revokes a Relationship Scenario: Revoke Relationship to an Identity in status "ToBeDeleted" Given Identities i1 and i2 - And a pending Relationship r between i1 and i2 created by i2 + And a pending Relationship r between i1 and i2 created by i1 And i2 is in status "ToBeDeleted" When i1 sends a PUT request to the /Relationships/{r.Id}/Revoke endpoint - Then the response status code is 400 (Bad Request) - And the response content contains an error with the error code "error.platform.validation.relationship.peerIsToBeDeleted" + Then the response status code is 200 (OK) + And the response contains a RelationshipMetadata diff --git a/Applications/ConsumerApi/test/ConsumerApi.Tests.Integration/StepDefinitions/RelationshipsStepDefinitions.cs b/Applications/ConsumerApi/test/ConsumerApi.Tests.Integration/StepDefinitions/RelationshipsStepDefinitions.cs index e5a66839cb..8eaaf020d4 100644 --- a/Applications/ConsumerApi/test/ConsumerApi.Tests.Integration/StepDefinitions/RelationshipsStepDefinitions.cs +++ b/Applications/ConsumerApi/test/ConsumerApi.Tests.Integration/StepDefinitions/RelationshipsStepDefinitions.cs @@ -128,21 +128,28 @@ public async Task WhenIdentitySendsAPostRequestToTheRelationshipsEndpointWithRel await client.Relationships.CreateRelationship(new CreateRelationshipRequest { RelationshipTemplateId = relationshipTemplateId, Content = TestData.SOME_BYTES }); } - [When($"{RegexFor.SINGLE_THING} sends a PUT request to the /Relationships/{{{RegexFor.SINGLE_THING}.Id}}/(Accept|Reject|Revoke) endpoint")] - public async Task WhenIdentitySendsAPostRequestToTheRelationshipsIdEndpoint(string identityName, string relationshipName, string requestType) + [When($"{RegexFor.SINGLE_THING} sends a PUT request to the /Relationships/{{{RegexFor.SINGLE_THING}.Id}}/Accept endpoint")] + public async Task WhenIdentitySendsAPostRequestToTheRelationshipsIdAcceptEndpoint(string identityName, string relationshipName) { var client = _clientPool.FirstForIdentityName(identityName); + var relationship = _relationshipsContext.Relationships[relationshipName]; + _responseContext.WhenResponse = await client.Relationships.AcceptRelationship(relationship.Id, new AcceptRelationshipRequest { CreationResponseContent = TestData.SOME_BYTES }); + } - _responseContext.WhenResponse = requestType switch - { - "Accept" => await client.Relationships.AcceptRelationship(_relationshipsContext.Relationships[relationshipName].Id, - new AcceptRelationshipRequest { CreationResponseContent = TestData.SOME_BYTES }), - "Reject" => await client.Relationships.RejectRelationship(_relationshipsContext.Relationships[relationshipName].Id, - new RejectRelationshipRequest { CreationResponseContent = TestData.SOME_BYTES }), - "Revoke" => await client.Relationships.RevokeRelationship(_relationshipsContext.Relationships[relationshipName].Id, - new RevokeRelationshipRequest { CreationResponseContent = TestData.SOME_BYTES }), - _ => throw new NotSupportedException($"Unsupported request type: {requestType}") - }; + [When($"{RegexFor.SINGLE_THING} sends a PUT request to the /Relationships/{{{RegexFor.SINGLE_THING}.Id}}/Reject endpoint")] + public async Task WhenIdentitySendsAPostRequestToTheRelationshipsIdRejectEndpoint(string identityName, string relationshipName) + { + var client = _clientPool.FirstForIdentityName(identityName); + var relationship = _relationshipsContext.Relationships[relationshipName]; + _responseContext.WhenResponse = await client.Relationships.RejectRelationship(relationship.Id, new RejectRelationshipRequest { CreationResponseContent = TestData.SOME_BYTES }); + } + + [When($"{RegexFor.SINGLE_THING} sends a PUT request to the /Relationships/{{{RegexFor.SINGLE_THING}.Id}}/Revoke endpoint")] + public async Task WhenIdentitySendsAPostRequestToTheRelationshipsIdRevokeEndpoint(string identityName, string relationshipName) + { + var client = _clientPool.FirstForIdentityName(identityName); + var relationship = _relationshipsContext.Relationships[relationshipName]; + _responseContext.WhenResponse = await client.Relationships.RevokeRelationship(relationship.Id, new RevokeRelationshipRequest { CreationResponseContent = TestData.SOME_BYTES }); } [When($"{RegexFor.SINGLE_THING} sends a PUT request to the /Relationships/{{{RegexFor.SINGLE_THING}.Id}}/Terminate endpoint")] diff --git a/Applications/IdentityDeletionJobs/test/Job.IdentityDeletion.Tests/Tests/ActualDeletionWorkerTests.cs b/Applications/IdentityDeletionJobs/test/Job.IdentityDeletion.Tests/Tests/ActualDeletionWorkerTests.cs index 943c64b3f9..319bf33b8e 100644 --- a/Applications/IdentityDeletionJobs/test/Job.IdentityDeletion.Tests/Tests/ActualDeletionWorkerTests.cs +++ b/Applications/IdentityDeletionJobs/test/Job.IdentityDeletion.Tests/Tests/ActualDeletionWorkerTests.cs @@ -5,7 +5,6 @@ using Backbone.Job.IdentityDeletion.Workers; using Backbone.Modules.Devices.Application.Identities.Commands.TriggerRipeDeletionProcesses; using Backbone.Modules.Relationships.Application.Relationships.Queries.FindRelationshipsOfIdentity; -using Backbone.Modules.Relationships.Domain.Aggregates.Relationships; using CSharpFunctionalExtensions; using FakeItEasy; using MediatR; @@ -45,7 +44,7 @@ public async Task Calls_Deleters_For_Each_Identity() var worker = CreateWorker(fakeMediator, [mockIdentityDeleter]); A.CallTo(() => fakeMediator.Send(A._, A._)) - .Returns(new FindRelationshipsOfIdentityResponse(new List())); + .Returns(new FindRelationshipsOfIdentityResponse([])); // Act await worker.StartProcessing(CancellationToken.None); diff --git a/Modules/Devices/src/Devices.Application/DomainEvents/Incoming/ExternalEventCreated/ExternalEventCreatedDomainEventHandler.cs b/Modules/Devices/src/Devices.Application/DomainEvents/Incoming/ExternalEventCreated/ExternalEventCreatedDomainEventHandler.cs index 818c804c32..a1f87f6971 100644 --- a/Modules/Devices/src/Devices.Application/DomainEvents/Incoming/ExternalEventCreated/ExternalEventCreatedDomainEventHandler.cs +++ b/Modules/Devices/src/Devices.Application/DomainEvents/Incoming/ExternalEventCreated/ExternalEventCreatedDomainEventHandler.cs @@ -1,17 +1,22 @@ +using Backbone.BuildingBlocks.Application.Abstractions.Exceptions; using Backbone.BuildingBlocks.Application.Abstractions.Infrastructure.EventBus; using Backbone.BuildingBlocks.Application.PushNotifications; +using Backbone.Modules.Devices.Application.Infrastructure.Persistence.Repository; using Backbone.Modules.Devices.Application.Infrastructure.PushNotifications.ExternalEvents; using Backbone.Modules.Devices.Domain.DomainEvents.Incoming.ExternalEventCreated; +using Backbone.Modules.Devices.Domain.Entities.Identities; namespace Backbone.Modules.Devices.Application.DomainEvents.Incoming.ExternalEventCreated; public class ExternalEventCreatedDomainEventHandler : IDomainEventHandler { private readonly IPushNotificationSender _pushSenderService; + private readonly IIdentitiesRepository _identitiesRepository; - public ExternalEventCreatedDomainEventHandler(IPushNotificationSender pushSenderService) + public ExternalEventCreatedDomainEventHandler(IPushNotificationSender pushSenderService, IIdentitiesRepository identitiesRepository) { _pushSenderService = pushSenderService; + _identitiesRepository = identitiesRepository; } public async Task Handle(ExternalEventCreatedDomainEvent @event) @@ -19,6 +24,9 @@ public async Task Handle(ExternalEventCreatedDomainEvent @event) if (@event.IsDeliveryBlocked) return; - await _pushSenderService.SendNotification(@event.Owner, new ExternalEventCreatedPushNotification(), CancellationToken.None); + 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); } } diff --git a/Modules/Devices/test/Devices.Application.Tests/Tests/DomainEvents/Incoming/ExternalEventCreatedDomainEventHandlerTests.cs b/Modules/Devices/test/Devices.Application.Tests/Tests/DomainEvents/Incoming/ExternalEventCreatedDomainEventHandlerTests.cs index 5640906349..ad15b7081c 100644 --- a/Modules/Devices/test/Devices.Application.Tests/Tests/DomainEvents/Incoming/ExternalEventCreatedDomainEventHandlerTests.cs +++ b/Modules/Devices/test/Devices.Application.Tests/Tests/DomainEvents/Incoming/ExternalEventCreatedDomainEventHandlerTests.cs @@ -1,5 +1,6 @@ using Backbone.BuildingBlocks.Application.PushNotifications; using Backbone.Modules.Devices.Application.DomainEvents.Incoming.ExternalEventCreated; +using Backbone.Modules.Devices.Application.Infrastructure.Persistence.Repository; using Backbone.Modules.Devices.Application.Infrastructure.PushNotifications.ExternalEvents; using Backbone.Modules.Devices.Domain.DomainEvents.Incoming.ExternalEventCreated; using FakeItEasy; @@ -13,11 +14,15 @@ public async Task Sends_a_push_notification_to_the_owner_of_the_external_event() { // Arrange var mockPushSender = A.Fake(); + var fakeIdentitiesRepository = A.Fake(); + var identity = TestDataGenerator.CreateIdentity(); - var handler = new ExternalEventCreatedDomainEventHandler(mockPushSender); + var handler = new ExternalEventCreatedDomainEventHandler(mockPushSender, fakeIdentitiesRepository); var externalEventOwner = CreateRandomIdentityAddress(); + A.CallTo(() => fakeIdentitiesRepository.FindByAddress(externalEventOwner, A._, A._)).Returns(identity); + // Act await handler.Handle(new ExternalEventCreatedDomainEvent { Owner = externalEventOwner, IsDeliveryBlocked = false }); @@ -25,16 +30,43 @@ public async Task Sends_a_push_notification_to_the_owner_of_the_external_event() A.CallTo(() => mockPushSender.SendNotification(externalEventOwner, A._, A._)).MustHaveHappenedOnceExactly(); } + [Fact] + public async Task Does_not_send_push_notification_if_owner_is_in_status_to_be_deleted() + { + // Arrange + var mockPushSender = A.Fake(); + var fakeIdentitiesRepository = A.Fake(); + var identity = TestDataGenerator.CreateIdentity(); + + var handler = new ExternalEventCreatedDomainEventHandler(mockPushSender, fakeIdentitiesRepository); + + var externalEventOwner = CreateRandomIdentityAddress(); + + identity.StartDeletionProcessAsOwner(identity.Devices[0].Id); + + A.CallTo(() => fakeIdentitiesRepository.FindByAddress(externalEventOwner, A._, A._)).Returns(identity); + + // Act + await handler.Handle(new ExternalEventCreatedDomainEvent { Owner = externalEventOwner, IsDeliveryBlocked = false }); + + // Assert + A.CallTo(() => mockPushSender.SendNotification(externalEventOwner, A._, A._)).MustNotHaveHappened(); + } + [Fact] public async Task Does_not_send_a_push_notification_when_delivery_of_the_external_event_is_blocked() { // Arrange var mockPushSender = A.Fake(); + var fakeIdentitiesRepository = A.Fake(); + var identity = TestDataGenerator.CreateIdentity(); - var handler = new ExternalEventCreatedDomainEventHandler(mockPushSender); + var handler = new ExternalEventCreatedDomainEventHandler(mockPushSender, fakeIdentitiesRepository); var externalEventOwner = CreateRandomIdentityAddress(); + A.CallTo(() => fakeIdentitiesRepository.FindByAddress(externalEventOwner, A._, A._)).Returns(identity); + // Act await handler.Handle(new ExternalEventCreatedDomainEvent { Owner = externalEventOwner, IsDeliveryBlocked = true }); diff --git a/Modules/Messages/src/Messages.Application/ApplicationErrors.cs b/Modules/Messages/src/Messages.Application/ApplicationErrors.cs index 8436b71406..e5f241185a 100644 --- a/Modules/Messages/src/Messages.Application/ApplicationErrors.cs +++ b/Modules/Messages/src/Messages.Application/ApplicationErrors.cs @@ -4,13 +4,6 @@ namespace Backbone.Modules.Messages.Application; public static class ApplicationErrors { - public static ApplicationError RecipientsToBeDeleted(IEnumerable peersToBeDeleted) - { - return new ApplicationError("error.platform.validation.message.recipientToBeDeleted", - $"Cannot send message to {peersToBeDeleted.Count()} of the recipients because they are in status 'ToBeDeleted'.", - new { PeersToBeDeleted = peersToBeDeleted }); - } - public static ApplicationError NoRelationshipToRecipientExists(string recipient = "") { var recipientText = string.IsNullOrEmpty(recipient) ? "one of the recipients" : recipient; diff --git a/Modules/Messages/src/Messages.ConsumerApi/Controllers/MessagesController.cs b/Modules/Messages/src/Messages.ConsumerApi/Controllers/MessagesController.cs index 5cf43e9811..ce13403334 100644 --- a/Modules/Messages/src/Messages.ConsumerApi/Controllers/MessagesController.cs +++ b/Modules/Messages/src/Messages.ConsumerApi/Controllers/MessagesController.cs @@ -3,8 +3,6 @@ using Backbone.BuildingBlocks.API.Mvc.ControllerAttributes; using Backbone.BuildingBlocks.Application.Abstractions.Exceptions; using Backbone.BuildingBlocks.Application.Pagination; -using Backbone.Modules.Devices.Application.Identities.Queries.ListIdentities; -using Backbone.Modules.Devices.Domain.Entities.Identities; using Backbone.Modules.Messages.Application; using Backbone.Modules.Messages.Application.Messages.Commands.SendMessage; using Backbone.Modules.Messages.Application.Messages.DTOs; @@ -61,11 +59,6 @@ public async Task GetMessage(string id, [FromQuery] bool? noBody, [ProducesError(StatusCodes.Status400BadRequest)] public async Task SendMessage(SendMessageCommand request, CancellationToken cancellationToken) { - var recipientAddresses = request.Recipients.Select(r => r.Address).ToList(); - var identitiesToBeDeleted = await _mediator.Send(new ListIdentitiesQuery(recipientAddresses, IdentityStatus.ToBeDeleted), cancellationToken); - if (identitiesToBeDeleted.Any()) - throw new ApplicationException(ApplicationErrors.RecipientsToBeDeleted(identitiesToBeDeleted.Select(i => i.Address))); - var response = await _mediator.Send(request, cancellationToken); return CreatedAtAction(nameof(GetMessage), new { id = response.Id }, response); } diff --git a/Modules/Relationships/src/Relationships.Application/Extensions/IEventBusExtensions.cs b/Modules/Relationships/src/Relationships.Application/Extensions/IEventBusExtensions.cs index 8c66b94c0a..1949320c73 100644 --- a/Modules/Relationships/src/Relationships.Application/Extensions/IEventBusExtensions.cs +++ b/Modules/Relationships/src/Relationships.Application/Extensions/IEventBusExtensions.cs @@ -8,13 +8,12 @@ namespace Backbone.Modules.Relationships.Application.Extensions; public static class IEventBusExtensions { - public static IEventBus AddRelationshipsDomainEventSubscriptions(this IEventBus eventBus) + public static void AddRelationshipsDomainEventSubscriptions(this IEventBus eventBus) { - eventBus.SubscribeToIdentitiesEvents(); - return eventBus; + SubscribeToIdentitiesEvents(eventBus); } - private static void SubscribeToIdentitiesEvents(this IEventBus eventBus) + private static void SubscribeToIdentitiesEvents(IEventBus eventBus) { eventBus.Subscribe(); eventBus.Subscribe(); diff --git a/Modules/Relationships/src/Relationships.ConsumerApi/Controllers/RelationshipsController.cs b/Modules/Relationships/src/Relationships.ConsumerApi/Controllers/RelationshipsController.cs index ec5ec448c0..8af74b0655 100644 --- a/Modules/Relationships/src/Relationships.ConsumerApi/Controllers/RelationshipsController.cs +++ b/Modules/Relationships/src/Relationships.ConsumerApi/Controllers/RelationshipsController.cs @@ -18,7 +18,6 @@ using Backbone.Modules.Relationships.Application.Relationships.Commands.TerminateRelationship; using Backbone.Modules.Relationships.Application.Relationships.DTOs; using Backbone.Modules.Relationships.Application.Relationships.Queries.CanEstablishRelationship; -using Backbone.Modules.Relationships.Application.Relationships.Queries.GetPeerOfActiveIdentityInRelationship; using Backbone.Modules.Relationships.Application.Relationships.Queries.GetRelationship; using Backbone.Modules.Relationships.Application.Relationships.Queries.ListRelationships; using Backbone.Modules.Relationships.Application.RelationshipTemplates.Queries.GetRelationshipTemplate; @@ -87,9 +86,6 @@ public async Task CreateRelationship(CreateRelationshipCommand re [ProducesError(StatusCodes.Status404NotFound)] public async Task AcceptRelationship([FromRoute] string id, [FromBody] AcceptRelationshipRequest request, CancellationToken cancellationToken) { - var peerOfActiveIdentityInRelationshipResponse = await _mediator.Send(new GetPeerOfActiveIdentityInRelationshipQuery { Id = id }, cancellationToken); - await EnsurePeerIsNotToBeDeleted(peerOfActiveIdentityInRelationshipResponse.IdentityAddress, cancellationToken); - var response = await _mediator.Send(new AcceptRelationshipCommand { RelationshipId = id, CreationResponseContent = request.CreationResponseContent }, cancellationToken); return Ok(response); } @@ -100,9 +96,6 @@ public async Task AcceptRelationship([FromRoute] string id, [From [ProducesError(StatusCodes.Status404NotFound)] public async Task RejectRelationship([FromRoute] string id, [FromBody] RejectRelationshipRequest request, CancellationToken cancellationToken) { - var peerOfActiveIdentityInRelationshipResponse = await _mediator.Send(new GetPeerOfActiveIdentityInRelationshipQuery { Id = id }, cancellationToken); - await EnsurePeerIsNotToBeDeleted(peerOfActiveIdentityInRelationshipResponse.IdentityAddress, cancellationToken); - var response = await _mediator.Send(new RejectRelationshipCommand { RelationshipId = id, CreationResponseContent = request.CreationResponseContent }, cancellationToken); return Ok(response); } @@ -113,9 +106,6 @@ public async Task RejectRelationship([FromRoute] string id, [From [ProducesError(StatusCodes.Status404NotFound)] public async Task RevokeRelationship([FromRoute] string id, [FromBody] RevokeRelationshipRequest request, CancellationToken cancellationToken) { - var peerOfActiveIdentityInRelationshipResponse = await _mediator.Send(new GetPeerOfActiveIdentityInRelationshipQuery { Id = id }, cancellationToken); - await EnsurePeerIsNotToBeDeleted(peerOfActiveIdentityInRelationshipResponse.IdentityAddress, cancellationToken); - var response = await _mediator.Send(new RevokeRelationshipCommand { RelationshipId = id, CreationResponseContent = request.CreationResponseContent }, cancellationToken); return Ok(response); } @@ -126,9 +116,6 @@ public async Task RevokeRelationship([FromRoute] string id, [From [ProducesError(StatusCodes.Status404NotFound)] public async Task TerminateRelationship([FromRoute] string id, CancellationToken cancellationToken) { - var peerOfActiveIdentityInRelationshipResponse = await _mediator.Send(new GetPeerOfActiveIdentityInRelationshipQuery { Id = id }, cancellationToken); - await EnsurePeerIsNotToBeDeleted(peerOfActiveIdentityInRelationshipResponse.IdentityAddress, cancellationToken); - var relationship = await _mediator.Send(new TerminateRelationshipCommand { RelationshipId = id }, cancellationToken); return Ok(relationship); } @@ -139,9 +126,6 @@ public async Task TerminateRelationship([FromRoute] string id, Ca [ProducesError(StatusCodes.Status404NotFound)] public async Task RelationshipReactivationRequest([FromRoute] string id, CancellationToken cancellationToken) { - var peerOfActiveIdentityInRelationshipResponse = await _mediator.Send(new GetPeerOfActiveIdentityInRelationshipQuery { Id = id }, cancellationToken); - await EnsurePeerIsNotToBeDeleted(peerOfActiveIdentityInRelationshipResponse.IdentityAddress, cancellationToken); - var response = await _mediator.Send(new RequestRelationshipReactivationCommand { RelationshipId = id }, cancellationToken); return Ok(response); } @@ -152,9 +136,6 @@ public async Task RelationshipReactivationRequest([FromRoute] str [ProducesError(StatusCodes.Status404NotFound)] public async Task RevokeRelationshipReactivation([FromRoute] string id, CancellationToken cancellationToken) { - var peerOfActiveIdentityInRelationshipResponse = await _mediator.Send(new GetPeerOfActiveIdentityInRelationshipQuery { Id = id }, cancellationToken); - await EnsurePeerIsNotToBeDeleted(peerOfActiveIdentityInRelationshipResponse.IdentityAddress, cancellationToken); - var response = await _mediator.Send(new RevokeRelationshipReactivationCommand { RelationshipId = id }, cancellationToken); return Ok(response); } @@ -165,9 +146,6 @@ public async Task RevokeRelationshipReactivation([FromRoute] stri [ProducesError(StatusCodes.Status404NotFound)] public async Task AcceptReactivationOfRelationship([FromRoute] string id, CancellationToken cancellationToken) { - var peerOfActiveIdentityInRelationshipResponse = await _mediator.Send(new GetPeerOfActiveIdentityInRelationshipQuery { Id = id }, cancellationToken); - await EnsurePeerIsNotToBeDeleted(peerOfActiveIdentityInRelationshipResponse.IdentityAddress, cancellationToken); - var response = await _mediator.Send(new AcceptRelationshipReactivationCommand { RelationshipId = id }, cancellationToken); return Ok(response); } @@ -178,9 +156,6 @@ public async Task AcceptReactivationOfRelationship([FromRoute] st [ProducesError(StatusCodes.Status404NotFound)] public async Task RejectReactivationOfRelationship([FromRoute] string id, CancellationToken cancellationToken) { - var peerOfActiveIdentityInRelationshipResponse = await _mediator.Send(new GetPeerOfActiveIdentityInRelationshipQuery { Id = id }, cancellationToken); - await EnsurePeerIsNotToBeDeleted(peerOfActiveIdentityInRelationshipResponse.IdentityAddress, cancellationToken); - var response = await _mediator.Send(new RejectRelationshipReactivationCommand { RelationshipId = id }, cancellationToken); return Ok(response); } diff --git a/Modules/Synchronization/src/Synchronization.Application/ApplicationErrors.cs b/Modules/Synchronization/src/Synchronization.Application/ApplicationErrors.cs index 0e6b094a30..6582fb8066 100644 --- a/Modules/Synchronization/src/Synchronization.Application/ApplicationErrors.cs +++ b/Modules/Synchronization/src/Synchronization.Application/ApplicationErrors.cs @@ -65,5 +65,11 @@ public static ApplicationError UnexpectedSyncRunType(SyncRun.SyncRunType expecte { return new ApplicationError("error.platform.validation.syncRun.unexpectedSyncRunType", $"The current operation only supports sync runs of type '{expectedType}'."); } + + public static ApplicationError CannotStartSyncRunWhileIdentityIsToBeDeleted() + { + return new ApplicationError("error.platform.validation.syncRun.cannotStartSyncRunWhileIdentityIsToBeDeleted", + "Cannot start sync run because the identity is in status 'ToBeDeleted'."); + } } } diff --git a/Modules/Synchronization/src/Synchronization.Application/Extensions/IEventBusExtensions.cs b/Modules/Synchronization/src/Synchronization.Application/Extensions/IEventBusExtensions.cs index 4c374ac8e6..0ce6264bca 100644 --- a/Modules/Synchronization/src/Synchronization.Application/Extensions/IEventBusExtensions.cs +++ b/Modules/Synchronization/src/Synchronization.Application/Extensions/IEventBusExtensions.cs @@ -22,12 +22,10 @@ namespace Backbone.Modules.Synchronization.Application.Extensions; public static class IEventBusExtensions { - public static IEventBus AddSynchronizationDomainEventSubscriptions(this IEventBus eventBus) + public static void AddSynchronizationDomainEventSubscriptions(this IEventBus eventBus) { SubscribeToMessagesEvents(eventBus); SubscribeToRelationshipsEvents(eventBus); - - return eventBus; } private static void SubscribeToMessagesEvents(IEventBus eventBus) diff --git a/Modules/Synchronization/src/Synchronization.ConsumerApi/Controllers/SyncRunsController.cs b/Modules/Synchronization/src/Synchronization.ConsumerApi/Controllers/SyncRunsController.cs index 16273d074a..6b348d5d99 100644 --- a/Modules/Synchronization/src/Synchronization.ConsumerApi/Controllers/SyncRunsController.cs +++ b/Modules/Synchronization/src/Synchronization.ConsumerApi/Controllers/SyncRunsController.cs @@ -2,7 +2,10 @@ using Backbone.BuildingBlocks.API.Mvc; using Backbone.BuildingBlocks.API.Mvc.ControllerAttributes; using Backbone.BuildingBlocks.Application.Abstractions.Exceptions; +using Backbone.BuildingBlocks.Application.Abstractions.Infrastructure.UserContext; using Backbone.BuildingBlocks.Application.Pagination; +using Backbone.Modules.Devices.Application.Identities.Queries.GetIdentity; +using Backbone.Modules.Devices.Domain.Entities.Identities; using Backbone.Modules.Synchronization.Application; using Backbone.Modules.Synchronization.Application.Datawallets.DTOs; using Backbone.Modules.Synchronization.Application.SyncRuns.Commands.FinalizeSyncRun; @@ -26,13 +29,14 @@ namespace Backbone.Modules.Synchronization.ConsumerApi.Controllers; public class SyncRunsController : ApiControllerBase { private readonly ApplicationOptions _options; + private readonly IUserContext _userContext; - public SyncRunsController(IMediator mediator, IOptions options) : base(mediator) + public SyncRunsController(IMediator mediator, IOptions options, IUserContext userContext) : base(mediator) { _options = options.Value; + _userContext = userContext; } - [HttpPost] [ProducesResponseType(typeof(HttpResponseEnvelopeResult), StatusCodes.Status200OK)] [ProducesError(StatusCodes.Status400BadRequest)] @@ -40,6 +44,9 @@ public async Task StartSyncRun(StartSyncRunRequestBody requestBod [FromHeader(Name = "X-Supported-Datawallet-Version")] ushort supportedDatawalletVersion, CancellationToken cancellationToken) { + var identityResponse = await _mediator.Send(new GetIdentityQuery(_userContext.GetAddress()), cancellationToken); + EnsureIdentityIsNotToBeDeleted(identityResponse); + var response = await _mediator.Send(new StartSyncRunCommand( requestBody.Type ?? SyncRunDTO.SyncRunType.ExternalEventSync, requestBody.Duration, supportedDatawalletVersion), cancellationToken); @@ -112,6 +119,12 @@ public async Task RefreshExpirationTimeOfSyncRun(SyncRunId id, Ca var response = await _mediator.Send(new RefreshExpirationTimeOfSyncRunCommand(id), cancellationToken); return Ok(response); } + + private static void EnsureIdentityIsNotToBeDeleted(GetIdentityResponse identityResponse) + { + if (identityResponse.Status is IdentityStatus.ToBeDeleted) + throw new ApplicationException(ApplicationErrors.SyncRuns.CannotStartSyncRunWhileIdentityIsToBeDeleted()); + } } public class StartSyncRunRequestBody