From 32399ecacce0224092ee5e08c8a9ab8e120fbff1 Mon Sep 17 00:00:00 2001 From: Norbert Truchsess Date: Tue, 13 Aug 2024 18:24:18 +0200 Subject: [PATCH] fix review findings --- .../BusinessLogic/UserBusinessLogic.cs | 41 ++++++++++--------- .../Bpdm.Library/Models/BpdmAccessSettings.cs | 19 +++++++++ .../AsyncAggregateExtensions.cs | 27 ++++++++++++ .../Framework.Async/Directory.Build.props | 2 +- .../Framework.Cors/Directory.Build.props | 2 +- .../Framework.DBAccess/Directory.Build.props | 2 +- .../Directory.Build.props | 2 +- .../Directory.Build.props | 2 +- .../Directory.Build.props | 2 +- .../Directory.Build.props | 2 +- .../Directory.Build.props | 2 +- .../Directory.Build.props | 2 +- .../Framework.IO/Directory.Build.props | 2 +- .../Framework.Linq/Directory.Build.props | 2 +- .../Framework.Logging/Directory.Build.props | 2 +- .../Framework.Models/Directory.Build.props | 2 +- .../Framework.Seeding/Directory.Build.props | 2 +- .../Framework.Swagger/Directory.Build.props | 2 +- .../Framework.Token/Directory.Build.props | 2 +- .../Framework.Web/Directory.Build.props | 2 +- .../IUserBusinessPartnerRepository.cs | 1 + .../UserBusinessPartnerRepository.cs | 5 +++ .../Administration.Service.Tests.csproj | 1 - .../BusinessLogic/UserBusinessLogicTests.cs | 2 +- 24 files changed, 91 insertions(+), 39 deletions(-) create mode 100644 src/framework/Framework.Async/AsyncAggregateExtensions.cs diff --git a/src/administration/Administration.Service/BusinessLogic/UserBusinessLogic.cs b/src/administration/Administration.Service/BusinessLogic/UserBusinessLogic.cs index 7f37562d44..002ad52dc5 100644 --- a/src/administration/Administration.Service/BusinessLogic/UserBusinessLogic.cs +++ b/src/administration/Administration.Service/BusinessLogic/UserBusinessLogic.cs @@ -22,6 +22,7 @@ using Org.Eclipse.TractusX.Portal.Backend.Bpdm.Library; using Org.Eclipse.TractusX.Portal.Backend.Framework.Async; using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling; +using Org.Eclipse.TractusX.Portal.Backend.Framework.Linq; using Org.Eclipse.TractusX.Portal.Backend.Framework.Models; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Models; @@ -34,7 +35,6 @@ using Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library.Models; using Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library.Service; using System.Collections.Immutable; -using System.Text.RegularExpressions; namespace Org.Eclipse.TractusX.Portal.Backend.Administration.Service.BusinessLogic; @@ -268,8 +268,6 @@ await Task.WhenAll(details.IdpUserIds.Select(async x => public async Task AddOwnCompanyUsersBusinessPartnerNumbersAsync(Guid userId, string token, IEnumerable businessPartnerNumbers, CancellationToken cancellationToken) { - var successfulBpns = new List(); - var unsuccessfulBpnsList = new List(); var companyId = _identityData.CompanyId; var (assignedBusinessPartnerNumbers, isValidUser) = await portalRepositories.GetInstance().GetOwnCompanyUserWithAssignedBusinessPartnerNumbersUntrackedAsync(userId, companyId).ConfigureAwait(ConfigureAwaitOptions.None); if (!isValidUser) @@ -279,31 +277,34 @@ public async Task AddOwnCompanyUsersBusinessPartnerNumbe var iamUserId = await provisioningManager.GetUserByUserName(userId.ToString()).ConfigureAwait(ConfigureAwaitOptions.None) ?? throw new ConflictException($"user {userId} not found in keycloak"); - var businessPartnerRepository = portalRepositories.GetInstance(); - foreach (var bpn in businessPartnerNumbers) - { - var (bpns, error) = await CompanyUsersBpnCheck(bpn, token, cancellationToken); - if (error == null) - { - successfulBpns.Add(bpns); - } - else + + var (successfulBpns, unsuccessfulBpns) = await businessPartnerNumbers.AggregateAwait( + (SuccessfulBpns: ImmutableList.CreateBuilder(), UnsuccessfulBpns: ImmutableList.CreateBuilder()), + async (acc, bpn) => { - unsuccessfulBpnsList.Add(new UnsuccessfulBpns(bpns, error.Message)); - } - } + var (bpns, error) = await CompanyUsersBpnCheck(bpn, token, cancellationToken).ConfigureAwait(false); + if (error == null) + { + acc.SuccessfulBpns.Add(bpns); + } + else + { + acc.UnsuccessfulBpns.Add(new UnsuccessfulBpns(bpns, error.Message)); + } + return acc; + }, + acc => (acc.SuccessfulBpns.ToImmutable(), acc.UnsuccessfulBpns.ToImmutable()) + ).ConfigureAwait(ConfigureAwaitOptions.None); if (successfulBpns.Count != 0) { await provisioningManager.AddBpnAttributetoUserAsync(iamUserId, successfulBpns).ConfigureAwait(false); - foreach (var businessPartnerToAdd in successfulBpns.Except(assignedBusinessPartnerNumbers)) - { - businessPartnerRepository.CreateCompanyUserAssignedBusinessPartner(userId, businessPartnerToAdd); - } + successfulBpns.Except(assignedBusinessPartnerNumbers).IfAny(businessPartnersToAdd => + portalRepositories.GetInstance().CreateCompanyUserAssignedBusinessPartners(businessPartnersToAdd.Select(bpn => (userId, bpn)))); } await portalRepositories.SaveAsync(); - return new CompanyUsersBpnDetails(successfulBpns, unsuccessfulBpnsList); + return new CompanyUsersBpnDetails(successfulBpns, unsuccessfulBpns); } private async ValueTask<(string bpns, Exception? error)> CompanyUsersBpnCheck(string bpn, string token, CancellationToken cancellationToken) diff --git a/src/externalsystems/Bpdm.Library/Models/BpdmAccessSettings.cs b/src/externalsystems/Bpdm.Library/Models/BpdmAccessSettings.cs index de330f2a58..cb1e3b1e4e 100644 --- a/src/externalsystems/Bpdm.Library/Models/BpdmAccessSettings.cs +++ b/src/externalsystems/Bpdm.Library/Models/BpdmAccessSettings.cs @@ -1,3 +1,22 @@ +/******************************************************************************** + * 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 System.ComponentModel.DataAnnotations; namespace Org.Eclipse.TractusX.Portal.Backend.Bpdm.Library.Models; diff --git a/src/framework/Framework.Async/AsyncAggregateExtensions.cs b/src/framework/Framework.Async/AsyncAggregateExtensions.cs new file mode 100644 index 0000000000..196c7a6a82 --- /dev/null +++ b/src/framework/Framework.Async/AsyncAggregateExtensions.cs @@ -0,0 +1,27 @@ +/******************************************************************************** + * 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 + ********************************************************************************/ + +public static class AsyncAggregateExtensions +{ + public static Task AggregateAwait(this IEnumerable source, TAccumulate seed, Func> accumulate, Func select) => + source.Aggregate( + Task.FromResult(seed), + async (accTask, item) => await accumulate(await accTask.ConfigureAwait(ConfigureAwaitOptions.None), item).ConfigureAwait(ConfigureAwaitOptions.None), + async (accTask) => select(await accTask.ConfigureAwait(ConfigureAwaitOptions.None))); +} diff --git a/src/framework/Framework.Async/Directory.Build.props b/src/framework/Framework.Async/Directory.Build.props index f53f08f151..416bf1cdf9 100644 --- a/src/framework/Framework.Async/Directory.Build.props +++ b/src/framework/Framework.Async/Directory.Build.props @@ -19,7 +19,7 @@ - 2.5.0 + 2.6.0 diff --git a/src/framework/Framework.Cors/Directory.Build.props b/src/framework/Framework.Cors/Directory.Build.props index f53f08f151..416bf1cdf9 100644 --- a/src/framework/Framework.Cors/Directory.Build.props +++ b/src/framework/Framework.Cors/Directory.Build.props @@ -19,7 +19,7 @@ - 2.5.0 + 2.6.0 diff --git a/src/framework/Framework.DBAccess/Directory.Build.props b/src/framework/Framework.DBAccess/Directory.Build.props index f53f08f151..416bf1cdf9 100644 --- a/src/framework/Framework.DBAccess/Directory.Build.props +++ b/src/framework/Framework.DBAccess/Directory.Build.props @@ -19,7 +19,7 @@ - 2.5.0 + 2.6.0 diff --git a/src/framework/Framework.DateTimeProvider/Directory.Build.props b/src/framework/Framework.DateTimeProvider/Directory.Build.props index f53f08f151..416bf1cdf9 100644 --- a/src/framework/Framework.DateTimeProvider/Directory.Build.props +++ b/src/framework/Framework.DateTimeProvider/Directory.Build.props @@ -19,7 +19,7 @@ - 2.5.0 + 2.6.0 diff --git a/src/framework/Framework.DependencyInjection/Directory.Build.props b/src/framework/Framework.DependencyInjection/Directory.Build.props index f53f08f151..416bf1cdf9 100644 --- a/src/framework/Framework.DependencyInjection/Directory.Build.props +++ b/src/framework/Framework.DependencyInjection/Directory.Build.props @@ -19,7 +19,7 @@ - 2.5.0 + 2.6.0 diff --git a/src/framework/Framework.ErrorHandling.Controller/Directory.Build.props b/src/framework/Framework.ErrorHandling.Controller/Directory.Build.props index f53f08f151..416bf1cdf9 100644 --- a/src/framework/Framework.ErrorHandling.Controller/Directory.Build.props +++ b/src/framework/Framework.ErrorHandling.Controller/Directory.Build.props @@ -19,7 +19,7 @@ - 2.5.0 + 2.6.0 diff --git a/src/framework/Framework.ErrorHandling.Web/Directory.Build.props b/src/framework/Framework.ErrorHandling.Web/Directory.Build.props index f53f08f151..416bf1cdf9 100644 --- a/src/framework/Framework.ErrorHandling.Web/Directory.Build.props +++ b/src/framework/Framework.ErrorHandling.Web/Directory.Build.props @@ -19,7 +19,7 @@ - 2.5.0 + 2.6.0 diff --git a/src/framework/Framework.ErrorHandling/Directory.Build.props b/src/framework/Framework.ErrorHandling/Directory.Build.props index f53f08f151..416bf1cdf9 100644 --- a/src/framework/Framework.ErrorHandling/Directory.Build.props +++ b/src/framework/Framework.ErrorHandling/Directory.Build.props @@ -19,7 +19,7 @@ - 2.5.0 + 2.6.0 diff --git a/src/framework/Framework.HttpClientExtensions/Directory.Build.props b/src/framework/Framework.HttpClientExtensions/Directory.Build.props index f53f08f151..416bf1cdf9 100644 --- a/src/framework/Framework.HttpClientExtensions/Directory.Build.props +++ b/src/framework/Framework.HttpClientExtensions/Directory.Build.props @@ -19,7 +19,7 @@ - 2.5.0 + 2.6.0 diff --git a/src/framework/Framework.IO/Directory.Build.props b/src/framework/Framework.IO/Directory.Build.props index f53f08f151..416bf1cdf9 100644 --- a/src/framework/Framework.IO/Directory.Build.props +++ b/src/framework/Framework.IO/Directory.Build.props @@ -19,7 +19,7 @@ - 2.5.0 + 2.6.0 diff --git a/src/framework/Framework.Linq/Directory.Build.props b/src/framework/Framework.Linq/Directory.Build.props index f53f08f151..416bf1cdf9 100644 --- a/src/framework/Framework.Linq/Directory.Build.props +++ b/src/framework/Framework.Linq/Directory.Build.props @@ -19,7 +19,7 @@ - 2.5.0 + 2.6.0 diff --git a/src/framework/Framework.Logging/Directory.Build.props b/src/framework/Framework.Logging/Directory.Build.props index f53f08f151..416bf1cdf9 100644 --- a/src/framework/Framework.Logging/Directory.Build.props +++ b/src/framework/Framework.Logging/Directory.Build.props @@ -19,7 +19,7 @@ - 2.5.0 + 2.6.0 diff --git a/src/framework/Framework.Models/Directory.Build.props b/src/framework/Framework.Models/Directory.Build.props index f53f08f151..416bf1cdf9 100644 --- a/src/framework/Framework.Models/Directory.Build.props +++ b/src/framework/Framework.Models/Directory.Build.props @@ -19,7 +19,7 @@ - 2.5.0 + 2.6.0 diff --git a/src/framework/Framework.Seeding/Directory.Build.props b/src/framework/Framework.Seeding/Directory.Build.props index f53f08f151..416bf1cdf9 100644 --- a/src/framework/Framework.Seeding/Directory.Build.props +++ b/src/framework/Framework.Seeding/Directory.Build.props @@ -19,7 +19,7 @@ - 2.5.0 + 2.6.0 diff --git a/src/framework/Framework.Swagger/Directory.Build.props b/src/framework/Framework.Swagger/Directory.Build.props index f53f08f151..416bf1cdf9 100644 --- a/src/framework/Framework.Swagger/Directory.Build.props +++ b/src/framework/Framework.Swagger/Directory.Build.props @@ -19,7 +19,7 @@ - 2.5.0 + 2.6.0 diff --git a/src/framework/Framework.Token/Directory.Build.props b/src/framework/Framework.Token/Directory.Build.props index f53f08f151..416bf1cdf9 100644 --- a/src/framework/Framework.Token/Directory.Build.props +++ b/src/framework/Framework.Token/Directory.Build.props @@ -19,7 +19,7 @@ - 2.5.0 + 2.6.0 diff --git a/src/framework/Framework.Web/Directory.Build.props b/src/framework/Framework.Web/Directory.Build.props index f53f08f151..416bf1cdf9 100644 --- a/src/framework/Framework.Web/Directory.Build.props +++ b/src/framework/Framework.Web/Directory.Build.props @@ -19,7 +19,7 @@ - 2.5.0 + 2.6.0 diff --git a/src/portalbackend/PortalBackend.DBAccess/Repositories/IUserBusinessPartnerRepository.cs b/src/portalbackend/PortalBackend.DBAccess/Repositories/IUserBusinessPartnerRepository.cs index 3b0301e953..2ba2aa15e3 100644 --- a/src/portalbackend/PortalBackend.DBAccess/Repositories/IUserBusinessPartnerRepository.cs +++ b/src/portalbackend/PortalBackend.DBAccess/Repositories/IUserBusinessPartnerRepository.cs @@ -24,6 +24,7 @@ namespace Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Repositorie public interface IUserBusinessPartnerRepository { CompanyUserAssignedBusinessPartner CreateCompanyUserAssignedBusinessPartner(Guid companyUserId, string businessPartnerNumber); + void CreateCompanyUserAssignedBusinessPartners(IEnumerable<(Guid CompanyUserId, string BusinessPartnerNumber)> companyUserIdBpns); CompanyUserAssignedBusinessPartner DeleteCompanyUserAssignedBusinessPartner(Guid companyUserId, string businessPartnerNumber); void DeleteCompanyUserAssignedBusinessPartners(IEnumerable<(Guid CompanyUserId, string BusinessPartnerNumber)> companyUserAssignedBusinessPartnerIds); Task<(bool IsValidUser, bool IsAssignedBusinessPartner, bool IsSameCompany)> GetOwnCompanyUserWithAssignedBusinessPartnerNumbersAsync(Guid companyUserId, Guid userCompanyId, string businessPartnerNumber); diff --git a/src/portalbackend/PortalBackend.DBAccess/Repositories/UserBusinessPartnerRepository.cs b/src/portalbackend/PortalBackend.DBAccess/Repositories/UserBusinessPartnerRepository.cs index dc78a838d4..3246972151 100644 --- a/src/portalbackend/PortalBackend.DBAccess/Repositories/UserBusinessPartnerRepository.cs +++ b/src/portalbackend/PortalBackend.DBAccess/Repositories/UserBusinessPartnerRepository.cs @@ -33,6 +33,11 @@ public CompanyUserAssignedBusinessPartner CreateCompanyUserAssignedBusinessPartn businessPartnerNumber )).Entity; + public void CreateCompanyUserAssignedBusinessPartners(IEnumerable<(Guid CompanyUserId, string BusinessPartnerNumber)> companyUserIdBpns) => + dbContext.CompanyUserAssignedBusinessPartners.AddRange(companyUserIdBpns.Select(x => new CompanyUserAssignedBusinessPartner( + x.CompanyUserId, + x.BusinessPartnerNumber))); + public CompanyUserAssignedBusinessPartner DeleteCompanyUserAssignedBusinessPartner(Guid companyUserId, string businessPartnerNumber) => dbContext.Remove( new CompanyUserAssignedBusinessPartner( diff --git a/tests/administration/Administration.Service.Tests/Administration.Service.Tests.csproj b/tests/administration/Administration.Service.Tests/Administration.Service.Tests.csproj index d0820532f4..f7e3ff82b8 100644 --- a/tests/administration/Administration.Service.Tests/Administration.Service.Tests.csproj +++ b/tests/administration/Administration.Service.Tests/Administration.Service.Tests.csproj @@ -43,7 +43,6 @@ - Always diff --git a/tests/administration/Administration.Service.Tests/BusinessLogic/UserBusinessLogicTests.cs b/tests/administration/Administration.Service.Tests/BusinessLogic/UserBusinessLogicTests.cs index e1c8247249..265b4c6953 100644 --- a/tests/administration/Administration.Service.Tests/BusinessLogic/UserBusinessLogicTests.cs +++ b/tests/administration/Administration.Service.Tests/BusinessLogic/UserBusinessLogicTests.cs @@ -1468,7 +1468,7 @@ public async Task AddOwnCompanyUsersBusinessPartnerNumbers_ReturnsExpected() A.CallTo(() => _userRepository.GetOwnCompanyUserWithAssignedBusinessPartnerNumbersUntrackedAsync(A._, A._)).MustHaveHappenedOnceExactly(); A.CallTo(() => _provisioningManager.GetUserByUserName(A._)).MustHaveHappenedOnceExactly(); A.CallTo(() => _provisioningManager.AddBpnAttributetoUserAsync(A._, A>._)).MustHaveHappenedOnceExactly(); - A.CallTo(() => _userBusinessPartnerRepository.CreateCompanyUserAssignedBusinessPartner(A._, A._)).MustHaveHappened(4, Times.Exactly); + A.CallTo(() => _userBusinessPartnerRepository.CreateCompanyUserAssignedBusinessPartners(A>.That.Matches(x => x.Count() == 4))).MustHaveHappenedOnceExactly(); A.CallTo(() => _bpnAccess.FetchLegalEntityByBpn(A._, A._, CancellationToken.None)).MustHaveHappened(8, Times.Exactly); result.Should().NotBeNull(); result.SuccessfulBpns.Should().HaveCount(successfullBpns.Count());