From 6103bde8af6e35a36002d1fd03a02b04e59a0661 Mon Sep 17 00:00:00 2001 From: AnuragNagpure <145100366+AnuragNagpure@users.noreply.github.com> Date: Tue, 5 Nov 2024 13:53:03 +0530 Subject: [PATCH 1/7] feat(connector): connector controller change url added (#1094) Reviewed-by: Phil Schneider Refs: #549 --- .../BusinessLogic/ConnectorsBusinessLogic.cs | 26 +++++++-- .../BusinessLogic/IConnectorsBusinessLogic.cs | 3 +- .../Controllers/ConnectorsController.cs | 5 +- .../Models/ConnectorUpdateInformation.cs | 4 +- .../Repositories/ConnectorsRepository.cs | 5 +- .../ConnectorsBusinessLogicTests.cs | 53 ++++++++++++++++--- .../Controllers/ConnectorsControllerTests.cs | 4 +- 7 files changed, 82 insertions(+), 18 deletions(-) diff --git a/src/administration/Administration.Service/BusinessLogic/ConnectorsBusinessLogic.cs b/src/administration/Administration.Service/BusinessLogic/ConnectorsBusinessLogic.cs index 9918e87408..0de31768de 100644 --- a/src/administration/Administration.Service/BusinessLogic/ConnectorsBusinessLogic.cs +++ b/src/administration/Administration.Service/BusinessLogic/ConnectorsBusinessLogic.cs @@ -384,16 +384,18 @@ public async Task ProcessClearinghouseSelfDescription(SelfDescriptionResponseDat } /// - public Task UpdateConnectorUrl(Guid connectorId, ConnectorUpdateRequest data) + public Task UpdateConnectorUrl(Guid connectorId, ConnectorUpdateRequest data, CancellationToken cancellationToken) { data.ConnectorUrl.EnsureValidHttpUrl(() => nameof(data.ConnectorUrl)); - return UpdateConnectorUrlInternal(connectorId, data); + return UpdateConnectorUrlInternal(connectorId, data, cancellationToken); } - private async Task UpdateConnectorUrlInternal(Guid connectorId, ConnectorUpdateRequest data) + private async Task UpdateConnectorUrlInternal(Guid connectorId, ConnectorUpdateRequest data, CancellationToken cancellationToken) { var connectorsRepository = portalRepositories .GetInstance(); + var documentRepository = portalRepositories + .GetInstance(); var connector = await connectorsRepository .GetConnectorUpdateInformation(connectorId, _identityData.CompanyId) .ConfigureAwait(ConfigureAwaitOptions.None); @@ -433,6 +435,24 @@ private async Task UpdateConnectorUrlInternal(Guid connectorId, ConnectorUpdateR con.ConnectorUrl = data.ConnectorUrl; }); + if (connector.SelfDescriptionDocumentId != null) + { + documentRepository.AttachAndModifyDocument(connector.SelfDescriptionDocumentId.Value, null, doc => + { + doc.DocumentStatusId = DocumentStatusId.INACTIVE; + }); + } + + if (connector.SelfDescriptionCompanyDocumentId is null) + { + throw ConflictException.Create(AdministrationConnectorErrors.CONNECTOR_CONFLICT_NO_DESCRIPTION, [new("connectorId", connectorId.ToString())]); + } + + var selfDescriptionDocumentUrl = $"{_settings.SelfDescriptionDocumentUrl}/{connector.SelfDescriptionCompanyDocumentId}"; + await sdFactoryBusinessLogic + .RegisterConnectorAsync(connectorId, selfDescriptionDocumentUrl, bpn, cancellationToken) + .ConfigureAwait(ConfigureAwaitOptions.None); + await portalRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None); } diff --git a/src/administration/Administration.Service/BusinessLogic/IConnectorsBusinessLogic.cs b/src/administration/Administration.Service/BusinessLogic/IConnectorsBusinessLogic.cs index 3c3ee577de..67b45fc456 100644 --- a/src/administration/Administration.Service/BusinessLogic/IConnectorsBusinessLogic.cs +++ b/src/administration/Administration.Service/BusinessLogic/IConnectorsBusinessLogic.cs @@ -89,7 +89,8 @@ public interface IConnectorsBusinessLogic /// /// Id of the connector /// Update data for the connector - Task UpdateConnectorUrl(Guid connectorId, ConnectorUpdateRequest data); + /// CancellationToken + Task UpdateConnectorUrl(Guid connectorId, ConnectorUpdateRequest data, CancellationToken cancellationToken); /// /// Gets the offer subscription data diff --git a/src/administration/Administration.Service/Controllers/ConnectorsController.cs b/src/administration/Administration.Service/Controllers/ConnectorsController.cs index f3324d2212..c1f4d599c4 100644 --- a/src/administration/Administration.Service/Controllers/ConnectorsController.cs +++ b/src/administration/Administration.Service/Controllers/ConnectorsController.cs @@ -208,6 +208,7 @@ public async Task ProcessClearinghouseSelfDescription([FromBody /// /// Id of the connector to trigger the daps call. /// The update data + /// CancellationToken /// NoContent Result. /// Example: PUT: /api/administration/connectors/{connectorId}/connectorUrl /// Url was successfully updated. @@ -224,9 +225,9 @@ public async Task ProcessClearinghouseSelfDescription([FromBody [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status403Forbidden)] [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status404NotFound)] [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status503ServiceUnavailable)] - public async Task UpdateConnectorUrl([FromRoute] Guid connectorId, [FromBody] ConnectorUpdateRequest data) + public async Task UpdateConnectorUrl([FromRoute] Guid connectorId, [FromBody] ConnectorUpdateRequest data, CancellationToken cancellationToken) { - await logic.UpdateConnectorUrl(connectorId, data) + await logic.UpdateConnectorUrl(connectorId, data, cancellationToken) .ConfigureAwait(ConfigureAwaitOptions.None); return NoContent(); } diff --git a/src/portalbackend/PortalBackend.DBAccess/Models/ConnectorUpdateInformation.cs b/src/portalbackend/PortalBackend.DBAccess/Models/ConnectorUpdateInformation.cs index 66b78c4b16..4b01548453 100644 --- a/src/portalbackend/PortalBackend.DBAccess/Models/ConnectorUpdateInformation.cs +++ b/src/portalbackend/PortalBackend.DBAccess/Models/ConnectorUpdateInformation.cs @@ -30,4 +30,6 @@ public record ConnectorUpdateInformation( ConnectorTypeId Type, bool IsHostCompany, string ConnectorUrl, - string? Bpn); + string? Bpn, + Guid? SelfDescriptionDocumentId, + Guid? SelfDescriptionCompanyDocumentId); diff --git a/src/portalbackend/PortalBackend.DBAccess/Repositories/ConnectorsRepository.cs b/src/portalbackend/PortalBackend.DBAccess/Repositories/ConnectorsRepository.cs index 67f8eaf7ad..e6bcbf1796 100644 --- a/src/portalbackend/PortalBackend.DBAccess/Repositories/ConnectorsRepository.cs +++ b/src/portalbackend/PortalBackend.DBAccess/Repositories/ConnectorsRepository.cs @@ -192,8 +192,9 @@ public Connector AttachAndModifyConnector(Guid connectorId, Action? i c.TypeId, c.HostId == companyId, c.ConnectorUrl, - c.Provider!.BusinessPartnerNumber - )) + c.Provider!.BusinessPartnerNumber, + c.SelfDescriptionDocumentId, + c.Host!.SelfDescriptionDocumentId)) .SingleOrDefaultAsync(); public void DeleteConnector(Guid connectorId) => diff --git a/tests/administration/Administration.Service.Tests/BusinessLogic/ConnectorsBusinessLogicTests.cs b/tests/administration/Administration.Service.Tests/BusinessLogic/ConnectorsBusinessLogicTests.cs index f1c55d916d..3058beee70 100644 --- a/tests/administration/Administration.Service.Tests/BusinessLogic/ConnectorsBusinessLogicTests.cs +++ b/tests/administration/Administration.Service.Tests/BusinessLogic/ConnectorsBusinessLogicTests.cs @@ -975,7 +975,7 @@ public async Task UpdateConnectorUrl_WithoutConnector_ThrowsNotFoundException() .Returns(null); // Act - async Task Act() => await _logic.UpdateConnectorUrl(connectorId, new ConnectorUpdateRequest("https://test.de")); + async Task Act() => await _logic.UpdateConnectorUrl(connectorId, new ConnectorUpdateRequest("https://test.de"), CancellationToken.None); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -994,7 +994,7 @@ public async Task UpdateConnectorUrl_WithSameUrlAsStored_ReturnsWithoutDoing() .Returns(data); // Act - await _logic.UpdateConnectorUrl(connectorId, new ConnectorUpdateRequest("https://test.de")); + await _logic.UpdateConnectorUrl(connectorId, new ConnectorUpdateRequest("https://test.de"), CancellationToken.None); // Assert A.CallTo(() => _portalRepositories.SaveAsync()).MustNotHaveHappened(); @@ -1013,7 +1013,7 @@ public async Task UpdateConnectorUrl_WithUserNotOfHostCompany_ThrowsForbiddenExc .Returns(data); // Act - async Task Act() => await _logic.UpdateConnectorUrl(connectorId, new ConnectorUpdateRequest("https://new.de")); + async Task Act() => await _logic.UpdateConnectorUrl(connectorId, new ConnectorUpdateRequest("https://new.de"), CancellationToken.None); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -1034,7 +1034,7 @@ public async Task UpdateConnectorUrl_WithInactiveConnector_ThrowsConflictExcepti .Returns(data); // Act - async Task Act() => await _logic.UpdateConnectorUrl(connectorId, new ConnectorUpdateRequest("https://new.de")); + async Task Act() => await _logic.UpdateConnectorUrl(connectorId, new ConnectorUpdateRequest("https://new.de"), CancellationToken.None); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -1057,7 +1057,7 @@ public async Task UpdateConnectorUrl_WithBpnNotSet_ThrowsConflictException() .Returns(data); // Act - async Task Act() => await _logic.UpdateConnectorUrl(connectorId, new ConnectorUpdateRequest("https://new.de")); + async Task Act() => await _logic.UpdateConnectorUrl(connectorId, new ConnectorUpdateRequest("https://new.de"), CancellationToken.None); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -1082,7 +1082,7 @@ public async Task UpdateConnectorUrl_WithCompanyBpnNotSet_ThrowsConflictExceptio .Returns(null); // Act - async Task Act() => await _logic.UpdateConnectorUrl(connectorId, new ConnectorUpdateRequest("https://new.de")); + async Task Act() => await _logic.UpdateConnectorUrl(connectorId, new ConnectorUpdateRequest("https://new.de"), CancellationToken.None); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -1093,7 +1093,9 @@ public async Task UpdateConnectorUrl_WithCompanyBpnNotSet_ThrowsConflictExceptio public async Task UpdateConnectorUrl_WithValidData_CallsExpected() { // Arrange + var documentId = Guid.NewGuid(); var connectorId = Guid.NewGuid(); + var document = new Document(documentId, null!, null!, null!, default, default, DocumentStatusId.PENDING, default); var connector = _fixture.Build() .With(x => x.ConnectorUrl, "https://old.de") .Create(); @@ -1103,7 +1105,10 @@ public async Task UpdateConnectorUrl_WithValidData_CallsExpected() .With(x => x.Status, ConnectorStatusId.ACTIVE) .With(x => x.Type, ConnectorTypeId.CONNECTOR_AS_A_SERVICE) .With(x => x.Bpn, "BPNL123456789") + .With(x => x.SelfDescriptionDocumentId, documentId) + .With(x => x.SelfDescriptionCompanyDocumentId, Guid.NewGuid()) .Create(); + A.CallTo(() => _connectorsRepository.GetConnectorUpdateInformation(connectorId, _identity.CompanyId)) .Returns(data); A.CallTo(() => _connectorsRepository.AttachAndModifyConnector(connectorId, null, A>._)) @@ -1112,14 +1117,48 @@ public async Task UpdateConnectorUrl_WithValidData_CallsExpected() initialize?.Invoke(connector); setOptionalProperties.Invoke(connector); }); + A.CallTo(() => _documentRepository.AttachAndModifyDocument(A._, A>._, A>._)) + .Invokes((Guid documentId, Action? initialize, Action modify) + => + { + initialize?.Invoke(document); + modify(document); + }); // Act - await _logic.UpdateConnectorUrl(connectorId, new ConnectorUpdateRequest("https://new.de")); + await _logic.UpdateConnectorUrl(connectorId, new ConnectorUpdateRequest("https://new.de"), CancellationToken.None); // Assert A.CallTo(() => _portalRepositories.SaveAsync()).MustHaveHappenedOnceExactly(); A.CallTo(() => _connectorsRepository.AttachAndModifyConnector(connectorId, null, A>._)).MustHaveHappenedOnceExactly(); + A.CallTo(() => _documentRepository.AttachAndModifyDocument((Guid)data.SelfDescriptionDocumentId!, null, A>._)).MustHaveHappenedOnceExactly(); + A.CallTo(() => _sdFactoryBusinessLogic.RegisterConnectorAsync(A._, A._, A._, A._)).MustHaveHappenedOnceExactly(); connector.ConnectorUrl.Should().Be("https://new.de"); + document.DocumentStatusId.Should().Be(DocumentStatusId.INACTIVE); + } + + [Fact] + public async Task UpdateConnectorUrl_WithSelfDescriptionCompanyIdNotSet_ThrowsConflictException() + { + // Arrange + var connectorId = Guid.NewGuid(); + var data = _fixture.Build() + .With(x => x.ConnectorUrl, "https://old.de") + .With(x => x.IsHostCompany, true) + .With(x => x.Status, ConnectorStatusId.ACTIVE) + .With(x => x.Type, ConnectorTypeId.CONNECTOR_AS_A_SERVICE) + .With(x => x.Bpn, "BPNL123456789") + .With(x => x.SelfDescriptionCompanyDocumentId, default(Guid?)) + .Create(); + A.CallTo(() => _connectorsRepository.GetConnectorUpdateInformation(connectorId, _identity.CompanyId)) + .Returns(data); + + // Act + async Task Act() => await _logic.UpdateConnectorUrl(connectorId, new ConnectorUpdateRequest("https://new.de"), CancellationToken.None); + + // Assert + var ex = await Assert.ThrowsAsync(Act); + ex.Message.Should().Be(AdministrationConnectorErrors.CONNECTOR_CONFLICT_NO_DESCRIPTION.ToString()); } #endregion diff --git a/tests/administration/Administration.Service.Tests/Controllers/ConnectorsControllerTests.cs b/tests/administration/Administration.Service.Tests/Controllers/ConnectorsControllerTests.cs index ea7e0cd7e7..33180aef88 100644 --- a/tests/administration/Administration.Service.Tests/Controllers/ConnectorsControllerTests.cs +++ b/tests/administration/Administration.Service.Tests/Controllers/ConnectorsControllerTests.cs @@ -219,10 +219,10 @@ public async Task UpdateConnectorUrl_ReturnsExpectedResult() var data = new ConnectorUpdateRequest("https://test.com"); // Act - var result = await _controller.UpdateConnectorUrl(connectorId, data); + var result = await _controller.UpdateConnectorUrl(connectorId, data, CancellationToken.None); // Assert - A.CallTo(() => _logic.UpdateConnectorUrl(connectorId, data)).MustHaveHappenedOnceExactly(); + A.CallTo(() => _logic.UpdateConnectorUrl(connectorId, data, CancellationToken.None)).MustHaveHappenedOnceExactly(); result.Should().BeOfType(); } From af32ca44b34c3bf31a458605735dc5abf7fbb4b2 Mon Sep 17 00:00:00 2001 From: "Dhirender Singh (Cofinity-X)" <144212607+dhiren-singh-007@users.noreply.github.com> Date: Tue, 5 Nov 2024 10:10:33 +0100 Subject: [PATCH 2/7] fix(registration): fixed the company name change in IDP (#1010) * in registration, if company-name is changed rename the displayname in shared idp and update the idp's organisation-mapper accordingly. * added the unit test and updated the existing one --------- Co-authored-by: Norbert Truchsess --- .../BusinessLogic/UserBusinessLogic.cs | 5 +- .../BusinessLogic/UserUploadBusinessLogic.cs | 8 +- .../Extensions/IdentityProviderManager.cs | 33 +++ .../IProvisioningManager.cs | 1 + .../IIdentityProviderProvisioningService.cs | 26 ++ .../Service/IUserProvisioningService.cs | 1 - .../IdentityProviderProvisioningService.cs | 37 +++ .../Service/UserProvisioningService.cs | 3 - .../RegistrationBusinessLogic.cs | 10 +- .../BusinessLogic/UserBusinessLogicTests.cs | 48 +++- .../UserUploadBusinessLogicTests.cs | 30 +- .../RegistrationBusinessLogicTest.cs | 264 ++++++++++++++---- 12 files changed, 377 insertions(+), 89 deletions(-) create mode 100644 src/provisioning/Provisioning.Library/Service/IIdentityProviderProvisioningService.cs create mode 100644 src/provisioning/Provisioning.Library/Service/IdentityProviderProvisioningService.cs diff --git a/src/administration/Administration.Service/BusinessLogic/UserBusinessLogic.cs b/src/administration/Administration.Service/BusinessLogic/UserBusinessLogic.cs index baf79f70eb..dec985e6e8 100644 --- a/src/administration/Administration.Service/BusinessLogic/UserBusinessLogic.cs +++ b/src/administration/Administration.Service/BusinessLogic/UserBusinessLogic.cs @@ -44,6 +44,7 @@ namespace Org.Eclipse.TractusX.Portal.Backend.Administration.Service.BusinessLog public class UserBusinessLogic( IProvisioningManager provisioningManager, IUserProvisioningService userProvisioningService, + IIdentityProviderProvisioningService identityProviderProvisioningService, IProvisioningDBAccess provisioningDbAccess, IPortalRepositories portalRepositories, IIdentityService identityService, @@ -96,7 +97,7 @@ private async IAsyncEnumerable CreateOwnCompanyUsersInternalAsync(IEnume user => user.userName ?? user.eMail, user => user.eMail); - var companyDisplayName = await userProvisioningService.GetIdentityProviderDisplayName(companyNameIdpAliasData.IdpAlias).ConfigureAwait(ConfigureAwaitOptions.None) ?? companyNameIdpAliasData.IdpAlias; + var companyDisplayName = await identityProviderProvisioningService.GetIdentityProviderDisplayName(companyNameIdpAliasData.IdpAlias).ConfigureAwait(ConfigureAwaitOptions.None) ?? companyNameIdpAliasData.IdpAlias; await foreach (var (companyUserId, userName, password, error) in userProvisioningService.CreateOwnCompanyIdpUsersAsync(companyNameIdpAliasData, userCreationInfoIdps).ConfigureAwait(false)) { @@ -137,7 +138,7 @@ private Task> GetOwnCompanyUserRoleData(IEnumerable CreateOwnCompanyIdpUserAsync(Guid identityProviderId, UserCreationInfoIdp userCreationInfo) { var (companyNameIdpAliasData, nameCreatedBy) = await userProvisioningService.GetCompanyNameIdpAliasData(identityProviderId, _identityData.IdentityId).ConfigureAwait(ConfigureAwaitOptions.None); - var displayName = await userProvisioningService.GetIdentityProviderDisplayName(companyNameIdpAliasData.IdpAlias).ConfigureAwait(ConfigureAwaitOptions.None) ?? companyNameIdpAliasData.IdpAlias; + var displayName = await identityProviderProvisioningService.GetIdentityProviderDisplayName(companyNameIdpAliasData.IdpAlias).ConfigureAwait(ConfigureAwaitOptions.None) ?? companyNameIdpAliasData.IdpAlias; if (!userCreationInfo.Roles.Any()) { diff --git a/src/administration/Administration.Service/BusinessLogic/UserUploadBusinessLogic.cs b/src/administration/Administration.Service/BusinessLogic/UserUploadBusinessLogic.cs index eb32fdfe2a..0f423923df 100644 --- a/src/administration/Administration.Service/BusinessLogic/UserUploadBusinessLogic.cs +++ b/src/administration/Administration.Service/BusinessLogic/UserUploadBusinessLogic.cs @@ -36,6 +36,7 @@ namespace Org.Eclipse.TractusX.Portal.Backend.Administration.Service.BusinessLog public class UserUploadBusinessLogic : IUserUploadBusinessLogic { private readonly IUserProvisioningService _userProvisioningService; + private readonly IIdentityProviderProvisioningService _identityProviderProvisioningServcie; private readonly IMailingProcessCreation _mailingProcessCreation; private readonly UserSettings _settings; private readonly IIdentityData _identityData; @@ -45,18 +46,21 @@ public class UserUploadBusinessLogic : IUserUploadBusinessLogic /// Constructor. /// /// User Provisioning Service + /// IdentityProvider Provisioning Service /// The mailingProcessCreation /// Access to the identity Service /// ErrorMessage Service /// Settings public UserUploadBusinessLogic( IUserProvisioningService userProvisioningService, + IIdentityProviderProvisioningService identityProviderProvisioningService, IMailingProcessCreation mailingProcessCreation, IIdentityService identityService, IErrorMessageService errorMessageService, IOptions settings) { _userProvisioningService = userProvisioningService; + _identityProviderProvisioningServcie = identityProviderProvisioningService; _mailingProcessCreation = mailingProcessCreation; _identityData = identityService.IdentityData; _errorMessageService = errorMessageService; @@ -79,7 +83,7 @@ private async ValueTask UploadOwnCompanyIdpUsersInternalAsync var displayName = companyNameIdpAliasData.IsSharedIdp ? null - : await _userProvisioningService.GetIdentityProviderDisplayName(companyNameIdpAliasData.IdpAlias).ConfigureAwait(ConfigureAwaitOptions.None) ?? companyNameIdpAliasData.IdpAlias; + : await _identityProviderProvisioningServcie.GetIdentityProviderDisplayName(companyNameIdpAliasData.IdpAlias).ConfigureAwait(ConfigureAwaitOptions.None) ?? companyNameIdpAliasData.IdpAlias; var (numCreated, numLines, errors) = await CsvParser.ProcessCsvAsync( stream, @@ -162,7 +166,7 @@ private async ValueTask UploadOwnCompanySharedIdpUsersInterna using var stream = document.OpenReadStream(); var (companyNameIdpAliasData, nameCreatedBy) = await _userProvisioningService.GetCompanyNameSharedIdpAliasData(_identityData.IdentityId).ConfigureAwait(ConfigureAwaitOptions.None); - var displayName = await _userProvisioningService.GetIdentityProviderDisplayName(companyNameIdpAliasData.IdpAlias).ConfigureAwait(ConfigureAwaitOptions.None) ?? companyNameIdpAliasData.IdpAlias; + var displayName = await _identityProviderProvisioningServcie.GetIdentityProviderDisplayName(companyNameIdpAliasData.IdpAlias).ConfigureAwait(ConfigureAwaitOptions.None) ?? companyNameIdpAliasData.IdpAlias; var validRoleData = new List(); diff --git a/src/provisioning/Provisioning.Library/Extensions/IdentityProviderManager.cs b/src/provisioning/Provisioning.Library/Extensions/IdentityProviderManager.cs index abc9dfa569..912c29350e 100644 --- a/src/provisioning/Provisioning.Library/Extensions/IdentityProviderManager.cs +++ b/src/provisioning/Provisioning.Library/Extensions/IdentityProviderManager.cs @@ -143,6 +143,39 @@ public async IAsyncEnumerable GetIdentityProviderMa public async Task GetIdentityProviderDisplayName(string alias) => (await GetCentralIdentityProviderAsync(alias).ConfigureAwait(ConfigureAwaitOptions.None)).DisplayName; + public async Task UpdateOrCreateCentralIdentityProviderOrganisationMapperAsync(string idpAlias, string organisationName) + { + var mapperName = _settings.MappedCompanyAttribute + "-mapper"; + IdentityProviderMapper? mapper; + try + { + mapper = (await _centralIdp.GetIdentityProviderMappersAsync(_settings.CentralRealm, idpAlias).ConfigureAwait(ConfigureAwaitOptions.None)) + .SingleOrDefault(z => z.Name == mapperName); + } + catch (InvalidOperationException) + { + throw new KeycloakEntityConflictException($"idp {idpAlias} attribute-mapper {mapperName} is ambigous in keycloak"); + } + if (mapper is null) + { + await CreateCentralIdentityProviderOrganisationMapperAsync(idpAlias, organisationName); + } + else + { + mapper.Config ??= new Dictionary + { + ["syncMode"] = "INHERIT", + ["attribute"] = _settings.MappedCompanyAttribute, + }; + mapper.Config["attribute.value"] = organisationName; + await _centralIdp.UpdateIdentityProviderMapperAsync( + _settings.CentralRealm, + idpAlias, + mapper.Id ?? throw new KeycloakEntityConflictException($"idp {idpAlias} attribute-mapper {mapperName} has no Id"), + mapper).ConfigureAwait(ConfigureAwaitOptions.None); + } + } + private async ValueTask GetCentralBrokerEndpointOIDCAsync(string alias) { var openidconfig = await _centralIdp.GetOpenIDConfigurationAsync(_settings.CentralRealm).ConfigureAwait(ConfigureAwaitOptions.None); diff --git a/src/provisioning/Provisioning.Library/IProvisioningManager.cs b/src/provisioning/Provisioning.Library/IProvisioningManager.cs index 39435fa187..6cfdd64475 100644 --- a/src/provisioning/Provisioning.Library/IProvisioningManager.cs +++ b/src/provisioning/Provisioning.Library/IProvisioningManager.cs @@ -72,4 +72,5 @@ public interface IProvisioningManager Task GetIdentityProviderDisplayName(string alias); Task DeleteSharedRealmAsync(string alias); Task DeleteIdpSharedServiceAccount(string alias); + Task UpdateOrCreateCentralIdentityProviderOrganisationMapperAsync(string idpAlias, string organisationName); } diff --git a/src/provisioning/Provisioning.Library/Service/IIdentityProviderProvisioningService.cs b/src/provisioning/Provisioning.Library/Service/IIdentityProviderProvisioningService.cs new file mode 100644 index 0000000000..8fe881c94e --- /dev/null +++ b/src/provisioning/Provisioning.Library/Service/IIdentityProviderProvisioningService.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.Provisioning.Library.Service; + +public interface IIdentityProviderProvisioningService +{ + Task GetIdentityProviderDisplayName(string idpAlias); + Task UpdateCompanyNameInSharedIdentityProvider(Guid companyId, string companyName); +} diff --git a/src/provisioning/Provisioning.Library/Service/IUserProvisioningService.cs b/src/provisioning/Provisioning.Library/Service/IUserProvisioningService.cs index b40bbcff84..ce82112e0e 100644 --- a/src/provisioning/Provisioning.Library/Service/IUserProvisioningService.cs +++ b/src/provisioning/Provisioning.Library/Service/IUserProvisioningService.cs @@ -31,7 +31,6 @@ public interface IUserProvisioningService Task HandleCentralKeycloakCreation(UserCreationRoleDataIdpInfo user, Guid companyUserId, string companyName, string? businessPartnerNumber, Identity? identity, IEnumerable identityProviderLinks, IUserRepository userRepository, IUserRolesRepository userRolesRepository); Task<(CompanyNameIdpAliasData IdpAliasData, string NameCreatedBy)> GetCompanyNameIdpAliasData(Guid identityProviderId, Guid companyUserId); Task<(CompanyNameIdpAliasData IdpAliasData, string NameCreatedBy)> GetCompanyNameSharedIdpAliasData(Guid companyUserId, Guid? applicationId = null); - Task GetIdentityProviderDisplayName(string idpAlias); IAsyncEnumerable GetRoleDatas(IEnumerable clientRoles); Task> GetOwnCompanyPortalRoleDatas(string clientId, IEnumerable roles, Guid companyId); Task<(Identity? Identity, Guid CompanyUserId)> GetOrCreateCompanyUser(IUserRepository userRepository, string alias, UserCreationRoleDataIdpInfo user, Guid companyId, Guid identityProviderId, string? businessPartnerNumber); diff --git a/src/provisioning/Provisioning.Library/Service/IdentityProviderProvisioningService.cs b/src/provisioning/Provisioning.Library/Service/IdentityProviderProvisioningService.cs new file mode 100644 index 0000000000..cb1f570ee3 --- /dev/null +++ b/src/provisioning/Provisioning.Library/Service/IdentityProviderProvisioningService.cs @@ -0,0 +1,37 @@ +/******************************************************************************** + * 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 + ********************************************************************************/ + +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; + +namespace Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library.Service; + +public class IdentityProviderProvisioningService(IPortalRepositories portalRepositories, IProvisioningManager provisioningManager) : IIdentityProviderProvisioningService +{ + public Task GetIdentityProviderDisplayName(string idpAlias) => + provisioningManager.GetCentralIdentityProviderDisplayName(idpAlias); + + public async Task UpdateCompanyNameInSharedIdentityProvider(Guid companyId, string companyName) + { + var idpAlias = await portalRepositories.GetInstance().GetSharedIdentityProviderIamAliasDataUntrackedAsync(companyId).ConfigureAwait(false) ?? throw new ConflictException($"company {companyId} is not associated with any shared idp"); + await provisioningManager.UpdateSharedIdentityProviderAsync(idpAlias, companyName).ConfigureAwait(false); + await provisioningManager.UpdateOrCreateCentralIdentityProviderOrganisationMapperAsync(idpAlias, companyName).ConfigureAwait(ConfigureAwaitOptions.None); + } +} diff --git a/src/provisioning/Provisioning.Library/Service/UserProvisioningService.cs b/src/provisioning/Provisioning.Library/Service/UserProvisioningService.cs index dcccba985c..6e29e4ee04 100644 --- a/src/provisioning/Provisioning.Library/Service/UserProvisioningService.cs +++ b/src/provisioning/Provisioning.Library/Service/UserProvisioningService.cs @@ -247,9 +247,6 @@ private Task CreateSharedIdpUserOrReturnUserId(UserCreationRoleDataIdpIn return (new CompanyNameIdpAliasData(company.CompanyId, company.CompanyName, company.BusinessPartnerNumber, idpAlias.Alias, idpAlias.IdentityProviderId, true), createdByName); } - public Task GetIdentityProviderDisplayName(string idpAlias) => - _provisioningManager.GetCentralIdentityProviderDisplayName(idpAlias); - private async Task ValidateDuplicateIdpUsersAsync(IUserRepository userRepository, string alias, UserCreationRoleDataIdpInfo user, Guid companyId) { var existingCompanyUserId = Guid.Empty; diff --git a/src/registration/Registration.Service/BusinessLogic/RegistrationBusinessLogic.cs b/src/registration/Registration.Service/BusinessLogic/RegistrationBusinessLogic.cs index a09dd3c680..717a41273b 100644 --- a/src/registration/Registration.Service/BusinessLogic/RegistrationBusinessLogic.cs +++ b/src/registration/Registration.Service/BusinessLogic/RegistrationBusinessLogic.cs @@ -48,6 +48,7 @@ public class RegistrationBusinessLogic( IOptions settings, IBpnAccess bpnAccess, IUserProvisioningService userProvisioningService, + IIdentityProviderProvisioningService identityProviderProvisioningService, ILogger logger, IPortalRepositories portalRepositories, IApplicationChecklistCreationService checklistService, @@ -254,7 +255,7 @@ await companyDetails.ValidateDatabaseData( var companyRepository = portalRepositories.GetInstance(); var companyApplicationData = await GetAndValidateApplicationData(applicationId, companyDetails, applicationRepository).ConfigureAwait(ConfigureAwaitOptions.None); - + var existingCompanyName = companyApplicationData.Name; var addressId = CreateOrModifyAddress(companyApplicationData, companyDetails, companyRepository); ModifyCompany(addressId, companyApplicationData, companyDetails, companyRepository); @@ -262,7 +263,10 @@ await companyDetails.ValidateDatabaseData( companyRepository.CreateUpdateDeleteIdentifiers(companyDetails.CompanyId, companyApplicationData.UniqueIds, companyDetails.UniqueIds.Select(x => (x.UniqueIdentifierId, x.Value))); UpdateApplicationStatus(applicationId, companyApplicationData.ApplicationStatusId, UpdateApplicationSteps.CompanyWithAddress, applicationRepository, dateTimeProvider); - + if (existingCompanyName != companyDetails.Name) + { + await identityProviderProvisioningService.UpdateCompanyNameInSharedIdentityProvider(_identityData.CompanyId, companyDetails.Name).ConfigureAwait(ConfigureAwaitOptions.None); + } await portalRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None); } @@ -409,7 +413,7 @@ private async Task InviteNewUserInternalAsync(Guid applicationId, UserCreat var modified = await portalRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None); - var companyDisplayName = await userProvisioningService.GetIdentityProviderDisplayName(companyNameIdpAliasData.IdpAlias).ConfigureAwait(ConfigureAwaitOptions.None) ?? companyNameIdpAliasData.IdpAlias; + var companyDisplayName = await identityProviderProvisioningService.GetIdentityProviderDisplayName(companyNameIdpAliasData.IdpAlias).ConfigureAwait(ConfigureAwaitOptions.None) ?? companyNameIdpAliasData.IdpAlias; var mailParameters = ImmutableDictionary.CreateRange(new[] { KeyValuePair.Create("password", password), diff --git a/tests/administration/Administration.Service.Tests/BusinessLogic/UserBusinessLogicTests.cs b/tests/administration/Administration.Service.Tests/BusinessLogic/UserBusinessLogicTests.cs index c8880aa92b..88f8221d45 100644 --- a/tests/administration/Administration.Service.Tests/BusinessLogic/UserBusinessLogicTests.cs +++ b/tests/administration/Administration.Service.Tests/BusinessLogic/UserBusinessLogicTests.cs @@ -46,6 +46,7 @@ public class UserBusinessLogicTests private readonly IFixture _fixture; private readonly IProvisioningManager _provisioningManager; private readonly IUserProvisioningService _userProvisioningService; + private readonly IIdentityProviderProvisioningService _identityProviderProvisioningService; private readonly IPortalRepositories _portalRepositories; private readonly IIdentityProviderRepository _identityProviderRepository; private readonly INotificationRepository _notificationRepository; @@ -92,6 +93,7 @@ public UserBusinessLogicTests() _provisioningManager = A.Fake(); _userProvisioningService = A.Fake(); + _identityProviderProvisioningService = A.Fake(); _portalRepositories = A.Fake(); _identityProviderRepository = A.Fake(); _userRepository = A.Fake(); @@ -167,6 +169,7 @@ public async Task TestUserCreationAllSuccess() var sut = new UserBusinessLogic( null!, _userProvisioningService, + _identityProviderProvisioningService, null!, _portalRepositories, _identityService, @@ -211,6 +214,7 @@ public async Task TestUserCreation_NoUserNameAndEmail_Throws() null!, _userProvisioningService, null!, + null!, _portalRepositories, _identityService, _mailingProcessCreation, @@ -245,6 +249,7 @@ public async Task TestUserCreation_NoRoles_Throws() null!, _userProvisioningService, null!, + null!, _portalRepositories, _identityService, _mailingProcessCreation, @@ -292,6 +297,7 @@ public async Task TestUserCreationCreationError() var sut = new UserBusinessLogic( null!, _userProvisioningService, + _identityProviderProvisioningService, null!, _portalRepositories, _identityService, @@ -349,6 +355,7 @@ public async Task TestUserCreationCreationThrows() var sut = new UserBusinessLogic( null!, _userProvisioningService, + _identityProviderProvisioningService, null!, _portalRepositories, _identityService, @@ -393,6 +400,7 @@ public async Task TestCreateOwnCompanyIdpUserAsyncSuccess() var sut = new UserBusinessLogic( null!, _userProvisioningService, + _identityProviderProvisioningService, null!, _portalRepositories, _identityService, @@ -423,6 +431,7 @@ public async Task TestCreateOwnCompanyIdpUserNoRolesThrowsArgumentException() var sut = new UserBusinessLogic( null!, _userProvisioningService, + _identityProviderProvisioningService, null!, null!, _identityService, @@ -458,6 +467,7 @@ public async Task TestCreateOwnCompanyIdpUserAsyncError() var sut = new UserBusinessLogic( null!, _userProvisioningService, + _identityProviderProvisioningService, null!, null!, _identityService, @@ -490,6 +500,7 @@ public async Task TestCreateOwnCompanyIdpUserAsyncThrows() var sut = new UserBusinessLogic( null!, _userProvisioningService, + _identityProviderProvisioningService, null!, null!, _identityService, @@ -519,6 +530,7 @@ public async Task TestDeleteOwnUserSuccess() _provisioningManager, null!, null!, + null!, _portalRepositories, _identityService, _mailingProcessCreation, @@ -572,6 +584,7 @@ public async Task TestDeleteOwnUserInvalidUserThrows() _provisioningManager, null!, null!, + null!, _portalRepositories, _identityService, _mailingProcessCreation, @@ -604,6 +617,7 @@ public async Task TestDeleteOwnUserInvalidCompanyUserThrows() _provisioningManager, null!, null!, + null!, _portalRepositories, _identityService, _mailingProcessCreation, @@ -981,6 +995,7 @@ public async Task TestDeleteOwnCompanyUsersAsyncSuccess() _provisioningManager, null!, null!, + null!, _portalRepositories, _identityService, _mailingProcessCreation, @@ -1015,6 +1030,7 @@ public async Task TestDeleteOwnCompanyUsersAsyncNoSharedIdpSuccess() _provisioningManager, null!, null!, + null!, _portalRepositories, _identityService, _mailingProcessCreation, @@ -1077,6 +1093,7 @@ public async Task TestDeleteOwnCompanyUsersAsyncError() _provisioningManager, null!, null!, + null!, _portalRepositories, _identityService, _mailingProcessCreation, @@ -1135,6 +1152,7 @@ public async Task TestDeleteOwnCompanyUsersAsyncNoSharedIdpError() _provisioningManager, null!, null!, + null!, _portalRepositories, _identityService, _mailingProcessCreation, @@ -1174,7 +1192,7 @@ public async Task GetOwnCompanyAppUsersAsync_ReturnsExpectedResult() A.CallTo(() => _userRepository.GetOwnCompanyAppUsersPaginationSourceAsync(A._, A._, A>._, A>._, A._)) .Returns((skip, take) => Task.FromResult?>(new Pagination.Source(companyUsers.Count(), companyUsers.Skip(skip).Take(take)))); - var sut = new UserBusinessLogic(null!, null!, null!, _portalRepositories, _identityService, null!, null!, null!, A.Fake>()); + var sut = new UserBusinessLogic(null!, null!, null!, null!, _portalRepositories, _identityService, null!, null!, null!, A.Fake>()); // Act var results = await sut.GetOwnCompanyAppUsersAsync( @@ -1199,7 +1217,7 @@ public async Task GetOwnCompanyAppUsersAsync_SecondPage_ReturnsExpectedResult() A.CallTo(() => _userRepository.GetOwnCompanyAppUsersPaginationSourceAsync(A._, A._, A>._, A>._, A._)) .Returns((skip, take) => Task.FromResult?>(new Pagination.Source(companyUsers.Count(), companyUsers.Skip(skip).Take(take)))); - var sut = new UserBusinessLogic(null!, null!, null!, _portalRepositories, _identityService, null!, null!, null!, A.Fake>()); + var sut = new UserBusinessLogic(null!, null!, null!, null!, _portalRepositories, _identityService, null!, null!, null!, A.Fake>()); // Act var results = await sut.GetOwnCompanyAppUsersAsync( @@ -1229,7 +1247,7 @@ public async Task GetOwnCompanyAppUsersAsync_WithNonExistingCompanyUser_ThrowsNo A.CallTo(() => _userBusinessPartnerRepository.GetOwnCompanyUserWithAssignedBusinessPartnerNumbersAsync(companyUserId, _adminCompanyId, businessPartnerNumber)) .Returns<(bool, bool, bool)>(default); A.CallTo(() => _portalRepositories.GetInstance()).Returns(_userBusinessPartnerRepository); - var sut = new UserBusinessLogic(null!, null!, null!, _portalRepositories, _identityService, null!, null!, null!, A.Fake>()); + var sut = new UserBusinessLogic(null!, null!, null!, null!, _portalRepositories, _identityService, null!, null!, null!, A.Fake>()); // Act async Task Act() => await sut.DeleteOwnUserBusinessPartnerNumbersAsync(companyUserId, businessPartnerNumber); @@ -1250,7 +1268,7 @@ public async Task GetOwnCompanyAppUsersAsync_WithUnassignedBusinessPartner_Throw A.CallTo(() => _userBusinessPartnerRepository.GetOwnCompanyUserWithAssignedBusinessPartnerNumbersAsync(companyUserId, _adminCompanyId, businessPartnerNumber.ToUpper())) .Returns((true, false, false)); A.CallTo(() => _portalRepositories.GetInstance()).Returns(_userBusinessPartnerRepository); - var sut = new UserBusinessLogic(null!, null!, null!, _portalRepositories, _identityService, null!, null!, null!, A.Fake>()); + var sut = new UserBusinessLogic(null!, null!, null!, null!, _portalRepositories, _identityService, null!, null!, null!, A.Fake>()); // Act async Task Act() => await sut.DeleteOwnUserBusinessPartnerNumbersAsync(companyUserId, businessPartnerNumber); @@ -1273,7 +1291,7 @@ public async Task GetOwnCompanyAppUsersAsync_WithoutUserForBpn_ThrowsArgumentExc A.CallTo(() => _userBusinessPartnerRepository.GetOwnCompanyUserWithAssignedBusinessPartnerNumbersAsync(companyUserId, _adminCompanyId, businessPartnerNumber.ToUpper())) .Returns((true, true, true)); A.CallTo(() => _portalRepositories.GetInstance()).Returns(_userBusinessPartnerRepository); - var sut = new UserBusinessLogic(_provisioningManager, null!, null!, _portalRepositories, _identityService, null!, null!, null!, A.Fake>()); + var sut = new UserBusinessLogic(_provisioningManager, null!, null!, null!, _portalRepositories, _identityService, null!, null!, null!, A.Fake>()); // Act async Task Act() => await sut.DeleteOwnUserBusinessPartnerNumbersAsync(companyUserId, businessPartnerNumber); @@ -1294,7 +1312,7 @@ public async Task GetOwnCompanyAppUsersAsync_WithInvalidUser_ThrowsForbiddenExce A.CallTo(() => _userBusinessPartnerRepository.GetOwnCompanyUserWithAssignedBusinessPartnerNumbersAsync(companyUserId, _adminCompanyId, businessPartnerNumber.ToUpper())) .Returns((true, true, false)); A.CallTo(() => _portalRepositories.GetInstance()).Returns(_userBusinessPartnerRepository); - var sut = new UserBusinessLogic(null!, null!, null!, _portalRepositories, _identityService, null!, null!, null!, A.Fake>()); + var sut = new UserBusinessLogic(null!, null!, null!, null!, _portalRepositories, _identityService, null!, null!, null!, A.Fake>()); // Act async Task Act() => await sut.DeleteOwnUserBusinessPartnerNumbersAsync(companyUserId, businessPartnerNumber); @@ -1317,7 +1335,7 @@ public async Task GetOwnCompanyAppUsersAsync_WithValidData_ThrowsForbiddenExcept .Returns((true, true, true)); A.CallTo(() => _portalRepositories.GetInstance()).Returns(_userBusinessPartnerRepository); A.CallTo(() => _provisioningManager.GetUserByUserName(companyUserId.ToString())).Returns(iamUserId); - var sut = new UserBusinessLogic(_provisioningManager, null!, null!, _portalRepositories, _identityService, null!, null!, null!, A.Fake>()); + var sut = new UserBusinessLogic(_provisioningManager, null!, null!, null!, _portalRepositories, _identityService, null!, null!, null!, A.Fake>()); // Act await sut.DeleteOwnUserBusinessPartnerNumbersAsync(companyUserId, businessPartnerNumber.ToUpper()); @@ -1346,7 +1364,7 @@ public async Task GetOwnUserDetails_ReturnsExpected() .Returns(userRoleIds.ToAsyncEnumerable()); A.CallTo(() => _userRepository.GetUserDetailsUntrackedAsync(A._, A>._)) .Returns(companyOwnUserDetails); - var sut = new UserBusinessLogic(_provisioningManager, null!, null!, _portalRepositories, _identityService, null!, _logger, null!, _options); + var sut = new UserBusinessLogic(_provisioningManager, null!, null!, null!, _portalRepositories, _identityService, null!, _logger, null!, _options); // Act var result = await sut.GetOwnUserDetails(); @@ -1375,7 +1393,7 @@ public async Task GetOwnUserDetails_ThrowsNotFoundException() A.CallTo(() => _identity.CompanyId).Returns(companyId); A.CallTo(() => _userRepository.GetUserDetailsUntrackedAsync(userId, A>._)) .Returns(default); - var sut = new UserBusinessLogic(_provisioningManager, null!, null!, _portalRepositories, _identityService, null!, _logger, null!, _options); + var sut = new UserBusinessLogic(_provisioningManager, null!, null!, null!, _portalRepositories, _identityService, null!, _logger, null!, _options); // Act async Task Act() => await sut.GetOwnUserDetails(); @@ -1400,7 +1418,7 @@ public async Task GetOwnCompanyUserDetailsAsync_ReturnsExpected() A.CallTo(() => _userRepository.GetOwnCompanyUserDetailsUntrackedAsync(A._, A._)) .Returns(companyOwnUserDetails); - var sut = new UserBusinessLogic(_provisioningManager, null!, null!, _portalRepositories, _identityService, null!, _logger, null!, _options); + var sut = new UserBusinessLogic(_provisioningManager, null!, null!, null!, _portalRepositories, _identityService, null!, _logger, null!, _options); // Act var result = await sut.GetOwnCompanyUserDetailsAsync(userId); @@ -1426,7 +1444,7 @@ public async Task GetOwnCompanyUserDetailsAsync_ThrowsNotFoundException() A.CallTo(() => _identity.CompanyId).Returns(companyId); A.CallTo(() => _userRepository.GetOwnCompanyUserDetailsUntrackedAsync(A._, A._)) .Returns(default); - var sut = new UserBusinessLogic(_provisioningManager, null!, null!, _portalRepositories, _identityService, null!, _logger, null!, _options); + var sut = new UserBusinessLogic(_provisioningManager, null!, null!, null!, _portalRepositories, _identityService, null!, _logger, null!, _options); // Act async Task Act() => await sut.GetOwnCompanyUserDetailsAsync(userId); @@ -1479,7 +1497,7 @@ public async Task AddOwnCompanyUsersBusinessPartnerNumbers_ReturnsExpected() A.CallTo(() => _provisioningManager.GetUserByUserName(userId.ToString())) .Returns(_iamUserId); - var sut = new UserBusinessLogic(_provisioningManager, null!, null!, _portalRepositories, _identityService, null!, _logger, _bpnAccess, _options); + var sut = new UserBusinessLogic(_provisioningManager, null!, null!, null!, _portalRepositories, _identityService, null!, _logger, _bpnAccess, _options); // Act var result = await sut.AddOwnCompanyUsersBusinessPartnerNumbersAsync(userId, token, businessPartnerNumbers, CancellationToken.None); @@ -1510,7 +1528,7 @@ public async Task AddOwnCompanyUsersBusinessPartnerNumbers_NotFoundException() var token = _fixture.Create(); A.CallTo(() => _userRepository.GetOwnCompanyUserWithAssignedBusinessPartnerNumbersUntrackedAsync(userId, companyId)) .Returns((Enumerable.Empty(), false)); - var sut = new UserBusinessLogic(_provisioningManager, null!, null!, _portalRepositories, _identityService, null!, _logger, _bpnAccess, _options); + var sut = new UserBusinessLogic(_provisioningManager, null!, null!, null!, _portalRepositories, _identityService, null!, _logger, _bpnAccess, _options); // Act async Task Act() => await sut.AddOwnCompanyUsersBusinessPartnerNumbersAsync(userId, token, businessPartnerNumbers, CancellationToken.None); @@ -1533,7 +1551,7 @@ public async Task AddOwnCompanyUsersBusinessPartnerNumbers_ConflictException() .Returns((assignedBusinessPartnerNumbers, true)); A.CallTo(() => _provisioningManager.GetUserByUserName(userId.ToString())) .Returns((string)null!); - var sut = new UserBusinessLogic(_provisioningManager, null!, null!, _portalRepositories, _identityService, null!, _logger, _bpnAccess, _options); + var sut = new UserBusinessLogic(_provisioningManager, null!, null!, null!, _portalRepositories, _identityService, null!, _logger, _bpnAccess, _options); // Act async Task Act() => await sut.AddOwnCompanyUsersBusinessPartnerNumbersAsync(userId, token, businessPartnerNumbers, CancellationToken.None); @@ -1564,7 +1582,7 @@ private void SetupFakesForUserCreation(bool isBulkUserCreation) .ReturnsLazily((CompanyNameIdpAliasData idpAliasData, IAsyncEnumerable userCreationInfos, Action? onSuccess, CancellationToken _) => userCreationInfos.Select(userCreationInfo => _processLine(idpAliasData, userCreationInfo, onSuccess))); - A.CallTo(() => _userProvisioningService.GetIdentityProviderDisplayName(A._)).Returns(_displayName); + A.CallTo(() => _identityProviderProvisioningService.GetIdentityProviderDisplayName(A._)).Returns(_displayName); A.CallTo(() => _processLine(A._, A._, A>._)) .ReturnsLazily((CompanyNameIdpAliasData aliasData, UserCreationRoleDataIdpInfo creationInfo, Action? onSucess) => diff --git a/tests/administration/Administration.Service.Tests/BusinessLogic/UserUploadBusinessLogicTests.cs b/tests/administration/Administration.Service.Tests/BusinessLogic/UserUploadBusinessLogicTests.cs index fdd434b18a..0af2fda6b9 100644 --- a/tests/administration/Administration.Service.Tests/BusinessLogic/UserUploadBusinessLogicTests.cs +++ b/tests/administration/Administration.Service.Tests/BusinessLogic/UserUploadBusinessLogicTests.cs @@ -39,6 +39,7 @@ public class UserUploadBusinessLogicTests { private readonly IFixture _fixture; private readonly IUserProvisioningService _userProvisioningService; + private readonly IIdentityProviderProvisioningService _identityProviderProvisioningService; private readonly IOptions _options; private readonly IFormFile _document; private readonly Guid _identityProviderId; @@ -62,6 +63,7 @@ public UserUploadBusinessLogicTests() _random = new Random(); _userProvisioningService = A.Fake(); + _identityProviderProvisioningService = A.Fake(); _mailingProcessCreation = A.Fake(); _options = A.Fake>(); @@ -94,7 +96,7 @@ public async Task TestSetup() { SetupFakes([HeaderLine()]); - var sut = new UserUploadBusinessLogic(_userProvisioningService, _mailingProcessCreation, _identityService, _errorMessageService, _options); + var sut = new UserUploadBusinessLogic(_userProvisioningService, _identityProviderProvisioningService, _mailingProcessCreation, _identityService, _errorMessageService, _options); var result = await sut.UploadOwnCompanyIdpUsersAsync(_identityProviderId, _document, CancellationToken.None); @@ -120,7 +122,7 @@ public async Task TestUserCreationAllSuccess() NextLine() ]); - var sut = new UserUploadBusinessLogic(_userProvisioningService, _mailingProcessCreation, _identityService, _errorMessageService, _options); + var sut = new UserUploadBusinessLogic(_userProvisioningService, _identityProviderProvisioningService, _mailingProcessCreation, _identityService, _errorMessageService, _options); var result = await sut.UploadOwnCompanyIdpUsersAsync(_identityProviderId, _document, CancellationToken.None); @@ -147,7 +149,7 @@ public async Task TestUserCreationHeaderParsingThrows() NextLine() ]); - var sut = new UserUploadBusinessLogic(_userProvisioningService, _mailingProcessCreation, _identityService, _errorMessageService, _options); + var sut = new UserUploadBusinessLogic(_userProvisioningService, _identityProviderProvisioningService, _mailingProcessCreation, _identityService, _errorMessageService, _options); async Task Act() => await sut.UploadOwnCompanyIdpUsersAsync(_identityProviderId, _document, CancellationToken.None); @@ -180,7 +182,7 @@ public async Task TestUserCreationCreationError() .With(x => x.Error, detailError) .Create()); - var sut = new UserUploadBusinessLogic(_userProvisioningService, _mailingProcessCreation, _identityService, _errorMessageService, _options); + var sut = new UserUploadBusinessLogic(_userProvisioningService, _identityProviderProvisioningService, _mailingProcessCreation, _identityService, _errorMessageService, _options); var result = await sut.UploadOwnCompanyIdpUsersAsync(_identityProviderId, _document, CancellationToken.None); @@ -222,7 +224,7 @@ public async Task TestUserCreationCreationNoRolesError() NextLine() ]); - var sut = new UserUploadBusinessLogic(_userProvisioningService, _mailingProcessCreation, _identityService, _errorMessageService, _options); + var sut = new UserUploadBusinessLogic(_userProvisioningService, _identityProviderProvisioningService, _mailingProcessCreation, _identityService, _errorMessageService, _options); var result = await sut.UploadOwnCompanyIdpUsersAsync(_identityProviderId, _document, CancellationToken.None); @@ -250,7 +252,7 @@ public async Task TestUserCreationParsingError() NextLine() ]); - var sut = new UserUploadBusinessLogic(_userProvisioningService, _mailingProcessCreation, _identityService, _errorMessageService, _options); + var sut = new UserUploadBusinessLogic(_userProvisioningService, _identityProviderProvisioningService, _mailingProcessCreation, _identityService, _errorMessageService, _options); var result = await sut.UploadOwnCompanyIdpUsersAsync(_identityProviderId, _document, CancellationToken.None); @@ -280,7 +282,7 @@ public async Task TestUserCreationCreationThrows() A.CallTo(() => _processLine(A._, A.That.Matches(info => CreationInfoMatches(info, creationInfo)), A>._)) .Throws(_error); - var sut = new UserUploadBusinessLogic(_userProvisioningService, _mailingProcessCreation, _identityService, _errorMessageService, _options); + var sut = new UserUploadBusinessLogic(_userProvisioningService, _identityProviderProvisioningService, _mailingProcessCreation, _identityService, _errorMessageService, _options); var result = await sut.UploadOwnCompanyIdpUsersAsync(_identityProviderId, _document, CancellationToken.None); @@ -304,7 +306,7 @@ public async Task TestSetupSharedIdp() { SetupFakes([HeaderLineSharedIdp()]); - var sut = new UserUploadBusinessLogic(_userProvisioningService, _mailingProcessCreation, _identityService, _errorMessageService, _options); + var sut = new UserUploadBusinessLogic(_userProvisioningService, _identityProviderProvisioningService, _mailingProcessCreation, _identityService, _errorMessageService, _options); var result = await sut.UploadOwnCompanySharedIdpUsersAsync(_document, CancellationToken.None); @@ -328,7 +330,7 @@ public async Task TestUserCreationSharedIdpAllSuccess() NextLineSharedIdp() ]); - var sut = new UserUploadBusinessLogic(_userProvisioningService, _mailingProcessCreation, _identityService, _errorMessageService, _options); + var sut = new UserUploadBusinessLogic(_userProvisioningService, _identityProviderProvisioningService, _mailingProcessCreation, _identityService, _errorMessageService, _options); var result = await sut.UploadOwnCompanySharedIdpUsersAsync(_document, CancellationToken.None); @@ -357,7 +359,7 @@ public async Task TestUserCreationSharedIdpHeaderParsingThrows() NextLineSharedIdp() ]); - var sut = new UserUploadBusinessLogic(_userProvisioningService, _mailingProcessCreation, _identityService, _errorMessageService, _options); + var sut = new UserUploadBusinessLogic(_userProvisioningService, _identityProviderProvisioningService, _mailingProcessCreation, _identityService, _errorMessageService, _options); async Task Act() => await sut.UploadOwnCompanySharedIdpUsersAsync(_document, CancellationToken.None); @@ -383,7 +385,7 @@ public async Task TestUserCreationSharedIdpNoRolesError() NextLineSharedIdp(), ]); - var sut = new UserUploadBusinessLogic(_userProvisioningService, _mailingProcessCreation, _identityService, _errorMessageService, _options); + var sut = new UserUploadBusinessLogic(_userProvisioningService, _identityProviderProvisioningService, _mailingProcessCreation, _identityService, _errorMessageService, _options); var result = await sut.UploadOwnCompanySharedIdpUsersAsync(_document, CancellationToken.None); @@ -425,7 +427,7 @@ public async Task TestUserCreationSharedIdpCreationError() .With(x => x.Error, detailError) .Create()); - var sut = new UserUploadBusinessLogic(_userProvisioningService, _mailingProcessCreation, _identityService, _errorMessageService, _options); + var sut = new UserUploadBusinessLogic(_userProvisioningService, _identityProviderProvisioningService, _mailingProcessCreation, _identityService, _errorMessageService, _options); var result = await sut.UploadOwnCompanySharedIdpUsersAsync(_document, CancellationToken.None); @@ -465,7 +467,7 @@ public async Task TestUserCreationSharedIdpParsingError() NextLineSharedIdp() ]); - var sut = new UserUploadBusinessLogic(_userProvisioningService, _mailingProcessCreation, _identityService, _errorMessageService, _options); + var sut = new UserUploadBusinessLogic(_userProvisioningService, _identityProviderProvisioningService, _mailingProcessCreation, _identityService, _errorMessageService, _options); var result = await sut.UploadOwnCompanySharedIdpUsersAsync(_document, CancellationToken.None); @@ -498,7 +500,7 @@ public async Task TestUserCreationSharedIdpCreationThrows() A.CallTo(() => _processLine(A._, A.That.Matches(info => CreationInfoMatchesSharedIdp(info, creationInfo)), A>._)) .Throws(_error); - var sut = new UserUploadBusinessLogic(_userProvisioningService, _mailingProcessCreation, _identityService, _errorMessageService, _options); + var sut = new UserUploadBusinessLogic(_userProvisioningService, _identityProviderProvisioningService, _mailingProcessCreation, _identityService, _errorMessageService, _options); var result = await sut.UploadOwnCompanySharedIdpUsersAsync(_document, CancellationToken.None); diff --git a/tests/registration/Registration.Service.Tests/BusinessLogic/RegistrationBusinessLogicTest.cs b/tests/registration/Registration.Service.Tests/BusinessLogic/RegistrationBusinessLogicTest.cs index 3e740c9464..1f39af9bb5 100644 --- a/tests/registration/Registration.Service.Tests/BusinessLogic/RegistrationBusinessLogicTest.cs +++ b/tests/registration/Registration.Service.Tests/BusinessLogic/RegistrationBusinessLogicTest.cs @@ -55,6 +55,7 @@ public class RegistrationBusinessLogicTest { private readonly IFixture _fixture; private readonly IUserProvisioningService _userProvisioningService; + private readonly IIdentityProviderProvisioningService _identityProviderProvisioningService; private readonly IInvitationRepository _invitationRepository; private readonly IDocumentRepository _documentRepository; private readonly IUserRepository _userRepository; @@ -91,6 +92,7 @@ public RegistrationBusinessLogicTest() _portalRepositories = A.Fake(); _userProvisioningService = A.Fake(); + _identityProviderProvisioningService = A.Fake(); _invitationRepository = A.Fake(); _documentRepository = A.Fake(); _userRepository = A.Fake(); @@ -158,6 +160,7 @@ public async Task GetClientRolesCompositeAsync_GetsAllRoles() null!, null!, null!, + null!, _portalRepositories, null!, _identityService, @@ -236,6 +239,7 @@ public async Task GetCompanyBpdmDetailDataByBusinessPartnerNumber_WithValidBpn_R bpnAccess, null!, null!, + null!, _portalRepositories, null!, _identityService, @@ -282,6 +286,7 @@ public async Task GetCompanyBpdmDetailDataByBusinessPartnerNumber_WithValidBpn_T null!, null!, null!, + null!, _identityService, _dateTimeProvider, _mailingProcessCreation); @@ -313,6 +318,7 @@ public async Task GetAllApplicationsForUserWithStatus_WithValidUser_GetsAllRoles null!, null!, null!, + null!, _portalRepositories, null!, _identityService, @@ -381,6 +387,7 @@ public async Task GetCompanyWithAddressAsync_WithValidApplication_GetsData() null!, null!, null!, + null!, _portalRepositories, null!, _identityService, @@ -410,6 +417,7 @@ public async Task GetCompanyWithAddressAsync_WithInvalidApplication_ThrowsNotFou null!, null!, null!, + null!, _portalRepositories, null!, _identityService, @@ -439,6 +447,7 @@ public async Task GetCompanyWithAddressAsync_WithInvalidUser_ThrowsForbiddenExce null!, null!, null!, + null!, _portalRepositories, null!, _identityService, @@ -490,6 +499,7 @@ public async Task SetCompanyWithAddressAsync_WithMissingData_ThrowsArgumentExcep null!, null!, null!, + null!, _identityService, _dateTimeProvider, _mailingProcessCreation); @@ -517,6 +527,7 @@ public async Task SetCompanyWithAddressAsync_WithInvalidApplicationId_ThrowsNotF null!, null!, null!, + null!, _portalRepositories, null!, _identityService, @@ -556,6 +567,7 @@ public async Task SetCompanyWithAddressAsync_WithoutCompanyUserId_ThrowsForbidde null!, null!, null!, + null!, _portalRepositories, null!, _identityService, @@ -595,6 +607,7 @@ public async Task SetCompanyWithAddressAsync__WithInvalidBpn_ThrowsControllerArg null!, null!, null!, + null!, _portalRepositories, null!, _identityService, @@ -632,7 +645,70 @@ public async Task SetCompanyWithAddressAsync__WithExistingBpn_ModifiesCompany() var sut = new RegistrationBusinessLogic( _options, null!, + _userProvisioningService, + _identityProviderProvisioningService, + null!, + _portalRepositories, + null!, + _identityService, + _dateTimeProvider, + _mailingProcessCreation); + + var existingData = _fixture.Build() + .With(x => x.IsUserOfCompany, true) + .Create(); + + A.CallTo(() => _applicationRepository.GetCompanyApplicationDetailDataAsync(applicationId, A._, companyId)) + .Returns(existingData); + + A.CallTo(() => _companyRepository.AttachAndModifyCompany(A._, A>._, A>._)) + .Invokes((Guid companyId, Action? initialize, Action modify) => + { + company = new Company(companyId, null!, default, default); + initialize?.Invoke(company); + modify(company); + }); + + // Act + await sut.SetCompanyDetailDataAsync(applicationId, companyData); + + // Assert + A.CallTo(() => _companyRepository.AttachAndModifyCompany(A._, A>._, A>._)) + .MustHaveHappenedOnceExactly(); + A.CallTo(() => _portalRepositories.SaveAsync()).MustHaveHappenedOnceExactly(); + + company.Should().NotBeNull(); + company.Should().Match(c => + c.Id == companyId && + c.Name == companyData.Name && + c.Shortname == companyData.ShortName && + c.BusinessPartnerNumber == companyData.BusinessPartnerNumber); + } + + [Fact] + public async Task SetCompanyWithAddressAsync__WithCompanyNameChange_ModifiesCompany() + { + //Arrange + var applicationId = Guid.NewGuid(); + var companyId = Guid.NewGuid(); + var identityData = A.Fake(); + Company? company = null; + A.CallTo(() => identityData.IdentityId).Returns(Guid.NewGuid()); + A.CallTo(() => identityData.IdentityTypeId).Returns(IdentityTypeId.COMPANY_USER); + A.CallTo(() => identityData.CompanyId).Returns(companyId); + A.CallTo(() => _identityService.IdentityData).Returns(identityData); + var companyData = _fixture.Build() + .With(x => x.Name, "Test Company Updated Name") + .With(x => x.BusinessPartnerNumber, "BPNL00000001TEST") + .With(x => x.CompanyId, companyId) + .With(x => x.CountryAlpha2Code, _alpha2code) + .Create(); + + var sut = new RegistrationBusinessLogic( + _options, null!, + _userProvisioningService, + _identityProviderProvisioningService, null!, _portalRepositories, null!, @@ -642,6 +718,7 @@ public async Task SetCompanyWithAddressAsync__WithExistingBpn_ModifiesCompany() var existingData = _fixture.Build() .With(x => x.IsUserOfCompany, true) + .With(x => x.Name, "Test Company") .Create(); A.CallTo(() => _applicationRepository.GetCompanyApplicationDetailDataAsync(applicationId, A._, companyId)) @@ -662,6 +739,71 @@ public async Task SetCompanyWithAddressAsync__WithExistingBpn_ModifiesCompany() A.CallTo(() => _companyRepository.AttachAndModifyCompany(A._, A>._, A>._)) .MustHaveHappenedOnceExactly(); A.CallTo(() => _portalRepositories.SaveAsync()).MustHaveHappenedOnceExactly(); + A.CallTo(() => _identityProviderProvisioningService.UpdateCompanyNameInSharedIdentityProvider(identityData.CompanyId, companyData.Name)).MustHaveHappenedOnceExactly(); + + company.Should().NotBeNull(); + company.Should().Match(c => + c.Id == companyId && + c.Name == companyData.Name && + c.Shortname == companyData.ShortName && + c.BusinessPartnerNumber == companyData.BusinessPartnerNumber); + } + + [Fact] + public async Task SetCompanyWithAddressAsync__WithoutCompanyNameChange_ModifiesCompany() + { + //Arrange + var applicationId = Guid.NewGuid(); + var companyId = Guid.NewGuid(); + var identityData = A.Fake(); + Company? company = null; + A.CallTo(() => identityData.IdentityId).Returns(Guid.NewGuid()); + A.CallTo(() => identityData.IdentityTypeId).Returns(IdentityTypeId.COMPANY_USER); + A.CallTo(() => identityData.CompanyId).Returns(companyId); + A.CallTo(() => _identityService.IdentityData).Returns(identityData); + var companyData = _fixture.Build() + .With(x => x.Name, "Test Company") + .With(x => x.BusinessPartnerNumber, "BPNL00000001TEST") + .With(x => x.CompanyId, companyId) + .With(x => x.CountryAlpha2Code, _alpha2code) + .Create(); + + var sut = new RegistrationBusinessLogic( + _options, + null!, + _userProvisioningService, + _identityProviderProvisioningService, + null!, + _portalRepositories, + null!, + _identityService, + _dateTimeProvider, + _mailingProcessCreation); + + var existingData = _fixture.Build() + .With(x => x.IsUserOfCompany, true) + .With(x => x.Name, "Test Company") + .Create(); + + A.CallTo(() => _applicationRepository.GetCompanyApplicationDetailDataAsync(applicationId, A._, companyId)) + .Returns(existingData); + + A.CallTo(() => _companyRepository.AttachAndModifyCompany(A._, A>._, A>._)) + .Invokes((Guid companyId, Action? initialize, Action modify) => + { + company = new Company(companyId, null!, default, default); + initialize?.Invoke(company); + modify(company); + }); + + // Act + await sut.SetCompanyDetailDataAsync(applicationId, companyData); + + // Assert + A.CallTo(() => _companyRepository.AttachAndModifyCompany(A._, A>._, A>._)) + .MustHaveHappenedOnceExactly(); + A.CallTo(() => _portalRepositories.SaveAsync()).MustHaveHappenedOnceExactly(); + A.CallTo(() => _identityProviderProvisioningService.UpdateCompanyNameInSharedIdentityProvider(identityData.CompanyId, companyData.Name)).MustNotHaveHappened(); company.Should().NotBeNull(); company.Should().Match(c => @@ -700,7 +842,8 @@ public async Task SetCompanyWithAddressAsync_ModifyCompany(string? bpn) var sut = new RegistrationBusinessLogic( _options, null!, - null!, + _userProvisioningService, + _identityProviderProvisioningService, null!, _portalRepositories, null!, @@ -776,7 +919,8 @@ public async Task SetCompanyWithAddressAsync_WithoutInitialCompanyAddress_Create var sut = new RegistrationBusinessLogic( _options, null!, - null!, + _userProvisioningService, + _identityProviderProvisioningService, null!, _portalRepositories, null!, @@ -865,7 +1009,8 @@ public async Task SetCompanyWithAddressAsync_WithInitialCompanyAddress_ModifyAdd var sut = new RegistrationBusinessLogic( _options, null!, - null!, + _userProvisioningService, + _identityProviderProvisioningService, null!, _portalRepositories, null!, @@ -974,7 +1119,8 @@ public async Task SetCompanyWithAddressAsync_WithUniqueIdentifiers_CreateModifyD var sut = new RegistrationBusinessLogic( _options, null!, - null!, + _userProvisioningService, + _identityProviderProvisioningService, null!, _portalRepositories, null!, @@ -1045,6 +1191,7 @@ public async Task SetCompanyWithAddressAsync_WithInvalidCountryCode_Throws() null!, null!, null!, + null!, _portalRepositories, null!, _identityService, @@ -1087,6 +1234,7 @@ public async Task SetCompanyWithAddressAsync_WithInvalidUniqueIdentifiers_Throws null!, null!, null!, + null!, _portalRepositories, null!, _identityService, @@ -1125,6 +1273,7 @@ public async Task SetOwnCompanyApplicationStatusAsync_WithInvalidStatus_ThrowsCo null!, null!, null!, + null!, _portalRepositories, null!, _identityService, @@ -1154,6 +1303,7 @@ public async Task SetOwnCompanyApplicationStatusAsync_WithInvalidApplication_Thr null!, null!, null!, + null!, _portalRepositories, null!, _identityService, @@ -1186,6 +1336,7 @@ public async Task SetOwnCompanyApplicationStatusAsync_WithInvalidStatus_ThrowsAr null!, null!, null!, + null!, _portalRepositories, null!, _identityService, @@ -1242,6 +1393,7 @@ public async Task SetOwnCompanyApplicationStatusAsync_WithValidData_SavesChanges null!, null!, null!, + null!, _portalRepositories, null!, _identityService, @@ -1286,6 +1438,7 @@ public async Task GetCompanyRolesAsync_() null!, null!, null!, + null!, _portalRepositories, null!, _identityService, @@ -1374,6 +1527,7 @@ public async Task UploadDocumentAsync_WithValidData_CreatesDocument() null!, null!, null!, + null!, _portalRepositories, null!, _identityService, @@ -1437,6 +1591,7 @@ public async Task UploadDocumentAsync_WithNotExistingApplicationId_ThrowsExcepti null!, null!, null!, + null!, _portalRepositories, null!, _identityService, @@ -1472,6 +1627,7 @@ public async Task UploadDocumentAsync_WithNotExistingIamUser_ThrowsException() null!, null!, null!, + null!, _portalRepositories, null!, _identityService, @@ -1505,6 +1661,7 @@ public async Task UploadDocumentAsync_WithInvalidDocumentTypeId_ThrowsException( null!, null!, null!, + null!, _portalRepositories, null!, _identityService, @@ -1544,6 +1701,7 @@ public async Task TestInviteNewUserAsyncSuccess() _options, null!, _userProvisioningService, + _identityProviderProvisioningService, null!, _portalRepositories, null!, @@ -1577,6 +1735,7 @@ public async Task TestInviteNewUserEmptyEmailThrows() _options, null!, _userProvisioningService, + _identityProviderProvisioningService, null!, _portalRepositories, null!, @@ -1607,6 +1766,7 @@ public async Task TestInviteNewUserUserAlreadyExistsThrows() _options, null!, _userProvisioningService, + _identityProviderProvisioningService, null!, _portalRepositories, null!, @@ -1642,6 +1802,7 @@ public async Task TestInviteNewUserAsyncCreationErrorThrows() _options, null!, _userProvisioningService, + _identityProviderProvisioningService, null!, _portalRepositories, null!, @@ -1682,6 +1843,7 @@ public async Task GetUploadedDocumentsAsync_ReturnsExpectedOutput() null!, null!, null!, + null!, _portalRepositories, null!, _identityService, @@ -1712,6 +1874,7 @@ public async Task GetUploadedDocumentsAsync_InvalidApplication_ThrowsNotFound() null!, null!, null!, + null!, _portalRepositories, null!, _identityService, @@ -1743,6 +1906,7 @@ public async Task GetUploadedDocumentsAsync_InvalidUser_ThrowsForbidden() null!, null!, null!, + null!, _portalRepositories, null!, _identityService, @@ -1769,7 +1933,7 @@ public async Task SubmitRoleConsentsAsync_WithNotExistingApplication_ThrowsNotFo var notExistingId = _fixture.Create(); A.CallTo(() => _companyRolesRepository.GetCompanyRoleAgreementConsentDataAsync(notExistingId)) .Returns(null); - var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); + var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); // Act Task Act() => sut.SubmitRoleConsentAsync(notExistingId, _fixture.Create()); @@ -1788,7 +1952,7 @@ public async Task SubmitRoleConsentsAsync_WithWrongCompanyUser_ThrowsForbiddenEx var data = new CompanyRoleAgreementConsentData(Guid.NewGuid(), applicationStatusId, _fixture.CreateMany(2), _fixture.CreateMany(5)); A.CallTo(() => _companyRolesRepository.GetCompanyRoleAgreementConsentDataAsync(applicationId)) .Returns(data); - var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); + var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); // Act Task Act() => sut.SubmitRoleConsentAsync(applicationId, _fixture.Create()); @@ -1817,7 +1981,7 @@ public async Task SubmitRoleConsentsAsync_WithInvalidRoles_ThrowsControllerArgum .Returns(data); A.CallTo(() => _companyRolesRepository.GetAgreementAssignedCompanyRolesUntrackedAsync(roleIds)) .Returns(companyRoleAssignedAgreements.ToAsyncEnumerable()); - var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); + var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); // Act Task Act() => sut.SubmitRoleConsentAsync(applicationId, _fixture.Create()); @@ -1853,7 +2017,7 @@ public async Task SubmitRoleConsentsAsync_WithoutAllRolesConsentGiven_ThrowsCont A.CallTo(() => _companyRolesRepository.GetAgreementAssignedCompanyRolesUntrackedAsync(A>._)) .Returns(companyRoleAssignedAgreements.ToAsyncEnumerable()); - var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); + var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); // Act Task Act() => sut.SubmitRoleConsentAsync(applicationId, consents); @@ -1935,7 +2099,7 @@ public async Task SubmitRoleConsentsAsync_WithValidData_CallsExpected() removedCompanyRoleIds = companyRoleIds; }); - var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); + var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); // Act await sut.SubmitRoleConsentAsync(applicationId, consents); @@ -1988,7 +2152,7 @@ public async Task SubmitRoleConsentsAsync_WithextraAgreement_ThrowsControllerArg A.CallTo(() => _companyRolesRepository.GetAgreementAssignedCompanyRolesUntrackedAsync(A>._)) .Returns(companyRoleAssignedAgreements.ToAsyncEnumerable()); - var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); + var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); // Act Task Act() => sut.SubmitRoleConsentAsync(applicationId, consents); @@ -2015,7 +2179,7 @@ public async Task SubmitRegistrationAsync_WithNotExistingApplication_ThrowsNotFo }; A.CallTo(() => _applicationRepository.GetOwnCompanyApplicationUserEmailDataAsync(A._, A._, A>._)) .Returns(null); - var sut = new RegistrationBusinessLogic(Options.Create(settings), null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); + var sut = new RegistrationBusinessLogic(Options.Create(settings), null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); // Act Task Act() => sut.SubmitRegistrationAsync(notExistingId); @@ -2105,7 +2269,7 @@ public async Task SubmitRegistrationAsync_WithDocumentId_Success() DocumentTypeId.COMMERCIAL_REGISTER_EXTRACT ] }; - var sut = new RegistrationBusinessLogic(Options.Create(settings), null!, null!, null!, _portalRepositories, _checklistService, _identityService, _dateTimeProvider, _mailingProcessCreation); + var sut = new RegistrationBusinessLogic(Options.Create(settings), null!, null!, null!, null!, _portalRepositories, _checklistService, _identityService, _dateTimeProvider, _mailingProcessCreation); // Act await sut.SubmitRegistrationAsync(applicationId); @@ -2196,7 +2360,7 @@ public async Task SubmitRegistrationAsync_InvalidStatus_ThrowsForbiddenException var companyData = new CompanyData("Test Company", Guid.NewGuid(), "Strabe Street", "Munich", "Germany", uniqueIds, companyRoleIds); A.CallTo(() => _applicationRepository.GetOwnCompanyApplicationUserEmailDataAsync(A._, A._, A>._)) .Returns(new CompanyApplicationUserEmailData(statusId, true, _fixture.Create(), documents, companyData, agreementConsents)); - var sut = new RegistrationBusinessLogic(Options.Create(settings), null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); + var sut = new RegistrationBusinessLogic(Options.Create(settings), null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); // Act Task Act() => sut.SubmitRegistrationAsync(applicationId); @@ -2241,7 +2405,7 @@ public async Task SubmitRegistrationAsync_AlreadyClosed_ThrowsForbiddenException }; A.CallTo(() => _applicationRepository.GetOwnCompanyApplicationUserEmailDataAsync(A._, A._, A>._)) .Returns(new CompanyApplicationUserEmailData(statusId, true, _fixture.Create(), documents, companyData, agreementConsents)); - var sut = new RegistrationBusinessLogic(Options.Create(settings), null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); + var sut = new RegistrationBusinessLogic(Options.Create(settings), null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); // Act Task Act() => sut.SubmitRegistrationAsync(applicationId); @@ -2279,7 +2443,7 @@ public async Task SubmitRegistrationAsync_WithNotExistingCompanyUser_ThrowsForbi }; A.CallTo(() => _applicationRepository.GetOwnCompanyApplicationUserEmailDataAsync(A._, A._, A>._)) .Returns(new CompanyApplicationUserEmailData(CompanyApplicationStatusId.VERIFY, false, null, null!, companyData, agreementConsents)); - var sut = new RegistrationBusinessLogic(Options.Create(settings), null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); + var sut = new RegistrationBusinessLogic(Options.Create(settings), null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); // Act Task Act() => sut.SubmitRegistrationAsync(applicationId); @@ -2317,7 +2481,7 @@ public async Task SubmitRegistrationAsync_WithNotExistingStreetName_ThrowsConfli }; A.CallTo(() => _applicationRepository.GetOwnCompanyApplicationUserEmailDataAsync(applicationId, userId, A>._)) .Returns(new CompanyApplicationUserEmailData(CompanyApplicationStatusId.VERIFY, true, _fixture.Create(), Enumerable.Empty(), companyData, agreementConsents)); - var sut = new RegistrationBusinessLogic(Options.Create(settings), null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); + var sut = new RegistrationBusinessLogic(Options.Create(settings), null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); // Act Task Act() => sut.SubmitRegistrationAsync(applicationId); @@ -2347,7 +2511,7 @@ public async Task SubmitRegistrationAsync_WithNotExistingAddressId_ThrowsConflic var companyData = new CompanyData("Test Company", null, "Strabe Street", "Munich", "Germany", uniqueIds, companyRoleIds); A.CallTo(() => _applicationRepository.GetOwnCompanyApplicationUserEmailDataAsync(applicationId, userId, A>._)) .Returns(new CompanyApplicationUserEmailData(CompanyApplicationStatusId.VERIFY, true, _fixture.Create(), Enumerable.Empty(), companyData, agreementConsents)); - var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); + var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); // Act Task Act() => sut.SubmitRegistrationAsync(applicationId); @@ -2377,7 +2541,7 @@ public async Task SubmitRegistrationAsync_WithNotExistingCompanyName_ThrowsConfl var companyData = new CompanyData(string.Empty, Guid.NewGuid(), "Strabe Street", "Munich", "Germany", uniqueIds, companyRoleIds); A.CallTo(() => _applicationRepository.GetOwnCompanyApplicationUserEmailDataAsync(applicationId, userId, A>._)) .Returns(new CompanyApplicationUserEmailData(CompanyApplicationStatusId.VERIFY, true, _fixture.Create(), Enumerable.Empty(), companyData, agreementConsents)); - var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); + var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); // Act Task Act() => sut.SubmitRegistrationAsync(applicationId); @@ -2407,7 +2571,7 @@ public async Task SubmitRegistrationAsync_WithNotExistingUniqueId_ThrowsConflict var companyData = new CompanyData("Test Company", Guid.NewGuid(), "Strabe Street", "Munich", "Germany", uniqueIdentifierData, companyRoleIds); A.CallTo(() => _applicationRepository.GetOwnCompanyApplicationUserEmailDataAsync(applicationId, userId, A>._)) .Returns(new CompanyApplicationUserEmailData(CompanyApplicationStatusId.VERIFY, true, _fixture.Create(), Enumerable.Empty(), companyData, agreementConsents)); - var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); + var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); // Act Task Act() => sut.SubmitRegistrationAsync(applicationId); @@ -2437,7 +2601,7 @@ public async Task SubmitRegistrationAsync_WithNotExistingCompanyRoleId_ThrowsCon var companyData = new CompanyData("Test Company", Guid.NewGuid(), "Strabe Street", "Munich", "Germany", uniqueIds, companyRoleIdData); A.CallTo(() => _applicationRepository.GetOwnCompanyApplicationUserEmailDataAsync(applicationId, userId, A>._)) .Returns(new CompanyApplicationUserEmailData(CompanyApplicationStatusId.VERIFY, true, _fixture.Create(), Enumerable.Empty(), companyData, agreementConsents)); - var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); + var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); // Act Task Act() => sut.SubmitRegistrationAsync(applicationId); @@ -2464,7 +2628,7 @@ public async Task SubmitRegistrationAsync_WithNotExistingAgreementandConsent_Thr var companyData = new CompanyData("Test Company", Guid.NewGuid(), "Strabe Street", "Munich", "Germany", uniqueIds, companyRoleIds); A.CallTo(() => _applicationRepository.GetOwnCompanyApplicationUserEmailDataAsync(applicationId, userId, A>._)) .Returns(new CompanyApplicationUserEmailData(CompanyApplicationStatusId.VERIFY, true, _fixture.Create(), Enumerable.Empty(), companyData, agreementConsents)); - var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); + var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); // Act Task Act() => sut.SubmitRegistrationAsync(applicationId); @@ -2494,7 +2658,7 @@ public async Task SubmitRegistrationAsync_WithNotExistingCity_ThrowsConflictExce var companyData = new CompanyData("Test Company", Guid.NewGuid(), "Strabe Street", string.Empty, "Germany", uniqueIds, companyRoleIds); A.CallTo(() => _applicationRepository.GetOwnCompanyApplicationUserEmailDataAsync(applicationId, userId, A>._)) .Returns(new CompanyApplicationUserEmailData(CompanyApplicationStatusId.VERIFY, true, _fixture.Create(), Enumerable.Empty(), companyData, agreementConsents)); - var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); + var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); // Act Task Act() => sut.SubmitRegistrationAsync(applicationId); @@ -2525,7 +2689,7 @@ public async Task SubmitRegistrationAsync_WithNotExistingCountry_ThrowsConflictE var companyData = new CompanyData("Test Company", Guid.NewGuid(), "Strabe Street", "Munich", string.Empty, uniqueIds, companyRoleIds); A.CallTo(() => _applicationRepository.GetOwnCompanyApplicationUserEmailDataAsync(applicationId, userId, A>._)) .Returns(new CompanyApplicationUserEmailData(CompanyApplicationStatusId.VERIFY, true, _fixture.Create(), Enumerable.Empty(), companyData, agreementConsents)); - var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); + var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); // Act Task Act() => sut.SubmitRegistrationAsync(applicationId); @@ -2569,7 +2733,7 @@ public async Task SubmitRegistrationAsync_WithUserEmail_SendsMail() { setOptionalFields.Invoke(application); }); - var sut = new RegistrationBusinessLogic(Options.Create(settings), null!, null!, null!, _portalRepositories, _checklistService, _identityService, _dateTimeProvider, _mailingProcessCreation); + var sut = new RegistrationBusinessLogic(Options.Create(settings), null!, null!, null!, null!, _portalRepositories, _checklistService, _identityService, _dateTimeProvider, _mailingProcessCreation); // Act var result = await sut.SubmitRegistrationAsync(applicationId); @@ -2619,7 +2783,7 @@ public async Task SubmitRegistrationAsync_WithoutUserEmail_DoesntSendMail() { setOptionalFields.Invoke(application); }); - var sut = new RegistrationBusinessLogic(Options.Create(settings), null!, null!, A.Fake>(), _portalRepositories, _checklistService, _identityService, _dateTimeProvider, _mailingProcessCreation); + var sut = new RegistrationBusinessLogic(Options.Create(settings), null!, null!, null!, A.Fake>(), _portalRepositories, _checklistService, _identityService, _dateTimeProvider, _mailingProcessCreation); // Act var result = await sut.SubmitRegistrationAsync(applicationId); @@ -2653,6 +2817,7 @@ public async Task GetCompanyIdentifiers_ReturnsExpectedOutput() null!, null!, null!, + null!, _portalRepositories, null!, _identityService, @@ -2684,6 +2849,7 @@ public async Task GetCompanyIdentifiers_InvalidCountry_Throws() null!, null!, null!, + null!, _portalRepositories, null!, _identityService, @@ -2712,7 +2878,7 @@ public async Task GetRegistrationDataAsync_ReturnsExpected() A.CallTo(() => _applicationRepository.GetRegistrationDataUntrackedAsync(_existingApplicationId, _identity.CompanyId, A>._)) .Returns((true, true, data)); - var sut = new RegistrationBusinessLogic(_options, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); + var sut = new RegistrationBusinessLogic(_options, null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); // Act var result = await sut.GetRegistrationDataAsync(_existingApplicationId); @@ -2757,7 +2923,7 @@ public async Task GetRegistrationDataAsync_WithInvalidApplicationId_Throws() A.CallTo(() => _applicationRepository.GetRegistrationDataUntrackedAsync(A._, _identity.CompanyId, A>._)) .Returns((false, false, data)); - var sut = new RegistrationBusinessLogic(_options, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); + var sut = new RegistrationBusinessLogic(_options, null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); // Act Task Act() => sut.GetRegistrationDataAsync(applicationId); @@ -2776,7 +2942,7 @@ public async Task GetRegistrationDataAsync_WithInvalidUser_Throws() A.CallTo(() => _applicationRepository.GetRegistrationDataUntrackedAsync(A._, _identity.CompanyId, A>._)) .Returns((true, false, data)); - var sut = new RegistrationBusinessLogic(_options, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); + var sut = new RegistrationBusinessLogic(_options, null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); // Act Task Act() => sut.GetRegistrationDataAsync(applicationId); @@ -2795,7 +2961,7 @@ public async Task GetRegistrationDataAsync_WithNullData_Throws() A.CallTo(() => _applicationRepository.GetRegistrationDataUntrackedAsync(A._, _identity.CompanyId, A>._)) .Returns((true, true, null)); - var sut = new RegistrationBusinessLogic(_options, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); + var sut = new RegistrationBusinessLogic(_options, null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); // Act Task Act() => sut.GetRegistrationDataAsync(applicationId); @@ -2815,7 +2981,7 @@ public async Task GetRegistrationDocumentAsync_ReturnsExpectedResult() var content = new byte[7]; A.CallTo(() => _documentRepository.GetDocumentAsync(documentId, A>._)) .Returns((content, "test.json", true, MediaTypeId.JSON)); - var sut = new RegistrationBusinessLogic(_options, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); + var sut = new RegistrationBusinessLogic(_options, null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); //Act var result = await sut.GetRegistrationDocumentAsync(documentId); @@ -2834,7 +3000,7 @@ public async Task GetRegistrationDocumentAsync_WithInvalidDocumentTypeId_ThrowsN var content = new byte[7]; A.CallTo(() => _documentRepository.GetDocumentAsync(documentId, A>._)) .Returns((content, "test.json", false, MediaTypeId.JSON)); - var sut = new RegistrationBusinessLogic(_options, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); + var sut = new RegistrationBusinessLogic(_options, null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); //Act Task Act() => sut.GetRegistrationDocumentAsync(documentId); @@ -2851,7 +3017,7 @@ public async Task GetRegistrationDocumentAsync_WithInvalidDocumentId_ThrowsNotFo var documentId = Guid.NewGuid(); A.CallTo(() => _documentRepository.GetDocumentAsync(documentId, A>._)) .Returns<(byte[], string, bool, MediaTypeId)>(default); - var sut = new RegistrationBusinessLogic(_options, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); + var sut = new RegistrationBusinessLogic(_options, null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); //Act Task Act() => sut.GetRegistrationDocumentAsync(documentId); @@ -2873,7 +3039,7 @@ public async Task GetDocumentAsync_WithValidData_ReturnsExpected() .Returns((documentId, true, true, false)); A.CallTo(() => _documentRepository.GetDocumentByIdAsync(documentId)) .Returns(new Document(documentId, content, content, "test.pdf", MediaTypeId.PDF, DateTimeOffset.UtcNow, DocumentStatusId.LOCKED, DocumentTypeId.APP_CONTRACT)); - var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); + var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); // Act var result = await sut.GetDocumentContentAsync(documentId); @@ -2891,7 +3057,7 @@ public async Task GetDocumentAsync_WithoutDocument_ThrowsNotFoundException() var documentId = Guid.NewGuid(); A.CallTo(() => _documentRepository.GetDocumentIdWithCompanyUserCheckAsync(documentId, _identity.IdentityId)) .Returns((Guid.Empty, false, false, false)); - var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); + var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); // Act Task Act() => sut.GetDocumentContentAsync(documentId); @@ -2908,7 +3074,7 @@ public async Task GetDocumentAsync_WithWrongUser_ThrowsForbiddenException() var documentId = Guid.NewGuid(); A.CallTo(() => _documentRepository.GetDocumentIdWithCompanyUserCheckAsync(documentId, _identity.IdentityId)) .Returns((documentId, false, false, false)); - var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); + var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); // Act Task Act() => sut.GetDocumentContentAsync(documentId); @@ -2925,7 +3091,7 @@ public async Task GetDocumentAsync_WithConfirmedApplicationStatus_ThrowsForbidde var documentId = Guid.NewGuid(); A.CallTo(() => _documentRepository.GetDocumentIdWithCompanyUserCheckAsync(documentId, _identity.IdentityId)) .Returns((documentId, true, true, true)); - var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); + var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); // Act Task Act() => sut.GetDocumentContentAsync(documentId); @@ -2962,7 +3128,7 @@ public async Task SetInvitationStatusAsync_ReturnsExpected() }); A.CallTo(() => _portalRepositories.SaveAsync()).Returns(retval); - var sut = new RegistrationBusinessLogic(_options, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); + var sut = new RegistrationBusinessLogic(_options, null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); // Act var result = await sut.SetInvitationStatusAsync(); @@ -2981,7 +3147,7 @@ public async Task SetInvitationStatusAsync_Throws_ForbiddenException() // Arrange A.CallTo(() => _invitationRepository.GetInvitationStatusAsync(A._)) .Returns(null); - var sut = new RegistrationBusinessLogic(_options, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); + var sut = new RegistrationBusinessLogic(_options, null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); //Act Task Act() => sut.SetInvitationStatusAsync(); @@ -3035,7 +3201,7 @@ public async Task DeleteRegistrationDocumentAsync_ReturnsExpected() A.CallTo(() => _documentRepository.GetDocumentDetailsForApplicationUntrackedAsync(documentId, _identity.CompanyId, settings.ApplicationStatusIds)) .Returns((documentId, DocumentStatusId.PENDING, true, DocumentTypeId.CX_FRAME_CONTRACT, false, applicationIds)); - var sut = new RegistrationBusinessLogic(Options.Create(settings), null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); + var sut = new RegistrationBusinessLogic(Options.Create(settings), null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); // Act var result = await sut.DeleteRegistrationDocumentAsync(documentId); @@ -3073,7 +3239,7 @@ public async Task DeleteRegistrationDocumentAsync_DocumentTypeId_ConflictExcepti A.CallTo(() => _documentRepository.GetDocumentDetailsForApplicationUntrackedAsync(documentId, _identity.CompanyId, settings.ApplicationStatusIds)) .Returns((documentId, DocumentStatusId.PENDING, true, DocumentTypeId.CONFORMITY_APPROVAL_BUSINESS_APPS, false, applicationId)); - var sut = new RegistrationBusinessLogic(Options.Create(settings), null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); + var sut = new RegistrationBusinessLogic(Options.Create(settings), null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); // Act Task Act() => sut.DeleteRegistrationDocumentAsync(documentId); @@ -3090,7 +3256,7 @@ public async Task DeleteRegistrationDocumentAsync_Throws_NotFoundException() A.CallTo(() => _documentRepository.GetDocumentDetailsForApplicationUntrackedAsync(A._, _identity.CompanyId, A>._)) .Returns<(Guid, DocumentStatusId, bool, DocumentTypeId, bool, IEnumerable)>(default); - var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); + var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); // Act Task Act() => sut.DeleteRegistrationDocumentAsync(_fixture.Create()); @@ -3121,7 +3287,7 @@ public async Task DeleteRegistrationDocumentAsync_Throws_ConflictException() A.CallTo(() => _documentRepository.GetDocumentDetailsForApplicationUntrackedAsync(A._, _identity.CompanyId, A>._)) .Returns((documentId, DocumentStatusId.PENDING, true, DocumentTypeId.CX_FRAME_CONTRACT, true, applicationId)); - var sut = new RegistrationBusinessLogic(Options.Create(settings), null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); + var sut = new RegistrationBusinessLogic(Options.Create(settings), null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); // Act Task Act() => sut.DeleteRegistrationDocumentAsync(documentId); @@ -3152,7 +3318,7 @@ public async Task DeleteRegistrationDocumentAsync_Throws_ForbiddenException() A.CallTo(() => _documentRepository.GetDocumentDetailsForApplicationUntrackedAsync(A._, _identity.CompanyId, A>._)) .Returns((documentId, DocumentStatusId.PENDING, false, DocumentTypeId.CX_FRAME_CONTRACT, false, applicationId)); - var sut = new RegistrationBusinessLogic(Options.Create(settings), null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); + var sut = new RegistrationBusinessLogic(Options.Create(settings), null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); // Act Task Act() => sut.DeleteRegistrationDocumentAsync(documentId); @@ -3183,7 +3349,7 @@ public async Task DeleteRegistrationDocumentAsync_DocumentStatusId_Throws_Confli A.CallTo(() => _documentRepository.GetDocumentDetailsForApplicationUntrackedAsync(A._, _identity.CompanyId, A>._)) .Returns((documentId, DocumentStatusId.LOCKED, true, DocumentTypeId.CX_FRAME_CONTRACT, false, applicationId)); - var sut = new RegistrationBusinessLogic(Options.Create(settings), null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); + var sut = new RegistrationBusinessLogic(Options.Create(settings), null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); // Act Task Act() => sut.DeleteRegistrationDocumentAsync(documentId); @@ -3197,7 +3363,7 @@ public async Task DeleteRegistrationDocumentAsync_DocumentStatusId_Throws_Confli public async Task DeleteRegistrationDocumentAsync_Throws_ControllerArgumentException() { // Arrange; - var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); + var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider, _mailingProcessCreation); // Act Task Act() => sut.DeleteRegistrationDocumentAsync(default); @@ -3281,7 +3447,7 @@ private void SetupFakesForInvitation() A.CallTo(() => _userProvisioningService.GetRoleDatas(A>._)) .ReturnsLazily((IEnumerable clientRoles) => clientRoles.SelectMany(r => r.UserRoleNames.Select(role => _fixture.Build().With(x => x.UserRoleText, role).Create())).ToAsyncEnumerable()); - A.CallTo(() => _userProvisioningService.GetIdentityProviderDisplayName(A._)).Returns(_displayName); + A.CallTo(() => _identityProviderProvisioningService.GetIdentityProviderDisplayName(A._)).Returns(_displayName); A.CallTo(() => _userProvisioningService.GetCompanyNameSharedIdpAliasData(A._, A._)).Returns( ( @@ -3320,7 +3486,7 @@ public async Task GetApplicationsDeclineData_CallsExpected() ApplicationDeclineStatusIds = [CompanyApplicationStatusId.CREATED] }); - var sut = new RegistrationBusinessLogic(options, null!, null!, null!, _portalRepositories, null!, _identityService, null!, _mailingProcessCreation); + var sut = new RegistrationBusinessLogic(options, null!, null!, null!, null!, _portalRepositories, null!, _identityService, null!, _mailingProcessCreation); // Act var result = await sut.GetApplicationsDeclineData(); @@ -3453,7 +3619,7 @@ public async Task DeclineApplicationRegistrationAsync_CallsExpected() } }); - var sut = new RegistrationBusinessLogic(options, null!, null!, null!, _portalRepositories, null!, _identityService, null!, _mailingProcessCreation); + var sut = new RegistrationBusinessLogic(options, null!, null!, null!, null!, _portalRepositories, null!, _identityService, null!, _mailingProcessCreation); // Act await sut.DeclineApplicationRegistrationAsync(applicationId); @@ -3627,7 +3793,7 @@ public async Task DeclineApplicationRegistrationAsync_ThrowsNotFoundException_Re A.CallTo(() => _applicationRepository.GetDeclineApplicationDataForApplicationId(A._, A._, A>._)) .Returns<(bool, bool, ApplicationDeclineData?)>(default); - var sut = new RegistrationBusinessLogic(options, null!, null!, null!, _portalRepositories, null!, _identityService, null!, _mailingProcessCreation); + var sut = new RegistrationBusinessLogic(options, null!, null!, null!, null!, _portalRepositories, null!, _identityService, null!, _mailingProcessCreation); // Act Task Act() => sut.DeclineApplicationRegistrationAsync(applicationId); From 0cb26c0590ceb40675a035b207c365fc50fd2b17 Mon Sep 17 00:00:00 2001 From: Phil Schneider Date: Fri, 8 Nov 2024 15:52:12 +0100 Subject: [PATCH 3/7] fix: adjust query to get users for role assignment (#1135) Refs: #1134 Reviewed-By: Evelyn Gurschler --- .../Repositories/ApplicationRepository.cs | 2 +- .../ApplicationRepositoryTests.cs | 59 ++++++++++++++----- 2 files changed, 45 insertions(+), 16 deletions(-) diff --git a/src/portalbackend/PortalBackend.DBAccess/Repositories/ApplicationRepository.cs b/src/portalbackend/PortalBackend.DBAccess/Repositories/ApplicationRepository.cs index 6662c60ea2..0cf5d33c14 100644 --- a/src/portalbackend/PortalBackend.DBAccess/Repositories/ApplicationRepository.cs +++ b/src/portalbackend/PortalBackend.DBAccess/Repositories/ApplicationRepository.cs @@ -249,7 +249,7 @@ public IAsyncEnumerable GetInvitedUsersWithoutInitialRol .Select(invitation => invitation.CompanyUser) .Where(companyUser => companyUser!.Identity!.UserStatusId == UserStatusId.ACTIVE && - userRoleIds.Any(x => companyUser.Identity.IdentityAssignedRoles.Select(iar => iar.UserRoleId).Contains(x))) + userRoleIds.Any(x => !companyUser.Identity.IdentityAssignedRoles.Any(iar => iar.UserRoleId == x))) .Select(companyUser => new CompanyInvitedUserData( companyUser!.Id, companyUser.Identity!.IdentityAssignedRoles.Select(companyUserAssignedRole => companyUserAssignedRole.UserRoleId))) diff --git a/tests/portalbackend/PortalBackend.DBAccess.Tests/ApplicationRepositoryTests.cs b/tests/portalbackend/PortalBackend.DBAccess.Tests/ApplicationRepositoryTests.cs index 80ddcb379c..23170fa938 100644 --- a/tests/portalbackend/PortalBackend.DBAccess.Tests/ApplicationRepositoryTests.cs +++ b/tests/portalbackend/PortalBackend.DBAccess.Tests/ApplicationRepositoryTests.cs @@ -28,23 +28,12 @@ namespace Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Tests; -public class ApplicationRepositoryTests : IAssemblyFixture +public class ApplicationRepositoryTests(TestDbFixture testDbFixture) + : IAssemblyFixture { private static readonly Guid SubmittedApplicationWithBpn = new("6b2d1263-c073-4a48-bfaf-704dc154ca9f"); private static readonly Guid ApplicationWithoutBpn = new("4829b64c-de6a-426c-81fc-c0bcf95bcb76"); private static readonly Guid CompanyId = new("2dc4249f-b5ca-4d42-bef1-7a7a950a4f88"); - private readonly IFixture _fixture; - private readonly TestDbFixture _dbTestDbFixture; - - public ApplicationRepositoryTests(TestDbFixture testDbFixture) - { - _fixture = new Fixture().Customize(new AutoFakeItEasyCustomization { ConfigureMembers = true }); - _fixture.Behaviors.OfType().ToList() - .ForEach(b => _fixture.Behaviors.Remove(b)); - - _fixture.Behaviors.Add(new OmitOnRecursionBehavior()); - _dbTestDbFixture = testDbFixture; - } #region GetCompanyUserRoleWithAddressUntrackedAsync @@ -662,15 +651,55 @@ public async Task GetDeclineApplicationForApplicationId_WithInvalidCompanyId_Ret #endregion + #region GetInvitedUsersWithoutInitialRoles + + [Fact] + public async Task GetInvitedUsersWithoutInitialRoles_WithAllRoles_ReturnsEmpty() + { + // Arrange + var userRoles = new[] + { + new Guid("58f897ec-0aad-4588-8ffa-5f45d6638632"), + new Guid("efc20368-9e82-46ff-b88f-6495b9810253"), + new Guid("aabcdfeb-6669-4c74-89f0-19cda090873f") + }; + var sut = await CreateSut().ConfigureAwait(false); + + // Act + var result = await sut.GetInvitedUsersWithoutInitialRoles(SubmittedApplicationWithBpn, userRoles).ToListAsync().ConfigureAwait(false); + + // Assert + result.Should().BeEmpty(); + } + + [Fact] + public async Task GetInvitedUsersWithoutInitialRoles_WithNotExistingRole_ReturnsExpected() + { + // Arrange + var userRoleId = Guid.NewGuid(); + var sut = await CreateSut().ConfigureAwait(false); + + // Act + var result = await sut.GetInvitedUsersWithoutInitialRoles(SubmittedApplicationWithBpn, new[] { userRoleId }).ToListAsync().ConfigureAwait(false); + + // Assert + result.Should().ContainSingle().And.Satisfy(x => + x.CompanyUserId == new Guid("ac1cf001-7fbc-1f2f-817f-bce058020001") && + x.RoleIds.Count() == 3); + } + + #endregion + private async Task<(IApplicationRepository sut, PortalDbContext context)> CreateSutWithContext() { - var context = await _dbTestDbFixture.GetPortalDbContext(); + var context = await testDbFixture.GetPortalDbContext(); var sut = new ApplicationRepository(context); return (sut, context); } + private async Task CreateSut() { - var context = await _dbTestDbFixture.GetPortalDbContext(); + var context = await testDbFixture.GetPortalDbContext(); var sut = new ApplicationRepository(context); return sut; } From 15c845b0f50fbf0e476d5fe838156d3ba9b9fbde Mon Sep 17 00:00:00 2001 From: Phil Schneider Date: Tue, 12 Nov 2024 11:01:15 +0100 Subject: [PATCH 4/7] fix: register IIdentityProviderBusinessLogic (#1145) Refs: #1144 --- .../BusinessLogic/UserUploadBusinessLogic.cs | 8 ++++---- src/administration/Administration.Service/Program.cs | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/administration/Administration.Service/BusinessLogic/UserUploadBusinessLogic.cs b/src/administration/Administration.Service/BusinessLogic/UserUploadBusinessLogic.cs index 0f423923df..ebe1bae377 100644 --- a/src/administration/Administration.Service/BusinessLogic/UserUploadBusinessLogic.cs +++ b/src/administration/Administration.Service/BusinessLogic/UserUploadBusinessLogic.cs @@ -36,7 +36,7 @@ namespace Org.Eclipse.TractusX.Portal.Backend.Administration.Service.BusinessLog public class UserUploadBusinessLogic : IUserUploadBusinessLogic { private readonly IUserProvisioningService _userProvisioningService; - private readonly IIdentityProviderProvisioningService _identityProviderProvisioningServcie; + private readonly IIdentityProviderProvisioningService _identityProviderProvisioningService; private readonly IMailingProcessCreation _mailingProcessCreation; private readonly UserSettings _settings; private readonly IIdentityData _identityData; @@ -60,7 +60,7 @@ public UserUploadBusinessLogic( IOptions settings) { _userProvisioningService = userProvisioningService; - _identityProviderProvisioningServcie = identityProviderProvisioningService; + _identityProviderProvisioningService = identityProviderProvisioningService; _mailingProcessCreation = mailingProcessCreation; _identityData = identityService.IdentityData; _errorMessageService = errorMessageService; @@ -83,7 +83,7 @@ private async ValueTask UploadOwnCompanyIdpUsersInternalAsync var displayName = companyNameIdpAliasData.IsSharedIdp ? null - : await _identityProviderProvisioningServcie.GetIdentityProviderDisplayName(companyNameIdpAliasData.IdpAlias).ConfigureAwait(ConfigureAwaitOptions.None) ?? companyNameIdpAliasData.IdpAlias; + : await _identityProviderProvisioningService.GetIdentityProviderDisplayName(companyNameIdpAliasData.IdpAlias).ConfigureAwait(ConfigureAwaitOptions.None) ?? companyNameIdpAliasData.IdpAlias; var (numCreated, numLines, errors) = await CsvParser.ProcessCsvAsync( stream, @@ -166,7 +166,7 @@ private async ValueTask UploadOwnCompanySharedIdpUsersInterna using var stream = document.OpenReadStream(); var (companyNameIdpAliasData, nameCreatedBy) = await _userProvisioningService.GetCompanyNameSharedIdpAliasData(_identityData.IdentityId).ConfigureAwait(ConfigureAwaitOptions.None); - var displayName = await _identityProviderProvisioningServcie.GetIdentityProviderDisplayName(companyNameIdpAliasData.IdpAlias).ConfigureAwait(ConfigureAwaitOptions.None) ?? companyNameIdpAliasData.IdpAlias; + var displayName = await _identityProviderProvisioningService.GetIdentityProviderDisplayName(companyNameIdpAliasData.IdpAlias).ConfigureAwait(ConfigureAwaitOptions.None) ?? companyNameIdpAliasData.IdpAlias; var validRoleData = new List(); diff --git a/src/administration/Administration.Service/Program.cs b/src/administration/Administration.Service/Program.cs index 33b94cc7d4..115aa00d74 100644 --- a/src/administration/Administration.Service/Program.cs +++ b/src/administration/Administration.Service/Program.cs @@ -55,6 +55,7 @@ await WebAppHelper builder.Services.AddTransient(); builder.Services.AddTransient() + .AddTransient() .AddTransient() .AddTransient() .ConfigureUserSettings(builder.Configuration.GetSection("UserManagement")); From 14e6d1a69c3a8a52810b078ca92b0a338b34c0f6 Mon Sep 17 00:00:00 2001 From: Phil Schneider Date: Wed, 13 Nov 2024 11:51:35 +0100 Subject: [PATCH 5/7] fix: add registration for missing services (#1147) Refs: #1144 Reviewed-By: Evelyn Gurschler --- src/Portal.Backend.sln | 6 ++++++ src/maintenance/Maintenance.App/Program.cs | 12 +++++++++++ .../ProcessIdentityDataDetermination.cs | 20 ++++++++----------- .../Registration.Service/Program.cs | 1 + 4 files changed, 27 insertions(+), 12 deletions(-) diff --git a/src/Portal.Backend.sln b/src/Portal.Backend.sln index 45967dba53..802022cfad 100644 --- a/src/Portal.Backend.sln +++ b/src/Portal.Backend.sln @@ -1678,6 +1678,12 @@ Global {07BDC20D-23DD-4C0E-9C3D-B1D232AF17E3}.Release|x86.Build.0 = Release|Any CPU {D666EADA-770A-42FF-B891-5745F7A6BC2F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D666EADA-770A-42FF-B891-5745F7A6BC2F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D666EADA-770A-42FF-B891-5745F7A6BC2F}.Release|x86.ActiveCfg = Release|Any CPU + {D666EADA-770A-42FF-B891-5745F7A6BC2F}.Release|x86.Build.0 = Release|Any CPU + {D666EADA-770A-42FF-B891-5745F7A6BC2F}.Debug|x86.ActiveCfg = Debug|Any CPU + {D666EADA-770A-42FF-B891-5745F7A6BC2F}.Debug|x86.Build.0 = Debug|Any CPU + {D666EADA-770A-42FF-B891-5745F7A6BC2F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D666EADA-770A-42FF-B891-5745F7A6BC2F}.Release|Any CPU.Build.0 = Release|Any CPU {59E4B63B-BEA2-4CDA-98F0-13962146AEA5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {59E4B63B-BEA2-4CDA-98F0-13962146AEA5}.Debug|Any CPU.Build.0 = Debug|Any CPU {59E4B63B-BEA2-4CDA-98F0-13962146AEA5}.Debug|x64.ActiveCfg = Debug|Any CPU diff --git a/src/maintenance/Maintenance.App/Program.cs b/src/maintenance/Maintenance.App/Program.cs index 91d7cacdc7..4c06841e10 100644 --- a/src/maintenance/Maintenance.App/Program.cs +++ b/src/maintenance/Maintenance.App/Program.cs @@ -21,11 +21,17 @@ using Laraue.EfCoreTriggers.PostgreSql.Extensions; using Microsoft.EntityFrameworkCore; using Org.Eclipse.TractusX.Portal.Backend.Clearinghouse.Library; +using Org.Eclipse.TractusX.Portal.Backend.Custodian.Library; +using Org.Eclipse.TractusX.Portal.Backend.Custodian.Library.BusinessLogic; using Org.Eclipse.TractusX.Portal.Backend.Framework.Logging; +using Org.Eclipse.TractusX.Portal.Backend.Framework.Token; using Org.Eclipse.TractusX.Portal.Backend.Maintenance.App.DependencyInjection; using Org.Eclipse.TractusX.Portal.Backend.Maintenance.App.Services; +using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Auditing; +using Org.Eclipse.TractusX.Portal.Backend.Processes.ApplicationChecklist.Library; +using Org.Eclipse.TractusX.Portal.Backend.Processes.ProcessIdentity; using Org.Eclipse.TractusX.Portal.Backend.Processes.ProcessIdentity.DependencyInjection; using Serilog; @@ -41,8 +47,14 @@ .AddMaintenanceService() .AddConfigurationProcessIdentityIdDetermination(hostContext.Configuration.GetSection("ProcessIdentity")) .AddBatchDelete(hostContext.Configuration.GetSection("BatchDelete")) + .AddTransient() + .AddTransient() + .AddTransient() + .AddTransient() + .AddTransient() .AddClearinghouseService(hostContext.Configuration.GetSection("Clearinghouse")) .AddDbAuditing() + .AddPortalRepositories(hostContext.Configuration) .AddDbContext(o => o.UseNpgsql(hostContext.Configuration.GetConnectionString("PortalDb")) .UsePostgreSqlTriggers()); diff --git a/src/processes/Processes.ProcessIdentity/ProcessIdentityDataDetermination.cs b/src/processes/Processes.ProcessIdentity/ProcessIdentityDataDetermination.cs index cdb46469fd..7468813450 100644 --- a/src/processes/Processes.ProcessIdentity/ProcessIdentityDataDetermination.cs +++ b/src/processes/Processes.ProcessIdentity/ProcessIdentityDataDetermination.cs @@ -24,25 +24,21 @@ namespace Org.Eclipse.TractusX.Portal.Backend.Processes.ProcessIdentity; -public class ProcessIdentityDataDetermination : IProcessIdentityDataDetermination +public class ProcessIdentityDataDetermination( + IPortalRepositories portalRepositories, + IProcessIdentityDataBuilder processIdentityDataBuilder) + : IProcessIdentityDataDetermination { - private readonly IIdentityRepository _identityRepository; - private readonly IProcessIdentityDataBuilder _processIdentityDataBuilder; - - public ProcessIdentityDataDetermination(IPortalRepositories portalRepositories, IProcessIdentityDataBuilder processIdentityDataBuilder) - { - _identityRepository = portalRepositories.GetInstance(); - _processIdentityDataBuilder = processIdentityDataBuilder; - } + private readonly IIdentityRepository _identityRepository = portalRepositories.GetInstance(); /// public async Task GetIdentityData() { (IdentityTypeId IdentityTypeId, Guid CompanyId) identityData; - if ((identityData = await _identityRepository.GetActiveIdentityDataByIdentityId(_processIdentityDataBuilder.IdentityId).ConfigureAwait(ConfigureAwaitOptions.None)) == default) - throw new ConflictException($"Identity {_processIdentityDataBuilder.IdentityId} could not be found"); + if ((identityData = await _identityRepository.GetActiveIdentityDataByIdentityId(processIdentityDataBuilder.IdentityId).ConfigureAwait(ConfigureAwaitOptions.None)) == default) + throw new ConflictException($"Identity {processIdentityDataBuilder.IdentityId} could not be found"); - _processIdentityDataBuilder.AddIdentityData(identityData.IdentityTypeId, identityData.CompanyId); + processIdentityDataBuilder.AddIdentityData(identityData.IdentityTypeId, identityData.CompanyId); } } diff --git a/src/registration/Registration.Service/Program.cs b/src/registration/Registration.Service/Program.cs index 703f18fb59..79edabd770 100644 --- a/src/registration/Registration.Service/Program.cs +++ b/src/registration/Registration.Service/Program.cs @@ -44,6 +44,7 @@ await WebAppHelper builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient() + .AddTransient() .ConfigureRegistrationSettings(builder.Configuration.GetSection("Registration")) .AddTransient(); From 45f4c4e0c4baf01aece120cc9298a0b085c293f1 Mon Sep 17 00:00:00 2001 From: Evelyn Gurschler Date: Wed, 13 Nov 2024 16:11:12 +0100 Subject: [PATCH 6/7] chore(trivy): add options according to TRG 8.04 https://github.com/eclipse-tractusx/portal/issues/467 --- .github/workflows/trivy-main.yml | 44 +++++++++++++++++++++++++++++++- .github/workflows/trivy.yml | 43 +++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 1 deletion(-) diff --git a/.github/workflows/trivy-main.yml b/.github/workflows/trivy-main.yml index 5644c5fd6c..32fcfd43de 100644 --- a/.github/workflows/trivy-main.yml +++ b/.github/workflows/trivy-main.yml @@ -63,6 +63,9 @@ jobs: vuln-type: "os,library" skip-files: "/src/portalbackend/PortalBackend.Migrations/Seeder/Data/documents.consortia.json" timeout: "3600s" + severity: "CRITICAL,HIGH" # While vulnerabilities of all severities are reported in the SARIF output, the exit code and workflow failure are triggered only by these specified severities (CRITICAL or HIGH). + exit-code: "1" # Trivy exits with code 1 if vulnerabilities are found, causing the workflow step to fail. + limit-severities-for-sarif: true - name: Upload Trivy scan results to GitHub Security tab uses: github/codeql-action/upload-sarif@f779452ac5af1c261dce0346a8f964149f49322b # v3.26.13 @@ -95,6 +98,10 @@ jobs: format: "sarif" output: "trivy-results3.sarif" vuln-type: "os,library" + severity: "CRITICAL,HIGH" # While vulnerabilities of all severities are reported in the SARIF output, the exit code and workflow failure are triggered only by these specified severities (CRITICAL or HIGH). + hide-progress: false + exit-code: "1" # Trivy exits with code 1 if vulnerabilities are found, causing the workflow step to fail. + limit-severities-for-sarif: true - name: Upload Trivy scan results to GitHub Security tab if: always() @@ -127,6 +134,10 @@ jobs: format: "sarif" output: "trivy-results4.sarif" vuln-type: "os,library" + severity: "CRITICAL,HIGH" # While vulnerabilities of all severities are reported in the SARIF output, the exit code and workflow failure are triggered only by these specified severities (CRITICAL or HIGH). + hide-progress: false + exit-code: "1" # Trivy exits with code 1 if vulnerabilities are found, causing the workflow step to fail. + limit-severities-for-sarif: true - name: Upload Trivy scan results to GitHub Security tab if: always() @@ -159,6 +170,10 @@ jobs: format: "sarif" output: "trivy-results5.sarif" vuln-type: "os,library" + severity: "CRITICAL,HIGH" # While vulnerabilities of all severities are reported in the SARIF output, the exit code and workflow failure are triggered only by these specified severities (CRITICAL or HIGH). + hide-progress: false + exit-code: "1" # Trivy exits with code 1 if vulnerabilities are found, causing the workflow step to fail. + limit-severities-for-sarif: true - name: Upload Trivy scan results to GitHub Security tab if: always() @@ -191,6 +206,10 @@ jobs: format: "sarif" output: "trivy-results6.sarif" vuln-type: "os,library" + severity: "CRITICAL,HIGH" # While vulnerabilities of all severities are reported in the SARIF output, the exit code and workflow failure are triggered only by these specified severities (CRITICAL or HIGH). + hide-progress: false + exit-code: "1" # Trivy exits with code 1 if vulnerabilities are found, causing the workflow step to fail. + limit-severities-for-sarif: true - name: Upload Trivy scan results to GitHub Security tab if: always() @@ -223,6 +242,10 @@ jobs: format: "sarif" output: "trivy-results7.sarif" vuln-type: "os,library" + severity: "CRITICAL,HIGH" # While vulnerabilities of all severities are reported in the SARIF output, the exit code and workflow failure are triggered only by these specified severities (CRITICAL or HIGH). + hide-progress: false + exit-code: "1" # Trivy exits with code 1 if vulnerabilities are found, causing the workflow step to fail. + limit-severities-for-sarif: true - name: Upload Trivy scan results to GitHub Security tab if: always() @@ -255,6 +278,10 @@ jobs: format: "sarif" output: "trivy-results8.sarif" vuln-type: "os,library" + severity: "CRITICAL,HIGH" # While vulnerabilities of all severities are reported in the SARIF output, the exit code and workflow failure are triggered only by these specified severities (CRITICAL or HIGH). + hide-progress: false + exit-code: "1" # Trivy exits with code 1 if vulnerabilities are found, causing the workflow step to fail. + limit-severities-for-sarif: true - name: Upload Trivy scan results to GitHub Security tab if: always() @@ -287,6 +314,10 @@ jobs: format: "sarif" output: "trivy-results9.sarif" vuln-type: "os,library" + severity: "CRITICAL,HIGH" # While vulnerabilities of all severities are reported in the SARIF output, the exit code and workflow failure are triggered only by these specified severities (CRITICAL or HIGH). + hide-progress: false + exit-code: "1" # Trivy exits with code 1 if vulnerabilities are found, causing the workflow step to fail. + limit-severities-for-sarif: true - name: Upload Trivy scan results to GitHub Security tab if: always() @@ -319,6 +350,10 @@ jobs: format: "sarif" output: "trivy-results10.sarif" vuln-type: "os,library" + severity: "CRITICAL,HIGH" # While vulnerabilities of all severities are reported in the SARIF output, the exit code and workflow failure are triggered only by these specified severities (CRITICAL or HIGH). + hide-progress: false + exit-code: "1" # Trivy exits with code 1 if vulnerabilities are found, causing the workflow step to fail. + limit-severities-for-sarif: true - name: Upload Trivy scan results to GitHub Security tab if: always() @@ -351,7 +386,10 @@ jobs: format: "sarif" output: "trivy-results11.sarif" vuln-type: "os,library" - + severity: "CRITICAL,HIGH" # While vulnerabilities of all severities are reported in the SARIF output, the exit code and workflow failure are triggered only by these specified severities (CRITICAL or HIGH). + hide-progress: false + exit-code: "1" # Trivy exits with code 1 if vulnerabilities are found, causing the workflow step to fail. + limit-severities-for-sarif: true - name: Upload Trivy scan results to GitHub Security tab if: always() uses: github/codeql-action/upload-sarif@f779452ac5af1c261dce0346a8f964149f49322b # v3.26.13 @@ -383,6 +421,10 @@ jobs: format: "sarif" output: "trivy-results12.sarif" vuln-type: "os,library" + severity: "CRITICAL,HIGH" # While vulnerabilities of all severities are reported in the SARIF output, the exit code and workflow failure are triggered only by these specified severities (CRITICAL or HIGH). + hide-progress: false + exit-code: "1" # Trivy exits with code 1 if vulnerabilities are found, causing the workflow step to fail. + limit-severities-for-sarif: true - name: Upload Trivy scan results to GitHub Security tab if: always() diff --git a/.github/workflows/trivy.yml b/.github/workflows/trivy.yml index 3cd3747cc0..440da57e6d 100644 --- a/.github/workflows/trivy.yml +++ b/.github/workflows/trivy.yml @@ -63,6 +63,9 @@ jobs: vuln-type: "os,library" skip-files: "/src/portalbackend/PortalBackend.Migrations/Seeder/Data/documents.consortia.json" timeout: "3600s" + severity: "CRITICAL,HIGH" # While vulnerabilities of all severities are reported in the SARIF output, the exit code and workflow failure are triggered only by these specified severities (CRITICAL or HIGH). + exit-code: "1" # Trivy exits with code 1 if vulnerabilities are found, causing the workflow step to fail. + limit-severities-for-sarif: true - name: Upload Trivy scan results to GitHub Security tab uses: github/codeql-action/upload-sarif@f779452ac5af1c261dce0346a8f964149f49322b # v3.26.13 @@ -95,6 +98,10 @@ jobs: format: "sarif" output: "trivy-results3.sarif" vuln-type: "os,library" + severity: "CRITICAL,HIGH" # While vulnerabilities of all severities are reported in the SARIF output, the exit code and workflow failure are triggered only by these specified severities (CRITICAL or HIGH). + hide-progress: false + exit-code: "1" # Trivy exits with code 1 if vulnerabilities are found, causing the workflow step to fail. + limit-severities-for-sarif: true - name: Upload Trivy scan results to GitHub Security tab if: always() @@ -127,6 +134,10 @@ jobs: format: "sarif" output: "trivy-results4.sarif" vuln-type: "os,library" + severity: "CRITICAL,HIGH" # While vulnerabilities of all severities are reported in the SARIF output, the exit code and workflow failure are triggered only by these specified severities (CRITICAL or HIGH). + hide-progress: false + exit-code: "1" # Trivy exits with code 1 if vulnerabilities are found, causing the workflow step to fail. + limit-severities-for-sarif: true - name: Upload Trivy scan results to GitHub Security tab if: always() @@ -159,6 +170,10 @@ jobs: format: "sarif" output: "trivy-results5.sarif" vuln-type: "os,library" + severity: "CRITICAL,HIGH" # While vulnerabilities of all severities are reported in the SARIF output, the exit code and workflow failure are triggered only by these specified severities (CRITICAL or HIGH). + hide-progress: false + exit-code: "1" # Trivy exits with code 1 if vulnerabilities are found, causing the workflow step to fail. + limit-severities-for-sarif: true - name: Upload Trivy scan results to GitHub Security tab if: always() @@ -191,6 +206,10 @@ jobs: format: "sarif" output: "trivy-results6.sarif" vuln-type: "os,library" + severity: "CRITICAL,HIGH" # While vulnerabilities of all severities are reported in the SARIF output, the exit code and workflow failure are triggered only by these specified severities (CRITICAL or HIGH). + hide-progress: false + exit-code: "1" # Trivy exits with code 1 if vulnerabilities are found, causing the workflow step to fail. + limit-severities-for-sarif: true - name: Upload Trivy scan results to GitHub Security tab if: always() @@ -223,6 +242,10 @@ jobs: format: "sarif" output: "trivy-results7.sarif" vuln-type: "os,library" + severity: "CRITICAL,HIGH" # While vulnerabilities of all severities are reported in the SARIF output, the exit code and workflow failure are triggered only by these specified severities (CRITICAL or HIGH). + hide-progress: false + exit-code: "1" # Trivy exits with code 1 if vulnerabilities are found, causing the workflow step to fail. + limit-severities-for-sarif: true - name: Upload Trivy scan results to GitHub Security tab if: always() @@ -255,6 +278,10 @@ jobs: format: "sarif" output: "trivy-results8.sarif" vuln-type: "os,library" + severity: "CRITICAL,HIGH" # While vulnerabilities of all severities are reported in the SARIF output, the exit code and workflow failure are triggered only by these specified severities (CRITICAL or HIGH). + hide-progress: false + exit-code: "1" # Trivy exits with code 1 if vulnerabilities are found, causing the workflow step to fail. + limit-severities-for-sarif: true - name: Upload Trivy scan results to GitHub Security tab if: always() @@ -287,6 +314,10 @@ jobs: format: "sarif" output: "trivy-results9.sarif" vuln-type: "os,library" + severity: "CRITICAL,HIGH" # While vulnerabilities of all severities are reported in the SARIF output, the exit code and workflow failure are triggered only by these specified severities (CRITICAL or HIGH). + hide-progress: false + exit-code: "1" # Trivy exits with code 1 if vulnerabilities are found, causing the workflow step to fail. + limit-severities-for-sarif: true - name: Upload Trivy scan results to GitHub Security tab if: always() @@ -319,6 +350,10 @@ jobs: format: "sarif" output: "trivy-results10.sarif" vuln-type: "os,library" + severity: "CRITICAL,HIGH" # While vulnerabilities of all severities are reported in the SARIF output, the exit code and workflow failure are triggered only by these specified severities (CRITICAL or HIGH). + hide-progress: false + exit-code: "1" # Trivy exits with code 1 if vulnerabilities are found, causing the workflow step to fail. + limit-severities-for-sarif: true - name: Upload Trivy scan results to GitHub Security tab if: always() @@ -351,6 +386,10 @@ jobs: format: "sarif" output: "trivy-results11.sarif" vuln-type: "os,library" + severity: "CRITICAL,HIGH" # While vulnerabilities of all severities are reported in the SARIF output, the exit code and workflow failure are triggered only by these specified severities (CRITICAL or HIGH). + hide-progress: false + exit-code: "1" # Trivy exits with code 1 if vulnerabilities are found, causing the workflow step to fail. + limit-severities-for-sarif: true - name: Upload Trivy scan results to GitHub Security tab if: always() @@ -383,6 +422,10 @@ jobs: format: "sarif" output: "trivy-results12.sarif" vuln-type: "os,library" + severity: "CRITICAL,HIGH" # While vulnerabilities of all severities are reported in the SARIF output, the exit code and workflow failure are triggered only by these specified severities (CRITICAL or HIGH). + hide-progress: false + exit-code: "1" # Trivy exits with code 1 if vulnerabilities are found, causing the workflow step to fail. + limit-severities-for-sarif: true - name: Upload Trivy scan results to GitHub Security tab if: always() From ab3c230254f1fca1ee4d58c6166da7b7de74b921 Mon Sep 17 00:00:00 2001 From: Evelyn Gurschler Date: Wed, 13 Nov 2024 16:34:36 +0100 Subject: [PATCH 7/7] build(2.3.0-rc2): bump version and update docs --- .tractusx | 10 +++++----- CHANGELOG.md | 13 +++++++++++++ docs/api/administration-service.yaml | 2 +- docs/api/apps-service.yaml | 2 +- docs/api/notifications-service.yaml | 2 +- docs/api/registration-service.yaml | 2 +- docs/api/services-service.yaml | 2 +- src/Directory.Build.props | 2 +- 8 files changed, 24 insertions(+), 11 deletions(-) diff --git a/.tractusx b/.tractusx index 0b15cc7e80..3949d4cdf2 100644 --- a/.tractusx +++ b/.tractusx @@ -19,8 +19,8 @@ leadingRepository: "https://github.com/eclipse-tractusx/portal" openApiSpecs: -- "https://raw.githubusercontent.com/eclipse-tractusx/portal-backend/refs/tags/v2.3.0-RC1/docs/api/administration-service.yaml" -- "https://raw.githubusercontent.com/eclipse-tractusx/portal-backend/refs/tags/v2.3.0-RC1/docs/api/apps-service.yaml" -- "https://raw.githubusercontent.com/eclipse-tractusx/portal-backend/refs/tags/v2.3.0-RC1/docs/api/notifications-service.yaml" -- "https://raw.githubusercontent.com/eclipse-tractusx/portal-backend/refs/tags/v2.3.0-RC1/docs/api/registration-service.yaml" -- "https://raw.githubusercontent.com/eclipse-tractusx/portal-backend/refs/tags/v2.3.0-RC1/docs/api/services-service.yaml" +- "https://raw.githubusercontent.com/eclipse-tractusx/portal-backend/refs/tags/v2.3.0-RC2/docs/api/administration-service.yaml" +- "https://raw.githubusercontent.com/eclipse-tractusx/portal-backend/refs/tags/v2.3.0-RC2/docs/api/apps-service.yaml" +- "https://raw.githubusercontent.com/eclipse-tractusx/portal-backend/refs/tags/v2.3.0-RC2/docs/api/notifications-service.yaml" +- "https://raw.githubusercontent.com/eclipse-tractusx/portal-backend/refs/tags/v2.3.0-RC2/docs/api/registration-service.yaml" +- "https://raw.githubusercontent.com/eclipse-tractusx/portal-backend/refs/tags/v2.3.0-RC2/docs/api/services-service.yaml" diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b550395e8..e454d0f2b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,19 @@ New features, fixed bugs, known defects and other noteworthy changes to each rel ## Unreleased +## 2.3.0-RC2 + +### Change + +* **Connectors**: enhanced PUT api/administration/Connectors/{connectorId}/connectorUrl endpoint logic [#1094](https://github.com/eclipse-tractusx/portal-backend/pull/1094) + +### Bugfixes + +* **Application Activation** + * fixed initial roles not being added to invited users [#1135](https://github.com/eclipse-tractusx/portal-backend/pull/1135) +* **Registration** + * fixed company name change not reflecting consistently [#1010](https://github.com/eclipse-tractusx/portal-backend/pull/1010), [#1145](https://github.com/eclipse-tractusx/portal-backend/pull/1145), [#1147](https://github.com/eclipse-tractusx/portal-backend/pull/1147) + ## 2.3.0-RC1 ### Bugfixes diff --git a/docs/api/administration-service.yaml b/docs/api/administration-service.yaml index 892423282c..1f42b23719 100644 --- a/docs/api/administration-service.yaml +++ b/docs/api/administration-service.yaml @@ -1,7 +1,7 @@ openapi: 3.0.1 info: title: Org.Eclipse.TractusX.Portal.Backend.Administration.Service - version: v2.3.0-RC1 + version: v2.3.0-RC2 paths: /api/administration/companydata/ownCompanyDetails: get: diff --git a/docs/api/apps-service.yaml b/docs/api/apps-service.yaml index 648af38be3..4d2f050fec 100644 --- a/docs/api/apps-service.yaml +++ b/docs/api/apps-service.yaml @@ -1,7 +1,7 @@ openapi: 3.0.1 info: title: Org.Eclipse.TractusX.Portal.Backend.Apps.Service - version: v2.3.0-RC1 + version: v2.3.0-RC2 paths: '/api/apps/AppChange/{appId}/role/activeapp': post: diff --git a/docs/api/notifications-service.yaml b/docs/api/notifications-service.yaml index acc9f2e5ed..eb3bd964f6 100644 --- a/docs/api/notifications-service.yaml +++ b/docs/api/notifications-service.yaml @@ -1,7 +1,7 @@ openapi: 3.0.1 info: title: Org.Eclipse.TractusX.Portal.Backend.Notifications.Service - version: v2.3.0-RC1 + version: v2.3.0-RC2 paths: /api/notification/errormessage: get: diff --git a/docs/api/registration-service.yaml b/docs/api/registration-service.yaml index e29f7da194..a8c8c1e072 100644 --- a/docs/api/registration-service.yaml +++ b/docs/api/registration-service.yaml @@ -1,7 +1,7 @@ openapi: 3.0.1 info: title: Org.Eclipse.TractusX.Portal.Backend.Registration.Service - version: v2.3.0-RC1 + version: v2.3.0-RC2 paths: /api/registration/errormessage: get: diff --git a/docs/api/services-service.yaml b/docs/api/services-service.yaml index c585977aed..25a8d05269 100644 --- a/docs/api/services-service.yaml +++ b/docs/api/services-service.yaml @@ -1,7 +1,7 @@ openapi: 3.0.1 info: title: Org.Eclipse.TractusX.Portal.Backend.Services.Service - version: v2.3.0-RC1 + version: v2.3.0-RC2 paths: /api/services/errormessage: get: diff --git a/src/Directory.Build.props b/src/Directory.Build.props index b2ba29daf3..f736243330 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -20,6 +20,6 @@ 2.3.0 - RC1 + RC2