Skip to content
Open
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
16 changes: 16 additions & 0 deletions HealthMediator.Utils.Tests/HealthMediator.Utils.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,22 @@
</PropertyGroup>

<ItemGroup>
<None Remove="config\emptyAppSettings.json" />
<None Remove="config\validAppSettings.json" />
</ItemGroup>

<ItemGroup>
<Content Include="config\emptyAppSettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="config\validAppSettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.1.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.1.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.0" />
<PackageReference Include="Moq" Version="4.9.0" />
<PackageReference Include="xunit" Version="2.4.0" />
Expand Down
68 changes: 67 additions & 1 deletion HealthMediator.Utils.Tests/HealthUtilTests.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,74 @@
using Microsoft.Extensions.Configuration;
using Moq;
using System;
using System.IO;
using Xunit;

namespace HealthMediator.Utils.Tests
{
public class HealthUtilTests
{
}
[Fact]
public void Initialize_GivenIConfigurationWithNoOpenHimAuthSection_ShouldThrowArgumentNullException()
{
// Arrange
var mock = new Mock<IConfiguration>();

// Act
var result = Assert.Throws<ArgumentNullException>(() => new HealthUtil().Initialize(mock.Object));

// Assert
Assert.Equal("Value cannot be null.\r\nParameter name: configuration", result.Message);
}

[Fact]
public void Initialize_GivenIConfigurationSectionsMocked_ShouldThrowArgumentNullExceptionForOpenHimCoreHost()
{
// Arrange
var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("config/emptyAppSettings.json", false, true)
.Build();

// Act
var result = Assert.Throws<ArgumentNullException>(() => new HealthUtil().Initialize(configuration));

// Assert
Assert.Equal("Value cannot be null.\r\nParameter name: OpenHimCoreHost", result.Message);
}

[Fact]
public void Initialize_GivenIConfigurationSectionsMocked_ShouldReturnHealthUtilObjectSuccess()
{
// Arrange
var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("config/validAppSettings.json", false, true)
.Build();

// Act
var result = new HealthUtil().Initialize(configuration);

// Assert
Assert.NotNull(result);
Assert.True(result.IsInitialized);
}

[Fact]
public void RegisterMediator_GivenIConfigurationSectionsMocked_ShouldThrowInvalidOperationExceptionInitializeRequired()
{
// Arrange
var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("config/emptyAppSettings.json", false, true)
.Build();

// Act
var result = Assert.Throws<InvalidOperationException>(() => new HealthUtil().RegisterMediator());

// Assert
Assert.Equal("You must call Initialize before calling RegisterMediator.", result.Message);
}

}
}
38 changes: 37 additions & 1 deletion HealthMediator.Utils.Tests/RestSharpExtensionsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public void GetRestResponseException_GivenIRestResponseIsSuccessful_ShouldReturn
}

[Fact]
public void GetRestResponseException_GivenIRestResponseIsNotSuccessful_ShouldReturnException()
public void GetRestResponseException_GivenIRestResponseIsNotSuccessful_ShouldReturnExceptionWithDefaultMessages()
{
// Arrange
var defaultMessage = "not specified";
Expand All @@ -45,6 +45,42 @@ public void GetRestResponseException_GivenIRestResponseIsNotSuccessful_ShouldRet

// Assert
Assert.NotNull(result);
Assert.Contains($"ResponseStatus: {defaultMessage}", result.Message);
Assert.Contains($"ResponseUri: {defaultMessage}", result.Message);
Assert.Contains($"ErrorException: {defaultMessage}", result.Message);
Assert.Contains($"Stacktrace: {defaultMessage}", result.Message);
Assert.Contains($"ExceptionType: {defaultMessage}", result.Message);
}

