diff --git a/src/externalsystems/BpnDidResolver.Library/BpnDidResolverService.cs b/src/externalsystems/BpnDidResolver.Library/BpnDidResolverService.cs
index 87b591b7a5..86de301c17 100644
--- a/src/externalsystems/BpnDidResolver.Library/BpnDidResolverService.cs
+++ b/src/externalsystems/BpnDidResolver.Library/BpnDidResolverService.cs
@@ -17,21 +17,43 @@
* SPDX-License-Identifier: Apache-2.0
********************************************************************************/
+using Microsoft.Extensions.Options;
+using Org.Eclipse.TractusX.Portal.Backend.BpnDidResolver.Library.DependencyInjection;
using Org.Eclipse.TractusX.Portal.Backend.Dim.Library.Models;
+using Org.Eclipse.TractusX.Portal.Backend.Framework.HttpClientExtensions;
+using Org.Eclipse.TractusX.Portal.Backend.Framework.Token;
using System.Net.Http.Json;
using System.Text.Json;
namespace Org.Eclipse.TractusX.Portal.Backend.BpnDidResolver.Library;
-public class BpnDidResolverService(IHttpClientFactory httpClientFactory) : IBpnDidResolverService
+public class BpnDidResolverService : IBpnDidResolverService
{
+ private readonly ITokenService _tokenService;
+ private readonly BpnDidResolverSettings _settings;
private static readonly JsonSerializerOptions Options = new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
+ ///
+ /// Creates a new instance of
+ ///
+ ///
+ ///
+ public BpnDidResolverService(ITokenService tokenService, IOptions options)
+ {
+ _tokenService = tokenService;
+ _settings = options.Value;
+ }
+
public async Task TransmitDidAndBpn(string did, string bpn, CancellationToken cancellationToken)
{
- using var httpClient = httpClientFactory.CreateClient(nameof(BpnDidResolverService));
+ using var httpClient = await _tokenService.GetAuthorizedClient(_settings, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None);
var data = new BpnMappingData(bpn, did);
- var result = await httpClient.PostAsJsonAsync("api/management/bpn-directory", data, Options, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None);
+
+ async ValueTask<(bool, string?)> CreateErrorMessage(HttpResponseMessage errorResponse) =>
+ (false, (await errorResponse.Content.ReadAsStringAsync(cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None)));
+
+ var result = await httpClient.PostAsJsonAsync("api/management/bpn-directory", data, Options, cancellationToken)
+ .CatchingIntoServiceExceptionFor("transmit-did-bpn", HttpAsyncResponseMessageExtension.RecoverOptions.INFRASTRUCTURE, CreateErrorMessage).ConfigureAwait(false);
return result.IsSuccessStatusCode;
}
}
diff --git a/src/externalsystems/BpnDidResolver.Library/DependencyInjection/BpnDidResolverServiceCollectionExtension.cs b/src/externalsystems/BpnDidResolver.Library/DependencyInjection/BpnDidResolverServiceCollectionExtension.cs
index c1370f21e2..e540a337f4 100644
--- a/src/externalsystems/BpnDidResolver.Library/DependencyInjection/BpnDidResolverServiceCollectionExtension.cs
+++ b/src/externalsystems/BpnDidResolver.Library/DependencyInjection/BpnDidResolverServiceCollectionExtension.cs
@@ -37,13 +37,9 @@ public static IServiceCollection AddBpnDidResolver(this IServiceCollection servi
var sp = services.BuildServiceProvider();
var settings = sp.GetRequiredService>();
- services.AddHttpClient(nameof(BpnDidResolverService), c =>
- {
- var baseAddress = settings.Value.BaseAddress;
- c.BaseAddress = new Uri(baseAddress.EndsWith('/') ? baseAddress : $"{baseAddress}/");
- c.DefaultRequestHeaders.Add("X-Api-Key", settings.Value.ApiKey);
- });
+ var baseAddress = settings.Value.BaseAddress;
services
+ .AddCustomHttpClientWithAuthentication(baseAddress.EndsWith('/') ? baseAddress : $"{baseAddress}/")
.AddTransient()
.AddTransient();
diff --git a/src/externalsystems/BpnDidResolver.Library/DependencyInjection/BpnDidResolverSettings.cs b/src/externalsystems/BpnDidResolver.Library/DependencyInjection/BpnDidResolverSettings.cs
index cb34bd3b7b..66599c77d1 100644
--- a/src/externalsystems/BpnDidResolver.Library/DependencyInjection/BpnDidResolverSettings.cs
+++ b/src/externalsystems/BpnDidResolver.Library/DependencyInjection/BpnDidResolverSettings.cs
@@ -17,15 +17,13 @@
* SPDX-License-Identifier: Apache-2.0
********************************************************************************/
+using Org.Eclipse.TractusX.Portal.Backend.Framework.Token;
using System.ComponentModel.DataAnnotations;
namespace Org.Eclipse.TractusX.Portal.Backend.BpnDidResolver.Library.DependencyInjection;
-public class BpnDidResolverSettings
+public class BpnDidResolverSettings : KeyVaultAuthSettings
{
[Required(AllowEmptyStrings = false)]
public string BaseAddress { get; set; } = null!;
-
- [Required(AllowEmptyStrings = false)]
- public string ApiKey { get; set; } = null!;
}
diff --git a/src/portalbackend/PortalBackend.Migrations/Seeder/Data/identities.json b/src/portalbackend/PortalBackend.Migrations/Seeder/Data/identities.json
index aff4a91132..0001c776fe 100644
--- a/src/portalbackend/PortalBackend.Migrations/Seeder/Data/identities.json
+++ b/src/portalbackend/PortalBackend.Migrations/Seeder/Data/identities.json
@@ -160,5 +160,13 @@
"user_status_id": 1,
"user_entity_id": null,
"identity_type_id": 2
+ },
+ {
+ "id": "b28aaf44-acd6-4b77-879b-398fdec28c8b",
+ "company_id": "2dc4249f-b5ca-4d42-bef1-7a7a950a4f87",
+ "date_created": "2024-11-05 18:01:33.439000 +00:00",
+ "user_status_id": 1,
+ "user_entity_id": null,
+ "identity_type_id": 2
}
]
diff --git a/src/portalbackend/PortalBackend.Migrations/Seeder/Data/identity_assigned_roles.json b/src/portalbackend/PortalBackend.Migrations/Seeder/Data/identity_assigned_roles.json
index 597881f70e..cc553f61e7 100644
--- a/src/portalbackend/PortalBackend.Migrations/Seeder/Data/identity_assigned_roles.json
+++ b/src/portalbackend/PortalBackend.Migrations/Seeder/Data/identity_assigned_roles.json
@@ -3,5 +3,10 @@
"identity_id": "ac1cf001-7fbc-1f2f-817f-bce058020006",
"user_role_id": "58f897ec-0aad-4588-8ffa-5f45d6638632",
"last_editor_id": null
+ },
+ {
+ "identity_id": "b28aaf44-acd6-4b77-879b-398fdec28c8b",
+ "user_role_id": "c01818be-4978-41f4-bf63-fa6d2de53212",
+ "last_editor_id": null
}
]
diff --git a/src/portalbackend/PortalBackend.Migrations/Seeder/Data/technical_users.json b/src/portalbackend/PortalBackend.Migrations/Seeder/Data/technical_users.json
index 15197766a5..f4bb8dd5f9 100644
--- a/src/portalbackend/PortalBackend.Migrations/Seeder/Data/technical_users.json
+++ b/src/portalbackend/PortalBackend.Migrations/Seeder/Data/technical_users.json
@@ -164,5 +164,13 @@
"technical_user_type_id": 2,
"technical_user_kind_id": 1,
"client_client_id": "sa-cl25-cx-3"
+ },
+ {
+ "id": "b28aaf44-acd6-4b77-879b-398fdec28c8b",
+ "name": "sa-cl25-01",
+ "description": "This client/technical user will be used to communicate between portal and BDRS to store new BPNL/DID connections.",
+ "technical_user_type_id": 2,
+ "technical_user_kind_id": 1,
+ "client_client_id": "sa-cl25-01"
}
]
diff --git a/src/portalbackend/PortalBackend.Migrations/Seeder/Data/user_role_assigned_collections.json b/src/portalbackend/PortalBackend.Migrations/Seeder/Data/user_role_assigned_collections.json
index d47782f948..3590888aa7 100644
--- a/src/portalbackend/PortalBackend.Migrations/Seeder/Data/user_role_assigned_collections.json
+++ b/src/portalbackend/PortalBackend.Migrations/Seeder/Data/user_role_assigned_collections.json
@@ -246,5 +246,9 @@
{
"user_role_collection_id": "a5b8b1de-7759-4620-9c87-6b6d74fb4fbc",
"user_role_id": "9956fa8d-e454-49ca-a3b1-45e2c106fe59"
+ },
+ {
+ "user_role_collection_id": "1a24eca5-901f-4191-84a7-4ef09a894575",
+ "user_role_id": "c01818be-4978-41f4-bf63-fa6d2de53212"
}
]
diff --git a/src/portalbackend/PortalBackend.Migrations/Seeder/Data/user_role_descriptions.json b/src/portalbackend/PortalBackend.Migrations/Seeder/Data/user_role_descriptions.json
index 1b6de8c287..87501fda6f 100644
--- a/src/portalbackend/PortalBackend.Migrations/Seeder/Data/user_role_descriptions.json
+++ b/src/portalbackend/PortalBackend.Migrations/Seeder/Data/user_role_descriptions.json
@@ -318,5 +318,15 @@
"user_role_id": "a53a95be-ea7b-4033-926c-26275dc16e0f",
"language_short_name": "en",
"description": "Reserviere und bearbeitete Golden Record Tasks im Schritt 'Pool'."
+ },
+ {
+ "user_role_id": "c01818be-4978-41f4-bf63-fa6d2de53212",
+ "language_short_name": "en",
+ "description": "Create and manage BPN/DID records inside the service BDRS."
+ },
+ {
+ "user_role_id": "c01818be-4978-41f4-bf63-fa6d2de53212",
+ "language_short_name": "de",
+ "description": "Erstellen und verwalten Sie BPN/DID-Datensätze im BDRS Service."
}
]
diff --git a/src/portalbackend/PortalBackend.Migrations/Seeder/Data/user_roles.json b/src/portalbackend/PortalBackend.Migrations/Seeder/Data/user_roles.json
index 37514c0f26..fca9155839 100644
--- a/src/portalbackend/PortalBackend.Migrations/Seeder/Data/user_roles.json
+++ b/src/portalbackend/PortalBackend.Migrations/Seeder/Data/user_roles.json
@@ -196,5 +196,11 @@
"user_role": "BPDM Orchestrator Processor PoolSync",
"offer_id": "0ffcb416-1101-4ba6-8d4a-a9dfa31745a4",
"last_editor_id": null
+ },
+ {
+ "id": "c01818be-4978-41f4-bf63-fa6d2de53212",
+ "user_role": "BDRS Management",
+ "offer_id": "0ffcb416-1101-4ba6-8d4a-a9dfa31745a4",
+ "last_editor_id": null
}
]
diff --git a/src/processes/Processes.Worker/appsettings.json b/src/processes/Processes.Worker/appsettings.json
index a30cff5fa1..0a0b7f3384 100644
--- a/src/processes/Processes.Worker/appsettings.json
+++ b/src/processes/Processes.Worker/appsettings.json
@@ -371,8 +371,14 @@
]
},
"BpnDidResolver": {
- "BaseAddress": "",
- "ApiKey": ""
+ "Username": "",
+ "Password": "",
+ "ClientId": "",
+ "GrantType": "",
+ "ClientSecret": "",
+ "Scope": "",
+ "TokenAddress": "",
+ "BaseAddress": ""
}
},
"Processes": {
diff --git a/tests/externalsystems/BpnDidResolver.Library.Tests/BpnDidResolveServiceTests.cs b/tests/externalsystems/BpnDidResolver.Library.Tests/BpnDidResolveServiceTests.cs
index 1831142cb2..c6cf9da126 100644
--- a/tests/externalsystems/BpnDidResolver.Library.Tests/BpnDidResolveServiceTests.cs
+++ b/tests/externalsystems/BpnDidResolver.Library.Tests/BpnDidResolveServiceTests.cs
@@ -17,9 +17,14 @@
* SPDX-License-Identifier: Apache-2.0
********************************************************************************/
+using Microsoft.Extensions.Options;
+using Org.Eclipse.TractusX.Portal.Backend.BpnDidResolver.Library.DependencyInjection;
+using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling;
using Org.Eclipse.TractusX.Portal.Backend.Framework.Tests.Shared;
+using Org.Eclipse.TractusX.Portal.Backend.Framework.Token;
using Org.Eclipse.TractusX.Portal.Backend.Tests.Shared.Extensions;
using System.Net;
+using System.Text.Json;
namespace Org.Eclipse.TractusX.Portal.Backend.BpnDidResolver.Library.Tests;
@@ -27,16 +32,26 @@ public class BpnDidResolveServiceTests
{
private const string BPN = "BPNL0000000000XX";
private readonly IBpnDidResolverService _sut;
- private readonly IHttpClientFactory _clientFactory;
+ private readonly ITokenService _tokenService;
+ private readonly IOptions _options;
public BpnDidResolveServiceTests()
{
var fixture = new Fixture().Customize(new AutoFakeItEasyCustomization { ConfigureMembers = true });
fixture.ConfigureFixture();
-
- _clientFactory = A.Fake();
-
- _sut = new BpnDidResolverService(_clientFactory);
+ _tokenService = A.Fake();
+ _options = Options.Create(new BpnDidResolverSettings
+ {
+ Password = "passWord",
+ Scope = "test",
+ Username = "user@name",
+ BaseAddress = "https://base.address.com",
+ ClientId = "CatenaX",
+ ClientSecret = "pass@Secret",
+ GrantType = "cred",
+ TokenAddress = "https://key.cloak.com"
+ });
+ _sut = new BpnDidResolverService(_tokenService, _options);
}
#region ValidateDid
@@ -51,7 +66,8 @@ public async Task ValidateDid_WithoutError_ReturnsTrue()
{
BaseAddress = new Uri("https://base.address.com")
};
- A.CallTo(() => _clientFactory.CreateClient(nameof(BpnDidResolverService))).Returns(httpClient);
+ A.CallTo(() => _tokenService.GetAuthorizedClient(_options.Value, A._))
+ .Returns(httpClient);
// Act
var result = await _sut.TransmitDidAndBpn(did, BPN, CancellationToken.None);
@@ -70,13 +86,15 @@ public async Task ValidateDid_WithError_ReturnsFalse()
{
BaseAddress = new Uri("https://base.address.com")
};
- A.CallTo(() => _clientFactory.CreateClient(nameof(BpnDidResolverService))).Returns(httpClient);
+ A.CallTo(() => _tokenService.GetAuthorizedClient(_options.Value, A._))
+ .Returns(httpClient);
// Act
- var result = await _sut.TransmitDidAndBpn(did, BPN, CancellationToken.None);
+ async Task Act() => await _sut.TransmitDidAndBpn(did, BPN, CancellationToken.None);
// Assert
- result.Should().BeFalse();
+ var ex = await Assert.ThrowsAsync(Act);
+ ex.StatusCode.Should().Be(HttpStatusCode.BadRequest);
}
#endregion
diff --git a/tests/portalbackend/PortalBackend.DBAccess.Tests/CompanyRepositoryTests.cs b/tests/portalbackend/PortalBackend.DBAccess.Tests/CompanyRepositoryTests.cs
index acdad34cec..6837754b44 100644
--- a/tests/portalbackend/PortalBackend.DBAccess.Tests/CompanyRepositoryTests.cs
+++ b/tests/portalbackend/PortalBackend.DBAccess.Tests/CompanyRepositoryTests.cs
@@ -688,7 +688,7 @@ public async Task GetCompanyIdAndBpnForIamUserUntrackedAsync_WithValidData_Retur
// Assert
result.Should().NotBe(default);
result.Bpn.Should().Be("BPNL00000003CRHK");
- result.TechnicalUserRoleIds.Should().HaveCount(19).And.OnlyHaveUniqueItems();
+ result.TechnicalUserRoleIds.Should().HaveCount(20).And.OnlyHaveUniqueItems();
}
#endregion
diff --git a/tests/portalbackend/PortalBackend.DBAccess.Tests/CompanyRoleCollectionRolesViewTests.cs b/tests/portalbackend/PortalBackend.DBAccess.Tests/CompanyRoleCollectionRolesViewTests.cs
index a55d7a2a54..94a1fc08c6 100644
--- a/tests/portalbackend/PortalBackend.DBAccess.Tests/CompanyRoleCollectionRolesViewTests.cs
+++ b/tests/portalbackend/PortalBackend.DBAccess.Tests/CompanyRoleCollectionRolesViewTests.cs
@@ -45,7 +45,7 @@ public async Task CompanyRoleCollectionRolesView_GetAll_ReturnsExpected()
// Act
var result = await sut.CompanyRoleCollectionRolesView.ToListAsync();
- result.Should().HaveCount(62);
+ result.Should().HaveCount(63);
}
[Fact]
diff --git a/tests/portalbackend/PortalBackend.DBAccess.Tests/TechnicalUserRepositoryTests.cs b/tests/portalbackend/PortalBackend.DBAccess.Tests/TechnicalUserRepositoryTests.cs
index 9a2ffbaaa2..0da0bba15f 100644
--- a/tests/portalbackend/PortalBackend.DBAccess.Tests/TechnicalUserRepositoryTests.cs
+++ b/tests/portalbackend/PortalBackend.DBAccess.Tests/TechnicalUserRepositoryTests.cs
@@ -292,7 +292,7 @@ public async Task GetOwnCompanyServiceAccountsUntracked_WithOwnerTrue_ReturnsExp
// Assert
result.Should().NotBeNull();
- result!.Count.Should().Be(21);
+ result!.Count.Should().Be(22);
result.Data.Should().HaveCount(10)
.And.AllSatisfy(x => x.Should().Match(y =>
y.TechnicalUserTypeId == TechnicalUserTypeId.OWN &&
@@ -371,7 +371,7 @@ public async Task GetOwnCompanyServiceAccountsUntracked_WithSearch_ReturnsExpect
// Assert
result.Should().NotBeNull();
- result!.Count.Should().Be(18);
+ result!.Count.Should().Be(19);
result.Data.Should().HaveCount(10);
}
diff --git a/tests/portalbackend/PortalBackend.DBAccess.Tests/UserRolesRepositoryTests.cs b/tests/portalbackend/PortalBackend.DBAccess.Tests/UserRolesRepositoryTests.cs
index e0836f3e2b..4949ced6d6 100644
--- a/tests/portalbackend/PortalBackend.DBAccess.Tests/UserRolesRepositoryTests.cs
+++ b/tests/portalbackend/PortalBackend.DBAccess.Tests/UserRolesRepositoryTests.cs
@@ -57,7 +57,7 @@ public async Task GetCoreOfferRolesAsync_WithValidData_ReturnsExpected()
var data = await sut.GetCoreOfferRolesAsync(_validCompanyId, "en", ClientId).ToListAsync();
// Assert
- data.Should().HaveCount(19);
+ data.Should().HaveCount(20);
}
#endregion
@@ -110,9 +110,9 @@ public async Task GetServiceAccountRolesAsync_WithValidData_ReturnsExpected()
var data = await sut.GetServiceAccountRolesAsync(_validCompanyId, ClientId, Enumerable.Repeat(new Guid("607818be-4978-41f4-bf63-fa8d2de51157"), 1), Constants.DefaultLanguage).ToListAsync();
// Assert
- data.Should().HaveCount(19);
+ data.Should().HaveCount(20);
data.Should().OnlyHaveUniqueItems();
- data.Where(x => !x.External).Should().HaveCount(18);
+ data.Where(x => !x.External).Should().HaveCount(19);
data.Where(x => x.External).Should().ContainSingle();
}