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

[DI-1339] - ODS API 7.x support. - Add ODS API Connection for Multi-tenant Modes #85

Merged
merged 3 commits into from
Apr 30, 2024
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
138 changes: 136 additions & 2 deletions DataImport.Web.Tests/Features/ApiServers/AddEditApiServerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ public async Task ShouldSuccessfullyAddEditApiServerForOdsApi71WithOdsContext()
Url = StubSwaggerWebClient.ApiServerUrlV711,
Key = SampleString("testKey"),
Secret = SampleString("testSecret"),
Context = SampleString("testContext")
Context = StubSwaggerWebClient.V711Context2002
};

var addApiServerResponse = await Send(new AddApiServer.Command { ViewModel = viewModel });
Expand All @@ -218,7 +218,7 @@ public async Task ShouldSuccessfullyAddEditApiServerForOdsApi71WithOdsContext()
Url = StubSwaggerWebClient.ApiServerUrlV711,
Key = SampleString("testKey"),
Secret = SampleString("testSecret"),
Context = SampleString("testContext")
Context = StubSwaggerWebClient.V711Context2002
};
var editApiServerResponse = await Send(new EditApiServer.Command { ViewModel = viewModel });
editApiServerResponse.AssertToast($"Connection '{viewModel.Name}' was modified.");
Expand All @@ -236,6 +236,140 @@ public async Task ShouldSuccessfullyAddEditApiServerForOdsApi71WithOdsContext()
ods711Resources.ShouldNotBeEmpty();
}

[Test]
public async Task ShouldSuccessfullyAddEditApiServerForOdsApi71WithTenant()
{
// Delete resources for testing.
var resources = Query(d => d.Resources.ToList());
foreach (var resource in resources)
{
Delete(resource);
}

var ods711Resources = Query(d => d.Resources.Where(x => x.ApiVersion.Version == OdsApiV711).ToList());
ods711Resources.ShouldBeEmpty();

var viewModel = new AddEditApiServerViewModel
{
Name = SampleString("ApiServer"),
ApiVersion = OdsApiV711,
Url = StubSwaggerWebClient.ApiServerUrlV711,
Key = SampleString("testKey"),
Secret = SampleString("testSecret"),
Tenant = StubSwaggerWebClient.V711Tenant1
};

var addApiServerResponse = await Send(new AddApiServer.Command { ViewModel = viewModel });
addApiServerResponse.AssertToast($"Connection '{viewModel.Name}' was created.");
addApiServerResponse.ApiServerId.ShouldBeGreaterThan(0);

var addEditViewModel = await Send(new EditApiServer.Query { Id = addApiServerResponse.ApiServerId });
addEditViewModel.Name.ShouldBe(viewModel.Name);
addEditViewModel.Url.ShouldBe(viewModel.Url);
addEditViewModel.ApiVersion.ShouldBe(viewModel.ApiVersion);
addEditViewModel.Tenant.ShouldBe(viewModel.Tenant);
addEditViewModel.Key.ShouldNotBeEmpty();
SensitiveText.IsMasked(addEditViewModel.Key).ShouldBeTrue();
SensitiveText.IsMasked(addEditViewModel.Secret).ShouldBeTrue();

ods711Resources = Query(d => d.Resources.Where(x => x.ApiVersion.Version == OdsApiV711).ToList());
ods711Resources.ShouldNotBeEmpty();

viewModel = new AddEditApiServerViewModel
{
Id = addApiServerResponse.ApiServerId,
Name = SampleString("ApiServer"),
ApiVersion = OdsApiV711,
Url = StubSwaggerWebClient.ApiServerUrlV711,
Key = SampleString("testKey"),
Secret = SampleString("testSecret"),
Tenant = StubSwaggerWebClient.V711Tenant1
};
var editApiServerResponse = await Send(new EditApiServer.Command { ViewModel = viewModel });
editApiServerResponse.AssertToast($"Connection '{viewModel.Name}' was modified.");
editApiServerResponse.ApiServerId.ShouldBeGreaterThan(0);

var editApiServerViewModel = await Send(new EditApiServer.Query { Id = addApiServerResponse.ApiServerId });
editApiServerViewModel.Name.ShouldBe(viewModel.Name);
editApiServerViewModel.Url.ShouldBe(viewModel.Url);
editApiServerViewModel.ApiVersion.ShouldBe(viewModel.ApiVersion);
editApiServerViewModel.Tenant.ShouldBe(viewModel.Tenant);
SensitiveText.IsMasked(editApiServerViewModel.Key).ShouldBeTrue();
SensitiveText.IsMasked(editApiServerViewModel.Secret).ShouldBeTrue();

ods711Resources = Query(d => d.Resources.Where(x => x.ApiVersion.Version == OdsApiV711).ToList());
ods711Resources.ShouldNotBeEmpty();
}

