Skip to content

Commit 1aac4ad

Browse files
LEGLINK-567: expose the vendor's signing key secret id on the facility response (#1793)
1 parent 642558b commit 1aac4ad

5 files changed

Lines changed: 110 additions & 2 deletions

File tree

DotNet/ServiceTests/IntegrationTests/Census/CensusIntegrationTestFixture.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,4 +190,6 @@ internal class NullTenantApiService : ITenantApiService
190190
public Task<bool> CheckFacilityExists(string facilityId, CancellationToken cancellationToken = default) => Task.FromResult(true);
191191
public Task<FacilityModel> GetFacilityConfig(string facilityId, CancellationToken cancellationToken = default)
192192
=> Task.FromResult(new FacilityModel { FacilityId = facilityId });
193+
public Task<string?> GetVendorSigningKeySecretId(string facilityId, CancellationToken cancellationToken = default)
194+
=> Task.FromResult<string?>(null);
193195
}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
using LantanaGroup.Link.Shared.Application.Models.Tenant;
2+
using LantanaGroup.Link.Tenant.Business.Queries;
3+
using LantanaGroup.Link.Tenant.Data.Entities;
4+
using LantanaGroup.Link.Tenant.Entities;
5+
using LantanaGroup.Link.Tenant.Repository.Context;
6+
using Microsoft.Extensions.DependencyInjection;
7+
using Task = System.Threading.Tasks.Task;
8+
9+
namespace IntegrationTests.Tenant;
10+
11+
/// <summary>
12+
/// Data Acquisition reads the vendor's signing key off the facility response rather than making a
13+
/// second call for the vendor, so the facility projection has to carry it.
14+
/// </summary>
15+
[Collection("IntegrationTests")]
16+
[Trait("Category", "IntegrationTests")]
17+
public class FacilityVendorAuthenticationTests : IDisposable
18+
{
19+
private readonly IServiceScope _scope;
20+
private readonly IFacilityQueries _facilityQueries;
21+
private readonly TenantDbContext _dbContext;
22+
23+
public FacilityVendorAuthenticationTests(TenantIntegrationTestFixture fixture)
24+
{
25+
_scope = fixture.ServiceProvider.CreateScope();
26+
var serviceProvider = _scope.ServiceProvider;
27+
28+
_facilityQueries = serviceProvider.GetRequiredService<IFacilityQueries>();
29+
_dbContext = serviceProvider.GetRequiredService<TenantDbContext>();
30+
}
31+
32+
public void Dispose() => _scope.Dispose();
33+
34+
[Fact]
35+
public async Task GetAsync_CarriesTheVendorsSigningKeySecretId()
36+
{
37+
var facilityId = await CreateFacilityWithVendorAsync(
38+
new VendorAuthenticationSettings { SigningKeySecretId = "epic-signing-key" });
39+
40+
var facility = await _facilityQueries.GetAsync(facilityId, null, CancellationToken.None);
41+
42+
Assert.Equal("epic-signing-key", facility?.Vendor?.Authentication?.SigningKeySecretId);
43+
}
44+
45+
[Fact]
46+
public async Task GetAsync_ReturnsNoSigningKey_WhenTheVendorHasNoneConfigured()
47+
{
48+
var facilityId = await CreateFacilityWithVendorAsync(authentication: null);
49+
50+
var facility = await _facilityQueries.GetAsync(facilityId, null, CancellationToken.None);
51+
52+
Assert.NotNull(facility?.Vendor);
53+
Assert.Null(facility!.Vendor!.Authentication?.SigningKeySecretId);
54+
}
55+
56+
private async Task<string> CreateFacilityWithVendorAsync(VendorAuthenticationSettings? authentication)
57+
{
58+
var vendor = new Vendor
59+
{
60+
Id = Guid.NewGuid(),
61+
Name = $"Vendor-{Guid.NewGuid():N}",
62+
Authentication = authentication
63+
};
64+
var vendorVersion = new VendorVersion
65+
{
66+
Id = Guid.NewGuid(),
67+
VendorId = vendor.Id,
68+
Version = "default"
69+
};
70+
var facility = new Facility
71+
{
72+
Id = Guid.NewGuid(),
73+
FacilityId = $"facility-{Guid.NewGuid():N}",
74+
FacilityName = "Vendor Authentication Test Facility",
75+
TimeZone = "America/Chicago",
76+
VendorVersionId = vendorVersion.Id,
77+
ScheduledReports = new ScheduledReportModel
78+
{
79+
Daily = [],
80+
Weekly = [],
81+
Monthly = []
82+
}
83+
};
84+
85+
await _dbContext.Vendors.AddAsync(vendor);
86+
await _dbContext.VendorVersions.AddAsync(vendorVersion);
87+
await _dbContext.Facilities.AddAsync(facility);
88+
await _dbContext.SaveChangesAsync();
89+
90+
return facility.FacilityId;
91+
}
92+
}

DotNet/Shared/Application/Services/ITenantApiService.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,10 @@ public interface ITenantApiService
66
{
77
Task<bool> CheckFacilityExists(string facilityId, CancellationToken cancellationToken = default);
88
Task<FacilityModel> GetFacilityConfig(string facilityId, CancellationToken cancellationToken = default);
9+
10+
/// <summary>
11+
/// Returns the Key Vault secret name holding the signing key for the facility's vendor, or
12+
/// null when the facility has no vendor or that vendor has no key configured.
13+
/// </summary>
14+
Task<string?> GetVendorSigningKeySecretId(string facilityId, CancellationToken cancellationToken = default);
915
}

DotNet/Shared/Application/Services/TenantApiService.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,13 @@ public async Task<bool> CheckFacilityExists(string facilityId, CancellationToken
8181
throw new Exception($"Error checking if facility ({sanitizedFacilityId}) exists in Tenant Service. Status Code: {response.StatusCode}");
8282
}
8383

84+
public async Task<string?> GetVendorSigningKeySecretId(string facilityId, CancellationToken cancellationToken = default)
85+
{
86+
var facility = await GetFacilityConfig(facilityId, cancellationToken);
87+
88+
return facility?.Vendor?.Authentication?.SigningKeySecretId;
89+
}
90+
8491
public async Task<FacilityModel> GetFacilityConfig(string facilityId, CancellationToken cancellationToken = default)
8592
{
8693
string sanitizedFacilityId = HtmlInputSanitizer.SanitizeAndRemove(facilityId);

DotNet/Tenant/Business/Queries/FacilityQueries.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,9 @@ public async Task<PagedConfigModel<FacilityModel>> PagedSearchAsync(
123123
Vendor = new VendorModel()
124124
{
125125
Id = f.VendorVersion.Vendor!.Id,
126-
Name = f.VendorVersion.Vendor.Name
127-
},
126+
Name = f.VendorVersion.Vendor.Name,
127+
Authentication = f.VendorVersion.Vendor.Authentication
128+
},
128129
ScheduledReports = new TenantScheduledReportConfig
129130
{
130131
Daily = f.ScheduledReports.Daily,

0 commit comments

Comments
 (0)