Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add support for dataset aliases #146

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
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
8 changes: 8 additions & 0 deletions Dan.Common/Models/EvidenceCode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -138,4 +138,12 @@ public class EvidenceCode
[DataMember(Name = "timeout")]
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public int? Timeout { get; set; }

/// <summary>
/// Optional setting for aliases. Key is service context, value is Dataset name
/// Allows for the same dataset to be shared between service contexts with different names.
/// </summary>
[DataMember(Name = "datasetAliases")]
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public Dictionary<string,string>? DatasetAliases { get; set; }
}
63 changes: 62 additions & 1 deletion Dan.Core.UnitTest/AvailableEvidenceCodesServiceTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Dan.Core.Services;
using Dan.Core.Services.Interfaces;
using Dan.Core.UnitTest.Helpers;
using FluentAssertions;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Logging;
Expand Down Expand Up @@ -55,6 +56,23 @@ public class AvailableEvidenceCodesServiceTest
Name = "ec2_req"
}
}
},
new EvidenceCode
{
EvidenceCodeName = "ec3",
BelongsToServiceContexts = new List<string> { "sc1", "sc2" },
DatasetAliases = new Dictionary<string, string>
{
{"sc1", "a1"},
{"sc2", "a2"}
},
AuthorizationRequirements = new List<Requirement>
{
new TestAuthorizationRequirement
{
Name = "ec3_req"
}
}
}
};

Expand Down Expand Up @@ -126,20 +144,63 @@ public async Task CheckServiceContextRequirementsIncluded()
var a = await acs.GetAvailableEvidenceCodes();

// Assert
Assert.AreEqual(4, a.Count); // we have two evidence sources in config
Assert.AreEqual(4, a.Count);

// ec1
Assert.AreEqual(3, a[0].AuthorizationRequirements.Count);
Assert.IsTrue(a[0].AuthorizationRequirements.All(x => x.GetType() == typeof(TestAuthorizationRequirement)));
Assert.IsTrue(a[0].AuthorizationRequirements.Any(x => ((TestAuthorizationRequirement)x).Name == "ec1_req"));
Assert.IsTrue(a[0].AuthorizationRequirements.Any(x => ((TestAuthorizationRequirement)x).Name == "sc1_req1"));
Assert.IsTrue(a[0].AuthorizationRequirements.Any(x => ((TestAuthorizationRequirement)x).Name == "sc1_req2"));

// ec2
Assert.AreEqual(5, a[1].AuthorizationRequirements.Count);
Assert.IsTrue(a[1].AuthorizationRequirements.All(x => x.GetType() == typeof(TestAuthorizationRequirement)));
Assert.IsTrue(a[1].AuthorizationRequirements.Any(x => ((TestAuthorizationRequirement)x).Name == "ec2_req"));
Assert.IsTrue(a[1].AuthorizationRequirements.Any(x => ((TestAuthorizationRequirement)x).Name == "sc1_req1"));
Assert.IsTrue(a[1].AuthorizationRequirements.Any(x => ((TestAuthorizationRequirement)x).Name == "sc1_req2"));
Assert.IsTrue(a[1].AuthorizationRequirements.Any(x => ((TestAuthorizationRequirement)x).Name == "sc2_req1"));
Assert.IsTrue(a[1].AuthorizationRequirements.Any(x => ((TestAuthorizationRequirement)x).Name == "sc2_req2"));

// Aliases get replaced at end of list
// a1
Assert.AreEqual(3, a[2].AuthorizationRequirements.Count);
Assert.IsTrue(a[2].AuthorizationRequirements.All(x => x.GetType() == typeof(TestAuthorizationRequirement)));
Assert.IsTrue(a[2].AuthorizationRequirements.Any(x => ((TestAuthorizationRequirement)x).Name == "ec3_req"));
Assert.IsTrue(a[2].AuthorizationRequirements.Any(x => ((TestAuthorizationRequirement)x).Name == "sc1_req1"));
Assert.IsTrue(a[2].AuthorizationRequirements.Any(x => ((TestAuthorizationRequirement)x).Name == "sc1_req2"));

// a2
Assert.AreEqual(3, a[3].AuthorizationRequirements.Count);
Assert.IsTrue(a[3].AuthorizationRequirements.All(x => x.GetType() == typeof(TestAuthorizationRequirement)));
Assert.IsTrue(a[3].AuthorizationRequirements.Any(x => ((TestAuthorizationRequirement)x).Name == "ec3_req"));
Assert.IsTrue(a[3].AuthorizationRequirements.Any(x => ((TestAuthorizationRequirement)x).Name == "sc2_req1"));
Assert.IsTrue(a[3].AuthorizationRequirements.Any(x => ((TestAuthorizationRequirement)x).Name == "sc2_req2"));
}