[Test]
public async Task ShouldSuccessfullyAddEditApiServerForOdsApi71WithContextAndTenant()
{
// Delete resources for testing.
var resources = Query(d => d.Resources.ToList());
foreach (var resource in resources)
{
Delete(resource);
}

var ods711Resources = Query(d => d.Resources.Where(x => x.ApiVersion.Version == OdsApiV711).ToList());
ods711Resources.ShouldBeEmpty();

var viewModel = new AddEditApiServerViewModel
{
Name = SampleString("ApiServer"),
ApiVersion = OdsApiV711,
Url = StubSwaggerWebClient.ApiServerUrlV711,
Key = SampleString("testKey"),
Secret = SampleString("testSecret"),
Tenant = StubSwaggerWebClient.V711Tenant1,
Context = StubSwaggerWebClient.V711Context2002
};

var addApiServerResponse = await Send(new AddApiServer.Command { ViewModel = viewModel });
addApiServerResponse.AssertToast($"Connection '{viewModel.Name}' was created.");
addApiServerResponse.ApiServerId.ShouldBeGreaterThan(0);

var addEditViewModel = await Send(new EditApiServer.Query { Id = addApiServerResponse.ApiServerId });
addEditViewModel.Name.ShouldBe(viewModel.Name);
addEditViewModel.Url.ShouldBe(viewModel.Url);
addEditViewModel.ApiVersion.ShouldBe(viewModel.ApiVersion);
addEditViewModel.Tenant.ShouldBe(viewModel.Tenant);
addEditViewModel.Context.ShouldBe(viewModel.Context);
addEditViewModel.Key.ShouldNotBeEmpty();
SensitiveText.IsMasked(addEditViewModel.Key).ShouldBeTrue();
SensitiveText.IsMasked(addEditViewModel.Secret).ShouldBeTrue();

ods711Resources = Query(d => d.Resources.Where(x => x.ApiVersion.Version == OdsApiV711).ToList());
ods711Resources.ShouldNotBeEmpty();

viewModel = new AddEditApiServerViewModel
{
Id = addApiServerResponse.ApiServerId,
Name = SampleString("ApiServer"),
ApiVersion = OdsApiV711,
Url = StubSwaggerWebClient.ApiServerUrlV711,
Key = SampleString("testKey"),
Secret = SampleString("testSecret"),
Tenant = StubSwaggerWebClient.V711Tenant1,
Context = StubSwaggerWebClient.V711Context2002
};
var editApiServerResponse = await Send(new EditApiServer.Command { ViewModel = viewModel });
editApiServerResponse.AssertToast($"Connection '{viewModel.Name}' was modified.");
editApiServerResponse.ApiServerId.ShouldBeGreaterThan(0);

var editApiServerViewModel = await Send(new EditApiServer.Query { Id = addApiServerResponse.ApiServerId });
editApiServerViewModel.Name.ShouldBe(viewModel.Name);
editApiServerViewModel.Url.ShouldBe(viewModel.Url);
editApiServerViewModel.ApiVersion.ShouldBe(viewModel.ApiVersion);
editApiServerViewModel.Tenant.ShouldBe(viewModel.Tenant);
editApiServerViewModel.Context.ShouldBe(viewModel.Context);
SensitiveText.IsMasked(editApiServerViewModel.Key).ShouldBeTrue();
SensitiveText.IsMasked(editApiServerViewModel.Secret).ShouldBeTrue();

ods711Resources = Query(d => d.Resources.Where(x => x.ApiVersion.Version == OdsApiV711).ToList());
ods711Resources.ShouldNotBeEmpty();
}

