Skip to content

Commit cb2231f

Browse files
authored
Refactor configuration with v2 and add backward compatibility (#93)
1 parent 3b736da commit cb2231f

132 files changed

Lines changed: 5002 additions & 2100 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

example/docker-compose.yml

Lines changed: 50 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -30,43 +30,56 @@ services:
3030
condition: service_started
3131
restart: always
3232
environment:
33-
- AasEnvironment__DataEngineRepositoryBaseUrl=http://localhost:8080
34-
- AasEnvironment__AasEnvironmentRepositoryBaseUrl=http://template-repository:8081
35-
- AasEnvironment__AasRegistryBaseUrl=http://aas-template-registry:8080
36-
- AasEnvironment__SubModelRegistryBaseUrl=http://sm-template-registry:8080
37-
- AasEnvironment__CustomerDomainUrl=https://mm-software.com
38-
- TemplateMappingRules__SubmodelTemplateMappings__0__templateId=https://admin-shell.io/ZVEI/TechnicalData/Submodel/1/2
39-
- TemplateMappingRules__SubmodelTemplateMappings__0__pattern__0=TechnicalData
40-
- TemplateMappingRules__SubmodelTemplateMappings__1__templateId=https://admin-shell.io/idta/SubmodelTemplate/DigitalNameplate/3/0
41-
- TemplateMappingRules__SubmodelTemplateMappings__1__pattern__0=Nameplate
42-
- TemplateMappingRules__SubmodelTemplateMappings__2__templateId=https://admin-shell.io/idta/SubmodelTemplate/ContactInformation/1/0
43-
- TemplateMappingRules__SubmodelTemplateMappings__2__pattern__0=ContactInformation
44-
- TemplateMappingRules__SubmodelTemplateMappings__3__templateId=https://admin-shell.io/idta/SubmodelTemplate/CarbonFootprint/1/0
45-
- TemplateMappingRules__SubmodelTemplateMappings__3__pattern__0=CarbonFootprint
46-
- TemplateMappingRules__SubmodelTemplateMappings__4__templateId=https://admin-shell.io/idta/SubmodelTemplate/HandoverDocumentation/2/0
47-
- TemplateMappingRules__SubmodelTemplateMappings__4__pattern__0=HandoverDocumentation
48-
- TemplateMappingRules__ShellTemplateMappings__0__templateId=https://mm-software.com/aas/aasTemplate
49-
- TemplateMappingRules__ShellTemplateMappings__0__pattern__0=
50-
- TemplateMappingRules__AasIdExtractionRules__0__pattern=Regex
51-
- TemplateMappingRules__AasIdExtractionRules__0__index=6
52-
- TemplateMappingRules__AasIdExtractionRules__0__separator=/
53-
- PluginConfig__Plugins__0__PluginName=Plugin1
54-
- PluginConfig__Plugins__0__PluginUrl=http://dpp-plugin:8080
55-
- HeaderForwarding__HeaderMappings__TemplateRepository__0__Source=Authorization
56-
- HeaderForwarding__HeaderMappings__TemplateRepository__0__Target=Authorization
57-
- HeaderForwarding__HeaderMappings__TemplateRepository__0__Required=false
58-
- HeaderForwarding__HeaderMappings__TemplateRepository__1__Source=X-User-Roles
59-
- HeaderForwarding__HeaderMappings__TemplateRepository__1__Target=X-Template-Access-Roles
60-
- HeaderForwarding__HeaderMappings__TemplateRepository__1__Required=false
61-
- HeaderForwarding__HeaderMappings__TemplateRegistry__0__Source=Authorization
62-
- HeaderForwarding__HeaderMappings__TemplateRegistry__0__Target=Authorization
63-
- HeaderForwarding__HeaderMappings__TemplateRegistry__0__Required=false
64-
- HeaderForwarding__HeaderMappings__Plugins__Plugin1__0__Source=Authorization
65-
- HeaderForwarding__HeaderMappings__Plugins__Plugin1__0__Target=X-Auth-Token
66-
- HeaderForwarding__HeaderMappings__Plugins__Plugin1__0__Required=false
67-
- HeaderForwarding__HeaderMappings__Plugins__Plugin1__1__Source=X-Organization-Id
68-
- HeaderForwarding__HeaderMappings__Plugins__Plugin1__1__Target=X-Tenant-Context
69-
- HeaderForwarding__HeaderMappings__Plugins__Plugin1__1__Required=false
33+
- General__DataEngineRepositoryBaseUrl=http://localhost:8080
34+
- General__CustomerDomainUrl=https://mm-software.com
35+
- Plugins__Instances__0__Name=RelationalDatabasePlugin
36+
- Plugins__Instances__0__baseUrl=http://dpp-plugin:8080
37+
- Plugins__Instances__0__headerMappings__0__source=Authorization
38+
- Plugins__Instances__0__headerMappings__0__target=X-Auth-Token
39+
- Plugins__Instances__0__headerMappings__0__required=false
40+
- Plugins__Instances__0__headerMappings__1__source=X-Organization-Id
41+
- Plugins__Instances__0__headerMappings__1__target=X-Tenant-Context
42+
- Plugins__Instances__0__headerMappings__1__required=false
43+
- TemplateManagement__TemplateMappingRules__SubmodelTemplateMappings__0__templateId=https://admin-shell.io/ZVEI/TechnicalData/Submodel/1/2
44+
- TemplateManagement__TemplateMappingRules__SubmodelTemplateMappings__0__pattern__0=TechnicalData
45+
- TemplateManagement__TemplateMappingRules__SubmodelTemplateMappings__1__templateId=https://admin-shell.io/idta/SubmodelTemplate/DigitalNameplate/3/0
46+
- TemplateManagement__TemplateMappingRules__SubmodelTemplateMappings__1__pattern__0=Nameplate
47+
- TemplateManagement__TemplateMappingRules__SubmodelTemplateMappings__2__templateId=https://admin-shell.io/idta/SubmodelTemplate/ContactInformation/1/0
48+
- TemplateManagement__TemplateMappingRules__SubmodelTemplateMappings__2__pattern__0=ContactInformation
49+
- TemplateManagement__TemplateMappingRules__SubmodelTemplateMappings__3__templateId=https://admin-shell.io/idta/SubmodelTemplate/CarbonFootprint/1/0
50+
- TemplateManagement__TemplateMappingRules__SubmodelTemplateMappings__3__pattern__0=CarbonFootprint
51+
- TemplateManagement__TemplateMappingRules__SubmodelTemplateMappings__4__templateId=https://admin-shell.io/idta/SubmodelTemplate/HandoverDocumentation/2/0
52+
- TemplateManagement__TemplateMappingRules__SubmodelTemplateMappings__4__pattern__0=HandoverDocumentation
53+
- TemplateManagement__TemplateMappingRules__ShellTemplateMappings__0__templateId=https://mm-software.com/aas/aasTemplate
54+
- TemplateManagement__TemplateMappingRules__ShellTemplateMappings__0__pattern__0=
55+
- TemplateManagement__TemplateMappingRules__AasIdExtractionRules__0__Pattern=Regex
56+
- TemplateManagement__TemplateMappingRules__AasIdExtractionRules__0__Index=6
57+
- TemplateManagement__TemplateMappingRules__AasIdExtractionRules__0__Separator=/
58+
- TemplateManagement__AasTemplateRepository__Name=AasTemplateRepository
59+
- TemplateManagement__AasTemplateRepository__baseUrl=http://template-repository:8081
60+
- TemplateManagement__AasTemplateRepository__headerMappings__0__source=Authorization
61+
- TemplateManagement__AasTemplateRepository__headerMappings__0__target=Authorization
62+
- TemplateManagement__AasTemplateRepository__headerMappings__0__required=false
63+
- TemplateManagement__SubmodelTemplateRepository__Name=SubmodelTemplateRepository
64+
- TemplateManagement__SubmodelTemplateRepository__baseUrl=http://template-repository:8081
65+
- TemplateManagement__SubmodelTemplateRepository__headerMappings__0__source=Authorization
66+
- TemplateManagement__SubmodelTemplateRepository__headerMappings__0__target=Authorization
67+
- TemplateManagement__SubmodelTemplateRepository__headerMappings__0__required=false
68+
- TemplateManagement__ConceptDescriptionTemplateRepository__Name=ConceptDescriptionTemplateRepository
69+
- TemplateManagement__ConceptDescriptionTemplateRepository__baseUrl=http://template-repository:8081
70+
- TemplateManagement__ConceptDescriptionTemplateRepository__headerMappings__0__source=Authorization
71+
- TemplateManagement__ConceptDescriptionTemplateRepository__headerMappings__0__target=Authorization
72+
- TemplateManagement__ConceptDescriptionTemplateRepository__headerMappings__0__required=false
73+
- TemplateManagement__AasTemplateRegistry__Name=AasTemplateRegistry
74+
- TemplateManagement__AasTemplateRegistry__baseUrl=http://aas-template-registry:8080
75+
- TemplateManagement__AasTemplateRegistry__headerMappings__0__source=Authorization
76+
- TemplateManagement__AasTemplateRegistry__headerMappings__0__target=Authorization
77+
- TemplateManagement__AasTemplateRegistry__headerMappings__0__required=false
78+
- TemplateManagement__SubmodelTemplateRegistry__Name=SubmodelTemplateRegistry
79+
- TemplateManagement__SubmodelTemplateRegistry__baseUrl=http://sm-template-registry:8080
80+
- TemplateManagement__SubmodelTemplateRegistry__headerMappings__0__source=Authorization
81+
- TemplateManagement__SubmodelTemplateRegistry__headerMappings__0__target=Authorization
82+
- TemplateManagement__SubmodelTemplateRegistry__headerMappings__0__required=false
7083
networks:
7184
- twinengine-network
7285

source/AAS.TwinEngine.DataEngine.ModuleTests/AAS.TwinEngine.DataEngine.ModuleTests.csproj

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,9 @@
2626
<Using Include="Xunit" />
2727
</ItemGroup>
2828

29+
<ItemGroup>
30+
<Content Include="TestData\v1-config\appsettings.json" CopyToOutputDirectory="PreserveNewest" />
31+
<Content Include="TestData\v2-config\appsettings.json" CopyToOutputDirectory="PreserveNewest" />
32+
</ItemGroup>
33+
2934
</Project>

source/AAS.TwinEngine.DataEngine.ModuleTests/Api/Services/AasRegistry/ShellDescriptorControllerTests.cs

Lines changed: 47 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System.Net;
1+
using System.Net;
22
using System.Net.Http.Json;
33
using System.Text;
44
using System.Text.Json.Nodes;
@@ -8,45 +8,51 @@
88
using AAS.TwinEngine.DataEngine.ApplicationLogic.Services.Plugin;
99
using AAS.TwinEngine.DataEngine.ApplicationLogic.Services.Plugin.Providers;
1010
using AAS.TwinEngine.DataEngine.Infrastructure.Http.Clients;
11-
using AAS.TwinEngine.DataEngine.Infrastructure.Providers.PluginDataProvider.Config;
11+
using AAS.TwinEngine.DataEngine.ModuleTests.Common;
1212

13-
using Microsoft.AspNetCore.Mvc.Testing;
1413
using Microsoft.AspNetCore.WebUtilities;
1514
using Microsoft.Extensions.DependencyInjection;
1615

1716
using NSubstitute;
1817
using NSubstitute.ExceptionExtensions;
1918

19+
using AAS.TwinEngine.DataEngine.ServiceConfiguration.Config;
20+
2021
namespace AAS.TwinEngine.DataEngine.ModuleTests.Api.Services.AasRegistry;
2122

22-
public class ShellDescriptorControllerTests : IClassFixture<WebApplicationFactory<Program>>
23+
public abstract class ShellDescriptorControllerTestsBase : IDisposable
2324
{
25+
private readonly ConfigTestFactory _factory;
2426
private readonly ITemplateProvider _mockTemplateProvider;
2527
private readonly HttpClient _client;
2628
private readonly ICreateClient _httpClientFactory;
2729

28-
public ShellDescriptorControllerTests(WebApplicationFactory<Program> factory)
30+
protected ShellDescriptorControllerTestsBase(string configDir)
2931
{
3032
_mockTemplateProvider = Substitute.For<ITemplateProvider>();
3133
var mockPluginManifestProvider = Substitute.For<IPluginManifestProvider>();
3234
var mockPluginManifestConflictHandler = Substitute.For<IPluginManifestConflictHandler>();
3335
_httpClientFactory = Substitute.For<ICreateClient>();
3436

35-
var factory1 = factory.WithWebHostBuilder(builder =>
37+
_factory = new ConfigTestFactory(configDir, services =>
3638
{
37-
_ = builder.ConfigureServices(services =>
38-
{
39-
_ = services.AddSingleton(_httpClientFactory);
40-
_ = services.AddSingleton(mockPluginManifestProvider);
41-
_ = services.AddSingleton(_mockTemplateProvider);
42-
_ = services.AddSingleton(mockPluginManifestConflictHandler);
43-
});
39+
_ = services.AddSingleton(_httpClientFactory);
40+
_ = services.AddSingleton(mockPluginManifestProvider);
41+
_ = services.AddSingleton(_mockTemplateProvider);
42+
_ = services.AddSingleton(mockPluginManifestConflictHandler);
4443
});
4544

46-
_client = factory1.CreateClient();
45+
_client = _factory.CreateClient();
4746
_ = mockPluginManifestConflictHandler.Manifests.Returns(TestData.CreatePluginManifests());
4847
}
4948

49+
public void Dispose()
50+
{
51+
_client.Dispose();
52+
_factory.Dispose();
53+
GC.SuppressFinalize(this);
54+
}
55+
5056
[Fact]
5157
public async Task GetAllShellDescriptorsAsync_ReturnsOkAsync()
5258
{
@@ -70,11 +76,11 @@ public async Task GetAllShellDescriptorsAsync_ReturnsOkAsync()
7076
using var httpClientPlugin2 = new HttpClient(messageHandlerPlugin2);
7177
httpClientPlugin2.BaseAddress = new Uri("https://testendpoint2.com");
7278

73-
const string HttpClientNamePlugin1 = $"{PluginConfig.HttpClientNamePrefix}TestPlugin1";
74-
_httpClientFactory.CreateClient(HttpClientNamePlugin1).Returns(httpClientPlugin1);
79+
const string HttpClientNamePlugin1 = $"{HttpClientNames.PluginDataProviderPrefix}TestPlugin1";
80+
_ = _httpClientFactory.CreateClient(HttpClientNamePlugin1).Returns(httpClientPlugin1);
7581

76-
const string HttpClientNamePlugin2 = $"{PluginConfig.HttpClientNamePrefix}TestPlugin2";
77-
_httpClientFactory.CreateClient(HttpClientNamePlugin2).Returns(httpClientPlugin2);
82+
const string HttpClientNamePlugin2 = $"{HttpClientNames.PluginDataProviderPrefix}TestPlugin2";
83+
_ = _httpClientFactory.CreateClient(HttpClientNamePlugin2).Returns(httpClientPlugin2);
7884

7985
_ = _mockTemplateProvider.GetShellDescriptorsTemplateAsync(Arg.Any<CancellationToken>()).Returns(template);
8086

@@ -154,11 +160,11 @@ public async Task GetShellDescriptorByIdAsync_ReturnsOkAsync()
154160
using var httpClient2 = new HttpClient(messageHandler2);
155161
httpClient2.BaseAddress = new Uri("https://testendpoint2.com");
156162

157-
const string HttpClientName1 = $"{PluginConfig.HttpClientNamePrefix}TestPlugin1";
158-
_httpClientFactory.CreateClient(HttpClientName1).Returns(httpClient1);
163+
const string HttpClientName1 = $"{HttpClientNames.PluginDataProviderPrefix}TestPlugin1";
164+
_ = _httpClientFactory.CreateClient(HttpClientName1).Returns(httpClient1);
159165

160-
const string HttpClientName2 = $"{PluginConfig.HttpClientNamePrefix}TestPlugin2";
161-
_httpClientFactory.CreateClient(HttpClientName2).Returns(httpClient2);
166+
const string HttpClientName2 = $"{HttpClientNames.PluginDataProviderPrefix}TestPlugin2";
167+
_ = _httpClientFactory.CreateClient(HttpClientName2).Returns(httpClient2);
162168

163169
_ = _mockTemplateProvider.GetShellDescriptorsTemplateAsync(Arg.Any<CancellationToken>()).Returns(template);
164170

@@ -213,7 +219,7 @@ public async Task GetShellDescriptorByIdAsync_WhenIdentifierIsInValid_Returns400
213219
[Theory]
214220
[InlineData("not-valid-base64!!!")]
215221
[InlineData("invalid!!base64")]
216-
public async Task GetShellDescriptorById_InvalidBase64_Returns400BadRequest(string invalidBase64)
222+
public async Task GetShellDescriptorById_InvalidBase64_Returns400BadRequestAsync(string invalidBase64)
217223
{
218224
var response = await _client.GetAsync($"/shell-descriptors/{invalidBase64}");
219225

@@ -227,7 +233,7 @@ public async Task GetShellDescriptorById_InvalidBase64_Returns400BadRequest(stri
227233
[InlineData("<script>alert('xss')</script>")]
228234
[InlineData("<img onerror=alert('xss')>")]
229235
[InlineData("<svg/onload=alert('xss')>")]
230-
public async Task GetShellDescriptorById_XssInDecodedId_Returns400BadRequest(string maliciousContent)
236+
public async Task GetShellDescriptorById_XssInDecodedId_Returns400BadRequestAsync(string maliciousContent)
231237
{
232238
var encoded = EncodeBase64Url(maliciousContent);
233239

@@ -243,7 +249,7 @@ public async Task GetShellDescriptorById_XssInDecodedId_Returns400BadRequest(str
243249
[InlineData("'; DROP TABLE shells--")]
244250
[InlineData("1 UNION SELECT * FROM descriptors")]
245251
[InlineData("admin'; DELETE FROM shells--")]
246-
public async Task GetShellDescriptorById_SqlInjectionInDecodedId_Returns400BadRequest(string maliciousContent)
252+
public async Task GetShellDescriptorById_SqlInjectionInDecodedId_Returns400BadRequestAsync(string maliciousContent)
247253
{
248254
var encoded = EncodeBase64Url(maliciousContent);
249255

@@ -259,7 +265,7 @@ public async Task GetShellDescriptorById_SqlInjectionInDecodedId_Returns400BadRe
259265
[InlineData("..\\..\\..\\windows\\system32")]
260266
[InlineData("%2e%2e/config")]
261267
[InlineData("..%2fconfig")]
262-
public async Task GetShellDescriptorById_PathTraversalInDecodedId_Returns400BadRequest(string maliciousContent)
268+
public async Task GetShellDescriptorById_PathTraversalInDecodedId_Returns400BadRequestAsync(string maliciousContent)
263269
{
264270
var encoded = EncodeBase64Url(maliciousContent);
265271

@@ -275,7 +281,7 @@ public async Task GetShellDescriptorById_PathTraversalInDecodedId_Returns400BadR
275281
[InlineData("data:text/html,<script>")]
276282
[InlineData("vbscript:msgbox('xss')")]
277283
[InlineData("file:///etc/passwd")]
278-
public async Task GetShellDescriptorById_DangerousProtocolInDecodedId_Returns400BadRequest(string maliciousContent)
284+
public async Task GetShellDescriptorById_DangerousProtocolInDecodedId_Returns400BadRequestAsync(string maliciousContent)
279285
{
280286
var encoded = EncodeBase64Url(maliciousContent);
281287

@@ -288,7 +294,7 @@ public async Task GetShellDescriptorById_DangerousProtocolInDecodedId_Returns400
288294

289295
[Theory]
290296
[InlineData("test\0value")]
291-
public async Task GetShellDescriptorById_NullByteInDecodedId_Returns400BadRequest(string contentWithNullByte)
297+
public async Task GetShellDescriptorById_NullByteInDecodedId_Returns400BadRequestAsync(string contentWithNullByte)
292298
{
293299
var encoded = EncodeBase64Url(contentWithNullByte);
294300

@@ -300,7 +306,7 @@ public async Task GetShellDescriptorById_NullByteInDecodedId_Returns400BadReques
300306
}
301307

302308
[Fact]
303-
public async Task GetShellDescriptorById_IdentifierExceedsMaxLength_Returns400BadRequest()
309+
public async Task GetShellDescriptorById_IdentifierExceedsMaxLength_Returns400BadRequestAsync()
304310
{
305311
var longIdentifier = "https://example.com/" + new string('a', 2050);
306312
var encoded = EncodeBase64Url(longIdentifier);
@@ -315,13 +321,13 @@ public async Task GetShellDescriptorById_IdentifierExceedsMaxLength_Returns400Ba
315321
[InlineData("https://admin-shell.io/idta/aas/ContactInformation/1/0")]
316322
[InlineData("urn:uuid:123e4567-e89b-12d3-a456-426614174000")]
317323
[InlineData("https://mm-software.com/submodel/test/Nameplate")]
318-
public async Task GetShellDescriptorById_ValidAasIdentifiers_DoesNotReturn400(string validIdentifier)
324+
public async Task GetShellDescriptorById_ValidAasIdentifiers_DoesNotReturn400Async(string validIdentifier)
319325
{
320326
var encoded = EncodeBase64Url(validIdentifier);
321327
_ = _mockTemplateProvider.GetShellDescriptorsTemplateAsync(Arg.Any<CancellationToken>())
322328
.Throws(new ResourceNotFoundException());
323329

324-
var response = await _client.GetAsync($"/shell-descriptors/{encoded}").ConfigureAwait(false);
330+
var response = await _client.GetAsync($"/shell-descriptors/{encoded}");
325331

326332
Assert.NotEqual(HttpStatusCode.BadRequest, response.StatusCode);
327333
}
@@ -340,6 +346,16 @@ private static string EncodeBase64Url(string plainText)
340346
}
341347
}
342348

349+
public class ShellDescriptorControllerTests_V1Config : ShellDescriptorControllerTestsBase
350+
{
351+
public ShellDescriptorControllerTests_V1Config() : base("v1-config") { }
352+
}
353+
354+
public class ShellDescriptorControllerTests_V2Config : ShellDescriptorControllerTestsBase
355+
{
356+
public ShellDescriptorControllerTests_V2Config() : base("v2-config") { }
357+
}
358+
343359
public class FakeHttpMessageHandler(Func<HttpRequestMessage, CancellationToken, Task<HttpResponseMessage>> send) : HttpMessageHandler
344360
{
345361
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)

0 commit comments

Comments
 (0)