Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 11 additions & 9 deletions CallbackHandler.BusinessLogic.Tests/Mediator/MediatorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@

namespace CallbackHandler.BusinessLogic.Tests.Mediator;

using CallbackHandler.Bootstrapper;
using BusinessLogic.Services;
using Lamar;
using Microsoft.Extensions.DependencyInjection;
using Shared.General;
using Shared.Serialisation;

public class MediatorTests
{
Expand All @@ -38,18 +40,17 @@ public async Task Mediator_Send_RequestHandled()
hostingEnvironment.ApplicationName.Getter().Returns("Test Application");

ServiceRegistry services = new();
Startup s = new(hostingEnvironment.Instance());
IConfigurationRoot configurationRoot = new ConfigurationBuilder().AddInMemoryCollection(TestData.DefaultAppSettings).Build();
//ConfigurationReader.Initialise(configurationRoot);

Startup.Configuration = configurationRoot;

this.AddTestRegistrations(services, hostingEnvironment.Instance());
s.ConfigureContainer(services);
Startup.Container.AssertConfigurationIsValid(AssertMode.Full);
this.AddTestRegistrations(services, hostingEnvironment.Instance(), configurationRoot);
services.AddCallbackHandlerRegistries(configurationRoot);
Container container = new(services);
container.AssertConfigurationIsValid(AssertMode.Full);
StringSerialiser.Initialise(container.GetRequiredService<IStringSerialiser>());

List<String> errors = new();
IMediator mediator = Startup.Container.GetService<IMediator>();
IMediator mediator = container.GetService<IMediator>();
foreach (IBaseRequest baseRequest in this.Requests)
{
try
Expand Down Expand Up @@ -92,15 +93,16 @@ private IConfigurationRoot SetupMemoryConfiguration()
}

private void AddTestRegistrations(ServiceRegistry services,
IWebHostEnvironment hostingEnvironment)
IWebHostEnvironment hostingEnvironment,
IConfiguration configuration)
{
services.AddLogging();
DiagnosticListener diagnosticSource = new(hostingEnvironment.ApplicationName);
services.AddSingleton<DiagnosticSource>(diagnosticSource);
services.AddSingleton<DiagnosticListener>(diagnosticSource);
services.AddSingleton<IWebHostEnvironment>(hostingEnvironment);
services.AddSingleton<IHostEnvironment>(hostingEnvironment);
services.AddSingleton<IConfiguration>(Startup.Configuration);
services.AddSingleton<IConfiguration>(configuration);

services.OverrideServices(s => { s.AddSingleton<ICallbackDomainService, DummyCallbackDomainService>(); });
}
Expand Down
17 changes: 8 additions & 9 deletions CallbackHandler.DataTransferObjects/CallbackMessage.cs
Original file line number Diff line number Diff line change
@@ -1,26 +1,25 @@
using System;
using System.Collections.Generic;
using System;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
using System.Text.Json.Serialization;
using System.Threading.Tasks;