[Test]
public async Task ShouldFullyMaskKeyAndSecret()
{
Expand Down
42 changes: 40 additions & 2 deletions DataImport.Web.Tests/StubSwaggerWebClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,16 @@ public class StubSwaggerWebClient : ISwaggerWebClient
{
private const string OdsDomainV25 = "http://test-ods-v2.5.0.1.example.com";
private const string OdsDomainV311 = "http://test-ods-v3.1.1.example.com";
private const string OdsDomainV711 = "http://test-ods-v7.1.1.example.com";

public const string V711Context2002 = "2022";
public const string V711Tenant1 = "tenant1";

public const string ApiServerUrlV25 = OdsDomainV25 + "/api/v2.0/2019";
public const string ApiServerUrlV311 = OdsDomainV311 + "/data/v3";
public const string ApiServerUrlV711 = OdsDomainV311 + "/data/v3";
public const string ApiServerUrlV711WithOdsContext = OdsDomainV311 + "/2022/data/v3";
public const string ApiServerUrlV711 = OdsDomainV711 + "/data/v3";
public const string ApiServerUrlV711WithOdsContext = $"{OdsDomainV711}/{V711Context2002}/data/v3";
public const string ApiServerUrlV711WithTenant = $"{OdsDomainV711}/{V711Tenant1}/data/v3";

public async Task<string> DownloadString(string url)
{
Expand All @@ -30,6 +35,18 @@ public async Task<string> DownloadString(string url)
const string SwaggerResourcesV311 = OdsDomainV311 + "/metadata/data/v3/resources/swagger.json";
const string SwaggerDescriptorsV311 = OdsDomainV311 + "/metadata/data/v3/descriptors/swagger.json";

const string SwaggerResourcesV711 = OdsDomainV711 + "/metadata/data/v3/resources/swagger.json";
const string SwaggerDescriptorsV711 = OdsDomainV711 + "/metadata/data/v3/descriptors/swagger.json";

const string SwaggerResourcesV711WithOdsContext = $"{OdsDomainV711}/metadata/{V711Context2002}/data/v3/resources/swagger.json";
const string SwaggerDescriptorsV711WithOdsContext = $"{OdsDomainV711}/metadata/{V711Context2002}/data/v3/descriptors/swagger.json";

const string SwaggerResourcesV711WithTenant = $"{OdsDomainV711}/metadata/{V711Tenant1}/data/v3/resources/swagger.json";
const string SwaggerDescriptorsV711WithTenant = $"{OdsDomainV711}/metadata/{V711Tenant1}/data/v3/descriptors/swagger.json";

const string SwaggerResourcesV711WithTenantAndContext = $"{OdsDomainV711}/metadata/{V711Tenant1}/{V711Context2002}/data/v3/resources/swagger.json";
const string SwaggerDescriptorsV711WithTenantAndContext = $"{OdsDomainV711}/metadata/{V711Tenant1}/{V711Context2002}/data/v3/descriptors/swagger.json";

if (url == SwaggerResourcesV25)
return await SampleSwaggerResponseV25("Swagger-Resources-API-Docs.json");

Expand Down Expand Up @@ -59,6 +76,21 @@ public async Task<string> DownloadString(string url)
if (url == OdsDomainV311)
return await SampleSwaggerResponseV311("Swagger-Base-API-Response.json");

if (url == SwaggerResourcesV711
|| url == SwaggerResourcesV711WithOdsContext
|| url == SwaggerResourcesV711WithTenant
|| url == SwaggerResourcesV711WithTenantAndContext)
return await SampleSwaggerResponseV711("Swagger-Resources-API-Docs.json");

if (url == SwaggerDescriptorsV711
|| url == SwaggerDescriptorsV711WithOdsContext
|| url == SwaggerDescriptorsV711WithTenant
|| url == SwaggerDescriptorsV711WithTenantAndContext)
return await SampleSwaggerResponseV711("Swagger-Descriptors-API-Docs.json");

if (url == OdsDomainV711)
return await SampleSwaggerResponseV711("Swagger-Base-API-Response.json");

throw new Exception(GetType().Name + " cannot simulate a request to url " + url);
}

Expand All @@ -75,5 +107,11 @@ private static Task<string> SampleSwaggerResponseV311(string filename)
TestContext.CurrentContext.TestDirectory,
"SampleMetadata-v3.1.1",
filename)));
private static Task<string> SampleSwaggerResponseV711(string filename)
=> Task.FromResult(File.ReadAllText(
Path.Combine(
TestContext.CurrentContext.TestDirectory,
"SampleMetadata-v7.1.1",
filename)));
}
}
1 change: 0 additions & 1 deletion DataImport.Web/Features/ApiServers/AddEditApiServer.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,6 @@ See the LICENSE and NOTICES files in the project root for more information.
disableSaveButton(true);
});