[TestMethod]
public async Task GetAliases()
{
var acs = new AvailableEvidenceCodesService(
_loggerFactory,
_mockHttpClientFactory.Object,
_policyRegistry,
_mockDistributedCache.Object,
_mockServiceContextService.Object,
_mockFunctionContextAccessor.Object);

var expected = new Dictionary<string, string>
{
{"a1", "ec3"},
{"a2", "ec3"}
};

// Act
await acs.GetAvailableEvidenceCodes();
var actual = acs.GetAliases();

// Assert
actual.Should().BeEquivalentTo(expected);
}
}

Expand Down
1 change: 1 addition & 0 deletions Dan.Core.UnitTest/Dan.Core.UnitTest.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="FluentAssertions" Version="7.0.0"/>
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="8.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0" />
<PackageReference Include="Moq" Version="4.20.70" />
Expand Down
91 changes: 81 additions & 10 deletions Dan.Core.UnitTest/EvidenceHarvesterServiceTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public class EvidenceHarvesterServiceTest
private readonly Mock<IEvidenceStatusService> _mockEvidenceStatusService = new();
private readonly Mock<ITokenRequesterService> _mockTokenRequesterService = new();
private readonly Mock<IRequestContextService> _mockRequestContextService = new();
private readonly Mock<IAvailableEvidenceCodesService> _mockAvailableEvidenceCodesService = new();

private const string CONSENT_DENIED = "denied";

Expand Down Expand Up @@ -61,7 +62,14 @@ public async Task Harvest_Success_Open()
);

Accreditation accreditation = MakeAccreditation("aid", Certificates.DEFAULT_ORG);
var evidenceHarvesterService = new EvidenceHarvesterService(_loggerFactory, _mockHttpClientFactory.Object, _mockConsentService.Object, _mockEvidenceStatusService.Object, _mockTokenRequesterService.Object, _mockRequestContextService.Object);
var evidenceHarvesterService = new EvidenceHarvesterService(
_loggerFactory,
_mockHttpClientFactory.Object,
_mockConsentService.Object,
_mockEvidenceStatusService.Object,
_mockTokenRequesterService.Object,
_mockRequestContextService.Object,
_mockAvailableEvidenceCodesService.Object);

var response = await evidenceHarvesterService.Harvest(EVIDENCECODE_OPEN, accreditation);

Expand All @@ -84,7 +92,14 @@ public async Task Harvest_Success_Consent()
_mockConsentService.Setup(_ => _.GetJwt(It.IsAny<Accreditation>())).Returns(Task.FromResult("somejwt"));

Accreditation accreditation = MakeAccreditation("aid", Certificates.DEFAULT_ORG);
var evidenceHarvesterService = new EvidenceHarvesterService(_loggerFactory, _mockHttpClientFactory.Object, _mockConsentService.Object, _mockEvidenceStatusService.Object, _mockTokenRequesterService.Object, _mockRequestContextService.Object);
var evidenceHarvesterService = new EvidenceHarvesterService(
_loggerFactory,
_mockHttpClientFactory.Object,
_mockConsentService.Object,
_mockEvidenceStatusService.Object,
_mockTokenRequesterService.Object,
_mockRequestContextService.Object,
_mockAvailableEvidenceCodesService.Object);

var response = await evidenceHarvesterService.Harvest(EVIDENCECODE_CONSENT, accreditation);

Expand All @@ -106,7 +121,14 @@ public void Harvest_Failure_ConsentRequestPending()
);
Accreditation accreditation = MakeAccreditation("aid", Certificates.DEFAULT_ORG, null);

var evidenceHarvesterService = new EvidenceHarvesterService(_loggerFactory, _mockHttpClientFactory.Object, _mockConsentService.Object, _mockEvidenceStatusService.Object, _mockTokenRequesterService.Object, _mockRequestContextService.Object);
var evidenceHarvesterService = new EvidenceHarvesterService(
_loggerFactory,
_mockHttpClientFactory.Object,
_mockConsentService.Object,
_mockEvidenceStatusService.Object,
_mockTokenRequesterService.Object,
_mockRequestContextService.Object,
_mockAvailableEvidenceCodesService.Object);

var actual = Assert.ThrowsExceptionAsync<RequiresConsentException>(() => evidenceHarvesterService.Harvest(EVIDENCECODE_CONSENT, accreditation));
StringAssert.Contains(actual.Result.Message, "pending a reply to the consent request");
Expand All @@ -126,7 +148,14 @@ public void Harvest_Failure_ConsentDenied()
);
Accreditation accreditation = MakeAccreditation("aid", Certificates.DEFAULT_ORG, null, CONSENT_DENIED);