[Fact]
public void GetRestResponseException_GivenIRestResponseIsNotSuccessful_ShouldReturnExceptionWithCustomMessages()
{
// Arrange
var statusDescription = "statusDescription";
var responseUri = new Uri("http://test.io");
var errorMessage = "errorMessage";
var exception = new Exception("testErrorMessage");
var defaultMessage = "not specified";

var mock = new Mock<IRestResponse>();
mock.Setup(x => x.IsSuccessful).Returns(false);
mock.Setup(x => x.StatusDescription).Returns(statusDescription);
mock.Setup(x => x.ResponseUri).Returns(responseUri);
mock.Setup(x => x.ErrorMessage).Returns(errorMessage);
mock.Setup(x => x.ErrorException).Returns(exception);

IRestResponse restRespone = mock.Object;

// Act
var result = restRespone.GetFailedRestResponseException();

// Assert
Assert.NotNull(result);
Assert.Contains($"ResponseStatus: {statusDescription}", result.Message);
Assert.Contains($"ResponseUri: {responseUri.ToString()}", result.Message);
Assert.Contains($"ErrorException: {errorMessage}", result.Message);
Assert.Contains($"Stacktrace: {defaultMessage}", result.Message);
Assert.Contains($"ExceptionType: {exception.GetType().Name}", result.Message);
}
}
}
44 changes: 44 additions & 0 deletions HealthMediator.Utils.Tests/SHATests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using HealthMediator.Utils.Helpers;
using System;
using Xunit;

namespace HealthMediator.Utils.Tests
{
public class SHATests
{
[Fact]
public void EncryptUsingSHA512_GivenNullInput_ShouldThrowArgumentNullException()
{
// Assert
Assert.Throws<ArgumentNullException>(() => SHA.EncryptUsingSHA512(null));
}

[Fact]
public void EncryptUsingSHA512_GivenEmptyInput_ShouldReturnEmptySHA512EncryptedString()
{
// Arrange
var input = string.Empty;

// Act
var result = SHA.EncryptUsingSHA512(input);

// Assert
Assert.Equal(string.Empty, result);
}

[Fact]
public void EncryptUsingSHA512_GivenValidInput_ShouldReturnSHA512EncryptedString()
{
// Arrange
var input = "password";
// generated at https://passwordsgenerator.net/sha512-hash-generator/
var sha512Value = "b109f3bbbc244eb82441917ed06d618b9008dd09b3befd1b5e07394c706a8bb980b1d7785e5976ec049b46df5f1326af5a2ea6d103fd07c95385ffab0cacbc86";

// Act
var result = SHA.EncryptUsingSHA512(input);

// Assert
Assert.Equal(sha512Value, result);
}
}
}
3 changes: 3 additions & 0 deletions HealthMediator.Utils.Tests/config/emptyAppSettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"ForInitialization" : "SomeValue"
}
54 changes: 54 additions & 0 deletions HealthMediator.Utils.Tests/config/validAppSettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
{
"mediatorconfig": {
"openHimAuth": {
"username": "root@openhim.org",
"password": "password",
"trustSelfSigned": true
},
"mediatorCore": {
"openHimCoreHost": "https://localhost:9095",
"openHimCoreAuthPath": "authenticate",
"openHimRegisterMediatorPath": "mediators",
"openHimheartbeatpath": "heartbeat",
"heartbeatInterval": 10,
"isHeartbeatDisabled": false
},
"mediatorSetup": {
"urn": "urn:uuid:3332e057-2ef5-4586-a437-105c9916147f",
"version": "0.0.1",
"name": "dotnet Core Health Mediator",
"description": "dotnet Core Health Mediator",
"defaultChannelConfig": [
{
"name": "Health Mediator",
"urlPattern": "^/healthMediator$",
"type": "http",
"routes": [
{
"name": "Health Mediator Route",
"host": "localhost",
"port": "5000",
"primary": true,
"type": "http",
"path": "api/health"
}
],
"allow": [
"admin",
"mobenzi"
]
}
],
"endpoints": [
{
"name": "healthRoute",
"host": "localhost",
"path": "/api/health",
"port": "5000",
"primary": true,
"type": "http"
}
]
}
}
}
22 changes: 18 additions & 4 deletions HealthMediator.Utils/HealthUtil.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,31 +21,45 @@ public class HealthUtil : IHealthUtil
private RestClient restClient;
private List<Parameter> authHeaders;
private Timer heartbeatTimer = null;
private string authSettingSection = "mediatorConfig:openHimAuth";
private string coreMediatorSettingsSection = "mediatorConfig:mediatorCore";
private string mediatorConfigSection = "mediatorConfig:mediatorSetup";