function handleApiVersionResponse(apiVersion) {
var apiUrl = $("#Url").val();
if (!apiVersion && apiUrl)
Expand Down
23 changes: 11 additions & 12 deletions DataImport.Web/Services/Swagger/SwaggerMetadataFetcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public async Task<string> GetTokenUrl(string apiUrl, string apiVersion, string t
{
var (swaggerDocument, handler) = await GetSwaggerDocument(apiUrl, apiVersion, tenant, context, ApiSection.Resources);

if (!string.IsNullOrEmpty(apiVersion) && apiVersion == "7.1" && !string.IsNullOrEmpty(context))
if (!string.IsNullOrEmpty(apiVersion) && apiVersion.StartsWith("7."))
{
return handler.GetTokenUrl(apiUrl, apiVersion, tenant, context);
}
Expand Down Expand Up @@ -195,27 +195,26 @@ protected async Task<string> GetSwaggerBaseDocumentUrl(string apiUrl, string api
else if (apiVersion.IsOdsV3())
{
var baseUrl = Common.Helpers.UrlUtility.RemoveAfterLastInstanceOf(apiUrl.Trim(), "/data/");
var year = await GetYearSpecificYear(apiUrl);

var instanceYearSpecificInstance = await GetInstanceYearSpecificInstance(apiUrl);
var instanceYearSpecificYear = await GetInstanceYearSpecificYear(apiUrl);

string path;

if (apiVersion == "7.1" && !string.IsNullOrEmpty(context))
if (!string.IsNullOrEmpty(tenant) && string.IsNullOrEmpty(context))
{
path = $"{context}/data/v3";
// MultiTenant Environment
path = $"{tenant}/data/v3";
}
else if (year is not null)
else if (!string.IsNullOrEmpty(context) && string.IsNullOrEmpty(tenant))
{
path = $"data/v3/{year}";
// SingleTenant with ODS Context Routes Environment
path = $"{context}/data/v3";
}
else if (instanceYearSpecificInstance is not null && instanceYearSpecificYear is not null)
else if (!string.IsNullOrEmpty(context) && !string.IsNullOrEmpty(tenant))
{
path = $"data/v3/{instanceYearSpecificInstance}/{instanceYearSpecificYear}";
// MultiTenant with ODS Context Routes Environments
path = $"{tenant}/{context}/data/v3";
}
else
{
// SingleTenant Environment
path = "data/v3";
}

Expand Down