From 075ab73792e440f33ebecd31ea6914af78852a42 Mon Sep 17 00:00:00 2001 From: Phil Schneider Date: Wed, 19 Jun 2024 09:32:23 +0200 Subject: [PATCH] feat(clearinghouse): add feature toggle for sd connectivity Refs: #792 --- .../BusinessLogic/ConnectorsBusinessLogic.cs | 99 +++++++++---------- .../BusinessLogic/ConnectorsSettings.cs | 5 + .../BusinessLogic/SdFactoryBusinessLogic.cs | 48 +++++---- .../SdFactory.Library/SdFactoryService.cs | 22 +---- .../SdFactory.Library/SdFactorySettings.cs | 5 + .../ConnectorsBusinessLogicTests.cs | 76 +++++++++++--- .../SdFactoryBusinessLogicTests.cs | 34 +++++-- .../SdFactoryServiceTests.cs | 2 +- 8 files changed, 173 insertions(+), 118 deletions(-) diff --git a/src/administration/Administration.Service/BusinessLogic/ConnectorsBusinessLogic.cs b/src/administration/Administration.Service/BusinessLogic/ConnectorsBusinessLogic.cs index 045184886d..1d68a30112 100644 --- a/src/administration/Administration.Service/BusinessLogic/ConnectorsBusinessLogic.cs +++ b/src/administration/Administration.Service/BusinessLogic/ConnectorsBusinessLogic.cs @@ -39,31 +39,17 @@ namespace Org.Eclipse.TractusX.Portal.Backend.Administration.Service.BusinessLog /// /// Implementation of making use of to retrieve data. /// -public class ConnectorsBusinessLogic : IConnectorsBusinessLogic +public class ConnectorsBusinessLogic( + IPortalRepositories portalRepositories, + IOptions options, + ISdFactoryBusinessLogic sdFactoryBusinessLogic, + IIdentityService identityService, + ILogger logger) + : IConnectorsBusinessLogic { - private readonly IPortalRepositories _portalRepositories; - private readonly ISdFactoryBusinessLogic _sdFactoryBusinessLogic; - private readonly IIdentityData _identityData; - private readonly ILogger _logger; - private readonly ConnectorsSettings _settings; - private static readonly Regex bpnRegex = new(@"(\w|\d){16}", RegexOptions.None, TimeSpan.FromSeconds(1)); - - /// - /// Constructor. - /// - /// Access to the needed repositories - /// The options - /// Access to the connectorsSdFactory - /// Access to the current logged in user - /// Access to the logger - public ConnectorsBusinessLogic(IPortalRepositories portalRepositories, IOptions options, ISdFactoryBusinessLogic sdFactoryBusinessLogic, IIdentityService identityService, ILogger logger) - { - _portalRepositories = portalRepositories; - _settings = options.Value; - _sdFactoryBusinessLogic = sdFactoryBusinessLogic; - _identityData = identityService.IdentityData; - _logger = logger; - } + private static readonly Regex BpnRegex = new(@"(\w|\d){16}", RegexOptions.None, TimeSpan.FromSeconds(1)); + private readonly IIdentityData _identityData = identityService.IdentityData; + private readonly ConnectorsSettings _settings = options.Value; /// public Task> GetAllCompanyConnectorDatas(int page, int size) => @@ -71,7 +57,7 @@ public ConnectorsBusinessLogic(IPortalRepositories portalRepositories, IOptions< page, size, _settings.MaxPageSize, - _portalRepositories.GetInstance().GetAllCompanyConnectorsForCompanyId(_identityData.CompanyId)); + portalRepositories.GetInstance().GetAllCompanyConnectorsForCompanyId(_identityData.CompanyId)); /// public Task> GetManagedConnectorForCompany(int page, int size) => @@ -79,12 +65,12 @@ public ConnectorsBusinessLogic(IPortalRepositories portalRepositories, IOptions< page, size, _settings.MaxPageSize, - _portalRepositories.GetInstance().GetManagedConnectorsForCompany(_identityData.CompanyId)); + portalRepositories.GetInstance().GetManagedConnectorsForCompany(_identityData.CompanyId)); public async Task GetCompanyConnectorData(Guid connectorId) { var companyId = _identityData.CompanyId; - var result = await _portalRepositories.GetInstance().GetConnectorByIdForCompany(connectorId, companyId).ConfigureAwait(ConfigureAwaitOptions.None); + var result = await portalRepositories.GetInstance().GetConnectorByIdForCompany(connectorId, companyId).ConfigureAwait(ConfigureAwaitOptions.None); if (result == default) { throw NotFoundException.Create(AdministrationConnectorErrors.CONNECTOR_NOT_FOUND, new ErrorParameter[] { new("connectorId", connectorId.ToString()) }); @@ -109,7 +95,7 @@ private async Task CreateConnectorInternalAsync(ConnectorInputModel connec var (name, connectorUrl, location, technicalUserId) = connectorInputModel; await CheckLocationExists(location); - var result = await _portalRepositories + var result = await portalRepositories .GetInstance() .GetCompanyBpnAndSelfDescriptionDocumentByIdAsync(companyId) .ConfigureAwait(ConfigureAwaitOptions.None); @@ -140,7 +126,7 @@ private async Task CreateManagedConnectorInternalAsync(ManagedConnectorInp var (name, connectorUrl, location, subscriptionId, technicalUserId) = connectorInputModel; await CheckLocationExists(location).ConfigureAwait(ConfigureAwaitOptions.None); - var result = await _portalRepositories.GetInstance() + var result = await portalRepositories.GetInstance() .CheckOfferSubscriptionWithOfferProvider(subscriptionId, companyId) .ConfigureAwait(ConfigureAwaitOptions.None); @@ -188,7 +174,7 @@ private async Task CreateManagedConnectorInternalAsync(ManagedConnectorInp private async Task CheckLocationExists(string location) { - if (!await _portalRepositories.GetInstance() + if (!await portalRepositories.GetInstance() .CheckCountryExistsByAlpha2CodeAsync(location.ToUpper()).ConfigureAwait(ConfigureAwaitOptions.None)) { throw ControllerArgumentException.Create(AdministrationConnectorErrors.CONNECTOR_ARGUMENT_LOCATION_NOT_EXIST, new ErrorParameter[] { new("location", location) }); @@ -202,7 +188,7 @@ private async Task ValidateTechnicalUser(Guid? technicalUserId, Guid companyId) return; } - if (!await _portalRepositories.GetInstance() + if (!await portalRepositories.GetInstance() .CheckActiveServiceAccountExistsForCompanyAsync(technicalUserId.Value, companyId).ConfigureAwait(ConfigureAwaitOptions.None)) { throw ControllerArgumentException.Create(AdministrationConnectorErrors.CONNECTOR_ARGUMENT_TECH_USER_NOT_ACTIVE, new ErrorParameter[] { new("technicalUserId", technicalUserId.Value.ToString()), new("companyId", companyId.ToString()) }); @@ -218,7 +204,7 @@ private async Task CreateAndRegisterConnectorAsync( { var (name, connectorUrl, type, location, provider, host, technicalUserId) = connectorInputModel; - var connectorsRepository = _portalRepositories.GetInstance(); + var connectorsRepository = portalRepositories.GetInstance(); var createdConnector = connectorsRepository.CreateConnector( name, location.ToUpper(), @@ -229,7 +215,7 @@ private async Task CreateAndRegisterConnectorAsync( connector.HostId = host; connector.TypeId = type; connector.DateLastChanged = DateTimeOffset.UtcNow; - connector.StatusId = ConnectorStatusId.PENDING; + connector.StatusId = _settings.ClearinghouseConnectDisabled ? ConnectorStatusId.ACTIVE : ConnectorStatusId.PENDING; if (technicalUserId != null) { connector.CompanyServiceAccountId = technicalUserId; @@ -241,12 +227,15 @@ private async Task CreateAndRegisterConnectorAsync( connectorsRepository.CreateConnectorAssignedSubscriptions(createdConnector.Id, subscriptionId.Value); } - var selfDescriptionDocumentUrl = $"{_settings.SelfDescriptionDocumentUrl}/{selfDescriptionDocumentId}"; - await _sdFactoryBusinessLogic - .RegisterConnectorAsync(createdConnector.Id, selfDescriptionDocumentUrl, businessPartnerNumber, cancellationToken) - .ConfigureAwait(ConfigureAwaitOptions.None); + if (!_settings.ClearinghouseConnectDisabled) + { + var selfDescriptionDocumentUrl = $"{_settings.SelfDescriptionDocumentUrl}/{selfDescriptionDocumentId}"; + await sdFactoryBusinessLogic + .RegisterConnectorAsync(createdConnector.Id, selfDescriptionDocumentUrl, businessPartnerNumber, cancellationToken) + .ConfigureAwait(ConfigureAwaitOptions.None); + } - await _portalRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None); + await portalRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None); return createdConnector.Id; } @@ -254,7 +243,7 @@ await _sdFactoryBusinessLogic public async Task DeleteConnectorAsync(Guid connectorId) { var companyId = _identityData.CompanyId; - var connectorsRepository = _portalRepositories.GetInstance(); + var connectorsRepository = portalRepositories.GetInstance(); var result = await connectorsRepository.GetConnectorDeleteDataAsync(connectorId, companyId).ConfigureAwait(ConfigureAwaitOptions.None) ?? throw NotFoundException.Create(AdministrationConnectorErrors.CONNECTOR_NOT_FOUND, new ErrorParameter[] { new("connectorId", connectorId.ToString()) }); if (!result.IsProvidingOrHostCompany) { @@ -262,7 +251,7 @@ public async Task DeleteConnectorAsync(Guid connectorId) } if (result.ServiceAccountId.HasValue && result.UserStatusId != UserStatusId.INACTIVE) { - _portalRepositories.GetInstance().AttachAndModifyIdentity(result.ServiceAccountId.Value, null, i => + portalRepositories.GetInstance().AttachAndModifyIdentity(result.ServiceAccountId.Value, null, i => { i.UserStatusId = UserStatusId.INACTIVE; }); @@ -286,7 +275,7 @@ public async Task DeleteConnectorAsync(Guid connectorId) private async Task DeleteConnector(Guid connectorId, IEnumerable connectorOfferSubscriptions, Guid selfDescriptionDocumentId, DocumentStatusId documentStatus, IConnectorsRepository connectorsRepository) { - _portalRepositories.GetInstance().AttachAndModifyDocument( + portalRepositories.GetInstance().AttachAndModifyDocument( selfDescriptionDocumentId, a => { a.DocumentStatusId = documentStatus; }, a => { a.DocumentStatusId = DocumentStatusId.INACTIVE; }); @@ -301,22 +290,22 @@ private async Task DeleteUpdateConnectorDetail(Guid connectorId, IConnectorsRepo con.StatusId = ConnectorStatusId.INACTIVE; con.DateLastChanged = DateTimeOffset.UtcNow; }); - await _portalRepositories.SaveAsync(); + await portalRepositories.SaveAsync(); } private async Task DeleteConnectorWithDocuments(Guid connectorId, Guid selfDescriptionDocumentId, IEnumerable connectorOfferSubscriptions, IConnectorsRepository connectorsRepository) { - _portalRepositories.GetInstance().RemoveDocument(selfDescriptionDocumentId); + portalRepositories.GetInstance().RemoveDocument(selfDescriptionDocumentId); RemoveConnectorAssignedOfferSubscriptions(connectorId, connectorOfferSubscriptions, connectorsRepository); connectorsRepository.DeleteConnector(connectorId); - await _portalRepositories.SaveAsync(); + await portalRepositories.SaveAsync(); } private async Task DeleteConnectorWithoutDocuments(Guid connectorId, IEnumerable connectorOfferSubscriptions, IConnectorsRepository connectorsRepository) { RemoveConnectorAssignedOfferSubscriptions(connectorId, connectorOfferSubscriptions, connectorsRepository); connectorsRepository.DeleteConnector(connectorId); - await _portalRepositories.SaveAsync(); + await portalRepositories.SaveAsync(); } private static void RemoveConnectorAssignedOfferSubscriptions(Guid connectorId, IEnumerable connectorOfferSubscriptions, IConnectorsRepository connectorsRepository) @@ -339,10 +328,10 @@ public IAsyncEnumerable GetCompanyConnectorEndPointAsync( { bpns ??= Enumerable.Empty(); - bpns.Where(bpn => !bpnRegex.IsMatch(bpn)).IfAny(invalid => + bpns.Where(bpn => !BpnRegex.IsMatch(bpn)).IfAny(invalid => throw ControllerArgumentException.Create(AdministrationConnectorErrors.CONNECTOR_ARGUMENT_INCORRECT_BPN, new ErrorParameter[] { new("bpns", string.Join(", ", invalid)) })); - return _portalRepositories.GetInstance() + return portalRepositories.GetInstance() .GetConnectorEndPointDataAsync(bpns.Select(x => x.ToUpper())) .PreSortedGroupBy(data => data.BusinessPartnerNumber) .Select(group => @@ -354,9 +343,9 @@ public IAsyncEnumerable GetCompanyConnectorEndPointAsync( /// public async Task ProcessClearinghouseSelfDescription(SelfDescriptionResponseData data, CancellationToken cancellationToken) { - _logger.LogInformation("Process SelfDescription called with the following data {Data}", data); + logger.LogInformation("Process SelfDescription called with the following data {Data}", data); - var result = await _portalRepositories.GetInstance() + var result = await portalRepositories.GetInstance() .GetConnectorDataById(data.ExternalId) .ConfigureAwait(ConfigureAwaitOptions.None); @@ -370,8 +359,8 @@ public async Task ProcessClearinghouseSelfDescription(SelfDescriptionResponseDat throw ConflictException.Create(AdministrationConnectorErrors.CONNECTOR_CONFLICT_ALREADY_ASSIGNED, new ErrorParameter[] { new("externalId", data.ExternalId.ToString()) }); } - await _sdFactoryBusinessLogic.ProcessFinishSelfDescriptionLpForConnector(data, _identityData.IdentityId, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); - await _portalRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None); + await sdFactoryBusinessLogic.ProcessFinishSelfDescriptionLpForConnector(data, _identityData.IdentityId, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); + await portalRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None); } /// @@ -383,7 +372,7 @@ public Task UpdateConnectorUrl(Guid connectorId, ConnectorUpdateRequest data) private async Task UpdateConnectorUrlInternal(Guid connectorId, ConnectorUpdateRequest data) { - var connectorsRepository = _portalRepositories + var connectorsRepository = portalRepositories .GetInstance(); var connector = await connectorsRepository .GetConnectorUpdateInformation(connectorId, _identityData.CompanyId) @@ -411,7 +400,7 @@ private async Task UpdateConnectorUrlInternal(Guid connectorId, ConnectorUpdateR var bpn = connector.Type == ConnectorTypeId.CONNECTOR_AS_A_SERVICE ? connector.Bpn - : await _portalRepositories.GetInstance() + : await portalRepositories.GetInstance() .GetCompanyBpnForIamUserAsync(_identityData.IdentityId) .ConfigureAwait(ConfigureAwaitOptions.None); if (string.IsNullOrWhiteSpace(bpn)) @@ -424,11 +413,11 @@ private async Task UpdateConnectorUrlInternal(Guid connectorId, ConnectorUpdateR con.ConnectorUrl = data.ConnectorUrl; }); - await _portalRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None); + await portalRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None); } /// public IAsyncEnumerable GetConnectorOfferSubscriptionData(bool? connectorIdSet) => - _portalRepositories.GetInstance() + portalRepositories.GetInstance() .GetConnectorOfferSubscriptionData(connectorIdSet, _identityData.CompanyId); } diff --git a/src/administration/Administration.Service/BusinessLogic/ConnectorsSettings.cs b/src/administration/Administration.Service/BusinessLogic/ConnectorsSettings.cs index f19a5d244a..a3890d054d 100644 --- a/src/administration/Administration.Service/BusinessLogic/ConnectorsSettings.cs +++ b/src/administration/Administration.Service/BusinessLogic/ConnectorsSettings.cs @@ -46,6 +46,11 @@ public class ConnectorsSettings /// [Required(AllowEmptyStrings = false)] public string SelfDescriptionDocumentUrl { get; set; } = null!; + + /// + /// If true all sd factory calls are disabled and won't be called. The respective process steps will be skipped. + /// + public bool ClearinghouseConnectDisabled { get; set; } } public static class ConnectorsSettingsExtensions diff --git a/src/externalsystems/SdFactory.Library/BusinessLogic/SdFactoryBusinessLogic.cs b/src/externalsystems/SdFactory.Library/BusinessLogic/SdFactoryBusinessLogic.cs index 91049cbd89..1cf3479903 100644 --- a/src/externalsystems/SdFactory.Library/BusinessLogic/SdFactoryBusinessLogic.cs +++ b/src/externalsystems/SdFactory.Library/BusinessLogic/SdFactoryBusinessLogic.cs @@ -17,6 +17,7 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ +using Microsoft.Extensions.Options; using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Repositories; @@ -28,19 +29,14 @@ namespace Org.Eclipse.TractusX.Portal.Backend.SdFactory.Library.BusinessLogic; -public class SdFactoryBusinessLogic : ISdFactoryBusinessLogic +public class SdFactoryBusinessLogic( + ISdFactoryService sdFactoryService, + IPortalRepositories portalRepositories, + IApplicationChecklistService checklistService, + IOptions options) + : ISdFactoryBusinessLogic { - private readonly ISdFactoryService _sdFactoryService; - private readonly IPortalRepositories _portalRepositories; - private readonly IApplicationChecklistService _checklistService; - - public SdFactoryBusinessLogic(ISdFactoryService sdFactoryService, IPortalRepositories portalRepositories, - IApplicationChecklistService checklistService) - { - _sdFactoryService = sdFactoryService; - _portalRepositories = portalRepositories; - _checklistService = checklistService; - } + private readonly SdFactorySettings _settings = options.Value; /// public Task RegisterConnectorAsync( @@ -48,11 +44,23 @@ public Task RegisterConnectorAsync( string selfDescriptionDocumentUrl, string businessPartnerNumber, CancellationToken cancellationToken) => - _sdFactoryService.RegisterConnectorAsync(connectorId, selfDescriptionDocumentUrl, businessPartnerNumber, cancellationToken); + sdFactoryService.RegisterConnectorAsync(connectorId, selfDescriptionDocumentUrl, businessPartnerNumber, cancellationToken); /// public async Task StartSelfDescriptionRegistration(IApplicationChecklistService.WorkerChecklistProcessStepData context, CancellationToken cancellationToken) { + if (_settings.ClearinghouseConnectDisabled) + { + return new IApplicationChecklistService.WorkerChecklistProcessStepExecutionResult( + ProcessStepStatusId.DONE, + entry => entry.ApplicationChecklistEntryStatusId = ApplicationChecklistEntryStatusId.DONE, + new[] { ProcessStepTypeId.ACTIVATE_APPLICATION }, + null, + true, + null + ); + } + await RegisterSelfDescriptionInternalAsync(context.ApplicationId, cancellationToken) .ConfigureAwait(ConfigureAwaitOptions.None); @@ -70,7 +78,7 @@ private async Task RegisterSelfDescriptionInternalAsync( Guid applicationId, CancellationToken cancellationToken) { - var result = await _portalRepositories.GetInstance() + var result = await portalRepositories.GetInstance() .GetCompanyAndApplicationDetailsWithUniqueIdentifiersAsync(applicationId) .ConfigureAwait(ConfigureAwaitOptions.None); if (result == default) @@ -86,7 +94,7 @@ private async Task RegisterSelfDescriptionInternalAsync( $"BusinessPartnerNumber (bpn) for CompanyApplications {applicationId} company {companyId} is empty"); } - await _sdFactoryService + await sdFactoryService .RegisterSelfDescriptionAsync(applicationId, uniqueIdentifiers, countryCode, businessPartnerNumber, cancellationToken) .ConfigureAwait(ConfigureAwaitOptions.None); } @@ -94,7 +102,7 @@ await _sdFactoryService public async Task ProcessFinishSelfDescriptionLpForApplication(SelfDescriptionResponseData data, Guid companyId, CancellationToken cancellationToken) { var confirm = ValidateData(data); - var context = await _checklistService + var context = await checklistService .VerifyChecklistEntryAndProcessSteps( data.ExternalId, ApplicationChecklistEntryTypeId.SELF_DESCRIPTION_LP, @@ -106,11 +114,11 @@ public async Task ProcessFinishSelfDescriptionLpForApplication(SelfDescriptionRe if (confirm) { var documentId = await ProcessDocument(SdFactoryResponseModelTitle.LegalPerson, data, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); - _portalRepositories.GetInstance().AttachAndModifyCompany(companyId, null, + portalRepositories.GetInstance().AttachAndModifyCompany(companyId, null, c => { c.SelfDescriptionDocumentId = documentId; }); } - _checklistService.FinalizeChecklistEntryAndProcessSteps( + checklistService.FinalizeChecklistEntryAndProcessSteps( context, null, item => @@ -133,7 +141,7 @@ public async Task ProcessFinishSelfDescriptionLpForConnector(SelfDescriptionResp { documentId = await ProcessDocument(SdFactoryResponseModelTitle.Connector, data, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); } - _portalRepositories.GetInstance().AttachAndModifyConnector(data.ExternalId, null, con => + portalRepositories.GetInstance().AttachAndModifyConnector(data.ExternalId, null, con => { if (documentId != null) { @@ -175,7 +183,7 @@ private async Task ProcessDocument(SdFactoryResponseModelTitle title, Self var documentContent = ms.ToArray(); var hash = SHA512.HashData(documentContent); - var document = _portalRepositories.GetInstance().CreateDocument( + var document = portalRepositories.GetInstance().CreateDocument( $"SelfDescription_{title}.json", documentContent, hash, diff --git a/src/externalsystems/SdFactory.Library/SdFactoryService.cs b/src/externalsystems/SdFactory.Library/SdFactoryService.cs index 10dfb07e41..0a8a4356a5 100644 --- a/src/externalsystems/SdFactory.Library/SdFactoryService.cs +++ b/src/externalsystems/SdFactory.Library/SdFactoryService.cs @@ -30,28 +30,14 @@ namespace Org.Eclipse.TractusX.Portal.Backend.SdFactory.Library; /// /// Service to handle communication with the connectors sd factory /// -public class SdFactoryService : ISdFactoryService +public class SdFactoryService(ITokenService tokenService, IOptions options) : ISdFactoryService { - private readonly ITokenService _tokenService; - private readonly SdFactorySettings _settings; - - /// - /// Creates a new instance of - /// - /// Access to the token service - /// The options - public SdFactoryService( - ITokenService tokenService, - IOptions options) - { - _settings = options.Value; - _tokenService = tokenService; - } + private readonly SdFactorySettings _settings = options.Value; /// public async Task RegisterConnectorAsync(Guid connectorId, string selfDescriptionDocumentUrl, string businessPartnerNumber, CancellationToken cancellationToken) { - var httpClient = await _tokenService.GetAuthorizedClient(_settings, cancellationToken) + var httpClient = await tokenService.GetAuthorizedClient(_settings, cancellationToken) .ConfigureAwait(ConfigureAwaitOptions.None); var requestModel = new ConnectorSdFactoryRequestModel( connectorId.ToString(), @@ -70,7 +56,7 @@ await httpClient.PostAsJsonAsync(default(string?), requestModel, cancellationTok /// public async Task RegisterSelfDescriptionAsync(Guid applicationId, IEnumerable<(UniqueIdentifierId Id, string Value)> uniqueIdentifiers, string countryCode, string businessPartnerNumber, CancellationToken cancellationToken) { - var httpClient = await _tokenService.GetAuthorizedClient(_settings, cancellationToken) + var httpClient = await tokenService.GetAuthorizedClient(_settings, cancellationToken) .ConfigureAwait(ConfigureAwaitOptions.None); var requestModel = new SdFactoryRequestModel( applicationId.ToString(), diff --git a/src/externalsystems/SdFactory.Library/SdFactorySettings.cs b/src/externalsystems/SdFactory.Library/SdFactorySettings.cs index 30775eca3a..a7b397de94 100644 --- a/src/externalsystems/SdFactory.Library/SdFactorySettings.cs +++ b/src/externalsystems/SdFactory.Library/SdFactorySettings.cs @@ -28,6 +28,11 @@ namespace Org.Eclipse.TractusX.Portal.Backend.SdFactory.Library; /// public class SdFactorySettings : KeyVaultAuthSettings { + /// + /// If true all sd factory calls are disabled and won't be called. The respective process steps will be skipped. + /// + public bool ClearinghouseConnectDisabled { get; set; } + /// /// SD Factory endpoint for registering connectors. /// diff --git a/tests/administration/Administration.Service.Tests/BusinessLogic/ConnectorsBusinessLogicTests.cs b/tests/administration/Administration.Service.Tests/BusinessLogic/ConnectorsBusinessLogicTests.cs index b5af392383..4f96886675 100644 --- a/tests/administration/Administration.Service.Tests/BusinessLogic/ConnectorsBusinessLogicTests.cs +++ b/tests/administration/Administration.Service.Tests/BusinessLogic/ConnectorsBusinessLogicTests.cs @@ -61,6 +61,8 @@ public class ConnectorsBusinessLogicTests private readonly ConnectorsBusinessLogic _logic; private readonly IDocumentRepository _documentRepository; private readonly IServiceAccountRepository _serviceAccountRepository; + private readonly IOptions _options; + private readonly IIdentityService _identityService; public ConnectorsBusinessLogicTests() { @@ -75,10 +77,10 @@ public ConnectorsBusinessLogicTests() _sdFactoryBusinessLogic = A.Fake(); _serviceAccountRepository = A.Fake(); _offerSubscriptionRepository = A.Fake(); - var identityService = A.Fake(); + _identityService = A.Fake(); _identity = A.Fake(); _connectors = new List(); - var options = A.Fake>(); + _options = A.Fake>(); var settings = new ConnectorsSettings { MaxPageSize = 15, @@ -92,13 +94,12 @@ public ConnectorsBusinessLogicTests() _documentRepository = A.Fake(); SetupRepositoryMethods(); - A.CallTo(() => options.Value).Returns(settings); - A.CallTo(() => identityService.IdentityData).Returns(_identity); - var logger = A.Fake>(); + A.CallTo(() => _options.Value).Returns(settings); + A.CallTo(() => _identityService.IdentityData).Returns(_identity); SetupIdentity(); - _logic = new ConnectorsBusinessLogic(_portalRepositories, options, _sdFactoryBusinessLogic, identityService, logger); + _logic = new ConnectorsBusinessLogic(_portalRepositories, _options, _sdFactoryBusinessLogic, _identityService, A.Fake>()); } #region GetAllCompanyConnectorDatas @@ -133,19 +134,34 @@ public async Task GetAllCompanyConnectorDatas_WithValidData_ReturnsExpected(int #region Create Connector - [Fact] - public async Task CreateConnectorAsync_WithValidInput_ReturnsCreatedConnectorData() + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task CreateConnectorAsync_WithValidInput_ReturnsCreatedConnectorData(bool clearingHouseDisabled) { // Arrange + var sut = new ConnectorsBusinessLogic(_portalRepositories, Options.Create(new ConnectorsSettings + { + MaxPageSize = 15, + ValidCertificationContentTypes = new[] + { + "application/x-pem-file", + "application/x-x509-ca-cert", + "application/pkix-cert" + }, + ClearinghouseConnectDisabled = clearingHouseDisabled + }), _sdFactoryBusinessLogic, _identityService, A.Fake>()); + var connectorInput = new ConnectorInputModel("connectorName", "https://test.de", "de", ServiceAccountUserId); // Act - var result = await _logic.CreateConnectorAsync(connectorInput, CancellationToken.None); + var result = await sut.CreateConnectorAsync(connectorInput, CancellationToken.None); // Assert result.Should().NotBeEmpty(); _connectors.Should().HaveCount(1); A.CallTo(() => _connectorsRepository.CreateConnectorAssignedSubscriptions(A._, A._)).MustNotHaveHappened(); + A.CallTo(() => _sdFactoryBusinessLogic.RegisterConnectorAsync(A._, A._, A._, A._)).MustHaveHappened(clearingHouseDisabled ? 0 : 1, Times.Exactly); } [Fact] @@ -248,36 +264,66 @@ public async Task CreateConnectorAsync_WithFailingDapsService_ReturnsCreatedConn #region CreateManagedConnectorAsync - [Fact] - public async Task CreateManagedConnectorAsync_WithValidInput_ReturnsCreatedConnectorData() + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task CreateManagedConnectorAsync_WithValidInput_ReturnsCreatedConnectorData(bool clearingHouseDisabled) { // Arrange + var sut = new ConnectorsBusinessLogic(_portalRepositories, Options.Create(new ConnectorsSettings + { + MaxPageSize = 15, + ValidCertificationContentTypes = new[] + { + "application/x-pem-file", + "application/x-x509-ca-cert", + "application/pkix-cert" + }, + ClearinghouseConnectDisabled = clearingHouseDisabled + }), _sdFactoryBusinessLogic, _identityService, A.Fake>()); + var connectorInput = new ManagedConnectorInputModel("connectorName", "https://test.de", "de", _validOfferSubscriptionId, ServiceAccountUserId); // Act - var result = await _logic.CreateManagedConnectorAsync(connectorInput, CancellationToken.None); + var result = await sut.CreateManagedConnectorAsync(connectorInput, CancellationToken.None); // Assert result.Should().NotBeEmpty(); _connectors.Should().HaveCount(1); A.CallTo(() => _connectorsRepository.CreateConnectorAssignedSubscriptions(A._, _validOfferSubscriptionId)).MustHaveHappenedOnceExactly(); + A.CallTo(() => _sdFactoryBusinessLogic.RegisterConnectorAsync(A._, A._, A._, A._)).MustHaveHappened(clearingHouseDisabled ? 0 : 1, Times.Exactly); } - [Fact] - public async Task CreateManagedConnectorAsync_WithTechnicalUser_ReturnsCreatedConnectorData() + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task CreateManagedConnectorAsync_WithTechnicalUser_ReturnsCreatedConnectorData(bool clearingHouseDisabled) { // Arrange + var sut = new ConnectorsBusinessLogic(_portalRepositories, Options.Create(new ConnectorsSettings + { + MaxPageSize = 15, + ValidCertificationContentTypes = new[] + { + "application/x-pem-file", + "application/x-x509-ca-cert", + "application/pkix-cert" + }, + ClearinghouseConnectDisabled = clearingHouseDisabled + }), _sdFactoryBusinessLogic, _identityService, A.Fake>()); + var connectorInput = new ManagedConnectorInputModel("connectorName", "https://test.de", "de", _validOfferSubscriptionId, null); SetupTechnicalIdentity(); // Act - var result = await _logic.CreateManagedConnectorAsync(connectorInput, CancellationToken.None); + var result = await sut.CreateManagedConnectorAsync(connectorInput, CancellationToken.None); // Assert result.Should().NotBeEmpty(); _connectors.Should().HaveCount(1); A.CallTo(() => _connectorsRepository.CreateConnectorAssignedSubscriptions(A._, _validOfferSubscriptionId)).MustHaveHappenedOnceExactly(); + A.CallTo(() => _sdFactoryBusinessLogic.RegisterConnectorAsync(A._, A._, A._, A._)).MustHaveHappened(clearingHouseDisabled ? 0 : 1, Times.Exactly); } [Fact] diff --git a/tests/externalsystems/SdFactory.Library.Tests/SdFactoryBusinessLogicTests.cs b/tests/externalsystems/SdFactory.Library.Tests/SdFactoryBusinessLogicTests.cs index 67c721ea77..7901edcb0b 100644 --- a/tests/externalsystems/SdFactory.Library.Tests/SdFactoryBusinessLogicTests.cs +++ b/tests/externalsystems/SdFactory.Library.Tests/SdFactoryBusinessLogicTests.cs @@ -17,6 +17,7 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ +using Microsoft.Extensions.Options; using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Repositories; @@ -41,22 +42,24 @@ public class SdFactoryBusinessLogicTests private static readonly Guid CompanyUserId = new("ac1cf001-7fbc-1f2f-817f-bce058020002"); private readonly Process _process; private static readonly Guid CompanyId = new("b4697623-dd87-410d-abb8-6d4f4d87ab58"); + private static readonly IEnumerable<(UniqueIdentifierId Id, string Value)> UniqueIdentifiers = new List<(UniqueIdentifierId Id, string Value)> { - new (UniqueIdentifierId.VAT_ID, "JUSTATEST") + new(UniqueIdentifierId.VAT_ID, "JUSTATEST") }; private readonly IApplicationRepository _applicationRepository; private readonly ICompanyRepository _companyRepository; private readonly IDocumentRepository _documentRepository; private readonly IConnectorsRepository _connectorsRepository; - private readonly IPortalRepositories _portalRepositories; private readonly ISdFactoryService _service; private readonly ICollection _documents; private readonly SdFactoryBusinessLogic _sut; private readonly IFixture _fixture; private readonly IApplicationChecklistService _checklistService; + private readonly IOptions _options; + private readonly IPortalRepositories _portalRepositories; public SdFactoryBusinessLogicTests() { @@ -79,7 +82,12 @@ public SdFactoryBusinessLogicTests() A.CallTo(() => _portalRepositories.GetInstance()).Returns(_connectorsRepository); A.CallTo(() => _portalRepositories.GetInstance()).Returns(_documentRepository); - _sut = new SdFactoryBusinessLogic(_service, _portalRepositories, _checklistService); + _options = Options.Create(new SdFactorySettings + { + SdFactoryUrl = "https://www.api.sdfactory.com", + SdFactoryIssuerBpn = "BPNL00000003CRHK" + }); + _sut = new SdFactoryBusinessLogic(_service, _portalRepositories, _checklistService, _options); } #endregion @@ -105,8 +113,10 @@ public async Task RegisterConnectorAsync_ExpectedServiceCallIsMade() #region StartSelfDescriptionRegistration - [Fact] - public async Task StartSelfDescriptionRegistration_WithValidData_CompanyIsUpdated() + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task StartSelfDescriptionRegistration_WithValidData_CompanyIsUpdated(bool clearinghouseConnectDisabled) { // Arrange var checklist = new Dictionary @@ -120,18 +130,24 @@ public async Task StartSelfDescriptionRegistration_WithValidData_CompanyIsUpdate var entry = new ApplicationChecklistEntry(Guid.NewGuid(), ApplicationChecklistEntryTypeId.SELF_DESCRIPTION_LP, ApplicationChecklistEntryStatusId.TO_DO, DateTimeOffset.UtcNow); A.CallTo(() => _applicationRepository.GetCompanyAndApplicationDetailsWithUniqueIdentifiersAsync(ApplicationId)) .Returns((CompanyId, Bpn, CountryCode, UniqueIdentifiers)); + var sut = new SdFactoryBusinessLogic(_service, _portalRepositories, _checklistService, Options.Create(new SdFactorySettings + { + SdFactoryUrl = "https://www.api.sdfactory.com", + SdFactoryIssuerBpn = "BPNL00000003CRHK", + ClearinghouseConnectDisabled = clearinghouseConnectDisabled + })); // Act - var result = await _sut.StartSelfDescriptionRegistration(context, CancellationToken.None); + var result = await sut.StartSelfDescriptionRegistration(context, CancellationToken.None); // Assert A.CallTo(() => _service.RegisterSelfDescriptionAsync(ApplicationId, UniqueIdentifiers, CountryCode, Bpn, A._)) - .MustHaveHappenedOnceExactly(); + .MustHaveHappened(clearinghouseConnectDisabled ? 0 : 1, Times.Exactly); result.Should().NotBeNull(); result.ModifyChecklistEntry.Should().NotBeNull(); result.ModifyChecklistEntry!.Invoke(entry); - entry.ApplicationChecklistEntryStatusId.Should().Be(ApplicationChecklistEntryStatusId.IN_PROGRESS); - result.ScheduleStepTypeIds.Should().ContainSingle().And.Match(x => x.Single() == ProcessStepTypeId.FINISH_SELF_DESCRIPTION_LP); + entry.ApplicationChecklistEntryStatusId.Should().Be(clearinghouseConnectDisabled ? ApplicationChecklistEntryStatusId.DONE : ApplicationChecklistEntryStatusId.IN_PROGRESS); + result.ScheduleStepTypeIds.Should().ContainSingle().And.Match(x => clearinghouseConnectDisabled ? x.Single() == ProcessStepTypeId.ACTIVATE_APPLICATION : x.Single() == ProcessStepTypeId.FINISH_SELF_DESCRIPTION_LP); result.SkipStepTypeIds.Should().BeNull(); result.Modified.Should().BeTrue(); } diff --git a/tests/externalsystems/SdFactory.Library.Tests/SdFactoryServiceTests.cs b/tests/externalsystems/SdFactory.Library.Tests/SdFactoryServiceTests.cs index c679cd9e18..2174e7ae4f 100644 --- a/tests/externalsystems/SdFactory.Library.Tests/SdFactoryServiceTests.cs +++ b/tests/externalsystems/SdFactory.Library.Tests/SdFactoryServiceTests.cs @@ -35,7 +35,7 @@ public class SdFactoryServiceTests private static readonly IEnumerable<(UniqueIdentifierId Id, string Value)> UniqueIdentifiers = new List<(UniqueIdentifierId Id, string Value)> { - new (UniqueIdentifierId.VAT_ID, "JUSTATEST") + new(UniqueIdentifierId.VAT_ID, "JUSTATEST") }; private readonly IPortalRepositories _portalRepositories;