public bool IsInitialized { get; protected set; }

public HealthUtil Initialize(IConfiguration configuration)
{
var authSettings = new OpenHIMAuth();
configuration.GetSection("mediatorConfig:openHimAuth").Bind(authSettings);
configuration.GetSection(authSettingSection).Bind(authSettings);

var coreMediatorSettings = new MediatorCoreConfig();
configuration.GetSection("mediatorConfig:mediatorCore").Bind(coreMediatorSettings);
configuration.GetSection(coreMediatorSettingsSection).Bind(coreMediatorSettings);

var mediatorConfig = new MediatorSetup();
configuration.GetSection("mediatorConfig:mediatorSetup").Bind(mediatorConfig);
configuration.GetSection(mediatorConfigSection).Bind(mediatorConfig);

this.authSettings = authSettings;
this.coreMediatorSettings = coreMediatorSettings;
this.mediatorConfig = mediatorConfig;

restClient = new RestClient(coreMediatorSettings.OpenHimCoreHost);
restClient = new RestClient(coreMediatorSettings?.OpenHimCoreHost
?? throw new ArgumentNullException(nameof(coreMediatorSettings.OpenHimCoreHost)));

restClient.RemoteCertificateValidationCallback +=
(sender, certificate, chain, sslPolicyErrors) => authSettings.TrustSelfSigned;

IsInitialized = true;

return this;
}

public HealthUtil RegisterMediator()
{
if(!IsInitialized)
{
throw new InvalidOperationException("You must call Initialize before calling RegisterMediator.");
}

// Authenticate with the HIM and get Authorization Token
authHeaders = GetAuthenticationRequestParameters();

Expand Down
8 changes: 8 additions & 0 deletions HealthMediator.Utils/Helpers/RestSharpExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ namespace HealthMediator.Utils.Helpers
{
public static class RestSharpExtensions
{
/// <summary>
/// A reusable method that can be called on a IRestResponse instance to
/// build an meaningful exception
/// </summary>
/// <param name="result">IRestResponse</param>
/// <returns>ArgumentNullException when IRestResponse is null</returns>
/// <returns>null when IRestResponse.IsSuccessful is true</returns>
/// <returns>Exception object when IRestResponse.IsSuccessful is false</returns>
public static Exception GetFailedRestResponseException(this IRestResponse result)
{
if(result is null)
Expand Down
16 changes: 13 additions & 3 deletions HealthMediator.Utils/Helpers/SHA.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,25 @@ public static class SHA
{
public static string EncryptUsingSHA512(string text)
{
string hex = "";
if(text is null)
{
throw new ArgumentNullException("text");
}

if(string.IsNullOrWhiteSpace(text))
{
return text;
}

StringBuilder hex = new StringBuilder();
SHA512 alg = SHA512Managed.Create();
byte[] result = alg.ComputeHash(Encoding.Default.GetBytes(text));
string hash = Encoding.UTF8.GetString(result);
foreach (byte x in result)
{
hex += String.Format("{0:x2}", x);
hex.Append($"{x:x2}");
}
return hex;
return hex.ToString();
}
}
}
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# openhim-mediator-dotnetcore-utils
# openhim-mediator-utils-dotnetstandard
This project defines a helper library (Utils) targetting dotNetStandard 2.0 that allows you to easily develop a dotNet Core or dotNet
OpenHIM Mediator extension by simply adding it as a dependency and defining your json config.