var evidenceHarvesterService = new EvidenceHarvesterService(_loggerFactory, _mockHttpClientFactory.Object, _mockConsentService.Object, _mockEvidenceStatusService.Object, _mockTokenRequesterService.Object, _mockRequestContextService.Object);
var evidenceHarvesterService = new EvidenceHarvesterService(
_loggerFactory,
_mockHttpClientFactory.Object,
_mockConsentService.Object,
_mockEvidenceStatusService.Object,
_mockTokenRequesterService.Object,
_mockRequestContextService.Object,
_mockAvailableEvidenceCodesService.Object);

var actual = Assert.ThrowsExceptionAsync<RequiresConsentException>(() => evidenceHarvesterService.Harvest(EVIDENCECODE_CONSENT, accreditation));
StringAssert.Contains(actual.Result.Message, "evidence code has been denied or revoked");
Expand All @@ -146,7 +175,14 @@ public void Harvest_Failure_ConsentExpired()
);
Accreditation accreditation = MakeAccreditation("aid", Certificates.DEFAULT_ORG, DateTime.Now.AddDays(-1));

var evidenceHarvesterService = new EvidenceHarvesterService(_loggerFactory, _mockHttpClientFactory.Object, _mockConsentService.Object, _mockEvidenceStatusService.Object, _mockTokenRequesterService.Object, _mockRequestContextService.Object);
var evidenceHarvesterService = new EvidenceHarvesterService(
_loggerFactory,
_mockHttpClientFactory.Object,
_mockConsentService.Object,
_mockEvidenceStatusService.Object,
_mockTokenRequesterService.Object,
_mockRequestContextService.Object,
_mockAvailableEvidenceCodesService.Object);

var actual = Assert.ThrowsExceptionAsync<RequiresConsentException>(() => evidenceHarvesterService.Harvest(EVIDENCECODE_CONSENT, accreditation));
StringAssert.Contains(actual.Result.Message, "evidence code has expired");
Expand All @@ -167,7 +203,14 @@ public void Harvest_Failure_AsyncWaiting()

Accreditation accreditation = MakeAccreditation("aid", Certificates.DEFAULT_ORG);

var evidenceHarvesterService = new EvidenceHarvesterService(_loggerFactory, _mockHttpClientFactory.Object, _mockConsentService.Object, _mockEvidenceStatusService.Object, _mockTokenRequesterService.Object, _mockRequestContextService.Object);
var evidenceHarvesterService = new EvidenceHarvesterService(
_loggerFactory,
_mockHttpClientFactory.Object,
_mockConsentService.Object,
_mockEvidenceStatusService.Object,
_mockTokenRequesterService.Object,
_mockRequestContextService.Object,
_mockAvailableEvidenceCodesService.Object);

var actual = Assert.ThrowsExceptionAsync<AsyncEvidenceStillWaitingException>(() => evidenceHarvesterService.Harvest(EVIDENCECODE_ASYNC, accreditation));
StringAssert.Contains(actual.Result.Message, "The data for the requested evidence is not yet available");
Expand All @@ -191,7 +234,14 @@ public void Harvest_Failure_MissingScope()

Accreditation accreditation = MakeAccreditation("aid", Certificates.DEFAULT_ORG);

var evidenceHarvesterService = new EvidenceHarvesterService(_loggerFactory, _mockHttpClientFactory.Object, _mockConsentService.Object, _mockEvidenceStatusService.Object, _mockTokenRequesterService.Object, _mockRequestContextService.Object);
var evidenceHarvesterService = new EvidenceHarvesterService(
_loggerFactory,
_mockHttpClientFactory.Object,
_mockConsentService.Object,
_mockEvidenceStatusService.Object,
_mockTokenRequesterService.Object,
_mockRequestContextService.Object,
_mockAvailableEvidenceCodesService.Object);

var actual = Assert.ThrowsExceptionAsync<ServiceNotAvailableException>(() => evidenceHarvesterService.Harvest(EVIDENCECODE_OPEN, accreditation));
StringAssert.Contains(actual.Result.Message, "unable to retrieve authentication token");
Expand All @@ -216,7 +266,14 @@ public void Harvest_Failure_AsyncWaitingWithRetry()

Accreditation accreditation = MakeAccreditation("aid", Certificates.DEFAULT_ORG, DateTime.Now.AddDays(-1));