namespace CallbackHandler.DataTransferObjects
{
[ExcludeFromCodeCoverage]
public class CallbackMessage
{
[Description("Original callback payload serialized as a JSON string.")]
public String Message { get; set; }

[Description(".NET type name recorded for the original callback payload.")]
public String TypeString { get; set; }

[Description("Reference supplied with the original deposit callback.")]
public String Reference { get; set; }
}

public class CallbackResponse {
public class CallbackResponse
{
[Description("Identifier assigned to the recorded callback. Use it to retrieve the callback.")]
public Guid CallbackId { get; set; }
}


}
10 changes: 9 additions & 1 deletion CallbackHandler.DataTransferObjects/Deposit.cs
Original file line number Diff line number Diff line change
@@ -1,23 +1,31 @@
namespace CallbackHandler.DataTransferObjects
{
using System;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;

[ExcludeFromCodeCoverage]
public class Deposit
{
[Description("Account number associated with the deposit.")]
public String AccountNumber { get; set; }

[Description("Amount deposited.")]
public Decimal Amount { get; set; }

[Description("Date and time when the deposit occurred.")]
public DateTime DateTime { get; set; }

[Description("Identifier of the deposit event.")]
public Guid DepositId { get; set; }

[Description("Identifier of the host that originated the deposit.")]
public Guid HostIdentifier { get; set; }

[Description("Reference used to identify or correlate the deposit.")]
public String Reference { get; set; }

[Description("Sort code associated with the account.")]
public String SortCode { get; set; }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="EventStore.Client.Grpc.ProjectionManagement" />
<PackageReference Include="EventStoreProjections" />
<PackageReference Include="Reqnroll.Tools.MsBuild.Generation" />
<PackageReference Include="Reqnroll" />
Expand Down
26 changes: 20 additions & 6 deletions CallbackHandler.IntegrationTests/Common/DockerHelper.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using EventStore.Client;
using KurrentDB.Client;
using SecurityService.Client;
using Shared.IntegrationTesting;
using Shared.Serialisation;
Expand All @@ -15,7 +16,10 @@ public DockerHelper() {

public ISecurityServiceClient SecurityServiceClient;
public ITransactionProcessorClient TransactionProcessorClient;
public EventStoreProjectionManagementClient ProjectionManagementClient;

public EventStoreProjectionManagementClient LegacyProjectionManagementClient;

public KurrentDBProjectionManagementClient ProjectionManagementClient;

public String AccessToken;

Expand Down Expand Up @@ -52,6 +56,18 @@ public Int32 GetCallbackHandlerPort()
return this.CallbackHandlerPort;
}

protected virtual EventStoreClientSettings ConfigureLegacyEventstoreDbSettings(String username = "admin", String password = "changeit") {
String connectionString = $"esdb://{username}:{password}@127.0.0.1:{this.KurrentDbHttpPort}";

connectionString = this.IsSecureKurrentDb switch {
true => $"{connectionString}?tls=true&tlsVerifyCert=false",
_ => $"{connectionString}?tls=false&tlsVerifyCert=false"
};

return EventStoreClientSettings.Create(connectionString);
}


public override async Task StartContainersForScenarioRun(String scenarioName,
DockerServices dockerServices, CancellationToken cancellationToken) {
await base.StartContainersForScenarioRun(scenarioName, dockerServices, cancellationToken);
Expand All @@ -65,15 +81,13 @@ public override async Task StartContainersForScenarioRun(String scenarioName,
ServerCertificateCustomValidationCallback = (message,
certificate2,
arg3,
arg4) =>
{
return true;
}
arg4) => true
};
HttpClient httpClient = new HttpClient(clientHandler);
this.SecurityServiceClient = new SecurityServiceClient(SecurityServiceBaseAddressResolver, httpClient, Serialise, Deserialise);
this.TransactionProcessorClient = new TransactionProcessorClient(TransactionProcessorBaseAddressResolver, httpClient, Serialise, Deserialise);
this.ProjectionManagementClient = new EventStoreProjectionManagementClient(ConfigureEventStoreSettings());
this.ProjectionManagementClient = new KurrentDBProjectionManagementClient(this.ConfigureKurrentDbSettings());
this.LegacyProjectionManagementClient = new EventStoreProjectionManagementClient(this.ConfigureLegacyEventstoreDbSettings());
this.TestHostHttpClient = new HttpClient(clientHandler);
this.TestHostHttpClient.BaseAddress = new Uri($"http://127.0.0.1:{this.TestHostServicePort}");
this.AgencyBankingClient = new AgencyBankingClient(TestHostServiceBaseAddressResolver, httpClient, Serialise_CamelCase, this.Deserialise_CamelCase);
Expand Down
2 changes: 1 addition & 1 deletion CallbackHandler.IntegrationTests/Common/GenericSteps.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public async Task StartSystem()
LogManager.AddHiddenAssembly(typeof(NlogLogger).Assembly);

DockerServices dockerServices = DockerServices.SecurityService | DockerServices.TransactionProcessor |
DockerServices.CallbackHandler | DockerServices.EventStore |
DockerServices.CallbackHandler | DockerServices.KurrentDb |
DockerServices.SqlServer | DockerServices.TestHost;

this.TestingContext.DockerHelper = new DockerHelper();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,13 @@ Given I create the following api scopes
| MerchantName | AddressLine1 | Town | Region | PostalCode | Country | ContactName | EmailAddress | EstateName |
| Test Merchant 1 | Address Line 1 | TestTown | Test Region | TE57 1NG | United Kingdom | Test Contact 1 | testcontact1@merchant1.co.uk | Test Estate 1 |

Scenario: Process a Bank Deposit Callback
Scenario Outline: Process a Bank Deposit Callback
Given I have the following Bank Deposit Callbacks
| Amount | DateTime | DepositId | HostIdentifier | SortCode | AccountNumber |
| 100.00 | Today | 6AE04AFC-D7F8-4936-A3A2-DCA177CAA106 | DC4A7DDA-45A1-4D5B-8D46-21FA99A3868E | 11-22-33 | 12345678 |
When I send the requests to the callback handler for deposits
Then the deposit records are recorded

Examples:
| APIVersion |
| 1 |

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 7 additions & 5 deletions CallbackHandler.IntegrationTests/Shared/SharedSteps.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public SharedSteps(ScenarioContext scenarioContext,

this.SecurityServiceSteps = new SecurityServiceSteps(testingContext.DockerHelper.SecurityServiceClient, testingContext.DockerHelper.AccessToken);
this.TransactionProcessorSteps = new TransactionProcessorSteps(testingContext.DockerHelper.TransactionProcessorClient, testingContext.DockerHelper.TestHostHttpClient,
testingContext.DockerHelper.ProjectionManagementClient, testingContext.DockerHelper.AgencyBankingClient);
testingContext.DockerHelper.LegacyProjectionManagementClient, testingContext.DockerHelper.AgencyBankingClient);

}

Expand All @@ -60,13 +60,14 @@ public async Task GivenIHaveTheFollowingBankDepositCallbacks(DataTable table)
}

[When(@"I send the requests to the callback handler for deposits")]
public async Task WhenISendTheRequestsToTheCallbackHandlerForDeposits()
{
public async Task WhenISendTheRequestsToTheCallbackHandlerForDeposits() {
String apiVersion = ScenarioContext.ScenarioInfo.Arguments["APIVersion"].ToString();

using HttpClient client = new();
foreach (var testingContextDeposit in this.TestingContext.Deposits)
{
String requestUri =
$"http://localhost:{this.TestingContext.DockerHelper.GetCallbackHandlerPort()}/api/callbacks";
$"http://localhost:{this.TestingContext.DockerHelper.GetCallbackHandlerPort()}/api/v{apiVersion}/callbacks";
HttpRequestMessage msg = new(HttpMethod.Post, requestUri);
var payload = StringSerialiser.Serialise(testingContextDeposit);

Expand All @@ -87,11 +88,12 @@ public async Task WhenISendTheRequestsToTheCallbackHandlerForDeposits()
[Then("the deposit records are recorded")]
public async Task ThenTheDepositRecordsAreRecorded()
{
String apiVersion = ScenarioContext.ScenarioInfo.Arguments["APIVersion"].ToString();
using HttpClient client = new();
foreach (var sentCallback in this.TestingContext.SentCallbacks)
{
String requestUri =
$"http://localhost:{this.TestingContext.DockerHelper.GetCallbackHandlerPort()}/api/callbacks/{sentCallback.Key}";
$"http://localhost:{this.TestingContext.DockerHelper.GetCallbackHandlerPort()}/api/v{apiVersion}/callbacks/{sentCallback.Key}";
HttpRequestMessage msg = new(HttpMethod.Get, requestUri);
var response = await client.SendAsync(msg);
response.StatusCode.ShouldBe(HttpStatusCode.OK);
Expand Down
18 changes: 11 additions & 7 deletions CallbackHandler.Tests/BootstrapperTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

namespace CallbackHandler.Tests
{
using CallbackHandler.Bootstrapper;
using System.Collections.Generic;
using System.Diagnostics;
using Lamar;
Expand All @@ -11,6 +12,7 @@ namespace CallbackHandler.Tests
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Shared.Serialisation;

[Collection("TestCollection")]
public class BootstrapperTests
Expand All @@ -24,12 +26,13 @@ public void VerifyBootstrapperIsValid()
hostingEnvironment.ApplicationName.Getter().Returns("Test Application");

ServiceRegistry services = new();
Startup s = new(hostingEnvironment.Instance());
Startup.Configuration = this.SetupMemoryConfiguration();
IConfigurationRoot configuration = this.SetupMemoryConfiguration();

this.AddTestRegistrations(services, hostingEnvironment.Instance());
s.ConfigureContainer(services);
Startup.Container.AssertConfigurationIsValid(AssertMode.Full);
this.AddTestRegistrations(services, hostingEnvironment.Instance(), configuration);
services.AddCallbackHandlerRegistries(configuration);
Container container = new(services);
container.AssertConfigurationIsValid(AssertMode.Full);
StringSerialiser.Initialise(container.GetRequiredService<IStringSerialiser>());
}

private IConfigurationRoot SetupMemoryConfiguration()
Expand All @@ -56,15 +59,16 @@ private IConfigurationRoot SetupMemoryConfiguration()
}

private void AddTestRegistrations(ServiceRegistry services,
IWebHostEnvironment hostingEnvironment)
IWebHostEnvironment hostingEnvironment,
IConfiguration configuration)
{
services.AddLogging();
DiagnosticListener diagnosticSource = new(hostingEnvironment.ApplicationName);
services.AddSingleton<DiagnosticSource>(diagnosticSource);
services.AddSingleton<DiagnosticListener>(diagnosticSource);
services.AddSingleton<IWebHostEnvironment>(hostingEnvironment);
services.AddSingleton<IHostEnvironment>(hostingEnvironment);
services.AddSingleton<IConfiguration>(Startup.Configuration);
services.AddSingleton<IConfiguration>(configuration);
}
}
}
32 changes: 9 additions & 23 deletions CallbackHandler/Bootstrapper/MiddlewareRegistry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
using KurrentDB.Client;
using Microsoft.Extensions.Logging;
using Microsoft.OpenApi;
using Swashbuckle.AspNetCore.SwaggerGen;
using TransactionProcessing.ApiDefaults;

namespace CallbackHandler.Bootstrapper;

Expand All @@ -14,7 +14,6 @@ namespace CallbackHandler.Bootstrapper;
using Shared.EventStore.Extensions;
using Shared.General;
using Shared.Middleware;
using Swashbuckle.AspNetCore.Filters;
using System;
using System.Diagnostics.CodeAnalysis;
using System.IO;
Expand All @@ -23,17 +22,14 @@ namespace CallbackHandler.Bootstrapper;
[ExcludeFromCodeCoverage]
public class MiddlewareRegistry :ServiceRegistry
{
public MiddlewareRegistry()
public MiddlewareRegistry(IConfiguration configuration)
{
String connectionString = Startup.Configuration.GetValue<String>("EventStoreSettings:ConnectionString");
String connectionString = configuration.GetValue<String>("EventStoreSettings:ConnectionString");
KurrentDBClientSettings eventStoreSettings = KurrentDBClientSettings.Create(connectionString);

this.AddHealthChecks().AddEventStore(eventStoreSettings, userCredentials: eventStoreSettings.DefaultCredentials,
name: "Eventstore", failureStatus: HealthStatus.Unhealthy, tags: new[] { "db", "eventstore" });

this.AddSwaggerGen(AddSwaggerAction);
this.AddSwaggerExamples();

this.AddControllers();

Assembly assembly = this.GetType().GetTypeInfo().Assembly;
Expand All @@ -47,22 +43,12 @@ public MiddlewareRegistry()

this.ConfigureHttpJsonOptions(jsonOptions => JsonSerializerConfiguration.ConfigureMinimalApi(jsonOptions.SerializerOptions));

this.AddHealthMonitoringRegistration(Startup.Configuration);
}

private void AddSwaggerAction(SwaggerGenOptions c) {
c.SwaggerDoc("v1", new OpenApiInfo { Title = "Callback Handler API", Version = "1.0", Description = "A REST Api to handle callback requests from external parties API's.", Contact = new OpenApiContact { Name = "Stuart Ferguson", Email = "golfhandicapping@btinternet.com" } });
// add a custom operation filter which sets default values
c.OperationFilter<SwaggerDefaultValues>();
c.ExampleFilters();

//Locate the XML files being generated by ASP.NET...
DirectoryInfo directory = new(AppContext.BaseDirectory);
FileInfo[] xmlFiles = directory.GetFiles("*.xml");
this.AddHealthMonitoringRegistration(configuration);

//... and tell Swagger to use those XML comments.
foreach (FileInfo fileInfo in xmlFiles) {
c.IncludeXmlComments(fileInfo.FullName);
}
this.AddApiDefaults(options =>
{
options.Title = "Callback Handler";
options.Description = "API to accept callbacks from external systems";
});
}
}
Loading
Loading