Skip to content
Open
Show file tree
Hide file tree
Changes from 2 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
Original file line number Diff line number Diff line change
Expand Up @@ -62,5 +62,7 @@ public ListedCapabilityStatement()
public IDictionary<string, JToken> AdditionalData { get; }

public ICollection<ReferenceComponent> Profile { get; }

public ICollection<string> Instantiates { get; internal set; }
}
}
6 changes: 6 additions & 0 deletions src/Microsoft.Health.Fhir.Shared.Api/Modules/FhirModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,12 @@ ResourceElement SetMetadata(Resource resource, string versionId, DateTimeOffset
services.AddTransient(typeof(IScopeProvider<>), typeof(ScopeProvider<>));

services.AddScoped<IDocRefRequestConverter, DocRefRequestConverter>();

services.TypesInSameAssembly(KnownAssemblies.All)
.AssignableTo<IInstantiateCapability>()
.Transient()
.AsService<IInstantiateCapability>();
services.AddFactory<IScoped<IEnumerable<IInstantiateCapability>>>();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
// -------------------------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
// -------------------------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Health.Extensions.DependencyInjection;
using Microsoft.Health.Fhir.Core.Features.Conformance;
using Microsoft.Health.Fhir.Core.Features.Conformance.Models;
using Microsoft.Health.Fhir.Shared.Core.Features.Conformance;
using Microsoft.Health.Fhir.Tests.Common;
using Microsoft.Health.Test.Utilities;
using NSubstitute;
using Xunit;

namespace Microsoft.Health.Fhir.Shared.Core.UnitTests.Features.Conformance
{
[Trait(Traits.OwningTeam, OwningTeam.Fhir)]
[Trait(Traits.Category, Categories.Conformance)]
public class InstantiatesCapabilityProviderTests
{
private readonly InstantiatesCapabilityProvider _provider;
private readonly List<IInstantiateCapability> _capabilities;

public InstantiatesCapabilityProviderTests()
{
_capabilities = new List<IInstantiateCapability>();
var s = Substitute.For<IScoped<IEnumerable<IInstantiateCapability>>>();
s.Value.Returns(_capabilities);

_provider = new InstantiatesCapabilityProvider(() => s);
}

[Theory]
[InlineData(1)]
[InlineData(0)]
[InlineData(1, 0)]
[InlineData(0, 0, 0)]
[InlineData(1, 2, 3, 4)]
[InlineData(1, 0, 3, 0)]
public async Task GivenCapabilities_WhenBuilding_ThenInstantiatesFieldIsPopulated(
params int[] counts)
{
var urls = AddCapabilities(counts);
var instantiates = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
var builder = Substitute.For<ICapabilityStatementBuilder>();
builder.Apply(Arg.Any<Action<ListedCapabilityStatement>>()).Returns(
x =>
{
var action = (Action<ListedCapabilityStatement>)x[0];
var statement = new ListedCapabilityStatement();
action(statement);
if (statement.Instantiates != null)
{
foreach (var i in statement.Instantiates)
{
instantiates.Add(i);
}
}

return builder;
});

await _provider.BuildAsync(builder, CancellationToken.None);

Assert.Equal(urls.Count, instantiates.Count);
Assert.All(
urls,
x =>
{
Assert.Contains(x, instantiates);
});
_capabilities.ForEach(x => x.Received(1).TryGetUrls(out Arg.Any<IEnumerable<string>>()));
builder.Received(urls.Any() ? 1 : 0).Apply(Arg.Any<Action<ListedCapabilityStatement>>());
}

private List<string> AddCapabilities(int[] counts)
{
_capabilities.Clear();
var capabilityUrls = new List<string>();
var i = 0;
foreach (var count in counts)
{
var app = $"app{i}";
var urls = Enumerable.Range(0, count).Select(x => $"http://hl7.org/fhir/{app}/CapabilityStatement/{x}");
var cap = Substitute.For<IInstantiateCapability>();
cap.TryGetUrls(out Arg.Any<IEnumerable<string>>()).Returns(
x =>
{
var c = count;
var copy = new List<string>(urls);
if (c > 0)
{
x[0] = copy;
return true;
}

x[0] = null;
return false;
});

_capabilities.Add(cap);
capabilityUrls.AddRange(urls);
i++;
}

return capabilityUrls;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// -------------------------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
// -------------------------------------------------------------------------------------------------

using Microsoft.Extensions.Options;
using Microsoft.Health.Fhir.Core.Configs;
using Microsoft.Health.Fhir.Shared.Core.Features.Conformance;
using Microsoft.Health.Fhir.Tests.Common;
using Microsoft.Health.Test.Utilities;
using Xunit;

namespace Microsoft.Health.Fhir.Shared.Core.UnitTests.Features.Conformance
{
[Trait(Traits.OwningTeam, OwningTeam.Fhir)]
[Trait(Traits.Category, Categories.Conformance)]
public class SmartV2InstantiateCapabilityTests
{
[Theory]
[InlineData(true, false)]
[InlineData(false, true)]
[InlineData(false, false)]
public void GivenSecurityConfiguration_WhenSmartV2IsEnabled_ThenInstantiateCapabilityUrlsAreReturned(
bool enabled,
bool enabledWithout)
{
var securityConfiguration = new SecurityConfiguration
{
Authorization = new AuthorizationConfiguration
{
Enabled = enabled,
EnableSmartWithoutAuth = enabledWithout,
},
};

var instantiateCapability = new SmartV2InstantiateCapability(
Options.Create(securityConfiguration));
if (instantiateCapability.TryGetUrls(out var urls))
{
Assert.True(enabled || enabledWithout);
Assert.NotNull(urls);
Assert.NotEmpty(urls);
}
else
{
Assert.False(enabled || enabledWithout);
Assert.Null(urls);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
<Compile Include="$(MSBuildThisFileDirectory)Features\Conformance\ConformanceProviderExtensionTests.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Features\Conformance\DocRefRequestConverterTests.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Features\Conformance\GetSmartConfigurationHandlerTests.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Features\Conformance\InstantiatesCapabilityProviderTests.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Features\Conformance\SmartV2InstantiateCapabilityTests.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Features\Conformance\TerminologyRequestHandlerTests.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Features\Operations\ConvertData\MockLogger.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Features\Operations\Everything\EverythingOperationContinuationTokenTests.cs" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// -------------------------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
// -------------------------------------------------------------------------------------------------

using System.Collections.Generic;

namespace Microsoft.Health.Fhir.Shared.Core.Features.Conformance
{
public interface IInstantiateCapability
{
bool TryGetUrls(out IEnumerable<string> urls);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// -------------------------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
// -------------------------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using EnsureThat;
using Microsoft.Health.Extensions.DependencyInjection;
using Microsoft.Health.Fhir.Core.Features.Conformance;

namespace Microsoft.Health.Fhir.Shared.Core.Features.Conformance
{
public class InstantiatesCapabilityProvider : IProvideCapability
{
private readonly Func<IScoped<IEnumerable<IInstantiateCapability>>> _instantiateCapabilityDelegate;

public InstantiatesCapabilityProvider(
Func<IScoped<IEnumerable<IInstantiateCapability>>> instantiateCapabilityDelegate)
{
EnsureArg.IsNotNull(instantiateCapabilityDelegate, nameof(instantiateCapabilityDelegate));

_instantiateCapabilityDelegate = instantiateCapabilityDelegate;
}

public Task BuildAsync(
ICapabilityStatementBuilder builder,
CancellationToken cancellationToken)
{
EnsureArg.IsNotNull(builder, nameof(builder));

var instantiateUrls = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
using var instantiates = _instantiateCapabilityDelegate();
foreach (var instantiate in instantiates.Value)
{
if (instantiate.TryGetUrls(out var urls) && urls != null && urls.Any())
{
foreach (var url in urls)
{
instantiateUrls.Add(url);
}
}
}

if (instantiateUrls.Any())
{
builder.Apply(
x =>
{
x.Instantiates = instantiateUrls;
});
}

return Task.CompletedTask;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// -------------------------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
// -------------------------------------------------------------------------------------------------

using System.Collections.Generic;
using EnsureThat;
using Microsoft.Extensions.Options;
using Microsoft.Health.Fhir.Core.Configs;

namespace Microsoft.Health.Fhir.Shared.Core.Features.Conformance
{
public class SmartV2InstantiateCapability : IInstantiateCapability
{
private static readonly string[] Urls =
{
"http://hl7.org/fhir/smart-app-launch/CapabilityStatement/smart-app-state-server",
};

private readonly SecurityConfiguration _securityConfiguration;

public SmartV2InstantiateCapability(IOptions<SecurityConfiguration> securityConfiguration)
{
EnsureArg.IsNotNull(securityConfiguration?.Value, nameof(securityConfiguration));

_securityConfiguration = securityConfiguration.Value;
}

public bool TryGetUrls(out IEnumerable<string> urls)
{
urls = null;
if (_securityConfiguration.Authorization.Enabled
|| _securityConfiguration.Authorization.EnableSmartWithoutAuth)
{
urls = Urls;
return true;
}

return false;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
<Compile Include="$(MSBuildThisFileDirectory)Features\Conformance\DocRefRequestConverter.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Features\Conformance\IDocRefRequestConverter.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Features\Conformance\FirelyTerminologyServiceProxy.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Features\Conformance\IInstantiateCapability.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Features\Conformance\InstantiatesCapabilityProvider.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Features\Conformance\SmartV2InstantiateCapability.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Features\Conformance\TerminologyRequestHandler.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Features\DefaultParserSettings.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Features\Operations\Everything\EverythingOperationParameterNames.cs" />
Expand Down
Loading