var evidenceHarvesterService = new EvidenceHarvesterService(_loggerFactory, _mockHttpClientFactory.Object, _mockConsentService.Object, _mockEvidenceStatusService.Object, _mockTokenRequesterService.Object, _mockRequestContextService.Object);
var evidenceHarvesterService = new EvidenceHarvesterService(
_loggerFactory,
_mockHttpClientFactory.Object,
_mockConsentService.Object,
_mockEvidenceStatusService.Object,
_mockTokenRequesterService.Object,
_mockRequestContextService.Object,
_mockAvailableEvidenceCodesService.Object);

var actual = Assert.ThrowsExceptionAsync<AsyncEvidenceStillWaitingException>(() => evidenceHarvesterService.Harvest(EVIDENCECODE_ASYNC, accreditation));
StringAssert.Contains(actual.Result.Message, "The data for the requested evidence is not yet available");
Expand All @@ -237,7 +294,14 @@ public async Task Harvest_Success_AsyncOpen()

Accreditation accreditation = MakeAccreditation("aid", Certificates.DEFAULT_ORG, DateTime.Now.AddDays(-1));

var evidenceHarvesterService = new EvidenceHarvesterService(_loggerFactory, _mockHttpClientFactory.Object, _mockConsentService.Object, _mockEvidenceStatusService.Object, _mockTokenRequesterService.Object, _mockRequestContextService.Object);
var evidenceHarvesterService = new EvidenceHarvesterService(
_loggerFactory,
_mockHttpClientFactory.Object,
_mockConsentService.Object,
_mockEvidenceStatusService.Object,
_mockTokenRequesterService.Object,
_mockRequestContextService.Object,
_mockAvailableEvidenceCodesService.Object);
var response = await evidenceHarvesterService.Harvest(EVIDENCECODE_ASYNC, accreditation);

Assert.AreEqual((int)StatusCodeId.Available, response.EvidenceStatus.Status.Code);
Expand All @@ -259,7 +323,14 @@ public async Task Harvest_Success_Stream()

Accreditation accreditation = MakeAccreditation("aid", Certificates.DEFAULT_ORG, DateTime.Now.AddDays(-1));

var evidenceHarvesterService = new EvidenceHarvesterService(_loggerFactory, _mockHttpClientFactory.Object, _mockConsentService.Object, _mockEvidenceStatusService.Object, _mockTokenRequesterService.Object, _mockRequestContextService.Object);
var evidenceHarvesterService = new EvidenceHarvesterService(
_loggerFactory,
_mockHttpClientFactory.Object,
_mockConsentService.Object,
_mockEvidenceStatusService.Object,
_mockTokenRequesterService.Object,
_mockRequestContextService.Object,
_mockAvailableEvidenceCodesService.Object);
var response = await evidenceHarvesterService.HarvestStream(EVIDENCECODE_STREAM, accreditation);

var sr = new StreamReader(response);
Expand Down
2 changes: 1 addition & 1 deletion Dan.Core.UnitTest/appsettings.unittest.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"AccreditationMaximumValidDays": 10,
"AccreditationMinimumValidDays": 1,
"DoffinLinkTemplate": "{0}",
"EvidenceSources": "ut1,ut2",
"EvidenceSources": "ut1",
"EvidenceSourceURLPattern": "http://%s.unittest.net/api/evidencecodes,",
"FunctionKeyValue": "x",
"ASPNETCORE_ENVIRONMENT": "LocalDevelopment"
Expand Down
6 changes: 4 additions & 2 deletions Dan.Core/Extensions/EvidenceCodeExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ public static class EvidenceCodeExtensions
/// Gets the full URL to the evidence code
/// </summary>
/// <param name="evidenceCode">The evidence code instance</param>
/// <param name="aliases">Collection of evidence code aliases</param>
/// <returns>A fully qualified URL</returns>
public static string GetEvidenceSourceUrl(this EvidenceCode evidenceCode)
public static string GetEvidenceSourceUrl(this EvidenceCode evidenceCode, Dictionary<string, string> aliases)
{
return Settings.GetEvidenceSourceUrl(evidenceCode.EvidenceSource).Replace("/api/evidencecodes", $"/api/{evidenceCode.EvidenceCodeName}?code={Settings.FunctionKeyValue}");
var evidenceCodeName = aliases?.GetValueOrDefault(evidenceCode.EvidenceCodeName) ?? evidenceCode.EvidenceCodeName;
return Settings.GetEvidenceSourceUrl(evidenceCode.EvidenceSource).Replace("/api/evidencecodes", $"/api/{evidenceCodeName}?code={Settings.FunctionKeyValue}");
}

/// <summary>
Expand Down
Loading
Loading