From 50bf07c8c025125644e2cbfe0e523ea8b138afae Mon Sep 17 00:00:00 2001 From: espent1004 Date: Sun, 27 Oct 2019 22:25:00 +0100 Subject: [PATCH 01/13] Work in progress --- docker-compose.override.yml | 1 - .../AbstractIntegrationEventHandler.cs | 65 +++++++++++++++++++ .../EventBus/EventBus/EventBus.csproj | 6 ++ .../EventBus/Events/CustomisationEvent.cs | 18 +++++ ...CheckoutAcceptedIntegrationEventHandler.cs | 60 +++++++++-------- 5 files changed, 121 insertions(+), 29 deletions(-) create mode 100644 src/BuildingBlocks/EventBus/EventBus/Abstractions/AbstractIntegrationEventHandler.cs create mode 100644 src/BuildingBlocks/EventBus/EventBus/Events/CustomisationEvent.cs diff --git a/docker-compose.override.yml b/docker-compose.override.yml index 41faa3580..8c59298ff 100644 --- a/docker-compose.override.yml +++ b/docker-compose.override.yml @@ -59,7 +59,6 @@ services: tenantmanager: environment: - ConnectionString=${ESHOP_AZURE_CATALOG_DB:-Server=sql.data;Database=Microsoft.eShopOnContainers.Services.TenantManagerDb;User Id=sa;Password=Pass@word} - ports: - "5115:80" diff --git a/src/BuildingBlocks/EventBus/EventBus/Abstractions/AbstractIntegrationEventHandler.cs b/src/BuildingBlocks/EventBus/EventBus/Abstractions/AbstractIntegrationEventHandler.cs new file mode 100644 index 000000000..c67e082cf --- /dev/null +++ b/src/BuildingBlocks/EventBus/EventBus/Abstractions/AbstractIntegrationEventHandler.cs @@ -0,0 +1,65 @@ +using System.Threading.Tasks; +using System; +using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; +using System.Net; +using System.IO; +using System.Net.Http; +using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; +using Microsoft.Extensions.Logging; + +namespace Ordering.API.Application.IntegrationEvents.EventHandling +{ + public abstract class AbstractIntegrationEventHandler + { + private static String url = @"http://tenantmanager/"; + private readonly IEventBus _eventBus; + + public async Task CheckIfCustomised(IntegrationEvent @event) + { + Boolean result = Get(@event); + if (result) + { + CustomisationEvent customisationEvent = new CustomisationEvent(1, @event); + try + { + //_logger.LogInformation("----- Publishing integration event: {IntegrationEventId} from {AppName} - ({@IntegrationEvent})", eventMessage.Id, Program.AppName, eventMessage); + + _eventBus.Publish(customisationEvent); + } + catch (Exception ex) + { + //_logger.LogError(ex, "ERROR Publishing integration event: {IntegrationEventId} from {AppName}", eventMessage.Id, Program.AppName); + + throw; + } + } + + return result; + } + + private Boolean Get(IntegrationEvent @event) + { + //TODO return true/false + Console.WriteLine("Making API Call..."); + using (var client = new HttpClient(new HttpClientHandler { AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate })) + { + client.BaseAddress = new Uri(url); + try + { + HttpResponseMessage response = client.GetAsync("api/tenants").Result; + response.EnsureSuccessStatusCode(); + string result = response.Content.ReadAsStringAsync().Result; + Console.WriteLine("Result: " + result); + + } + catch(Exception e) + { + Console.WriteLine(e); + } + + } + return false; + } + } + +} diff --git a/src/BuildingBlocks/EventBus/EventBus/EventBus.csproj b/src/BuildingBlocks/EventBus/EventBus/EventBus.csproj index 9704f6ff5..9dc11b510 100644 --- a/src/BuildingBlocks/EventBus/EventBus/EventBus.csproj +++ b/src/BuildingBlocks/EventBus/EventBus/EventBus.csproj @@ -9,4 +9,10 @@ + + + ..\..\..\..\..\..\..\..\..\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.extensions.logging.abstractions\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Logging.Abstractions.dll + + + \ No newline at end of file diff --git a/src/BuildingBlocks/EventBus/EventBus/Events/CustomisationEvent.cs b/src/BuildingBlocks/EventBus/EventBus/Events/CustomisationEvent.cs new file mode 100644 index 000000000..38b1564a5 --- /dev/null +++ b/src/BuildingBlocks/EventBus/EventBus/Events/CustomisationEvent.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events +{ + public class CustomisationEvent : IntegrationEvent + { + public CustomisationEvent(int tenantId, IntegrationEvent @event) + { + TenantId = tenantId; + this.@event = @event; + } + + public int TenantId { get; set; } + public IntegrationEvent @event { get; set; } + } +} diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/UserCheckoutAcceptedIntegrationEventHandler.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/UserCheckoutAcceptedIntegrationEventHandler.cs index a1452b23c..5782930f3 100644 --- a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/UserCheckoutAcceptedIntegrationEventHandler.cs +++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/UserCheckoutAcceptedIntegrationEventHandler.cs @@ -12,7 +12,7 @@ using System; namespace Ordering.API.Application.IntegrationEvents.EventHandling { - public class UserCheckoutAcceptedIntegrationEventHandler : IIntegrationEventHandler + public class UserCheckoutAcceptedIntegrationEventHandler : AbstractIntegrationEventHandler, IIntegrationEventHandler { private readonly IMediator _mediator; private readonly ILogger _logger; @@ -40,41 +40,45 @@ namespace Ordering.API.Application.IntegrationEvents.EventHandling { _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event); - var result = false; - - if (@event.RequestId != Guid.Empty) + var customised = await CheckIfCustomised(@event); + if (!customised) { - using (LogContext.PushProperty("IdentifiedCommandId", @event.RequestId)) + var result = false; + + if (@event.RequestId != Guid.Empty) { - var createOrderCommand = new CreateOrderCommand(@event.Basket.Items, @event.UserId, @event.UserName, @event.City, @event.Street, - @event.State, @event.Country, @event.ZipCode, - @event.CardNumber, @event.CardHolderName, @event.CardExpiration, - @event.CardSecurityNumber, @event.CardTypeId); + using (LogContext.PushProperty("IdentifiedCommandId", @event.RequestId)) + { + var createOrderCommand = new CreateOrderCommand(@event.Basket.Items, @event.UserId, @event.UserName, @event.City, @event.Street, + @event.State, @event.Country, @event.ZipCode, + @event.CardNumber, @event.CardHolderName, @event.CardExpiration, + @event.CardSecurityNumber, @event.CardTypeId); - var requestCreateOrder = new IdentifiedCommand(createOrderCommand, @event.RequestId); + var requestCreateOrder = new IdentifiedCommand(createOrderCommand, @event.RequestId); - _logger.LogInformation( - "----- Sending command: {CommandName} - {IdProperty}: {CommandId} ({@Command})", - requestCreateOrder.GetGenericTypeName(), - nameof(requestCreateOrder.Id), - requestCreateOrder.Id, - requestCreateOrder); + _logger.LogInformation( + "----- Sending command: {CommandName} - {IdProperty}: {CommandId} ({@Command})", + requestCreateOrder.GetGenericTypeName(), + nameof(requestCreateOrder.Id), + requestCreateOrder.Id, + requestCreateOrder); - result = await _mediator.Send(requestCreateOrder); + result = await _mediator.Send(requestCreateOrder); - if (result) - { - _logger.LogInformation("----- CreateOrderCommand suceeded - RequestId: {RequestId}", @event.RequestId); - } - else - { - _logger.LogWarning("CreateOrderCommand failed - RequestId: {RequestId}", @event.RequestId); + if (result) + { + _logger.LogInformation("----- CreateOrderCommand suceeded - RequestId: {RequestId}", @event.RequestId); + } + else + { + _logger.LogWarning("CreateOrderCommand failed - RequestId: {RequestId}", @event.RequestId); + } } } - } - else - { - _logger.LogWarning("Invalid IntegrationEvent - RequestId is missing - {@IntegrationEvent}", @event); + else + { + _logger.LogWarning("Invalid IntegrationEvent - RequestId is missing - {@IntegrationEvent}", @event); + } } } } From a804a53f8c7693ab265bdd551c2eb1a486299c7f Mon Sep 17 00:00:00 2001 From: espent1004 Date: Sun, 27 Oct 2019 22:45:23 +0100 Subject: [PATCH 02/13] Adding project --- eShopOnContainers-ServicesAndWebApps.sln | 108 ++--- .../Controllers/ValuesController.cs | 45 ++ src/Services/TenantACustomisations/Dockerfile | 59 +++ .../Filters/AuthorizeCheckOperationFilter.cs | 33 ++ .../Filters/HttpGlobalExceptionFilter.cs | 70 +++ src/Services/TenantACustomisations/Program.cs | 87 ++++ .../Properties/launchSettings.json | 30 ++ src/Services/TenantACustomisations/Startup.cs | 411 ++++++++++++++++++ .../TenantACustomisations.csproj | 61 +++ .../appsettings.Development.json | 9 + .../TenantACustomisations/appsettings.json | 8 + 11 files changed, 867 insertions(+), 54 deletions(-) create mode 100644 src/Services/TenantACustomisations/Controllers/ValuesController.cs create mode 100644 src/Services/TenantACustomisations/Dockerfile create mode 100644 src/Services/TenantACustomisations/Infrastructure/Filters/AuthorizeCheckOperationFilter.cs create mode 100644 src/Services/TenantACustomisations/Infrastructure/Filters/HttpGlobalExceptionFilter.cs create mode 100644 src/Services/TenantACustomisations/Program.cs create mode 100644 src/Services/TenantACustomisations/Properties/launchSettings.json create mode 100644 src/Services/TenantACustomisations/Startup.cs create mode 100644 src/Services/TenantACustomisations/TenantACustomisations.csproj create mode 100644 src/Services/TenantACustomisations/appsettings.Development.json create mode 100644 src/Services/TenantACustomisations/appsettings.json diff --git a/eShopOnContainers-ServicesAndWebApps.sln b/eShopOnContainers-ServicesAndWebApps.sln index 0de6d0ed7..929dde778 100644 --- a/eShopOnContainers-ServicesAndWebApps.sln +++ b/eShopOnContainers-ServicesAndWebApps.sln @@ -150,14 +150,14 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Devspace.Support", "Devspac EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Devspaces.Support", "src\BuildingBlocks\Devspaces.Support\Devspaces.Support.csproj", "{56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TenantCustomisations", "TenantCustomisations", "{D2D53ADC-5230-4EF4-95B0-31FD734992F6}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TenantACustomisations", "..\TenantACustomisations\TenantACustomisations.csproj", "{6CBF0D7F-7566-428E-B704-4059A10FFD52}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TenantManager", "TenantManager", "{71587505-2945-4286-BF0B-BA4C004B0BA7}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TenantManager", "src\Services\TenantManager\TenantManager\TenantManager.csproj", "{9C101827-119D-44EE-B0F0-94E7ABA8AE6A}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TenantCustomisations", "TenantCustomisations", "{773A0C2A-CA6F-4D4A-860B-C518EFA6FACB}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TenantACustomisations", "src\Services\TenantACustomisations\TenantACustomisations.csproj", "{58221C04-F14C-47E3-A802-E5979B4A5630}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Ad-Hoc|Any CPU = Ad-Hoc|Any CPU @@ -1804,54 +1804,6 @@ Global {56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35}.Release|x64.Build.0 = Release|Any CPU {56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35}.Release|x86.ActiveCfg = Release|Any CPU {56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35}.Release|x86.Build.0 = Release|Any CPU - {6CBF0D7F-7566-428E-B704-4059A10FFD52}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU - {6CBF0D7F-7566-428E-B704-4059A10FFD52}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU - {6CBF0D7F-7566-428E-B704-4059A10FFD52}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU - {6CBF0D7F-7566-428E-B704-4059A10FFD52}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU - {6CBF0D7F-7566-428E-B704-4059A10FFD52}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU - {6CBF0D7F-7566-428E-B704-4059A10FFD52}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU - {6CBF0D7F-7566-428E-B704-4059A10FFD52}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {6CBF0D7F-7566-428E-B704-4059A10FFD52}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU - {6CBF0D7F-7566-428E-B704-4059A10FFD52}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU - {6CBF0D7F-7566-428E-B704-4059A10FFD52}.Ad-Hoc|x64.Build.0 = Debug|Any CPU - {6CBF0D7F-7566-428E-B704-4059A10FFD52}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU - {6CBF0D7F-7566-428E-B704-4059A10FFD52}.Ad-Hoc|x86.Build.0 = Debug|Any CPU - {6CBF0D7F-7566-428E-B704-4059A10FFD52}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU - {6CBF0D7F-7566-428E-B704-4059A10FFD52}.AppStore|Any CPU.Build.0 = Debug|Any CPU - {6CBF0D7F-7566-428E-B704-4059A10FFD52}.AppStore|ARM.ActiveCfg = Debug|Any CPU - {6CBF0D7F-7566-428E-B704-4059A10FFD52}.AppStore|ARM.Build.0 = Debug|Any CPU - {6CBF0D7F-7566-428E-B704-4059A10FFD52}.AppStore|iPhone.ActiveCfg = Debug|Any CPU - {6CBF0D7F-7566-428E-B704-4059A10FFD52}.AppStore|iPhone.Build.0 = Debug|Any CPU - {6CBF0D7F-7566-428E-B704-4059A10FFD52}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {6CBF0D7F-7566-428E-B704-4059A10FFD52}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU - {6CBF0D7F-7566-428E-B704-4059A10FFD52}.AppStore|x64.ActiveCfg = Debug|Any CPU - {6CBF0D7F-7566-428E-B704-4059A10FFD52}.AppStore|x64.Build.0 = Debug|Any CPU - {6CBF0D7F-7566-428E-B704-4059A10FFD52}.AppStore|x86.ActiveCfg = Debug|Any CPU - {6CBF0D7F-7566-428E-B704-4059A10FFD52}.AppStore|x86.Build.0 = Debug|Any CPU - {6CBF0D7F-7566-428E-B704-4059A10FFD52}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6CBF0D7F-7566-428E-B704-4059A10FFD52}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6CBF0D7F-7566-428E-B704-4059A10FFD52}.Debug|ARM.ActiveCfg = Debug|Any CPU - {6CBF0D7F-7566-428E-B704-4059A10FFD52}.Debug|ARM.Build.0 = Debug|Any CPU - {6CBF0D7F-7566-428E-B704-4059A10FFD52}.Debug|iPhone.ActiveCfg = Debug|Any CPU - {6CBF0D7F-7566-428E-B704-4059A10FFD52}.Debug|iPhone.Build.0 = Debug|Any CPU - {6CBF0D7F-7566-428E-B704-4059A10FFD52}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {6CBF0D7F-7566-428E-B704-4059A10FFD52}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU - {6CBF0D7F-7566-428E-B704-4059A10FFD52}.Debug|x64.ActiveCfg = Debug|Any CPU - {6CBF0D7F-7566-428E-B704-4059A10FFD52}.Debug|x64.Build.0 = Debug|Any CPU - {6CBF0D7F-7566-428E-B704-4059A10FFD52}.Debug|x86.ActiveCfg = Debug|Any CPU - {6CBF0D7F-7566-428E-B704-4059A10FFD52}.Debug|x86.Build.0 = Debug|Any CPU - {6CBF0D7F-7566-428E-B704-4059A10FFD52}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6CBF0D7F-7566-428E-B704-4059A10FFD52}.Release|Any CPU.Build.0 = Release|Any CPU - {6CBF0D7F-7566-428E-B704-4059A10FFD52}.Release|ARM.ActiveCfg = Release|Any CPU - {6CBF0D7F-7566-428E-B704-4059A10FFD52}.Release|ARM.Build.0 = Release|Any CPU - {6CBF0D7F-7566-428E-B704-4059A10FFD52}.Release|iPhone.ActiveCfg = Release|Any CPU - {6CBF0D7F-7566-428E-B704-4059A10FFD52}.Release|iPhone.Build.0 = Release|Any CPU - {6CBF0D7F-7566-428E-B704-4059A10FFD52}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU - {6CBF0D7F-7566-428E-B704-4059A10FFD52}.Release|iPhoneSimulator.Build.0 = Release|Any CPU - {6CBF0D7F-7566-428E-B704-4059A10FFD52}.Release|x64.ActiveCfg = Release|Any CPU - {6CBF0D7F-7566-428E-B704-4059A10FFD52}.Release|x64.Build.0 = Release|Any CPU - {6CBF0D7F-7566-428E-B704-4059A10FFD52}.Release|x86.ActiveCfg = Release|Any CPU - {6CBF0D7F-7566-428E-B704-4059A10FFD52}.Release|x86.Build.0 = Release|Any CPU {9C101827-119D-44EE-B0F0-94E7ABA8AE6A}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU {9C101827-119D-44EE-B0F0-94E7ABA8AE6A}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU {9C101827-119D-44EE-B0F0-94E7ABA8AE6A}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU @@ -1900,6 +1852,54 @@ Global {9C101827-119D-44EE-B0F0-94E7ABA8AE6A}.Release|x64.Build.0 = Release|Any CPU {9C101827-119D-44EE-B0F0-94E7ABA8AE6A}.Release|x86.ActiveCfg = Release|Any CPU {9C101827-119D-44EE-B0F0-94E7ABA8AE6A}.Release|x86.Build.0 = Release|Any CPU + {58221C04-F14C-47E3-A802-E5979B4A5630}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU + {58221C04-F14C-47E3-A802-E5979B4A5630}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU + {58221C04-F14C-47E3-A802-E5979B4A5630}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU + {58221C04-F14C-47E3-A802-E5979B4A5630}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU + {58221C04-F14C-47E3-A802-E5979B4A5630}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU + {58221C04-F14C-47E3-A802-E5979B4A5630}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU + {58221C04-F14C-47E3-A802-E5979B4A5630}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {58221C04-F14C-47E3-A802-E5979B4A5630}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU + {58221C04-F14C-47E3-A802-E5979B4A5630}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU + {58221C04-F14C-47E3-A802-E5979B4A5630}.Ad-Hoc|x64.Build.0 = Debug|Any CPU + {58221C04-F14C-47E3-A802-E5979B4A5630}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU + {58221C04-F14C-47E3-A802-E5979B4A5630}.Ad-Hoc|x86.Build.0 = Debug|Any CPU + {58221C04-F14C-47E3-A802-E5979B4A5630}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU + {58221C04-F14C-47E3-A802-E5979B4A5630}.AppStore|Any CPU.Build.0 = Debug|Any CPU + {58221C04-F14C-47E3-A802-E5979B4A5630}.AppStore|ARM.ActiveCfg = Debug|Any CPU + {58221C04-F14C-47E3-A802-E5979B4A5630}.AppStore|ARM.Build.0 = Debug|Any CPU + {58221C04-F14C-47E3-A802-E5979B4A5630}.AppStore|iPhone.ActiveCfg = Debug|Any CPU + {58221C04-F14C-47E3-A802-E5979B4A5630}.AppStore|iPhone.Build.0 = Debug|Any CPU + {58221C04-F14C-47E3-A802-E5979B4A5630}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {58221C04-F14C-47E3-A802-E5979B4A5630}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU + {58221C04-F14C-47E3-A802-E5979B4A5630}.AppStore|x64.ActiveCfg = Debug|Any CPU + {58221C04-F14C-47E3-A802-E5979B4A5630}.AppStore|x64.Build.0 = Debug|Any CPU + {58221C04-F14C-47E3-A802-E5979B4A5630}.AppStore|x86.ActiveCfg = Debug|Any CPU + {58221C04-F14C-47E3-A802-E5979B4A5630}.AppStore|x86.Build.0 = Debug|Any CPU + {58221C04-F14C-47E3-A802-E5979B4A5630}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {58221C04-F14C-47E3-A802-E5979B4A5630}.Debug|Any CPU.Build.0 = Debug|Any CPU + {58221C04-F14C-47E3-A802-E5979B4A5630}.Debug|ARM.ActiveCfg = Debug|Any CPU + {58221C04-F14C-47E3-A802-E5979B4A5630}.Debug|ARM.Build.0 = Debug|Any CPU + {58221C04-F14C-47E3-A802-E5979B4A5630}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {58221C04-F14C-47E3-A802-E5979B4A5630}.Debug|iPhone.Build.0 = Debug|Any CPU + {58221C04-F14C-47E3-A802-E5979B4A5630}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {58221C04-F14C-47E3-A802-E5979B4A5630}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {58221C04-F14C-47E3-A802-E5979B4A5630}.Debug|x64.ActiveCfg = Debug|Any CPU + {58221C04-F14C-47E3-A802-E5979B4A5630}.Debug|x64.Build.0 = Debug|Any CPU + {58221C04-F14C-47E3-A802-E5979B4A5630}.Debug|x86.ActiveCfg = Debug|Any CPU + {58221C04-F14C-47E3-A802-E5979B4A5630}.Debug|x86.Build.0 = Debug|Any CPU + {58221C04-F14C-47E3-A802-E5979B4A5630}.Release|Any CPU.ActiveCfg = Release|Any CPU + {58221C04-F14C-47E3-A802-E5979B4A5630}.Release|Any CPU.Build.0 = Release|Any CPU + {58221C04-F14C-47E3-A802-E5979B4A5630}.Release|ARM.ActiveCfg = Release|Any CPU + {58221C04-F14C-47E3-A802-E5979B4A5630}.Release|ARM.Build.0 = Release|Any CPU + {58221C04-F14C-47E3-A802-E5979B4A5630}.Release|iPhone.ActiveCfg = Release|Any CPU + {58221C04-F14C-47E3-A802-E5979B4A5630}.Release|iPhone.Build.0 = Release|Any CPU + {58221C04-F14C-47E3-A802-E5979B4A5630}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {58221C04-F14C-47E3-A802-E5979B4A5630}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {58221C04-F14C-47E3-A802-E5979B4A5630}.Release|x64.ActiveCfg = Release|Any CPU + {58221C04-F14C-47E3-A802-E5979B4A5630}.Release|x64.Build.0 = Release|Any CPU + {58221C04-F14C-47E3-A802-E5979B4A5630}.Release|x86.ActiveCfg = Release|Any CPU + {58221C04-F14C-47E3-A802-E5979B4A5630}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1966,10 +1966,10 @@ Global {766D7E92-6AF0-476C-ADD5-282BF4D8C576} = {E279BF0F-7F66-4F3A-A3AB-2CDA66C1CD04} {68F5041D-51F2-4630-94B6-B49789F5E51A} = {DB0EFB20-B024-4E5E-A75C-52143C131D25} {56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35} = {68F5041D-51F2-4630-94B6-B49789F5E51A} - {D2D53ADC-5230-4EF4-95B0-31FD734992F6} = {91CF7717-08AB-4E65-B10E-0B426F01E2E8} - {6CBF0D7F-7566-428E-B704-4059A10FFD52} = {D2D53ADC-5230-4EF4-95B0-31FD734992F6} {71587505-2945-4286-BF0B-BA4C004B0BA7} = {91CF7717-08AB-4E65-B10E-0B426F01E2E8} {9C101827-119D-44EE-B0F0-94E7ABA8AE6A} = {71587505-2945-4286-BF0B-BA4C004B0BA7} + {773A0C2A-CA6F-4D4A-860B-C518EFA6FACB} = {91CF7717-08AB-4E65-B10E-0B426F01E2E8} + {58221C04-F14C-47E3-A802-E5979B4A5630} = {773A0C2A-CA6F-4D4A-860B-C518EFA6FACB} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {25728519-5F0F-4973-8A64-0A81EB4EA8D9} diff --git a/src/Services/TenantACustomisations/Controllers/ValuesController.cs b/src/Services/TenantACustomisations/Controllers/ValuesController.cs new file mode 100644 index 000000000..e297683b6 --- /dev/null +++ b/src/Services/TenantACustomisations/Controllers/ValuesController.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; + +namespace TenantACustomisations.Controllers +{ + [Route("api/[controller]")] + [ApiController] + public class ValuesController : ControllerBase + { + // GET api/values + [HttpGet] + public ActionResult> Get() + { + return new string[] { "value1", "value2" }; + } + + // GET api/values/5 + [HttpGet("{id}")] + public ActionResult Get(int id) + { + return "value"; + } + + // POST api/values + [HttpPost] + public void Post([FromBody] string value) + { + } + + // PUT api/values/5 + [HttpPut("{id}")] + public void Put(int id, [FromBody] string value) + { + } + + // DELETE api/values/5 + [HttpDelete("{id}")] + public void Delete(int id) + { + } + } +} diff --git a/src/Services/TenantACustomisations/Dockerfile b/src/Services/TenantACustomisations/Dockerfile new file mode 100644 index 000000000..5a3805dec --- /dev/null +++ b/src/Services/TenantACustomisations/Dockerfile @@ -0,0 +1,59 @@ +FROM mcr.microsoft.com/dotnet/core/aspnet:2.2-stretch-slim AS base +WORKDIR /app +EXPOSE 80 + +FROM mcr.microsoft.com/dotnet/core/sdk:2.2-stretch AS build +WORKDIR /src + +# Keep the project list and command dotnet restore identical in all Dockfiles to maximize image cache utilization +COPY eShopOnContainers-ServicesAndWebApps.sln . +COPY docker-compose.dcproj /src/ +COPY src/ApiGateways/ApiGw-Base/OcelotApiGw.csproj src/ApiGateways/ApiGw-Base/ +COPY src/ApiGateways/Mobile.Bff.Shopping/aggregator/Mobile.Shopping.HttpAggregator.csproj src/ApiGateways/Mobile.Bff.Shopping/aggregator/ +COPY src/ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj src/ApiGateways/Web.Bff.Shopping/aggregator/ +COPY src/BuildingBlocks/Devspaces.Support/Devspaces.Support.csproj src/BuildingBlocks/Devspaces.Support/ +COPY src/BuildingBlocks/EventBus/EventBus/EventBus.csproj src/BuildingBlocks/EventBus/EventBus/ +COPY src/BuildingBlocks/EventBus/EventBus.Tests/EventBus.Tests.csproj src/BuildingBlocks/EventBus/EventBus.Tests/ +COPY src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj src/BuildingBlocks/EventBus/EventBusRabbitMQ/ +COPY src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj src/BuildingBlocks/EventBus/EventBusServiceBus/ +COPY src/BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEF.csproj src/BuildingBlocks/EventBus/IntegrationEventLogEF/ +COPY src/BuildingBlocks/WebHostCustomization/WebHost.Customization/WebHost.Customization.csproj src/BuildingBlocks/WebHostCustomization/WebHost.Customization/ +COPY src/Services/Basket/Basket.API/Basket.API.csproj src/Services/Basket/Basket.API/ +COPY src/Services/Basket/Basket.FunctionalTests/Basket.FunctionalTests.csproj src/Services/Basket/Basket.FunctionalTests/ +COPY src/Services/Basket/Basket.UnitTests/Basket.UnitTests.csproj src/Services/Basket/Basket.UnitTests/ +COPY src/Services/Catalog/Catalog.API/Catalog.API.csproj src/Services/Catalog/Catalog.API/ +COPY src/Services/Catalog/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj src/Services/Catalog/Catalog.FunctionalTests/ +COPY src/Services/Catalog/Catalog.UnitTests/Catalog.UnitTests.csproj src/Services/Catalog/Catalog.UnitTests/ +COPY src/Services/Identity/Identity.API/Identity.API.csproj src/Services/Identity/Identity.API/ +COPY src/Services/Location/Locations.API/Locations.API.csproj src/Services/Location/Locations.API/ +COPY src/Services/Location/Locations.FunctionalTests/Locations.FunctionalTests.csproj src/Services/Location/Locations.FunctionalTests/ +COPY src/Services/Marketing/Marketing.API/Marketing.API.csproj src/Services/Marketing/Marketing.API/ +COPY src/Services/Marketing/Marketing.FunctionalTests/Marketing.FunctionalTests.csproj src/Services/Marketing/Marketing.FunctionalTests/ +COPY src/Services/Ordering/Ordering.API/Ordering.API.csproj src/Services/Ordering/Ordering.API/ +COPY src/Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj src/Services/Ordering/Ordering.BackgroundTasks/ +COPY src/Services/Ordering/Ordering.Domain/Ordering.Domain.csproj src/Services/Ordering/Ordering.Domain/ +COPY src/Services/Ordering/Ordering.FunctionalTests/Ordering.FunctionalTests.csproj src/Services/Ordering/Ordering.FunctionalTests/ +COPY src/Services/Ordering/Ordering.Infrastructure/Ordering.Infrastructure.csproj src/Services/Ordering/Ordering.Infrastructure/ +COPY src/Services/Ordering/Ordering.SignalrHub/Ordering.SignalrHub.csproj src/Services/Ordering/Ordering.SignalrHub/ +COPY src/Services/Ordering/Ordering.UnitTests/Ordering.UnitTests.csproj src/Services/Ordering/Ordering.UnitTests/ +COPY src/Services/Payment/Payment.API/Payment.API.csproj src/Services/Payment/Payment.API/ +COPY src/Services/Webhooks/Webhooks.API/Webhooks.API.csproj src/Services/Webhooks/Webhooks.API/ +COPY src/Web/WebhookClient/WebhookClient.csproj src/Web/WebhookClient/ +COPY src/Web/WebMVC/WebMVC.csproj src/Web/WebMVC/ +COPY src/Web/WebSPA/WebSPA.csproj src/Web/WebSPA/ +COPY src/Web/WebStatus/WebStatus.csproj src/Web/WebStatus/ +COPY test/ServicesTests/Application.FunctionalTests/Application.FunctionalTests.csproj test/ServicesTests/Application.FunctionalTests/ +COPY test/ServicesTests/LoadTest/LoadTest.csproj test/ServicesTests/LoadTest/ + +RUN dotnet restore eShopOnContainers-ServicesAndWebApps.sln + +COPY . . +WORKDIR /src/src/Services/TenantCustomisations/TenantACustomisations +RUN dotnet publish --no-restore -c Release -o /app + +FROM build AS publish + +FROM base AS final +WORKDIR /app +COPY --from=publish /app . +ENTRYPOINT ["dotnet", "TenantACustomisations.dll"] diff --git a/src/Services/TenantACustomisations/Infrastructure/Filters/AuthorizeCheckOperationFilter.cs b/src/Services/TenantACustomisations/Infrastructure/Filters/AuthorizeCheckOperationFilter.cs new file mode 100644 index 000000000..2851101a8 --- /dev/null +++ b/src/Services/TenantACustomisations/Infrastructure/Filters/AuthorizeCheckOperationFilter.cs @@ -0,0 +1,33 @@ +using Microsoft.AspNetCore.Authorization; +using Swashbuckle.AspNetCore.Swagger; +using Swashbuckle.AspNetCore.SwaggerGen; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace TenantACustomisations.Infrastructure.Filters +{ + public class AuthorizeCheckOperationFilter : IOperationFilter + { + public void Apply(Operation operation, OperationFilterContext context) + { + // Check for authorize attribute + var hasAuthorize = context.MethodInfo.DeclaringType.GetCustomAttributes(true).OfType().Any() || + context.MethodInfo.GetCustomAttributes(true).OfType().Any(); + + if (!hasAuthorize) return; + + operation.Responses.TryAdd("401", new Response { Description = "Unauthorized" }); + operation.Responses.TryAdd("403", new Response { Description = "Forbidden" }); + + operation.Security = new List>> + { + new Dictionary> + { + { "oauth2", new [] { "orderingapi" } } + } + }; + } + } +} \ No newline at end of file diff --git a/src/Services/TenantACustomisations/Infrastructure/Filters/HttpGlobalExceptionFilter.cs b/src/Services/TenantACustomisations/Infrastructure/Filters/HttpGlobalExceptionFilter.cs new file mode 100644 index 000000000..a4ce415ea --- /dev/null +++ b/src/Services/TenantACustomisations/Infrastructure/Filters/HttpGlobalExceptionFilter.cs @@ -0,0 +1,70 @@ +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Filters +{ + using AspNetCore.Mvc; + using global::Ordering.Domain.Exceptions; + using Microsoft.AspNetCore.Hosting; + using Microsoft.AspNetCore.Http; + using Microsoft.AspNetCore.Mvc.Filters; + using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.ActionResults; + using Microsoft.Extensions.Logging; + using System.Net; + + public class HttpGlobalExceptionFilter : IExceptionFilter + { + private readonly IHostingEnvironment env; + private readonly ILogger logger; + + public HttpGlobalExceptionFilter(IHostingEnvironment env, ILogger logger) + { + this.env = env; + this.logger = logger; + } + + public void OnException(ExceptionContext context) + { + logger.LogError(new EventId(context.Exception.HResult), + context.Exception, + context.Exception.Message); + + if (context.Exception.GetType() == typeof(OrderingDomainException)) + { + var problemDetails = new ValidationProblemDetails() + { + Instance = context.HttpContext.Request.Path, + Status = StatusCodes.Status400BadRequest, + Detail = "Please refer to the errors property for additional details." + }; + + problemDetails.Errors.Add("DomainValidations", new string[] { context.Exception.Message.ToString() }); + + context.Result = new BadRequestObjectResult(problemDetails); + context.HttpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest; + } + else + { + var json = new JsonErrorResponse + { + Messages = new[] { "An error occur.Try it again." } + }; + + if (env.IsDevelopment()) + { + json.DeveloperMessage = context.Exception; + } + + // Result asigned to a result object but in destiny the response is empty. This is a known bug of .net core 1.1 + // It will be fixed in .net core 1.1.2. See https://github.com/aspnet/Mvc/issues/5594 for more information + context.Result = new InternalServerErrorObjectResult(json); + context.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError; + } + context.ExceptionHandled = true; + } + + private class JsonErrorResponse + { + public string[] Messages { get; set; } + + public object DeveloperMessage { get; set; } + } + } +} diff --git a/src/Services/TenantACustomisations/Program.cs b/src/Services/TenantACustomisations/Program.cs new file mode 100644 index 000000000..bfe683782 --- /dev/null +++ b/src/Services/TenantACustomisations/Program.cs @@ -0,0 +1,87 @@ +using Microsoft.AspNetCore; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Serilog; +using System; +using System.IO; + +namespace Microsoft.eShopOnContainers.Services.Ordering.API +{ + public class Program + { + public static readonly string Namespace = typeof(Program).Namespace; + public static readonly string AppName = Namespace.Substring(Namespace.LastIndexOf('.', Namespace.LastIndexOf('.') - 1) + 1); + + public static int Main(string[] args) + { + var configuration = GetConfiguration(); + + Log.Logger = CreateSerilogLogger(configuration); + + try + { + Log.Information("Configuring web host ({ApplicationContext})...", AppName); + var host = BuildWebHost(configuration, args); + + Log.Information("Starting web host ({ApplicationContext})...", AppName); + host.Run(); + + return 0; + } + catch (Exception ex) + { + Log.Fatal(ex, "Program terminated unexpectedly ({ApplicationContext})!", AppName); + return 1; + } + finally + { + Log.CloseAndFlush(); + } + } + + private static IWebHost BuildWebHost(IConfiguration configuration, string[] args) => + WebHost.CreateDefaultBuilder(args) + .CaptureStartupErrors(false) + .UseStartup() + .UseApplicationInsights() + .UseContentRoot(Directory.GetCurrentDirectory()) + .UseConfiguration(configuration) + .UseSerilog() + .Build(); + + private static Serilog.ILogger CreateSerilogLogger(IConfiguration configuration) + { + var seqServerUrl = configuration["Serilog:SeqServerUrl"]; + var logstashUrl = configuration["Serilog:LogstashgUrl"]; + return new LoggerConfiguration() + .MinimumLevel.Verbose() + .Enrich.WithProperty("ApplicationContext", AppName) + .Enrich.FromLogContext() + .WriteTo.Console() + .WriteTo.Seq(string.IsNullOrWhiteSpace(seqServerUrl) ? "http://seq" : seqServerUrl) + .WriteTo.Http(string.IsNullOrWhiteSpace(logstashUrl) ? "http://logstash:8080" : logstashUrl) + .ReadFrom.Configuration(configuration) + .CreateLogger(); + } + + private static IConfiguration GetConfiguration() + { + var builder = new ConfigurationBuilder() + .SetBasePath(Directory.GetCurrentDirectory()) + .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) + .AddEnvironmentVariables(); + + var config = builder.Build(); + + if (config.GetValue("UseVault", false)) + { + builder.AddAzureKeyVault( + $"https://{config["Vault:Name"]}.vault.azure.net/", + config["Vault:ClientId"], + config["Vault:ClientSecret"]); + } + + return builder.Build(); + } + } +} \ No newline at end of file diff --git a/src/Services/TenantACustomisations/Properties/launchSettings.json b/src/Services/TenantACustomisations/Properties/launchSettings.json new file mode 100644 index 000000000..09e073222 --- /dev/null +++ b/src/Services/TenantACustomisations/Properties/launchSettings.json @@ -0,0 +1,30 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:57040", + "sslPort": 44328 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "api/values", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "TenantACustomisations": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "api/values", + "applicationUrl": "https://localhost:5001;http://localhost:5000", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} \ No newline at end of file diff --git a/src/Services/TenantACustomisations/Startup.cs b/src/Services/TenantACustomisations/Startup.cs new file mode 100644 index 000000000..69538d9c1 --- /dev/null +++ b/src/Services/TenantACustomisations/Startup.cs @@ -0,0 +1,411 @@ +namespace Microsoft.eShopOnContainers.Services.Ordering.API +{ + using AspNetCore.Http; + using Autofac; + using Autofac.Extensions.DependencyInjection; + using Microsoft.ApplicationInsights.Extensibility; + using Microsoft.ApplicationInsights.ServiceFabric; + using Microsoft.AspNetCore.Authentication.JwtBearer; + using Microsoft.AspNetCore.Builder; + using Microsoft.AspNetCore.Hosting; + using Microsoft.AspNetCore.Mvc; + using Microsoft.Azure.ServiceBus; + using Microsoft.EntityFrameworkCore; + using Microsoft.eShopOnContainers.BuildingBlocks.EventBus; + using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; + using Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ; + using Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus; + using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF; + using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Services; + using Microsoft.Extensions.Configuration; + using Microsoft.Extensions.DependencyInjection; + using Microsoft.Extensions.Logging; + using RabbitMQ.Client; + using Swashbuckle.AspNetCore.Swagger; + using System; + using System.Collections.Generic; + using System.Data.Common; + using System.IdentityModel.Tokens.Jwt; + using System.Reflection; + using HealthChecks.UI.Client; + using Microsoft.AspNetCore.Diagnostics.HealthChecks; + using Microsoft.Extensions.Diagnostics.HealthChecks; + using TenantACustomisations.Infrastructure.Filters; + + public class Startup + { + public Startup(IConfiguration configuration) + { + Configuration = configuration; + } + + public IConfiguration Configuration { get; } + + public IServiceProvider ConfigureServices(IServiceCollection services) + { + services.AddApplicationInsights(Configuration) + .AddCustomMvc() + .AddHealthChecks(Configuration) + .AddCustomDbContext(Configuration) + .AddCustomSwagger(Configuration) + .AddCustomIntegrations(Configuration) + .AddCustomConfiguration(Configuration) + .AddEventBus(Configuration) + .AddCustomAuthentication(Configuration); + + //configure autofac + + var container = new ContainerBuilder(); + container.Populate(services); + + container.RegisterModule(new MediatorModule()); + container.RegisterModule(new ApplicationModule(Configuration["ConnectionString"])); + + return new AutofacServiceProvider(container.Build()); + } + + + public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory) + { + //loggerFactory.AddAzureWebAppDiagnostics(); + //loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace); + + var pathBase = Configuration["PATH_BASE"]; + if (!string.IsNullOrEmpty(pathBase)) + { + loggerFactory.CreateLogger().LogDebug("Using PATH BASE '{pathBase}'", pathBase); + app.UsePathBase(pathBase); + } + + app.UseCors("CorsPolicy"); + + app.UseHealthChecks("/liveness", new HealthCheckOptions + { + Predicate = r => r.Name.Contains("self") + }); + + app.UseHealthChecks("/hc", new HealthCheckOptions() + { + Predicate = _ => true, + ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse + }); + + ConfigureAuth(app); + + app.UseMvcWithDefaultRoute(); + + app.UseSwagger() + .UseSwaggerUI(c => + { + c.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "Ordering.API V1"); + c.OAuthClientId("orderingswaggerui"); + c.OAuthAppName("Ordering Swagger UI"); + }); + + ConfigureEventBus(app); + } + + + private void ConfigureEventBus(IApplicationBuilder app) + { + var eventBus = app.ApplicationServices.GetRequiredService(); + + //eventBus.Subscribe>(); + } + + protected virtual void ConfigureAuth(IApplicationBuilder app) + { + if (Configuration.GetValue("UseLoadTest")) + { + app.UseMiddleware(); + } + + app.UseAuthentication(); + } + } + + static class CustomExtensionsMethods + { + public static IServiceCollection AddApplicationInsights(this IServiceCollection services, IConfiguration configuration) + { + services.AddApplicationInsightsTelemetry(configuration); + var orchestratorType = configuration.GetValue("OrchestratorType"); + + if (orchestratorType?.ToUpper() == "K8S") + { + // Enable K8s telemetry initializer + services.AddApplicationInsightsKubernetesEnricher(); + } + if (orchestratorType?.ToUpper() == "SF") + { + // Enable SF telemetry initializer + services.AddSingleton((serviceProvider) => + new FabricTelemetryInitializer()); + } + + return services; + } + + public static IServiceCollection AddCustomMvc(this IServiceCollection services) + { + // Add framework services. + services.AddMvc(options => + { + options.Filters.Add(typeof(HttpGlobalExceptionFilter)); + }) + .SetCompatibilityVersion(CompatibilityVersion.Version_2_2) + .AddControllersAsServices(); //Injecting Controllers themselves thru DI + //For further info see: http://docs.autofac.org/en/latest/integration/aspnetcore.html#controllers-as-services + + services.AddCors(options => + { + options.AddPolicy("CorsPolicy", + builder => builder + .SetIsOriginAllowed((host) => true) + .AllowAnyMethod() + .AllowAnyHeader() + .AllowCredentials()); + }); + + return services; + } + + public static IServiceCollection AddHealthChecks(this IServiceCollection services, IConfiguration configuration) + { + var hcBuilder = services.AddHealthChecks(); + + hcBuilder.AddCheck("self", () => HealthCheckResult.Healthy()); + + hcBuilder + .AddSqlServer( + configuration["ConnectionString"], + name: "OrderingDB-check", + tags: new string[] { "orderingdb" }); + + if (configuration.GetValue("AzureServiceBusEnabled")) + { + hcBuilder + .AddAzureServiceBusTopic( + configuration["EventBusConnection"], + topicName: "eshop_event_bus", + name: "ordering-servicebus-check", + tags: new string[] { "servicebus" }); + } + else + { + hcBuilder + .AddRabbitMQ( + $"amqp://{configuration["EventBusConnection"]}", + name: "ordering-rabbitmqbus-check", + tags: new string[] { "rabbitmqbus" }); + } + + return services; + } + + public static IServiceCollection AddCustomDbContext(this IServiceCollection services, IConfiguration configuration) + { + //services.AddEntityFrameworkSqlServer() + // .AddDbContext(options => + // { + // options.UseSqlServer(configuration["ConnectionString"], + // sqlServerOptionsAction: sqlOptions => + // { + // sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name); + // sqlOptions.EnableRetryOnFailure(maxRetryCount: 10, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null); + // }); + // }, + // ServiceLifetime.Scoped //Showing explicitly that the DbContext is shared across the HTTP request scope (graph of objects started in the HTTP request) + // ); + + services.AddDbContext(options => + { + options.UseSqlServer(configuration["ConnectionString"], + sqlServerOptionsAction: sqlOptions => + { + sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name); + //Configuring Connection Resiliency: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency + sqlOptions.EnableRetryOnFailure(maxRetryCount: 10, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null); + }); + }); + + return services; + } + + public static IServiceCollection AddCustomSwagger(this IServiceCollection services, IConfiguration configuration) + { + services.AddSwaggerGen(options => + { + options.DescribeAllEnumsAsStrings(); + options.SwaggerDoc("v1", new Swashbuckle.AspNetCore.Swagger.Info + { + Title = "Ordering HTTP API", + Version = "v1", + Description = "The Ordering Service HTTP API", + TermsOfService = "Terms Of Service" + }); + + options.AddSecurityDefinition("oauth2", new OAuth2Scheme + { + Type = "oauth2", + Flow = "implicit", + AuthorizationUrl = $"{configuration.GetValue("IdentityUrlExternal")}/connect/authorize", + TokenUrl = $"{configuration.GetValue("IdentityUrlExternal")}/connect/token", + Scopes = new Dictionary() + { + { "orders", "Ordering API" } + } + }); + + options.OperationFilter(); + }); + + return services; + } + + public static IServiceCollection AddCustomIntegrations(this IServiceCollection services, IConfiguration configuration) + { + services.AddSingleton(); + //services.AddTransient(); + services.AddTransient>( + sp => (DbConnection c) => new IntegrationEventLogService(c)); + + //services.AddTransient(); + + if (configuration.GetValue("AzureServiceBusEnabled")) + { + services.AddSingleton(sp => + { + var logger = sp.GetRequiredService>(); + + var serviceBusConnectionString = configuration["EventBusConnection"]; + var serviceBusConnection = new ServiceBusConnectionStringBuilder(serviceBusConnectionString); + + return new DefaultServiceBusPersisterConnection(serviceBusConnection, logger); + }); + } + else + { + services.AddSingleton(sp => + { + var logger = sp.GetRequiredService>(); + + + var factory = new ConnectionFactory() + { + HostName = configuration["EventBusConnection"], + DispatchConsumersAsync = true + }; + + if (!string.IsNullOrEmpty(configuration["EventBusUserName"])) + { + factory.UserName = configuration["EventBusUserName"]; + } + + if (!string.IsNullOrEmpty(configuration["EventBusPassword"])) + { + factory.Password = configuration["EventBusPassword"]; + } + + var retryCount = 5; + if (!string.IsNullOrEmpty(configuration["EventBusRetryCount"])) + { + retryCount = int.Parse(configuration["EventBusRetryCount"]); + } + + return new DefaultRabbitMQPersistentConnection(factory, logger, retryCount); + }); + } + + return services; + } + + public static IServiceCollection AddCustomConfiguration(this IServiceCollection services, IConfiguration configuration) + { + services.AddOptions(); + //services.Configure(configuration); + services.Configure(options => + { + options.InvalidModelStateResponseFactory = context => + { + var problemDetails = new ValidationProblemDetails(context.ModelState) + { + Instance = context.HttpContext.Request.Path, + Status = StatusCodes.Status400BadRequest, + Detail = "Please refer to the errors property for additional details." + }; + + return new BadRequestObjectResult(problemDetails) + { + ContentTypes = { "application/problem+json", "application/problem+xml" } + }; + }; + }); + + return services; + } + + public static IServiceCollection AddEventBus(this IServiceCollection services, IConfiguration configuration) + { + var subscriptionClientName = configuration["SubscriptionClientName"]; + + if (configuration.GetValue("AzureServiceBusEnabled")) + { + services.AddSingleton(sp => + { + var serviceBusPersisterConnection = sp.GetRequiredService(); + var iLifetimeScope = sp.GetRequiredService(); + var logger = sp.GetRequiredService>(); + var eventBusSubcriptionsManager = sp.GetRequiredService(); + + return new EventBusServiceBus(serviceBusPersisterConnection, logger, + eventBusSubcriptionsManager, subscriptionClientName, iLifetimeScope); + }); + } + else + { + services.AddSingleton(sp => + { + var rabbitMQPersistentConnection = sp.GetRequiredService(); + var iLifetimeScope = sp.GetRequiredService(); + var logger = sp.GetRequiredService>(); + var eventBusSubcriptionsManager = sp.GetRequiredService(); + + var retryCount = 5; + if (!string.IsNullOrEmpty(configuration["EventBusRetryCount"])) + { + retryCount = int.Parse(configuration["EventBusRetryCount"]); + } + + return new EventBusRabbitMQ(rabbitMQPersistentConnection, logger, iLifetimeScope, eventBusSubcriptionsManager, subscriptionClientName, retryCount); + }); + } + + services.AddSingleton(); + + return services; + } + + public static IServiceCollection AddCustomAuthentication(this IServiceCollection services, IConfiguration configuration) + { + // prevent from mapping "sub" claim to nameidentifier. + JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Remove("sub"); + + var identityUrl = configuration.GetValue("IdentityUrl"); + + services.AddAuthentication(options => + { + options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; + options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; + + }).AddJwtBearer(options => + { + options.Authority = identityUrl; + options.RequireHttpsMetadata = false; + options.Audience = "orders"; + }); + + return services; + } + } +} diff --git a/src/Services/TenantACustomisations/TenantACustomisations.csproj b/src/Services/TenantACustomisations/TenantACustomisations.csproj new file mode 100644 index 000000000..1e6b1036b --- /dev/null +++ b/src/Services/TenantACustomisations/TenantACustomisations.csproj @@ -0,0 +1,61 @@ + + + + netcoreapp2.2 + InProcess + Linux + ..\eShopOnContainersCustomised + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Services/TenantACustomisations/appsettings.Development.json b/src/Services/TenantACustomisations/appsettings.Development.json new file mode 100644 index 000000000..e203e9407 --- /dev/null +++ b/src/Services/TenantACustomisations/appsettings.Development.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Debug", + "System": "Information", + "Microsoft": "Information" + } + } +} diff --git a/src/Services/TenantACustomisations/appsettings.json b/src/Services/TenantACustomisations/appsettings.json new file mode 100644 index 000000000..def9159a7 --- /dev/null +++ b/src/Services/TenantACustomisations/appsettings.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Warning" + } + }, + "AllowedHosts": "*" +} From dc8fed53f986ca7ec6c062400c1fe721e3b378dc Mon Sep 17 00:00:00 2001 From: espent1004 Date: Sun, 27 Oct 2019 22:52:18 +0100 Subject: [PATCH 03/13] More setup --- .../AutofacModules/ApplicationModule.cs | 24 +++++++++++++++++++ .../AutofacModules/MediatorModule.cs | 12 ++++++++++ .../Filters/HttpGlobalExceptionFilter.cs | 9 ++++--- src/Services/TenantACustomisations/Startup.cs | 9 ++++--- .../TenantACustomisations.csproj | 8 +++---- 5 files changed, 50 insertions(+), 12 deletions(-) create mode 100644 src/Services/TenantACustomisations/Infrastructure/AutofacModules/ApplicationModule.cs create mode 100644 src/Services/TenantACustomisations/Infrastructure/AutofacModules/MediatorModule.cs diff --git a/src/Services/TenantACustomisations/Infrastructure/AutofacModules/ApplicationModule.cs b/src/Services/TenantACustomisations/Infrastructure/AutofacModules/ApplicationModule.cs new file mode 100644 index 000000000..69cc1d12a --- /dev/null +++ b/src/Services/TenantACustomisations/Infrastructure/AutofacModules/ApplicationModule.cs @@ -0,0 +1,24 @@ +using Autofac; +using System.Reflection; + +namespace Microsoft.eShopOnContainers.Services.TenantACustomisations.Infrastructure.AutofacModules +{ + + public class ApplicationModule + :Autofac.Module + { + + public string QueriesConnectionString { get; } + + public ApplicationModule(string qconstr) + { + QueriesConnectionString = qconstr; + + } + + protected override void Load(ContainerBuilder builder) + { + //TODO + } + } +} diff --git a/src/Services/TenantACustomisations/Infrastructure/AutofacModules/MediatorModule.cs b/src/Services/TenantACustomisations/Infrastructure/AutofacModules/MediatorModule.cs new file mode 100644 index 000000000..bfcdb42b3 --- /dev/null +++ b/src/Services/TenantACustomisations/Infrastructure/AutofacModules/MediatorModule.cs @@ -0,0 +1,12 @@ +using Autofac; + +namespace Microsoft.eShopOnContainers.Services.TenantACustomisations.Infrastructure.AutofacModules +{ + public class MediatorModule : Autofac.Module + { + protected override void Load(ContainerBuilder builder) + { + //TODO + } + } +} diff --git a/src/Services/TenantACustomisations/Infrastructure/Filters/HttpGlobalExceptionFilter.cs b/src/Services/TenantACustomisations/Infrastructure/Filters/HttpGlobalExceptionFilter.cs index a4ce415ea..0fb959a65 100644 --- a/src/Services/TenantACustomisations/Infrastructure/Filters/HttpGlobalExceptionFilter.cs +++ b/src/Services/TenantACustomisations/Infrastructure/Filters/HttpGlobalExceptionFilter.cs @@ -1,11 +1,9 @@ -namespace Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Filters +namespace Microsoft.eShopOnContainers.Services.TenantACustomisations.Infrastructure.Filters { using AspNetCore.Mvc; - using global::Ordering.Domain.Exceptions; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc.Filters; - using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.ActionResults; using Microsoft.Extensions.Logging; using System.Net; @@ -26,7 +24,7 @@ context.Exception, context.Exception.Message); - if (context.Exception.GetType() == typeof(OrderingDomainException)) + if (1==2)//TODO { var problemDetails = new ValidationProblemDetails() { @@ -54,7 +52,8 @@ // Result asigned to a result object but in destiny the response is empty. This is a known bug of .net core 1.1 // It will be fixed in .net core 1.1.2. See https://github.com/aspnet/Mvc/issues/5594 for more information - context.Result = new InternalServerErrorObjectResult(json); + //TODO + //context.Result = new InternalServerErrorObjectResult(json); context.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError; } context.ExceptionHandled = true; diff --git a/src/Services/TenantACustomisations/Startup.cs b/src/Services/TenantACustomisations/Startup.cs index 69538d9c1..afdb96f30 100644 --- a/src/Services/TenantACustomisations/Startup.cs +++ b/src/Services/TenantACustomisations/Startup.cs @@ -1,4 +1,4 @@ -namespace Microsoft.eShopOnContainers.Services.Ordering.API +namespace Microsoft.eShopOnContainers.Services.TenantACustomisations { using AspNetCore.Http; using Autofac; @@ -30,7 +30,9 @@ using HealthChecks.UI.Client; using Microsoft.AspNetCore.Diagnostics.HealthChecks; using Microsoft.Extensions.Diagnostics.HealthChecks; - using TenantACustomisations.Infrastructure.Filters; + using Infrastructure.AutofacModules; + using Microsoft.eShopOnContainers.Services.TenantACustomisations.Infrastructure.Filters; + using global::TenantACustomisations.Infrastructure.Filters; public class Startup { @@ -117,7 +119,8 @@ { if (Configuration.GetValue("UseLoadTest")) { - app.UseMiddleware(); + //app.UseMiddleware(); + //TODO } app.UseAuthentication(); diff --git a/src/Services/TenantACustomisations/TenantACustomisations.csproj b/src/Services/TenantACustomisations/TenantACustomisations.csproj index 1e6b1036b..606018fed 100644 --- a/src/Services/TenantACustomisations/TenantACustomisations.csproj +++ b/src/Services/TenantACustomisations/TenantACustomisations.csproj @@ -48,10 +48,10 @@ - - - - + + + + From b697de1f2a929b2932bf9a0252ac6baff3d717f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Espen=20T=C3=B8nnessen=20Nordli?= Date: Sun, 17 Nov 2019 16:17:07 +0100 Subject: [PATCH 04/13] Fixes --- docker-compose.override.yml | 4 + docker-compose.yml | 6 ++ eShopOnContainers-ServicesAndWebApps.sln | 100 +++++++++--------- .../Controllers/ValuesController.cs | 0 .../TenantACustomisations/Dockerfile | 2 +- .../AutofacModules/ApplicationModule.cs | 0 .../AutofacModules/MediatorModule.cs | 0 .../Filters/AuthorizeCheckOperationFilter.cs | 0 .../Filters/HttpGlobalExceptionFilter.cs | 0 .../TenantACustomisations/Program.cs | 1 + .../Properties/launchSettings.json | 0 .../TenantACustomisations/Startup.cs | 0 .../TenantACustomisations.csproj | 8 +- .../appsettings.Development.json | 0 .../TenantACustomisations/appsettings.json | 0 15 files changed, 66 insertions(+), 55 deletions(-) rename src/Services/{ => TenantCustomisations}/TenantACustomisations/Controllers/ValuesController.cs (100%) rename src/Services/{ => TenantCustomisations}/TenantACustomisations/Dockerfile (99%) rename src/Services/{ => TenantCustomisations}/TenantACustomisations/Infrastructure/AutofacModules/ApplicationModule.cs (100%) rename src/Services/{ => TenantCustomisations}/TenantACustomisations/Infrastructure/AutofacModules/MediatorModule.cs (100%) rename src/Services/{ => TenantCustomisations}/TenantACustomisations/Infrastructure/Filters/AuthorizeCheckOperationFilter.cs (100%) rename src/Services/{ => TenantCustomisations}/TenantACustomisations/Infrastructure/Filters/HttpGlobalExceptionFilter.cs (100%) rename src/Services/{ => TenantCustomisations}/TenantACustomisations/Program.cs (97%) rename src/Services/{ => TenantCustomisations}/TenantACustomisations/Properties/launchSettings.json (100%) rename src/Services/{ => TenantCustomisations}/TenantACustomisations/Startup.cs (100%) rename src/Services/{ => TenantCustomisations}/TenantACustomisations/TenantACustomisations.csproj (88%) rename src/Services/{ => TenantCustomisations}/TenantACustomisations/appsettings.Development.json (100%) rename src/Services/{ => TenantCustomisations}/TenantACustomisations/appsettings.json (100%) diff --git a/docker-compose.override.yml b/docker-compose.override.yml index 8c59298ff..6a9a6448e 100644 --- a/docker-compose.override.yml +++ b/docker-compose.override.yml @@ -62,6 +62,10 @@ services: ports: - "5115:80" + tenantacustomisation: + ports: + - "5116:80" + basket.api: environment: - ASPNETCORE_ENVIRONMENT=Development diff --git a/docker-compose.yml b/docker-compose.yml index abd837ec8..2fbdf2781 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -43,6 +43,12 @@ services: depends_on: - sql.data + tenantacustomisation: + image: ${REGISTRY:-eshop}/tenantacustomisation:${PLATFORM:-linux}-${TAG:-latest} + build: + context: . + dockerfile: src/Services/TenantCustomisations/TenantACustomisations/Dockerfile + catalog.api: image: ${REGISTRY:-eshop}/catalog.api:${PLATFORM:-linux}-${TAG:-latest} build: diff --git a/eShopOnContainers-ServicesAndWebApps.sln b/eShopOnContainers-ServicesAndWebApps.sln index 929dde778..4a671c9d9 100644 --- a/eShopOnContainers-ServicesAndWebApps.sln +++ b/eShopOnContainers-ServicesAndWebApps.sln @@ -156,7 +156,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TenantManager", "src\Servic EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TenantCustomisations", "TenantCustomisations", "{773A0C2A-CA6F-4D4A-860B-C518EFA6FACB}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TenantACustomisations", "src\Services\TenantACustomisations\TenantACustomisations.csproj", "{58221C04-F14C-47E3-A802-E5979B4A5630}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TenantACustomisations", "src\Services\TenantCustomisations\TenantACustomisations\TenantACustomisations.csproj", "{76651DAE-FF27-44A4-AF84-34689E2FFDF2}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -1852,54 +1852,54 @@ Global {9C101827-119D-44EE-B0F0-94E7ABA8AE6A}.Release|x64.Build.0 = Release|Any CPU {9C101827-119D-44EE-B0F0-94E7ABA8AE6A}.Release|x86.ActiveCfg = Release|Any CPU {9C101827-119D-44EE-B0F0-94E7ABA8AE6A}.Release|x86.Build.0 = Release|Any CPU - {58221C04-F14C-47E3-A802-E5979B4A5630}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU - {58221C04-F14C-47E3-A802-E5979B4A5630}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU - {58221C04-F14C-47E3-A802-E5979B4A5630}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU - {58221C04-F14C-47E3-A802-E5979B4A5630}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU - {58221C04-F14C-47E3-A802-E5979B4A5630}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU - {58221C04-F14C-47E3-A802-E5979B4A5630}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU - {58221C04-F14C-47E3-A802-E5979B4A5630}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {58221C04-F14C-47E3-A802-E5979B4A5630}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU - {58221C04-F14C-47E3-A802-E5979B4A5630}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU - {58221C04-F14C-47E3-A802-E5979B4A5630}.Ad-Hoc|x64.Build.0 = Debug|Any CPU - {58221C04-F14C-47E3-A802-E5979B4A5630}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU - {58221C04-F14C-47E3-A802-E5979B4A5630}.Ad-Hoc|x86.Build.0 = Debug|Any CPU - {58221C04-F14C-47E3-A802-E5979B4A5630}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU - {58221C04-F14C-47E3-A802-E5979B4A5630}.AppStore|Any CPU.Build.0 = Debug|Any CPU - {58221C04-F14C-47E3-A802-E5979B4A5630}.AppStore|ARM.ActiveCfg = Debug|Any CPU - {58221C04-F14C-47E3-A802-E5979B4A5630}.AppStore|ARM.Build.0 = Debug|Any CPU - {58221C04-F14C-47E3-A802-E5979B4A5630}.AppStore|iPhone.ActiveCfg = Debug|Any CPU - {58221C04-F14C-47E3-A802-E5979B4A5630}.AppStore|iPhone.Build.0 = Debug|Any CPU - {58221C04-F14C-47E3-A802-E5979B4A5630}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {58221C04-F14C-47E3-A802-E5979B4A5630}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU - {58221C04-F14C-47E3-A802-E5979B4A5630}.AppStore|x64.ActiveCfg = Debug|Any CPU - {58221C04-F14C-47E3-A802-E5979B4A5630}.AppStore|x64.Build.0 = Debug|Any CPU - {58221C04-F14C-47E3-A802-E5979B4A5630}.AppStore|x86.ActiveCfg = Debug|Any CPU - {58221C04-F14C-47E3-A802-E5979B4A5630}.AppStore|x86.Build.0 = Debug|Any CPU - {58221C04-F14C-47E3-A802-E5979B4A5630}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {58221C04-F14C-47E3-A802-E5979B4A5630}.Debug|Any CPU.Build.0 = Debug|Any CPU - {58221C04-F14C-47E3-A802-E5979B4A5630}.Debug|ARM.ActiveCfg = Debug|Any CPU - {58221C04-F14C-47E3-A802-E5979B4A5630}.Debug|ARM.Build.0 = Debug|Any CPU - {58221C04-F14C-47E3-A802-E5979B4A5630}.Debug|iPhone.ActiveCfg = Debug|Any CPU - {58221C04-F14C-47E3-A802-E5979B4A5630}.Debug|iPhone.Build.0 = Debug|Any CPU - {58221C04-F14C-47E3-A802-E5979B4A5630}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {58221C04-F14C-47E3-A802-E5979B4A5630}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU - {58221C04-F14C-47E3-A802-E5979B4A5630}.Debug|x64.ActiveCfg = Debug|Any CPU - {58221C04-F14C-47E3-A802-E5979B4A5630}.Debug|x64.Build.0 = Debug|Any CPU - {58221C04-F14C-47E3-A802-E5979B4A5630}.Debug|x86.ActiveCfg = Debug|Any CPU - {58221C04-F14C-47E3-A802-E5979B4A5630}.Debug|x86.Build.0 = Debug|Any CPU - {58221C04-F14C-47E3-A802-E5979B4A5630}.Release|Any CPU.ActiveCfg = Release|Any CPU - {58221C04-F14C-47E3-A802-E5979B4A5630}.Release|Any CPU.Build.0 = Release|Any CPU - {58221C04-F14C-47E3-A802-E5979B4A5630}.Release|ARM.ActiveCfg = Release|Any CPU - {58221C04-F14C-47E3-A802-E5979B4A5630}.Release|ARM.Build.0 = Release|Any CPU - {58221C04-F14C-47E3-A802-E5979B4A5630}.Release|iPhone.ActiveCfg = Release|Any CPU - {58221C04-F14C-47E3-A802-E5979B4A5630}.Release|iPhone.Build.0 = Release|Any CPU - {58221C04-F14C-47E3-A802-E5979B4A5630}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU - {58221C04-F14C-47E3-A802-E5979B4A5630}.Release|iPhoneSimulator.Build.0 = Release|Any CPU - {58221C04-F14C-47E3-A802-E5979B4A5630}.Release|x64.ActiveCfg = Release|Any CPU - {58221C04-F14C-47E3-A802-E5979B4A5630}.Release|x64.Build.0 = Release|Any CPU - {58221C04-F14C-47E3-A802-E5979B4A5630}.Release|x86.ActiveCfg = Release|Any CPU - {58221C04-F14C-47E3-A802-E5979B4A5630}.Release|x86.Build.0 = Release|Any CPU + {76651DAE-FF27-44A4-AF84-34689E2FFDF2}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU + {76651DAE-FF27-44A4-AF84-34689E2FFDF2}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU + {76651DAE-FF27-44A4-AF84-34689E2FFDF2}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU + {76651DAE-FF27-44A4-AF84-34689E2FFDF2}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU + {76651DAE-FF27-44A4-AF84-34689E2FFDF2}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU + {76651DAE-FF27-44A4-AF84-34689E2FFDF2}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU + {76651DAE-FF27-44A4-AF84-34689E2FFDF2}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {76651DAE-FF27-44A4-AF84-34689E2FFDF2}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU + {76651DAE-FF27-44A4-AF84-34689E2FFDF2}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU + {76651DAE-FF27-44A4-AF84-34689E2FFDF2}.Ad-Hoc|x64.Build.0 = Debug|Any CPU + {76651DAE-FF27-44A4-AF84-34689E2FFDF2}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU + {76651DAE-FF27-44A4-AF84-34689E2FFDF2}.Ad-Hoc|x86.Build.0 = Debug|Any CPU + {76651DAE-FF27-44A4-AF84-34689E2FFDF2}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU + {76651DAE-FF27-44A4-AF84-34689E2FFDF2}.AppStore|Any CPU.Build.0 = Debug|Any CPU + {76651DAE-FF27-44A4-AF84-34689E2FFDF2}.AppStore|ARM.ActiveCfg = Debug|Any CPU + {76651DAE-FF27-44A4-AF84-34689E2FFDF2}.AppStore|ARM.Build.0 = Debug|Any CPU + {76651DAE-FF27-44A4-AF84-34689E2FFDF2}.AppStore|iPhone.ActiveCfg = Debug|Any CPU + {76651DAE-FF27-44A4-AF84-34689E2FFDF2}.AppStore|iPhone.Build.0 = Debug|Any CPU + {76651DAE-FF27-44A4-AF84-34689E2FFDF2}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {76651DAE-FF27-44A4-AF84-34689E2FFDF2}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU + {76651DAE-FF27-44A4-AF84-34689E2FFDF2}.AppStore|x64.ActiveCfg = Debug|Any CPU + {76651DAE-FF27-44A4-AF84-34689E2FFDF2}.AppStore|x64.Build.0 = Debug|Any CPU + {76651DAE-FF27-44A4-AF84-34689E2FFDF2}.AppStore|x86.ActiveCfg = Debug|Any CPU + {76651DAE-FF27-44A4-AF84-34689E2FFDF2}.AppStore|x86.Build.0 = Debug|Any CPU + {76651DAE-FF27-44A4-AF84-34689E2FFDF2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {76651DAE-FF27-44A4-AF84-34689E2FFDF2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {76651DAE-FF27-44A4-AF84-34689E2FFDF2}.Debug|ARM.ActiveCfg = Debug|Any CPU + {76651DAE-FF27-44A4-AF84-34689E2FFDF2}.Debug|ARM.Build.0 = Debug|Any CPU + {76651DAE-FF27-44A4-AF84-34689E2FFDF2}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {76651DAE-FF27-44A4-AF84-34689E2FFDF2}.Debug|iPhone.Build.0 = Debug|Any CPU + {76651DAE-FF27-44A4-AF84-34689E2FFDF2}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {76651DAE-FF27-44A4-AF84-34689E2FFDF2}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {76651DAE-FF27-44A4-AF84-34689E2FFDF2}.Debug|x64.ActiveCfg = Debug|Any CPU + {76651DAE-FF27-44A4-AF84-34689E2FFDF2}.Debug|x64.Build.0 = Debug|Any CPU + {76651DAE-FF27-44A4-AF84-34689E2FFDF2}.Debug|x86.ActiveCfg = Debug|Any CPU + {76651DAE-FF27-44A4-AF84-34689E2FFDF2}.Debug|x86.Build.0 = Debug|Any CPU + {76651DAE-FF27-44A4-AF84-34689E2FFDF2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {76651DAE-FF27-44A4-AF84-34689E2FFDF2}.Release|Any CPU.Build.0 = Release|Any CPU + {76651DAE-FF27-44A4-AF84-34689E2FFDF2}.Release|ARM.ActiveCfg = Release|Any CPU + {76651DAE-FF27-44A4-AF84-34689E2FFDF2}.Release|ARM.Build.0 = Release|Any CPU + {76651DAE-FF27-44A4-AF84-34689E2FFDF2}.Release|iPhone.ActiveCfg = Release|Any CPU + {76651DAE-FF27-44A4-AF84-34689E2FFDF2}.Release|iPhone.Build.0 = Release|Any CPU + {76651DAE-FF27-44A4-AF84-34689E2FFDF2}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {76651DAE-FF27-44A4-AF84-34689E2FFDF2}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {76651DAE-FF27-44A4-AF84-34689E2FFDF2}.Release|x64.ActiveCfg = Release|Any CPU + {76651DAE-FF27-44A4-AF84-34689E2FFDF2}.Release|x64.Build.0 = Release|Any CPU + {76651DAE-FF27-44A4-AF84-34689E2FFDF2}.Release|x86.ActiveCfg = Release|Any CPU + {76651DAE-FF27-44A4-AF84-34689E2FFDF2}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1969,7 +1969,7 @@ Global {71587505-2945-4286-BF0B-BA4C004B0BA7} = {91CF7717-08AB-4E65-B10E-0B426F01E2E8} {9C101827-119D-44EE-B0F0-94E7ABA8AE6A} = {71587505-2945-4286-BF0B-BA4C004B0BA7} {773A0C2A-CA6F-4D4A-860B-C518EFA6FACB} = {91CF7717-08AB-4E65-B10E-0B426F01E2E8} - {58221C04-F14C-47E3-A802-E5979B4A5630} = {773A0C2A-CA6F-4D4A-860B-C518EFA6FACB} + {76651DAE-FF27-44A4-AF84-34689E2FFDF2} = {773A0C2A-CA6F-4D4A-860B-C518EFA6FACB} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {25728519-5F0F-4973-8A64-0A81EB4EA8D9} diff --git a/src/Services/TenantACustomisations/Controllers/ValuesController.cs b/src/Services/TenantCustomisations/TenantACustomisations/Controllers/ValuesController.cs similarity index 100% rename from src/Services/TenantACustomisations/Controllers/ValuesController.cs rename to src/Services/TenantCustomisations/TenantACustomisations/Controllers/ValuesController.cs diff --git a/src/Services/TenantACustomisations/Dockerfile b/src/Services/TenantCustomisations/TenantACustomisations/Dockerfile similarity index 99% rename from src/Services/TenantACustomisations/Dockerfile rename to src/Services/TenantCustomisations/TenantACustomisations/Dockerfile index 5a3805dec..30a7e5d1c 100644 --- a/src/Services/TenantACustomisations/Dockerfile +++ b/src/Services/TenantCustomisations/TenantACustomisations/Dockerfile @@ -48,7 +48,7 @@ COPY test/ServicesTests/LoadTest/LoadTest.csproj test/ServicesTests/LoadTest/ RUN dotnet restore eShopOnContainers-ServicesAndWebApps.sln COPY . . -WORKDIR /src/src/Services/TenantCustomisations/TenantACustomisations +WORKDIR /src/src/Services/TenantCustomisations/TenantACustomisations RUN dotnet publish --no-restore -c Release -o /app FROM build AS publish diff --git a/src/Services/TenantACustomisations/Infrastructure/AutofacModules/ApplicationModule.cs b/src/Services/TenantCustomisations/TenantACustomisations/Infrastructure/AutofacModules/ApplicationModule.cs similarity index 100% rename from src/Services/TenantACustomisations/Infrastructure/AutofacModules/ApplicationModule.cs rename to src/Services/TenantCustomisations/TenantACustomisations/Infrastructure/AutofacModules/ApplicationModule.cs diff --git a/src/Services/TenantACustomisations/Infrastructure/AutofacModules/MediatorModule.cs b/src/Services/TenantCustomisations/TenantACustomisations/Infrastructure/AutofacModules/MediatorModule.cs similarity index 100% rename from src/Services/TenantACustomisations/Infrastructure/AutofacModules/MediatorModule.cs rename to src/Services/TenantCustomisations/TenantACustomisations/Infrastructure/AutofacModules/MediatorModule.cs diff --git a/src/Services/TenantACustomisations/Infrastructure/Filters/AuthorizeCheckOperationFilter.cs b/src/Services/TenantCustomisations/TenantACustomisations/Infrastructure/Filters/AuthorizeCheckOperationFilter.cs similarity index 100% rename from src/Services/TenantACustomisations/Infrastructure/Filters/AuthorizeCheckOperationFilter.cs rename to src/Services/TenantCustomisations/TenantACustomisations/Infrastructure/Filters/AuthorizeCheckOperationFilter.cs diff --git a/src/Services/TenantACustomisations/Infrastructure/Filters/HttpGlobalExceptionFilter.cs b/src/Services/TenantCustomisations/TenantACustomisations/Infrastructure/Filters/HttpGlobalExceptionFilter.cs similarity index 100% rename from src/Services/TenantACustomisations/Infrastructure/Filters/HttpGlobalExceptionFilter.cs rename to src/Services/TenantCustomisations/TenantACustomisations/Infrastructure/Filters/HttpGlobalExceptionFilter.cs diff --git a/src/Services/TenantACustomisations/Program.cs b/src/Services/TenantCustomisations/TenantACustomisations/Program.cs similarity index 97% rename from src/Services/TenantACustomisations/Program.cs rename to src/Services/TenantCustomisations/TenantACustomisations/Program.cs index bfe683782..43b52f419 100644 --- a/src/Services/TenantACustomisations/Program.cs +++ b/src/Services/TenantCustomisations/TenantACustomisations/Program.cs @@ -1,5 +1,6 @@ using Microsoft.AspNetCore; using Microsoft.AspNetCore.Hosting; +using Microsoft.eShopOnContainers.Services.TenantACustomisations; using Microsoft.Extensions.Configuration; using Serilog; using System; diff --git a/src/Services/TenantACustomisations/Properties/launchSettings.json b/src/Services/TenantCustomisations/TenantACustomisations/Properties/launchSettings.json similarity index 100% rename from src/Services/TenantACustomisations/Properties/launchSettings.json rename to src/Services/TenantCustomisations/TenantACustomisations/Properties/launchSettings.json diff --git a/src/Services/TenantACustomisations/Startup.cs b/src/Services/TenantCustomisations/TenantACustomisations/Startup.cs similarity index 100% rename from src/Services/TenantACustomisations/Startup.cs rename to src/Services/TenantCustomisations/TenantACustomisations/Startup.cs diff --git a/src/Services/TenantACustomisations/TenantACustomisations.csproj b/src/Services/TenantCustomisations/TenantACustomisations/TenantACustomisations.csproj similarity index 88% rename from src/Services/TenantACustomisations/TenantACustomisations.csproj rename to src/Services/TenantCustomisations/TenantACustomisations/TenantACustomisations.csproj index 606018fed..272a27355 100644 --- a/src/Services/TenantACustomisations/TenantACustomisations.csproj +++ b/src/Services/TenantCustomisations/TenantACustomisations/TenantACustomisations.csproj @@ -48,10 +48,10 @@ - - - - + + + + diff --git a/src/Services/TenantACustomisations/appsettings.Development.json b/src/Services/TenantCustomisations/TenantACustomisations/appsettings.Development.json similarity index 100% rename from src/Services/TenantACustomisations/appsettings.Development.json rename to src/Services/TenantCustomisations/TenantACustomisations/appsettings.Development.json diff --git a/src/Services/TenantACustomisations/appsettings.json b/src/Services/TenantCustomisations/TenantACustomisations/appsettings.json similarity index 100% rename from src/Services/TenantACustomisations/appsettings.json rename to src/Services/TenantCustomisations/TenantACustomisations/appsettings.json From 2be714234b18c752c29004de2058fca601d341b7 Mon Sep 17 00:00:00 2001 From: espent1004 Date: Tue, 19 Nov 2019 20:44:48 +0100 Subject: [PATCH 05/13] More stuff --- docker-compose.override.yml | 5 ++ .../AbstractIntegrationEventHandler.cs | 13 +++++- .../EventBus/Events/IntegrationEvent.cs | 11 +++++ .../EventBusRabbitMQ/EventBusRabbitMQ.cs | 8 ++-- ...CheckoutAcceptedIntegrationEventHandler.cs | 4 +- .../CustomisationEventHandler.cs | 46 +++++++++++++++++++ .../Services/IValidationService.cs | 14 ++++++ .../Services/ValidationService.cs | 17 +++++++ .../TenantACustomisations/Startup.cs | 5 +- .../TenantACustomisations.csproj | 2 +- .../TenantACustomisations/appsettings.json | 30 ++++++++++-- 11 files changed, 141 insertions(+), 14 deletions(-) create mode 100644 src/Services/TenantCustomisations/TenantACustomisations/IntegrationEvents/EventHandling/CustomisationEventHandler.cs create mode 100644 src/Services/TenantCustomisations/TenantACustomisations/Services/IValidationService.cs create mode 100644 src/Services/TenantCustomisations/TenantACustomisations/Services/ValidationService.cs diff --git a/docker-compose.override.yml b/docker-compose.override.yml index 6a9a6448e..8f408c722 100644 --- a/docker-compose.override.yml +++ b/docker-compose.override.yml @@ -63,6 +63,11 @@ services: - "5115:80" tenantacustomisation: + environment: + - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} + - EventBusUserName=${ESHOP_SERVICE_BUS_USERNAME} + - EventBusPassword=${ESHOP_SERVICE_BUS_PASSWORD} + - AzureServiceBusEnabled=False ports: - "5116:80" diff --git a/src/BuildingBlocks/EventBus/EventBus/Abstractions/AbstractIntegrationEventHandler.cs b/src/BuildingBlocks/EventBus/EventBus/Abstractions/AbstractIntegrationEventHandler.cs index c67e082cf..947b1c406 100644 --- a/src/BuildingBlocks/EventBus/EventBus/Abstractions/AbstractIntegrationEventHandler.cs +++ b/src/BuildingBlocks/EventBus/EventBus/Abstractions/AbstractIntegrationEventHandler.cs @@ -13,9 +13,19 @@ namespace Ordering.API.Application.IntegrationEvents.EventHandling { private static String url = @"http://tenantmanager/"; private readonly IEventBus _eventBus; + //private readonly ILogger> _logger; + + protected AbstractIntegrationEventHandler(IEventBus eventBus) + { + _eventBus = eventBus ?? throw new ArgumentNullException(nameof(eventBus)); + } public async Task CheckIfCustomised(IntegrationEvent @event) { + if (!@event.CheckForCustomisation) + { + return false; + } Boolean result = Get(@event); if (result) { @@ -23,7 +33,6 @@ namespace Ordering.API.Application.IntegrationEvents.EventHandling try { //_logger.LogInformation("----- Publishing integration event: {IntegrationEventId} from {AppName} - ({@IntegrationEvent})", eventMessage.Id, Program.AppName, eventMessage); - _eventBus.Publish(customisationEvent); } catch (Exception ex) @@ -58,7 +67,7 @@ namespace Ordering.API.Application.IntegrationEvents.EventHandling } } - return false; + return true; } } diff --git a/src/BuildingBlocks/EventBus/EventBus/Events/IntegrationEvent.cs b/src/BuildingBlocks/EventBus/EventBus/Events/IntegrationEvent.cs index ef09911fe..6536ba721 100644 --- a/src/BuildingBlocks/EventBus/EventBus/Events/IntegrationEvent.cs +++ b/src/BuildingBlocks/EventBus/EventBus/Events/IntegrationEvent.cs @@ -9,6 +9,14 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events { Id = Guid.NewGuid(); CreationDate = DateTime.UtcNow; + CheckForCustomisation = true; + } + + public IntegrationEvent(Boolean checkForCustomisation) + { + Id = Guid.NewGuid(); + CreationDate = DateTime.UtcNow; + CheckForCustomisation = checkForCustomisation; } [JsonConstructor] @@ -23,5 +31,8 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events [JsonProperty] public DateTime CreationDate { get; private set; } + + [JsonProperty] + public Boolean CheckForCustomisation { get; set; } } } diff --git a/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs b/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs index 5623549d5..05af15cf6 100644 --- a/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs +++ b/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs @@ -82,12 +82,12 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ var eventName = @event.GetType().Name; - _logger.LogTrace("Creating RabbitMQ channel to publish event: {EventId} ({EventName})", @event.Id, eventName); + _logger.LogWarning("Creating RabbitMQ channel to publish event: {EventId} ({EventName})", @event.Id, eventName); using (var channel = _persistentConnection.CreateModel()) { - _logger.LogTrace("Declaring RabbitMQ exchange to publish event: {EventId}", @event.Id); + _logger.LogWarning("Declaring RabbitMQ exchange to publish event: {EventId}", @event.Id); channel.ExchangeDeclare(exchange: BROKER_NAME, type: "direct"); @@ -99,7 +99,7 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ var properties = channel.CreateBasicProperties(); properties.DeliveryMode = 2; // persistent - _logger.LogTrace("Publishing event to RabbitMQ: {EventId}", @event.Id); + _logger.LogWarning("Publishing event to RabbitMQ: {EventId}", @event.Id); channel.BasicPublish( exchange: BROKER_NAME, @@ -260,7 +260,7 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ private async Task ProcessEvent(string eventName, string message) { - _logger.LogTrace("Processing RabbitMQ event: {EventName}", eventName); + _logger.LogWarning("Processing RabbitMQ event: {EventName}", eventName); if (_subsManager.HasSubscriptionsForEvent(eventName)) { diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/UserCheckoutAcceptedIntegrationEventHandler.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/UserCheckoutAcceptedIntegrationEventHandler.cs index 5782930f3..7c2615c25 100644 --- a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/UserCheckoutAcceptedIntegrationEventHandler.cs +++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/UserCheckoutAcceptedIntegrationEventHandler.cs @@ -15,14 +15,16 @@ namespace Ordering.API.Application.IntegrationEvents.EventHandling public class UserCheckoutAcceptedIntegrationEventHandler : AbstractIntegrationEventHandler, IIntegrationEventHandler { private readonly IMediator _mediator; + private readonly IEventBus _eventBus; private readonly ILogger _logger; public UserCheckoutAcceptedIntegrationEventHandler( IMediator mediator, - ILogger logger) + ILogger logger, IEventBus eventBus) : base(eventBus) { _mediator = mediator ?? throw new ArgumentNullException(nameof(mediator)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + _eventBus = eventBus ?? throw new ArgumentNullException(nameof(eventBus)); } /// diff --git a/src/Services/TenantCustomisations/TenantACustomisations/IntegrationEvents/EventHandling/CustomisationEventHandler.cs b/src/Services/TenantCustomisations/TenantACustomisations/IntegrationEvents/EventHandling/CustomisationEventHandler.cs new file mode 100644 index 000000000..990afa51c --- /dev/null +++ b/src/Services/TenantCustomisations/TenantACustomisations/IntegrationEvents/EventHandling/CustomisationEventHandler.cs @@ -0,0 +1,46 @@ +using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; +using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; +using Microsoft.Extensions.Logging; +using Ordering.API.Application.IntegrationEvents.Events; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using TenantACustomisations.Services; + +namespace TenantACustomisations.IntegrationEvents.EventHandling +{ + public class CustomisationEventHandler : IIntegrationEventHandler + { + + private readonly ILogger _logger; + private readonly IEventBus _eventBus; + private readonly IValidationService validationService; + + public CustomisationEventHandler(ILogger logger, IEventBus eventBus) + { + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + _eventBus = eventBus ?? throw new ArgumentNullException(nameof(eventBus)); + validationService = new ValidationService(); + } + + public async Task Handle(CustomisationEvent @event) + { + _logger.LogInformation("----- Handling integration event: {IntegrationEventId} - ({@IntegrationEvent})", @event.Id, @event); + IntegrationEvent integrationEvent = @event.@event; + + switch (integrationEvent.GetType().Name) + { + case "UserCheckoutAcceptedIntegrationEvent": + if (validationService.Validate((UserCheckoutAcceptedIntegrationEvent)integrationEvent)) + { + integrationEvent.CheckForCustomisation = false; + _eventBus.Publish(integrationEvent); + } + break; + default: + break; + } + } + } +} diff --git a/src/Services/TenantCustomisations/TenantACustomisations/Services/IValidationService.cs b/src/Services/TenantCustomisations/TenantACustomisations/Services/IValidationService.cs new file mode 100644 index 000000000..cdf5d8172 --- /dev/null +++ b/src/Services/TenantCustomisations/TenantACustomisations/Services/IValidationService.cs @@ -0,0 +1,14 @@ +using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; +using Ordering.API.Application.IntegrationEvents.Events; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace TenantACustomisations.Services +{ + interface IValidationService + { + Boolean Validate(UserCheckoutAcceptedIntegrationEvent @event); + } +} diff --git a/src/Services/TenantCustomisations/TenantACustomisations/Services/ValidationService.cs b/src/Services/TenantCustomisations/TenantACustomisations/Services/ValidationService.cs new file mode 100644 index 000000000..618e9c257 --- /dev/null +++ b/src/Services/TenantCustomisations/TenantACustomisations/Services/ValidationService.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; +using Ordering.API.Application.IntegrationEvents.Events; + +namespace TenantACustomisations.Services +{ + public class ValidationService : IValidationService + { + public bool Validate(UserCheckoutAcceptedIntegrationEvent @event) + { + return @event.State == "Oslo"; + } + } +} diff --git a/src/Services/TenantCustomisations/TenantACustomisations/Startup.cs b/src/Services/TenantCustomisations/TenantACustomisations/Startup.cs index afdb96f30..8aad4f6ee 100644 --- a/src/Services/TenantCustomisations/TenantACustomisations/Startup.cs +++ b/src/Services/TenantCustomisations/TenantACustomisations/Startup.cs @@ -33,6 +33,8 @@ using Infrastructure.AutofacModules; using Microsoft.eShopOnContainers.Services.TenantACustomisations.Infrastructure.Filters; using global::TenantACustomisations.Infrastructure.Filters; + using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; + using global::TenantACustomisations.IntegrationEvents.EventHandling; public class Startup { @@ -112,7 +114,7 @@ { var eventBus = app.ApplicationServices.GetRequiredService(); - //eventBus.Subscribe>(); + eventBus.Subscribe(); } protected virtual void ConfigureAuth(IApplicationBuilder app) @@ -385,6 +387,7 @@ } services.AddSingleton(); + services.AddTransient(); return services; } diff --git a/src/Services/TenantCustomisations/TenantACustomisations/TenantACustomisations.csproj b/src/Services/TenantCustomisations/TenantACustomisations/TenantACustomisations.csproj index 272a27355..44c3fe7ff 100644 --- a/src/Services/TenantCustomisations/TenantACustomisations/TenantACustomisations.csproj +++ b/src/Services/TenantCustomisations/TenantACustomisations/TenantACustomisations.csproj @@ -44,7 +44,6 @@ - @@ -52,6 +51,7 @@ + diff --git a/src/Services/TenantCustomisations/TenantACustomisations/appsettings.json b/src/Services/TenantCustomisations/TenantACustomisations/appsettings.json index def9159a7..76cd21c29 100644 --- a/src/Services/TenantCustomisations/TenantACustomisations/appsettings.json +++ b/src/Services/TenantCustomisations/TenantACustomisations/appsettings.json @@ -1,8 +1,28 @@ { - "Logging": { - "LogLevel": { - "Default": "Warning" + "Serilog": { + "SeqServerUrl": null, + "LogstashgUrl": null, + "MinimumLevel": { + "Default": "Information", + "Override": { + "Microsoft": "Warning", + "Microsoft.eShopOnContainers": "Information", + "System": "Warning" + } } }, - "AllowedHosts": "*" -} + "IdentityUrl": "http://localhost:5105", + "ConnectionString": "127.0.0.1", + "AzureServiceBusEnabled": false, + "SubscriptionClientName": "TenantACustomisation", + "ApplicationInsights": { + "InstrumentationKey": "" + }, + "EventBusRetryCount": 5, + "UseVault": false, + "Vault": { + "Name": "eshop", + "ClientId": "your-clien-id", + "ClientSecret": "your-client-secret" + } +} \ No newline at end of file From 89c5addfe828f56eb27ac2b48b5932224c7251f7 Mon Sep 17 00:00:00 2001 From: espent1004 Date: Tue, 19 Nov 2019 22:39:48 +0100 Subject: [PATCH 06/13] FF --- .../EventBus/EventBus/Events/CustomisationEvent.cs | 2 ++ .../EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs | 1 - .../EventHandling/CustomisationEventHandler.cs | 3 +++ .../TenantCustomisations/TenantACustomisations/Program.cs | 2 +- .../TenantACustomisations/Services/ValidationService.cs | 5 ++--- 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/BuildingBlocks/EventBus/EventBus/Events/CustomisationEvent.cs b/src/BuildingBlocks/EventBus/EventBus/Events/CustomisationEvent.cs index 38b1564a5..695aef7ea 100644 --- a/src/BuildingBlocks/EventBus/EventBus/Events/CustomisationEvent.cs +++ b/src/BuildingBlocks/EventBus/EventBus/Events/CustomisationEvent.cs @@ -10,9 +10,11 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events { TenantId = tenantId; this.@event = @event; + eventType = @event.GetType().Name; } public int TenantId { get; set; } public IntegrationEvent @event { get; set; } + public String eventType { get; set; } } } diff --git a/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs b/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs index 05af15cf6..be7b8abd2 100644 --- a/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs +++ b/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs @@ -257,7 +257,6 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ return channel; } - private async Task ProcessEvent(string eventName, string message) { _logger.LogWarning("Processing RabbitMQ event: {EventName}", eventName); diff --git a/src/Services/TenantCustomisations/TenantACustomisations/IntegrationEvents/EventHandling/CustomisationEventHandler.cs b/src/Services/TenantCustomisations/TenantACustomisations/IntegrationEvents/EventHandling/CustomisationEventHandler.cs index 990afa51c..57321418b 100644 --- a/src/Services/TenantCustomisations/TenantACustomisations/IntegrationEvents/EventHandling/CustomisationEventHandler.cs +++ b/src/Services/TenantCustomisations/TenantACustomisations/IntegrationEvents/EventHandling/CustomisationEventHandler.cs @@ -1,6 +1,7 @@ using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; using Microsoft.Extensions.Logging; +using Newtonsoft.Json; using Ordering.API.Application.IntegrationEvents.Events; using System; using System.Collections.Generic; @@ -39,6 +40,8 @@ namespace TenantACustomisations.IntegrationEvents.EventHandling } break; default: + integrationEvent.CheckForCustomisation = false; + _eventBus.Publish(integrationEvent); break; } } diff --git a/src/Services/TenantCustomisations/TenantACustomisations/Program.cs b/src/Services/TenantCustomisations/TenantACustomisations/Program.cs index 43b52f419..b3e34cf44 100644 --- a/src/Services/TenantCustomisations/TenantACustomisations/Program.cs +++ b/src/Services/TenantCustomisations/TenantACustomisations/Program.cs @@ -6,7 +6,7 @@ using Serilog; using System; using System.IO; -namespace Microsoft.eShopOnContainers.Services.Ordering.API +namespace Microsoft.eShopOnContainers.Services.TenantACustomisations { public class Program { diff --git a/src/Services/TenantCustomisations/TenantACustomisations/Services/ValidationService.cs b/src/Services/TenantCustomisations/TenantACustomisations/Services/ValidationService.cs index 618e9c257..9dbab5b24 100644 --- a/src/Services/TenantCustomisations/TenantACustomisations/Services/ValidationService.cs +++ b/src/Services/TenantCustomisations/TenantACustomisations/Services/ValidationService.cs @@ -1,9 +1,8 @@ -using System; +using Ordering.API.Application.IntegrationEvents.Events; +using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; -using Ordering.API.Application.IntegrationEvents.Events; namespace TenantACustomisations.Services { From 02c644f79a0e61dbaaf954d857aebc31195561d0 Mon Sep 17 00:00:00 2001 From: espent1004 Date: Wed, 20 Nov 2019 11:18:50 +0100 Subject: [PATCH 07/13] .. --- .../AbstractIntegrationEventHandler.cs | 1 + .../Events/CustomisationEvent.cs | 23 +++++++++++++++++++ .../CustomisationEventHandler.cs | 2 ++ .../Events/CustomisationEvent.cs | 9 ++++++-- .../TenantACustomisations/Startup.cs | 1 + .../TenantACustomisations.csproj | 4 ---- 6 files changed, 34 insertions(+), 6 deletions(-) rename src/{BuildingBlocks/EventBus/EventBus/Abstractions => Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling}/AbstractIntegrationEventHandler.cs (97%) create mode 100644 src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/CustomisationEvent.cs rename src/{BuildingBlocks/EventBus/EventBus => Services/TenantCustomisations/TenantACustomisations/IntegrationEvents}/Events/CustomisationEvent.cs (53%) diff --git a/src/BuildingBlocks/EventBus/EventBus/Abstractions/AbstractIntegrationEventHandler.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/AbstractIntegrationEventHandler.cs similarity index 97% rename from src/BuildingBlocks/EventBus/EventBus/Abstractions/AbstractIntegrationEventHandler.cs rename to src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/AbstractIntegrationEventHandler.cs index 947b1c406..15b9de442 100644 --- a/src/BuildingBlocks/EventBus/EventBus/Abstractions/AbstractIntegrationEventHandler.cs +++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/AbstractIntegrationEventHandler.cs @@ -6,6 +6,7 @@ using System.IO; using System.Net.Http; using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; using Microsoft.Extensions.Logging; +using Ordering.API.Application.IntegrationEvents.Events; namespace Ordering.API.Application.IntegrationEvents.EventHandling { diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/CustomisationEvent.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/CustomisationEvent.cs new file mode 100644 index 000000000..e49922640 --- /dev/null +++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/CustomisationEvent.cs @@ -0,0 +1,23 @@ +using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; +using Ordering.API.Application.IntegrationEvents.Events; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Ordering.API.Application.IntegrationEvents.Events +{ + public class CustomisationEvent : IntegrationEvent + { + public CustomisationEvent(int tenantId, IntegrationEvent @event) + { + TenantId = tenantId; + eventType = @event.GetType().Name; + //TODO + userCheckoutAcceptedIntegrationEvent = (UserCheckoutAcceptedIntegrationEvent)@event; + } + + public int TenantId { get; set; } + public String eventType { get; set; } + public UserCheckoutAcceptedIntegrationEvent userCheckoutAcceptedIntegrationEvent { get; set; } + } +} diff --git a/src/Services/TenantCustomisations/TenantACustomisations/IntegrationEvents/EventHandling/CustomisationEventHandler.cs b/src/Services/TenantCustomisations/TenantACustomisations/IntegrationEvents/EventHandling/CustomisationEventHandler.cs index 57321418b..1b753dc2c 100644 --- a/src/Services/TenantCustomisations/TenantACustomisations/IntegrationEvents/EventHandling/CustomisationEventHandler.cs +++ b/src/Services/TenantCustomisations/TenantACustomisations/IntegrationEvents/EventHandling/CustomisationEventHandler.cs @@ -7,7 +7,9 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using TenantACustomisations.IntegrationEvents.Events; using TenantACustomisations.Services; +using CustomisationEvent = TenantACustomisations.IntegrationEvents.Events.CustomisationEvent; namespace TenantACustomisations.IntegrationEvents.EventHandling { diff --git a/src/BuildingBlocks/EventBus/EventBus/Events/CustomisationEvent.cs b/src/Services/TenantCustomisations/TenantACustomisations/IntegrationEvents/Events/CustomisationEvent.cs similarity index 53% rename from src/BuildingBlocks/EventBus/EventBus/Events/CustomisationEvent.cs rename to src/Services/TenantCustomisations/TenantACustomisations/IntegrationEvents/Events/CustomisationEvent.cs index 695aef7ea..42c0607eb 100644 --- a/src/BuildingBlocks/EventBus/EventBus/Events/CustomisationEvent.cs +++ b/src/Services/TenantCustomisations/TenantACustomisations/IntegrationEvents/Events/CustomisationEvent.cs @@ -1,8 +1,10 @@ -using System; +using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; +using Ordering.API.Application.IntegrationEvents.Events; +using System; using System.Collections.Generic; using System.Text; -namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events +namespace TenantACustomisations.IntegrationEvents.Events { public class CustomisationEvent : IntegrationEvent { @@ -11,10 +13,13 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events TenantId = tenantId; this.@event = @event; eventType = @event.GetType().Name; + //TODO + userCheckoutAcceptedIntegrationEvent = (UserCheckoutAcceptedIntegrationEvent)@event; } public int TenantId { get; set; } public IntegrationEvent @event { get; set; } public String eventType { get; set; } + public UserCheckoutAcceptedIntegrationEvent userCheckoutAcceptedIntegrationEvent { get; set; } } } diff --git a/src/Services/TenantCustomisations/TenantACustomisations/Startup.cs b/src/Services/TenantCustomisations/TenantACustomisations/Startup.cs index 8aad4f6ee..dbbed6396 100644 --- a/src/Services/TenantCustomisations/TenantACustomisations/Startup.cs +++ b/src/Services/TenantCustomisations/TenantACustomisations/Startup.cs @@ -35,6 +35,7 @@ using global::TenantACustomisations.Infrastructure.Filters; using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; using global::TenantACustomisations.IntegrationEvents.EventHandling; + using global::TenantACustomisations.IntegrationEvents.Events; public class Startup { diff --git a/src/Services/TenantCustomisations/TenantACustomisations/TenantACustomisations.csproj b/src/Services/TenantCustomisations/TenantACustomisations/TenantACustomisations.csproj index 44c3fe7ff..d21ad07f5 100644 --- a/src/Services/TenantCustomisations/TenantACustomisations/TenantACustomisations.csproj +++ b/src/Services/TenantCustomisations/TenantACustomisations/TenantACustomisations.csproj @@ -42,10 +42,6 @@ - - - - From f1328f721e7c513e8835a6b87f029b76c5cc7d12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Espen=20T=C3=B8nnessen=20Nordli?= Date: Tue, 3 Dec 2019 11:31:35 +0100 Subject: [PATCH 08/13] Revert ".." This reverts commit 02c644f79a0e61dbaaf954d857aebc31195561d0. --- .../AbstractIntegrationEventHandler.cs | 1 - .../EventBus}/Events/CustomisationEvent.cs | 9 ++------ .../Events/CustomisationEvent.cs | 23 ------------------- .../CustomisationEventHandler.cs | 2 -- .../TenantACustomisations/Startup.cs | 1 - .../TenantACustomisations.csproj | 4 ++++ 6 files changed, 6 insertions(+), 34 deletions(-) rename src/{Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling => BuildingBlocks/EventBus/EventBus/Abstractions}/AbstractIntegrationEventHandler.cs (97%) rename src/{Services/TenantCustomisations/TenantACustomisations/IntegrationEvents => BuildingBlocks/EventBus/EventBus}/Events/CustomisationEvent.cs (53%) delete mode 100644 src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/CustomisationEvent.cs diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/AbstractIntegrationEventHandler.cs b/src/BuildingBlocks/EventBus/EventBus/Abstractions/AbstractIntegrationEventHandler.cs similarity index 97% rename from src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/AbstractIntegrationEventHandler.cs rename to src/BuildingBlocks/EventBus/EventBus/Abstractions/AbstractIntegrationEventHandler.cs index 15b9de442..947b1c406 100644 --- a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/AbstractIntegrationEventHandler.cs +++ b/src/BuildingBlocks/EventBus/EventBus/Abstractions/AbstractIntegrationEventHandler.cs @@ -6,7 +6,6 @@ using System.IO; using System.Net.Http; using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; using Microsoft.Extensions.Logging; -using Ordering.API.Application.IntegrationEvents.Events; namespace Ordering.API.Application.IntegrationEvents.EventHandling { diff --git a/src/Services/TenantCustomisations/TenantACustomisations/IntegrationEvents/Events/CustomisationEvent.cs b/src/BuildingBlocks/EventBus/EventBus/Events/CustomisationEvent.cs similarity index 53% rename from src/Services/TenantCustomisations/TenantACustomisations/IntegrationEvents/Events/CustomisationEvent.cs rename to src/BuildingBlocks/EventBus/EventBus/Events/CustomisationEvent.cs index 42c0607eb..695aef7ea 100644 --- a/src/Services/TenantCustomisations/TenantACustomisations/IntegrationEvents/Events/CustomisationEvent.cs +++ b/src/BuildingBlocks/EventBus/EventBus/Events/CustomisationEvent.cs @@ -1,10 +1,8 @@ -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; -using Ordering.API.Application.IntegrationEvents.Events; -using System; +using System; using System.Collections.Generic; using System.Text; -namespace TenantACustomisations.IntegrationEvents.Events +namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events { public class CustomisationEvent : IntegrationEvent { @@ -13,13 +11,10 @@ namespace TenantACustomisations.IntegrationEvents.Events TenantId = tenantId; this.@event = @event; eventType = @event.GetType().Name; - //TODO - userCheckoutAcceptedIntegrationEvent = (UserCheckoutAcceptedIntegrationEvent)@event; } public int TenantId { get; set; } public IntegrationEvent @event { get; set; } public String eventType { get; set; } - public UserCheckoutAcceptedIntegrationEvent userCheckoutAcceptedIntegrationEvent { get; set; } } } diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/CustomisationEvent.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/CustomisationEvent.cs deleted file mode 100644 index e49922640..000000000 --- a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/CustomisationEvent.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; -using Ordering.API.Application.IntegrationEvents.Events; -using System; -using System.Collections.Generic; -using System.Text; - -namespace Ordering.API.Application.IntegrationEvents.Events -{ - public class CustomisationEvent : IntegrationEvent - { - public CustomisationEvent(int tenantId, IntegrationEvent @event) - { - TenantId = tenantId; - eventType = @event.GetType().Name; - //TODO - userCheckoutAcceptedIntegrationEvent = (UserCheckoutAcceptedIntegrationEvent)@event; - } - - public int TenantId { get; set; } - public String eventType { get; set; } - public UserCheckoutAcceptedIntegrationEvent userCheckoutAcceptedIntegrationEvent { get; set; } - } -} diff --git a/src/Services/TenantCustomisations/TenantACustomisations/IntegrationEvents/EventHandling/CustomisationEventHandler.cs b/src/Services/TenantCustomisations/TenantACustomisations/IntegrationEvents/EventHandling/CustomisationEventHandler.cs index 1b753dc2c..57321418b 100644 --- a/src/Services/TenantCustomisations/TenantACustomisations/IntegrationEvents/EventHandling/CustomisationEventHandler.cs +++ b/src/Services/TenantCustomisations/TenantACustomisations/IntegrationEvents/EventHandling/CustomisationEventHandler.cs @@ -7,9 +7,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using TenantACustomisations.IntegrationEvents.Events; using TenantACustomisations.Services; -using CustomisationEvent = TenantACustomisations.IntegrationEvents.Events.CustomisationEvent; namespace TenantACustomisations.IntegrationEvents.EventHandling { diff --git a/src/Services/TenantCustomisations/TenantACustomisations/Startup.cs b/src/Services/TenantCustomisations/TenantACustomisations/Startup.cs index dbbed6396..8aad4f6ee 100644 --- a/src/Services/TenantCustomisations/TenantACustomisations/Startup.cs +++ b/src/Services/TenantCustomisations/TenantACustomisations/Startup.cs @@ -35,7 +35,6 @@ using global::TenantACustomisations.Infrastructure.Filters; using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; using global::TenantACustomisations.IntegrationEvents.EventHandling; - using global::TenantACustomisations.IntegrationEvents.Events; public class Startup { diff --git a/src/Services/TenantCustomisations/TenantACustomisations/TenantACustomisations.csproj b/src/Services/TenantCustomisations/TenantACustomisations/TenantACustomisations.csproj index d21ad07f5..44c3fe7ff 100644 --- a/src/Services/TenantCustomisations/TenantACustomisations/TenantACustomisations.csproj +++ b/src/Services/TenantCustomisations/TenantACustomisations/TenantACustomisations.csproj @@ -42,6 +42,10 @@ + + + + From c3f6bf3698a58fdbaedf8f63e92b6abbe14868ea Mon Sep 17 00:00:00 2001 From: espent1004 Date: Sun, 19 Jan 2020 22:41:44 +0100 Subject: [PATCH 09/13] Progress --- docker-compose.override.yml | 2 + docker-compose.yml | 2 + .../EventBusRabbitMQ/EventBusRabbitMQ.cs | 5 ++ ...CheckoutAcceptedIntegrationEventHandler.cs | 12 ++-- .../Controllers/ValuesController.cs | 17 ++++- .../Database/DbInitializer.cs | 34 ++++++++++ .../Database/TenantAContext.cs | 31 ++++++++++ .../ExternalServices/IRFIDService.cs | 12 ++++ .../ExternalServices/IShippingService.cs | 13 ++++ .../ExternalServices/MockedShippingService.cs | 23 +++++++ .../ExternalServices/Models/Fragility.cs | 12 ++++ .../ExternalServices/Models/Priority.cs | 12 ++++ .../Models/ShippingInformation.cs | 17 +++++ .../AutofacModules/ApplicationModule.cs | 11 +++- ...angedToSubmittedIntegrationEventHandler.cs | 45 ++++++++++++++ ...CheckoutAcceptedIntegrationEventHandler.cs | 60 ++++++++++++++++++ ...tatusChangedToSubmittedIntegrationEvent.cs | 22 +++++++ .../UserCheckoutAcceptedIntegrationEvent.cs | 62 +++++++++++++++++++ .../TenantACustomisations/Program.cs | 1 + .../TenantACustomisations/Startup.cs | 29 +++++---- .../TenantACustomisations.csproj | 4 -- .../TenantACustomisations/appsettings.json | 3 +- src/Web/WebMVC/Controllers/OrderController.cs | 41 ++++++++++++ .../ViewModels/Customisation/Fragility.cs | 12 ++++ .../ViewModels/Customisation/Priority.cs | 12 ++++ .../Customisation/ShippingInformation.cs | 17 +++++ src/Web/WebMVC/Views/Order/Index.cshtml | 43 ++++++++++--- 27 files changed, 516 insertions(+), 38 deletions(-) create mode 100644 src/Services/TenantCustomisations/TenantACustomisations/Database/DbInitializer.cs create mode 100644 src/Services/TenantCustomisations/TenantACustomisations/Database/TenantAContext.cs create mode 100644 src/Services/TenantCustomisations/TenantACustomisations/ExternalServices/IRFIDService.cs create mode 100644 src/Services/TenantCustomisations/TenantACustomisations/ExternalServices/IShippingService.cs create mode 100644 src/Services/TenantCustomisations/TenantACustomisations/ExternalServices/MockedShippingService.cs create mode 100644 src/Services/TenantCustomisations/TenantACustomisations/ExternalServices/Models/Fragility.cs create mode 100644 src/Services/TenantCustomisations/TenantACustomisations/ExternalServices/Models/Priority.cs create mode 100644 src/Services/TenantCustomisations/TenantACustomisations/ExternalServices/Models/ShippingInformation.cs create mode 100644 src/Services/TenantCustomisations/TenantACustomisations/IntegrationEvents/EventHandling/OrderStatusChangedToSubmittedIntegrationEventHandler.cs create mode 100644 src/Services/TenantCustomisations/TenantACustomisations/IntegrationEvents/EventHandling/TenantAUserCheckoutAcceptedIntegrationEventHandler.cs create mode 100644 src/Services/TenantCustomisations/TenantACustomisations/IntegrationEvents/Events/OrderStatusChangedToSubmittedIntegrationEvent.cs create mode 100644 src/Services/TenantCustomisations/TenantACustomisations/IntegrationEvents/Events/UserCheckoutAcceptedIntegrationEvent.cs create mode 100644 src/Web/WebMVC/ViewModels/Customisation/Fragility.cs create mode 100644 src/Web/WebMVC/ViewModels/Customisation/Priority.cs create mode 100644 src/Web/WebMVC/ViewModels/Customisation/ShippingInformation.cs diff --git a/docker-compose.override.yml b/docker-compose.override.yml index 8f408c722..37c19004a 100644 --- a/docker-compose.override.yml +++ b/docker-compose.override.yml @@ -68,6 +68,8 @@ services: - EventBusUserName=${ESHOP_SERVICE_BUS_USERNAME} - EventBusPassword=${ESHOP_SERVICE_BUS_PASSWORD} - AzureServiceBusEnabled=False + - ConnectionString=${ESHOP_AZURE_CATALOG_DB:-Server=sql.data;Database=Microsoft.eShopOnContainers.Services.TenantADb;User Id=sa;Password=Pass@word} + ports: - "5116:80" diff --git a/docker-compose.yml b/docker-compose.yml index 2fbdf2781..4feb44ae0 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -48,6 +48,8 @@ services: build: context: . dockerfile: src/Services/TenantCustomisations/TenantACustomisations/Dockerfile + depends_on: + - sql.data catalog.api: image: ${REGISTRY:-eshop}/catalog.api:${PLATFORM:-linux}-${TAG:-latest} diff --git a/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs b/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs index be7b8abd2..44137abae 100644 --- a/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs +++ b/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs @@ -12,6 +12,7 @@ using RabbitMQ.Client; using RabbitMQ.Client.Events; using RabbitMQ.Client.Exceptions; using System; +using System.Diagnostics; using System.Net.Sockets; using System.Text; using System.Threading.Tasks; @@ -280,6 +281,10 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ else { var handler = scope.ResolveOptional(subscription.HandlerType); + if (eventName.Equals("OrderStatusChangedToSubmittedIntegrationEvent") || eventName.Equals("UserCheckoutAcceptedIntegrationEvent")) + { + Debug.WriteLine("Here"); + } if (handler == null) continue; var eventType = _subsManager.GetEventTypeByName(eventName); var integrationEvent = JsonConvert.DeserializeObject(message, eventType); diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/UserCheckoutAcceptedIntegrationEventHandler.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/UserCheckoutAcceptedIntegrationEventHandler.cs index 7c2615c25..314c35faa 100644 --- a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/UserCheckoutAcceptedIntegrationEventHandler.cs +++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/UserCheckoutAcceptedIntegrationEventHandler.cs @@ -12,7 +12,7 @@ using System; namespace Ordering.API.Application.IntegrationEvents.EventHandling { - public class UserCheckoutAcceptedIntegrationEventHandler : AbstractIntegrationEventHandler, IIntegrationEventHandler + public class UserCheckoutAcceptedIntegrationEventHandler : IIntegrationEventHandler { private readonly IMediator _mediator; private readonly IEventBus _eventBus; @@ -20,7 +20,7 @@ namespace Ordering.API.Application.IntegrationEvents.EventHandling public UserCheckoutAcceptedIntegrationEventHandler( IMediator mediator, - ILogger logger, IEventBus eventBus) : base(eventBus) + ILogger logger, IEventBus eventBus) { _mediator = mediator ?? throw new ArgumentNullException(nameof(mediator)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); @@ -42,9 +42,9 @@ namespace Ordering.API.Application.IntegrationEvents.EventHandling { _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event); - var customised = await CheckIfCustomised(@event); - if (!customised) - { + //var customised = await CheckIfCustomised(@event); + //if (!customised) + //{ var result = false; if (@event.RequestId != Guid.Empty) @@ -81,7 +81,7 @@ namespace Ordering.API.Application.IntegrationEvents.EventHandling { _logger.LogWarning("Invalid IntegrationEvent - RequestId is missing - {@IntegrationEvent}", @event); } - } + //} } } } diff --git a/src/Services/TenantCustomisations/TenantACustomisations/Controllers/ValuesController.cs b/src/Services/TenantCustomisations/TenantACustomisations/Controllers/ValuesController.cs index e297683b6..ff8ef509b 100644 --- a/src/Services/TenantCustomisations/TenantACustomisations/Controllers/ValuesController.cs +++ b/src/Services/TenantCustomisations/TenantACustomisations/Controllers/ValuesController.cs @@ -3,6 +3,9 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using TenantACustomisations.Database; +using TenantACustomisations.ExternalServices; namespace TenantACustomisations.Controllers { @@ -10,11 +13,21 @@ namespace TenantACustomisations.Controllers [ApiController] public class ValuesController : ControllerBase { + + private readonly TenantAContext _context; + + public ValuesController(TenantAContext context) + { + _context = context ?? throw new ArgumentNullException(nameof(context)); + } + + + // GET api/values [HttpGet] - public ActionResult> Get() + public async Task>> GetShippingInformation() { - return new string[] { "value1", "value2" }; + return await _context.ShippingInformation.ToListAsync(); } // GET api/values/5 diff --git a/src/Services/TenantCustomisations/TenantACustomisations/Database/DbInitializer.cs b/src/Services/TenantCustomisations/TenantACustomisations/Database/DbInitializer.cs new file mode 100644 index 000000000..acea47b5f --- /dev/null +++ b/src/Services/TenantCustomisations/TenantACustomisations/Database/DbInitializer.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using TenantACustomisations.ExternalServices; + +namespace TenantACustomisations.Database +{ + public class DbInitializer + { + public void Initialize(TenantAContext context) + { + context.Database.EnsureCreated(); + + if (context.ShippingInformation.Any()) + { + return; + } + + ShippingInformation shippingInformation = new ShippingInformation(); + shippingInformation.ShippingTime = DateTime.Today; + shippingInformation.ArrivalTime = DateTime.Today.AddDays(2); + shippingInformation.FragilityLevel = Fragility.Medium; + shippingInformation.PriorityLevel = Priority.High; + shippingInformation.ShippingInformationId = 1; + shippingInformation.OrderNumber = 1; + context.ShippingInformation.Add(shippingInformation); + + context.SaveChanges(); + + + } + } +} diff --git a/src/Services/TenantCustomisations/TenantACustomisations/Database/TenantAContext.cs b/src/Services/TenantCustomisations/TenantACustomisations/Database/TenantAContext.cs new file mode 100644 index 000000000..0f893e3b5 --- /dev/null +++ b/src/Services/TenantCustomisations/TenantACustomisations/Database/TenantAContext.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Design; +using TenantACustomisations.ExternalServices; + +namespace TenantACustomisations.Database +{ + public class TenantAContext : DbContext + { + public TenantAContext(DbContextOptions options) + : base(options) + { + } + + public DbSet ShippingInformation { get; set; } + + } + public class TenantAContextDesignFactory : IDesignTimeDbContextFactory + { + public TenantAContext CreateDbContext(string[] args) + { + var optionsBuilder = new DbContextOptionsBuilder() + .UseSqlServer("Server=.;Initial Catalog=Microsoft.eShopOnContainers.Services.TenantADb;Integrated Security=true"); + + return new TenantAContext(optionsBuilder.Options); + } + } +} diff --git a/src/Services/TenantCustomisations/TenantACustomisations/ExternalServices/IRFIDService.cs b/src/Services/TenantCustomisations/TenantACustomisations/ExternalServices/IRFIDService.cs new file mode 100644 index 000000000..bc52c2fc3 --- /dev/null +++ b/src/Services/TenantCustomisations/TenantACustomisations/ExternalServices/IRFIDService.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace TenantACustomisations.ExternalServices +{ + public interface IRFIDService + { + bool IsOrderRFIDTagged(int orderNumber); + } +} diff --git a/src/Services/TenantCustomisations/TenantACustomisations/ExternalServices/IShippingService.cs b/src/Services/TenantCustomisations/TenantACustomisations/ExternalServices/IShippingService.cs new file mode 100644 index 000000000..3db814143 --- /dev/null +++ b/src/Services/TenantCustomisations/TenantACustomisations/ExternalServices/IShippingService.cs @@ -0,0 +1,13 @@ +using Ordering.API.Application.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace TenantACustomisations.ExternalServices +{ + public interface IShippingService + { + ShippingInformation CalculateShippingInformation(int orderId); + } +} diff --git a/src/Services/TenantCustomisations/TenantACustomisations/ExternalServices/MockedShippingService.cs b/src/Services/TenantCustomisations/TenantACustomisations/ExternalServices/MockedShippingService.cs new file mode 100644 index 000000000..b3561d50b --- /dev/null +++ b/src/Services/TenantCustomisations/TenantACustomisations/ExternalServices/MockedShippingService.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Ordering.API.Application.Models; + +namespace TenantACustomisations.ExternalServices +{ + public class MockedShippingService : IShippingService + { + public ShippingInformation CalculateShippingInformation(int orderId) + { + ShippingInformation shippingInformation = new ShippingInformation(); + shippingInformation.ShippingTime = DateTime.Today; + shippingInformation.ArrivalTime = DateTime.Today.AddDays(2); + shippingInformation.FragilityLevel = Fragility.Medium; + shippingInformation.PriorityLevel = Priority.High; + shippingInformation.OrderNumber = orderId; + + return shippingInformation; + } + } +} diff --git a/src/Services/TenantCustomisations/TenantACustomisations/ExternalServices/Models/Fragility.cs b/src/Services/TenantCustomisations/TenantACustomisations/ExternalServices/Models/Fragility.cs new file mode 100644 index 000000000..a2afffc22 --- /dev/null +++ b/src/Services/TenantCustomisations/TenantACustomisations/ExternalServices/Models/Fragility.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace TenantACustomisations.ExternalServices +{ + public enum Fragility + { + Low, Medium, High + } +} diff --git a/src/Services/TenantCustomisations/TenantACustomisations/ExternalServices/Models/Priority.cs b/src/Services/TenantCustomisations/TenantACustomisations/ExternalServices/Models/Priority.cs new file mode 100644 index 000000000..cd0efcb73 --- /dev/null +++ b/src/Services/TenantCustomisations/TenantACustomisations/ExternalServices/Models/Priority.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace TenantACustomisations.ExternalServices +{ + public enum Priority + { + Low, Medium, High + } +} diff --git a/src/Services/TenantCustomisations/TenantACustomisations/ExternalServices/Models/ShippingInformation.cs b/src/Services/TenantCustomisations/TenantACustomisations/ExternalServices/Models/ShippingInformation.cs new file mode 100644 index 000000000..f83a7d5cb --- /dev/null +++ b/src/Services/TenantCustomisations/TenantACustomisations/ExternalServices/Models/ShippingInformation.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace TenantACustomisations.ExternalServices +{ + public class ShippingInformation + { + public int ShippingInformationId { get; set; } + public DateTime ArrivalTime { get; set; } + public DateTime ShippingTime { get; set; } + public Priority PriorityLevel {get;set;} + public Fragility FragilityLevel { get; set; } + public String OrderNumber { get; set; } + } +} diff --git a/src/Services/TenantCustomisations/TenantACustomisations/Infrastructure/AutofacModules/ApplicationModule.cs b/src/Services/TenantCustomisations/TenantACustomisations/Infrastructure/AutofacModules/ApplicationModule.cs index 69cc1d12a..ea46f0586 100644 --- a/src/Services/TenantCustomisations/TenantACustomisations/Infrastructure/AutofacModules/ApplicationModule.cs +++ b/src/Services/TenantCustomisations/TenantACustomisations/Infrastructure/AutofacModules/ApplicationModule.cs @@ -1,5 +1,8 @@ using Autofac; +using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; using System.Reflection; +using TenantACustomisations.ExternalServices; +using TenantACustomisations.IntegrationEvents.Events; namespace Microsoft.eShopOnContainers.Services.TenantACustomisations.Infrastructure.AutofacModules { @@ -18,7 +21,13 @@ namespace Microsoft.eShopOnContainers.Services.TenantACustomisations.Infrastruct protected override void Load(ContainerBuilder builder) { - //TODO + builder.RegisterAssemblyTypes(typeof(UserCheckoutAcceptedIntegrationEvent).GetTypeInfo().Assembly) + .AsClosedTypesOf(typeof(IIntegrationEventHandler<>)); + + + builder.RegisterType() + .As() + .InstancePerLifetimeScope(); } } } diff --git a/src/Services/TenantCustomisations/TenantACustomisations/IntegrationEvents/EventHandling/OrderStatusChangedToSubmittedIntegrationEventHandler.cs b/src/Services/TenantCustomisations/TenantACustomisations/IntegrationEvents/EventHandling/OrderStatusChangedToSubmittedIntegrationEventHandler.cs new file mode 100644 index 000000000..78cb7a46d --- /dev/null +++ b/src/Services/TenantCustomisations/TenantACustomisations/IntegrationEvents/EventHandling/OrderStatusChangedToSubmittedIntegrationEventHandler.cs @@ -0,0 +1,45 @@ +using Microsoft.AspNetCore.SignalR; +using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; +using Microsoft.Extensions.Logging; +using Serilog.Context; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Threading.Tasks; +using TenantACustomisations.Database; +using TenantACustomisations.ExternalServices; +using TenantACustomisations.IntegrationEvents.Events; + +namespace TenantACustomisations.IntegrationEvents.EventHandling +{ + public class OrderStatusChangedToSubmittedIntegrationEventHandler : + IIntegrationEventHandler + { + private readonly ILogger _logger; + private readonly IShippingService _shippingService; + private readonly TenantAContext _context; + + public OrderStatusChangedToSubmittedIntegrationEventHandler(ILogger logger, IShippingService shippingService, TenantAContext context) + { + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + _shippingService = shippingService ?? throw new ArgumentNullException(nameof(shippingService)); + _context = context ?? throw new ArgumentNullException(nameof(shippingService)); + } + + public async Task Handle(OrderStatusChangedToSubmittedIntegrationEvent @event) + { + using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}- TenantA")) + { + _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at TenantA - ({@IntegrationEvent})", @event.Id, @event); + _logger.LogInformation("Hello"); + //TODO + Debug.WriteLine(@event); + ShippingInformation shippingInformation = _shippingService.CalculateShippingInformation(@event.OrderId); + _context.ShippingInformation.Add(shippingInformation); + _logger.LogInformation("----- Saving shipping information: {IntegrationEventId} at TenantA - ({@IntegrationEvent}) - {@ShippingInformation}", @event.Id, @event, shippingInformation); + _context.SaveChanges(); + } + } + } +} \ No newline at end of file diff --git a/src/Services/TenantCustomisations/TenantACustomisations/IntegrationEvents/EventHandling/TenantAUserCheckoutAcceptedIntegrationEventHandler.cs b/src/Services/TenantCustomisations/TenantACustomisations/IntegrationEvents/EventHandling/TenantAUserCheckoutAcceptedIntegrationEventHandler.cs new file mode 100644 index 000000000..fb8196ebf --- /dev/null +++ b/src/Services/TenantCustomisations/TenantACustomisations/IntegrationEvents/EventHandling/TenantAUserCheckoutAcceptedIntegrationEventHandler.cs @@ -0,0 +1,60 @@ +using MediatR; +using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; +using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Extensions; +using Microsoft.Extensions.Logging; +using Ordering.API.Application.Behaviors; +using Serilog.Context; +using System.Threading.Tasks; +using System; +using System.Diagnostics; +using TenantACustomisations.IntegrationEvents.Events; +using TenantACustomisations.ExternalServices; +using TenantACustomisations.Database; + +namespace TenantACustomisations.IntegrationEvents.EventHandling +{ + public class TenantAUserCheckoutAcceptedIntegrationEventHandler : + IIntegrationEventHandler + { + private readonly IMediator _mediator; + private readonly IEventBus _eventBus; + private readonly ILogger _logger; + //private readonly TenantAContext _context; + //private readonly IShippingService _shippingService; + + public TenantAUserCheckoutAcceptedIntegrationEventHandler( + IMediator mediator, + ILogger logger, + IEventBus eventBus + ) + { + _mediator = mediator ?? throw new ArgumentNullException(nameof(mediator)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + _eventBus = eventBus ?? throw new ArgumentNullException(nameof(eventBus)); + } + + /// + /// Integration event handler which starts the create order process + /// + /// + /// Integration event message which is sent by the + /// basket.api once it has successfully process the + /// order items. + /// + /// + public async Task Handle(UserCheckoutAcceptedIntegrationEvent @event) + { + using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}- TenantA")) + { + _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at TenantA- ({@IntegrationEvent})", @event.Id, @event); + _logger.LogInformation("Hello"); + + //TODO + Debug.WriteLine(@event); + //Save shipping info + //Hard code view comp + //Retrieve shipping info and show + } + } + } +} \ No newline at end of file diff --git a/src/Services/TenantCustomisations/TenantACustomisations/IntegrationEvents/Events/OrderStatusChangedToSubmittedIntegrationEvent.cs b/src/Services/TenantCustomisations/TenantACustomisations/IntegrationEvents/Events/OrderStatusChangedToSubmittedIntegrationEvent.cs new file mode 100644 index 000000000..12a759508 --- /dev/null +++ b/src/Services/TenantCustomisations/TenantACustomisations/IntegrationEvents/Events/OrderStatusChangedToSubmittedIntegrationEvent.cs @@ -0,0 +1,22 @@ +using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace TenantACustomisations.IntegrationEvents.Events +{ + public class OrderStatusChangedToSubmittedIntegrationEvent : IntegrationEvent + { + public int OrderId { get; } + public string OrderStatus { get; } + public string BuyerName { get; } + + public OrderStatusChangedToSubmittedIntegrationEvent(int orderId, string orderStatus, string buyerName) + { + OrderId = orderId; + OrderStatus = orderStatus; + BuyerName = buyerName; + } + } +} diff --git a/src/Services/TenantCustomisations/TenantACustomisations/IntegrationEvents/Events/UserCheckoutAcceptedIntegrationEvent.cs b/src/Services/TenantCustomisations/TenantACustomisations/IntegrationEvents/Events/UserCheckoutAcceptedIntegrationEvent.cs new file mode 100644 index 000000000..7f6fa4a36 --- /dev/null +++ b/src/Services/TenantCustomisations/TenantACustomisations/IntegrationEvents/Events/UserCheckoutAcceptedIntegrationEvent.cs @@ -0,0 +1,62 @@ +using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; +using Ordering.API.Application.Models; +using System; + +namespace TenantACustomisations.IntegrationEvents.Events +{ + public class UserCheckoutAcceptedIntegrationEvent : IntegrationEvent + { + public string UserId { get; } + + public string UserName { get; } + + public string City { get; set; } + + public string Street { get; set; } + + public string State { get; set; } + + public string Country { get; set; } + + public string ZipCode { get; set; } + + public string CardNumber { get; set; } + + public string CardHolderName { get; set; } + + public DateTime CardExpiration { get; set; } + + public string CardSecurityNumber { get; set; } + + public int CardTypeId { get; set; } + + public string Buyer { get; set; } + + public Guid RequestId { get; set; } + + public CustomerBasket Basket { get; } + + public UserCheckoutAcceptedIntegrationEvent(string userId, string userName, string city, string street, + string state, string country, string zipCode, string cardNumber, string cardHolderName, + DateTime cardExpiration, string cardSecurityNumber, int cardTypeId, string buyer, Guid requestId, + CustomerBasket basket) + { + UserId = userId; + City = city; + Street = street; + State = state; + Country = country; + ZipCode = zipCode; + CardNumber = cardNumber; + CardHolderName = cardHolderName; + CardExpiration = cardExpiration; + CardSecurityNumber = cardSecurityNumber; + CardTypeId = cardTypeId; + Buyer = buyer; + Basket = basket; + RequestId = requestId; + UserName = userName; + } + + } +} diff --git a/src/Services/TenantCustomisations/TenantACustomisations/Program.cs b/src/Services/TenantCustomisations/TenantACustomisations/Program.cs index b3e34cf44..f1a3015e3 100644 --- a/src/Services/TenantCustomisations/TenantACustomisations/Program.cs +++ b/src/Services/TenantCustomisations/TenantACustomisations/Program.cs @@ -5,6 +5,7 @@ using Microsoft.Extensions.Configuration; using Serilog; using System; using System.IO; +using TenantACustomisations.Database; namespace Microsoft.eShopOnContainers.Services.TenantACustomisations { diff --git a/src/Services/TenantCustomisations/TenantACustomisations/Startup.cs b/src/Services/TenantCustomisations/TenantACustomisations/Startup.cs index 8aad4f6ee..c8f551829 100644 --- a/src/Services/TenantCustomisations/TenantACustomisations/Startup.cs +++ b/src/Services/TenantCustomisations/TenantACustomisations/Startup.cs @@ -35,6 +35,9 @@ using global::TenantACustomisations.Infrastructure.Filters; using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; using global::TenantACustomisations.IntegrationEvents.EventHandling; + using global::TenantACustomisations.IntegrationEvents.Events; + using global::TenantACustomisations.ExternalServices; + using global::TenantACustomisations.Database; public class Startup { @@ -107,6 +110,11 @@ }); ConfigureEventBus(app); + using (var serviceScope = app.ApplicationServices.GetService().CreateScope()) + { + var context = serviceScope.ServiceProvider.GetRequiredService(); + context.Database.EnsureCreated(); + } } @@ -114,7 +122,9 @@ { var eventBus = app.ApplicationServices.GetRequiredService(); - eventBus.Subscribe(); + //eventBus.Subscribe>(); + eventBus.Subscribe(); + } protected virtual void ConfigureAuth(IApplicationBuilder app) @@ -210,18 +220,8 @@ public static IServiceCollection AddCustomDbContext(this IServiceCollection services, IConfiguration configuration) { - //services.AddEntityFrameworkSqlServer() - // .AddDbContext(options => - // { - // options.UseSqlServer(configuration["ConnectionString"], - // sqlServerOptionsAction: sqlOptions => - // { - // sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name); - // sqlOptions.EnableRetryOnFailure(maxRetryCount: 10, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null); - // }); - // }, - // ServiceLifetime.Scoped //Showing explicitly that the DbContext is shared across the HTTP request scope (graph of objects started in the HTTP request) - // ); + services.AddDbContext(options => + options.UseSqlServer(configuration["ConnectionString"])); services.AddDbContext(options => { @@ -276,7 +276,6 @@ sp => (DbConnection c) => new IntegrationEventLogService(c)); //services.AddTransient(); - if (configuration.GetValue("AzureServiceBusEnabled")) { services.AddSingleton(sp => @@ -387,7 +386,7 @@ } services.AddSingleton(); - services.AddTransient(); + //services.AddTransient(); return services; } diff --git a/src/Services/TenantCustomisations/TenantACustomisations/TenantACustomisations.csproj b/src/Services/TenantCustomisations/TenantACustomisations/TenantACustomisations.csproj index 44c3fe7ff..d21ad07f5 100644 --- a/src/Services/TenantCustomisations/TenantACustomisations/TenantACustomisations.csproj +++ b/src/Services/TenantCustomisations/TenantACustomisations/TenantACustomisations.csproj @@ -42,10 +42,6 @@ - - - - diff --git a/src/Services/TenantCustomisations/TenantACustomisations/appsettings.json b/src/Services/TenantCustomisations/TenantACustomisations/appsettings.json index 76cd21c29..55e48a978 100644 --- a/src/Services/TenantCustomisations/TenantACustomisations/appsettings.json +++ b/src/Services/TenantCustomisations/TenantACustomisations/appsettings.json @@ -12,7 +12,8 @@ } }, "IdentityUrl": "http://localhost:5105", - "ConnectionString": "127.0.0.1", + //"ConnectionString": "127.0.0.1", + "ConnectionString": "Server=tcp:127.0.0.1,5433;Database=Microsoft.eShopOnContainers.Services.TenantADb;User Id=sa;Password=Pass@word;", "AzureServiceBusEnabled": false, "SubscriptionClientName": "TenantACustomisation", "ApplicationInsights": { diff --git a/src/Web/WebMVC/Controllers/OrderController.cs b/src/Web/WebMVC/Controllers/OrderController.cs index cb5234e3c..1c3cff632 100644 --- a/src/Web/WebMVC/Controllers/OrderController.cs +++ b/src/Web/WebMVC/Controllers/OrderController.cs @@ -2,7 +2,14 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.eShopOnContainers.WebMVC.Services; using Microsoft.eShopOnContainers.WebMVC.ViewModels; +using Microsoft.eShopOnContainers.WebMVC.ViewModels.Customisation; +using Newtonsoft.Json; using Polly.CircuitBreaker; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Net.Http; using System.Threading.Tasks; namespace Microsoft.eShopOnContainers.WebMVC.Controllers @@ -13,6 +20,8 @@ namespace Microsoft.eShopOnContainers.WebMVC.Controllers private IOrderingService _orderSvc; private IBasketService _basketSvc; private readonly IIdentityParser _appUserParser; + private static String url = @"http://tenantacustomisation/"; + public OrderController(IOrderingService orderSvc, IBasketService basketSvc, IIdentityParser appUserParser) { _appUserParser = appUserParser; @@ -75,7 +84,39 @@ namespace Microsoft.eShopOnContainers.WebMVC.Controllers { var user = _appUserParser.Parse(HttpContext.User); var vm = await _orderSvc.GetMyOrders(user); + List shippingInformation = GetShippingInfo(vm); + ViewData["ShippingInfo"] = shippingInformation; return View(vm); } + + private List GetShippingInfo(List orders) + { + List shippingInformation = new List(); + using (var client = new HttpClient(new HttpClientHandler { AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate })) + { + client.BaseAddress = new Uri(url); + try + { + HttpResponseMessage response = client.GetAsync("api/shippinginformation").Result; + response.EnsureSuccessStatusCode(); + string result = response.Content.ReadAsStringAsync().Result; + List results = JsonConvert.DeserializeObject>(result); + results.ForEach( s => + { + if(orders.Any(item => item.OrderNumber.Equals(s.OrderNumber))) + { + shippingInformation.Add(s); + } + }); + + } + catch (Exception e) + { + Console.WriteLine(e); + } + } + + return shippingInformation; + } } } \ No newline at end of file diff --git a/src/Web/WebMVC/ViewModels/Customisation/Fragility.cs b/src/Web/WebMVC/ViewModels/Customisation/Fragility.cs new file mode 100644 index 000000000..f08ea09f8 --- /dev/null +++ b/src/Web/WebMVC/ViewModels/Customisation/Fragility.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Microsoft.eShopOnContainers.WebMVC.ViewModels.Customisation +{ + public enum Fragility + { + Low, Medium, High + } +} diff --git a/src/Web/WebMVC/ViewModels/Customisation/Priority.cs b/src/Web/WebMVC/ViewModels/Customisation/Priority.cs new file mode 100644 index 000000000..a8060fcae --- /dev/null +++ b/src/Web/WebMVC/ViewModels/Customisation/Priority.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Microsoft.eShopOnContainers.WebMVC.ViewModels.Customisation +{ + public enum Priority + { + Low, Medium, High + } +} diff --git a/src/Web/WebMVC/ViewModels/Customisation/ShippingInformation.cs b/src/Web/WebMVC/ViewModels/Customisation/ShippingInformation.cs new file mode 100644 index 000000000..a9c866b07 --- /dev/null +++ b/src/Web/WebMVC/ViewModels/Customisation/ShippingInformation.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Microsoft.eShopOnContainers.WebMVC.ViewModels.Customisation +{ + public class ShippingInformation + { + public int ShippingInformationId { get; set; } + public DateTime ArrivalTime { get; set; } + public DateTime ShippingTime { get; set; } + public Priority PriorityLevel { get; set; } + public Fragility FragilityLevel { get; set; } + public String OrderNumber { get; set; } + } +} diff --git a/src/Web/WebMVC/Views/Order/Index.cshtml b/src/Web/WebMVC/Views/Order/Index.cshtml index d3247433c..48da48d1f 100644 --- a/src/Web/WebMVC/Views/Order/Index.cshtml +++ b/src/Web/WebMVC/Views/Order/Index.cshtml @@ -1,25 +1,31 @@ @using Microsoft.eShopOnContainers.WebMVC.ViewModels +@using Microsoft.eShopOnContainers.WebMVC.ViewModels.Customisation @model IEnumerable @{ - ViewData["Title"] = "My Orders"; - var headerList= new List
() { + ViewData["Title"] = "My Orders"; + var headerList = new List
() { new Header() { Controller = "Catalog", Text = "Back to catalog" }, new Header() { Text = " / " }, new Header() { Controller = "OrderManagement", Text = "Orders Management" } }; + var shippingInfo = ViewData["ShippingInfo"] as List; + }
- +
Order number
-
Date
-
Total
-
Status
+
Date
+
Total
+
Status
+
Shipping date
+
Estimated arrival date
+
@if (Model != null && Model.Any()) { @@ -27,9 +33,28 @@ {
@Html.DisplayFor(modelItem => item.OrderNumber)
-
@Html.DisplayFor(modelItem => item.Date)
-
$ @Html.DisplayFor(modelItem => item.Total)
-
@Html.DisplayFor(modelItem => item.Status)
+
@Html.DisplayFor(modelItem => item.Date)
+
$ @Html.DisplayFor(modelItem => item.Total)
+
@Html.DisplayFor(modelItem => item.Status)
+
+ @for (var i = 0; i < shippingInfo.Count(); i++) + { + var si = shippingInfo[i]; + if (si.OrderNumber.Equals(item.OrderNumber)){ + @si.ShippingTime + } + } +
+
+ @for (var i = 0; i < shippingInfo.Count(); i++) + { + var si = shippingInfo[i]; + if (si.OrderNumber.Equals(item.OrderNumber)) + { + @si.ArrivalTime + } + } +
Detail
From 6f2a89481a6a6917002de3b555c23b26773b1e3a Mon Sep 17 00:00:00 2001 From: espent1004 Date: Sun, 19 Jan 2020 23:09:11 +0100 Subject: [PATCH 10/13] Fix --- .../TenantACustomisations/Database/DbInitializer.cs | 2 +- .../ExternalServices/MockedShippingService.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Services/TenantCustomisations/TenantACustomisations/Database/DbInitializer.cs b/src/Services/TenantCustomisations/TenantACustomisations/Database/DbInitializer.cs index acea47b5f..1c2aa2da7 100644 --- a/src/Services/TenantCustomisations/TenantACustomisations/Database/DbInitializer.cs +++ b/src/Services/TenantCustomisations/TenantACustomisations/Database/DbInitializer.cs @@ -23,7 +23,7 @@ namespace TenantACustomisations.Database shippingInformation.FragilityLevel = Fragility.Medium; shippingInformation.PriorityLevel = Priority.High; shippingInformation.ShippingInformationId = 1; - shippingInformation.OrderNumber = 1; + shippingInformation.OrderNumber = "1"; context.ShippingInformation.Add(shippingInformation); context.SaveChanges(); diff --git a/src/Services/TenantCustomisations/TenantACustomisations/ExternalServices/MockedShippingService.cs b/src/Services/TenantCustomisations/TenantACustomisations/ExternalServices/MockedShippingService.cs index b3561d50b..7dc39a90b 100644 --- a/src/Services/TenantCustomisations/TenantACustomisations/ExternalServices/MockedShippingService.cs +++ b/src/Services/TenantCustomisations/TenantACustomisations/ExternalServices/MockedShippingService.cs @@ -15,7 +15,7 @@ namespace TenantACustomisations.ExternalServices shippingInformation.ArrivalTime = DateTime.Today.AddDays(2); shippingInformation.FragilityLevel = Fragility.Medium; shippingInformation.PriorityLevel = Priority.High; - shippingInformation.OrderNumber = orderId; + shippingInformation.OrderNumber = orderId.ToString(); return shippingInformation; } From 07e2d6ef7e1f7dd61d67bafc0bd91e972ff4dad0 Mon Sep 17 00:00:00 2001 From: espent1004 Date: Mon, 20 Jan 2020 10:14:10 +0100 Subject: [PATCH 11/13] Endpoint --- .../ShippingInformationsController.cs | 106 ++++++++++++++++++ .../TenantACustomisations.csproj | 1 + 2 files changed, 107 insertions(+) create mode 100644 src/Services/TenantCustomisations/TenantACustomisations/Controllers/ShippingInformationsController.cs diff --git a/src/Services/TenantCustomisations/TenantACustomisations/Controllers/ShippingInformationsController.cs b/src/Services/TenantCustomisations/TenantACustomisations/Controllers/ShippingInformationsController.cs new file mode 100644 index 000000000..a62c1c98e --- /dev/null +++ b/src/Services/TenantCustomisations/TenantACustomisations/Controllers/ShippingInformationsController.cs @@ -0,0 +1,106 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using TenantACustomisations.Database; +using TenantACustomisations.ExternalServices; + +namespace TenantACustomisations.Controllers +{ + [Route("api/[controller]")] + [ApiController] + public class ShippingInformationsController : ControllerBase + { + private readonly TenantAContext _context; + + public ShippingInformationsController(TenantAContext context) + { + _context = context; + } + + // GET: api/ShippingInformations + [HttpGet] + public async Task>> GetShippingInformation() + { + return await _context.ShippingInformation.ToListAsync(); + } + + // GET: api/ShippingInformations/5 + [HttpGet("{id}")] + public async Task> GetShippingInformation(int id) + { + var shippingInformation = await _context.ShippingInformation.FindAsync(id); + + if (shippingInformation == null) + { + return NotFound(); + } + + return shippingInformation; + } + + // PUT: api/ShippingInformations/5 + [HttpPut("{id}")] + public async Task PutShippingInformation(int id, ShippingInformation shippingInformation) + { + if (id != shippingInformation.ShippingInformationId) + { + return BadRequest(); + } + + _context.Entry(shippingInformation).State = EntityState.Modified; + + try + { + await _context.SaveChangesAsync(); + } + catch (DbUpdateConcurrencyException) + { + if (!ShippingInformationExists(id)) + { + return NotFound(); + } + else + { + throw; + } + } + + return NoContent(); + } + + // POST: api/ShippingInformations + [HttpPost] + public async Task> PostShippingInformation(ShippingInformation shippingInformation) + { + _context.ShippingInformation.Add(shippingInformation); + await _context.SaveChangesAsync(); + + return CreatedAtAction("GetShippingInformation", new { id = shippingInformation.ShippingInformationId }, shippingInformation); + } + + // DELETE: api/ShippingInformations/5 + [HttpDelete("{id}")] + public async Task> DeleteShippingInformation(int id) + { + var shippingInformation = await _context.ShippingInformation.FindAsync(id); + if (shippingInformation == null) + { + return NotFound(); + } + + _context.ShippingInformation.Remove(shippingInformation); + await _context.SaveChangesAsync(); + + return shippingInformation; + } + + private bool ShippingInformationExists(int id) + { + return _context.ShippingInformation.Any(e => e.ShippingInformationId == id); + } + } +} diff --git a/src/Services/TenantCustomisations/TenantACustomisations/TenantACustomisations.csproj b/src/Services/TenantCustomisations/TenantACustomisations/TenantACustomisations.csproj index d21ad07f5..637a02603 100644 --- a/src/Services/TenantCustomisations/TenantACustomisations/TenantACustomisations.csproj +++ b/src/Services/TenantCustomisations/TenantACustomisations/TenantACustomisations.csproj @@ -28,6 +28,7 @@ + From 63cc2743605b3d891bc0bece20de9a0f3f5ee7f9 Mon Sep 17 00:00:00 2001 From: espent1004 Date: Fri, 31 Jan 2020 20:41:44 +0100 Subject: [PATCH 12/13] Implementing the shipping info, and most of the rfid use case --- docker-compose.dcproj | 2 +- .../EventBus/Events/IntegrationEvent.cs | 3 + .../EventBusRabbitMQ/EventBusRabbitMQ.cs | 133 ++++++++++++++---- ...dToSubmittedIntegrationEventsController.cs | 133 ++++++++++++++++++ .../Database/TenantAContext.cs | 7 + ...tatusChangedToSubmittedIntegrationEvent.cs | 6 +- src/Web/WebMVC/Controllers/OrderController.cs | 59 ++++++-- src/Web/WebMVC/Views/Order/Detail.cshtml | 31 ++-- src/Web/WebMVC/Views/Order/Index.cshtml | 17 ++- 9 files changed, 332 insertions(+), 59 deletions(-) create mode 100644 src/Services/TenantCustomisations/TenantACustomisations/Controllers/OrderStatusChangedToSubmittedIntegrationEventsController.cs diff --git a/docker-compose.dcproj b/docker-compose.dcproj index 296c4b5e0..21c2d5641 100644 --- a/docker-compose.dcproj +++ b/docker-compose.dcproj @@ -7,7 +7,7 @@ webmvc Linux 2.1 - LaunchBrowser + None diff --git a/src/BuildingBlocks/EventBus/EventBus/Events/IntegrationEvent.cs b/src/BuildingBlocks/EventBus/EventBus/Events/IntegrationEvent.cs index 6536ba721..6121e3939 100644 --- a/src/BuildingBlocks/EventBus/EventBus/Events/IntegrationEvent.cs +++ b/src/BuildingBlocks/EventBus/EventBus/Events/IntegrationEvent.cs @@ -34,5 +34,8 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events [JsonProperty] public Boolean CheckForCustomisation { get; set; } + + /*[JsonProperty] + public String TenantId { get; set; }*/ } } diff --git a/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs b/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs index 44137abae..50500da8e 100644 --- a/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs +++ b/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs @@ -12,10 +12,14 @@ using RabbitMQ.Client; using RabbitMQ.Client.Events; using RabbitMQ.Client.Exceptions; using System; +using System.Collections.Generic; using System.Diagnostics; +using System.Net; +using System.Net.Http; using System.Net.Sockets; using System.Text; using System.Threading.Tasks; +using System.Web; namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ { @@ -28,15 +32,20 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ private readonly IEventBusSubscriptionsManager _subsManager; private readonly ILifetimeScope _autofac; private readonly string AUTOFAC_SCOPE_NAME = "eshop_event_bus"; + private static readonly String tenantACustomisationUrl = @"http://tenantacustomisation/"; + private static readonly String tenantManagerUrl = @"http://tenantmanager/"; private readonly int _retryCount; + private IModel _consumerChannel; private string _queueName; public EventBusRabbitMQ(IRabbitMQPersistentConnection persistentConnection, ILogger logger, - ILifetimeScope autofac, IEventBusSubscriptionsManager subsManager, string queueName = null, int retryCount = 5) + ILifetimeScope autofac, IEventBusSubscriptionsManager subsManager, string queueName = null, + int retryCount = 5) { - _persistentConnection = persistentConnection ?? throw new ArgumentNullException(nameof(persistentConnection)); + _persistentConnection = + persistentConnection ?? throw new ArgumentNullException(nameof(persistentConnection)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _subsManager = subsManager ?? new InMemoryEventBusSubscriptionsManager(); _queueName = queueName; @@ -76,18 +85,21 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ var policy = RetryPolicy.Handle() .Or() - .WaitAndRetry(_retryCount, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (ex, time) => - { - _logger.LogWarning(ex, "Could not publish event: {EventId} after {Timeout}s ({ExceptionMessage})", @event.Id, $"{time.TotalSeconds:n1}", ex.Message); - }); + .WaitAndRetry(_retryCount, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), + (ex, time) => + { + _logger.LogWarning(ex, + "Could not publish event: {EventId} after {Timeout}s ({ExceptionMessage})", @event.Id, + $"{time.TotalSeconds:n1}", ex.Message); + }); var eventName = @event.GetType().Name; - _logger.LogWarning("Creating RabbitMQ channel to publish event: {EventId} ({EventName})", @event.Id, eventName); + _logger.LogWarning("Creating RabbitMQ channel to publish event: {EventId} ({EventName})", @event.Id, + eventName); using (var channel = _persistentConnection.CreateModel()) { - _logger.LogWarning("Declaring RabbitMQ exchange to publish event: {EventId}", @event.Id); channel.ExchangeDeclare(exchange: BROKER_NAME, type: "direct"); @@ -115,7 +127,8 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ public void SubscribeDynamic(string eventName) where TH : IDynamicIntegrationEventHandler { - _logger.LogInformation("Subscribing to dynamic event {EventName} with {EventHandler}", eventName, typeof(TH).GetGenericTypeName()); + _logger.LogInformation("Subscribing to dynamic event {EventName} with {EventHandler}", eventName, + typeof(TH).GetGenericTypeName()); DoInternalSubscription(eventName); _subsManager.AddDynamicSubscription(eventName); @@ -129,7 +142,8 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ var eventName = _subsManager.GetEventKey(); DoInternalSubscription(eventName); - _logger.LogInformation("Subscribing to event {EventName} with {EventHandler}", eventName, typeof(TH).GetGenericTypeName()); + _logger.LogInformation("Subscribing to event {EventName} with {EventHandler}", eventName, + typeof(TH).GetGenericTypeName()); _subsManager.AddSubscription(); StartBasicConsume(); @@ -148,8 +162,8 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ using (var channel = _persistentConnection.CreateModel()) { channel.QueueBind(queue: _queueName, - exchange: BROKER_NAME, - routingKey: eventName); + exchange: BROKER_NAME, + routingKey: eventName); } } } @@ -239,13 +253,13 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ var channel = _persistentConnection.CreateModel(); channel.ExchangeDeclare(exchange: BROKER_NAME, - type: "direct"); + type: "direct"); channel.QueueDeclare(queue: _queueName, - durable: true, - exclusive: false, - autoDelete: false, - arguments: null); + durable: true, + exclusive: false, + autoDelete: false, + arguments: null); channel.CallbackException += (sender, ea) => { @@ -258,6 +272,60 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ return channel; } + + private async void SendEventToTenant(Object @event) + { + string myJson = JsonConvert.SerializeObject(@event); + using (var client = new HttpClient()) + { + try + { + //TODO replace URL with response from tenantmanager + var response = await client.PostAsync( + tenantACustomisationUrl + "api/OrderStatusChangedToSubmittedIntegrationEvents", + new StringContent(myJson, Encoding.UTF8, "application/json")); + response.EnsureSuccessStatusCode(); + _logger.LogInformation("----- Event sent to tenant{@event} -----", @event); + } + + catch (Exception e) + { + _logger.LogInformation("----- Exception{@e} -- Event{@event} -----", e, @event); + } + } + } + + private async Task IsEventCustomised(String eventName, String tenantId) + { + Boolean isCustomised = false; + + var builder = new UriBuilder(tenantManagerUrl + "api/Customisations"); + builder.Port = -1; + var query = HttpUtility.ParseQueryString(builder.Query); + query["eventName"] = eventName; + query["tenantId"] = tenantId; + builder.Query = query.ToString(); + string url = builder.ToString(); + + using (var client = new HttpClient()) + { + try + { + var response = await client.GetAsync( + url); + response.EnsureSuccessStatusCode(); + isCustomised = + JsonConvert.DeserializeObject(response.Content.ReadAsStringAsync().Result); + } + catch (Exception e) + { + _logger.LogInformation("----- Exception{@e}", e); + } + } + + return isCustomised; + } + private async Task ProcessEvent(string eventName, string message) { _logger.LogWarning("Processing RabbitMQ event: {EventName}", eventName); @@ -271,7 +339,9 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ { if (subscription.IsDynamic) { - var handler = scope.ResolveOptional(subscription.HandlerType) as IDynamicIntegrationEventHandler; + //TODO check if it is required here aswell + var handler = + scope.ResolveOptional(subscription.HandlerType) as IDynamicIntegrationEventHandler; if (handler == null) continue; dynamic eventData = JObject.Parse(message); @@ -281,17 +351,32 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ else { var handler = scope.ResolveOptional(subscription.HandlerType); - if (eventName.Equals("OrderStatusChangedToSubmittedIntegrationEvent") || eventName.Equals("UserCheckoutAcceptedIntegrationEvent")) - { - Debug.WriteLine("Here"); - } + if (handler == null) continue; var eventType = _subsManager.GetEventTypeByName(eventName); var integrationEvent = JsonConvert.DeserializeObject(message, eventType); + //IsEventCustomised(eventName, integrationEvent.TenantId); + if (eventName.Equals("OrderStatusChangedToSubmittedIntegrationEvent") && + integrationEvent is IntegrationEvent) //TODO replace with tenantmanager + { + //Casting + IntegrationEvent evt = (IntegrationEvent) integrationEvent; + //Checking if event should be sent to tenant, or handled normally + //Can instead create an endpoint in the tenant manager that also handles all the events that a tenant wants to postpone + //Additionally, an endpoint in the tenant manager is required, where the tenant + //Issue with the tenant knowing the id of the event + if (evt.CheckForCustomisation) + { + SendEventToTenant(integrationEvent); + break; + } + } + var concreteType = typeof(IIntegrationEventHandler<>).MakeGenericType(eventType); await Task.Yield(); - await (Task)concreteType.GetMethod("Handle").Invoke(handler, new object[] { integrationEvent }); + await (Task) concreteType.GetMethod("Handle") + .Invoke(handler, new object[] {integrationEvent}); } } } @@ -302,4 +387,4 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ } } } -} +} \ No newline at end of file diff --git a/src/Services/TenantCustomisations/TenantACustomisations/Controllers/OrderStatusChangedToSubmittedIntegrationEventsController.cs b/src/Services/TenantCustomisations/TenantACustomisations/Controllers/OrderStatusChangedToSubmittedIntegrationEventsController.cs new file mode 100644 index 000000000..f42916f62 --- /dev/null +++ b/src/Services/TenantCustomisations/TenantACustomisations/Controllers/OrderStatusChangedToSubmittedIntegrationEventsController.cs @@ -0,0 +1,133 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; +using Microsoft.Extensions.Logging; +using TenantACustomisations.Database; +using TenantACustomisations.IntegrationEvents.Events; + +namespace TenantACustomisations.Controllers +{ + [Route("api/[controller]")] + [ApiController] + public class OrderStatusChangedToSubmittedIntegrationEventsController : ControllerBase + { + private readonly TenantAContext _context; + private readonly IEventBus _eventBus; + private readonly ILogger _logger; + + + public OrderStatusChangedToSubmittedIntegrationEventsController(TenantAContext context, IEventBus eventBus, ILogger logger) + { + _context = context; + _eventBus = eventBus; + _logger = logger; + } + + // GET: api/OrderStatusChangedToSubmittedIntegrationEvents + [HttpGet] + public async Task>> GetOrderStatusChangedToSubmittedIntegrationEvent(String orderId) + { + if (String.IsNullOrEmpty(orderId)) + { + return await _context.OrderStatusChangedToSubmittedIntegrationEvent.ToListAsync(); + } + else + { + var orderStatusChangedToSubmittedIntegrationEvent = _context.OrderStatusChangedToSubmittedIntegrationEvent.Where(x => x.OrderId == Int32.Parse(orderId)).ToListAsync(); + + return await orderStatusChangedToSubmittedIntegrationEvent; + } + } + + // GET: api/OrderStatusChangedToSubmittedIntegrationEvents/5 + [HttpGet("{id}")] + public async Task> GetOrderStatusChangedToSubmittedIntegrationEvent(Guid id) + { + var orderStatusChangedToSubmittedIntegrationEvent = await _context.OrderStatusChangedToSubmittedIntegrationEvent.FindAsync(id); + + if (orderStatusChangedToSubmittedIntegrationEvent == null) + { + return NotFound(); + } + + return orderStatusChangedToSubmittedIntegrationEvent; + } + + // PUT: api/OrderStatusChangedToSubmittedIntegrationEvents/5 + [HttpPut("{id}")] + public async Task PutOrderStatusChangedToSubmittedIntegrationEvent(Guid id, OrderStatusChangedToSubmittedIntegrationEvent orderStatusChangedToSubmittedIntegrationEvent) + { + if (id != orderStatusChangedToSubmittedIntegrationEvent.Id) + { + return BadRequest(); + } + + _context.Entry(orderStatusChangedToSubmittedIntegrationEvent).State = EntityState.Modified; + + try + { + await _context.SaveChangesAsync(); + } + catch (DbUpdateConcurrencyException) + { + if (!OrderStatusChangedToSubmittedIntegrationEventExists(id)) + { + return NotFound(); + } + else + { + throw; + } + } + + return NoContent(); + } + + // POST: api/OrderStatusChangedToSubmittedIntegrationEvents + [HttpPost] + public async Task> PostOrderStatusChangedToSubmittedIntegrationEvent(OrderStatusChangedToSubmittedIntegrationEvent orderStatusChangedToSubmittedIntegrationEvent) + { + _context.OrderStatusChangedToSubmittedIntegrationEvent.Add(orderStatusChangedToSubmittedIntegrationEvent); + await _context.SaveChangesAsync(); + + return CreatedAtAction("GetOrderStatusChangedToSubmittedIntegrationEvent", new { id = orderStatusChangedToSubmittedIntegrationEvent.Id }, orderStatusChangedToSubmittedIntegrationEvent); + } + + // DELETE: api/OrderStatusChangedToSubmittedIntegrationEvents/5 + [HttpDelete("{id}")] + public async Task> DeleteOrderStatusChangedToSubmittedIntegrationEvent(Guid id) + { + var orderStatusChangedToSubmittedIntegrationEvent = await _context.OrderStatusChangedToSubmittedIntegrationEvent.FindAsync(id); + if (orderStatusChangedToSubmittedIntegrationEvent == null) + { + return NotFound(); + } + + try + { + _logger.LogInformation("----- Publishing integration event: {IntegrationEventId} from OrderStatusChangedToSubmittedIntegrationEventsController - ({@IntegrationEvent})", orderStatusChangedToSubmittedIntegrationEvent.Id, orderStatusChangedToSubmittedIntegrationEvent); + orderStatusChangedToSubmittedIntegrationEvent.CheckForCustomisation = false; + _eventBus.Publish(orderStatusChangedToSubmittedIntegrationEvent); + _context.OrderStatusChangedToSubmittedIntegrationEvent.Remove(orderStatusChangedToSubmittedIntegrationEvent); + await _context.SaveChangesAsync(); + return orderStatusChangedToSubmittedIntegrationEvent; + } + catch (Exception ex) + { + _logger.LogError(ex, "ERROR Publishing integration event: {IntegrationEventId} from OrderStatusChangedToSubmittedIntegrationEventsController", orderStatusChangedToSubmittedIntegrationEvent.Id); + + throw; + } + } + + private bool OrderStatusChangedToSubmittedIntegrationEventExists(Guid id) + { + return _context.OrderStatusChangedToSubmittedIntegrationEvent.Any(e => e.Id == id); + } + } +} diff --git a/src/Services/TenantCustomisations/TenantACustomisations/Database/TenantAContext.cs b/src/Services/TenantCustomisations/TenantACustomisations/Database/TenantAContext.cs index 0f893e3b5..d435fbf14 100644 --- a/src/Services/TenantCustomisations/TenantACustomisations/Database/TenantAContext.cs +++ b/src/Services/TenantCustomisations/TenantACustomisations/Database/TenantAContext.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Design; using TenantACustomisations.ExternalServices; +using TenantACustomisations.IntegrationEvents.Events; namespace TenantACustomisations.Database { @@ -17,6 +18,12 @@ namespace TenantACustomisations.Database public DbSet ShippingInformation { get; set; } + public DbSet OrderStatusChangedToSubmittedIntegrationEvent + { + get; + set; + } + } public class TenantAContextDesignFactory : IDesignTimeDbContextFactory { diff --git a/src/Services/TenantCustomisations/TenantACustomisations/IntegrationEvents/Events/OrderStatusChangedToSubmittedIntegrationEvent.cs b/src/Services/TenantCustomisations/TenantACustomisations/IntegrationEvents/Events/OrderStatusChangedToSubmittedIntegrationEvent.cs index 12a759508..1b929c3c4 100644 --- a/src/Services/TenantCustomisations/TenantACustomisations/IntegrationEvents/Events/OrderStatusChangedToSubmittedIntegrationEvent.cs +++ b/src/Services/TenantCustomisations/TenantACustomisations/IntegrationEvents/Events/OrderStatusChangedToSubmittedIntegrationEvent.cs @@ -8,9 +8,9 @@ namespace TenantACustomisations.IntegrationEvents.Events { public class OrderStatusChangedToSubmittedIntegrationEvent : IntegrationEvent { - public int OrderId { get; } - public string OrderStatus { get; } - public string BuyerName { get; } + public int OrderId { get; set; } + public string OrderStatus { get; set; } + public string BuyerName { get; set; } public OrderStatusChangedToSubmittedIntegrationEvent(int orderId, string orderStatus, string buyerName) { diff --git a/src/Web/WebMVC/Controllers/OrderController.cs b/src/Web/WebMVC/Controllers/OrderController.cs index 1c3cff632..5d70228cd 100644 --- a/src/Web/WebMVC/Controllers/OrderController.cs +++ b/src/Web/WebMVC/Controllers/OrderController.cs @@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.eShopOnContainers.WebMVC.Services; using Microsoft.eShopOnContainers.WebMVC.ViewModels; using Microsoft.eShopOnContainers.WebMVC.ViewModels.Customisation; +using Microsoft.Extensions.Logging; using Newtonsoft.Json; using Polly.CircuitBreaker; using System; @@ -11,6 +12,7 @@ using System.Linq; using System.Net; using System.Net.Http; using System.Threading.Tasks; +using System.Web; namespace Microsoft.eShopOnContainers.WebMVC.Controllers { @@ -20,18 +22,21 @@ namespace Microsoft.eShopOnContainers.WebMVC.Controllers private IOrderingService _orderSvc; private IBasketService _basketSvc; private readonly IIdentityParser _appUserParser; - private static String url = @"http://tenantacustomisation/"; + private static String tenantACustomisationsUrl = @"http://tenantacustomisation/"; + private readonly ILogger _logger; - public OrderController(IOrderingService orderSvc, IBasketService basketSvc, IIdentityParser appUserParser) + + public OrderController(IOrderingService orderSvc, IBasketService basketSvc, + IIdentityParser appUserParser, ILogger logger) { _appUserParser = appUserParser; _orderSvc = orderSvc; _basketSvc = basketSvc; + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); } public async Task Create() { - var user = _appUserParser.Parse(HttpContext.User); var order = await _basketSvc.GetOrderDraft(user.Id); var vm = _orderSvc.MapUserInfoIntoOrder(user, order); @@ -58,7 +63,8 @@ namespace Microsoft.eShopOnContainers.WebMVC.Controllers } catch (BrokenCircuitException) { - ModelState.AddModelError("Error", "It was not possible to create a new order, please try later on. (Business Msg Due to Circuit-Breaker)"); + ModelState.AddModelError("Error", + "It was not possible to create a new order, please try later on. (Business Msg Due to Circuit-Breaker)"); } return View("Create", model); @@ -75,6 +81,8 @@ namespace Microsoft.eShopOnContainers.WebMVC.Controllers public async Task Detail(string orderId) { var user = _appUserParser.Parse(HttpContext.User); + Boolean RFIDScanned = await AllGoodsRFIDScanned(orderId); + ViewData["RFIDScanned"] = RFIDScanned; var order = await _orderSvc.GetOrder(user, orderId); return View(order); @@ -85,34 +93,63 @@ namespace Microsoft.eShopOnContainers.WebMVC.Controllers var user = _appUserParser.Parse(HttpContext.User); var vm = await _orderSvc.GetMyOrders(user); List shippingInformation = GetShippingInfo(vm); + _logger.LogInformation("----- Shipping info{@ShippingInformation}", shippingInformation); + ViewData["ShippingInfo"] = shippingInformation; return View(vm); } + + private async Task AllGoodsRFIDScanned(String orderId) + { + var builder = new UriBuilder(tenantACustomisationsUrl + "api/OrderStatusChangedToSubmittedIntegrationEvents"); + builder.Port = -1; + var query = HttpUtility.ParseQueryString(builder.Query); + query["orderId"] = orderId; + builder.Query = query.ToString(); + string url = builder.ToString(); + + using (var client = new HttpClient()) + { + var response = await client.GetAsync( + url); + if (response.StatusCode.Equals(HttpStatusCode.NotFound)) + { + return true; + } + + return false; + } + } + private List GetShippingInfo(List orders) { List shippingInformation = new List(); - using (var client = new HttpClient(new HttpClientHandler { AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate })) + using (var client = new HttpClient(new HttpClientHandler + {AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate})) { - client.BaseAddress = new Uri(url); + client.BaseAddress = new Uri(tenantACustomisationsUrl); try { - HttpResponseMessage response = client.GetAsync("api/shippinginformation").Result; + HttpResponseMessage response = client.GetAsync("api/shippinginformations").Result; response.EnsureSuccessStatusCode(); string result = response.Content.ReadAsStringAsync().Result; - List results = JsonConvert.DeserializeObject>(result); - results.ForEach( s => + _logger.LogInformation("----- Result{@result} -----", result); + + List + results = JsonConvert.DeserializeObject>(result); + results.ForEach(s => { - if(orders.Any(item => item.OrderNumber.Equals(s.OrderNumber))) + if (orders.Any(item => item.OrderNumber.Equals(s.OrderNumber))) { shippingInformation.Add(s); } }); - } catch (Exception e) { Console.WriteLine(e); + _logger.LogInformation("----- Exception{@e} -----", e); } } diff --git a/src/Web/WebMVC/Views/Order/Detail.cshtml b/src/Web/WebMVC/Views/Order/Detail.cshtml index 6b7c0b46e..41158463a 100644 --- a/src/Web/WebMVC/Views/Order/Detail.cshtml +++ b/src/Web/WebMVC/Views/Order/Detail.cshtml @@ -3,9 +3,12 @@ @model Microsoft.eShopOnContainers.WebMVC.ViewModels.Order @{ - ViewData["Title"] = "Order Detail"; - var headerList= new List
() { - new Header() { Controller = "Catalog", Text = "Back to catalog" } }; + ViewData["Title"] = "Order Detail"; + var headerList = new List
() + { + new Header() {Controller = "Catalog", Text = "Back to catalog"} + }; + var rfidScanned = ViewData["RFIDScanned"]; }
@@ -14,20 +17,22 @@
-
Order number
-
Date
-
Total
-
Status
+
Order number
+
Date
+
Total
+
Status
+
RFID Scanned
-
@Model.OrderNumber
-
@Model.Date
-
$@Model.Total
-
@Model.Status
+
$@Model.Total
+
@Model.OrderNumber
+
@Model.Date
+
@Model.Status
+
@rfidScanned
- +
Description
@@ -88,4 +93,4 @@
-
+
\ No newline at end of file diff --git a/src/Web/WebMVC/Views/Order/Index.cshtml b/src/Web/WebMVC/Views/Order/Index.cshtml index 48da48d1f..d0eb4fe0e 100644 --- a/src/Web/WebMVC/Views/Order/Index.cshtml +++ b/src/Web/WebMVC/Views/Order/Index.cshtml @@ -18,7 +18,7 @@
-
Order number
+
Order number
Date
Total
Status
@@ -32,26 +32,29 @@ foreach (var item in Model) {
-
@Html.DisplayFor(modelItem => item.OrderNumber)
-
@Html.DisplayFor(modelItem => item.Date)
+
@Html.DisplayFor(modelItem => item.OrderNumber)
+
@item.Date.ToShortDateString()
$ @Html.DisplayFor(modelItem => item.Total)
@Html.DisplayFor(modelItem => item.Status)
@for (var i = 0; i < shippingInfo.Count(); i++) { var si = shippingInfo[i]; - if (si.OrderNumber.Equals(item.OrderNumber)){ - @si.ShippingTime + if (si.OrderNumber.Equals(item.OrderNumber)) + { + @si.ShippingTime.ToShortDateString(); + break; } } -
+
@for (var i = 0; i < shippingInfo.Count(); i++) { var si = shippingInfo[i]; if (si.OrderNumber.Equals(item.OrderNumber)) { - @si.ArrivalTime + @si.ArrivalTime.ToShortDateString(); + break; } }
From e6296df5d182ec1083d0b643b0bf872c238fed9d Mon Sep 17 00:00:00 2001 From: espent1004 Date: Sat, 1 Feb 2020 00:39:23 +0100 Subject: [PATCH 13/13] Added RFID use case, and support for events being saved in the tenants microservice. The tenant manager is responsible whether a certain event is customised for a certain tenant. --- .../EventBus/Events/IntegrationEvent.cs | 8 +- .../EventBusRabbitMQ/EventBusRabbitMQ.cs | 48 +++-- ...dToSubmittedIntegrationEventsController.cs | 133 ------------- .../Controllers/SavedEventsController.cs | 183 ++++++++++++++++++ .../Database/SavedEvent.cs | 11 ++ .../Database/TenantAContext.cs | 2 +- ...gedToAwaitingValidationIntegrationEvent.cs | 30 +++ .../Controllers/CustomisationsController.cs | 14 ++ .../TenantManager/Database/DbInitializer.cs | 43 ++-- .../TenantManager/Models/Customisation.cs | 9 +- .../TenantManager/Models/Methods.cs | 2 +- .../TenantManager/Models/Tenant.cs | 4 +- src/Web/WebMVC/Controllers/OrderController.cs | 2 +- 13 files changed, 299 insertions(+), 190 deletions(-) delete mode 100644 src/Services/TenantCustomisations/TenantACustomisations/Controllers/OrderStatusChangedToSubmittedIntegrationEventsController.cs create mode 100644 src/Services/TenantCustomisations/TenantACustomisations/Controllers/SavedEventsController.cs create mode 100644 src/Services/TenantCustomisations/TenantACustomisations/Database/SavedEvent.cs create mode 100644 src/Services/TenantCustomisations/TenantACustomisations/IntegrationEvents/Events/OrderStatusChangedToAwaitingValidationIntegrationEvent.cs diff --git a/src/BuildingBlocks/EventBus/EventBus/Events/IntegrationEvent.cs b/src/BuildingBlocks/EventBus/EventBus/Events/IntegrationEvent.cs index 6121e3939..6199c5cb3 100644 --- a/src/BuildingBlocks/EventBus/EventBus/Events/IntegrationEvent.cs +++ b/src/BuildingBlocks/EventBus/EventBus/Events/IntegrationEvent.cs @@ -10,6 +10,7 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events Id = Guid.NewGuid(); CreationDate = DateTime.UtcNow; CheckForCustomisation = true; + TenantId = 1; } public IntegrationEvent(Boolean checkForCustomisation) @@ -17,6 +18,7 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events Id = Guid.NewGuid(); CreationDate = DateTime.UtcNow; CheckForCustomisation = checkForCustomisation; + TenantId = 1; } [JsonConstructor] @@ -24,6 +26,7 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events { Id = id; CreationDate = createDate; + TenantId = 1; } [JsonProperty] @@ -35,7 +38,8 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events [JsonProperty] public Boolean CheckForCustomisation { get; set; } - /*[JsonProperty] - public String TenantId { get; set; }*/ + //TODO fix this somehow + [JsonProperty] + public int TenantId { get; set; } } } diff --git a/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs b/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs index 50500da8e..e4f8663a5 100644 --- a/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs +++ b/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs @@ -16,6 +16,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Net; using System.Net.Http; +using System.Net.Mime; using System.Net.Sockets; using System.Text; using System.Threading.Tasks; @@ -273,37 +274,44 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ return channel; } - private async void SendEventToTenant(Object @event) + private async void SendEventToTenant(String content, String id, String eventName) { - string myJson = JsonConvert.SerializeObject(@event); + var temp = new SavedEvent(); + temp.Content = content; + temp.SavedEventId = id; + temp.EventName = eventName; + string myJson = JsonConvert.SerializeObject(temp); using (var client = new HttpClient()) { try { //TODO replace URL with response from tenantmanager var response = await client.PostAsync( - tenantACustomisationUrl + "api/OrderStatusChangedToSubmittedIntegrationEvents", + tenantACustomisationUrl + "api/SavedEvents", new StringContent(myJson, Encoding.UTF8, "application/json")); response.EnsureSuccessStatusCode(); - _logger.LogInformation("----- Event sent to tenant{@event} -----", @event); + _logger.LogInformation("----- Event sent to tenant{@id} -----", id); } catch (Exception e) { - _logger.LogInformation("----- Exception{@e} -- Event{@event} -----", e, @event); + _logger.LogInformation("----- Exception{@e} -- Event{@id} -----", e, @id); } } } - private async Task IsEventCustomised(String eventName, String tenantId) + private async Task IsEventCustomised(String eventName, int tenantId) { + CustomisationInfo customisationInfo = new CustomisationInfo(); + customisationInfo.EventName = eventName; + customisationInfo.TenantId = tenantId; Boolean isCustomised = false; - var builder = new UriBuilder(tenantManagerUrl + "api/Customisations"); + var builder = new UriBuilder(tenantManagerUrl + "api/Customisations/IsCustomised"); builder.Port = -1; var query = HttpUtility.ParseQueryString(builder.Query); query["eventName"] = eventName; - query["tenantId"] = tenantId; + query["tenantId"] = tenantId.ToString(); builder.Query = query.ToString(); string url = builder.ToString(); @@ -355,19 +363,12 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ if (handler == null) continue; var eventType = _subsManager.GetEventTypeByName(eventName); var integrationEvent = JsonConvert.DeserializeObject(message, eventType); - //IsEventCustomised(eventName, integrationEvent.TenantId); - if (eventName.Equals("OrderStatusChangedToSubmittedIntegrationEvent") && - integrationEvent is IntegrationEvent) //TODO replace with tenantmanager + if (integrationEvent is IntegrationEvent evt && IsEventCustomised(eventName, evt.TenantId).Result) //TODO replace with tenantmanager { - //Casting - IntegrationEvent evt = (IntegrationEvent) integrationEvent; //Checking if event should be sent to tenant, or handled normally - //Can instead create an endpoint in the tenant manager that also handles all the events that a tenant wants to postpone - //Additionally, an endpoint in the tenant manager is required, where the tenant - //Issue with the tenant knowing the id of the event if (evt.CheckForCustomisation) { - SendEventToTenant(integrationEvent); + SendEventToTenant(message, evt.Id.ToString(), eventName); break; } } @@ -387,4 +388,17 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ } } } +} + +class SavedEvent +{ + public string SavedEventId { get; set; } + public string Content { get; set; } + public String EventName { get; set; } +} + +class CustomisationInfo +{ + public string EventName { get; set; } + public int TenantId { get; set; } } \ No newline at end of file diff --git a/src/Services/TenantCustomisations/TenantACustomisations/Controllers/OrderStatusChangedToSubmittedIntegrationEventsController.cs b/src/Services/TenantCustomisations/TenantACustomisations/Controllers/OrderStatusChangedToSubmittedIntegrationEventsController.cs deleted file mode 100644 index f42916f62..000000000 --- a/src/Services/TenantCustomisations/TenantACustomisations/Controllers/OrderStatusChangedToSubmittedIntegrationEventsController.cs +++ /dev/null @@ -1,133 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -using Microsoft.EntityFrameworkCore; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; -using Microsoft.Extensions.Logging; -using TenantACustomisations.Database; -using TenantACustomisations.IntegrationEvents.Events; - -namespace TenantACustomisations.Controllers -{ - [Route("api/[controller]")] - [ApiController] - public class OrderStatusChangedToSubmittedIntegrationEventsController : ControllerBase - { - private readonly TenantAContext _context; - private readonly IEventBus _eventBus; - private readonly ILogger _logger; - - - public OrderStatusChangedToSubmittedIntegrationEventsController(TenantAContext context, IEventBus eventBus, ILogger logger) - { - _context = context; - _eventBus = eventBus; - _logger = logger; - } - - // GET: api/OrderStatusChangedToSubmittedIntegrationEvents - [HttpGet] - public async Task>> GetOrderStatusChangedToSubmittedIntegrationEvent(String orderId) - { - if (String.IsNullOrEmpty(orderId)) - { - return await _context.OrderStatusChangedToSubmittedIntegrationEvent.ToListAsync(); - } - else - { - var orderStatusChangedToSubmittedIntegrationEvent = _context.OrderStatusChangedToSubmittedIntegrationEvent.Where(x => x.OrderId == Int32.Parse(orderId)).ToListAsync(); - - return await orderStatusChangedToSubmittedIntegrationEvent; - } - } - - // GET: api/OrderStatusChangedToSubmittedIntegrationEvents/5 - [HttpGet("{id}")] - public async Task> GetOrderStatusChangedToSubmittedIntegrationEvent(Guid id) - { - var orderStatusChangedToSubmittedIntegrationEvent = await _context.OrderStatusChangedToSubmittedIntegrationEvent.FindAsync(id); - - if (orderStatusChangedToSubmittedIntegrationEvent == null) - { - return NotFound(); - } - - return orderStatusChangedToSubmittedIntegrationEvent; - } - - // PUT: api/OrderStatusChangedToSubmittedIntegrationEvents/5 - [HttpPut("{id}")] - public async Task PutOrderStatusChangedToSubmittedIntegrationEvent(Guid id, OrderStatusChangedToSubmittedIntegrationEvent orderStatusChangedToSubmittedIntegrationEvent) - { - if (id != orderStatusChangedToSubmittedIntegrationEvent.Id) - { - return BadRequest(); - } - - _context.Entry(orderStatusChangedToSubmittedIntegrationEvent).State = EntityState.Modified; - - try - { - await _context.SaveChangesAsync(); - } - catch (DbUpdateConcurrencyException) - { - if (!OrderStatusChangedToSubmittedIntegrationEventExists(id)) - { - return NotFound(); - } - else - { - throw; - } - } - - return NoContent(); - } - - // POST: api/OrderStatusChangedToSubmittedIntegrationEvents - [HttpPost] - public async Task> PostOrderStatusChangedToSubmittedIntegrationEvent(OrderStatusChangedToSubmittedIntegrationEvent orderStatusChangedToSubmittedIntegrationEvent) - { - _context.OrderStatusChangedToSubmittedIntegrationEvent.Add(orderStatusChangedToSubmittedIntegrationEvent); - await _context.SaveChangesAsync(); - - return CreatedAtAction("GetOrderStatusChangedToSubmittedIntegrationEvent", new { id = orderStatusChangedToSubmittedIntegrationEvent.Id }, orderStatusChangedToSubmittedIntegrationEvent); - } - - // DELETE: api/OrderStatusChangedToSubmittedIntegrationEvents/5 - [HttpDelete("{id}")] - public async Task> DeleteOrderStatusChangedToSubmittedIntegrationEvent(Guid id) - { - var orderStatusChangedToSubmittedIntegrationEvent = await _context.OrderStatusChangedToSubmittedIntegrationEvent.FindAsync(id); - if (orderStatusChangedToSubmittedIntegrationEvent == null) - { - return NotFound(); - } - - try - { - _logger.LogInformation("----- Publishing integration event: {IntegrationEventId} from OrderStatusChangedToSubmittedIntegrationEventsController - ({@IntegrationEvent})", orderStatusChangedToSubmittedIntegrationEvent.Id, orderStatusChangedToSubmittedIntegrationEvent); - orderStatusChangedToSubmittedIntegrationEvent.CheckForCustomisation = false; - _eventBus.Publish(orderStatusChangedToSubmittedIntegrationEvent); - _context.OrderStatusChangedToSubmittedIntegrationEvent.Remove(orderStatusChangedToSubmittedIntegrationEvent); - await _context.SaveChangesAsync(); - return orderStatusChangedToSubmittedIntegrationEvent; - } - catch (Exception ex) - { - _logger.LogError(ex, "ERROR Publishing integration event: {IntegrationEventId} from OrderStatusChangedToSubmittedIntegrationEventsController", orderStatusChangedToSubmittedIntegrationEvent.Id); - - throw; - } - } - - private bool OrderStatusChangedToSubmittedIntegrationEventExists(Guid id) - { - return _context.OrderStatusChangedToSubmittedIntegrationEvent.Any(e => e.Id == id); - } - } -} diff --git a/src/Services/TenantCustomisations/TenantACustomisations/Controllers/SavedEventsController.cs b/src/Services/TenantCustomisations/TenantACustomisations/Controllers/SavedEventsController.cs new file mode 100644 index 000000000..a90a8df7c --- /dev/null +++ b/src/Services/TenantCustomisations/TenantACustomisations/Controllers/SavedEventsController.cs @@ -0,0 +1,183 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; +using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; +using Microsoft.Extensions.Logging; +using Newtonsoft.Json; +using TenantACustomisations.Database; +using TenantACustomisations.IntegrationEvents.Events; + +namespace TenantACustomisations.Controllers +{ + [Route("api/[controller]")] + [ApiController] + public class SavedEventsController : ControllerBase + { + private readonly TenantAContext _context; + private readonly ILogger _logger; + private readonly IEventBus _eventBus; + + private List types = new List() + { + typeof(OrderStatusChangedToSubmittedIntegrationEvent), + typeof(OrderStatusChangedToAwaitingValidationIntegrationEvent) + }; + + public SavedEventsController(TenantAContext context, ILogger logger, IEventBus eventBus) + { + _context = context; + _logger = logger; + _eventBus = eventBus; + } + + // GET: api/SavedEvents + [HttpGet] + public async Task>> GetSavedEvent(String orderId) + { + if (String.IsNullOrEmpty(orderId)) + { + return await _context.SavedEvent.ToListAsync(); + } + + //Getting saved events + var savedEvents = await _context.SavedEvent.ToListAsync(); + + //Returning if list is empty + if (savedEvents.Count == 0) + { + return NotFound(); + } + List events = new List(); + + //Converting events to actual type + savedEvents.ForEach(e => + { + var integrationEvent =JsonConvert.DeserializeObject(e.Content, GetEventTypeByName(e.EventName)); + IntegrationEvent evt = (IntegrationEvent)integrationEvent; + events.Add(evt); + }); + + bool found = false; + //Casting to class to check the orderId + events.ForEach(e => + { + if(e is OrderStatusChangedToAwaitingValidationIntegrationEvent) + { + OrderStatusChangedToAwaitingValidationIntegrationEvent evt = (OrderStatusChangedToAwaitingValidationIntegrationEvent)e; + if (evt.OrderId == Int32.Parse(orderId)) + { + found = true; + } + } + else if(e is OrderStatusChangedToSubmittedIntegrationEvent) + { + OrderStatusChangedToSubmittedIntegrationEvent evt = (OrderStatusChangedToSubmittedIntegrationEvent)e; + if (evt.OrderId == Int32.Parse(orderId)) + { + found = true; + + } + } + }); + + if (!found) + { + return NotFound(); + } + + return savedEvents; + } + + // PUT: api/SavedEvents/5 + [HttpPut("{id}")] + public async Task PutSavedEvent(string id, SavedEvent savedEvent) + { + if (id != savedEvent.SavedEventId) + { + return BadRequest(); + } + + _context.Entry(savedEvent).State = EntityState.Modified; + + try + { + await _context.SaveChangesAsync(); + } + catch (DbUpdateConcurrencyException) + { + if (!SavedEventExists(id)) + { + return NotFound(); + } + else + { + throw; + } + } + + return NoContent(); + } + + // POST: api/SavedEvents + [HttpPost] + public async Task> PostSavedEvent(SavedEvent savedEvent) + { + _context.SavedEvent.Add(savedEvent); + await _context.SaveChangesAsync(); + + return CreatedAtAction("GetSavedEvent", new {id = savedEvent.SavedEventId}, savedEvent); + } + + // DELETE: api/SavedEvents/5 + [HttpDelete("{id}")] + public async Task> DeleteSavedEvent(string id) + { + var savedEvent = await _context.SavedEvent.FindAsync(id); + if (savedEvent == null) + { + return NotFound(); + } + + var integrationEvent = + JsonConvert.DeserializeObject(savedEvent.Content, GetEventTypeByName(savedEvent.EventName)); + IntegrationEvent evt = (IntegrationEvent) integrationEvent; + try + { + _logger.LogInformation( + "----- Publishing integration event: {IntegrationEventId} from OrderStatusChangedToSubmittedIntegrationEventsController - ({@IntegrationEvent})", + evt.Id, evt); + evt.CheckForCustomisation = false; + _eventBus.Publish(evt); + _context.SavedEvent.Remove(savedEvent); + await _context.SaveChangesAsync(); + return savedEvent; + } + catch (Exception ex) + { + _logger.LogError(ex, + "ERROR Publishing integration event: {IntegrationEventId} from OrderStatusChangedToSubmittedIntegrationEventsController", + evt.Id); + + throw; + } + + + _context.SavedEvent.Remove(savedEvent); + await _context.SaveChangesAsync(); + + return savedEvent; + } + + private bool SavedEventExists(string id) + { + return _context.SavedEvent.Any(e => e.SavedEventId == id); + } + + private Type GetEventTypeByName(string eventName) => types.SingleOrDefault(t => t.Name == eventName); + } +} \ No newline at end of file diff --git a/src/Services/TenantCustomisations/TenantACustomisations/Database/SavedEvent.cs b/src/Services/TenantCustomisations/TenantACustomisations/Database/SavedEvent.cs new file mode 100644 index 000000000..7b4e5b98d --- /dev/null +++ b/src/Services/TenantCustomisations/TenantACustomisations/Database/SavedEvent.cs @@ -0,0 +1,11 @@ +using System; + +namespace TenantACustomisations.Database +{ + public class SavedEvent + { + public string SavedEventId { get; set; } + public string Content { get; set; } + public String EventName { get; set; } + } +} \ No newline at end of file diff --git a/src/Services/TenantCustomisations/TenantACustomisations/Database/TenantAContext.cs b/src/Services/TenantCustomisations/TenantACustomisations/Database/TenantAContext.cs index d435fbf14..222d63dd8 100644 --- a/src/Services/TenantCustomisations/TenantACustomisations/Database/TenantAContext.cs +++ b/src/Services/TenantCustomisations/TenantACustomisations/Database/TenantAContext.cs @@ -18,7 +18,7 @@ namespace TenantACustomisations.Database public DbSet ShippingInformation { get; set; } - public DbSet OrderStatusChangedToSubmittedIntegrationEvent + public DbSet SavedEvent { get; set; diff --git a/src/Services/TenantCustomisations/TenantACustomisations/IntegrationEvents/Events/OrderStatusChangedToAwaitingValidationIntegrationEvent.cs b/src/Services/TenantCustomisations/TenantACustomisations/IntegrationEvents/Events/OrderStatusChangedToAwaitingValidationIntegrationEvent.cs new file mode 100644 index 000000000..14534b549 --- /dev/null +++ b/src/Services/TenantCustomisations/TenantACustomisations/IntegrationEvents/Events/OrderStatusChangedToAwaitingValidationIntegrationEvent.cs @@ -0,0 +1,30 @@ +using System.Collections.Generic; +using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; + +namespace TenantACustomisations.IntegrationEvents.Events +{ + public class OrderStatusChangedToAwaitingValidationIntegrationEvent : IntegrationEvent + { + public int OrderId { get; } + public IEnumerable OrderStockItems { get; } + + public OrderStatusChangedToAwaitingValidationIntegrationEvent(int orderId, + IEnumerable orderStockItems) + { + OrderId = orderId; + OrderStockItems = orderStockItems; + } + } + + public class OrderStockItem + { + public int ProductId { get; } + public int Units { get; } + + public OrderStockItem(int productId, int units) + { + ProductId = productId; + Units = units; + } + } +} \ No newline at end of file diff --git a/src/Services/TenantManager/TenantManager/Controllers/CustomisationsController.cs b/src/Services/TenantManager/TenantManager/Controllers/CustomisationsController.cs index 12f9367bb..23e230b70 100644 --- a/src/Services/TenantManager/TenantManager/Controllers/CustomisationsController.cs +++ b/src/Services/TenantManager/TenantManager/Controllers/CustomisationsController.cs @@ -41,6 +41,20 @@ namespace TenantManager.Controllers return customisation; } + + // GET: api/Customisations/5 + [HttpGet("isCustomised")] + public async Task> IsCustomised(String eventName, int tenantId) + { + var customisation = await _context.Customisation.Include(c => c.Method).Include(c => c.Tenant).Where(c => c.Method.MethodName.Equals(eventName) && c.TenantId == tenantId).FirstOrDefaultAsync(); + + if (customisation == null) + { + return false; + } + + return true; + } // PUT: api/Customisations/5 [HttpPut("{id}")] diff --git a/src/Services/TenantManager/TenantManager/Database/DbInitializer.cs b/src/Services/TenantManager/TenantManager/Database/DbInitializer.cs index 08c77ff6a..f91994866 100644 --- a/src/Services/TenantManager/TenantManager/Database/DbInitializer.cs +++ b/src/Services/TenantManager/TenantManager/Database/DbInitializer.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; +using System.Linq; using TenantManager.Models; namespace TenantManager.Database @@ -17,28 +14,13 @@ namespace TenantManager.Database return; } - var tenant1 = new Tenant() { TenantName = "Tekna" }; - var tenant2 = new Tenant() { TenantName = "NITO" }; - var tenant3 = new Tenant() { TenantName = "LO" }; + var tenant1 = new Tenant { TenantName = "Tekna" }; + context.Tenant.Add(tenant1); + + var method1 = new Method { MethodName = "OrderStatusChangedToSubmittedIntegrationEvent" }; + var method2 = new Method { MethodName = "OrderStatusChangedToAwaitingValidationIntegrationEvent" }; - var tenants = new Tenant[] - { - tenant1, - tenant2, - tenant3 - }; - - foreach(Tenant t in tenants) - { - context.Tenant.Add(t); - } - - context.SaveChanges(); - - var method1 = new Method() { MethodName = "GetPrice" }; - var method2 = new Method() { MethodName = "GetItem" }; - - var methods = new Method[] + var methods = new[] { method1, method2 @@ -48,14 +30,11 @@ namespace TenantManager.Database { context.Method.Add(m); } - - context.SaveChanges(); - - var customisations = new Customisation[] + + var customisations = new[] { - new Customisation(){Tenant=tenant1, Method=method1 }, - new Customisation(){Tenant=tenant1, Method=method2}, - new Customisation(){Tenant=tenant2, Method=method1 } + new Customisation {Tenant=tenant1, Method=method1 }, + new Customisation {Tenant=tenant1, Method=method2} }; foreach(Customisation c in customisations) diff --git a/src/Services/TenantManager/TenantManager/Models/Customisation.cs b/src/Services/TenantManager/TenantManager/Models/Customisation.cs index ad6f3669b..6f0583f77 100644 --- a/src/Services/TenantManager/TenantManager/Models/Customisation.cs +++ b/src/Services/TenantManager/TenantManager/Models/Customisation.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; using System.Linq; using System.Threading.Tasks; @@ -8,9 +9,15 @@ namespace TenantManager.Models public class Customisation { public int CustomisationId { get; set; } + + //Foreign keys public int TenantId { get; set; } - public virtual Tenant Tenant { get; set; } public int MethodId { get; set; } + + + [ForeignKey("TenantId")] + public virtual Tenant Tenant { get; set; } + [ForeignKey("MethodId")] public virtual Method Method { get; set; } } } diff --git a/src/Services/TenantManager/TenantManager/Models/Methods.cs b/src/Services/TenantManager/TenantManager/Models/Methods.cs index b1ab9027c..ab0713191 100644 --- a/src/Services/TenantManager/TenantManager/Models/Methods.cs +++ b/src/Services/TenantManager/TenantManager/Models/Methods.cs @@ -10,6 +10,6 @@ namespace TenantManager.Models { public int MethodId { get; set; } public String MethodName { get; set; } - public ICollection Customisations { get; set; } + public List Customisations { get; set; } } } diff --git a/src/Services/TenantManager/TenantManager/Models/Tenant.cs b/src/Services/TenantManager/TenantManager/Models/Tenant.cs index 72cb69624..96aa2e119 100644 --- a/src/Services/TenantManager/TenantManager/Models/Tenant.cs +++ b/src/Services/TenantManager/TenantManager/Models/Tenant.cs @@ -10,7 +10,7 @@ namespace TenantManager.Models { public String TenantName { get; set; } [Key] - public long TenantId { get; set; } - public ICollection Customisations { get; set; } + public int TenantId { get; set; } + public List Customisations { get; set; } } } diff --git a/src/Web/WebMVC/Controllers/OrderController.cs b/src/Web/WebMVC/Controllers/OrderController.cs index 5d70228cd..265cd91ac 100644 --- a/src/Web/WebMVC/Controllers/OrderController.cs +++ b/src/Web/WebMVC/Controllers/OrderController.cs @@ -102,7 +102,7 @@ namespace Microsoft.eShopOnContainers.WebMVC.Controllers private async Task AllGoodsRFIDScanned(String orderId) { - var builder = new UriBuilder(tenantACustomisationsUrl + "api/OrderStatusChangedToSubmittedIntegrationEvents"); + var builder = new UriBuilder(tenantACustomisationsUrl + "api/SavedEvents"); builder.Port = -1; var query = HttpUtility.ParseQueryString(builder.Query); query["orderId"] = orderId;