From 09be71dd32ce6dabb85558a1b9357dff52e01f56 Mon Sep 17 00:00:00 2001 From: Phil Schneider Date: Wed, 24 Jul 2024 13:19:43 +0200 Subject: [PATCH] fix: enhance subscription/provider endpoint with external Service data Refs: #841 --- .../BusinessLogic/AppsBusinessLogic.cs | 2 +- .../BusinessLogic/AppsSettings.cs | 9 +++++++ .../Offers.Library/Models/WalletConfigData.cs | 26 +++++++++++++++++++ .../Offers.Library/Service/IOfferService.cs | 3 ++- .../Offers.Library/Service/OfferService.cs | 22 ++++++++++++++-- .../Models/OfferSubscriptionDetailData.cs | 23 ++++++++++++++-- .../OfferSubscriptionsRepository.cs | 4 ++- .../BusinessLogic/AppBusinessLogicTests.cs | 4 +-- .../appsettings.IntegrationTests.json | 5 +++- .../Service/OfferServiceTests.cs | 12 ++++++--- 10 files changed, 96 insertions(+), 14 deletions(-) create mode 100644 src/marketplace/Offers.Library/Models/WalletConfigData.cs diff --git a/src/marketplace/Apps.Service/BusinessLogic/AppsBusinessLogic.cs b/src/marketplace/Apps.Service/BusinessLogic/AppsBusinessLogic.cs index 3927fd2028..dbf0d81ff9 100644 --- a/src/marketplace/Apps.Service/BusinessLogic/AppsBusinessLogic.cs +++ b/src/marketplace/Apps.Service/BusinessLogic/AppsBusinessLogic.cs @@ -234,7 +234,7 @@ public IAsyncEnumerable GetAppAgreement(Guid appId) => /// public Task GetSubscriptionDetailForProvider(Guid appId, Guid subscriptionId) => - _offerService.GetAppSubscriptionDetailsForProviderAsync(appId, subscriptionId, OfferTypeId.APP, _settings.CompanyAdminRoles); + _offerService.GetAppSubscriptionDetailsForProviderAsync(appId, subscriptionId, OfferTypeId.APP, _settings.CompanyAdminRoles, new WalletConfigData(_settings.IssuerDid, _settings.BpnDidResolverUrl, _settings.DecentralIdentityManagementAuthUrl)); /// public Task GetSubscriptionDetailForSubscriber(Guid appId, Guid subscriptionId) => diff --git a/src/marketplace/Apps.Service/BusinessLogic/AppsSettings.cs b/src/marketplace/Apps.Service/BusinessLogic/AppsSettings.cs index 5ef1812d18..796595886a 100644 --- a/src/marketplace/Apps.Service/BusinessLogic/AppsSettings.cs +++ b/src/marketplace/Apps.Service/BusinessLogic/AppsSettings.cs @@ -225,6 +225,15 @@ public class AppsSettings [Required] [DistinctValues("x => x.DocumentTypeId")] public IEnumerable UploadActiveAppDocumentTypeIds { get; set; } = null!; + + [Required(AllowEmptyStrings = true)] + public string DecentralIdentityManagementAuthUrl { get; set; } = null!; + + [Required(AllowEmptyStrings = true)] + public string IssuerDid { get; set; } = null!; + + [Required(AllowEmptyStrings = true)] + public string BpnDidResolverUrl { get; set; } = null!; } /// diff --git a/src/marketplace/Offers.Library/Models/WalletConfigData.cs b/src/marketplace/Offers.Library/Models/WalletConfigData.cs new file mode 100644 index 0000000000..a30fd5c62f --- /dev/null +++ b/src/marketplace/Offers.Library/Models/WalletConfigData.cs @@ -0,0 +1,26 @@ +/******************************************************************************** + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +namespace Org.Eclipse.TractusX.Portal.Backend.Offers.Library.Models; + +public record WalletConfigData( + string IssuerDid, + string BpnDidResolverUrl, + string DecentralIdentityManagementAuthUrl +); diff --git a/src/marketplace/Offers.Library/Service/IOfferService.cs b/src/marketplace/Offers.Library/Service/IOfferService.cs index 4500324be6..df7e12aabe 100644 --- a/src/marketplace/Offers.Library/Service/IOfferService.cs +++ b/src/marketplace/Offers.Library/Service/IOfferService.cs @@ -248,8 +248,9 @@ Task CreateOrUpdateOfferSubscriptionAgreementConsentAsync(Guid subscriptionId, /// Id of the subscription /// Offer type /// The roles of the users that will be listed as contact + /// The information for the external service data /// Returns the details of the subscription - Task GetAppSubscriptionDetailsForProviderAsync(Guid offerId, Guid subscriptionId, OfferTypeId offerTypeId, IEnumerable contactUserRoles); + Task GetAppSubscriptionDetailsForProviderAsync(Guid offerId, Guid subscriptionId, OfferTypeId offerTypeId, IEnumerable contactUserRoles, WalletConfigData walletData); /// /// Unsubscribe the Offer subscription by subscriptionId diff --git a/src/marketplace/Offers.Library/Service/OfferService.cs b/src/marketplace/Offers.Library/Service/OfferService.cs index 892630e5ce..f9824f6644 100644 --- a/src/marketplace/Offers.Library/Service/OfferService.cs +++ b/src/marketplace/Offers.Library/Service/OfferService.cs @@ -824,11 +824,29 @@ public Task GetSubscriptionDetailsForProviderAsy GetOfferSubscriptionDetailsInternal(offerId, subscriptionId, offerTypeId, contactUserRoles, OfferCompanyRole.Provider, _portalRepositories.GetInstance().GetSubscriptionDetailsForProviderAsync); /// - public async Task GetAppSubscriptionDetailsForProviderAsync(Guid offerId, Guid subscriptionId, OfferTypeId offerTypeId, IEnumerable contactUserRoles) + public async Task GetAppSubscriptionDetailsForProviderAsync(Guid offerId, Guid subscriptionId, OfferTypeId offerTypeId, IEnumerable contactUserRoles, WalletConfigData walletData) { var data = await GetOfferSubscriptionDetailsInternal(offerId, subscriptionId, offerTypeId, contactUserRoles, OfferCompanyRole.Provider, _portalRepositories.GetInstance().GetAppSubscriptionDetailsForProviderAsync) .ConfigureAwait(ConfigureAwaitOptions.None); - return new AppProviderSubscriptionDetailData(data.Id, data.OfferSubscriptionStatus, data.Name, data.Customer, data.Bpn, data.Contact, data.TechnicalUserData, data.TenantUrl, data.AppInstanceId, data.ProcessSteps.GetProcessStepTypeId(data.Id, _logger)); + return new AppProviderSubscriptionDetailData( + data.Id, + data.OfferSubscriptionStatus, + data.Name, + data.Customer, + data.Bpn, + data.Contact, + data.TechnicalUserData, + data.ConnectorData, + data.TenantUrl, + data.AppInstanceId, + data.ProcessSteps.GetProcessStepTypeId(data.Id, _logger), + new SubscriptionExternalServiceData( + walletData.IssuerDid, + data.ExternalServiceData?.ParticipantId, + data.ExternalServiceData?.TrustedIssuer == null || data.ExternalServiceData.TrustedIssuer.EndsWith(":holder-iatp") ? null : $"{data.ExternalServiceData.TrustedIssuer}:holder-iatp", + walletData.BpnDidResolverUrl, + walletData.DecentralIdentityManagementAuthUrl, + data.ExternalServiceData?.DecentralIdentityManagementServiceUrl)); } /// diff --git a/src/portalbackend/PortalBackend.DBAccess/Models/OfferSubscriptionDetailData.cs b/src/portalbackend/PortalBackend.DBAccess/Models/OfferSubscriptionDetailData.cs index 7b72845a77..f7b8ca48d4 100644 --- a/src/portalbackend/PortalBackend.DBAccess/Models/OfferSubscriptionDetailData.cs +++ b/src/portalbackend/PortalBackend.DBAccess/Models/OfferSubscriptionDetailData.cs @@ -69,9 +69,20 @@ public record AppProviderSubscriptionDetailData( string? Bpn, IEnumerable Contact, IEnumerable TechnicalUserData, + IEnumerable ConnectorData, string? TenantUrl, string AppInstanceId, - ProcessStepTypeId? ProcessStepTypeId + ProcessStepTypeId? ProcessStepTypeId, + SubscriptionExternalServiceData ExternalService +); + +public record SubscriptionExternalServiceData( + [property: JsonPropertyName("trusted_issuer")] string TrustedIssuer, + [property: JsonPropertyName("participant_id")] string? ParticipantId, + [property: JsonPropertyName("iatp_id")] string? IatpId, + [property: JsonPropertyName("did_resolver")] string DidResolver, + [property: JsonPropertyName("decentralIdentityManagementAuthUrl")] string DecentralIdentityManagementAuthUrl, + [property: JsonPropertyName("decentralIdentityManagementServiceUrl")] string? DecentralIdentityManagementServiceUrl ); /// @@ -126,5 +137,13 @@ public record AppProviderSubscriptionDetail( IEnumerable TechnicalUserData, string? TenantUrl, string AppInstanceId, - IEnumerable<(ProcessStepTypeId ProcessStepTypeId, ProcessStepStatusId ProcessStepStatusId)> ProcessSteps + IEnumerable<(ProcessStepTypeId ProcessStepTypeId, ProcessStepStatusId ProcessStepStatusId)> ProcessSteps, + IEnumerable ConnectorData, + ExternalServiceData? ExternalServiceData +); + +public record ExternalServiceData( + [property: JsonPropertyName("trusted_issuer")] string TrustedIssuer, + [property: JsonPropertyName("participant_id")] string? ParticipantId, + [property: JsonPropertyName("decentralIdentityManagementServiceUrl")] string DecentralIdentityManagementServiceUrl ); diff --git a/src/portalbackend/PortalBackend.DBAccess/Repositories/OfferSubscriptionsRepository.cs b/src/portalbackend/PortalBackend.DBAccess/Repositories/OfferSubscriptionsRepository.cs index f81b4a50bf..a98adc8d4d 100644 --- a/src/portalbackend/PortalBackend.DBAccess/Repositories/OfferSubscriptionsRepository.cs +++ b/src/portalbackend/PortalBackend.DBAccess/Repositories/OfferSubscriptionsRepository.cs @@ -244,7 +244,9 @@ public OfferSubscription AttachAndModifyOfferSubscription(Guid offerSubscription .Select(ps => new ValueTuple( ps.ProcessStepTypeId, ps.ProcessStepStatusId)) - .Distinct()) + .Distinct(), + x.Subscription.ConnectorAssignedOfferSubscriptions.Select(c => new SubscriptionAssignedConnectorData(c.ConnectorId, c.Connector!.Name, c.Connector.ConnectorUrl)), + x.Company.CompanyWalletData == null ? null : new ExternalServiceData(x.Company.CompanyWalletData!.Did, x.Company.BusinessPartnerNumber, x.Company.CompanyWalletData.AuthenticationServiceUrl)) : null)) .SingleOrDefaultAsync(); diff --git a/tests/marketplace/Apps.Service.Tests/BusinessLogic/AppBusinessLogicTests.cs b/tests/marketplace/Apps.Service.Tests/BusinessLogic/AppBusinessLogicTests.cs index c38266a3d4..eab4c9ea8c 100644 --- a/tests/marketplace/Apps.Service.Tests/BusinessLogic/AppBusinessLogicTests.cs +++ b/tests/marketplace/Apps.Service.Tests/BusinessLogic/AppBusinessLogicTests.cs @@ -507,7 +507,7 @@ public async Task GetSubscriptionDetailForProvider_ReturnsExpected() new UserRoleConfig("ClientTest", new[] {"Test"}) } }; - A.CallTo(() => _offerService.GetAppSubscriptionDetailsForProviderAsync(A._, A._, A._, A>._)) + A.CallTo(() => _offerService.GetAppSubscriptionDetailsForProviderAsync(A._, A._, A._, A>._, A._)) .Returns(data); var sut = new AppsBusinessLogic(null!, null!, _offerService, null!, Options.Create(settings), _identityService, _logger); @@ -516,7 +516,7 @@ public async Task GetSubscriptionDetailForProvider_ReturnsExpected() // Assert result.Should().Be(data); - A.CallTo(() => _offerService.GetAppSubscriptionDetailsForProviderAsync(appId, subscriptionId, OfferTypeId.APP, A>._)) + A.CallTo(() => _offerService.GetAppSubscriptionDetailsForProviderAsync(appId, subscriptionId, OfferTypeId.APP, A>._, A._)) .MustHaveHappenedOnceExactly(); } diff --git a/tests/marketplace/Apps.Service.Tests/appsettings.IntegrationTests.json b/tests/marketplace/Apps.Service.Tests/appsettings.IntegrationTests.json index 1f00b30b42..1617190390 100644 --- a/tests/marketplace/Apps.Service.Tests/appsettings.IntegrationTests.json +++ b/tests/marketplace/Apps.Service.Tests/appsettings.IntegrationTests.json @@ -234,7 +234,10 @@ } ], "OfferSubscriptionAddress": "https://test.de", - "OfferDetailAddress": "https://detail.de" + "OfferDetailAddress": "https://detail.de", + "DecentralIdentityManagementAuthUrl": "https://test.org/auth", + "IssuerDid": "did:web:example.org:test123", + "BpnDidResolverUrl": "https://test.org/bpn-did" }, "Provisioning": { "CentralRealm": "CX-Central", diff --git a/tests/marketplace/Offers.Library.Tests/Service/OfferServiceTests.cs b/tests/marketplace/Offers.Library.Tests/Service/OfferServiceTests.cs index 6a71983f01..7e5997aae7 100644 --- a/tests/marketplace/Offers.Library.Tests/Service/OfferServiceTests.cs +++ b/tests/marketplace/Offers.Library.Tests/Service/OfferServiceTests.cs @@ -2218,11 +2218,12 @@ public async Task GetAppSubscriptionDetailForProvider_WithNotMatchingUserRoles_T var offerId = Guid.NewGuid(); var subscriptionId = Guid.NewGuid(); var companyAdminRoles = _fixture.CreateMany().ToImmutableArray(); + var walletData = _fixture.Create(); SetupGetSubscriptionDetailForProvider(); // Act - async Task Act() => await _sut.GetAppSubscriptionDetailsForProviderAsync(offerId, subscriptionId, OfferTypeId.APP, companyAdminRoles); + async Task Act() => await _sut.GetAppSubscriptionDetailsForProviderAsync(offerId, subscriptionId, OfferTypeId.APP, companyAdminRoles, walletData); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -2243,13 +2244,14 @@ public async Task GetAppSubscriptionDetailForProvider_WithNotExistingOffer_Throw { new UserRoleConfig("ClientTest", new[] {"Test"}) }; + var walletData = _fixture.Create(); SetupGetSubscriptionDetailForProvider(); A.CallTo(() => _offerSubscriptionsRepository.GetAppSubscriptionDetailsForProviderAsync(A._, A._, A._, A._, A>._)) .Returns<(bool, bool, AppProviderSubscriptionDetail?)>(default); // Act - async Task Act() => await _sut.GetAppSubscriptionDetailsForProviderAsync(appId, subscriptionId, OfferTypeId.APP, companyAdminRoles); + async Task Act() => await _sut.GetAppSubscriptionDetailsForProviderAsync(appId, subscriptionId, OfferTypeId.APP, companyAdminRoles, walletData); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -2270,13 +2272,14 @@ public async Task GetAppSubscriptionDetailForProvider_WithUserNotInProvidingComp { new UserRoleConfig("ClientTest", new[] {"Test"}) }; + var walletData = _fixture.Create(); SetupGetSubscriptionDetailForProvider(); A.CallTo(() => _offerSubscriptionsRepository.GetAppSubscriptionDetailsForProviderAsync(A._, A._, A._, A._, A>._)) .Returns((true, false, _fixture.Create())); // Act - async Task Act() => await _sut.GetAppSubscriptionDetailsForProviderAsync(appId, subscriptionId, OfferTypeId.APP, companyAdminRoles); + async Task Act() => await _sut.GetAppSubscriptionDetailsForProviderAsync(appId, subscriptionId, OfferTypeId.APP, companyAdminRoles, walletData); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -2297,6 +2300,7 @@ public async Task GetAppSubscriptionDetailForProvider_WithValidData_ReturnsExpec { new UserRoleConfig("ClientTest", new[] {"Test"}) }; + var walletData = _fixture.Create(); SetupGetSubscriptionDetailForProvider(); var data = _fixture.Create(); @@ -2305,7 +2309,7 @@ public async Task GetAppSubscriptionDetailForProvider_WithValidData_ReturnsExpec .Returns((true, true, data)); // Act - var result = await _sut.GetAppSubscriptionDetailsForProviderAsync(appId, subscriptionId, OfferTypeId.APP, companyAdminRoles); + var result = await _sut.GetAppSubscriptionDetailsForProviderAsync(appId, subscriptionId, OfferTypeId.APP, companyAdminRoles, walletData); // Assert result.Id.Should().Be(data.Id);